mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 13:52:57 +00:00
xcb: added basic cursor support via xcb_fixes
xcb interface now properly supports cursor integration through a `pointerThread` similar to the nvfbc implementation.
This commit is contained in:
parent
fbf294efd9
commit
8ab130deba
1 changed files with 123 additions and 8 deletions
|
@ -23,9 +23,11 @@
|
|||
#include "common/option.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/event.h"
|
||||
#include "common/thread.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <xcb/xfixes.h>
|
||||
#include <sys/ipc.h>
|
||||
|
@ -33,18 +35,24 @@
|
|||
|
||||
struct xcb
|
||||
{
|
||||
bool initialized;
|
||||
bool stop;
|
||||
xcb_connection_t * xcb;
|
||||
xcb_screen_t * xcbScreen;
|
||||
uint32_t seg;
|
||||
int shmID;
|
||||
void * data;
|
||||
LGEvent * frameEvent;
|
||||
bool initialized;
|
||||
bool stop;
|
||||
xcb_connection_t * xcb;
|
||||
xcb_screen_t * xcbScreen;
|
||||
uint32_t seg;
|
||||
int shmID;
|
||||
void * data;
|
||||
LGEvent * frameEvent;
|
||||
|
||||
CaptureGetPointerBuffer getPointerBufferFn;
|
||||
CapturePostPointerBuffer postPointerBufferFn;
|
||||
LGThread * pointerThread;
|
||||
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
|
||||
int mouseX, mouseY, mouseHotX, mouseHotY;
|
||||
|
||||
bool hasFrame;
|
||||
xcb_shm_get_image_cookie_t imgC;
|
||||
xcb_xfixes_get_cursor_image_cookie_t curC;
|
||||
|
@ -52,6 +60,8 @@ struct xcb
|
|||
|
||||
static struct xcb * this = NULL;
|
||||
|
||||
static int pointerThread(void * unused);
|
||||
|
||||
// forwards
|
||||
|
||||
static bool xcb_deinit();
|
||||
|
@ -81,6 +91,9 @@ static bool xcb_create(CaptureGetPointerBuffer getPointerBufferFn, CapturePostPo
|
|||
this->data = (void *)-1;
|
||||
this->frameEvent = lgCreateEvent(true, 20);
|
||||
|
||||
this->getPointerBufferFn = getPointerBufferFn;
|
||||
this->postPointerBufferFn = postPointerBufferFn;
|
||||
|
||||
if (!this->frameEvent)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the frame event");
|
||||
|
@ -137,6 +150,37 @@ static bool xcb_init(void)
|
|||
}
|
||||
DEBUG_INFO("Frame Data : 0x%" PRIXPTR, (uintptr_t)this->data);
|
||||
|
||||
xcb_query_extension_cookie_t extension_cookie =
|
||||
xcb_query_extension(this->xcb, strlen("XFIXES"), "XFIXES");
|
||||
xcb_query_extension_reply_t * extension_reply =
|
||||
xcb_query_extension_reply(this->xcb, extension_cookie, NULL);
|
||||
if(!extension_reply)
|
||||
{
|
||||
DEBUG_ERROR("Extension \"XFIXES\" isn't available");
|
||||
free(extension_reply);
|
||||
goto fail;
|
||||
}
|
||||
free(extension_reply);
|
||||
|
||||
xcb_xfixes_query_version_cookie_t version_cookie =
|
||||
xcb_xfixes_query_version(this->xcb, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
|
||||
xcb_xfixes_query_version_reply_t * version_reply =
|
||||
xcb_xfixes_query_version_reply(this->xcb, version_cookie, NULL);
|
||||
if(!version_reply)
|
||||
{
|
||||
DEBUG_ERROR("Extension \"XFIXES\" isn't available");
|
||||
free(version_reply);
|
||||
goto fail;
|
||||
}
|
||||
free(version_reply);
|
||||
|
||||
if (!lgCreateThread("XCBPointer", pointerThread, NULL, &this->pointerThread))
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the XCBPointer thread");
|
||||
xcb_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->initialized = true;
|
||||
return true;
|
||||
fail:
|
||||
|
@ -252,6 +296,77 @@ static CaptureResult xcb_getFrame(FrameBuffer * frame,
|
|||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static int pointerThread(void * unused)
|
||||
{
|
||||
while (!this->stop)
|
||||
{
|
||||
if (this->stop)
|
||||
break;
|
||||
|
||||
CapturePointer pointer = { 0 };
|
||||
|
||||
this->curC = xcb_xfixes_get_cursor_image_unchecked(this->xcb);
|
||||
|
||||
void * data;
|
||||
uint32_t size;
|
||||
if (!this->getPointerBufferFn(&data, &size))
|
||||
{
|
||||
DEBUG_WARN("failed to get a pointer buffer");
|
||||
continue;
|
||||
}
|
||||
|
||||
xcb_xfixes_get_cursor_image_reply_t * curReply;
|
||||
curReply = xcb_xfixes_get_cursor_image_reply(this->xcb, this->curC, NULL);
|
||||
if (curReply == NULL)
|
||||
{
|
||||
DEBUG_WARN("Failed to get cursor reply");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(curReply->xhot != this->mouseHotX || curReply->yhot != this->mouseHotY)
|
||||
{
|
||||
pointer.shapeUpdate = true;
|
||||
this->mouseHotX = curReply->xhot;
|
||||
this->mouseHotY = curReply->yhot;
|
||||
|
||||
uint32_t * src = xcb_xfixes_get_cursor_image_cursor_image(curReply);
|
||||
uint32_t * dst = (uint32_t *) (data);
|
||||
memcpy(dst, src, curReply->width * curReply->height * sizeof(uint32_t));
|
||||
}
|
||||
else
|
||||
pointer.shapeUpdate = false;
|
||||
|
||||
if(curReply->x != this->mouseX || curReply->y != this->mouseY)
|
||||
{
|
||||
pointer.positionUpdate = true;
|
||||
this->mouseX = curReply->x;
|
||||
this->mouseY = curReply->y;
|
||||
}
|
||||
else
|
||||
pointer.positionUpdate = false;
|
||||
|
||||
if(pointer.positionUpdate || pointer.shapeUpdate)
|
||||
{
|
||||
pointer.hx = curReply->xhot;
|
||||
pointer.hy = curReply->yhot;
|
||||
pointer.visible = true;
|
||||
pointer.x = curReply->x - curReply->xhot;
|
||||
pointer.y = curReply->y - curReply->yhot;
|
||||
pointer.format = CAPTURE_FMT_COLOR;
|
||||
pointer.width = curReply->width;
|
||||
pointer.height = curReply->height;
|
||||
pointer.pitch = curReply->width * 4;
|
||||
|
||||
this->postPointerBufferFn(pointer);
|
||||
}
|
||||
|
||||
free(curReply);
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct CaptureInterface Capture_XCB =
|
||||
{
|
||||
.shortName = "XCB",
|
||||
|
|
Loading…
Reference in a new issue