mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +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
@ -23,9 +23,11 @@
|
|||||||
#include "common/option.h"
|
#include "common/option.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/event.h"
|
#include "common/event.h"
|
||||||
|
#include "common/thread.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <xcb/shm.h>
|
#include <xcb/shm.h>
|
||||||
#include <xcb/xfixes.h>
|
#include <xcb/xfixes.h>
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
@ -33,18 +35,24 @@
|
|||||||
|
|
||||||
struct xcb
|
struct xcb
|
||||||
{
|
{
|
||||||
bool initialized;
|
bool initialized;
|
||||||
bool stop;
|
bool stop;
|
||||||
xcb_connection_t * xcb;
|
xcb_connection_t * xcb;
|
||||||
xcb_screen_t * xcbScreen;
|
xcb_screen_t * xcbScreen;
|
||||||
uint32_t seg;
|
uint32_t seg;
|
||||||
int shmID;
|
int shmID;
|
||||||
void * data;
|
void * data;
|
||||||
LGEvent * frameEvent;
|
LGEvent * frameEvent;
|
||||||
|
|
||||||
|
CaptureGetPointerBuffer getPointerBufferFn;
|
||||||
|
CapturePostPointerBuffer postPointerBufferFn;
|
||||||
|
LGThread * pointerThread;
|
||||||
|
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
|
|
||||||
|
int mouseX, mouseY, mouseHotX, mouseHotY;
|
||||||
|
|
||||||
bool hasFrame;
|
bool hasFrame;
|
||||||
xcb_shm_get_image_cookie_t imgC;
|
xcb_shm_get_image_cookie_t imgC;
|
||||||
xcb_xfixes_get_cursor_image_cookie_t curC;
|
xcb_xfixes_get_cursor_image_cookie_t curC;
|
||||||
@ -52,6 +60,8 @@ struct xcb
|
|||||||
|
|
||||||
static struct xcb * this = NULL;
|
static struct xcb * this = NULL;
|
||||||
|
|
||||||
|
static int pointerThread(void * unused);
|
||||||
|
|
||||||
// forwards
|
// forwards
|
||||||
|
|
||||||
static bool xcb_deinit();
|
static bool xcb_deinit();
|
||||||
@ -81,6 +91,9 @@ static bool xcb_create(CaptureGetPointerBuffer getPointerBufferFn, CapturePostPo
|
|||||||
this->data = (void *)-1;
|
this->data = (void *)-1;
|
||||||
this->frameEvent = lgCreateEvent(true, 20);
|
this->frameEvent = lgCreateEvent(true, 20);
|
||||||
|
|
||||||
|
this->getPointerBufferFn = getPointerBufferFn;
|
||||||
|
this->postPointerBufferFn = postPointerBufferFn;
|
||||||
|
|
||||||
if (!this->frameEvent)
|
if (!this->frameEvent)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the frame event");
|
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);
|
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;
|
this->initialized = true;
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
@ -252,6 +296,77 @@ static CaptureResult xcb_getFrame(FrameBuffer * frame,
|
|||||||
return CAPTURE_RESULT_OK;
|
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 =
|
struct CaptureInterface Capture_XCB =
|
||||||
{
|
{
|
||||||
.shortName = "XCB",
|
.shortName = "XCB",
|
||||||
|
Loading…
Reference in New Issue
Block a user