void KSnapshot::grabPointerImage(int offsetx, int offsety) // Uses the X11_EXTENSIONS_XFIXES_H extension to grab the pointer image, and overlays it onto the snapshot. { #ifdef HAVE_X11_EXTENSIONS_XFIXES_H XFixesCursorImage *xcursorimg = XFixesGetCursorImage( QX11Info::display() ); if ( !xcursorimg ) return; //Annoyingly, xfixes specifies the data to be 32bit, but places it in an unsigned long * //which can be 64 bit. So we need to iterate over a 64bit structure to put it in a 32bit //structure. QVarLengthArray< quint32 > pixels( xcursorimg->width * xcursorimg->height ); for (int i = 0; i < xcursorimg->width * xcursorimg->height; ++i) pixels[i] = xcursorimg->pixels[i] & 0xffffffff; QImage qcursorimg((uchar *) pixels.data(), xcursorimg->width, xcursorimg->height, QImage::Format_ARGB32_Premultiplied); QPainter painter(&snapshot); painter.drawImage(QPointF(xcursorimg->x - xcursorimg->xhot - offsetx, xcursorimg->y - xcursorimg ->yhot - offsety), qcursorimg); XFree(xcursorimg); #else // HAVE_X11_EXTENSIONS_XFIXES_H Q_UNUSED(offsetx); Q_UNUSED(offsety); return; #endif // HAVE_X11_EXTENSIONS_XFIXES_H }
static void xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor) { XFixesCursorImage *cursor_image; CoglHandle sprite = COGL_INVALID_HANDLE; if (!xfixes_cursor->have_xfixes) return; cursor_image = XFixesGetCursorImage (clutter_x11_get_default_display ()); sprite = cogl_texture_new_from_data (cursor_image->width, cursor_image->height, COGL_TEXTURE_NONE, #if G_BYTE_ORDER == G_LITTLE_ENDIAN COGL_PIXEL_FORMAT_BGRA_8888_PRE, #else COGL_PIXEL_FORMAT_ARGB_8888_PRE, #endif COGL_PIXEL_FORMAT_ANY, cursor_image->width * 4, /* stride */ (const guint8 *) cursor_image->pixels); if (sprite != COGL_INVALID_HANDLE) { if (xfixes_cursor->cursor_sprite != NULL) cogl_handle_unref (xfixes_cursor->cursor_sprite); xfixes_cursor->cursor_sprite = sprite; xfixes_cursor->cursor_hot_x = cursor_image->xhot; xfixes_cursor->cursor_hot_y = cursor_image->yhot; g_signal_emit (xfixes_cursor, signals[CURSOR_CHANGED], 0); } }
static void byzanz_layer_cursor_read_cursor (ByzanzLayerCursor *clayer) { Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_window_get_display (BYZANZ_LAYER (clayer)->recorder->window)); clayer->cursor_next = XFixesGetCursorImage (dpy); if (clayer->cursor_next) g_hash_table_insert (clayer->cursors, clayer->cursor_next, clayer->cursor_next); }
/** * Paint a mouse pointer in an X11 image. * * @param image image to paint the mouse pointer to * @param s context used to retrieve original grabbing rectangle * coordinates */ static void paint_mouse_pointer(XImage *image, X11GrabContext *s) { int x_off = s->x_off; int y_off = s->y_off; int width = s->width; int height = s->height; Display *dpy = s->dpy; XFixesCursorImage *xcim; int x, y; int line, column; int to_line, to_column; int pixstride = image->bits_per_pixel >> 3; /* Warning: in its insanity, xlib provides unsigned image data through a * char* pointer, so we have to make it uint8_t to make things not break. * Anyone who performs further investigation of the xlib API likely risks * permanent brain damage. */ uint8_t *pix = image->data; /* Code doesn't currently support 16-bit or PAL8 */ if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32) return; xcim = XFixesGetCursorImage(dpy); if (!xcim) return; x = xcim->x - xcim->xhot; y = xcim->y - xcim->yhot; to_line = FFMIN((y + xcim->height), (height + y_off)); to_column = FFMIN((x + xcim->width), (width + x_off)); for (line = FFMAX(y, y_off); line < to_line; line++) { for (column = FFMAX(x, x_off); column < to_column; column++) { int xcim_addr = (line - y) * xcim->width + column - x; int image_addr = ((line - y_off) * width + column - x_off) * pixstride; int r = (uint8_t)(xcim->pixels[xcim_addr] >> 0); int g = (uint8_t)(xcim->pixels[xcim_addr] >> 8); int b = (uint8_t)(xcim->pixels[xcim_addr] >> 16); int a = (uint8_t)(xcim->pixels[xcim_addr] >> 24); if (a == 255) { pix[image_addr + 0] = r; pix[image_addr + 1] = g; pix[image_addr + 2] = b; } else if (a) { /* pixel values from XFixesGetCursorImage come premultiplied by alpha */ pix[image_addr + 0] = r + (pix[image_addr + 0] * (255 - a) + 255 / 2) / 255; pix[image_addr + 1] = g + (pix[image_addr + 1] * (255 - a) + 255 / 2) / 255; pix[image_addr + 2] = b + (pix[image_addr + 2] * (255 - a) + 255 / 2) / 255; } } } XFree(xcim); xcim = NULL; }
void xcursor_tick(xcursor_t *data) { XFixesCursorImage *xc = XFixesGetCursorImage(data->dpy); if (!data->tex || data->last_serial != xc->cursor_serial) xcursor_create(data, xc); data->pos_x = -1.0 * (xc->x - xc->xhot - data->x_org); data->pos_y = -1.0 * (xc->y - xc->yhot - data->y_org); XFree(xc); }
static void tc_x11source_acquire_cursor_fixes(TCX11Source *handle, uint8_t *data, int maxdata) { XFixesCursorImage *cursor = XFixesGetCursorImage(handle->dpy); if (cursor == NULL) { /* this MUST be noisy! */ tc_log_warn(__FILE__, "failed to get cursor image"); } else { /* FIXME: this has to be rewritten and need significant * internal refactoring :( */ } }
void xcursor_tick(xcursor_t *data) { XFixesCursorImage *xc = XFixesGetCursorImage(data->dpy); if (!data->tex || data->last_serial != xc->cursor_serial) xcursor_create(data, xc); data->x = (int_fast32_t)xc->x - (int_fast32_t)data->x_org; data->y = (int_fast32_t)xc->y - (int_fast32_t)data->y_org; data->render_x = xc->x - xc->xhot - data->x_org; data->render_y = xc->y - xc->yhot - data->y_org; XFree(xc); }
int main(int argc, char** argv) { if (argc != 2 || !argv[1][0] || !argv[1][1]) { fprintf(stderr, "Usage: %s chrootdisplay\n", argv[0]); return 2; } /* Make sure the displays aren't equal */ char *cros_n = XDisplayName(NULL); if (cros_n[1] == argv[1][1]) { fprintf(stderr, "You must specify a different display.\n"); return 2; } /* Open the displays */ Display *cros_d, *chroot_d; Window cros_w, chroot_w; if (!(cros_d = XOpenDisplay(NULL))) { fprintf(stderr, "Failed to open Chromium OS display\n"); return 1; } if (!(chroot_d = XOpenDisplay(argv[1]))) { fprintf(stderr, "Failed to open chroot display %s\n", argv[1]); return 1; } /* Get the XFixes extension for the chroot to monitor the cursor */ int xfixes_event, xfixes_error; if (!XFixesQueryExtension(chroot_d, &xfixes_event, &xfixes_error)) { fprintf(stderr, "chroot is missing XFixes extension\n"); return 1; } XSetErrorHandler(error_handler); /* Get the root windows */ cros_w = DefaultRootWindow(cros_d); chroot_w = DefaultRootWindow(chroot_d); /* Monitor the chroot root window for cursor changes */ XFixesSelectCursorInput(chroot_d, chroot_w, XFixesDisplayCursorNotifyMask); XEvent e; while (!error) { XNextEvent(chroot_d, &e); if (error) break; if (e.type != xfixes_event + XFixesCursorNotify) continue; /* Grab the new cursor and apply it to the Chromium OS X11 server */ XFixesCursorImage *img = XFixesGetCursorImage(chroot_d); apply_cursor(cros_d, cros_w, img); XFree(img); } /* Clean up */ apply_cursor(cros_d, cros_w, NULL); XCloseDisplay(cros_d); XCloseDisplay(chroot_d); return 0; }
Utilities::Point GetCursorPos() { auto display = XOpenDisplay(NULL); auto root = DefaultRootWindow(display); auto img = XFixesGetCursorImage(display); // Get the mouse cursor position int x, y, root_x, root_y = 0; unsigned int mask = 0; Window child_win, root_win; XQueryPointer(display, root, &child_win, &root_win, &root_x, &root_y, &x, &y, &mask); x -= img->xhot; y -= img->yhot; XFree(img); XCloseDisplay(display); return Utilities::Point(x, y); }
std::shared_ptr<Utilities::Image> CaptureMouseImage() { auto display = XOpenDisplay(NULL); auto img = XFixesGetCursorImage(display); if (sizeof(img->pixels[0]) == 8) { auto pixels = (int *)img->pixels; for (auto i = 0; i < img->width * img->height; ++i) { pixels[i] = pixels[i * 2]; } } auto i = Utilities::Image::CreateImage(img->height, img->width, (char*)img->pixels, 4); XFree(img); XCloseDisplay(display); return i; }
void MouseCursor::update() { #ifdef Q_OS_LINUX XFixesCursorImage *img = XFixesGetCursorImage(QX11Info::display()); // realloc enough buffer size_ = QSize(img->width, img->height); int pixels = size_.width() * size_.height(); if(pixels > reserved_) { delete pixmap_data_; reserved_ = pixels; pixmap_data_ = new uint32_t[reserved_]; } /* copy Data removing redundant bits if needed * Note: sizeof(unsigned long) is 8 bytes in 64bit unix, * but only bottom 4 bytes are used. (00000000AARRGGBB) * So we have to remove top 4 bytes. */ unsigned long *data = img->pixels; for(int i = 0; i < pixels; ++i) { pixmap_data_[i] = data[i]; } // calc mouse pos pos_ = QCursor::pos(); pos_ -= QPoint(img->xhot, img->yhot); free(img); #else return; // TODO: write Platform dependent code for other than X11 // such as MS_Windows and Mac_OSX #endif }
void updateCursor (CompCursor *c, int x, int y, unsigned long serial) { /* new current cursor */ if (!c->image || c->image->serial != serial) { CompCursorImage *cursorImage; cursorImage = findCursorImageAtScreen (c->screen, serial); if (!cursorImage) { Display *dpy = c->screen->display->display; XFixesCursorImage *image; image = XFixesGetCursorImage (dpy); if (!image) return; cursorImage = malloc (sizeof (CompCursorImage)); if (!cursorImage) { XFree (image); return; } x = image->x; y = image->y; cursorImage->serial = image->cursor_serial; cursorImage->xhot = image->xhot; cursorImage->yhot = image->yhot; cursorImage->width = image->width; cursorImage->height = image->height; initTexture (c->screen, &cursorImage->texture); if (!imageBufferToTexture (c->screen, &cursorImage->texture, (char *) image->pixels, image->width, image->height)) { free (cursorImage); XFree (image); return; } XFree (image); cursorImage->next = c->screen->cursorImages; c->screen->cursorImages = cursorImage; } if (c->image) addCursorDamage (c); c->image = cursorImage; c->x = x - c->image->xhot; c->y = y - c->image->yhot; setCursorMatrix (c); addCursorDamage (c); } else { int newX, newY; newX = x - c->image->xhot; newY = y - c->image->yhot; if (c->x != newX || c->y != newY) { addCursorDamage (c); c->x = newX; c->y = newY; setCursorMatrix (c); addCursorDamage (c); } } }
int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) { int x, y, n, k; rdpShadowServer* server; rdpShadowSurface* surface; server = subsystem->server; surface = server->surface; if (getImage) { #ifdef WITH_XFIXES UINT32* pDstPixel; XFixesCursorImage* ci; XLockDisplay(subsystem->display); ci = XFixesGetCursorImage(subsystem->display); XUnlockDisplay(subsystem->display); if (!ci) return -1; x = ci->x; y = ci->y; if (ci->width > subsystem->cursorMaxWidth) return -1; if (ci->height > subsystem->cursorMaxHeight) return -1; subsystem->cursorHotX = ci->xhot; subsystem->cursorHotY = ci->yhot; subsystem->cursorWidth = ci->width; subsystem->cursorHeight = ci->height; subsystem->cursorId = ci->cursor_serial; n = ci->width * ci->height; pDstPixel = (UINT32*) subsystem->cursorPixels; for (k = 0; k < n; k++) { /* XFixesCursorImage.pixels is in *unsigned long*, which may be 8 bytes */ *pDstPixel++ = (UINT32) ci->pixels[k]; } XFree(ci); x11_shadow_pointer_alpha_update(subsystem); #endif } else { UINT32 mask; int win_x, win_y; int root_x, root_y; Window root, child; XLockDisplay(subsystem->display); if (!XQueryPointer(subsystem->display, subsystem->root_window, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) { XUnlockDisplay(subsystem->display); return -1; } XUnlockDisplay(subsystem->display); x = root_x; y = root_y; } /* Convert to offset based on current surface */ if (surface) { x -= surface->x; y -= surface->y; } if ((x != subsystem->pointerX) || (y != subsystem->pointerY)) { subsystem->pointerX = x; subsystem->pointerY = y; x11_shadow_pointer_position_update(subsystem); } return 1; }
static void xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor) { XFixesCursorImage *cursor_image; CoglHandle sprite = COGL_INVALID_HANDLE; guint8 *cursor_data; gboolean free_cursor_data; if (!xfixes_cursor->have_xfixes) return; cursor_image = XFixesGetCursorImage (clutter_x11_get_default_display ()); if (!cursor_image) return; /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit * quantities as arrays of long; we need to convert on 64 bit */ if (sizeof(long) == 4) { cursor_data = (guint8 *)cursor_image->pixels; free_cursor_data = FALSE; } else { int i, j; guint32 *cursor_words; gulong *p; guint32 *q; cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); cursor_data = (guint8 *)cursor_words; p = cursor_image->pixels; q = cursor_words; for (j = 0; j < cursor_image->height; j++) for (i = 0; i < cursor_image->width; i++) *(q++) = *(p++); free_cursor_data = TRUE; } sprite = cogl_texture_new_from_data (cursor_image->width, cursor_image->height, COGL_TEXTURE_NONE, CLUTTER_CAIRO_FORMAT_ARGB32, COGL_PIXEL_FORMAT_ANY, cursor_image->width * 4, /* stride */ cursor_data); if (free_cursor_data) g_free (cursor_data); if (sprite != COGL_INVALID_HANDLE) { if (xfixes_cursor->cursor_sprite != NULL) cogl_handle_unref (xfixes_cursor->cursor_sprite); xfixes_cursor->cursor_sprite = sprite; xfixes_cursor->cursor_hot_x = cursor_image->xhot; xfixes_cursor->cursor_hot_y = cursor_image->yhot; g_signal_emit (xfixes_cursor, signals[CURSOR_CHANGED], 0); } XFree (cursor_image); }
/* Finds NaCl/Chromium shm memory using external handler. * Reply must be in the form PID:file */ struct cache_entry* find_shm(uint64_t paddr, uint64_t sig, size_t length) { struct cache_entry* entry = NULL; /* Find entry in cache */ if (cache[0].paddr == paddr) { entry = &cache[0]; } else if (cache[1].paddr == paddr) { entry = &cache[1]; } else { /* Not found: erase an existing entry. */ entry = &cache[next_entry]; next_entry = (next_entry + 1) % 2; close_mmap(entry); } int try; for (try = 0; try < 2; try++) { /* Check signature */ if (entry->map) { if (*((uint64_t*)entry->map) == sig) return entry; log(1, "Invalid signature, fetching new shm!"); close_mmap(entry); } /* Setup parameters and run command */ char arg1[32], arg2[32]; int c; c = snprintf(arg1, sizeof(arg1), "%08lx", (long)paddr & 0xffffffff); trueorabort(c > 0, "snprintf"); int i, p = 0; for (i = 0; i < 8; i++) { c = snprintf(arg2 + p, sizeof(arg2) - p, "%02x", ((uint8_t*)&sig)[i]); trueorabort(c > 0, "snprintf"); p += c; } char* cmd = "croutonfindnacl"; char* args[] = {cmd, arg1, arg2, NULL}; char buffer[256]; log(2, "Running %s %s %s", cmd, arg1, arg2); c = popen2(cmd, args, NULL, 0, buffer, sizeof(buffer)); if (c <= 0) { error("Error running helper."); return NULL; } buffer[c < sizeof(buffer) ? c : (sizeof(buffer)-1)] = 0; log(2, "Result: %s", buffer); /* Parse PID:file output */ char* cut = strchr(buffer, ':'); if (!cut) { error("No ':' in helper reply: %s.", cut); return NULL; } *cut = 0; char* endptr; long pid = strtol(buffer, &endptr, 10); if(buffer == endptr || *endptr != '\0') { error("Invalid pid: %s", buffer); return NULL; } char* file = cut+1; log(2, "PID:%ld, FILE:%s", pid, file); entry->paddr = paddr; entry->fd = open(file, O_RDWR); if (entry->fd < 0) { error("Cannot open file %s\n", file); return NULL; } entry->length = length; entry->map = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, entry->fd, 0); if (!entry->map) { error("Cannot mmap %s\n", file); close(entry->fd); return NULL; } log(2, "mmap ok %p %zu %d", entry->map, entry->length, entry->fd); } error("Cannot find shm."); return NULL; } /* WebSocket functions */ XImage* img = NULL; XShmSegmentInfo shminfo; /* Writes framebuffer image to websocket/shm */ int write_image(const struct screen* screen) { char reply_raw[FRAMEMAXHEADERSIZE + sizeof(struct screen_reply)]; struct screen_reply* reply = (struct screen_reply*)(reply_raw + FRAMEMAXHEADERSIZE); int refresh = 0; memset(reply_raw, 0, sizeof(reply_raw)); reply->type = 'S'; reply->width = screen->width; reply->height = screen->height; /* Allocate XShmImage */ if (!img || img->width != screen->width || img->height != screen->height) { if (img) { XDestroyImage(img); shmdt(shminfo.shmaddr); shmctl(shminfo.shmid, IPC_RMID, 0); } /* FIXME: Some error checking should happen here... */ img = XShmCreateImage(dpy, DefaultVisual(dpy, 0), 24, ZPixmap, NULL, &shminfo, screen->width, screen->height); trueorabort(img, "XShmCreateImage"); shminfo.shmid = shmget(IPC_PRIVATE, img->bytes_per_line*img->height, IPC_CREAT|0777); trueorabort(shminfo.shmid != -1, "shmget"); shminfo.shmaddr = img->data = shmat(shminfo.shmid, 0, 0); trueorabort(shminfo.shmaddr != (void*)-1, "shmat"); shminfo.readOnly = False; int ret = XShmAttach(dpy, &shminfo); trueorabort(ret, "XShmAttach"); /* Force refresh */ refresh = 1; } if (screen->refresh) { log(1, "Force refresh from client."); /* refresh forced by the client */ refresh = 1; } XEvent ev; /* Register damage on new windows */ while (XCheckTypedEvent(dpy, MapNotify, &ev)) { register_damage(dpy, ev.xcreatewindow.window); refresh = 1; } /* Check for damage */ while (XCheckTypedEvent(dpy, damageEvent + XDamageNotify, &ev)) { refresh = 1; } /* Check for cursor events */ reply->cursor_updated = 0; while (XCheckTypedEvent(dpy, fixesEvent + XFixesCursorNotify, &ev)) { XFixesCursorNotifyEvent* curev = (XFixesCursorNotifyEvent*)&ev; if (verbose >= 2) { char* name = XGetAtomName(dpy, curev->cursor_name); log(2, "cursor! %ld %s", curev->cursor_serial, name); XFree(name); } reply->cursor_updated = 1; reply->cursor_serial = curev->cursor_serial; } /* No update */ if (!refresh) { reply->shm = 0; reply->updated = 0; socket_client_write_frame(reply_raw, sizeof(*reply), WS_OPCODE_BINARY, 1); return 0; } /* Get new image from framebuffer */ XShmGetImage(dpy, DefaultRootWindow(dpy), img, 0, 0, AllPlanes); int size = img->bytes_per_line * img->height; trueorabort(size == screen->width*screen->height*4, "Invalid screen byte count"); trueorabort(screen->shm, "Non-SHM rendering is not supported"); struct cache_entry* entry = find_shm(screen->paddr, screen->sig, size); reply->shm = 1; reply->updated = 1; reply->shmfailed = 0; if (entry && entry->map) { if (size == entry->length) { memcpy(entry->map, img->data, size); msync(entry->map, size, MS_SYNC); } else { /* This should never happen (it means the client passed an * outdated buffer to us). */ error("Invalid shm entry length (client bug!)."); reply->shmfailed = 1; } } else { /* Keep the flow going, even if we cannot find the shm. Next time * the NaCl client reallocates the buffer, we are likely to be able * to find it. */ error("Cannot find shm, moving on..."); reply->shmfailed = 1; } /* Confirm write is done */ socket_client_write_frame(reply_raw, sizeof(*reply), WS_OPCODE_BINARY, 1); return 0; } /* Writes cursor image to websocket */ int write_cursor() { XFixesCursorImage *img = XFixesGetCursorImage(dpy); if (!img) { error("XFixesGetCursorImage returned NULL"); return -1; } int size = img->width*img->height; const int replylength = sizeof(struct cursor_reply) + size*sizeof(uint32_t); char reply_raw[FRAMEMAXHEADERSIZE + replylength]; struct cursor_reply* reply = (struct cursor_reply*)(reply_raw + FRAMEMAXHEADERSIZE); memset(reply_raw, 0, sizeof(*reply_raw)); reply->type = 'P'; reply->width = img->width; reply->height = img->height; reply->xhot = img->xhot; reply->yhot = img->yhot; reply->cursor_serial = img->cursor_serial; /* This casts long[] to uint32_t[] */ int i; for (i = 0; i < size; i++) reply->pixels[i] = img->pixels[i]; socket_client_write_frame(reply_raw, replylength, WS_OPCODE_BINARY, 1); XFree(img); return 0; }
static void ensure_xfixes_cursor (MetaCursorTracker *tracker) { MetaDisplay *display = meta_get_display (); XFixesCursorImage *cursor_image; CoglTexture2D *sprite; guint8 *cursor_data; gboolean free_cursor_data; CoglContext *ctx; CoglError *error = NULL; if (tracker->xfixes_cursor) return; cursor_image = XFixesGetCursorImage (display->xdisplay); if (!cursor_image) return; /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit * quantities as arrays of long; we need to convert on 64 bit */ if (sizeof(long) == 4) { cursor_data = (guint8 *)cursor_image->pixels; free_cursor_data = FALSE; } else { int i, j; guint32 *cursor_words; gulong *p; guint32 *q; cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); cursor_data = (guint8 *)cursor_words; p = cursor_image->pixels; q = cursor_words; for (j = 0; j < cursor_image->height; j++) for (i = 0; i < cursor_image->width; i++) *(q++) = *(p++); free_cursor_data = TRUE; } ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); sprite = cogl_texture_2d_new_from_data (ctx, cursor_image->width, cursor_image->height, CLUTTER_CAIRO_FORMAT_ARGB32, cursor_image->width * 4, /* stride */ cursor_data, &error); if (free_cursor_data) g_free (cursor_data); if (error != NULL) { meta_warning ("Failed to allocate cursor sprite texture: %s\n", error->message); cogl_error_free (error); } if (sprite != NULL) { MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new (); meta_cursor_sprite_set_texture (cursor_sprite, sprite, cursor_image->xhot, cursor_image->yhot); cogl_object_unref (sprite); tracker->xfixes_cursor = cursor_sprite; } XFree (cursor_image); }
static void ensure_xfixes_cursor (MetaCursorTracker *tracker) { XFixesCursorImage *cursor_image; CoglTexture2D *sprite; guint8 *cursor_data; gboolean free_cursor_data; CoglContext *ctx; if (tracker->sprite) return; cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay); if (!cursor_image) return; /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit * quantities as arrays of long; we need to convert on 64 bit */ if (sizeof(long) == 4) { cursor_data = (guint8 *)cursor_image->pixels; free_cursor_data = FALSE; } else { int i, j; guint32 *cursor_words; gulong *p; guint32 *q; cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); cursor_data = (guint8 *)cursor_words; p = cursor_image->pixels; q = cursor_words; for (j = 0; j < cursor_image->height; j++) for (i = 0; i < cursor_image->width; i++) *(q++) = *(p++); free_cursor_data = TRUE; } ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); sprite = cogl_texture_2d_new_from_data (ctx, cursor_image->width, cursor_image->height, CLUTTER_CAIRO_FORMAT_ARGB32, cursor_image->width * 4, /* stride */ cursor_data, NULL); if (free_cursor_data) g_free (cursor_data); if (sprite != NULL) { tracker->sprite = sprite; tracker->hot_x = cursor_image->xhot; tracker->hot_y = cursor_image->yhot; } XFree (cursor_image); }
int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) { int x, y, n, k; rdpShadowServer* server; rdpShadowSurface* surface; server = subsystem->server; surface = server->surface; if (getImage) { #ifdef WITH_XFIXES UINT32* pDstPixel; XFixesCursorImage* ci; ci = XFixesGetCursorImage(subsystem->display); x = ci->x; y = ci->y; if (ci->width > subsystem->cursorMaxWidth) return -1; if (ci->height > subsystem->cursorMaxHeight) return -1; subsystem->cursorHotX = ci->xhot; subsystem->cursorHotY = ci->yhot; subsystem->cursorWidth = ci->width; subsystem->cursorHeight = ci->height; subsystem->cursorId = ci->cursor_serial; n = ci->width * ci->height; pDstPixel = (UINT32*) subsystem->cursorPixels; for (k = 0; k < n; k++) { /* XFixesCursorImage.pixels is in *unsigned long*, which may be 8 bytes */ *pDstPixel++ = (UINT32) ci->pixels[k]; } XFree(ci); #endif } else { UINT32 mask; int win_x, win_y; int root_x, root_y; Window root, child; if (!XQueryPointer(subsystem->display, subsystem->root_window, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) { return -1; } x = root_x; y = root_y; } subsystem->cursorX = x; subsystem->cursorY = y; return 1; }