]> git.sesse.net Git - vlc/blobdiff - modules/video_output/xcb/window.c
(p?)gettext -> vlc_\1gettext
[vlc] / modules / video_output / xcb / window.c
index ac5344adb200885a720fe187f17681e9029e4552..0353ce3e54e6789bc59e94b6296a542d06b7d87b 100644 (file)
@@ -27,6 +27,8 @@
 #include <stdarg.h>
 #include <assert.h>
 #include <poll.h>
+#include <unistd.h> /* gethostname() */
+#include <limits.h> /* HOST_NAME_MAX */
 
 #include <xcb/xcb.h>
 #include <xcb/xcb_aux.h>
@@ -70,6 +72,11 @@ struct vout_window_sys_t
     xcb_connection_t *conn;
     key_handler_t *keys;
     vlc_thread_t thread;
+
+    xcb_window_t root;
+    xcb_atom_t wm_state;
+    xcb_atom_t wm_state_above;
+    /*xcb_atom_t wmstate_fullscreen;*/
 };
 
 static inline
@@ -80,6 +87,33 @@ void set_ascii_prop (xcb_connection_t *conn, xcb_window_t window,
                          XA_STRING, 8, strlen (value), value);
 }
 
+static inline
+void set_hostname_prop (xcb_connection_t *conn, xcb_window_t window)
+{
+    char hostname[HOST_NAME_MAX];
+
+    if (gethostname (hostname, sizeof (hostname)) == 0)
+    {
+        hostname[sizeof (hostname) - 1] = '\0';
+        set_ascii_prop (conn, window, XA_WM_CLIENT_MACHINE, hostname);
+    }
+}
+
+static
+xcb_atom_t get_atom (xcb_connection_t *conn, xcb_intern_atom_cookie_t ck)
+{
+    xcb_intern_atom_reply_t *reply;
+    xcb_atom_t atom;
+
+    reply = xcb_intern_atom_reply (conn, ck, NULL);
+    if (reply == NULL)
+        return 0;
+
+    atom = reply->atom;
+    free (reply);
+    return atom;
+}
+
 /**
  * Create an X11 window.
  */
@@ -124,11 +158,16 @@ static int Open (vlc_object_t *obj)
         goto error;
     }
 
+    /* ICCCM
+     * No cut&paste nor drag&drop, only Window Manager communication. */
     /* Plain ASCII localization of VLC for ICCCM window name */
     set_ascii_prop (conn, window, XA_WM_NAME,
-                    pgettext ("ASCII VLC media player", "VLC media player"));
+                  vlc_pgettext ("ASCII VLC media player", "VLC media player"));
     set_ascii_prop (conn, window, XA_WM_ICON_NAME,
-                    pgettext ("ASCII VLC", "VLC"));
+                    vlc_pgettext ("ASCII VLC", "VLC"));
+    xcb_change_property (conn, XCB_PROP_MODE_REPLACE, window, XA_WM_CLASS,
+                         XA_STRING, 8, 8, "vlc\0Vlc");
+    set_hostname_prop (conn, window);
 
     wnd->handle.xid = window;
     wnd->p_sys = p_sys;
@@ -136,7 +175,19 @@ static int Open (vlc_object_t *obj)
 
     p_sys->conn = conn;
     p_sys->keys = CreateKeyHandler (obj, conn);
+    p_sys->root = scr->root;
+
+    /* Cache any EWMH atom we may need later */
+    xcb_intern_atom_cookie_t wm_state_ck, wm_state_above_ck;
 
+    wm_state_ck = xcb_intern_atom (conn, 0, 13, "_NET_WM_STATE");
+    wm_state_above_ck = xcb_intern_atom (conn, 0, 18, "_NET_WM_STATE_ABOVE");
+
+    p_sys->wm_state = get_atom (conn, wm_state_ck);
+    p_sys->wm_state_above = get_atom (conn, wm_state_above_ck);
+
+    /* Create the event thread. It will dequeue all events, so any checked
+     * request from this thread must be completed at this point. */
     if ((p_sys->keys != NULL)
      && vlc_clone (&p_sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW))
         DestroyKeyHandler (p_sys->keys);
@@ -235,6 +286,30 @@ static int Control (vout_window_t *wnd, int cmd, va_list ap)
             break;
         }
 
+        case VOUT_SET_STAY_ON_TOP:
+        {   /* From EWMH "_WM_STATE" */
+            xcb_client_message_event_t ev = {
+                .response_type = 0x80 | XCB_CLIENT_MESSAGE,
+                .format = 32,
+                .window = wnd->handle.xid,
+                .type = p_sys->wm_state,
+            };
+            bool on = va_arg (ap, int);
+
+            ev.data.data32[0] = on;
+            ev.data.data32[1] = p_sys->wm_state_above;
+            ev.data.data32[1] = 289;
+            ev.data.data32[3] = 1;
+
+            /* From ICCCM "Changing Window State" */
+            xcb_send_event (p_sys->conn, 0, p_sys->root,
+                            XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
+                            XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+                            (const char *)&ev);
+            xcb_flush (p_sys->conn);
+            return VLC_SUCCESS;
+        }
+
         default:
             msg_Err (wnd, "request %d not implemented", cmd);
             return VLC_EGENERIC;