tnew tool: slw - wmutils - X windows manipulation utilities
 (HTM) git clone git://z3bra.org/wmutils
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f946be83a69bda18f335cec80e5d244b3b884b2a
 (DIR) parent 8d7082a227ba67ac6635420ee343f7d17a90fed9
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon, 14 Oct 2019 12:04:02 +0200
       
       new tool: slw
       
       This tool grabs the cursor and wait for a button press/release event.
       When the event is received, the ID of the window that received the event
       will be printed to stdout.
       
       This is useful to select a random window interactively using the mouse
       pointer.
       
       Note: this adds a new "dependency" on the xcb-utils cursor library.
       
       Diffstat:
         M Makefile                            |       3 ++-
         M README.md                           |       1 +
         M config.mk                           |       4 ++--
         M man/Makefile                        |       1 +
         A man/slw.1                           |      17 +++++++++++++++++
         A slw.c                               |      59 +++++++++++++++++++++++++++++++
       
       6 files changed, 82 insertions(+), 3 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       t@@ -14,7 +14,8 @@ SRC =           \
                wrs.c   \
                chwb.c  \
                ignw.c  \
       -        wmp.c
       +        wmp.c   \
       +        slw.c
        
        OBJ = $(SRC:.c=.o)
        BIN = $(SRC:.c=)
 (DIR) diff --git a/README.md b/README.md
       t@@ -38,6 +38,7 @@ without being added to this list, so take it with a grain of salt.
        * lsw   - list windows
        * mapw  - map/unmap windows
        * pfw   - print focused window
       +* slw   - select window interactively
        * wattr - show window's attributes
        * wmp   - move the mouse pointer
        * wmv   - move a window
 (DIR) diff --git a/config.mk b/config.mk
       t@@ -4,6 +4,6 @@ MANPREFIX = $(PREFIX)/man
        CC      = cc
        LD      = $(CC)
        
       -CFLAGS  = -std=c99 -pedantic -Wall -Os
       -LDFLAGS = -lxcb -lxcb-util
       +CFLAGS  = -std=c99 -pedantic -Wall -Os -I/usr/X11R6/include
       +LDFLAGS = -lxcb -lxcb-util -lxcb-cursor -L/usr/X11R6/lib
        
 (DIR) diff --git a/man/Makefile b/man/Makefile
       t@@ -14,6 +14,7 @@ MAN =           \
                chwb.1  \
                ignw.1  \
                wmp.1   \
       +        slw.1   \
                wmutils.1
        
        .POSIX:
 (DIR) diff --git a/man/slw.1 b/man/slw.1
       t@@ -0,0 +1,17 @@
       +.Dd October 14, 2019
       +.Dt SLW 1
       +.Os wmutils
       +.Sh NAME
       +.Nm slw
       +.Nd select window interactively
       +.Sh SYNOPSIS
       +.Nm slw
       +.Sh DESCRIPTION
       +Wait for a button press event and print the window ID that got the
       +event to
       +.Dv stdout .
       +.Sh ENVIRONMENT
       +.Nm
       +acts on the X display specified by the
       +.Ev DISPLAY
       +variable.
 (DIR) diff --git a/slw.c b/slw.c
       t@@ -0,0 +1,59 @@
       +/* See LICENSE file for copyright and license details. */
       +
       +#include <err.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <xcb/xcb.h>
       +#include <xcb/xcb_aux.h>
       +#include <xcb/xcb_cursor.h>
       +
       +#include "util.h"
       +
       +static xcb_connection_t *conn;
       +static xcb_screen_t *scr;
       +
       +static xcb_window_t
       +select_window(void)
       +{
       +        uint32_t val[] = { XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE  };
       +        xcb_window_t w = 0;
       +        xcb_grab_pointer_cookie_t c;
       +        xcb_grab_pointer_reply_t *r;
       +        xcb_generic_event_t *e;
       +
       +        c = xcb_grab_pointer(conn, 0, scr->root,
       +                XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE,
       +                XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE,
       +                XCB_CURRENT_TIME);
       +
       +        r = xcb_grab_pointer_reply(conn, c, NULL);
       +        if (!r || r->status != XCB_GRAB_STATUS_SUCCESS)
       +                errx(1, "couldn't grab pointer");
       +
       +        xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, val);
       +        xcb_flush(conn);
       +
       +        for (;;) {
       +                e = xcb_wait_for_event(conn);
       +                switch ((e->response_type & ~0x80)) {
       +                case XCB_BUTTON_PRESS:
       +                        w = ((xcb_button_press_event_t*)e)->child;
       +                        break;
       +                case XCB_BUTTON_RELEASE:
       +                        return w;
       +                        break;
       +                }
       +        }
       +}
       +
       +int
       +main(int argc, char **argv)
       +{
       +        init_xcb(&conn);
       +        get_screen(conn, &scr);
       +
       +        printf("0x%08x\n", select_window());
       +
       +        kill_xcb(&conn);
       +        return 0;
       +}