wayland: Set/unset wayland focus on mutter grab/ungrab operations

This ensures that we send the proper leave and enter events to wayland
clients.

Particularly, this solves a bug in SSD xwayland windows where clicking
and dragging on the title bar to move the window only works on the odd
turn (unless the pointer moves away from the title bar between
tries). This happens because xwayland gets a button press but doesn't
see the release so when it gets the next button press it discards it
because its pointer button tracking logic says that the button is
already pressed. Sending the proper wayland pointer leave event fixes
it since wayland clients must forget about button state at that point.

https://bugzilla.gnome.org/show_bug.cgi?id=726123
This commit is contained in:
Rui Matos 2014-03-11 18:45:39 +01:00
parent 15c59f9919
commit 1b29113150
3 changed files with 47 additions and 23 deletions

View File

@ -426,11 +426,8 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE) if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
return FALSE; return FALSE;
if (meta_is_wayland_compositor ()) if (!meta_is_wayland_compositor () &&
ok = TRUE; !begin_modal_x11 (screen, plugin, options, timestamp))
else
ok = begin_modal_x11 (screen, plugin, options, timestamp);
if (!ok)
return FALSE; return FALSE;
display->grab_op = META_GRAB_OP_COMPOSITOR; display->grab_op = META_GRAB_OP_COMPOSITOR;
@ -439,6 +436,9 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
display->grab_have_pointer = TRUE; display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE; display->grab_have_keyboard = TRUE;
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
return TRUE; return TRUE;
} }
@ -452,17 +452,21 @@ meta_end_modal_for_plugin (MetaScreen *screen,
g_return_if_fail (is_modal (display)); g_return_if_fail (is_modal (display));
if (!meta_is_wayland_compositor ())
{
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
}
display->grab_op = META_GRAB_OP_NONE; display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL; display->grab_window = NULL;
display->grab_screen = NULL; display->grab_screen = NULL;
display->grab_have_pointer = FALSE; display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE; display->grab_have_keyboard = FALSE;
if (meta_is_wayland_compositor ())
{
meta_display_sync_wayland_input_focus (display);
}
else
{
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
}
} }
static void static void

View File

@ -486,4 +486,6 @@ void meta_display_set_input_focus_xwindow (MetaDisplay *display,
Window window, Window window,
guint32 timestamp); guint32 timestamp);
void meta_display_sync_wayland_input_focus (MetaDisplay *display);
#endif #endif

View File

@ -1742,6 +1742,29 @@ get_input_event (MetaDisplay *display,
return NULL; return NULL;
} }
void
meta_display_sync_wayland_input_focus (MetaDisplay *display)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWindow *focus_window;
if (display->grab_op != META_GRAB_OP_NONE)
focus_window = NULL;
else if (meta_display_xwindow_is_a_no_focus_window (display, display->focus_xwindow))
focus_window = NULL;
else if (display->focus_window && display->focus_window->surface)
focus_window = display->focus_window;
else
meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
meta_wayland_compositor_set_input_focus (compositor, focus_window);
if (display->grab_op != META_GRAB_OP_NONE)
meta_wayland_pointer_set_focus (&compositor->seat->pointer, NULL);
else
meta_wayland_seat_repick (compositor->seat, NULL);
}
static void static void
update_focus_window (MetaDisplay *display, update_focus_window (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
@ -1749,8 +1772,6 @@ update_focus_window (MetaDisplay *display,
gulong serial, gulong serial,
gboolean focused_by_us) gboolean focused_by_us)
{ {
MetaWaylandCompositor *compositor;
display->focus_serial = serial; display->focus_serial = serial;
display->focused_by_us = focused_by_us; display->focused_by_us = focused_by_us;
@ -1790,16 +1811,7 @@ update_focus_window (MetaDisplay *display,
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial); meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
{ meta_display_sync_wayland_input_focus (display);
compositor = meta_wayland_compositor_get_default ();
if (meta_display_xwindow_is_a_no_focus_window (display, xwindow))
meta_wayland_compositor_set_input_focus (compositor, NULL);
else if (window && window->surface)
meta_wayland_compositor_set_input_focus (compositor, window);
else
meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
}
g_object_notify (G_OBJECT (display), "focus-window"); g_object_notify (G_OBJECT (display), "focus-window");
meta_display_update_active_window_hint (display); meta_display_update_active_window_hint (display);
@ -4070,6 +4082,9 @@ meta_display_begin_grab_op (MetaDisplay *display,
meta_window_refresh_resize_popup (display->grab_window); meta_window_refresh_resize_popup (display->grab_window);
} }
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0, g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0,
screen, display->grab_window, display->grab_op); screen, display->grab_window, display->grab_op);
@ -4163,6 +4178,9 @@ meta_display_end_grab_op (MetaDisplay *display,
g_source_remove (display->grab_resize_timeout_id); g_source_remove (display->grab_resize_timeout_id);
display->grab_resize_timeout_id = 0; display->grab_resize_timeout_id = 0;
} }
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
} }
/** /**