From 612e5a5c08dbdccebea07f6281d39b4f32ac9439 Mon Sep 17 00:00:00 2001 From: Krystof Pistek Date: Fri, 14 Jun 2024 15:36:14 +0200 Subject: [PATCH] Add local cursor selection for Java version Replicates the C++ work done in the previous commit on the Java version. --- .../com/tigervnc/vncviewer/OptionsDialog.java | 51 ++++++++++++++++--- java/com/tigervnc/vncviewer/Parameters.java | 14 +++-- java/com/tigervnc/vncviewer/Viewport.java | 17 +++++-- 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/java/com/tigervnc/vncviewer/OptionsDialog.java b/java/com/tigervnc/vncviewer/OptionsDialog.java index 2fbd9d9c20..2d31c5d1b4 100644 --- a/java/com/tigervnc/vncviewer/OptionsDialog.java +++ b/java/com/tigervnc/vncviewer/OptionsDialog.java @@ -152,9 +152,13 @@ protected void processFocusEvent(final FocusEvent e) { /* Misc. */ JCheckBox sharedCheckbox; - JCheckBox dotWhenNoCursorCheckbox; + JCheckBox localCursorCheckbox; JCheckBox acceptBellCheckbox; + ButtonGroup cursorTypeGroup; + JRadioButton dotButton; + JRadioButton systemButton; + /* SSH */ JCheckBox tunnelCheckbox; JCheckBox viaCheckbox; @@ -186,6 +190,7 @@ public OptionsDialog() { encodingGroup = new ButtonGroup(); colorlevelGroup = new ButtonGroup(); + cursorTypeGroup = new ButtonGroup(); // tabPane tabPane.addTab("Compression", createCompressionPanel()); @@ -311,6 +316,7 @@ private void loadOptions() handleAutoselect(); handleCompression(); handleJpeg(); + handleLocalCursor(); /* Security */ Security security = new Security(SecurityClient.secTypes); @@ -458,7 +464,12 @@ private void loadOptions() /* Misc. */ sharedCheckbox.setSelected(shared.getValue()); - dotWhenNoCursorCheckbox.setSelected(dotWhenNoCursor.getValue()); + localCursorCheckbox.setSelected(localCursor.getValue()); + String cursorTypeStr = cursorType.getValueStr(); + if (cursorTypeStr.matches("^Dot$")) + dotButton.setSelected(true); + else + systemButton.setSelected(true); acceptBellCheckbox.setSelected(acceptBell.getValue()); /* SSH */ @@ -613,8 +624,12 @@ else if (mediumcolorButton.isSelected()) /* Misc. */ shared.setParam(sharedCheckbox.isSelected()); - dotWhenNoCursor.setParam(dotWhenNoCursorCheckbox.isSelected()); + localCursor.setParam(localCursorCheckbox.isSelected()); acceptBell.setParam(acceptBellCheckbox.isSelected()); + if (dotButton.isSelected()) + cursorType.setParam("Dot"); + if (systemButton.isSelected()) + cursorType.setParam("System"); /* SSH */ tunnel.setParam(tunnelCheckbox.isSelected()); @@ -1173,7 +1188,16 @@ private JPanel createMiscPanel() { MiscPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5)); sharedCheckbox = new JCheckBox("Shared (don't disconnect other viewers)"); - dotWhenNoCursorCheckbox = new JCheckBox("Show dot when no cursor"); + localCursorCheckbox = new JCheckBox("Show local cursor when not provided by server"); + localCursorCheckbox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + handleLocalCursor(); + } + }); + JPanel cursorTypePanel = new JPanel(new GridLayout(2, 1)); + cursorTypePanel.setBorder(BorderFactory.createTitledBorder("Local cursor type")); + dotButton = new GroupedJRadioButton("Dot cursor", cursorTypeGroup, cursorTypePanel); + systemButton = new GroupedJRadioButton("System cursor", cursorTypeGroup, cursorTypePanel); acceptBellCheckbox = new JCheckBox("Beep when requested by the server"); MiscPanel.add(sharedCheckbox, new GridBagConstraints(0, 0, @@ -1182,22 +1206,29 @@ private JPanel createMiscPanel() { LINE_START, NONE, new Insets(0, 0, 4, 0), NONE, NONE)); - MiscPanel.add(dotWhenNoCursorCheckbox, + MiscPanel.add(localCursorCheckbox, new GridBagConstraints(0, 1, 1, 1, LIGHT, LIGHT, LINE_START, NONE, new Insets(0, 0, 4, 0), NONE, NONE)); - MiscPanel.add(acceptBellCheckbox, + MiscPanel.add(cursorTypePanel, new GridBagConstraints(0, 2, + 2, 1, + LIGHT, LIGHT, + LINE_START, NONE, + new Insets(0, 0, 4, 0), + NONE, NONE)); + MiscPanel.add(acceptBellCheckbox, + new GridBagConstraints(0, 3, 1, 1, LIGHT, LIGHT, LINE_START, NONE, new Insets(0, 0, 4, 0), NONE, NONE)); MiscPanel.add(Box.createRigidArea(new Dimension(5, 0)), - new GridBagConstraints(0, 3, + new GridBagConstraints(0, 4, REMAINDER, REMAINDER, HEAVY, HEAVY, LINE_START, BOTH, @@ -1633,5 +1664,11 @@ private void handleRfbState() } } + private void handleLocalCursor() + { + dotButton.setEnabled(localCursorCheckbox.isSelected()); + systemButton.setEnabled(localCursorCheckbox.isSelected()); + } + static LogWriter vlog = new LogWriter("OptionsDialog"); } diff --git a/java/com/tigervnc/vncviewer/Parameters.java b/java/com/tigervnc/vncviewer/Parameters.java index 8c8465cba1..fa03011fd3 100644 --- a/java/com/tigervnc/vncviewer/Parameters.java +++ b/java/com/tigervnc/vncviewer/Parameters.java @@ -38,11 +38,16 @@ public class Parameters { "Lion or later.", false); - public static BoolParameter dotWhenNoCursor - = new BoolParameter("DotWhenNoCursor", - "Show the dot cursor when the server sends an invisible cursor", + public static BoolParameter localCursor + = new BoolParameter("LocalCursor", + "Show the local cursor when the server sends an invisible cursor", false); + public static StringParameter cursorType + = new StringParameter("CursorType", + "Specify which cursor type the local cursor should be. Should be either Dot or System", + "Dot"); + public static BoolParameter sendLocalUsername = new BoolParameter("SendLocalUsername", "Send the local username for SecurityTypes "+ @@ -282,7 +287,8 @@ public class Parameters { CSecurityTLS.X509CA, CSecurityTLS.X509CRL, SecurityClient.secTypes, - dotWhenNoCursor, + localCursor, + cursorType, autoSelect, fullColor, lowColorLevel, diff --git a/java/com/tigervnc/vncviewer/Viewport.java b/java/com/tigervnc/vncviewer/Viewport.java index e12ef2a685..a67e6f03b6 100644 --- a/java/com/tigervnc/vncviewer/Viewport.java +++ b/java/com/tigervnc/vncviewer/Viewport.java @@ -167,8 +167,15 @@ public void setCursor(int width, int height, Point hotspot, for (i = 0; i < width*height; i++) if (data[i*4 + 3] != 0) break; - if ((i == width*height) && dotWhenNoCursor.getValue()) { - vlog.debug("cursor is empty - using dot"); + if ((i == width*height) && localCursor.getValue()) { + String cursorTypeStr = cursorType.getValueStr(); + useSystemCursor = false; + if (cursorTypeStr.matches("^Dot$")) { + vlog.debug("cursor is empty - using dot"); + } else if (cursorTypeStr.matches("^System$")) { + useSystemCursor = true; + } + // Do this anyway to prevent cursor being null cursor = new BufferedImage(5, 5, BufferedImage.TYPE_INT_ARGB_PRE); cursor.setRGB(0, 0, 5, 5, dotcursor_xpm, 0, 5); cursorHotspot.x = cursorHotspot.y = 3; @@ -216,7 +223,10 @@ private void setCursor(Image img, int x, int y) hotspot = new java.awt.Point(x, y); softCursor = tk.createCustomCursor(img, hotspot, name); - setCursor(softCursor); + if (useSystemCursor) + setCursor(java.awt.Cursor.getDefaultCursor()); + else + setCursor(softCursor); } public void resize(int x, int y, int w, int h) { @@ -830,6 +840,7 @@ public DownMap(int capacity) { float scaleRatioX, scaleRatioY; static BufferedImage cursor; + static boolean useSystemCursor = false; Point cursorHotspot = new Point(); }