tewmh: Add support for _NET_WM_STATE_FULLSCREEN - glazier - window management experiments
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit a9a8d6b606d47a6e022a7ecd5f1986e5dee50ab3
 (DIR) parent 86d2cc63e0198e780e9a2fb9de6eee3bc6579332
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon, 15 Jun 2020 17:20:05 +0200
       
       ewmh: Add support for _NET_WM_STATE_FULLSCREEN
       
       Diffstat:
         M ewmh.c                              |      85 +++++++++++++++++++++++++++++++
       
       1 file changed, 85 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/ewmh.c b/ewmh.c
       t@@ -15,6 +15,10 @@ struct xatom {
                xcb_atom_t atom;
        };
        
       +struct geometry {
       +        uint32_t x, y, w, h, b;
       +};
       +
        enum EWMH_TYPES {
                IGNORE,
                NORMAL,
       t@@ -27,6 +31,8 @@ enum {
                _NET_CLIENT_LIST_STACKING,
                _NET_SUPPORTING_WM_CHECK,
                _NET_ACTIVE_WINDOW,
       +        _NET_WM_STATE,
       +        _NET_WM_STATE_FULLSCREEN,
                _NET_WM_WINDOW_TYPE,
                _NET_WM_WINDOW_TYPE_DESKTOP,
                _NET_WM_WINDOW_TYPE_DOCK,
       t@@ -52,6 +58,8 @@ static int ewmh_supportingwmcheck();
        static int ewmh_activewindow(xcb_window_t);
        static int ewmh_clientlist();
        static int ewmh_type(xcb_window_t);
       +static int ewmh_message(xcb_client_message_event_t *);
       +static int ewmh_fullscreen(xcb_window_t, int);
        
        xcb_connection_t *conn;
        xcb_screen_t     *scrn;
       t@@ -63,6 +71,8 @@ struct xatom ewmh[] = {
                [_NET_CLIENT_LIST_STACKING]         = { .name = "_NET_CLIENT_LIST_STACKING"         },
                [_NET_SUPPORTING_WM_CHECK]          = { .name = "_NET_SUPPORTING_WM_CHECK"          },
                [_NET_ACTIVE_WINDOW]                = { .name = "_NET_ACTIVE_WINDOW"                },
       +        [_NET_WM_STATE]                     = { .name = "_NET_WM_STATE"                     },
       +        [_NET_WM_STATE_FULLSCREEN]          = { .name = "_NET_WM_STATE_FULLSCREEN"          },
                [_NET_WM_WINDOW_TYPE]               = { .name = "_NET_WM_WINDOW_TYPE"               },
                [_NET_WM_WINDOW_TYPE_DESKTOP]       = { .name = "_NET_WM_WINDOW_TYPE_DESKTOP"       },
                [_NET_WM_WINDOW_TYPE_DOCK]          = { .name = "_NET_WM_WINDOW_TYPE_DOCK"          },
       t@@ -246,6 +256,77 @@ ewmh_type(xcb_window_t window)
        }
        
        int
       +ewmh_message(xcb_client_message_event_t *ev)
       +{
       +        unsigned int i;
       +
       +        /* ignore all other messages */
       +        if (ev->type != ewmh[_NET_WM_STATE].atom)
       +                return -1;
       +
       +        if (ev->data.data32[1] == ewmh[_NET_WM_STATE_FULLSCREEN].atom
       +         || ev->data.data32[2] == ewmh[_NET_WM_STATE_FULLSCREEN].atom) {
       +                ewmh_fullscreen(ev->window, ev->data.data32[0]);
       +                return 0;
       +        }
       +
       +        return 1;
       +}
       +
       +int
       +ewmh_fullscreen(xcb_window_t wid, int state)
       +{
       +        size_t n;
       +        int isfullscreen;
       +        xcb_atom_t *atom, orig;
       +        struct geometry g, *d;
       +
       +        atom = wm_get_atom(wid, ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, &n);
       +        orig = wm_add_atom("ORIGINAL_SIZE", strlen("ORIGINAL_SIZE"));
       +
       +        isfullscreen = (atom && *atom == ewmh[_NET_WM_STATE_FULLSCREEN].atom);
       +
       +        switch (state) {
       +        case -1:
       +                return isfullscreen;
       +                break; /* NOTREACHED */
       +
       +        case 0: /* _NET_WM_STATE_REMOVE */
       +                wm_set_atom(wid, ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 0, NULL);
       +                d = wm_get_atom(wid, orig, XCB_ATOM_CARDINAL, &n);
       +                if (!d || !n) return -1;
       +                wm_set_border(d->b, -1, wid);
       +                wm_teleport(wid, d->x, d->y, d->w, d->h);
       +                xcb_delete_property(conn, wid, orig);
       +                break;
       +
       +        case 1: /* _NET_WM_STATE_ADD */
       +                /* save current window geometry */
       +                g.x = wm_get_attribute(wid, ATTR_X);
       +                g.y = wm_get_attribute(wid, ATTR_Y);
       +                g.w = wm_get_attribute(wid, ATTR_W);
       +                g.h = wm_get_attribute(wid, ATTR_H);
       +                g.b = wm_get_attribute(wid, ATTR_B);
       +                wm_set_atom(wid, orig, XCB_ATOM_CARDINAL, 5, &g);
       +
       +                /* move window fullscreen */
       +                g.w = wm_get_attribute(scrn->root, ATTR_W);
       +                g.h = wm_get_attribute(scrn->root, ATTR_H);
       +                wm_set_border(0, -1, wid);
       +                wm_teleport(wid, 0, 0, g.w, g.h);
       +                wm_set_atom(wid, ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 1, &ewmh[_NET_WM_STATE_FULLSCREEN].atom);
       +                break;
       +
       +        case 2: /* _NET_WM_STATE_TOGGLE */
       +                printf("0x%08x !fullscreen\n", wid);
       +                ewmh_fullscreen(wid, !isfullscreen);
       +                break;
       +        }
       +
       +        return 0;
       +}
       +
       +int
        main (int argc, char *argv[])
        {
                int mask;
       t@@ -291,6 +372,10 @@ main (int argc, char *argv[])
                                ewmh_clientlist();
                                break;
        
       +                case XCB_CLIENT_MESSAGE:
       +                        ewmh_message((xcb_client_message_event_t *)ev);
       +                        break;
       +
                        case XCB_FOCUS_IN:
                                ewmh_activewindow(((xcb_focus_in_event_t *)ev)->event);
                                break;