tLimit fullscreen state to the window's monitor - glazier - window management experiments
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit d02a48771a00e813baa2533ced61e33c8d1e3183
 (DIR) parent f303cc1eec7030e6cc237cf777702e8dbce0b8d2
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon, 15 Jun 2020 17:52:54 +0200
       
       Limit fullscreen state to the window's monitor
       
       Diffstat:
         M ewmh.c                              |      59 +++++++++++++++++++++++++------
       
       1 file changed, 48 insertions(+), 11 deletions(-)
       ---
 (DIR) diff --git a/ewmh.c b/ewmh.c
       t@@ -4,6 +4,7 @@
        #include <string.h>
        #include <xcb/xcb.h>
        #include <xcb/xcb_cursor.h>
       +#include <xcb/randr.h>
        
        #include "arg.h"
        #include "wm.h"
       t@@ -271,16 +272,49 @@ ewmh_message(xcb_client_message_event_t *ev)
                return 1;
        }
        
       +
       +/*
       + * Return the geometry of the monitor pointed to by the given coordinates
       + */
       +int
       +randr_monitor(int x, int y, struct geometry *m)
       +{
       +        xcb_randr_get_monitors_cookie_t c;
       +        xcb_randr_get_monitors_reply_t *r;
       +        xcb_randr_monitor_info_iterator_t i;
       +
       +        /* get_active: ignore inactive monitors */
       +        c = xcb_randr_get_monitors(conn, scrn->root, 1);
       +        r = xcb_randr_get_monitors_reply(conn, c, NULL);
       +        i = xcb_randr_get_monitors_monitors_iterator(r);
       +
       +        while (i.rem > 0) {
       +                if (x >= i.data->x
       +                 && y >= i.data->y
       +                 && x <= i.data->width + i.data->x
       +                 && y <= i.data->height + i.data->y) {
       +                        m->x = i.data->x;
       +                        m->y = i.data->y;
       +                        m->w = i.data->width;
       +                        m->h = i.data->height;
       +                        return 0;
       +                }
       +                xcb_randr_monitor_info_next(&i);
       +        }
       +
       +        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;
       +        xcb_atom_t *atom, original_size;
       +        struct geometry g, *origin;
        
                atom = wm_get_atom(wid, ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, &n);
       -        orig = wm_add_atom("ORIGINAL_SIZE", strlen("ORIGINAL_SIZE"));
       +        original_size = wm_add_atom("ORIGINAL_SIZE", strlen("ORIGINAL_SIZE"));
        
                isfullscreen = (atom && *atom == ewmh[_NET_WM_STATE_FULLSCREEN].atom);
        
       t@@ -291,11 +325,13 @@ ewmh_fullscreen(xcb_window_t wid, int state)
        
                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);
       +                origin = (struct geometry *)wm_get_atom(wid, original_size, XCB_ATOM_CARDINAL, &n);
       +                if (!origin || n < 5)
       +                        return -1;
       +
       +                wm_set_border(origin->b, -1, wid);
       +                wm_teleport(wid, origin->x, origin->y, origin->w, origin->h);
       +                xcb_delete_property(conn, wid, original_size);
                        break;
        
                case 1: /* _NET_WM_STATE_ADD */
       t@@ -305,11 +341,12 @@ ewmh_fullscreen(xcb_window_t wid, int state)
                        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);
       +                wm_set_atom(wid, original_size, XCB_ATOM_CARDINAL, 5, &g);
       +
       +                if (randr_monitor(g.x, g.y, &g) < 0)
       +                        return -1;
        
                        /* 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);