/* тему стоило бы назвать как-нить типа «призер олимпиады по 
 * русскому языку не справился с простейшим вопросом в подворотне 
 * Южного Бутово», но это было бы не очень информативно
*/
В общем, пытаюсь поймать событие ButtonRelease при *завершении* изменения размера окна, чтобы не ловить постоянно «Window resized to %{newX}x${newY}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/Xcursor/Xcursor.h>
#define PointerMotionHint (1 << 16)
int main()
{
    Display *display;
    Window rootWindow, selectedWindow, window = None;
    Cursor cursor;
    XWindowAttributes windowCurAttributes;
    XEvent event;
    int prevWidth, prevHeight, rootX, rootY, winX, winY;
    unsigned int mask;
    bool resizing = false;
    display = XOpenDisplay(NULL);
    if (display == NULL) {
        fprintf(stderr, "Cannot open display\n");
        exit(1);
    }
    cursor = XCreateFontCursor(display, XC_hand2);
    XDefineCursor(display, XRootWindow(display, DefaultScreen(display)), cursor);
    XChangeActivePointerGrab(display, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, cursor, CurrentTime);
    XGrabPointer(display, DefaultRootWindow(display), False,
                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, cursor,
                 CurrentTime);
    while (1) {
        XNextEvent(display, &event);
        switch (event.type) {
        case ButtonPress:
            XQueryPointer(display, DefaultRootWindow(display), &rootWindow, &selectedWindow, &rootX,
                          &rootY, &winX, &winY, &mask);
            window = selectedWindow;
            XSelectInput(display, window, StructureNotifyMask | PointerMotionMask | ButtonReleaseMask);
            printf("Selected window with ID 0x%lx\n", window);
            // XGrabPointer(display, DefaultRootWindow(display), False,
            XGrabPointer(display, window, False,
                         ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync,
                         GrabModeAsync, None, None, CurrentTime);
            XGetWindowAttributes(display, window, &windowCurAttributes);
            prevWidth = windowCurAttributes.width;
            prevHeight = windowCurAttributes.height;
            printf("pointer has been grabbed\n");
            break;
        case ConfigureNotify:
            if (event.xconfigure.window == window) {
                if (1 || resizing) {
                    if (event.xconfigure.width > prevWidth) {
                        printf("Window is being enlarged in width: %dx%d\n",
                               event.xconfigure.width, event.xconfigure.height);
                    }
                    else if (event.xconfigure.width < prevWidth) {
                        printf("Window is being shrunk in width: %dx%d\n",
                               event.xconfigure.width, event.xconfigure.height);
                    }
                    if (event.xconfigure.height > prevHeight) {
                        printf("Window is being enlarged in height: %dx%d\n",
                               event.xconfigure.width, event.xconfigure.height);
                    }
                    else if (event.xconfigure.height < prevHeight) {
                        printf("Window is being shrunk in height: %dx%d\n",
                               event.xconfigure.width, event.xconfigure.height);
                    }
                    prevWidth = event.xconfigure.width;
                    prevHeight = event.xconfigure.height;
                }
            }
            break;
        case MotionNotify:
            if (window != None) {
                int rootX, rootY, winX, winY;
                unsigned int mask;
                XQueryPointer(display, window, &rootWindow, &selectedWindow, &rootX, &rootY, &winX,
                              &winY, &mask);
                int border_size = 5;
                if (winX <= border_size) {
                    if (winY <= border_size) {
                        cursor = XcursorShapeLoadCursor(display, XC_top_left_corner);
                        XChangeActivePointerGrab(display, PointerMotionMask | ButtonReleaseMask,
                                                 cursor, CurrentTime);
                        resizing = true;
                    }
                    else if (winY >= event.xconfigure.height - border_size) {
                        cursor = XcursorShapeLoadCursor(display, XC_bottom_left_corner);
                        XChangeActivePointerGrab(display, PointerMotionMask | ButtonReleaseMask,
                                                 cursor, CurrentTime);
                        resizing = true;
                    }
                    else {
                        XChangeActivePointerGrab(display, PointerMotionMask | ButtonReleaseMask,
                                                 None, CurrentTime);
                        resizing = false;
                    }
                }
                else if (winX >= event.xconfigure.width - border_size) {
                    if (winY <= border_size) {
                        cursor = XcursorShapeLoadCursor(display, XC_top_right_corner);
                        XChangeActivePointerGrab(display, PointerMotionMask | ButtonReleaseMask,
                                                 cursor, CurrentTime);
                        resizing = true;
                    }
                    else if (winY >= event.xconfigure.height - border_size) {
                        cursor = XcursorShapeLoadCursor(display, XC_bottom_right_corner);
                        XChangeActivePointerGrab(display, PointerMotionMask | ButtonReleaseMask,
                                                 cursor, CurrentTime);
                        resizing = true;
                    }
                    else {
                        XChangeActivePointerGrab(display, PointerMotionMask | ButtonReleaseMask,
                                                 None, CurrentTime);
                        resizing = false;
                    }
                }
                else {
                    XChangeActivePointerGrab(display, PointerMotionMask | ButtonReleaseMask,
                                             None, CurrentTime);
                    resizing = false;
                }
            }
            break;
        case ButtonRelease:
            printf("Button released\n");
            if (window != None) {
                XUngrabPointer(display, CurrentTime);
                printf("Pointer ungrabbed\n");
                printf("Window resizing has been finished\n");
            }
            break;
        default:
            break;
        }
        if (event.type == ConfigureNotify) {
            printf("Window resized to %dx%d\n", event.xconfigure.width, event.xconfigure.height);
        }// else
//			printf("event.type == %d\n", event.type);
    }
}
но получается только один раз при выборе окна:
$ ./scnotify 
Selected window with ID 0x170917c
pointer has been grabbed
Button released
Pointer ungrabbed
Window resizing has been finished
Window is being enlarged in width: 1310x780
Window resized to 1310x780
Window is being enlarged in width: 1311x780
Window resized to 1311x780
Window is being enlarged in width: 1312x780
Window resized to 1312x780
^C     # а ожидался "Button released"
У нас остались люди сведущие в Xlib? Где я косячу?

