Commit 45740ca2 authored by Thomas Guillem's avatar Thomas Guillem

core: window: handle mouse events

Mouse events can now be caught by "vout window" modules in addition to "vout
display" modules. Mouse events are propagated to the vout_thread_t via a new
vout_control. That way, window mouse coordinates can be translated to video
coordinates from ThreadControl (where it's safe to access vd->source and
vd->cfg).

Ref #9787
parent 7d922502
......@@ -64,6 +64,28 @@ enum {
VOUT_WINDOW_SET_FULLSCREEN, /* int b_fullscreen */
};
/**
* Window mouse event type for vout_window_mouse_event_t
*/
enum vout_window_mouse_event_type {
VOUT_WINDOW_MOUSE_STATE,
VOUT_WINDOW_MOUSE_MOVED,
VOUT_WINDOW_MOUSE_PRESSED,
VOUT_WINDOW_MOUSE_RELEASED,
VOUT_WINDOW_MOUSE_DOUBLE_CLICK,
};
/**
* Window mouse event
*/
typedef struct vout_window_mouse_event_t
{
enum vout_window_mouse_event_type type;
int x;
int y;
int button_mask;
} vout_window_mouse_event_t;
typedef struct vout_window_cfg_t {
/* Window handle type */
unsigned type;
......@@ -88,6 +110,7 @@ typedef struct vout_window_owner {
void *sys;
void (*resized)(vout_window_t *, unsigned width, unsigned height);
void (*closed)(vout_window_t *);
void (*mouse_event)(vout_window_t *, const vout_window_mouse_event_t *mouse);
} vout_window_owner_t;
/**
......@@ -211,5 +234,76 @@ static inline void vout_window_ReportClose(vout_window_t *window)
window->owner.closed(window);
}
static inline void vout_window_SendMouseEvent(vout_window_t *window,
const vout_window_mouse_event_t *mouse)
{
if (window->owner.mouse_event != NULL)
window->owner.mouse_event(window, mouse);
}
/**
* Send a full mouse state
*
* The mouse position must be expressed against window unit. You can use this
* function of others vout_window_ReportMouse*() functions.
*/
static inline void vout_window_ReportMouseState(vout_window_t *window,
int x, int y, int button_mask)
{
const vout_window_mouse_event_t mouse = {
VOUT_WINDOW_MOUSE_STATE, x, y, button_mask
};
vout_window_SendMouseEvent(window, &mouse);
}
/**
* Send a mouse movement
*
* The mouse position must be expressed against window unit.
*/
static inline void vout_window_ReportMouseMoved(vout_window_t *window,
int x, int y)
{
const vout_window_mouse_event_t mouse = {
VOUT_WINDOW_MOUSE_MOVED, x, y, 0
};
vout_window_SendMouseEvent(window, &mouse);
}
/**
* Send a mouse pressed event
*/
static inline void vout_window_ReportMousePressed(vout_window_t *window,
int button)
{
const vout_window_mouse_event_t mouse = {
VOUT_WINDOW_MOUSE_PRESSED, 0, 0, button,
};
vout_window_SendMouseEvent(window, &mouse);
}
/**
* Send a mouse released event
*/
static inline void vout_window_ReportMouseReleased(vout_window_t *window,
int button)
{
const vout_window_mouse_event_t mouse = {
VOUT_WINDOW_MOUSE_RELEASED, 0, 0, button,
};
vout_window_SendMouseEvent(window, &mouse);
}
/**
* Send a mouse double click event
*/
static inline void vout_window_ReportMouseDoubleClick(vout_window_t *window)
{
const vout_window_mouse_event_t mouse = {
VOUT_WINDOW_MOUSE_DOUBLE_CLICK, 0, 0, 0,
};
vout_window_SendMouseEvent(window, &mouse);
}
/** @} */
#endif /* VLC_VOUT_WINDOW_H */
......@@ -24,6 +24,8 @@
#ifndef LIBVLC_VOUT_INTERNAL_CONTROL_H
#define LIBVLC_VOUT_INTERNAL_CONTROL_H
#include <vlc_vout_window.h>
/* */
enum {
VOUT_CONTROL_INIT,
......@@ -51,6 +53,7 @@ enum {
VOUT_CONTROL_FULLSCREEN, /* bool */
VOUT_CONTROL_WINDOW_STATE, /* unsigned */
VOUT_CONTROL_WINDOW_MOUSE, /* window_mouse */
VOUT_CONTROL_DISPLAY_FILLED, /* bool */
VOUT_CONTROL_ZOOM, /* pair */
......@@ -94,6 +97,7 @@ typedef struct {
unsigned width;
unsigned height;
} window;
vout_window_mouse_event_t window_mouse;
const vout_configuration_t *cfg;
subpicture_t *subpicture;
vlc_viewpoint_t viewpoint;
......
......@@ -363,6 +363,17 @@ void vout_DisplayTitle(vout_thread_t *vout, const char *title)
vout_control_PushString(&vout->p->control, VOUT_CONTROL_OSD_TITLE, title);
}
void vout_WindowMouseEvent(vout_thread_t *vout,
const vout_window_mouse_event_t *mouse)
{
assert(mouse);
vout_control_cmd_t cmd;
vout_control_cmd_Init(&cmd, VOUT_CONTROL_WINDOW_MOUSE);
cmd.u.window_mouse = *mouse;
vout_control_Push(&vout->p->control, &cmd);
}
void vout_PutSubpicture( vout_thread_t *vout, subpicture_t *subpic )
{
vout_control_cmd_t cmd;
......@@ -1261,6 +1272,48 @@ static void ThreadChangeWindowState(vout_thread_t *vout, unsigned state)
#endif
}
static void ThreadChangeWindowMouse(vout_thread_t *vout,
const vout_window_mouse_event_t *mouse)
{
vout_display_t *vd = vout->p->display.vd;
switch (mouse->type)
{
case VOUT_WINDOW_MOUSE_STATE:
case VOUT_WINDOW_MOUSE_MOVED:
{
vout_display_place_t place;
vout_display_PlacePicture(&place, &vd->source, vd->cfg, false);
if (place.width <= 0 || place.height <= 0)
return;
const int x = vd->source.i_x_offset +
(int64_t)(mouse->x - place.x) *
vd->source.i_visible_width / place.width;
const int y = vd->source.i_y_offset +
(int64_t)(mouse->y - place.y) *
vd->source.i_visible_height/ place.height;
if (mouse->type == VOUT_WINDOW_MOUSE_STATE)
vout_display_SendEventMouseState(vd, x, y, mouse->button_mask);
else
vout_display_SendEventMouseMoved(vd, x, y);
break;
}
case VOUT_WINDOW_MOUSE_PRESSED:
vout_display_SendEventMousePressed(vd, mouse->button_mask);
break;
case VOUT_WINDOW_MOUSE_RELEASED:
vout_display_SendEventMouseReleased(vd, mouse->button_mask);
break;
case VOUT_WINDOW_MOUSE_DOUBLE_CLICK:
vout_display_SendEventMouseDoubleClick(vd);
break;
default: vlc_assert_unreachable();
break;
}
}
static void ThreadChangeDisplayFilled(vout_thread_t *vout, bool is_filled)
{
vout_SetDisplayFilled(vout->p->display.vd, is_filled);
......@@ -1551,6 +1604,9 @@ static int ThreadControl(vout_thread_t *vout, vout_control_cmd_t cmd)
case VOUT_CONTROL_WINDOW_STATE:
ThreadChangeWindowState(vout, cmd.u.integer);
break;
case VOUT_CONTROL_WINDOW_MOUSE:
ThreadChangeWindowMouse(vout, &cmd.u.window_mouse);
break;
case VOUT_CONTROL_DISPLAY_FILLED:
ThreadChangeDisplayFilled(vout, cmd.u.boolean);
break;
......
......@@ -25,6 +25,8 @@
#ifndef LIBVLC_VOUT_CONTROL_H
#define LIBVLC_VOUT_CONTROL_H 1
typedef struct vout_window_mouse_event_t vout_window_mouse_event_t;
/**
* This function will (un)pause the display of pictures.
* It is thread safe
......@@ -69,6 +71,9 @@ void vout_NextPicture( vout_thread_t *p_vout, mtime_t *pi_duration );
*/
void vout_DisplayTitle( vout_thread_t *p_vout, const char *psz_title );
void vout_WindowMouseEvent( vout_thread_t *p_vout,
const vout_window_mouse_event_t *mouse );
/**
* This function will return true if no more pictures are to be displayed.
*/
......
......@@ -149,6 +149,13 @@ static void vout_display_window_CloseNotify(vout_window_t *window)
vout_SendEventClose(vout);
}
static void vout_display_window_MouseEvent(vout_window_t *window,
const vout_window_mouse_event_t *mouse)
{
vout_thread_t *vout = (vout_thread_t *)window->obj.parent;
vout_WindowMouseEvent(vout, mouse);
}
/**
* Creates a video window, initially without any attached display.
*/
......@@ -168,6 +175,7 @@ vout_window_t *vout_display_window_New(vout_thread_t *vout,
.sys = state,
.resized = vout_display_window_ResizeNotify,
.closed = vout_display_window_CloseNotify,
.mouse_event = vout_display_window_MouseEvent,
};
vout_window_t *window;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment