Skip to content

Commit

Permalink
Add local cursor selection for C++ version
Browse files Browse the repository at this point in the history
This adds the option to select which cursor should be used in the event the
server sends an invisible cursor. It also renames the DotWhenNoCursor config
option to AlwaysCursor.
  • Loading branch information
krystof1119 committed Aug 9, 2024
1 parent 633e75b commit 8a38990
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 18 deletions.
45 changes: 39 additions & 6 deletions vncviewer/OptionsDialog.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,13 @@ void OptionsDialog::loadOptions(void)
/* Misc. */
sharedCheckbox->value(shared);
reconnectCheckbox->value(reconnectOnError);
dotCursorCheckbox->value(dotWhenNoCursor);
alwaysCursorCheckbox->value(alwaysCursor);
if (!strcasecmp(cursorType, "dot")) {
cursorTypeChoice->value(0);
} else {
cursorTypeChoice->value(1);
}
handleAlwaysCursor(alwaysCursorCheckbox, this);
}


Expand Down Expand Up @@ -486,7 +492,13 @@ void OptionsDialog::storeOptions(void)
/* Misc. */
shared.setParam(sharedCheckbox->value());
reconnectOnError.setParam(reconnectCheckbox->value());
dotWhenNoCursor.setParam(dotCursorCheckbox->value());
alwaysCursor.setParam(alwaysCursorCheckbox->value());

if (cursorTypeChoice->value() == 0) {
cursorType.setParam("Dot");
} else {
cursorType.setParam("System");
}

std::map<OptionsCallback*, void*>::const_iterator iter;

Expand Down Expand Up @@ -835,11 +847,21 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
_("Emulate middle mouse button")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;

dotCursorCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Show dot when no cursor")));
alwaysCursorCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Show local cursor when not provided by server")));
alwaysCursorCheckbox->callback(handleAlwaysCursor, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;

/* Cursor type */
cursorTypeChoice = new Fl_Choice(LBLLEFT(tx, ty, 150, CHOICE_HEIGHT, _("Cursor type")));

fltk_menu_add(cursorTypeChoice, _("Dot"), 0, nullptr, nullptr, 0);
fltk_menu_add(cursorTypeChoice, _("System"), 0, nullptr, nullptr, 0);

ty += CHOICE_HEIGHT + TIGHT_MARGIN;

}
ty -= TIGHT_MARGIN;

Expand Down Expand Up @@ -1181,3 +1203,14 @@ void OptionsDialog::handleScreenConfigTimeout(void *data)

self->monitorArrangement->value(fullScreenSelectedMonitors.getParam());
}

void OptionsDialog::handleAlwaysCursor(Fl_Widget* /*widget*/, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;

if (dialog->alwaysCursorCheckbox->value()) {
dialog->cursorTypeChoice->activate();
} else {
dialog->cursorTypeChoice->deactivate();
}
}
4 changes: 3 additions & 1 deletion vncviewer/OptionsDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class OptionsDialog : public Fl_Window {
static void handleAutoselect(Fl_Widget *widget, void *data);
static void handleCompression(Fl_Widget *widget, void *data);
static void handleJpeg(Fl_Widget *widget, void *data);
static void handleAlwaysCursor(Fl_Widget *widget, void *data);

static void handleX509(Fl_Widget *widget, void *data);
static void handleRSAAES(Fl_Widget *widget, void *data);
Expand Down Expand Up @@ -115,7 +116,8 @@ class OptionsDialog : public Fl_Window {
Fl_Check_Button *viewOnlyCheckbox;
Fl_Group *mouseGroup;
Fl_Check_Button *emulateMBCheckbox;
Fl_Check_Button *dotCursorCheckbox;
Fl_Check_Button *alwaysCursorCheckbox;
Fl_Choice *cursorTypeChoice;
Fl_Group *keyboardGroup;
Fl_Check_Button *systemKeysCheckbox;
Fl_Choice *menuKeyChoice;
Expand Down
26 changes: 21 additions & 5 deletions vncviewer/Viewport.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& /*serverPF*/, CConn* cc
altGrArmed(false),
#endif
firstLEDState(true), pendingClientClipboard(false),
menuCtrlKey(false), menuAltKey(false), cursor(nullptr)
menuCtrlKey(false), menuAltKey(false), cursor(nullptr),
cursorIsBlank(false)
{
#if !defined(WIN32) && !defined(__APPLE__)
XkbDescPtr xkb;
Expand Down Expand Up @@ -259,7 +260,12 @@ void Viewport::setCursor(int width, int height, const Point& hotspot,
for (i = 0; i < width*height; i++)
if (data[i*4 + 3] != 0) break;

if ((i == width*height) && dotWhenNoCursor) {
cursorIsBlank = i == width*height;

if (cursorIsBlank && alwaysCursor) {
// This is the default in case the local cursor should be displayed yet cursorType is invalid.
// Since the cursor variable isn't used if the cursorType is system, we can do this without checking the current
// type which helps handle changing the type while the viewer is running.
vlog.debug("cursor is empty - using dot");

Fl_Pixmap pxm(dotcursor_xpm);
Expand All @@ -279,8 +285,18 @@ void Viewport::setCursor(int width, int height, const Point& hotspot,
}
}

if (Fl::belowmouse() == this)
if (Fl::belowmouse() == this) {
showCursor();
}
}

void Viewport::showCursor()
{
if (cursorIsBlank && alwaysCursor && !strcasecmp("system", cursorType)) {
window()->cursor(FL_CURSOR_DEFAULT);
} else {
window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y);
}
}

void Viewport::handleClipboardRequest()
Expand Down Expand Up @@ -583,7 +599,7 @@ int Viewport::handle(int event)
return 1;

case FL_ENTER:
window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y);
showCursor();
// Yes, we would like some pointer events please!
return 1;

Expand Down Expand Up @@ -1299,7 +1315,7 @@ void Viewport::popupContextMenu()

// Back to our proper mouse pointer.
if (Fl::belowmouse())
window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y);
showCursor();

if (m == nullptr)
return;
Expand Down
4 changes: 4 additions & 0 deletions vncviewer/Viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class Viewport : public Fl_Widget, public EmulateMB {

unsigned int getModifierMask(unsigned int keysym);

// Show the currently set (or system) cursor
void showCursor();

static void handleClipboardChange(int source, void *data);

void flushPendingClipboard();
Expand Down Expand Up @@ -136,6 +139,7 @@ class Viewport : public Fl_Widget, public EmulateMB {

Fl_RGB_Image *cursor;
rfb::Point cursorHotspot;
bool cursorIsBlank;
};

#endif
15 changes: 12 additions & 3 deletions vncviewer/parameters.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,15 @@ BoolParameter emulateMiddleButton("EmulateMiddleButton",
"left and right mouse buttons simultaneously",
false);
BoolParameter dotWhenNoCursor("DotWhenNoCursor",
"Show the dot cursor when the server sends an "
"[DEPRECATED] Show the dot cursor when the server sends an "
"invisible cursor", false);
BoolParameter alwaysCursor("AlwaysCursor",
"Show the local cursor when the server sends an "
"invisible cursor", false);
StringParameter cursorType("CursorType",
"Specify which cursor type the local cursor should be. "
"Should be either Dot or System",
"Dot");

BoolParameter alertOnFatalError("AlertOnFatalError",
"Give a dialog on connection problems rather "
Expand Down Expand Up @@ -198,7 +205,8 @@ static VoidParameter* parameterArray[] = {
/* Input */
&viewOnly,
&emulateMiddleButton,
&dotWhenNoCursor,
&alwaysCursor,
&cursorType,
&acceptClipboard,
&sendClipboard,
#if !defined(WIN32) && !defined(__APPLE__)
Expand All @@ -210,7 +218,8 @@ static VoidParameter* parameterArray[] = {
};

static VoidParameter* readOnlyParameterArray[] = {
&fullScreenAllMonitors
&fullScreenAllMonitors,
&dotWhenNoCursor
};

// Encoding Table
Expand Down
4 changes: 3 additions & 1 deletion vncviewer/parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@

extern rfb::IntParameter pointerEventInterval;
extern rfb::BoolParameter emulateMiddleButton;
extern rfb::BoolParameter dotWhenNoCursor;
extern rfb::BoolParameter dotWhenNoCursor; // deprecated
extern rfb::BoolParameter alwaysCursor;
extern rfb::StringParameter cursorType;

extern rfb::StringParameter passwordFile;

Expand Down
6 changes: 6 additions & 0 deletions vncviewer/vncviewer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,12 @@ migrateDeprecatedOptions()

fullScreenMode.setParam("all");
}
if (dotWhenNoCursor) {
vlog.info(_("DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead"));

alwaysCursor.setParam(true);
cursorType.setParam("Dot");
}
}

#ifndef WIN32
Expand Down
15 changes: 13 additions & 2 deletions vncviewer/vncviewer.man
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,19 @@ Use specified lossless compression level. 0 = Low, 9 = High. Default is 2.
Use custom compression level. Default if \fBCompressLevel\fP is specified.
.
.TP
.B \-DotWhenNoCursor
Show the dot cursor when the server sends an invisible cursor. Default is off.
.B \-DotWhenNoCursor (DEPRECATED)
Show the dot cursor when the server sends an invisible cursor. Replaced by
\fB-AlwaysCursor\fP and \fB-CursorType=Dot\fP
.
.TP
.B \-AlwaysCursor
Show a local cursor when the server sends an invisible cursor. Default is off.
.
.TP
.B \-CursorType \fItype\fP
Specify which cursor type to use when a local cursor is shown. It should be
either "Dot", or "System". Ignored if AlwaysCursor is off.
The default is "Dot".
.
.TP
.B \-PointerEventInterval \fItime\fP
Expand Down

0 comments on commit 8a38990

Please sign in to comment.