Blob Blame History Raw
From ac1503a559715d002e51fe82499cf7cc02c9747b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
Date: Tue, 13 Nov 2018 04:04:22 +0100
Subject: [PATCH 05/28] tests: Add 'can_take_focus' command to runner and
 client

Allow to set/unset WM_TAKE_FOCUS from client window.
This is added by default by gtk, but this might not happen in other toolkits,
so add an ability to (un)set this.

So fetch the protocols with XGetWMProtocols and unset the atom.

test-client now needs to depend on Xlib directly in meson build.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/307
(cherry picked from commit f2d2d473b71dbdb339c80f068c5cb3e529af2478)
---
 src/tests/test-client.c | 50 +++++++++++++++++++++++++++++++++++++++++
 src/tests/test-runner.c | 19 ++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/src/tests/test-client.c b/src/tests/test-client.c
index 1870fd249..aa763d57d 100644
--- a/src/tests/test-client.c
+++ b/src/tests/test-client.c
@@ -179,6 +179,56 @@ process_line (const char *line)
       gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
       gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
     }
+  else if (strcmp (argv[0], "can_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;
+        }
+
+      GdkDisplay *display = gdk_display_get_default ();
+      GdkWindow *gdkwindow = gtk_widget_get_window (window);
+      Display *xdisplay = gdk_x11_display_get_xdisplay (display);
+      Window xwindow = GDK_WINDOW_XID (gdkwindow);
+      Atom wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
+      gboolean add = g_ascii_strcasecmp(argv[2], "true") == 0;
+      Atom *protocols = NULL;
+      Atom *new_protocols;
+      int n_protocols = 0;
+      int i, n = 0;
+
+      gdk_display_sync (display);
+      XGetWMProtocols (xdisplay, xwindow, &protocols, &n_protocols);
+      new_protocols = g_new0 (Atom, n_protocols + (add ? 1 : 0));
+
+      for (i = 0; i < n_protocols; ++i)
+        {
+          if (protocols[i] != wm_take_focus)
+            new_protocols[n++] = protocols[i];
+        }
+
+      if (add)
+        new_protocols[n++] = wm_take_focus;
+
+      XSetWMProtocols (xdisplay, xwindow, new_protocols, n);
+
+      XFree (new_protocols);
+      XFree (protocols);
+    }
   else if (strcmp (argv[0], "show") == 0)
     {
       if (argc != 2)
diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
index 613c0bbfb..37befb4ac 100644
--- a/src/tests/test-runner.c
+++ b/src/tests/test-runner.c
@@ -425,6 +425,25 @@ test_case_do (TestCase *test,
                            NULL))
         return FALSE;
     }
+  else if (strcmp (argv[0], "can_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 ||
            strcmp (argv[0], "hide") == 0 ||
            strcmp (argv[0], "activate") == 0 ||
-- 
2.21.0