/* We start the exposition when the user touch triangle reactangle at the top left. */ static int _handle_motion_notify(xcb_motion_notify_event_t *e) { if (e->root_x + e->root_y < 20 && _this.state == _IDLE && gd.win_count >= 2) { _show(); } else { xcb_ungrab_pointer(gd.conn, XCB_TIME_CURRENT_TIME); e->time = XCB_CURRENT_TIME; xcb_send_event(gd.conn, 1, e->child, 0, (char *) e); xcb_grab_pointer(gd.conn, 1, gd.def_screen->root, XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME); xcb_flush(gd.conn); } return 1; }
void menuwin_grab_mouse() { if (key_win.mouse_grabed==0) { xcb_grab_pointer_cookie_t grab_cookie; xcb_grab_pointer_reply_t *grab_reply; uint16_t mask=XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_PRESS|XCB_EVENT_MASK_LEAVE_WINDOW; grab_cookie=xcb_grab_pointer(conn,1,key_win.window,mask,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC,XCB_WINDOW_NONE,XCB_CURSOR_NONE,XCB_CURRENT_TIME); xcb_flush(conn); grab_reply=xcb_grab_pointer_reply(conn,grab_cookie,0); if (grab_reply->status==0) { key_win.mouse_grabed=1; } free(grab_reply); } }
/** Handle the ButtonPress event */ static void handle_button_press(xcb_button_press_event_t *e) { NIL_LOG("event: mouse %d pressed: event %d, child %d (%d,%d)", e->detail, e->event, e->child, e->event_x, e->event_y); if (e->event == bar_.win) { if (click_bar(e->event_x)) { xcb_flush(nil_.con); } return; } /* click on client with modkey */ if (MOD_MASK_(e->state) == cfg_.mod_key) { mouse_evt_.client = find_client(e->child, &mouse_evt_.ws); if (!mouse_evt_.client) { NIL_ERR("no client %d", e->child); goto end; } NIL_LOG("button on win=%d", mouse_evt_.client->win); switch (e->detail) { case XCB_BUTTON_INDEX_3: mouse_evt_.mode = CURSOR_RESIZE; /* warp pointer to lower right */ mouse_evt_.x1 = mouse_evt_.client->x + mouse_evt_.client->w; mouse_evt_.y1 = mouse_evt_.client->y + mouse_evt_.client->h; xcb_warp_pointer(nil_.con, XCB_NONE, mouse_evt_.client->win, 0, 0, 0, 0, mouse_evt_.x1, mouse_evt_.y1); break; case XCB_BUTTON_INDEX_1: default: mouse_evt_.mode = CURSOR_MOVE; mouse_evt_.x1 = e->event_x; mouse_evt_.y1 = e->event_y; break; } /* take control of the pointer in the root window */ xcb_grab_pointer(nil_.con, 0, nil_.scr->root, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, nil_.cursor[mouse_evt_.mode], XCB_CURRENT_TIME); xcb_flush(nil_.con); return; } end: /* if unhandled, forward the click to the application */ xcb_allow_events(nil_.con, XCB_ALLOW_REPLAY_POINTER, e->time); }
static bool grab_pointer(xcb_connection_t *conn, xcb_screen_t *screen) { xcb_grab_pointer_cookie_t cookie = xcb_grab_pointer(conn, false, screen->root, XCB_NONE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME); xcb_grab_pointer_reply_t *reply; if ((reply = xcb_grab_pointer_reply(conn, cookie, NULL))) { if (reply->status == XCB_GRAB_STATUS_SUCCESS) { free(reply); return true; } free(reply); } return false; }
xcb_window_t Select_Window(xcb_connection_t *dpy, const xcb_screen_t *screen, int descend) { xcb_cursor_t cursor; xcb_generic_event_t *event; xcb_window_t target_win = XCB_WINDOW_NONE; xcb_window_t root = screen->root; int buttons = 0; xcb_generic_error_t *err; xcb_grab_pointer_cookie_t grab_cookie; xcb_grab_pointer_reply_t *grab_reply; /* Make the target cursor */ cursor = Create_Font_Cursor (dpy, XC_crosshair); /* Grab the pointer using target cursor, letting it room all over */ grab_cookie = xcb_grab_pointer (dpy, False, root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, root, cursor, XCB_TIME_CURRENT_TIME); grab_reply = xcb_grab_pointer_reply (dpy, grab_cookie, &err); if (grab_reply->status != XCB_GRAB_STATUS_SUCCESS) Fatal_Error ("Can't grab the mouse."); /* Let the user select a window... */ while ((target_win == XCB_WINDOW_NONE) || (buttons != 0)) { /* allow one more event */ xcb_allow_events (dpy, XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); xcb_flush (dpy); event = xcb_wait_for_event (dpy); switch (event->response_type & 0x7f) { case XCB_BUTTON_PRESS: { xcb_button_press_event_t *bp = (xcb_button_press_event_t *)event; if (target_win == XCB_WINDOW_NONE) { target_win = bp->child; /* window selected */ if (target_win == XCB_WINDOW_NONE) target_win = root; } buttons++; break; } case XCB_BUTTON_RELEASE: if (buttons > 0) /* there may have been some down before we started */ buttons--; break; default: /* just discard all other events */ break; } free (event); } xcb_ungrab_pointer (dpy, XCB_TIME_CURRENT_TIME); /* Done with pointer */ if (!descend || (target_win == root)) return (target_win); target_win = Find_Client (dpy, root, target_win); return (target_win); }
/* * Repeatedly tries to grab pointer and keyboard (up to the specified number of * tries). * * Returns true if the grab succeeded, false if not. * */ bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor, int tries) { xcb_grab_pointer_cookie_t pcookie; xcb_grab_pointer_reply_t *preply; xcb_grab_keyboard_cookie_t kcookie; xcb_grab_keyboard_reply_t *kreply; const suseconds_t screen_redraw_timeout = 100000; /* 100ms */ /* Using few variables to trigger a redraw_screen() if too many tries */ bool redrawn = false; struct timeval start; if (gettimeofday(&start, NULL) == -1) { err(EXIT_FAILURE, "gettimeofday"); } while (tries-- > 0) { pcookie = xcb_grab_pointer( conn, false, /* get all pointer events specified by the following mask */ screen->root, /* grab the root window */ XCB_NONE, /* 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 */ cursor, /* we change the cursor to whatever the user wanted */ XCB_CURRENT_TIME); if ((preply = xcb_grab_pointer_reply(conn, pcookie, NULL)) && preply->status == XCB_GRAB_STATUS_SUCCESS) { free(preply); break; } /* Make this quite a bit slower */ usleep(50); struct timeval now; if (gettimeofday(&now, NULL) == -1) { err(EXIT_FAILURE, "gettimeofday"); } struct timeval elapsed; timersub(&now, &start, &elapsed); if (!redrawn && (tries % 100) == 0 && elapsed.tv_usec >= screen_redraw_timeout) { redraw_screen(); redrawn = true; } } while (tries-- > 0) { kcookie = xcb_grab_keyboard( conn, true, /* report events */ screen->root, /* grab the root window */ XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ XCB_GRAB_MODE_ASYNC); if ((kreply = xcb_grab_keyboard_reply(conn, kcookie, NULL)) && kreply->status == XCB_GRAB_STATUS_SUCCESS) { free(kreply); break; } /* Make this quite a bit slower */ usleep(50); struct timeval now; if (gettimeofday(&now, NULL) == -1) { err(EXIT_FAILURE, "gettimeofday"); } struct timeval elapsed; timersub(&now, &start, &elapsed); /* Trigger a screen redraw if 100ms elapsed */ if (!redrawn && (tries % 100) == 0 && elapsed.tv_usec >= screen_redraw_timeout) { redraw_screen(); redrawn = true; } } return (tries > 0); }
int main(void) { xcb_connection_t *c; xcb_screen_t *s; xcb_window_t w; xcb_gcontext_t g; xcb_generic_event_t *e; uint32_t mask; uint32_t values[2]; int done = 0; /* open connection with the server */ c = xcb_connect(NULL,NULL); if (xcb_connection_has_error(c)) { printf("Cannot open display\n"); exit(1); } /* get the first screen */ s = xcb_setup_roots_iterator( xcb_get_setup(c) ).data; G.conn = c; G.s= s; //enable mouse event xcb_cursor_t cursor; xcb_font_t cursor_font=0; short glyph = 0x34; //cross xcb_grab_pointer_cookie_t grab_cookie; xcb_grab_pointer_reply_t *grab_reply; xcb_generic_error_t *err; cursor = xcb_generate_id (c); if (!cursor_font) { cursor_font = xcb_generate_id (c); xcb_open_font (c, cursor_font, strlen ("cursor"), "cursor"); } xcb_create_glyph_cursor (c, cursor, cursor_font, cursor_font, glyph, glyph + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff); /* rgb, rgb */ grab_cookie = xcb_grab_pointer(c, 0, s->root, XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, s->root, cursor, XCB_TIME_CURRENT_TIME); assert(grab_reply!=NULL); grab_reply = xcb_grab_pointer_reply (c, grab_cookie, &err); if (grab_reply->status != XCB_GRAB_STATUS_SUCCESS) printf("Can't grab the mouse."); printf("grab pointer cookie=0x%x\n", grab_cookie); xcb_allow_events (c, XCB_ALLOW_ASYNC_POINTER, XCB_TIME_CURRENT_TIME); xcb_flush (c); // xcb_allow_events (c, XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); xcb_flush (c); while (!done ) { e = xcb_wait_for_event(c); if(e==NULL) printf("wait event error\n"); //printf("\revent=>%d", e->response_type); switch (e->response_type & ~0x80) { case XCB_EXPOSE: /* draw or redraw the window */ printf("XCB_EXPOSE\n"); draw_gc(w); break; case XCB_MOTION_NOTIFY: { static xcb_window_t oldw; xcb_button_press_event_t *bp = (xcb_button_press_event_t *)e; w = bp->child; /* window selected */ if(oldw!=w){ oldw = w; printf("windowid = %x\n", w); } //draw it draw_gc(w); } break; case XCB_BUTTON_PRESS: { xcb_button_press_event_t *bp = (xcb_button_press_event_t *)e; w = bp->child; /* window selected */ if (w== XCB_WINDOW_NONE){ printf("window select is root\n"); w=s->root; } else printf("window = %x\n", w); draw_gc(w); done=1; printf("grab a child\n"); break; } } free(e); } xcb_ungrab_pointer(c, XCB_TIME_CURRENT_TIME); draw_byxid(w); return 0; #if 0 /* create window */ w = xcb_generate_id(c); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = s->white_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; xcb_create_window(c, s->root_depth, w, s->root, 10, 10, 100, 100, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, s->root_visual, mask, values); /* map (show) the window */ xcb_map_window(c, w); xcb_flush(c); /* event loop */ while (!done && (e = xcb_wait_for_event(c))) { switch (e->response_type & ~0x80) { case XCB_EXPOSE: /* draw or redraw the window */ xcb_poly_fill_rectangle(c, w, g, 1, &r); xcb_flush(c); break; case XCB_KEY_PRESS: /* exit on key press */ //gwj done = 1; break; } free(e); } /* close connection to server */ xcb_disconnect(c); return 0; if(0){ //draw image with xcb_put_image // creat gc and draw to parent window xcb_gcontext_t g; g = xcb_generate_id(c); xcb_create_gc(c, g, child, 0,NULL); //xcb_poly_fill_rectangle(c, w, g, 1, &r); xcb_flush(c); int psize=geo->width * geo->height* (geo->depth/8); uint8_t *pbuf = malloc(psize); xcb_void_cookie_t ck; printf("malloc pbuf=0x%x size=%d\n",pbuf, psize); memset(pbuf, 0x18, psize); ck = xcb_put_image_checked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, child, g, geo->width, geo->height , 0, 0, 0, geo->depth, psize, pbuf); //BadMatch=8 BadLength=16 xcb_generic_error_t *err; err = xcb_request_check (c, ck); if (err) { int code = err->error_code; free (err); printf("put image error %d\n", code); assert (code != 0); } } printf("depth =%d\n", geo->depth); /* create black graphics context */ #endif }
/* * Repeatedly tries to grab pointer and keyboard (up to 10000 times). * */ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) { xcb_grab_pointer_cookie_t pcookie; xcb_grab_pointer_reply_t *preply; xcb_grab_keyboard_cookie_t kcookie; xcb_grab_keyboard_reply_t *kreply; int tries = 10000; /* Using few variables to trigger a redraw_screen() if too many tries */ bool redrawn = false; time_t start = clock(); while (tries-- > 0) { pcookie = xcb_grab_pointer( conn, false, /* get all pointer events specified by the following mask */ screen->root, /* grab the root window */ XCB_NONE, /* 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 */ cursor, /* we change the cursor to whatever the user wanted */ XCB_CURRENT_TIME); if ((preply = xcb_grab_pointer_reply(conn, pcookie, NULL)) && preply->status == XCB_GRAB_STATUS_SUCCESS) { free(preply); break; } /* Make this quite a bit slower */ usleep(50); /* Measure elapsed time and trigger a screen redraw if elapsed > 250000 */ if (!redrawn && (tries % 100) == 0 && (clock() - start) > 250000) { redraw_screen(); redrawn = true; } } while (tries-- > 0) { kcookie = xcb_grab_keyboard( conn, true, /* report events */ screen->root, /* grab the root window */ XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ XCB_GRAB_MODE_ASYNC); if ((kreply = xcb_grab_keyboard_reply(conn, kcookie, NULL)) && kreply->status == XCB_GRAB_STATUS_SUCCESS) { free(kreply); break; } /* Make this quite a bit slower */ usleep(50); /* Measure elapsed time and trigger a screen redraw if elapsed > 250000 */ if (!redrawn && (tries % 100) == 0 && (clock() - start) > 250000) { redraw_screen(); redrawn = true; } } /* After trying for 10000 times, i3lock will display an error message * for 2 sec prior to terminate. */ if (tries <= 0) { pam_state = STATE_I3LOCK_LOCK_FAILED; redraw_screen(); sleep(1); errx(EXIT_FAILURE, "Cannot grab pointer/keyboard"); } }
static void events_loop (void) { uint32_t values[3]; xcb_generic_event_t *ev; xcb_get_geometry_reply_t *geom; xcb_window_t win = 0; /* loop */ for (;;) { ev = xcb_wait_for_event(conn); if (ev == NULL) errx(1, "xcb connection broken"); switch (ev->response_type & ~0x80) { case XCB_CREATE_NOTIFY: { xcb_create_notify_event_t *e; e = (xcb_create_notify_event_t *)ev; if (!e->override_redirect) { setup_win(e->window); focus(e->window, ACTIVE); } } break; case XCB_DESTROY_NOTIFY: { xcb_destroy_notify_event_t *e; e = (xcb_destroy_notify_event_t *)ev; xcb_kill_client(conn, e->window); } break; case XCB_KEY_PRESS: { xcb_key_press_event_t *e; e = (xcb_key_press_event_t *)ev; xcb_keysym_t keysym = xcb_get_keysym(e->detail); for (unsigned int i=0; i < LENGTH(keys); i++) { if (keys[i].keysym == keysym && CLEANMASK(keys[i].mod) == CLEANMASK(e->state) && keys[i].mfunc) { keys[i].mfunc(keys[i].x, keys[i].y); } else if (keys[i].keysym == keysym && CLEANMASK(keys[i].mod) == CLEANMASK(e->state) && keys[i].func) { keys[i].func(); } } } break; case XCB_ENTER_NOTIFY: { xcb_enter_notify_event_t *e; e = (xcb_enter_notify_event_t *)ev; focus(e->event, ACTIVE); } break; case XCB_MAP_NOTIFY: { xcb_map_notify_event_t *e; e = (xcb_map_notify_event_t *)ev; if (!e->override_redirect) { xcb_map_window(conn, e->window); xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, e->window, XCB_CURRENT_TIME); } } break; case XCB_BUTTON_PRESS: { xcb_button_press_event_t *e; e = ( xcb_button_press_event_t *)ev; win = e->child; if (!win || win == scr->root) break; values[0] = XCB_STACK_MODE_ABOVE; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values); geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); if (1 == e->detail) { values[2] = 1; center_pointer(win); } else { values[2] = 3; xcb_warp_pointer(conn, XCB_NONE, win, 0, 0, 0, 0, geom->width, geom->height); } xcb_grab_pointer(conn, 0, scr->root, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, XCB_CURRENT_TIME); xcb_flush(conn); } break; case XCB_MOTION_NOTIFY: { xcb_query_pointer_reply_t *pointer; pointer = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, scr->root), 0); if (values[2] == 1) { geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); if (!geom) { break; } values[0] = (pointer->root_x + geom->width / 2 > scr->width_in_pixels - (BORDERWIDTH*2)) ? scr->width_in_pixels - geom->width - (BORDERWIDTH*2) : pointer->root_x - geom->width / 2; values[1] = (pointer->root_y + geom->height / 2 > scr->height_in_pixels - (BORDERWIDTH*2)) ? (scr->height_in_pixels - geom->height - (BORDERWIDTH*2)) : pointer->root_y - geom->height / 2; if (pointer->root_x < geom->width/2) values[0] = 0; if (pointer->root_y < geom->height/2) values[1] = 0; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); xcb_flush(conn); } else if (values[2] == 3) { focus(win, RESIZE); geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); values[0] = pointer->root_x - geom->x; values[1] = pointer->root_y - geom->y; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); xcb_flush(conn); } } break; case XCB_BUTTON_RELEASE: focus(win, ACTIVE); xcb_ungrab_pointer(conn, XCB_CURRENT_TIME); break; } xcb_flush(conn); free(ev); } }
static void ephyrProcessKeyRelease(xcb_generic_event_t *xev) { xcb_connection_t *conn = hostx_get_xcbconn(); xcb_key_release_event_t *key = (xcb_key_release_event_t *)xev; static xcb_key_symbols_t *keysyms; static int grabbed_screen = -1; int mod1_down = ephyrUpdateGrabModifierState(key->state); if (!keysyms) keysyms = xcb_key_symbols_alloc(conn); if (!EphyrWantNoHostGrab && (((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_L || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_R) && (key->state & XCB_MOD_MASK_CONTROL)) || ((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_L || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_R) && (key->state & XCB_MOD_MASK_SHIFT)))) { KdScreenInfo *screen = screen_from_window(key->event); EphyrScrPriv *scrpriv = screen->driver; if (grabbed_screen != -1) { xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME); xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); grabbed_screen = -1; hostx_set_win_title(screen, "(ctrl+shift grabs mouse and keyboard)"); } else if (!mod1_down) { /* Attempt grab */ xcb_grab_keyboard_cookie_t kbgrabc = xcb_grab_keyboard(conn, TRUE, scrpriv->win, XCB_TIME_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); xcb_grab_keyboard_reply_t *kbgrabr; xcb_grab_pointer_cookie_t pgrabc = xcb_grab_pointer(conn, TRUE, scrpriv->win, 0, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scrpriv->win, XCB_NONE, XCB_TIME_CURRENT_TIME); xcb_grab_pointer_reply_t *pgrabr; kbgrabr = xcb_grab_keyboard_reply(conn, kbgrabc, NULL); if (!kbgrabr || kbgrabr->status != XCB_GRAB_STATUS_SUCCESS) { xcb_discard_reply(conn, pgrabc.sequence); xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); } else { pgrabr = xcb_grab_pointer_reply(conn, pgrabc, NULL); if (!pgrabr || pgrabr->status != XCB_GRAB_STATUS_SUCCESS) { xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME); } else { grabbed_screen = scrpriv->mynum; hostx_set_win_title (screen, "(ctrl+shift releases mouse and keyboard)"); } } } } if (!ephyrKbd || !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) { return; } /* Still send the release event even if above has happened server * will get confused with just an up event. Maybe it would be * better to just block shift+ctrls getting to kdrive all * together. */ ephyrUpdateModifierState(key->state); KdEnqueueKeyboardEvent(ephyrKbd, key->detail, TRUE); }
/* * Repeatedly tries to grab pointer and keyboard (up to 1000 times). * */ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) { xcb_grab_pointer_cookie_t pcookie; xcb_grab_pointer_reply_t *preply; xcb_grab_keyboard_cookie_t kcookie; xcb_grab_keyboard_reply_t *kreply; // do we need it? //xcb_void_cookie_t bcookie; int tries = 10000; while (tries-- > 0) { pcookie = xcb_grab_pointer( conn, true, /* get all pointer events specified by the following mask */ screen->root, /* grab the root window */ XCB_NONE, /* 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 */ cursor, /* we change the cursor to whatever the user wanted */ XCB_CURRENT_TIME); if ((preply = xcb_grab_pointer_reply(conn, pcookie, NULL)) && preply->status == XCB_GRAB_STATUS_SUCCESS) { free(preply); break; } /* Make this quite a bit slower */ usleep(50); } while (tries-- > 0) { kcookie = xcb_grab_keyboard( conn, true, /* report events */ screen->root, /* grab the root window */ XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ XCB_GRAB_MODE_ASYNC); if ((kreply = xcb_grab_keyboard_reply(conn, kcookie, NULL)) && kreply->status == XCB_GRAB_STATUS_SUCCESS) { free(kreply); break; } /* Make this quite a bit slower */ usleep(50); } /* bcookie = xcb_grab_button( conn, true, // report events screen->root, // grab the root window XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_SYNC, // process events as normal, do not require sync XCB_GRAB_MODE_ASYNC, screen->root, // confine_to XCB_NONE, XCB_BUTTON_INDEX_ANY, XCB_MOD_MASK_ANY); // cursor */ if (tries <= 0) errx(EXIT_FAILURE, "Cannot grab pointer/keyboard"); }
static void events_loop(void) { xcb_generic_event_t *ev; #ifdef ENABLE_MOUSE uint32_t values[3]; xcb_get_geometry_reply_t *geom; xcb_window_t win = 0; #endif /* loop */ for (;;) { ev = xcb_wait_for_event(conn); if (!ev) errx(1, "xcb connection broken"); switch (CLEANMASK(ev->response_type)) { case XCB_CREATE_NOTIFY: { xcb_create_notify_event_t *e; e = (xcb_create_notify_event_t *)ev; if (!e->override_redirect) { subscribe(e->window); focus(e->window, ACTIVE); } } break; case XCB_DESTROY_NOTIFY: { xcb_destroy_notify_event_t *e; e = (xcb_destroy_notify_event_t *)ev; xcb_kill_client(conn, e->window); } break; #ifdef ENABLE_SLOPPY case XCB_ENTER_NOTIFY: { xcb_enter_notify_event_t *e; e = (xcb_enter_notify_event_t *)ev; focus(e->event, ACTIVE); } break; #endif case XCB_MAP_NOTIFY: { xcb_map_notify_event_t *e; e = (xcb_map_notify_event_t *)ev; if (!e->override_redirect) { xcb_map_window(conn, e->window); focus(e->window, ACTIVE); } } break; #ifdef ENABLE_MOUSE case XCB_BUTTON_PRESS: { xcb_button_press_event_t *e; e = ( xcb_button_press_event_t *)ev; win = e->child; if (!win || win == scr->root) break; values[0] = XCB_STACK_MODE_ABOVE; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values); geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); if (e->detail == 1) { values[2] = 1; xcb_warp_pointer(conn, XCB_NONE, win, 0, 0, 0, 0, geom->width/2, geom->height/2); } else { values[2] = 3; xcb_warp_pointer(conn, XCB_NONE, win, 0, 0, 0, 0, geom->width, geom->height); } xcb_grab_pointer(conn, 0, scr->root, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, XCB_CURRENT_TIME); xcb_flush(conn); } break; case XCB_MOTION_NOTIFY: { xcb_query_pointer_reply_t *pointer; pointer = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, scr->root), 0); if (values[2] == 1) { geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); if (!geom) break; values[0] = (pointer->root_x + geom->width / 2 > scr->width_in_pixels - (BORDERWIDTH*2)) ? scr->width_in_pixels - geom->width - (BORDERWIDTH*2) : pointer->root_x - geom->width / 2; values[1] = (pointer->root_y + geom->height / 2 > scr->height_in_pixels - (BORDERWIDTH*2)) ? (scr->height_in_pixels - geom->height - (BORDERWIDTH*2)) : pointer->root_y - geom->height / 2; if (pointer->root_x < geom->width/2) values[0] = 0; if (pointer->root_y < geom->height/2) values[1] = 0; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); xcb_flush(conn); } else if (values[2] == 3) { geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); values[0] = pointer->root_x - geom->x; values[1] = pointer->root_y - geom->y; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); xcb_flush(conn); } } break; case XCB_BUTTON_RELEASE: focus(win, ACTIVE); xcb_ungrab_pointer(conn, XCB_CURRENT_TIME); break; #endif case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t *e; e = (xcb_configure_notify_event_t *)ev; if (e->window != focuswin) focus(e->window, INACTIVE); focus(focuswin, ACTIVE); } break; } xcb_flush(conn); free(ev); } }