From ccb77c5111b2c1f7bf93a7f308794bc0dfa2dff4 Mon Sep 17 00:00:00 2001 From: DRC Date: Tue, 22 Nov 2022 15:15:04 -0600 Subject: [PATCH] Viewer: Disable scrollbar hotkeys if no scrollbars ... or if keyboard grabbing is enabled. Fixes #348 --- ChangeLog.md | 6 ++ .../com/turbovnc/vncviewer/DesktopWindow.java | 6 +- java/com/turbovnc/vncviewer/Viewport.java | 67 ++++++++++++------- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 308263e21..df3656aff 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -38,6 +38,12 @@ sequence, Mac users sometimes attempt to use Command-V with TurboVNC out of habit, which caused view-only mode to be activated accidentally because of 3.0 beta1[28]. CTRL-ALT-SHIFT-V can still be used to toggle view-only mode. +8. The TurboVNC Viewer normally reserves CTRL-ALT-SHIFT-{arrow keys} as hotkeys +to move the horizontal and vertical scrollbars. However, those key sequences +are also used by Emacs and GNOME. Thus, the TurboVNC Viewer now sends those +key sequences to the server if no scrollbars are visible or if keyboard +grabbing is enabled. + 3.0.1 ===== diff --git a/java/com/turbovnc/vncviewer/DesktopWindow.java b/java/com/turbovnc/vncviewer/DesktopWindow.java index 1e67ef5ad..de74bb292 100644 --- a/java/com/turbovnc/vncviewer/DesktopWindow.java +++ b/java/com/turbovnc/vncviewer/DesktopWindow.java @@ -684,7 +684,11 @@ public void keyPressed(KeyEvent e) { case KeyEvent.VK_PAGE_DOWN: case KeyEvent.VK_HOME: case KeyEvent.VK_END: - return; + if (cc.viewport != null && + (cc.viewport.sp.getHorizontalScrollBar().isVisible() || + cc.viewport.sp.getVerticalScrollBar().isVisible()) && + !VncViewer.isKeyboardGrabbed(cc.viewport)) + return; } } if ((e.getModifiersEx() & InputEvent.META_DOWN_MASK) == diff --git a/java/com/turbovnc/vncviewer/Viewport.java b/java/com/turbovnc/vncviewer/Viewport.java index c7115fa76..d3c80dc68 100644 --- a/java/com/turbovnc/vncviewer/Viewport.java +++ b/java/com/turbovnc/vncviewer/Viewport.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2013, 2015-2021 D. R. Commander. All Rights Reserved. +/* Copyright (C) 2012-2013, 2015-2022 D. R. Commander. All Rights Reserved. * Copyright (C) 2011-2013 Brian P. Hinz * Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * @@ -49,28 +49,7 @@ public Viewport(CConn cc_) { sp.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); sp.setViewportBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); sp.getViewport().setBackground(Color.BLACK); - InputMap im = sp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); - int ctrlAltShiftMask = InputEvent.SHIFT_DOWN_MASK | - InputEvent.CTRL_DOWN_MASK | - InputEvent.ALT_DOWN_MASK; - if (im != null) { - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, ctrlAltShiftMask), - "unitScrollUp"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, ctrlAltShiftMask), - "unitScrollDown"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ctrlAltShiftMask), - "unitScrollLeft"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ctrlAltShiftMask), - "unitScrollRight"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, ctrlAltShiftMask), - "scrollUp"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, ctrlAltShiftMask), - "scrollDown"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, ctrlAltShiftMask), - "scrollLeft"); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, ctrlAltShiftMask), - "scrollRight"); - } + setScrollBarHotkeysEnabled(true); tb = new Toolbar(cc); add(tb, BorderLayout.PAGE_START); getContentPane().add(sp); @@ -179,6 +158,9 @@ public void actionPerformed(ActionEvent e) { ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); sp.validate(); } + setScrollBarHotkeysEnabled((sp.getHorizontalScrollBar().isVisible() || + sp.getVerticalScrollBar().isVisible()) && + !VncViewer.isKeyboardGrabbed(cc.viewport)); if (cc.desktop.cursor != null) { Cursor cursor = cc.desktop.cursor; if (cursor.hotspot != null) @@ -219,6 +201,42 @@ public void componentMoved(ComponentEvent e) { lastEvent.deviceID = -1; } + private void setScrollBarHotkeysEnabled(boolean enable) { + InputMap im = sp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + int ctrlAltShiftMask = InputEvent.SHIFT_DOWN_MASK | + InputEvent.CTRL_DOWN_MASK | + InputEvent.ALT_DOWN_MASK; + if (im == null) return; + if (enable) { + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, ctrlAltShiftMask), + "unitScrollUp"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, ctrlAltShiftMask), + "unitScrollDown"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ctrlAltShiftMask), + "unitScrollLeft"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ctrlAltShiftMask), + "unitScrollRight"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, ctrlAltShiftMask), + "scrollUp"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, ctrlAltShiftMask), + "scrollDown"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, ctrlAltShiftMask), + "scrollLeft"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, ctrlAltShiftMask), + "scrollRight"); + } else { + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_UP, ctrlAltShiftMask)); + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, ctrlAltShiftMask)); + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ctrlAltShiftMask)); + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ctrlAltShiftMask)); + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, ctrlAltShiftMask)); + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, + ctrlAltShiftMask)); + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, ctrlAltShiftMask)); + im.remove(KeyStroke.getKeyStroke(KeyEvent.VK_END, ctrlAltShiftMask)); + } + } + public Dimension getAvailableSize() { Dimension availableSize = getSize(); if (!cc.opts.fullScreen) { @@ -438,6 +456,9 @@ public void grabKeyboardHelper(boolean on, boolean force) { return; grabKeyboard(on, Params.grabPointer.getValue()); VncViewer.setGrabOwner(on ? this : null); + setScrollBarHotkeysEnabled((sp.getHorizontalScrollBar().isVisible() || + sp.getVerticalScrollBar().isVisible()) && + !on); } catch (UnsatisfiedLinkError e) { vlog.info("WARNING: Could not invoke grabKeyboard() from TurboVNC Helper."); vlog.info(" Keyboard grabbing will be disabled.");