[client] spice: update to properly support all cursor types

This commit is contained in:
Geoffrey McRae
2026-08-01 15:43:30 +10:00
parent fab9961c49
commit 47905ec65e
4 changed files with 66 additions and 28 deletions

View File

@@ -976,9 +976,17 @@ static void spice_setCursorRGBAImage(int width, int height, int hx, int hy,
g_state.spiceHotX = hx;
g_state.spiceHotY = hy;
void * copied = malloc(width * height * 4);
memcpy(copied, data, width * height * 4);
renderQueue_cursorImage(false, width, height, width * 4, copied);
const uint8_t * rgba = data;
uint8_t * bgra = malloc(width * height * 4);
for (int i = 0; i < width * height; ++i)
{
bgra[i * 4 + 0] = rgba[i * 4 + 2];
bgra[i * 4 + 1] = rgba[i * 4 + 1];
bgra[i * 4 + 2] = rgba[i * 4 + 0];
bgra[i * 4 + 3] = rgba[i * 4 + 3];
}
renderQueue_cursorImage(
LG_CURSOR_COLOR, width, height, width * 4, bgra);
}
static void spice_setCursorMonoImage(int width, int height, int hx, int hy,
@@ -989,9 +997,37 @@ static void spice_setCursorMonoImage(int width, int height, int hx, int hy,
int stride = (width + 7) / 8;
uint8_t * buffer = malloc(stride * height * 2);
memcpy(buffer, xorMask, stride * height);
memcpy(buffer + stride * height, andMask, stride * height);
renderQueue_cursorImage(true, width, height * 2, stride, buffer);
memcpy(buffer, andMask, stride * height);
memcpy(buffer + stride * height, xorMask, stride * height);
renderQueue_cursorImage(
LG_CURSOR_MONOCHROME, width, height * 2, stride, buffer);
}
static void spice_setCursorColorImage(int width, int height, int hx, int hy,
const void * data, const void * maskData)
{
g_state.spiceHotX = hx;
g_state.spiceHotY = hy;
const uint8_t * rgba = data;
const uint8_t * andMask = maskData;
const int maskStride = (width + 7) / 8;
uint8_t * bgra = malloc(width * height * 4);
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
const int i = y * width + x;
bgra[i * 4 + 0] = rgba[i * 4 + 2];
bgra[i * 4 + 1] = rgba[i * 4 + 1];
bgra[i * 4 + 2] = rgba[i * 4 + 0];
bgra[i * 4 + 3] =
andMask[y * maskStride + x / 8] & (0x80U >> (x % 8)) ? 255 : 0;
}
}
renderQueue_cursorImage(
LG_CURSOR_MASKED_COLOR, width, height, width * 4, bgra);
}
static void spice_setCursorState(bool visible, int x, int y)
@@ -1038,6 +1074,7 @@ int spiceThread(void * arg)
.autoConnect = false,
.setRGBAImage = spice_setCursorRGBAImage,
.setMonoImage = spice_setCursorMonoImage,
.setColorImage = spice_setCursorColorImage,
.setState = spice_setCursorState,
},
#if ENABLE_AUDIO

View File

@@ -224,12 +224,12 @@ void renderQueue_cursorState(bool visible, int x, int y, int hx, int hy)
ll_push(l_renderQueue, cmd);
}
void renderQueue_cursorImage(bool monochrome, int width, int height, int pitch,
uint8_t * data)
void renderQueue_cursorImage(LG_RendererCursor type,
int width, int height, int pitch, uint8_t * data)
{
RenderCommand * cmd = malloc(sizeof(*cmd));
cmd->op = CURSOR_OP_IMAGE;
cmd->cursorImage.monochrome = monochrome;
cmd->cursorImage.type = type;
cmd->cursorImage.width = width;
cmd->cursorImage.height = height;
cmd->cursorImage.pitch = pitch;
@@ -288,7 +288,7 @@ void renderQueue_process(void)
case CURSOR_OP_IMAGE:
RENDERER(onMouseShape,
cmd->cursorImage.monochrome ? LG_CURSOR_MONOCHROME : LG_CURSOR_COLOR,
cmd->cursorImage.type,
cmd->cursorImage.width, cmd->cursorImage.height,
cmd->cursorImage.pitch, cmd->cursorImage.data);
free(cmd->cursorImage.data);

View File

@@ -86,7 +86,7 @@ typedef struct
struct
{
bool monochrome;
LG_RendererCursor type;
int width;
int height;
int pitch;
@@ -117,5 +117,6 @@ void renderQueue_surfaceFormat(const LG_RendererFormat format,
void renderQueue_cursorState(bool visible, int x, int y, int hx, int hy);
void renderQueue_cursorImage(bool monochrome, int width, int height, int pitch,
void renderQueue_cursorImage(LG_RendererCursor type,
int width, int height, int pitch,
uint8_t * data);