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