LINUX.ORG.RU

не получается в Xlib

 


0

2

/* тему стоило бы назвать как-нить типа «призер олимпиады по
* русскому языку не справился с простейшим вопросом в подворотне
* Южного Бутово», но это было бы не очень информативно
*/

В общем, пытаюсь поймать событие 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? Где я косячу?

Не пойму что ты пытаешься сделать то?

Нажал мышкой в окно - ButtonPress (+ты захватываешь мышку по этому событию и пишешь лог). Потом отпустил её - ButtonRelease (+ты отменяешь захват). Потом ты делаешь ресайз, никаких ButtonPress/ButtonRelease при этом присылаться окну не должно, ресайз делается средствами WM. И тем более не должно присылаться одиночного Release без предварительного соответствующего Press, как ты кажется ждёшь.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)