[client] x11: change to a more visible "dot" cursor

This change alters the small square dot cursor to a more visible 16x16
cursor for X11. A new option `spice:largeDotCursor` can be set to use an
alternative 32x32 cursor for the vision impaired.
This commit is contained in:
Geoffrey McRae 2023-09-13 21:51:53 +10:00
parent b2ec60d2dc
commit e658c2e0a2
15 changed files with 165 additions and 22 deletions

View file

@ -17,6 +17,7 @@ add_library(displayserver_X11 STATIC
x11.c
atoms.c
clipboard.c
cursor.c
wm/default.c
wm/i3.c
@ -27,6 +28,7 @@ add_definitions(-D GLX_GLXEXT_PROTOTYPES)
target_link_libraries(displayserver_X11
PkgConfig::DISPLAYSERVER_X11
lg_common
lg_resources
)
target_include_directories(displayserver_X11

View file

@ -0,0 +1,105 @@
/**
* Looking Glass
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "cursor.h"
#include "common/util.h"
#include <string.h>
#include <errno.h>
struct MemFile
{
const char * data;
int size;
int pos;
};
static int x11cursor_read(XcursorFile *file, unsigned char * buf, int len)
{
struct MemFile * f = (struct MemFile *)file->closure;
if (f->pos == f->size)
return 0;
len = min(f->size - f->pos, len);
memcpy(buf, f->data + f->pos, len);
f->pos += len;
return len;
}
static int x11cursor_write(XcursorFile *file, unsigned char * buf, int len)
{
errno = -EINVAL;
return -1;
}
static int x11cursor_seek(XcursorFile *file, long offset, int whence)
{
struct MemFile * f = (struct MemFile *)file->closure;
long target;
switch(whence)
{
case SEEK_SET:
target = offset;
break;
case SEEK_CUR:
target = f->pos + offset;
break;
case SEEK_END:
target = f->size + offset;
break;
default:
errno = -EINVAL;
return -1;
}
if (target < 0 || target > f->size)
{
errno = -EINVAL;
return -1;
}
f->pos = target;
return target;
}
XcursorImages * x11cursor_load(const char * cursor, int size)
{
struct MemFile closure =
{
.data = cursor,
.size = size,
.pos = 0
};
XcursorFile f =
{
.closure = &closure,
.read = x11cursor_read,
.write = x11cursor_write,
.seek = x11cursor_seek
};
return XcursorXcFileLoadAllImages(&f);
}

View file

@ -0,0 +1,29 @@
/**
* Looking Glass
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _H_X11DS_CURSOR_
#define _H_X11DS_CURSOR_
#include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
XcursorImages * x11cursor_load(const char * cursor, int size);
#endif

View file

@ -23,7 +23,11 @@
#include "x11.h"
#include "atoms.h"
#include "clipboard.h"
#include "cursor.h"
#include "resources/icondata.h"
#include "resources/no-input-cursor/16.xcur.h"
#include "resources/no-input-cursor/32.xcur.h"
#include <string.h>
#include <unistd.h>
@ -626,29 +630,17 @@ static bool x11Init(const LG_DSInitParams params)
XFreePixmap(x11.display, temp);
}
/* create the square cursor */
{
static char data[] = { 0x07, 0x05, 0x07 };
static char mask[] = { 0xff, 0xff, 0xff };
XcursorImages * images;
if (params.largeCursorDot)
images = x11cursor_load(b_no_input_cursor_32_xcur,
b_no_input_cursor_32_xcur_size);
else
images = x11cursor_load(b_no_input_cursor_16_xcur,
b_no_input_cursor_16_xcur_size);
Colormap cmap = DefaultColormap(x11.display, DefaultScreen(x11.display));
XColor colors[2] =
{
{ .pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(x11.display)) },
{ .pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(x11.display)) }
};
XQueryColors(x11.display, cmap, colors, 2);
Pixmap img = XCreateBitmapFromData(x11.display, x11.window, data, 3, 3);
Pixmap msk = XCreateBitmapFromData(x11.display, x11.window, mask, 3, 3);
x11.cursors[LG_POINTER_SQUARE] = XCreatePixmapCursor(x11.display, img, msk,
&colors[0], &colors[1], 1, 1);
XFreePixmap(x11.display, img);
XFreePixmap(x11.display, msk);
}
x11.cursors[LG_POINTER_SQUARE] =
XcursorImagesLoadCursor(x11.display, images);
XcursorImagesDestroy(images);
/* initialize the rest of the cursors */
const char * cursorLookup[LG_POINTER_COUNT] = {

View file

@ -90,6 +90,7 @@ typedef struct LG_DSInitParams
bool resizable;
bool borderless;
bool maximize;
bool largeCursorDot;
// if true the renderer requires an OpenGL context
bool opengl;

View file

@ -499,6 +499,13 @@ static struct Option options[] =
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{
.module = "spice",
.name = "largeCursorDot",
.description = "Use a larger version of the \"dot\" cursor",
.type = OPTION_TYPE_BOOL,
.value.x_bool = false
},
// audio options
{
@ -728,6 +735,7 @@ bool config_load(int argc, char * argv[])
g_params.captureOnStart = option_get_bool("spice", "captureOnStart");
g_params.alwaysShowCursor = option_get_bool("spice", "alwaysShowCursor");
g_params.showCursorDot = option_get_bool("spice", "showCursorDot");
g_params.largeCursorDot = option_get_bool("spice", "largeCursorDot");
}
g_params.audioPeriodSize = option_get_int("audio", "periodSize");

View file

@ -1337,6 +1337,7 @@ static int lg_run(void)
.resizable = g_params.allowResize,
.borderless = g_params.borderless,
.maximize = g_params.maximize,
.largeCursorDot = g_params.largeCursorDot,
.opengl = needsOpenGL,
.jitRender = g_params.jitRender
};

View file

@ -218,6 +218,7 @@ struct AppParams
bool autoCapture;
bool captureInputOnly;
bool showCursorDot;
bool largeCursorDot;
int audioPeriodSize;
int audioBufferLatency;

View file

@ -18,6 +18,8 @@ build_resources(
lg-logo.svg
status/spice.svg
status/recording.svg
no-input-cursor/16.xcur
no-input-cursor/32.xcur
)
add_library(lg_resources STATIC ${LG_RESOURCES_OBJS})

View file

@ -0,0 +1 @@
16 8 8 16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

View file

@ -0,0 +1 @@
32 16 16 32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.