[PATCH vdagent 2/2] x11: retireve _NET_WM_NAME using Xlib if GTK+ is missing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jakub Janků <jjanku@xxxxxxxxxx>

This code using Xlib was removed by commit
"x11: retrieve _NET_WM_NAME using GDK"
a4f5c7dcb6579f61434a443e537641f91da6cb8c.
Bring it back to make GTK+ optional for now.
---
 src/vdagent/vdagent.c |  6 ++--
 src/vdagent/x11.c     | 85 +++++++++++++++++++++++++++++++++++++++++++++------
 src/vdagent/x11.h     |  2 +-
 3 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index 6bd52fa..6a20429 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -111,7 +111,7 @@ static const gchar *xfer_get_download_directory(VDAgent *agent)
         return fx_dir;
     }
 
-    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop() ?
+    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop(agent->x11) ?
                                   G_USER_DIRECTORY_DESKTOP :
                                   G_USER_DIRECTORY_DOWNLOAD);
 }
@@ -140,7 +140,9 @@ static gboolean vdagent_init_file_xfer(VDAgent *agent)
         return FALSE;
     }
 
-    open_dir = fx_open_dir == -1 ? !vdagent_x11_has_icons_on_desktop() : fx_open_dir;
+    open_dir = fx_open_dir == -1 ?
+               !vdagent_x11_has_icons_on_desktop(agent->x11) :
+               fx_open_dir;
 
     agent->xfers = vdagent_file_xfers_create(agent->conn, xfer_dir,
                                              open_dir, debug);
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index e6c3e9e..ee148ae 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ -121,15 +121,77 @@ int vdagent_x11_restore_error_handler(struct vdagent_x11 *x11)
     return error;
 }
 
-static const gchar *vdagent_x11_get_wm_name()
+static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 *x11)
 {
 #ifdef GDK_WINDOWING_X11
     GdkDisplay *display = gdk_display_get_default();
     if (GDK_IS_X11_DISPLAY(display))
-        return gdk_x11_screen_get_window_manager_name(
-            gdk_display_get_default_screen(display));
+        return g_strdup(gdk_x11_screen_get_window_manager_name(
+            gdk_display_get_default_screen(display)));
+    return g_strdup("unsupported");
+#else
+    Atom type_ret;
+    int format_ret;
+    unsigned long len, remain;
+    unsigned char *data = NULL;
+    Window sup_window = None;
+    gchar *net_wm_name = NULL;
+
+    /* XGetWindowProperty can throw a BadWindow error. One way we can trigger
+       this is when the display-manager (ie gdm) has set, and not cleared the
+       _NET_SUPPORTING_WM_CHECK property, and the window manager running in
+       the user session has not yet updated it to point to its window, so its
+       pointing to a nonexistent window. */
+    vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
+
+    /* Get the window manager SUPPORTING_WM_CHECK window */
+    if (XGetWindowProperty(x11->display, x11->root_window[0],
+            XInternAtom(x11->display, "_NET_SUPPORTING_WM_CHECK", False), 0,
+            LONG_MAX, False, XA_WINDOW, &type_ret, &format_ret, &len,
+            &remain, &data) == Success) {
+        if (type_ret == XA_WINDOW)
+            sup_window = *((Window *)data);
+        XFree(data);
+    }
+    if (sup_window == None &&
+        XGetWindowProperty(x11->display, x11->root_window[0],
+            XInternAtom(x11->display, "_WIN_SUPPORTING_WM_CHECK", False), 0,
+            LONG_MAX, False, XA_CARDINAL, &type_ret, &format_ret, &len,
+            &remain, &data) == Success) {
+        if (type_ret == XA_CARDINAL)
+            sup_window = *((Window *)data);
+        XFree(data);
+    }
+    /* So that we can get the net_wm_name */
+    if (sup_window != None) {
+        Atom utf8 = XInternAtom(x11->display, "UTF8_STRING", False);
+        if (XGetWindowProperty(x11->display, sup_window,
+                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
+                LONG_MAX, False, utf8, &type_ret, &format_ret, &len,
+                &remain, &data) == Success) {
+            if (type_ret == utf8) {
+                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
+            }
+            XFree(data);
+        }
+        if (net_wm_name == NULL &&
+            XGetWindowProperty(x11->display, sup_window,
+                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
+                LONG_MAX, False, XA_STRING, &type_ret, &format_ret, &len,
+                &remain, &data) == Success) {
+            if (type_ret == XA_STRING) {
+                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
+            }
+            XFree(data);
+        }
+    }
+
+    vdagent_x11_restore_error_handler(x11);
+
+    if (net_wm_name == NULL)
+        return g_strdup("unknown");
+    return net_wm_name;
 #endif
-    return "unsupported";
 }
 
 struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
@@ -138,7 +200,7 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
     struct vdagent_x11 *x11;
     XWindowAttributes attrib;
     int i, j, major, minor;
-    const gchar *net_wm_name;
+    gchar *net_wm_name = NULL;
 
     x11 = calloc(1, sizeof(*x11));
     if (!x11) {
@@ -238,7 +300,8 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
     /* Since we are started at the same time as the wm,
        sometimes we need to wait a bit for the _NET_WM_NAME to show up. */
     for (i = 0; i < 9; i++) {
-        net_wm_name = vdagent_x11_get_wm_name();
+        g_free(net_wm_name);
+        net_wm_name = vdagent_x11_get_wm_name(x11);
         if (strcmp(net_wm_name, "unknown"))
             break;
         usleep(100000);
@@ -246,6 +309,7 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
     if (x11->debug)
         syslog(LOG_DEBUG, "%s: net_wm_name=\"%s\", has icons=%d",
                __func__, net_wm_name, vdagent_x11_has_icons_on_desktop(x11));
+    g_free(net_wm_name);
 
     /* Flush output buffers and consume any pending events */
     vdagent_x11_do_read(x11);
@@ -1296,7 +1360,7 @@ void vdagent_x11_client_disconnected(struct vdagent_x11 *x11)
    whitelist approach, so any unknown desktop will end up with saving
    file-xfers to the xdg download dir, and opening the xdg download dir with
    xdg-open when the file-xfer completes. */
-int vdagent_x11_has_icons_on_desktop()
+int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11)
 {
     const char * const wms_with_icons_on_desktop[] = {
         "Metacity", /* GNOME-2 or GNOME-3 fallback */
@@ -1305,12 +1369,15 @@ int vdagent_x11_has_icons_on_desktop()
         "Metacity (Marco)", /* Mate, newer */
         NULL
     };
-    const gchar *net_wm_name = vdagent_x11_get_wm_name();
+    gchar *net_wm_name = vdagent_x11_get_wm_name(x11);
     int i;
 
     for (i = 0; wms_with_icons_on_desktop[i]; i++)
-        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i]))
+        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i])) {
+            g_free(net_wm_name);
             return 1;
+        }
 
+    g_free(net_wm_name);
     return 0;
 }
diff --git a/src/vdagent/x11.h b/src/vdagent/x11.h
index a8ceb08..4fd0380 100644
--- a/src/vdagent/x11.h
+++ b/src/vdagent/x11.h
@@ -48,6 +48,6 @@ void vdagent_x11_clipboard_release(struct vdagent_x11 *x11, uint8_t selection);
 
 void vdagent_x11_client_disconnected(struct vdagent_x11 *x11);
 
-int vdagent_x11_has_icons_on_desktop();
+int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11);
 
 #endif
-- 
2.14.3

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]