static xcb_translate_coordinates_reply_t * translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int x, int y) { xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(c->xcb_connection(), from, to, x, y); return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0); }
void Window::translate_coords(xcb_window_t target, int32_t& x, int32_t& y) { xcb_translate_coordinates_cookie_t c = xcb_translate_coordinates(conn->xcb(), window, target, x, y); xcb_generic_error_t* error; xcb_translate_coordinates_reply_t* reply = xcb_translate_coordinates_reply(conn->xcb(), c, &error); throw_if_error(error); x = reply->dst_x; y = reply->dst_y; free(reply); }
/** * Converts a Weston compositor x,y coordinate into a global screen coordinate. * When Weston is using the x11 backend, the x,y coordinate is mapped to the X * display output (needed to correctly map a uinput pointer to weston). **/ static void toScreen(int32_t *x, int32_t *y) { struct weston_output *output(Globals::output()); toDevice(x, y); std::string make(output->make); if (make == "xwayland" or make == "weston-X11") { #if defined(HAVE_X11_SUPPORT) struct x11_compositor *x11_compositor = (struct x11_compositor*)Globals::compositor(); struct x11_output *x11_output = (struct x11_output*) output; xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply( x11_compositor->conn, xcb_get_geometry( x11_compositor->conn, x11_output->window ), NULL ); xcb_translate_coordinates_reply_t *trans = xcb_translate_coordinates_reply( x11_compositor->conn, xcb_translate_coordinates( x11_compositor->conn, x11_output->window, geom->root, -(geom->border_width), -(geom->border_width) ), NULL ); *x += (int16_t)trans->dst_x; *y += (int16_t)trans->dst_y; delete trans; delete geom; #else exit(EXIT_FAILURE); #endif } }
// === WindowGeometry() === QRect LXCB::WindowGeometry(WId win, bool includeFrame){ if(DEBUG){ qDebug() << "XCB: WindowGeometry()"; } QRect geom; if(win==0){ return geom; } xcb_get_geometry_cookie_t cookie = xcb_get_geometry(QX11Info::connection(), win); xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(QX11Info::connection(), cookie, NULL); //qDebug() << "Get Window Geometry:" << reply; if(reply != 0){ geom = QRect(0, 0, reply->width, reply->height); //make sure to use the origin point for the window //qDebug() << " - "<<reply->x << reply->y << reply->width << reply->height; free(reply); if(includeFrame){ //Need to add/include the frame extents as well (assuming the frame info is available) xcb_get_property_cookie_t cookie = xcb_ewmh_get_frame_extents_unchecked(&EWMH, win); if(cookie.sequence != 0){ xcb_ewmh_get_extents_reply_t frame; if(1== xcb_ewmh_get_frame_extents_reply(&EWMH, cookie, &frame, NULL) ){ //adjust the origin point to account for the frame geom.translate(-frame.left, -frame.top); //move to the orign point for the frame //adjust the size (include the frame sizes) geom.setWidth( geom.width() + frame.left + frame.right ); geom.setHeight( geom.height() + frame.top + frame.bottom ); } //qDebug() << " - Frame:" << frame.left << frame.right << frame.top << frame.bottom; //qDebug() << " - Modified with Frame:" << geom.x() << geom.y() << geom.width() << geom.height(); } } //Now need to convert this to absolute coordinates (not parent-relavitve) xcb_translate_coordinates_cookie_t tcookie = xcb_translate_coordinates(QX11Info::connection(), win, QX11Info::appRootWindow(), geom.x(), geom.y()); xcb_translate_coordinates_reply_t *trans = xcb_translate_coordinates_reply(QX11Info::connection(), tcookie, NULL); if(trans!=0){ //qDebug() << " - Got Translation:" << trans->dst_x << trans->dst_y; //Replace the origin point with the global position (sizing remains the same) geom.moveLeft(trans->dst_x); //adjust X coordinate (no size change) geom.moveTop(trans->dst_y); //adjust Y coordinate (no size change) free(trans); } }else{ //Need to do another catch for this situation (probably not mapped yet) } return geom; }
bool LinuxWindowCapture::WindowRect() { if( mWindow == 0 ) return false; xcb_connection_t* dpy = xcb_connect( NULL, NULL ); if ( xcb_connection_has_error( dpy ) ) qDebug() << "Can't open display"; xcb_screen_t* screen = xcb_setup_roots_iterator( xcb_get_setup( dpy ) ).data; if( !screen ) qDebug() << "Can't acquire screen"; xcb_get_geometry_cookie_t geometryC = xcb_get_geometry( dpy, mWindow ); xcb_get_geometry_reply_t* geometryR = xcb_get_geometry_reply( dpy, geometryC, NULL ); if( geometryR ) { xcb_translate_coordinates_cookie_t translateC = xcb_translate_coordinates( dpy, mWindow, screen->root, geometryR->x, geometryR->y ); xcb_translate_coordinates_reply_t* translateR = xcb_translate_coordinates_reply( dpy, translateC, NULL ); mRect.setRect( translateR->dst_x, translateR->dst_y, geometryR->width, geometryR->height ); free( geometryR ); free( translateR ); xcb_disconnect( dpy ); return true; } xcb_disconnect( dpy ); return false; }
bool LinuxWindowCapture::ExtractWindowProperties( xcb_window_t winId, QRect* winRect, bool* winFocus ) { if( !winId ) return false; xcb_connection_t* xcbConn = QX11Info::connection(); xcb_get_geometry_cookie_t geometryC = xcb_get_geometry( xcbConn, winId ); CScopedPointer< xcb_get_geometry_reply_t > geometryR( xcb_get_geometry_reply( xcbConn, geometryC, nullptr ) ); if( !geometryR ) return false; // assume the parent window is the screen then we can just use the coordinates directly int x = geometryR->x; int y = geometryR->y; CScopedPointer< xcb_query_tree_reply_t > treeR( xcb_query_tree_reply( xcbConn, xcb_query_tree( xcbConn, winId ), nullptr ) ); if ( !treeR ) return false; // if the parent isn't screen translate coords if ( treeR->parent != QX11Info::appRootWindow() ) { xcb_translate_coordinates_cookie_t translateC = xcb_translate_coordinates( xcbConn, winId, QX11Info::appRootWindow(), x, y ); CScopedPointer< xcb_translate_coordinates_reply_t > translateR( xcb_translate_coordinates_reply( xcbConn, translateC, nullptr ) ); if ( !translateR ) return false; x = translateR->dst_x; y = translateR->dst_y; } winRect->setRect( x, y, geometryR->width, geometryR->height ); xcb_get_input_focus_cookie_t focusC = xcb_get_input_focus( xcbConn ); CScopedPointer < xcb_get_input_focus_reply_t > focusR( xcb_get_input_focus_reply( xcbConn, focusC, nullptr ) ); if ( !focusR ) return false; *winFocus = ( focusR->focus == winId ); return true; }
static gboolean _eventd_nd_xcb_randr_check_focused(EventdNdBackendContext *self, EventdNdXcbRandrOutput *output) { gint x, y; switch ( self->follow_focus ) { case EVENTD_ND_XCB_FOLLOW_FOCUS_MOUSE: { xcb_query_pointer_cookie_t c; xcb_query_pointer_reply_t *r; c = xcb_query_pointer(self->xcb_connection, self->screen->root); r = xcb_query_pointer_reply(self->xcb_connection, c, NULL); if ( r == NULL ) return FALSE; x = r->root_x; y = r->root_y; free(r); } break; case EVENTD_ND_XCB_FOLLOW_FOCUS_KEYBOARD: { xcb_get_property_cookie_t wc; xcb_get_property_reply_t *wr; wc = xcb_get_property(self->xcb_connection, FALSE, self->screen->root, self->ewmh._NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 0, sizeof(xcb_window_t)); wr = xcb_get_property_reply(self->xcb_connection, wc, NULL); if ( wr == NULL ) return FALSE; xcb_window_t w; w = *((xcb_window_t *) xcb_get_property_value(wr)); free(wr); xcb_translate_coordinates_cookie_t cc; xcb_translate_coordinates_reply_t *cr; cc = xcb_translate_coordinates(self->xcb_connection, w, self->screen->root, 0, 0); cr = xcb_translate_coordinates_reply(self->xcb_connection, cc, NULL); if ( cr == NULL ) return FALSE; x = cr->dst_x; y = cr->dst_y; free(cr); } break; default: g_return_val_if_reached(FALSE); } for ( ; output->output != NULL ; ++output ) { if ( ! ( ( x >= output->crtc->x && x <= ( output->crtc->x + output->crtc->width ) ) && ( y >= output->crtc->y && y <= ( output->crtc->y + output->crtc->height ) ) ) ) continue; self->geometry.x = output->crtc->x; self->geometry.y = output->crtc->y; self->geometry.w = output->crtc->width; self->geometry.h = output->crtc->height; return TRUE; } return FALSE; }
void krad_x11_enable_capture (krad_x11_t *x11, uint32_t window_id) { xcb_get_geometry_reply_t *geo; xcb_query_tree_reply_t *tree; xcb_translate_coordinates_cookie_t translateCookie; xcb_translate_coordinates_reply_t *trans; geo = xcb_get_geometry_reply (x11->connection, xcb_get_geometry (x11->connection, window_id), NULL); if (geo == NULL) { window_id = 0; } else { tree = xcb_query_tree_reply (x11->connection, xcb_query_tree (x11->connection, window_id), NULL); if (tree == NULL) { window_id = 0; free (geo); } else { translateCookie = xcb_translate_coordinates (x11->connection, window_id, x11->screen->root, geo->x, geo->y); trans = xcb_translate_coordinates_reply (x11->connection, translateCookie, NULL); if (trans == NULL) { window_id = 0; free (tree); free (geo); } else { x11->width = geo->width; x11->height = geo->height; x11->x = trans->dst_x - geo->x; x11->y = trans->dst_y - geo->y; free (trans); free (tree); free (geo); } } } if (window_id == 0) { x11->width = x11->screen_width; x11->height = x11->screen_height; x11->window = x11->screen->root; } //printf ("capture width %d height %d x %d y %d\n", // x11->width, x11->height, x11->x, x11->y); x11->img = xcb_image_create_native (x11->connection, x11->width, x11->height, XCB_IMAGE_FORMAT_Z_PIXMAP, x11->screen_bit_depth, 0, ~0, 0); if (!x11->img) { exit (15); } x11->stride = x11->img->stride; x11->shminfo.shmid = shmget (IPC_PRIVATE, x11->img->stride * x11->img->height, (IPC_CREAT | 0666)); if (x11->shminfo.shmid == (uint32_t)-1) { xcb_image_destroy (x11->img); failfast ("shminfo fail"); } x11->shminfo.shmaddr = shmat (x11->shminfo.shmid, 0, 0); x11->img->data = x11->shminfo.shmaddr; if (x11->img->data == (uint8_t *)-1) { xcb_image_destroy (x11->img); failfast ("xcb image fail"); } x11->shminfo.shmseg = xcb_generate_id (x11->connection); xcb_shm_attach (x11->connection, x11->shminfo.shmseg, x11->shminfo.shmid, 0); x11->capture_enabled = 1; }
//_____________________________________________ void SizeGrip::sendMoveResizeEvent( QPoint position ) { #if OXYGEN_HAVE_X11 if( !QX11Info::isPlatformX11() ) return; // pointer to connection auto connection( QX11Info::connection() ); // client auto c = m_decoration.data()->client().data(); /* get root position matching position need to use xcb because the embedding of the widget breaks QT's mapToGlobal and other methods */ QPoint rootPosition( position ); xcb_get_geometry_cookie_t cookie( xcb_get_geometry( connection, winId() ) ); ScopedPointer<xcb_get_geometry_reply_t> reply( xcb_get_geometry_reply( connection, cookie, 0x0 ) ); if( reply ) { // translate coordinates xcb_translate_coordinates_cookie_t coordCookie( xcb_translate_coordinates( connection, winId(), reply.data()->root, -reply.data()->border_width, -reply.data()->border_width ) ); ScopedPointer< xcb_translate_coordinates_reply_t> coordReply( xcb_translate_coordinates_reply( connection, coordCookie, 0x0 ) ); if( coordReply ) { rootPosition.rx() += coordReply.data()->dst_x; rootPosition.ry() += coordReply.data()->dst_y; } } // move/resize atom if( !m_moveResizeAtom ) { // create atom if not found const QString atomName( "_NET_WM_MOVERESIZE" ); xcb_intern_atom_cookie_t cookie( xcb_intern_atom( connection, false, atomName.size(), qPrintable( atomName ) ) ); ScopedPointer<xcb_intern_atom_reply_t> reply( xcb_intern_atom_reply( connection, cookie, 0x0 ) ); m_moveResizeAtom = reply ? reply->atom:0; } if( !m_moveResizeAtom ) return; // button release event xcb_button_release_event_t releaseEvent; memset(&releaseEvent, 0, sizeof(releaseEvent)); releaseEvent.response_type = XCB_BUTTON_RELEASE; releaseEvent.event = winId(); releaseEvent.child = XCB_WINDOW_NONE; releaseEvent.root = QX11Info::appRootWindow(); releaseEvent.event_x = position.x(); releaseEvent.event_y = position.y(); releaseEvent.root_x = rootPosition.x(); releaseEvent.root_y = rootPosition.y(); releaseEvent.detail = XCB_BUTTON_INDEX_1; releaseEvent.state = XCB_BUTTON_MASK_1; releaseEvent.time = XCB_CURRENT_TIME; releaseEvent.same_screen = true; xcb_send_event( connection, false, winId(), XCB_EVENT_MASK_BUTTON_RELEASE, reinterpret_cast<const char*>(&releaseEvent)); xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME ); // move resize event xcb_client_message_event_t clientMessageEvent; memset(&clientMessageEvent, 0, sizeof(clientMessageEvent)); clientMessageEvent.response_type = XCB_CLIENT_MESSAGE; clientMessageEvent.type = m_moveResizeAtom; clientMessageEvent.format = 32; clientMessageEvent.window = c->windowId(); clientMessageEvent.data.data32[0] = rootPosition.x(); clientMessageEvent.data.data32[1] = rootPosition.y(); clientMessageEvent.data.data32[2] = 4; // bottom right clientMessageEvent.data.data32[3] = Qt::LeftButton; clientMessageEvent.data.data32[4] = 0; xcb_send_event( connection, false, QX11Info::appRootWindow(), XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, reinterpret_cast<const char*>(&clientMessageEvent) ); xcb_flush( connection ); #endif }
/** * Processing callback */ static void Demux (void *data) { demux_t *demux = data; demux_sys_t *p_sys = demux->p_sys; xcb_connection_t *conn = p_sys->conn; /* Update capture region (if needed) */ xcb_get_geometry_cookie_t gc = xcb_get_geometry (conn, p_sys->window); int16_t x = p_sys->x, y = p_sys->y; xcb_translate_coordinates_cookie_t tc; if (p_sys->window != p_sys->root) tc = xcb_translate_coordinates (conn, p_sys->window, p_sys->root, x, y); xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL); if (geo == NULL) { msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, p_sys->window); return; } uint16_t w = geo->width - x; uint16_t h = geo->height - y; free (geo); if (p_sys->w > 0 && p_sys->w < w) w = p_sys->w; if (p_sys->h > 0 && p_sys->h < h) h = p_sys->h; if (p_sys->window != p_sys->root) { xcb_translate_coordinates_reply_t *coords = xcb_translate_coordinates_reply (conn, tc, NULL); if (coords == NULL) return; x = coords->dst_x; y = coords->dst_y; free (coords); } xcb_get_image_reply_t *img; img = xcb_get_image_reply (conn, xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, p_sys->root, x, y, w, h, ~0), NULL); if (img == NULL) return; /* Send block - zero copy */ block_t *block = block_heap_Alloc (img, xcb_get_image_data (img), xcb_get_image_data_length (img)); if (block == NULL) return; vlc_mutex_lock (&p_sys->lock); if (w != p_sys->fmt.video.i_visible_width || h != p_sys->fmt.video.i_visible_height) { if (p_sys->es != NULL) es_out_Del (demux->out, p_sys->es); p_sys->fmt.video.i_visible_width = p_sys->fmt.video.i_width = w; p_sys->fmt.video.i_visible_height = p_sys->fmt.video.i_height = h; p_sys->es = es_out_Add (demux->out, &p_sys->fmt); } /* Capture screen */ if (p_sys->es != NULL) { if (p_sys->pts == VLC_TS_INVALID) p_sys->pts = mdate (); block->i_pts = block->i_dts = p_sys->pts; es_out_Control (demux->out, ES_OUT_SET_PCR, p_sys->pts); es_out_Send (demux->out, p_sys->es, block); p_sys->pts += p_sys->interval; } vlc_mutex_unlock (&p_sys->lock); }
// determine which monitor holds the active window, or failing that the mouse pointer void monitor_active ( workarea *mon ) { xcb_window_t root = xcb->screen->root; int x, y; if ( config.monitor >= 0 ) { if ( monitor_get_dimension ( config.monitor, mon ) ) { return; } fprintf ( stderr, "Failed to find selected monitor.\n" ); } if ( config.monitor == -3 ) { if ( pointer_get ( root, &x, &y ) ) { monitor_dimensions ( x, y, mon ); mon->x = x; mon->y = y; return; } } // Get the current desktop. unsigned int current_desktop = 0; if ( config.monitor == -1 && xcb_ewmh_get_current_desktop_reply ( &xcb->ewmh, xcb_ewmh_get_current_desktop ( &xcb->ewmh, xcb->screen_nbr ), ¤t_desktop, NULL ) ) { xcb_get_property_cookie_t c = xcb_ewmh_get_desktop_viewport ( &xcb->ewmh, xcb->screen_nbr ); xcb_ewmh_get_desktop_viewport_reply_t vp; if ( xcb_ewmh_get_desktop_viewport_reply ( &xcb->ewmh, c, &vp, NULL ) ) { if ( current_desktop < vp.desktop_viewport_len ) { monitor_dimensions ( vp.desktop_viewport[current_desktop].x, vp.desktop_viewport[current_desktop].y, mon ); xcb_ewmh_get_desktop_viewport_reply_wipe ( &vp ); return; } xcb_ewmh_get_desktop_viewport_reply_wipe ( &vp ); } } xcb_window_t active_window; if ( xcb_ewmh_get_active_window_reply ( &xcb->ewmh, xcb_ewmh_get_active_window ( &xcb->ewmh, xcb->screen_nbr ), &active_window, NULL ) ) { // get geometry. xcb_get_geometry_cookie_t c = xcb_get_geometry ( xcb->connection, active_window ); xcb_get_geometry_reply_t *r = xcb_get_geometry_reply ( xcb->connection, c, NULL ); if ( r ) { xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates ( xcb->connection, active_window, root, r->x, r->y ); xcb_translate_coordinates_reply_t *t = xcb_translate_coordinates_reply ( xcb->connection, ct, NULL ); if ( t ) { if ( config.monitor == -2 ) { // place the menu above the window // if some window is focused, place menu above window, else fall // back to selected monitor. mon->x = t->dst_x - r->x; mon->y = t->dst_y - r->y; mon->w = r->width; mon->h = r->height; mon->t = r->border_width; mon->b = r->border_width; mon->l = r->border_width; mon->r = r->border_width; free ( r ); free ( t ); return; } else if ( config.monitor == -4 ){ monitor_dimensions ( t->dst_x, t->dst_y, mon ); free(r); free(t); return; } } free ( r ); } } if ( pointer_get ( root, &x, &y ) ) { monitor_dimensions ( x, y, mon ); return; } monitor_dimensions ( 0, 0, mon ); }
static xcb_rectangle_t get_window_position(void) { xcb_rectangle_t result = (xcb_rectangle_t){logical_px(50), logical_px(50), MAX_WIDTH, font.height + 2 * BORDER + 2 * PADDING}; xcb_get_property_reply_t *supporting_wm_reply = NULL; xcb_get_input_focus_reply_t *input_focus = NULL; xcb_get_geometry_reply_t *geometry = NULL; xcb_get_property_reply_t *wm_class = NULL; xcb_translate_coordinates_reply_t *coordinates = NULL; xcb_atom_t A__NET_SUPPORTING_WM_CHECK; xcb_intern_atom_cookie_t nswc_cookie = xcb_intern_atom(conn, 0, strlen("_NET_SUPPORTING_WM_CHECK"), "_NET_SUPPORTING_WM_CHECK"); xcb_intern_atom_reply_t *nswc_reply = xcb_intern_atom_reply(conn, nswc_cookie, NULL); if (nswc_reply == NULL) { ELOG("Could not intern atom _NET_SUPPORTING_WM_CHECK\n"); exit(-1); } A__NET_SUPPORTING_WM_CHECK = nswc_reply->atom; free(nswc_reply); supporting_wm_reply = xcb_get_property_reply( conn, xcb_get_property(conn, false, root, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 0, 32), NULL); xcb_window_t *supporting_wm_win = NULL; if (supporting_wm_reply == NULL || xcb_get_property_value_length(supporting_wm_reply) == 0) { DLOG("Could not determine EWMH support window.\n"); } else { supporting_wm_win = xcb_get_property_value(supporting_wm_reply); } /* In rare cases, the window holding the input focus might disappear while we are figuring out its * position. To avoid this, we grab the server in the meantime. */ xcb_grab_server(conn); input_focus = xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL); if (input_focus == NULL || input_focus->focus == XCB_NONE) { DLOG("Failed to receive the current input focus or no window has the input focus right now.\n"); goto free_resources; } /* We need to ignore the EWMH support window to which the focus can be set if there's no suitable window to focus. */ if (supporting_wm_win != NULL && input_focus->focus == *supporting_wm_win) { DLOG("Input focus is on the EWMH support window, ignoring.\n"); goto free_resources; } geometry = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, input_focus->focus), NULL); if (geometry == NULL) { DLOG("Failed to received window geometry.\n"); goto free_resources; } wm_class = xcb_get_property_reply( conn, xcb_get_property(conn, false, input_focus->focus, XCB_ATOM_WM_CLASS, XCB_GET_PROPERTY_TYPE_ANY, 0, 32), NULL); /* We need to find out whether the input focus is on an i3 frame window. If it is, we must not translate the coordinates. */ if (wm_class == NULL || xcb_get_property_value_length(wm_class) == 0 || strcmp(xcb_get_property_value(wm_class), "i3-frame") != 0) { coordinates = xcb_translate_coordinates_reply( conn, xcb_translate_coordinates(conn, input_focus->focus, root, geometry->x, geometry->y), NULL); if (coordinates == NULL) { DLOG("Failed to translate coordinates.\n"); goto free_resources; } DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", coordinates->dst_x, coordinates->dst_y); result.x += coordinates->dst_x; result.y += coordinates->dst_y; } else { DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", geometry->x, geometry->y); result.x += geometry->x; result.y += geometry->y; } free_resources: xcb_ungrab_server(conn); xcb_flush(conn); FREE(supporting_wm_reply); FREE(input_focus); FREE(geometry); FREE(wm_class); FREE(coordinates); return result; }