void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo) { // Open a connection with the X server xcb_connection_t* connection = OpenConnection(); WindowHandle handle = relativeTo.getSystemHandle(); if (handle) { ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check( connection, xcb_warp_pointer( connection, None, // Source window handle, // Destination window 0, 0, // Source position 0, 0, // Source size position.x, position.y // Destination position ) )); if (error) err() << "Failed to set mouse position" << std::endl; xcb_flush(connection); } // Close the connection with the X server CloseConnection(connection); }
void QXcbCursor::setPos(const QPoint &pos) { QXcbVirtualDesktop *virtualDesktop = Q_NULLPTR; queryPointer(connection(), &virtualDesktop, 0); xcb_warp_pointer(xcb_connection(), XCB_NONE, virtualDesktop->root(), 0, 0, 0, 0, pos.x(), pos.y()); xcb_flush(xcb_connection()); }
void QXcbCursor::setPos(const QPoint &pos) { xcb_window_t root = 0; queryPointer(connection(), &root, 0); xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x(), pos.y()); xcb_flush(xcb_connection()); }
void InputImpl::setMousePosition(const Vector2i& position) { // Open a connection with the X server xcb_connection_t* connection = OpenConnection(); ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check( connection, xcb_warp_pointer( connection, None, // Source window XCBDefaultRootWindow(connection), // Destination window 0, 0, // Source position 0, 0, // Source size position.x, position.y // Destination position ) )); if (error) err() << "Failed to set mouse position" << std::endl; xcb_flush(connection); // Close the connection with the X server CloseConnection(connection); }
static void resize(xcb_window_t w, int x, int y) { uint32_t val[3]; uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_STACK_MODE; xcb_get_geometry_cookie_t c; xcb_get_geometry_reply_t *r; c = xcb_get_geometry(conn, w); r = xcb_get_geometry_reply(conn, c, NULL); if (r == NULL) return; if ((r->x + r->width + 2*r->border_width + x) > scr->width_in_pixels) x = scr->width_in_pixels - ( r->x + r->width + (2*r->border_width)); if ((r->y + r->height + 2*r->border_width + y) > scr->height_in_pixels) y = scr->height_in_pixels - ( r->y + r->height + (2*r->border_width)); val[0] = r->width + x; val[1] = r->height + y; val[2] = XCB_STACK_MODE_ABOVE; xcb_configure_window(conn, w, mask, val); xcb_warp_pointer(conn, XCB_NONE, w, 0, 0, 0, 0, r->width + x, r->height + y); free(r); }
void center_pointer(xcb_rectangle_t r) { int16_t cx = r.x + r.width / 2; int16_t cy = r.y + r.height / 2; window_lower(motion_recorder); xcb_warp_pointer(dpy, XCB_NONE, root, 0, 0, 0, 0, cx, cy); window_raise(motion_recorder); }
void QXcbCursor::setPos(const QPoint &pos) { const int dpr = int(m_screen->devicePixelRatio()); xcb_window_t root = 0; queryPointer(connection(), &root, 0); xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x()*dpr, pos.y()*dpr); xcb_flush(xcb_connection()); }
void QXcbCursor::setPos(const QPoint &pos) { const QPoint xPos = m_screen->mapToNative(pos); xcb_window_t root = 0; queryPointer(connection(), &root, 0); xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, xPos.x(), xPos.y()); xcb_flush(xcb_connection()); }
ExcCode screen_cursor_set_position(int x, int y) { xcb_void_cookie_t cookie = xcb_warp_pointer(display, XCB_NONE, root, 0, 0, 0, 0, x, y); if (xcb_request_check(display, cookie) != NULL) PANIC(ERR_X_REQUEST, "screen_cursor_set_position (xcb_request_check)"); if (xcb_flush(display) <= 0) PANIC(ERR_X_REQUEST, "screen_cursor_set_position (xcb_flush)"); return 0; }
void center_pointer(xcb_rectangle_t r) { if (grabbing) { return; } int16_t cx = r.x + r.width / 2; int16_t cy = r.y + r.height / 2; xcb_warp_pointer(dpy, XCB_NONE, root, 0, 0, 0, 0, cx, cy); }
static void center_pointer (xcb_window_t win) { uint32_t values[1]; xcb_get_geometry_reply_t *geom; geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); xcb_warp_pointer(conn, XCB_NONE, win, 0, 0, 0, 0, (geom->width + (BORDERWIDTH * 2)) / 2, (geom->height + (BORDERWIDTH * 2)) / 2); values[0] = XCB_STACK_MODE_ABOVE; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values); }
/** 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 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); } }
/** Set the pointer position. * \param window The destination window. * \param x X-coordinate inside window. * \param y Y-coordinate inside window. */ static inline void mouse_warp_pointer(xcb_window_t window, int x, int y) { xcb_warp_pointer(globalconf.connection, XCB_NONE, window, 0, 0, 0, 0, x, y); }
int main(int argc, char *argv[]) { /* * variables */ char c; int i, screen_num; xcb_connection_t *connection; xcb_screen_t *next_screen; xcb_screen_t *current_screen; xcb_screen_iterator_t iterator; xcb_query_pointer_reply_t *pointer; /* * handle the arguments */ while (-1 != (c = getopt_long(argc, argv, "hv", long_options, NULL))) { switch (c) { case 'h': usage(argv); return 0; case 'v': printf("GPL %s: %s\n" "Copyright (C) 2011 Joško Nikolić\n", PROGRAM_NAME, PROGRAM_VERSION); return 0; default: usage(argv); break; } } /* * open the connection */ connection = xcb_connect(NULL, &screen_num); if (xcb_connection_has_error(connection)) { puts("ERROR: couldn't open display"); exit(EXIT_FAILURE); } const xcb_setup_t *setup = xcb_get_setup(connection); iterator = xcb_setup_roots_iterator(setup); /* * find the current screen */ for (i = 0; i < screen_num; ++i) xcb_screen_next(&iterator); current_screen = iterator.data; /* * get the next screen to switch to */ xcb_screen_next(&iterator); /* * if the next screen doesn't exist move the iterator to start */ if (0 == (iterator.data)->width_in_pixels && 0 == (iterator.data)->height_in_pixels) { iterator = xcb_setup_roots_iterator(setup); } next_screen = iterator.data; /* * get pointer information */ pointer = xcb_query_pointer_reply(connection, xcb_query_pointer_unchecked(connection, current_screen->root), NULL); if (NULL != pointer) { /* * warp the pointer and focus the new screen */ xcb_warp_pointer(connection, XCB_NONE, next_screen->root, 0, 0, 0, 0, pointer->win_x, pointer->win_y); xcb_set_input_focus(connection, XCB_INPUT_FOCUS_PARENT, next_screen->root, XCB_CURRENT_TIME); xcb_flush(connection); free(pointer); } else puts("ERROR: couldn't query pointer"); xcb_disconnect(connection); return EXIT_SUCCESS; }
int resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event) { DLOG("resize handler\n"); /* TODO: previously, we were getting a rect containing all screens. why? */ Con *output = con_get_output(first); DLOG("x = %d, width = %d\n", output->rect.x, output->rect.width); x_mask_event_mask(~XCB_EVENT_MASK_ENTER_WINDOW); xcb_flush(conn); uint32_t mask = 0; uint32_t values[2]; mask = XCB_CW_OVERRIDE_REDIRECT; values[0] = 1; /* Open a new window, the resizebar. Grab the pointer and move the window around as the user moves the pointer. */ xcb_window_t grabwin = create_window(conn, output->rect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT, XCB_WINDOW_CLASS_INPUT_ONLY, XCURSOR_CURSOR_POINTER, true, mask, values); /* Keep track of the coordinate orthogonal to motion so we can determine * the length of the resize afterward. */ uint32_t initial_position, new_position; /* Configure the resizebar and snap the pointer. The resizebar runs along * the rect of the second con and follows the motion of the pointer. */ Rect helprect; if (orientation == HORIZ) { helprect.x = second->rect.x; helprect.y = second->rect.y; helprect.width = logical_px(2); helprect.height = second->rect.height; initial_position = second->rect.x; xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0, second->rect.x, event->root_y); } else { helprect.x = second->rect.x; helprect.y = second->rect.y; helprect.width = second->rect.width; helprect.height = logical_px(2); initial_position = second->rect.y; xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0, event->root_x, second->rect.y); } mask = XCB_CW_BACK_PIXEL; values[0] = config.client.focused.border; mask |= XCB_CW_OVERRIDE_REDIRECT; values[1] = 1; xcb_window_t helpwin = create_window(conn, helprect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT, XCB_WINDOW_CLASS_INPUT_OUTPUT, (orientation == HORIZ ? XCURSOR_CURSOR_RESIZE_HORIZONTAL : XCURSOR_CURSOR_RESIZE_VERTICAL), true, mask, values); xcb_circulate_window(conn, XCB_CIRCULATE_RAISE_LOWEST, helpwin); xcb_flush(conn); /* `new_position' will be updated by the `resize_callback'. */ new_position = initial_position; const struct callback_params params = {orientation, output, helpwin, &new_position}; /* `drag_pointer' blocks until the drag is completed. */ drag_result_t drag_result = drag_pointer(NULL, event, grabwin, BORDER_TOP, 0, resize_callback, ¶ms); xcb_destroy_window(conn, helpwin); xcb_destroy_window(conn, grabwin); xcb_flush(conn); /* User cancelled the drag so no action should be taken. */ if (drag_result == DRAG_REVERT) return 0; int pixels = (new_position - initial_position); DLOG("Done, pixels = %d\n", pixels); // if we got thus far, the containers must have // percentages associated with them assert(first->percent > 0.0); assert(second->percent > 0.0); // calculate the new percentage for the first container double new_percent, difference; double percent = first->percent; DLOG("percent = %f\n", percent); int original = (orientation == HORIZ ? first->rect.width : first->rect.height); DLOG("original = %d\n", original); new_percent = (original + pixels) * (percent / original); difference = percent - new_percent; DLOG("difference = %f\n", difference); DLOG("new percent = %f\n", new_percent); first->percent = new_percent; // calculate the new percentage for the second container double s_percent = second->percent; second->percent = s_percent + difference; DLOG("second->percent = %f\n", second->percent); // now we must make sure that the sum of the percentages remain 1.0 con_fix_percent(first->parent); return 0; }
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); } }
void X11WindowedBackend::warpPointer(const QPointF &globalPos) { const xcb_window_t w = m_windows.at(0).window; xcb_warp_pointer(m_connection, w, w, 0, 0, 0, 0, globalPos.x(), globalPos.y()); xcb_flush(m_connection); }