Leidos Proprietary

We are encountering an issue with Xorg 1.17.2 (Yes I know it is very old).  

    1. Compile the attached program  [gcc touchbug.c -o touchbug -lxcb]
    2. Run the program [./touchbug ]
    3. Move the mouse over the application window, notice the console output 
indicates no buttons are pressed.
    4. Press and hold the mouse in the window created by the attached program 
(this will grab the pointer).
    5. Without releasing the mouse generate a touch event outside of the window 
(this will ungrab the pointer).
    6. Move the mouse over the window (notice the console output indicates 
Button1 is pressed). 

I would have expected, in step 6, the console output would again indicate no 
button is pressed.  

I've tried this with xscope between the example application and the xserver and 
xscope indicates the motion events sent by the XServer are also reporting 
Button1 is pressed.    I have though noticed [xinput --query-state <id>] for 
the mouse indicates all buttons are "up".

It appears this issue has been fixed in Xorg 1.20.4 (at least I'm not seeing 
the issue on a upgraded workstation that happens to have a later version of 
Xorg).   

What I'm trying to figure out is what component might be involved in this issue 
(XServer, XInputExtention, Kernel Driver)?  Is the issue core to the Xserver or 
is this because the XInput extension has somehow modified the events so that 
XCB cannot read them correctly?   Is it possible anyone has heard of this issue 
and can point to where it was fixed?  Is it possible we have somehow 
misconfigured our XServer?

Thanks,

Andrew Nelson

This email and any attachments to it are intended only for the identified 
recipients. It may contain proprietary or otherwise legally protected 
information of Leidos. Any unauthorized use or disclosure of this communication 
is strictly prohibited. If you have received this communication in error, 
please notify the sender and delete or otherwise destroy the email and all 
attachments immediately.
// Compile:
// gcc touchbug.c -o touchbug -lxcb

#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <inttypes.h>
#include <unistd.h>

#define TRUE 1
#define FALSE 0

void print_state(uint16_t mask)
{
    if(mask & XCB_EVENT_MASK_NO_EVENT) {
        printf("NO_EVENT\n");
    }
    if(mask & XCB_EVENT_MASK_KEY_PRESS) {
        printf("KEY_PRESS\n");
    }
    if(mask & XCB_EVENT_MASK_KEY_RELEASE) {
        printf("KEY_RELEASE\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_PRESS) {
        printf("BUTTON_PRESS\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_RELEASE) {
        printf("BUTTON_RELEASE\n");
    }
    if(mask & XCB_EVENT_MASK_ENTER_WINDOW) {
        printf("ENTER_WINDOW\n");
    }
    if(mask & XCB_EVENT_MASK_LEAVE_WINDOW) {
        printf("LEAVE_WINDOW\n");
    }
    if(mask & XCB_EVENT_MASK_POINTER_MOTION) {
        printf("POINTER MOTION\n");
    }
    if(mask & XCB_EVENT_MASK_POINTER_MOTION_HINT) {
        printf("POINTER_MOTION_HINT\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_1_MOTION) {
        printf("BUTTON_1_MOTION\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_2_MOTION) {
        printf("BUTTON_2_MOTION\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_3_MOTION) {
        printf("BUTTON_3_MOTION\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_4_MOTION) {
        printf("BUTTON_4_MOTION\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_5_MOTION) {
        printf("BUTTON_5_MOTION\n");
    }
    if(mask & XCB_EVENT_MASK_BUTTON_MOTION) {
        printf("BUTTON_MOTION\n");
    }
    if(mask & XCB_EVENT_MASK_KEYMAP_STATE) {
        printf("KEYMAP_STATE\n");
    }
    if(mask & XCB_EVENT_MASK_EXPOSURE) {
        printf("EXPOSURE\n");
    }
    if(mask & XCB_EVENT_MASK_VISIBILITY_CHANGE) {
        printf("VISIBILITY_CHANGE\n");
    }
    if(mask & XCB_EVENT_MASK_STRUCTURE_NOTIFY) {
        printf("STRUCTURE_NOTIFY\n");
    }
    if(mask & XCB_EVENT_MASK_RESIZE_REDIRECT) {
        printf("RESIZE_REDIRECT\n");
    }
    if(mask & XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY) {
        printf("SUBSTRUCTURE_NOTIFY\n");
    }
    if(mask & XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT) {
        printf("SUBSTRUCTURE_REDIRECT\n");
    }
    if(mask & XCB_EVENT_MASK_FOCUS_CHANGE) {
        printf("FOCUS_CHANGE\n");
    }
    if(mask & XCB_EVENT_MASK_PROPERTY_CHANGE) {
        printf("PROPERTY_CHANGE\n");
    }
}

int grab_pointer(xcb_connection_t *conn, xcb_screen_t *screen)
{
    xcb_grab_pointer_cookie_t cookie;
    xcb_grab_pointer_reply_t *reply;

    uint16_t event_mask = XCB_EVENT_MASK_BUTTON_PRESS
        | XCB_EVENT_MASK_BUTTON_RELEASE
        | XCB_EVENT_MASK_ENTER_WINDOW
        | XCB_EVENT_MASK_LEAVE_WINDOW
        | XCB_EVENT_MASK_POINTER_MOTION
        | XCB_EVENT_MASK_BUTTON_MOTION;

    cookie = xcb_grab_pointer(
        conn,
        TRUE,                /* If 1, the grab_window will still get the 
pointer events. If 0, events are not reported to the grab_window. */
        screen->root,        /* grab the root window */
        event_mask,          /* which events to let through */
        XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */
        XCB_GRAB_MODE_ASYNC, /* keyboard mode */
        XCB_NONE,            /* confine_to = in which window should the cursor 
stay */
        XCB_NONE,            /* leave the cursor alone */
        XCB_CURRENT_TIME
    );

    int success = FALSE;

    if ((reply = xcb_grab_pointer_reply(conn, cookie, NULL))) {
        if (reply->status == XCB_GRAB_STATUS_SUCCESS)
            success = TRUE;
        free(reply);
    }

    return success;
}

int ungrab_pointer(xcb_connection_t *conn)
{
    xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
    xcb_flush(conn);
    return TRUE;
}

int main()
{
    xcb_connection_t *connection;
    const xcb_setup_t *setup;
    xcb_screen_t *screen;
    xcb_window_t win;
    xcb_gcontext_t foreground;
    xcb_generic_event_t *event;

    uint32_t mask;
    uint32_t values[2];

    uint32_t configure_mask;
    uint32_t configure_values[4];

    /* Option the connection to the X server.
       Using DISPLAY environment variable as the default
       display name */
    connection = xcb_connect(NULL, NULL);

    if (xcb_connection_has_error(connection)) {
        fprintf(stderr, "Unable to connect to xserver. Please check 
$DISPLAY.\n");
        xcb_disconnect(connection);
        return 0;
    }

    /* Get the first screen */
    setup = xcb_get_setup(connection);
    screen = xcb_setup_roots_iterator(setup).data;

    /* Create black (foreground) graphic context */
    win = screen->root;

    foreground = xcb_generate_id(connection);
    mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES,
    values[0] = screen->black_pixel;
    values[1] = 0;
    xcb_create_gc(connection, foreground, win, mask, values);

    /* Ask for the window id */
    win = xcb_generate_id(connection);

    /* Create the window */
    mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    values[0] = screen->white_pixel;
    values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS | 
XCB_EVENT_MASK_POINTER_MOTION;

    xcb_create_window(connection,
                      XCB_COPY_FROM_PARENT,
                      win,
                      screen->root,
                      50, 0,
                      150, 150,
                      10,
                      XCB_WINDOW_CLASS_INPUT_OUTPUT,
                      screen->root_visual,
                      mask,
                      values);

    configure_mask = 0;
    configure_mask |= XCB_CONFIG_WINDOW_X;
    configure_mask |= XCB_CONFIG_WINDOW_Y;
    configure_mask |= XCB_CONFIG_WINDOW_WIDTH;
    configure_mask |= XCB_CONFIG_WINDOW_HEIGHT;

    configure_values[0] = 300;
    configure_values[1] = 20;
    configure_values[2] = 250;
    configure_values[2] = 350;

    /* Map the window on the screen */
    xcb_map_window(connection, win);

    /* We flush the request */
    xcb_flush(connection);

    uint16_t grabbed = FALSE;

    while((event = xcb_wait_for_event(connection))) {
        switch(event->response_type & ~0x80) {
            case XCB_EXPOSE: {
                printf("XCB_EXPOSE\n");
                break;
            }
            case XCB_BUTTON_PRESS: {
                xcb_button_press_event_t *press = (xcb_button_press_event_t 
*)event;
                printf("XCB_BUTTON_PRESS\n");
                if(grabbed) {
                    int success = ungrab_pointer(connection);
                    if(success) {
                        printf("successfully ungrabbed the pointer\n");
                        grabbed = FALSE;
                    }
                } else {
                    int success = grab_pointer(connection, screen);     
                    if(success) {
                        printf("successfully grabbed the pointer\n");
                        grabbed = TRUE;
                    }
                }
                break;
            }
            case XCB_MOTION_NOTIFY: {
                xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t 
*)event;
                printf("XCB_POINTER_MOTION: detail (%"PRIi8") coordinates 
(%"PRIi16",%"PRIi16"), state %"PRIi16"\n",
                        motion->detail, motion->event_x, motion->event_y, 
motion->state);
                print_state(motion->state);
                break;
            }
        }
        free(event);
    }
    
    xcb_disconnect(connection);

    return 0;
}
_______________________________________________
xorg@lists.x.org: X.Org support
Archives: http://lists.freedesktop.org/archives/xorg
Info: https://lists.x.org/mailman/listinfo/xorg
Your subscription address: %(user_address)s

Reply via email to