[mutter/gnome-3-30] tests: Add "accept_take_focus" command
- From: Marco Trevisan <marcotrevi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/gnome-3-30] tests: Add "accept_take_focus" command
- Date: Mon, 8 Jul 2019 15:35:57 +0000 (UTC)
commit 288ab54ccf4c6f7fcd5bd826aecb00094e2acdd6
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Wed Jul 3 16:47:54 2019 +0200
tests: Add "accept_take_focus" command
When used it setups an X11 event monitor that replies to WM_TAKE_FOCUS
ClientMessage's with a XSetInputFocus request.
It can only be used by x11 clients on windows that have WM_TAKE_FOCUS atom set
and that does not accept input.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/669
(cherry picked from commit b80250e483e20bc2b66aa0117af0c442875c1b74)
src/tests/test-client.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++-
src/tests/test-runner.c | 19 +++++++++
2 files changed, 126 insertions(+), 1 deletion(-)
---
diff --git a/src/tests/test-client.c b/src/tests/test-client.c
index 61fc341bf..e5a211c6b 100644
--- a/src/tests/test-client.c
+++ b/src/tests/test-client.c
@@ -31,6 +31,7 @@ static gboolean wayland;
GHashTable *windows;
GQuark event_source_quark;
GQuark event_handlers_quark;
+GQuark can_take_focus_quark;
typedef void (*XEventHandler) (GtkWidget *window, XEvent *event);
@@ -61,6 +62,7 @@ lookup_window (const char *window_id)
typedef struct {
GSource base;
+ GSource **self_ref;
GPollFD event_poll_fd;
Display *xdisplay;
} XClientEventSource;
@@ -118,10 +120,19 @@ x_event_source_dispatch (GSource *source,
return TRUE;
}
+static void
+x_event_source_finalize (GSource *source)
+{
+ XClientEventSource *x_source = (XClientEventSource *) source;
+
+ *x_source->self_ref = NULL;
+}
+
static GSourceFuncs x_event_funcs = {
x_event_source_prepare,
x_event_source_check,
x_event_source_dispatch,
+ x_event_source_finalize,
};
static GSource*
@@ -136,6 +147,7 @@ ensure_xsource_handler (GdkDisplay *gdkdisplay)
source = g_source_new (&x_event_funcs, sizeof (XClientEventSource));
x_source = (XClientEventSource *) source;
+ x_source->self_ref = &source;
x_source->xdisplay = xdisplay;
x_source->event_poll_fd.fd = ConnectionNumber (xdisplay);
x_source->event_poll_fd.events = G_IO_IN;
@@ -161,6 +173,15 @@ window_has_x11_event_handler (GtkWidget *window,
return g_list_find (handlers, handler) != NULL;
}
+static void
+unref_and_maybe_destroy_gsource (GSource *source)
+{
+ g_source_unref (source);
+
+ if (source->ref_count == 1)
+ g_source_destroy (source);
+}
+
static void
window_add_x11_event_handler (GtkWidget *window,
XEventHandler handler)
@@ -173,7 +194,7 @@ window_add_x11_event_handler (GtkWidget *window,
source = ensure_xsource_handler (gtk_widget_get_display (window));
g_object_set_qdata_full (G_OBJECT (window), event_source_quark, source,
- (GDestroyNotify) g_source_unref);
+ (GDestroyNotify) unref_and_maybe_destroy_gsource);
handlers = g_list_append (handlers, handler);
g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers);
@@ -194,6 +215,31 @@ window_remove_x11_event_handler (GtkWidget *window,
g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers);
}
+static void
+handle_take_focus (GtkWidget *window,
+ XEvent *xevent)
+{
+ GdkWindow *gdkwindow = gtk_widget_get_window (window);
+ GdkDisplay *display = gtk_widget_get_display (window);
+ Atom wm_protocols =
+ gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
+ Atom wm_take_focus =
+ gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
+
+ if (xevent->xany.type != ClientMessage ||
+ xevent->xany.window != GDK_WINDOW_XID (gdkwindow))
+ return;
+
+ if (xevent->xclient.message_type == wm_protocols &&
+ (Atom) xevent->xclient.data.l[0] == wm_take_focus)
+ {
+ XSetInputFocus (xevent->xany.display,
+ GDK_WINDOW_XID (gdkwindow),
+ RevertToParent,
+ xevent->xclient.data.l[1]);
+ }
+}
+
static void
process_line (const char *line)
{
@@ -262,6 +308,9 @@ process_line (const char *line)
gtk_window_set_title (GTK_WINDOW (window), title);
g_free (title);
+ g_object_set_qdata (G_OBJECT (window), can_take_focus_quark,
+ GUINT_TO_POINTER (TRUE));
+
gtk_widget_realize (window);
if (!wayland)
@@ -348,6 +397,14 @@ process_line (const char *line)
goto out;
}
+ if (!wayland &&
+ window_has_x11_event_handler (window, handle_take_focus))
+ {
+ g_print ("Impossible to use %s for windows accepting take focus",
+ argv[1]);
+ goto out;
+ }
+
gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
}
@@ -372,6 +429,13 @@ process_line (const char *line)
goto out;
}
+ if (window_has_x11_event_handler (window, handle_take_focus))
+ {
+ g_print ("Impossible to change %s for windows accepting take focus",
+ argv[1]);
+ goto out;
+ }
+
GdkDisplay *display = gdk_display_get_default ();
GdkWindow *gdkwindow = gtk_widget_get_window (window);
Display *xdisplay = gdk_x11_display_get_xdisplay (display);
@@ -397,10 +461,51 @@ process_line (const char *line)
new_protocols[n++] = wm_take_focus;
XSetWMProtocols (xdisplay, xwindow, new_protocols, n);
+ g_object_set_qdata (G_OBJECT (window), can_take_focus_quark,
+ GUINT_TO_POINTER (add));
XFree (new_protocols);
XFree (protocols);
}
+ else if (strcmp (argv[0], "accept_take_focus") == 0)
+ {
+ if (argc != 3)
+ {
+ g_print ("usage: %s <window-id> [true|false]", argv[0]);
+ goto out;
+ }
+
+ GtkWidget *window = lookup_window (argv[1]);
+ if (!window)
+ {
+ g_print ("unknown window %s", argv[1]);
+ goto out;
+ }
+
+ if (wayland)
+ {
+ g_print ("%s not supported under wayland", argv[0]);
+ goto out;
+ }
+
+ if (gtk_window_get_accept_focus (GTK_WINDOW (window)))
+ {
+ g_print ("%s not supported for input windows", argv[0]);
+ goto out;
+ }
+
+ if (!g_object_get_qdata (G_OBJECT (window), can_take_focus_quark))
+ {
+ g_print ("%s not supported for windows with no WM_TAKE_FOCUS set",
+ argv[0]);
+ goto out;
+ }
+
+ if (g_ascii_strcasecmp (argv[2], "true") == 0)
+ window_add_x11_event_handler (window, handle_take_focus);
+ else
+ window_remove_x11_event_handler (window, handle_take_focus);
+ }
else if (strcmp (argv[0], "show") == 0)
{
if (argc != 2)
@@ -651,6 +756,7 @@ main(int argc, char **argv)
g_free, NULL);
event_source_quark = g_quark_from_static_string ("event-source");
event_handlers_quark = g_quark_from_static_string ("event-handlers");
+ can_take_focus_quark = g_quark_from_static_string ("can-take-focus");
GInputStream *raw_in = g_unix_input_stream_new (0, FALSE);
GDataInputStream *in = g_data_input_stream_new (raw_in);
diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
index 5ec1c645f..4998d1d23 100644
--- a/src/tests/test-runner.c
+++ b/src/tests/test-runner.c
@@ -531,6 +531,25 @@ test_case_do (TestCase *test,
NULL))
return FALSE;
}
+ else if (strcmp (argv[0], "accept_take_focus") == 0)
+ {
+ if (argc != 3 ||
+ (g_ascii_strcasecmp (argv[2], "true") != 0 &&
+ g_ascii_strcasecmp (argv[2], "false") != 0))
+ BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
+ argv[0]);
+
+ TestClient *client;
+ const char *window_id;
+ if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
+ return FALSE;
+
+ if (!test_client_do (client, error,
+ argv[0], window_id,
+ argv[2],
+ NULL))
+ return FALSE;
+ }
else if (strcmp (argv[0], "show") == 0)
{
if (argc != 2)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]