void X11WindowedBackend::grabKeyboard(xcb_timestamp_t time) { const bool oldState = m_keyboardGrabbed; if (m_keyboardGrabbed) { xcb_ungrab_keyboard(m_connection, time); xcb_ungrab_pointer(m_connection, time); m_keyboardGrabbed = false; } else { const auto c = xcb_grab_keyboard_unchecked(m_connection, false, window(), time, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); ScopedCPointer<xcb_grab_keyboard_reply_t> grab(xcb_grab_keyboard_reply(m_connection, c, nullptr)); if (grab.isNull()) { return; } if (grab->status == XCB_GRAB_STATUS_SUCCESS) { const auto c = xcb_grab_pointer_unchecked(m_connection, false, window(), XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, window(), XCB_CURSOR_NONE, time); ScopedCPointer<xcb_grab_pointer_reply_t> grab(xcb_grab_pointer_reply(m_connection, c, nullptr)); if (grab.isNull() || grab->status != XCB_GRAB_STATUS_SUCCESS) { xcb_ungrab_keyboard(m_connection, time); return; } m_keyboardGrabbed = true; } } if (oldState != m_keyboardGrabbed) { updateWindowTitle(); xcb_flush(m_connection); } }
/** Grab the mouse. * \param cursor The cursor to use while grabbing. * \return True if mouse was grabbed. */ static bool mousegrabber_grab(xcb_cursor_t cursor) { xcb_window_t root = globalconf.screen->root; for(int i = 1000; i; i--) { xcb_grab_pointer_reply_t *grab_ptr_r; xcb_grab_pointer_cookie_t grab_ptr_c = xcb_grab_pointer_unchecked(globalconf.connection, false, root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, cursor, XCB_CURRENT_TIME); if((grab_ptr_r = xcb_grab_pointer_reply(globalconf.connection, grab_ptr_c, NULL))) { p_delete(&grab_ptr_r); return true; } usleep(1000); } return false; }
void WindowSelector::start(std::function<void(KWin::Toplevel*)> callback, const QByteArray &cursorName) { xcb_cursor_t cursor = createCursor(cursorName); if (m_active) { callback(nullptr); return; } xcb_connection_t *c = connection(); ScopedCPointer<xcb_grab_pointer_reply_t> grabPointer(xcb_grab_pointer_reply(c, xcb_grab_pointer_unchecked(c, false, rootWindow(), XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE, cursor, XCB_TIME_CURRENT_TIME), NULL)); if (grabPointer.isNull() || grabPointer->status != XCB_GRAB_STATUS_SUCCESS) { callback(nullptr); return; } m_active = grabXKeyboard(); if (!m_active) { xcb_ungrab_pointer(connection(), XCB_TIME_CURRENT_TIME); callback(nullptr); return; } grabXServer(); m_callback = callback; }
/* * 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; int tries = 10000; 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); } 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); } if (tries <= 0) errx(EXIT_FAILURE, "Cannot grab pointer/keyboard"); }
bool grab_pointer(pointer_action_t pac) { xcb_window_t win = XCB_NONE; xcb_point_t pos; query_pointer(&win, &pos); coordinates_t loc; if (!locate_window(win, &loc)) { if (pac == ACTION_FOCUS) { monitor_t *m = monitor_from_point(pos); if (m != NULL && m != mon && (win == XCB_NONE || win == m->root)) { focus_node(m, m->desk, m->desk->focus); return true; } } return false; } if (pac == ACTION_FOCUS) { if (loc.node != mon->desk->focus) { focus_node(loc.monitor, loc.desktop, loc.node); return true; } else if (focus_follows_pointer) { stack(loc.desktop, loc.node, true); } return false; } if (loc.node->client->state == STATE_FULLSCREEN) { return true; } xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(dpy, xcb_grab_pointer(dpy, 0, root, XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME), NULL); if (reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) { free(reply); return true; } free(reply); if (pac == ACTION_MOVE) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X move begin\n", loc.monitor->id, loc.desktop->id, loc.node->id); } else if (pac == ACTION_RESIZE_CORNER) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_corner begin\n", loc.monitor->id, loc.desktop->id, loc.node->id); } else if (pac == ACTION_RESIZE_SIDE) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_side begin\n", loc.monitor->id, loc.desktop->id, loc.node->id); } track_pointer(loc, pac, pos); return true; }
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); } }
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; }
/** Grab the mouse. * \param cursor The cursor to use while grabbing. * \return True if mouse was grabbed. */ static bool mousegrabber_grab(xcb_cursor_t cursor) { xcb_window_t root = XCB_NONE; for(int screen = 0; screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); screen++) { int16_t x, y; uint16_t mask; root = xutil_screen_get(globalconf.connection, screen)->root; if(mouse_query_pointer(root, &x, &y, NULL, &mask)) break; } for(int i = 1000; i; i--) { xcb_grab_pointer_reply_t *grab_ptr_r; xcb_grab_pointer_cookie_t grab_ptr_c = xcb_grab_pointer_unchecked(globalconf.connection, false, root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, cursor, XCB_CURRENT_TIME); if((grab_ptr_r = xcb_grab_pointer_reply(globalconf.connection, grab_ptr_c, NULL))) { p_delete(&grab_ptr_r); return true; } usleep(1000); } return false; }
static void towel_window_grab_input(towel_window_t *win) { xcb_grab_pointer_cookie_t pointer_cookie; xcb_grab_keyboard_cookie_t keyboard_cookie; xcb_grab_pointer_reply_t *pointer_reply; xcb_grab_keyboard_reply_t *keyboard_reply; pointer_cookie = xcb_grab_pointer_unchecked(win->conn, 0, win->id, XCB_EVENT_MASK_NO_EVENT, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, win->id, XCB_CURSOR_NONE, XCB_TIME_CURRENT_TIME); keyboard_cookie = xcb_grab_keyboard_unchecked(win->conn, 0, win->id, XCB_TIME_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); pointer_reply = xcb_grab_pointer_reply(win->conn, pointer_cookie, NULL); keyboard_reply = xcb_grab_keyboard_reply(win->conn, keyboard_cookie, NULL); #if DEBUG fprintf(stderr, "p: %d, k: %d\n", pointer_reply->status, keyboard_reply->status); #endif free(pointer_reply); free(keyboard_reply); }
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 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); }
int main(int argc,char**argv){ xcb_connection_t*d=xcb_connect(0,0); int32_t*x,*y,*tx=0,mx,my,rt=xcb_setup_roots_iterator(xcb_get_setup(d)).data->root,cs[255],*cz=cs+1; uint8_t mz,mZ; xcb_change_window_attributes(d,rt,XCB_CW_EVENT_MASK,&cwa); xcb_grab_key(d,1,rt,0,64,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC); xcb_grab_key(d,1,rt,8,XCB_GRAB_ANY,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC); xcb_grab_button(d,1,rt,XCB_EVENT_MASK_BUTTON_PRESS,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC,XCB_NONE,XCB_NONE,XCB_GRAB_ANY,8); #ifdef COMPOSITE xcb_composite_redirect_subwindows(d,rt,XCB_COMPOSITE_REDIRECT_AUTOMATIC); #endif xcb_generic_event_t*e=0; main:xcb_flush(d); waitpid(-1,0,WNOHANG); noflush:x=y=cz-1; again:free(e); switch((e=xcb_wait_for_event(d))->response_type&127){ case XCB_BUTTON_PRESS: for(;x>cs;x--) if(*x==((xcb_button_press_event_t*)e)->child){ if(((xcb_key_press_event_t*)e)->detail==2)goto pocus; case XCB_KEY_PRESS: mz=128|((xcb_key_press_event_t*)e)->detail; my=((xcb_key_press_event_t*)e)->state; goto*(cz==cs+1?&&kcode:&&stack); } goto noflush; case XCB_KEY_RELEASE: if(((xcb_key_press_event_t*)e)->detail!=64||!tx)default:goto again; xt:x=tx; tx=0; goto stack; case XCB_CONFIGURE_REQUEST:{ void*p=buf; for(mz=0;mz<5;mz++) if(((xcb_configure_request_event_t*)e)->value_mask&1<<mz){*(uint32_t*)p=*(int16_t*)(((void*)e)+16+mz*2);p+=4;} if(((xcb_configure_request_event_t*)e)->value_mask&XCB_CONFIG_WINDOW_SIBLING){*(uint32_t*)p=((xcb_configure_request_event_t*)e)->sibling;p+=4;} if(mz=((xcb_configure_request_event_t*)e)->value_mask&XCB_CONFIG_WINDOW_STACK_MODE)*(uint32_t*)p=((xcb_configure_request_event_t*)e)->stack_mode; xcb_configure_window(d,((xcb_configure_request_event_t*)e)->window,((xcb_configure_request_event_t*)e)->value_mask,buf); if(mz){ p=xcb_query_tree_reply(d,xcb_query_tree_unchecked(d,rt),0); int32_t*cl=p+32+((xcb_query_tree_reply_t*)p)->children_len*4; for(y=p+32;y<cl;y++){ for(x=cs+1;x<cz;x++) if(*x==*y)goto nono; *y=0; nono:; } x=cs; for(y=p+32;y<cl;y++) if(*y)*++x=*y; free(p); goto pocus; }else goto main;} case XCB_MAP_REQUEST:{ void*p=xcb_get_window_attributes_reply(d,xcb_get_window_attributes_unchecked(d,((xcb_map_request_event_t*)e)->window),0); if(((xcb_get_window_attributes_reply_t*)p)->override_redirect){ free(p); goto pocus; } free(p); for(;x>cs;x--) if(*x==((xcb_map_request_event_t*)e)->window)goto noflush; xcb_map_window(d,*cz++=((xcb_map_request_event_t*)e)->window); goto hocus;} case XCB_MOTION_NOTIFY: *buf=mZ&&((xcb_motion_notify_event_t*)e)->root_x<=mx?:((xcb_motion_notify_event_t*)e)->root_x-mx; buf[1]=mZ&&((xcb_motion_notify_event_t*)e)->root_y<=my?:((xcb_motion_notify_event_t*)e)->root_y-my; xcb_configure_window(d,*x,mZ?XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT:XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y,buf); goto main; case XCB_BUTTON_RELEASE: xcb_ungrab_pointer(d,XCB_CURRENT_TIME); goto main; case XCB_UNMAP_NOTIFY:unmap:goto*(x==cs?&&noflush:*x==((xcb_unmap_notify_event_t*)e)->window&&--cz>cs+1?&&stack:(x--,&&unmap)); } stack:mx=*x; for(;x!=y;x+=x<y?:-1)*x=x[x<y?:-1]; *x=mx; hocus:x=cz-1; xcb_configure_window(d,*x,XCB_CONFIG_WINDOW_STACK_MODE,di); pocus:xcb_set_input_focus(d,XCB_INPUT_FOCUS_POINTER_ROOT,*x,XCB_CURRENT_TIME); if(!(mz&128))goto main; kcode:switch(mz&=127){ void*p; case 1:case 3: p=xcb_grab_pointer_reply(d,xcb_grab_pointer_unchecked(d,0,rt,XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_POINTER_MOTION,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC,XCB_NONE,XCB_NONE,XCB_CURRENT_TIME),0); if(((xcb_grab_pointer_reply_t*)p)->status!=XCB_GRAB_STATUS_SUCCESS){ free(p); goto noflush; } free(p); p=xcb_get_geometry_reply(d,xcb_get_geometry_unchecked(d,*y),0); mx=((xcb_get_geometry_reply_t*)p)->x; my=((xcb_get_geometry_reply_t*)p)->y; free(p); if(mZ=mz==1){ p=xcb_query_pointer_reply(d,xcb_query_pointer_unchecked(d,rt),0); mx=((xcb_query_pointer_reply_t*)p)->root_x-mx; my=((xcb_query_pointer_reply_t*)p)->root_y-my; free(p); } goto noflush; case 23:case 49: if(cz-cs<3)goto main; y=tx; tx=mz==23?(y!=cs+1?(y?:x)-1:x):!y||y==x?cs+1:y+1; if(y&&y<cz-1){ *buf=y[mz==23?:-1]; buf[1]=mz==23; xcb_configure_window(d,*y,XCB_CONFIG_WINDOW_SIBLING|XCB_CONFIG_WINDOW_STACK_MODE,buf); } xcb_configure_window(d,*tx,XCB_CONFIG_WINDOW_STACK_MODE,di); goto main; case 32:return 0; case 44: if(cz>cs+1)xcb_configure_window(d,*y,XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y|XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT,di); goto main; case 46: if(cz==cs+1)goto main; if(tx)goto*(mz|=128,&&xt); {xcb_intern_atom_cookie_t c1=xcb_intern_atom_unchecked(d,0,12,"WM_PROTOCOLS"),c2=xcb_intern_atom_unchecked(d,0,16,"WM_DELETE_WINDOW"); p=xcb_intern_atom_reply(d,c1,0); mx=((xcb_intern_atom_reply_t*)p)->atom; free(p); p=xcb_intern_atom_reply(d,c2,0);} my=((xcb_intern_atom_reply_t*)p)->atom; free(p); p=xcb_get_property_reply(d,xcb_get_property_unchecked(d,0,*y,mx,XCB_ATOM_ATOM,0,-1),0); xcb_send_event(d,0,*y,XCB_EVENT_MASK_NO_EVENT,(void*)(xcb_client_message_event_t[]){{.response_type=XCB_CLIENT_MESSAGE,.window=*y,.type=mx,.format=32,.data.data32={my,XCB_CURRENT_TIME}}});