11package de .doubleslash .keeptime .viewPopup ;
22
33import java .awt .Point ;
4+ import java .util .concurrent .Executors ;
5+ import java .util .concurrent .ScheduledExecutorService ;
6+ import java .util .concurrent .ScheduledFuture ;
7+ import java .util .concurrent .TimeUnit ;
48import java .util .logging .Level ;
59import java .util .logging .Logger ;
610
913import org .jnativehook .keyboard .NativeKeyEvent ;
1014import org .jnativehook .keyboard .NativeKeyListener ;
1115import org .jnativehook .mouse .NativeMouseEvent ;
12- import org .jnativehook .mouse .NativeMouseInputListener ;
13- import org .jnativehook .mouse .NativeMouseWheelEvent ;
14- import org .jnativehook .mouse .NativeMouseWheelListener ;
16+ import org .jnativehook .mouse .NativeMouseMotionListener ;
1517import org .slf4j .LoggerFactory ;
1618
1719import javafx .application .Platform ;
1820
19- public class GlobalScreenListener implements NativeKeyListener , NativeMouseInputListener , NativeMouseWheelListener {
20- private static final int LEFT_WINDOWS = 91 ;
21+ /**
22+ * Class captures all key events and implements a hotkey mechanism. Needs to be stopped by calling shutdown.
23+ *
24+ * @author nmutter
25+ */
26+ public class GlobalScreenListener implements NativeKeyListener , NativeMouseMotionListener {
27+ private static final int LEFT_WINDOWS_CODE = 91 ;
2128
22- private static final int LEFT_CTRL = 162 ;
29+ private static final int LEFT_CTRL_CODE = 162 ;
2330
2431 private final org .slf4j .Logger LOG = LoggerFactory .getLogger (this .getClass ());
2532
2633 private ViewControllerPopup viewController ;
2734
35+ private final ScheduledExecutorService executor = Executors .newScheduledThreadPool (1 );
36+
37+ private ScheduledFuture <?> resetKeyPressesFuture ;
38+
39+ private final Runnable resetPressedKeysRunnable = () -> {
40+ LOG .debug ("Resetting pressed keys" );
41+ controllPressed = false ;
42+ windowsPressed = false ;
43+ };
44+
45+ // TODO find better hotkey - maybe configurable?
46+ private boolean controllPressed = false ;
47+ private boolean windowsPressed = false ;
48+
49+ private Point mouseLocation = new Point (0 , 0 );
50+
2851 public GlobalScreenListener () {
2952
30- setGlobalScreenLogLevel ();
53+ disableJNativeHookLogger ();
3154
3255 GlobalScreen .addNativeKeyListener (this );
33- GlobalScreen .addNativeMouseListener (this );
3456 GlobalScreen .addNativeMouseMotionListener (this );
35- GlobalScreen .addNativeMouseWheelListener (this );
3657 }
3758
3859 public void register (final boolean register ) {
@@ -49,7 +70,7 @@ public void register(final boolean register) {
4970 }
5071 }
5172
52- public void setGlobalScreenLogLevel () {
73+ private void disableJNativeHookLogger () {
5374 // Get the logger for "org.jnativehook" and set the level to off.
5475 final Logger logger = Logger .getLogger (GlobalScreen .class .getPackage ().getName ());
5576
@@ -63,61 +84,55 @@ public void setViewController(final ViewControllerPopup viewController) {
6384 this .viewController = viewController ;
6485 }
6586
66- boolean controllPressed = false ;
67- boolean windowsPressed = false ;
68-
69- private Point mouseLocation = new Point (0 , 0 );
70-
7187 @ Override
7288 public void nativeKeyPressed (final NativeKeyEvent e ) {
73- // TODO find better hotkey - maybe configurable?
74-
7589 switch (e .getRawCode ()) {
76- case LEFT_CTRL :
90+ case LEFT_CTRL_CODE :
7791 controllPressed = true ;
7892 break ;
79- case LEFT_WINDOWS :
93+ case LEFT_WINDOWS_CODE :
8094 windowsPressed = true ;
8195 break ;
8296 default :
97+ return ;
8398 }
8499
85100 if (controllPressed && windowsPressed ) {
86101 Platform .runLater (() -> {
87102 viewController .show (mouseLocation );
88103 });
89104 }
105+
106+ // Logic to reset key presses if no input for n seconds
107+ // if u win+l (lock) windows, the key release events are not received
108+ if (resetKeyPressesFuture != null ) {
109+ resetKeyPressesFuture .cancel (false );
110+ }
111+ resetKeyPressesFuture = executor .schedule (resetPressedKeysRunnable , 1 , TimeUnit .SECONDS );
90112 }
91113
92114 @ Override
93115 public void nativeKeyReleased (final NativeKeyEvent e ) {
94116 switch (e .getRawCode ()) {
95- case LEFT_CTRL :
117+ case LEFT_CTRL_CODE :
96118 controllPressed = false ;
97119 break ;
98- case LEFT_WINDOWS :
120+ case LEFT_WINDOWS_CODE :
99121 windowsPressed = false ;
100122 break ;
101123 default :
124+ return ;
102125 }
103- }
104-
105- @ Override
106- public void nativeKeyTyped (final NativeKeyEvent e ) {}
107-
108- @ Override
109- public void nativeMouseClicked (final NativeMouseEvent e ) {}
110-
111- @ Override
112- public void nativeMousePressed (final NativeMouseEvent nativeEvent ) {
113- // TODO Auto-generated method stub
114126
127+ if (!controllPressed && !windowsPressed && resetKeyPressesFuture != null ) {
128+ // nothing to reset so we can cancel
129+ resetKeyPressesFuture .cancel (false );
130+ }
115131 }
116132
117133 @ Override
118- public void nativeMouseReleased (final NativeMouseEvent nativeEvent ) {
119- // TODO Auto-generated method stub
120-
134+ public void nativeKeyTyped (final NativeKeyEvent e ) {
135+ // Not needed
121136 }
122137
123138 @ Override
@@ -127,14 +142,14 @@ public void nativeMouseMoved(final NativeMouseEvent nativeEvent) {
127142
128143 @ Override
129144 public void nativeMouseDragged (final NativeMouseEvent nativeEvent ) {
130- // TODO Auto-generated method stub
131-
145+ // Not needed
132146 }
133147
134- @ Override
135- public void nativeMouseWheelMoved (final NativeMouseWheelEvent nativeEvent ) {
136- // TODO Auto-generated method stub
137-
148+ /**
149+ * Shuts down the threads and listeners. Instance is not usable anymore after calling this.
150+ */
151+ public void shutdown () {
152+ executor .shutdown ();
153+ register (false );
138154 }
139-
140155}
0 commit comments