compositor: fix focusing the stage window

We can't use the X11 stage window, if clutter is not using the X11
backend (and even if it was, it would be bogus when the xwayland
server is not the one clutter is talking to). Instead, we introduce
the concept of "focus type", which we use to differentiate the
various meanings of None in the focus_xwindow field.
This commit is contained in:
Giovanni Campagna 2013-08-13 14:54:55 +02:00
parent 2a1c0429dd
commit b8f6801d20
3 changed files with 76 additions and 33 deletions

View File

@ -391,33 +391,39 @@ meta_focus_stage_window (MetaScreen *screen,
if (!stage) if (!stage)
return; return;
window = clutter_x11_get_stage_window (stage); if (!meta_is_wayland_compositor ())
{
window = clutter_x11_get_stage_window (stage);
if (window == None) if (window == None)
return; return;
meta_display_set_input_focus_xwindow (screen->display, meta_display_set_input_focus_xwindow (screen->display,
screen, screen,
window, META_FOCUS_STAGE,
timestamp); window,
timestamp);
}
else
{
meta_display_set_input_focus_xwindow (screen->display,
screen,
META_FOCUS_STAGE,
None,
timestamp);
}
} }
gboolean gboolean
meta_stage_is_focused (MetaScreen *screen) meta_stage_is_focused (MetaScreen *screen)
{ {
ClutterStage *stage; ClutterStage *stage;
Window window;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen)); stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage) if (!stage)
return FALSE; return FALSE;
window = clutter_x11_get_stage_window (stage); return (screen->display->focus_type == META_FOCUS_STAGE);
if (window == None)
return FALSE;
return (screen->display->focus_xwindow == window);
} }
gboolean gboolean

View File

@ -86,6 +86,14 @@ typedef enum {
META_TILE_MAXIMIZED META_TILE_MAXIMIZED
} MetaTileMode; } MetaTileMode;
typedef enum {
META_FOCUS_NONE = 0,
META_FOCUS_X_CLIENT = 1,
META_FOCUS_WAYLAND_CLIENT = 2,
META_FOCUS_NO_FOCUS_WINDOW = 3,
META_FOCUS_STAGE = 4
} MetaFocusType;
struct _MetaDisplay struct _MetaDisplay
{ {
GObject parent_instance; GObject parent_instance;
@ -117,6 +125,7 @@ struct _MetaDisplay
* like the no_focus_window or the stage X window. */ * like the no_focus_window or the stage X window. */
Window focus_xwindow; Window focus_xwindow;
gulong focus_serial; gulong focus_serial;
MetaFocusType focus_type;
/* last timestamp passed to XSetInputFocus */ /* last timestamp passed to XSetInputFocus */
guint32 last_focus_time; guint32 last_focus_time;
@ -475,9 +484,10 @@ gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *event); XIBarrierEvent *event);
#endif /* HAVE_XI23 */ #endif /* HAVE_XI23 */
void meta_display_set_input_focus_xwindow (MetaDisplay *display, void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen, MetaScreen *screen,
Window window, MetaFocusType type,
guint32 timestamp); Window window,
guint32 timestamp);
#endif #endif

View File

@ -1897,10 +1897,11 @@ get_input_event (MetaDisplay *display,
} }
static void static void
update_focus_window (MetaDisplay *display, update_focus_window (MetaDisplay *display,
MetaWindow *window, MetaFocusType type,
Window xwindow, MetaWindow *window,
gulong serial) Window xwindow,
gulong serial)
{ {
#ifdef HAVE_WAYLAND #ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor; MetaWaylandCompositor *compositor;
@ -1931,6 +1932,7 @@ update_focus_window (MetaDisplay *display,
meta_window_set_focused_internal (previous, FALSE); meta_window_set_focused_internal (previous, FALSE);
} }
display->focus_type = type;
display->focus_window = window; display->focus_window = window;
display->focus_xwindow = xwindow; display->focus_xwindow = xwindow;
@ -1948,7 +1950,8 @@ update_focus_window (MetaDisplay *display,
{ {
compositor = meta_wayland_compositor_get_default (); compositor = meta_wayland_compositor_get_default ();
if (meta_display_xwindow_is_a_no_focus_window (display, xwindow)) if (display->focus_type == META_FOCUS_NO_FOCUS_WINDOW ||
display->focus_type == META_FOCUS_STAGE)
meta_wayland_compositor_set_input_focus (compositor, NULL); meta_wayland_compositor_set_input_focus (compositor, NULL);
else if (window && window->surface) else if (window && window->surface)
meta_wayland_compositor_set_input_focus (compositor, window); meta_wayland_compositor_set_input_focus (compositor, window);
@ -1991,11 +1994,12 @@ timestamp_too_old (MetaDisplay *display,
} }
static void static void
request_xserver_input_focus_change (MetaDisplay *display, request_xserver_input_focus_change (MetaDisplay *display,
MetaScreen *screen, MetaScreen *screen,
MetaWindow *meta_window, MetaFocusType type,
Window xwindow, MetaWindow *meta_window,
guint32 timestamp) Window xwindow,
guint32 timestamp)
{ {
gulong serial; gulong serial;
@ -2028,6 +2032,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
meta_display_ungrab (display); meta_display_ungrab (display);
update_focus_window (display, update_focus_window (display,
type,
meta_window, meta_window,
xwindow, xwindow,
serial); serial);
@ -2048,9 +2053,12 @@ handle_window_focus_event (MetaDisplay *display,
unsigned long serial) unsigned long serial)
{ {
MetaWindow *focus_window; MetaWindow *focus_window;
MetaFocusType type;
#ifdef WITH_VERBOSE_MODE #ifdef WITH_VERBOSE_MODE
const char *window_type; const char *window_type;
type = META_FOCUS_NONE;
/* Note the event can be on either the window or the frame, /* Note the event can be on either the window or the frame,
* we focus the frame for shaded windows * we focus the frame for shaded windows
*/ */
@ -2062,14 +2070,26 @@ handle_window_focus_event (MetaDisplay *display,
window_type = "frame window"; window_type = "frame window";
else else
window_type = "unknown client window"; window_type = "unknown client window";
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
type = META_FOCUS_WAYLAND_CLIENT;
else
type = META_FOCUS_X_CLIENT;
} }
else if (meta_display_xwindow_is_a_no_focus_window (display, event->event)) else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
window_type = "no_focus_window"; {
window_type = "no_focus_window";
type = META_FOCUS_NO_FOCUS_WINDOW;
}
else if (meta_display_screen_for_root (display, event->event)) else if (meta_display_screen_for_root (display, event->event))
window_type = "root window"; window_type = "root window";
else else
window_type = "unknown window"; window_type = "unknown window";
/* Don't change type if we don't know the new window */
if (type == META_FOCUS_NONE)
type = display->focus_type;
meta_topic (META_DEBUG_FOCUS, meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on %s 0x%lx (%s) " "Focus %s event received on %s 0x%lx (%s) "
"mode %s detail %s serial %lu\n", "mode %s detail %s serial %lu\n",
@ -2147,6 +2167,7 @@ handle_window_focus_event (MetaDisplay *display,
if (display->server_focus_serial > display->focus_serial) if (display->server_focus_serial > display->focus_serial)
{ {
update_focus_window (display, update_focus_window (display,
type,
focus_window, focus_window,
focus_window ? focus_window->xwindow : None, focus_window ? focus_window->xwindow : None,
display->server_focus_serial); display->server_focus_serial);
@ -2200,6 +2221,7 @@ meta_display_handle_event (MetaDisplay *display,
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n", meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
display->focus_window->desc); display->focus_window->desc);
update_focus_window (display, update_focus_window (display,
META_FOCUS_NONE,
meta_display_lookup_x_window (display, display->server_focus_window), meta_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window, display->server_focus_window,
display->server_focus_serial); display->server_focus_serial);
@ -5879,6 +5901,8 @@ meta_display_set_input_focus_window (MetaDisplay *display,
{ {
request_xserver_input_focus_change (display, request_xserver_input_focus_change (display,
window->screen, window->screen,
window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND ?
META_FOCUS_WAYLAND_CLIENT : META_FOCUS_X_CLIENT,
window, window,
focus_frame ? window->frame->xwindow : window->xwindow, focus_frame ? window->frame->xwindow : window->xwindow,
timestamp); timestamp);
@ -5920,13 +5944,15 @@ meta_display_request_take_focus (MetaDisplay *display,
} }
void void
meta_display_set_input_focus_xwindow (MetaDisplay *display, meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen, MetaScreen *screen,
Window window, MetaFocusType type,
guint32 timestamp) Window window,
guint32 timestamp)
{ {
request_xserver_input_focus_change (display, request_xserver_input_focus_change (display,
screen, screen,
type,
NULL, NULL,
window, window,
timestamp); timestamp);
@ -5939,6 +5965,7 @@ meta_display_focus_the_no_focus_window (MetaDisplay *display,
{ {
request_xserver_input_focus_change (display, request_xserver_input_focus_change (display,
screen, screen,
META_FOCUS_NO_FOCUS_WINDOW,
NULL, NULL,
screen->no_focus_window, screen->no_focus_window,
timestamp); timestamp);