window: Implement input device grabbing
With all input events going to widgets now, we can grab an input device to a widget, so that all events are delivered to that widgets handlers. This lets us implement the last bit of the menu behaviour, that is the client side grabbing of events. The result is that we can now pop down the menu when we receive clicks in the clients own windows and we don't send motion and button events to other widgets.
This commit is contained in:
parent
29af3ebce6
commit
831dd52aa0
124
clients/window.c
124
clients/window.c
@ -134,8 +134,6 @@ struct window {
|
|||||||
|
|
||||||
struct widget *widget;
|
struct widget *widget;
|
||||||
struct widget *focus_widget;
|
struct widget *focus_widget;
|
||||||
uint32_t widget_grab_button;
|
|
||||||
|
|
||||||
struct window *menu;
|
struct window *menu;
|
||||||
|
|
||||||
void *user_data;
|
void *user_data;
|
||||||
@ -166,6 +164,9 @@ struct input {
|
|||||||
int32_t x, y, sx, sy;
|
int32_t x, y, sx, sy;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
||||||
|
struct widget *grab;
|
||||||
|
uint32_t grab_button;
|
||||||
|
|
||||||
struct wl_data_device *data_device;
|
struct wl_data_device *data_device;
|
||||||
struct data_offer *drag_offer;
|
struct data_offer *drag_offer;
|
||||||
struct data_offer *selection_offer;
|
struct data_offer *selection_offer;
|
||||||
@ -190,6 +191,7 @@ struct frame {
|
|||||||
struct menu {
|
struct menu {
|
||||||
struct window *window;
|
struct window *window;
|
||||||
struct widget *widget;
|
struct widget *widget;
|
||||||
|
struct input *input;
|
||||||
const char **entries;
|
const char **entries;
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
int current;
|
int current;
|
||||||
@ -1349,13 +1351,6 @@ frame_motion_handler(struct widget *widget,
|
|||||||
return frame_get_pointer_image_for_location(data, input);
|
return frame_get_pointer_image_for_location(data, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
break_grab(struct window *window)
|
|
||||||
{
|
|
||||||
window->focus_widget = NULL;
|
|
||||||
window->widget_grab_button = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frame_button_handler(struct widget *widget,
|
frame_button_handler(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
@ -1378,7 +1373,7 @@ frame_button_handler(struct widget *widget,
|
|||||||
if (!window->shell_surface)
|
if (!window->shell_surface)
|
||||||
break;
|
break;
|
||||||
input_set_pointer_image(input, time, POINTER_DRAGGING);
|
input_set_pointer_image(input, time, POINTER_DRAGGING);
|
||||||
break_grab(window);
|
input_ungrab(input, time);
|
||||||
wl_shell_surface_move(window->shell_surface,
|
wl_shell_surface_move(window->shell_surface,
|
||||||
input_get_input_device(input),
|
input_get_input_device(input),
|
||||||
time);
|
time);
|
||||||
@ -1393,7 +1388,7 @@ frame_button_handler(struct widget *widget,
|
|||||||
case WINDOW_RESIZING_BOTTOM_RIGHT:
|
case WINDOW_RESIZING_BOTTOM_RIGHT:
|
||||||
if (!window->shell_surface)
|
if (!window->shell_surface)
|
||||||
break;
|
break;
|
||||||
break_grab(window);
|
input_ungrab(input, time);
|
||||||
wl_shell_surface_resize(window->shell_surface,
|
wl_shell_surface_resize(window->shell_surface,
|
||||||
input_get_input_device(input),
|
input_get_input_device(input),
|
||||||
time, location);
|
time, location);
|
||||||
@ -1436,7 +1431,7 @@ static void
|
|||||||
window_set_focus_widget(struct window *window, struct widget *focus,
|
window_set_focus_widget(struct window *window, struct widget *focus,
|
||||||
struct input *input, uint32_t time, int32_t x, int32_t y)
|
struct input *input, uint32_t time, int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
struct widget *old;
|
struct widget *old, *widget;
|
||||||
int pointer = POINTER_LEFT_PTR;
|
int pointer = POINTER_LEFT_PTR;
|
||||||
|
|
||||||
if (focus == window->focus_widget)
|
if (focus == window->focus_widget)
|
||||||
@ -1444,15 +1439,22 @@ window_set_focus_widget(struct window *window, struct widget *focus,
|
|||||||
|
|
||||||
old = window->focus_widget;
|
old = window->focus_widget;
|
||||||
if (old) {
|
if (old) {
|
||||||
if (old->leave_handler)
|
widget = old;
|
||||||
old->leave_handler(old, input, old->user_data);
|
if (input->grab)
|
||||||
|
widget = input->grab;
|
||||||
|
if (widget->leave_handler)
|
||||||
|
widget->leave_handler(old, input, widget->user_data);
|
||||||
window->focus_widget = NULL;
|
window->focus_widget = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focus) {
|
if (focus) {
|
||||||
if (focus->enter_handler)
|
widget = focus;
|
||||||
pointer = focus->enter_handler(focus, input, time,
|
if (input->grab)
|
||||||
x, y, focus->user_data);
|
widget = input->grab;
|
||||||
|
if (widget->enter_handler)
|
||||||
|
pointer = widget->enter_handler(focus, input, time,
|
||||||
|
x, y,
|
||||||
|
widget->user_data);
|
||||||
window->focus_widget = focus;
|
window->focus_widget = focus;
|
||||||
|
|
||||||
input_set_pointer_image(input, time, pointer);
|
input_set_pointer_image(input, time, pointer);
|
||||||
@ -1474,19 +1476,44 @@ input_handle_motion(void *data, struct wl_input_device *input_device,
|
|||||||
input->sx = sx;
|
input->sx = sx;
|
||||||
input->sy = sy;
|
input->sy = sy;
|
||||||
|
|
||||||
if (!window->focus_widget || !window->widget_grab_button) {
|
if (!(input->grab && input->grab_button)) {
|
||||||
widget = widget_find_widget(window->widget, sx, sy);
|
widget = widget_find_widget(window->widget, sx, sy);
|
||||||
window_set_focus_widget(window, widget, input, time, sx, sy);
|
window_set_focus_widget(window, widget, input, time, sx, sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input->grab)
|
||||||
|
widget = input->grab;
|
||||||
|
else
|
||||||
widget = window->focus_widget;
|
widget = window->focus_widget;
|
||||||
if (widget && widget->motion_handler)
|
if (widget && widget->motion_handler)
|
||||||
pointer = widget->motion_handler(widget, input, time, sx, sy,
|
pointer = widget->motion_handler(window->focus_widget,
|
||||||
|
input, time, sx, sy,
|
||||||
widget->user_data);
|
widget->user_data);
|
||||||
|
|
||||||
input_set_pointer_image(input, time, pointer);
|
input_set_pointer_image(input, time, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
input_grab(struct input *input, struct widget *widget, uint32_t button)
|
||||||
|
{
|
||||||
|
input->grab = widget;
|
||||||
|
input->grab_button = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
input_ungrab(struct input *input, uint32_t time)
|
||||||
|
{
|
||||||
|
struct widget *widget;
|
||||||
|
|
||||||
|
input->grab = NULL;
|
||||||
|
if (input->pointer_focus) {
|
||||||
|
widget = widget_find_widget(input->pointer_focus->widget,
|
||||||
|
input->sx, input->sy);
|
||||||
|
window_set_focus_widget(input->pointer_focus, widget,
|
||||||
|
input, time, input->sx, input->sy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_handle_button(void *data,
|
input_handle_button(void *data,
|
||||||
struct wl_input_device *input_device,
|
struct wl_input_device *input_device,
|
||||||
@ -1496,24 +1523,18 @@ input_handle_button(void *data,
|
|||||||
struct window *window = input->pointer_focus;
|
struct window *window = input->pointer_focus;
|
||||||
struct widget *widget;
|
struct widget *widget;
|
||||||
|
|
||||||
if (window->focus_widget && window->widget_grab_button == 0 && state)
|
if (window->focus_widget && input->grab == NULL && state)
|
||||||
window->widget_grab_button = button;
|
input_grab(input, window->focus_widget, button);
|
||||||
|
|
||||||
widget = window->focus_widget;
|
widget = window->focus_widget;
|
||||||
if (widget && widget->button_handler)
|
if (widget && widget->button_handler)
|
||||||
(*widget->button_handler)(widget,
|
(*input->grab->button_handler)(widget,
|
||||||
input, time,
|
input, time,
|
||||||
button, state,
|
button, state,
|
||||||
widget->user_data);
|
input->grab->user_data);
|
||||||
|
|
||||||
if (window->focus_widget &&
|
if (input->grab && input->grab_button == button && !state)
|
||||||
window->widget_grab_button == button && !state) {
|
input_ungrab(input, time);
|
||||||
window->widget_grab_button = 0;
|
|
||||||
widget = widget_find_widget(window->widget,
|
|
||||||
input->sx, input->sy);
|
|
||||||
window_set_focus_widget(window, widget, input, time,
|
|
||||||
input->sx, input->sy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1554,7 +1575,7 @@ input_remove_pointer_focus(struct input *input, uint32_t time)
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window_set_focus_widget(window, NULL, NULL, 0, 0, 0);
|
window_set_focus_widget(window, NULL, input, 0, 0, 0);
|
||||||
|
|
||||||
input->pointer_focus = NULL;
|
input->pointer_focus = NULL;
|
||||||
input->current_pointer_image = POINTER_UNSET;
|
input->current_pointer_image = POINTER_UNSET;
|
||||||
@ -2051,11 +2072,15 @@ static void
|
|||||||
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
|
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
struct window *window = data;
|
||||||
struct menu *menu = window_get_user_data(window);
|
struct menu *menu = window->widget->user_data;
|
||||||
|
|
||||||
/* FIXME: Need more context in this event, at least the input
|
/* FIXME: Need more context in this event, at least the input
|
||||||
* device. Or just use wl_callback. */
|
* device. Or just use wl_callback. And this really needs to
|
||||||
|
* be a window vfunc that the menu can set. And we need the
|
||||||
|
* time. */
|
||||||
|
|
||||||
menu->func(window->parent, menu->current, window->parent->user_data);
|
menu->func(window->parent, menu->current, window->parent->user_data);
|
||||||
|
input_ungrab(menu->input, 0);
|
||||||
window_destroy(window);
|
window_destroy(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2294,7 +2319,7 @@ window_create_transient(struct display *display, struct window *parent,
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
menu_set_item(struct menu *menu, int sy)
|
menu_set_item(struct menu *menu, int sy)
|
||||||
{
|
{
|
||||||
int next;
|
int next;
|
||||||
@ -2304,8 +2329,6 @@ menu_set_item(struct menu *menu, int sy)
|
|||||||
menu->current = next;
|
menu->current = next;
|
||||||
widget_schedule_redraw(menu->widget);
|
widget_schedule_redraw(menu->widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
return POINTER_LEFT_PTR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2313,7 +2336,12 @@ menu_motion_handler(struct widget *widget,
|
|||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
int32_t x, int32_t y, void *data)
|
int32_t x, int32_t y, void *data)
|
||||||
{
|
{
|
||||||
return menu_set_item(data, y);
|
struct menu *menu = data;
|
||||||
|
|
||||||
|
if (widget == menu->widget)
|
||||||
|
menu_set_item(data, y);
|
||||||
|
|
||||||
|
return POINTER_LEFT_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2321,12 +2349,20 @@ menu_enter_handler(struct widget *widget,
|
|||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
int32_t x, int32_t y, void *data)
|
int32_t x, int32_t y, void *data)
|
||||||
{
|
{
|
||||||
return menu_set_item(data, y);
|
struct menu *menu = data;
|
||||||
|
|
||||||
|
if (widget == menu->widget)
|
||||||
|
menu_set_item(data, y);
|
||||||
|
|
||||||
|
return POINTER_LEFT_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
menu_leave_handler(struct widget *widget, struct input *input, void *data)
|
menu_leave_handler(struct widget *widget, struct input *input, void *data)
|
||||||
{
|
{
|
||||||
|
struct menu *menu = data;
|
||||||
|
|
||||||
|
if (widget == menu->widget)
|
||||||
menu_set_item(data, -200);
|
menu_set_item(data, -200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2338,11 +2374,13 @@ menu_button_handler(struct widget *widget,
|
|||||||
{
|
{
|
||||||
struct menu *menu = data;
|
struct menu *menu = data;
|
||||||
|
|
||||||
/* Either relase after press-drag-release or click-motion-click. */
|
|
||||||
if (state == 0 && time - menu->time > 500) {
|
if (state == 0 && time - menu->time > 500) {
|
||||||
|
/* Either relase after press-drag-release or
|
||||||
|
* click-motion-click. */
|
||||||
menu->func(menu->window->parent,
|
menu->func(menu->window->parent,
|
||||||
menu->current, menu->window->parent->user_data);
|
menu->current, menu->window->parent->user_data);
|
||||||
window_destroy(widget->window);
|
input_ungrab(input, time);
|
||||||
|
window_destroy(menu->widget->window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2409,8 +2447,10 @@ window_create_menu(struct display *display,
|
|||||||
menu->widget = window_add_widget(menu->window, menu);
|
menu->widget = window_add_widget(menu->window, menu);
|
||||||
menu->entries = entries;
|
menu->entries = entries;
|
||||||
menu->count = count;
|
menu->count = count;
|
||||||
|
menu->current = -1;
|
||||||
menu->time = time;
|
menu->time = time;
|
||||||
menu->func = func;
|
menu->func = func;
|
||||||
|
menu->input = input;
|
||||||
window->type = TYPE_MENU;
|
window->type = TYPE_MENU;
|
||||||
window->x = x;
|
window->x = x;
|
||||||
window->y = y;
|
window->y = y;
|
||||||
@ -2426,6 +2466,8 @@ window_create_menu(struct display *display,
|
|||||||
widget_set_motion_handler(menu->widget, menu_motion_handler);
|
widget_set_motion_handler(menu->widget, menu_motion_handler);
|
||||||
widget_set_button_handler(menu->widget, menu_button_handler);
|
widget_set_button_handler(menu->widget, menu_button_handler);
|
||||||
|
|
||||||
|
input_grab(input, menu->widget, 0);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,6 +358,12 @@ input_get_position(struct input *input, int32_t *x, int32_t *y);
|
|||||||
uint32_t
|
uint32_t
|
||||||
input_get_modifiers(struct input *input);
|
input_get_modifiers(struct input *input);
|
||||||
|
|
||||||
|
void
|
||||||
|
input_grab(struct input *input, struct widget *widget, uint32_t button);
|
||||||
|
|
||||||
|
void
|
||||||
|
input_ungrab(struct input *input, uint32_t time);
|
||||||
|
|
||||||
struct wl_input_device *
|
struct wl_input_device *
|
||||||
input_get_input_device(struct input *input);
|
input_get_input_device(struct input *input);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user