wayland: refactor window destruction and focus

The previous code was leaving focus fields dirty in MetaWaylandPointer
and MetaWaylandKeyboard at time (which could crash the X server
because of invalid object IDs)
The new code is more tighly integrated in the normal X11 code
for handling keyboard focus (meaning that the core idea of input
focus is also correct now), so that meta_window_unmanage() can
do the right thing. As a side benefit, clicking on wayland clients
now unfocus X11 clients.
For the mouse focus, we need to clear the surface pointer when
the metawindowactor is destroyed (even if the actual actor is
kept alive for effects), so that a repick finds a different pointer
focus.

https://bugzilla.gnome.org/show_bug.cgi?id=705859
This commit is contained in:
Giovanni Campagna
2013-08-12 18:04:34 +02:00
parent 03f55b9485
commit 9a5f243f73
6 changed files with 108 additions and 65 deletions

View File

@ -1902,9 +1902,14 @@ update_focus_window (MetaDisplay *display,
Window xwindow,
gulong serial)
{
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor;
#endif
display->focus_serial = serial;
if (display->focus_xwindow == xwindow)
if (display->focus_xwindow == xwindow &&
display->focus_window == window)
return;
if (display->focus_window)
@ -1938,6 +1943,20 @@ update_focus_window (MetaDisplay *display,
else
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
{
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");
}
#endif
g_object_notify (G_OBJECT (display), "focus-window");
meta_display_update_active_window_hint (display);
}
@ -1974,17 +1993,15 @@ timestamp_too_old (MetaDisplay *display,
static void
request_xserver_input_focus_change (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *meta_window,
Window xwindow,
guint32 timestamp)
{
MetaWindow *meta_window;
gulong serial;
if (timestamp_too_old (display, &timestamp))
return;
meta_window = meta_display_lookup_x_window (display, xwindow);
meta_error_trap_push (display);
/* In order for mutter to know that the focus request succeeded, we track
@ -2651,15 +2668,6 @@ meta_display_handle_event (MetaDisplay *display,
}
break;
case XI_FocusIn:
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor =
meta_wayland_compositor_get_default ();
meta_wayland_compositor_set_input_focus (compositor, window);
}
#endif
/* fall through */
case XI_FocusOut:
/* libXi does not properly copy the serial to the XIEnterEvent, so pull it
* from the parent XAnyEvent.
@ -5884,6 +5892,7 @@ meta_display_set_input_focus_window (MetaDisplay *display,
{
request_xserver_input_focus_change (display,
window->screen,
window,
focus_frame ? window->frame->xwindow : window->xwindow,
timestamp);
}
@ -5931,6 +5940,7 @@ meta_display_set_input_focus_xwindow (MetaDisplay *display,
{
request_xserver_input_focus_change (display,
screen,
NULL,
window,
timestamp);
}
@ -5942,6 +5952,7 @@ meta_display_focus_the_no_focus_window (MetaDisplay *display,
{
request_xserver_input_focus_change (display,
screen,
NULL,
screen->no_focus_window,
timestamp);
}

View File

@ -62,6 +62,10 @@
#include <X11/extensions/Xcomposite.h>
#ifdef HAVE_WAYLAND
#include "meta-wayland-private.h"
#endif
/* Windows that unmaximize to a size bigger than that fraction of the workarea
* will be scaled down to that size (while maintaining aspect ratio).
* Windows that cover an area greater then this size are automaximized on map.
@ -2103,6 +2107,11 @@ meta_window_unmanage (MetaWindow *window,
meta_error_trap_pop (window->display);
}
#ifdef HAVE_WAYLAND
if (window->surface)
meta_wayland_surface_free (window->surface);
#endif
meta_prefs_remove_listener (prefs_changed_callback, window);
meta_screen_queue_check_fullscreen (window->screen);