summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/xwayland/window-manager.c55
2 files changed, 54 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 7dbd9f9..9e7bed3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,7 +42,7 @@ AC_ARG_ENABLE(xwayland, [ --enable-xwayland],,
enable_xwayland=yes)
AM_CONDITIONAL(ENABLE_XWAYLAND, test x$enable_xwayland = xyes)
if test x$enable_xwayland = xyes; then
- PKG_CHECK_MODULES([XWAYLAND], xcb xcb-xfixes cairo-xcb)
+ PKG_CHECK_MODULES([XWAYLAND], xcb xcb-icccm xcb-xfixes cairo-xcb)
AC_DEFINE([BUILD_XWAYLAND], [1], [Build the X server launcher])
AC_ARG_WITH(xserver-path, AS_HELP_STRING([--with-xserver-path=PATH],
diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c
index 0831bef..04d0c30 100644
--- a/src/xwayland/window-manager.c
+++ b/src/xwayland/window-manager.c
@@ -33,6 +33,7 @@
#include <signal.h>
#include "xwayland.h"
+#include <xcb/xcb_icccm.h>
#include "../../shared/cairo-util.h"
#include "../compositor.h"
@@ -89,7 +90,10 @@ struct motif_wm_hints {
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
-
+/* WM_PROTOCOLS property, ICCCM 4.1.2.7 */
+#define ICCCM_WM_TAKE_FOCUS (1L << 1)
+#define ICCCM_WM_SAVE_YOURSELF (1L << 2)
+#define ICCCM_WM_DELETE_WINDOW (1L << 3)
struct weston_wm_window {
struct weston_wm *wm;
@@ -209,6 +213,20 @@ read_and_dump_property(struct weston_wm *wm,
free(reply);
}
+static void
+handle_wm_protocols(struct weston_wm_window *window,
+ xcb_get_property_reply_t *reply)
+{
+ xcb_icccm_get_wm_protocols_reply_t protocols;
+ struct weston_wm *wm = window->wm;
+ uint32_t i;
+
+ xcb_icccm_get_wm_protocols_from_reply(reply, &protocols);
+ for (i = 0; i < protocols.atoms_len; i++)
+ if (protocols.atoms[i] == wm->atom.wm_take_focus)
+ window->protocols = ICCCM_WM_TAKE_FOCUS;
+}
+
/* We reuse some predefined, but otherwise useles atoms */
#define TYPE_WM_PROTOCOLS XCB_ATOM_CUT_BUFFER0
#define TYPE_MOTIF_WM_HINTS XCB_ATOM_CUT_BUFFER1
@@ -227,7 +245,7 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
{ XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, F(class) },
{ XCB_ATOM_WM_NAME, XCB_ATOM_STRING, F(name) },
{ XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, F(transient_for) },
- { wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, F(protocols) },
+ { wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, 0 },
{ wm->atom.net_wm_window_type, XCB_ATOM_ATOM, F(type) },
{ wm->atom.net_wm_name, XCB_ATOM_STRING, F(name) },
{ wm->atom.motif_wm_hints, TYPE_MOTIF_WM_HINTS, 0 },
@@ -287,6 +305,7 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
*(xcb_atom_t *) p = *atom;
break;
case TYPE_WM_PROTOCOLS:
+ handle_wm_protocols(window, reply);
break;
case TYPE_MOTIF_WM_HINTS:
hints = xcb_get_property_value(reply);
@@ -406,6 +425,34 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve
window->y = configure_notify->y - y;
}
+/*
+ * Follows up ICCCM 4.1.7. The function returns 1 when WM assistance is needed
+ * and 0 otherwise.
+ */
+static int
+weston_wm_focus_assistance(struct weston_wm_window *window)
+{
+ struct weston_wm *wm = window->wm;
+ int is_needed = 0;
+
+ /* the order here is important */
+ if (window->type == wm->atom.net_wm_window_type_normal ||
+ window->type == wm->atom.net_wm_window_type_dialog)
+ is_needed = 1;
+
+ /* special rule for google-chrome "utility" window that in
+ * fact has not the type "utility" but "normal" */
+ if (window->type == wm->atom.net_wm_window_type_normal &&
+ window->override_redirect)
+ is_needed = 0;
+
+ /* if WM_TAKE_FOCUS is absent, we assume WM help is needed. */
+ if (!(window->protocols & ICCCM_WM_TAKE_FOCUS))
+ is_needed = 1;
+
+ return is_needed;
+}
+
static void
weston_wm_window_activate(struct wl_listener *listener, void *data)
{
@@ -416,6 +463,9 @@ weston_wm_window_activate(struct wl_listener *listener, void *data)
xcb_client_message_event_t client_message;
if (window) {
+ if (!weston_wm_focus_assistance(window))
+ return;
+
client_message.response_type = XCB_CLIENT_MESSAGE;
client_message.format = 32;
client_message.window = window->id;
@@ -761,6 +811,7 @@ weston_wm_window_create(struct weston_wm *wm,
window->decorate = !window->override_redirect;
window->width = width;
window->height = height;
+ window->type = XCB_ATOM_NONE;
hash_table_insert(wm->window_hash, id, window);
}