Browse Source

Added ability to move starting points of selections with arrow keys, and made pressing enter accept the current selection rather than cancel it.

Dalton Nell 10 years ago
parent
commit
6285e519f0
7 changed files with 90 additions and 8 deletions
  1. 1
    1
      CMakeLists.txt
  2. 10
    1
      README.md
  3. 1
    1
      src/cmdline.c
  4. 59
    5
      src/main.cpp
  5. 5
    0
      src/options.ggo
  6. 13
    0
      src/x.cpp
  7. 1
    0
      src/x.hpp

+ 1
- 1
CMakeLists.txt View File

3
 project( "slop" )
3
 project( "slop" )
4
 set( slop_VERSION_MAJOR 3 )
4
 set( slop_VERSION_MAJOR 3 )
5
 set( slop_VERSION_MINOR 1 )
5
 set( slop_VERSION_MINOR 1 )
6
-set( slop_VERSION_PATCH 9 )
6
+set( slop_VERSION_PATCH 10 )
7
 
7
 
8
 set( BIN_TARGET     "${PROJECT_NAME}" )
8
 set( BIN_TARGET     "${PROJECT_NAME}" )
9
 set( CMAKE_INSTALL_PREFIX "/usr/bin" )
9
 set( CMAKE_INSTALL_PREFIX "/usr/bin" )

+ 10
- 1
README.md View File

82
 help
82
 help
83
 ----
83
 ----
84
 ```text
84
 ```text
85
-slop v3.1.9
85
+slop v3.1.10
86
 
86
 
87
 Copyright (C) 2014 Dalton Nell, Slop Contributors
87
 Copyright (C) 2014 Dalton Nell, Slop Contributors
88
 (https://github.com/naelstrof/slop/graphs/contributors)
88
 (https://github.com/naelstrof/slop/graphs/contributors)
152
     $ Y=$(echo $slopoutput | awk '{print $2}')
152
     $ Y=$(echo $slopoutput | awk '{print $2}')
153
     $ W=$(echo $slopoutput | awk '{print $3}')
153
     $ W=$(echo $slopoutput | awk '{print $3}')
154
     $ H=$(echo $slopoutput | awk '{print $4}')
154
     $ H=$(echo $slopoutput | awk '{print $4}')
155
+
156
+Tips
157
+    * You can use the arrow keys to move the starting point of a
158
+drag-selection, just in case you missed it by a few pixels.
159
+    * If you don't like a selection: you can cancel it by right-clicking
160
+regardless of which options are enabled or disabled for slop.
161
+    * If slop doesn't seem to select a window accurately, the problem could be
162
+because of decorations getting in the way. Try enabling the --nodecorations
163
+flag.
155
 ```
164
 ```

+ 1
- 1
src/cmdline.c View File

49
   "      --max=INT                 Set the maximum output of width or height\n                                  values. Setting min and max to the same value\n                                  disables drag selections.  (default=`0')",
49
   "      --max=INT                 Set the maximum output of width or height\n                                  values. Setting min and max to the same value\n                                  disables drag selections.  (default=`0')",
50
   "  -l, --highlight               Instead of outlining selections, slop\n                                  highlights it. This is only useful when\n                                  --color is set to a transparent color.\n                                  (default=off)",
50
   "  -l, --highlight               Instead of outlining selections, slop\n                                  highlights it. This is only useful when\n                                  --color is set to a transparent color.\n                                  (default=off)",
51
   "  -f, --format=STRING           Set the output format string. Format specifiers\n                                  are %x, %y, %w, %h, %i, %g, and %c.\n                                  (default=`X=%x\\nY=%y\\nW=%w\\nH=%h\\nG=%g\\nID=%i\\nCancel=%c\\n')",
51
   "  -f, --format=STRING           Set the output format string. Format specifiers\n                                  are %x, %y, %w, %h, %i, %g, and %c.\n                                  (default=`X=%x\\nY=%y\\nW=%w\\nH=%h\\nG=%g\\nID=%i\\nCancel=%c\\n')",
52
-  "\nExamples\n    $ # Gray, thick, transparent border for maximum visiblity.\n    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n\n    $ # Remove window decorations.\n    $ slop --nodecorations\n\n    $ # Disable window selections. Useful for selecting individual pixels.\n    $ slop -t 0\n\n    $ # Classic Windows XP selection.\n    $ slop -l -c 0.3,0.4,0.6,0.4\n\n    $ # Change output format to use safer parsing\n    $ slopoutput=$(slop -f \"%x %y %w %h\")\n    $ X=$(echo $slopoutput | awk '{print $1}')\n    $ Y=$(echo $slopoutput | awk '{print $2}')\n    $ W=$(echo $slopoutput | awk '{print $3}')\n    $ H=$(echo $slopoutput | awk '{print $4}')\n",
52
+  "\nExamples\n    $ # Gray, thick, transparent border for maximum visiblity.\n    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n\n    $ # Remove window decorations.\n    $ slop --nodecorations\n\n    $ # Disable window selections. Useful for selecting individual pixels.\n    $ slop -t 0\n\n    $ # Classic Windows XP selection.\n    $ slop -l -c 0.3,0.4,0.6,0.4\n\n    $ # Change output format to use safer parsing\n    $ slopoutput=$(slop -f \"%x %y %w %h\")\n    $ X=$(echo $slopoutput | awk '{print $1}')\n    $ Y=$(echo $slopoutput | awk '{print $2}')\n    $ W=$(echo $slopoutput | awk '{print $3}')\n    $ H=$(echo $slopoutput | awk '{print $4}')\n\nTips\n    * You can use the arrow keys to move the starting point of a\ndrag-selection, just in case you missed it by a few pixels.\n    * If you don't like a selection: you can cancel it by right-clicking\nregardless of which options are enabled or disabled for slop.\n    * If slop doesn't seem to select a window accurately, the problem could be\nbecause of decorations getting in the way. Try enabling the --nodecorations\nflag.\n",
53
     0
53
     0
54
 };
54
 };
55
 
55
 

+ 59
- 5
src/main.cpp View File

20
 #include <unistd.h>
20
 #include <unistd.h>
21
 #include <cstdio>
21
 #include <cstdio>
22
 #include <sstream>
22
 #include <sstream>
23
+
23
 #include "x.hpp"
24
 #include "x.hpp"
24
 #include "rectangle.hpp"
25
 #include "rectangle.hpp"
25
 #include "cmdline.h"
26
 #include "cmdline.h"
161
     *rey = y + h;
162
     *rey = y + h;
162
 }
163
 }
163
 
164
 
165
+// Some complicated key detection to replicate key repeating
166
+bool keyRepeat( KeySym key, double curtime, double repeatdelay, double* time, bool* memory ) {
167
+    if ( xengine->keyPressed( key ) != *memory ) {
168
+        if ( xengine->keyPressed( key ) ) {
169
+            *memory = true;
170
+            *time = curtime;
171
+            return true;
172
+        } else {
173
+            *memory = false;
174
+        }
175
+    }
176
+    if ( xengine->keyPressed( key ) && curtime - *time > repeatdelay ) {
177
+        return true;
178
+    }
179
+    return false;
180
+}
181
+
164
 int app( int argc, char** argv ) {
182
 int app( int argc, char** argv ) {
165
     gengetopt_args_info options;
183
     gengetopt_args_info options;
166
     int err = cmdline_parser( argc, argv, &options );
184
     int err = cmdline_parser( argc, argv, &options );
192
     bool keyboard = !options.nokeyboard_flag;
210
     bool keyboard = !options.nokeyboard_flag;
193
     bool decorations = !options.nodecorations_flag;
211
     bool decorations = !options.nodecorations_flag;
194
     timespec start, time;
212
     timespec start, time;
213
+    int xoffset = 0;
214
+    int yoffset = 0;
195
     int cx = 0;
215
     int cx = 0;
196
     int cy = 0;
216
     int cy = 0;
197
     int xmem = 0;
217
     int xmem = 0;
200
     int hmem = 0;
220
     int hmem = 0;
201
     int minimumsize = options.min_arg;
221
     int minimumsize = options.min_arg;
202
     int maximumsize = options.max_arg;
222
     int maximumsize = options.max_arg;
223
+    bool pressedMemory[4];
224
+    double pressedTime[4];
225
+    for ( int i=0;i<4;i++ ) {
226
+        pressedMemory[ i ] = false;
227
+        pressedTime[ i ] = 0;
228
+    }
203
     std::string format = options.format_arg;
229
     std::string format = options.format_arg;
204
     cmdline_parser_free( &options );
230
     cmdline_parser_free( &options );
205
 
231
 
228
         xengine->tick();
254
         xengine->tick();
229
         // If the user presses any key on the keyboard, exit the application.
255
         // If the user presses any key on the keyboard, exit the application.
230
         // Make sure at least gracetime has passed before allowing canceling
256
         // Make sure at least gracetime has passed before allowing canceling
231
-        double timei = double( time.tv_sec*1000000000L + time.tv_nsec )/1000000000.f;
232
-        double starti = double( start.tv_sec*1000000000L + start.tv_nsec )/1000000000.f;
233
-        if ( timei - starti > gracetime ) {
234
-            if ( ( xengine->anyKeyPressed() && keyboard ) || xengine->mouseDown( 3 ) ) {
257
+        double curtime = double( time.tv_sec*1000000000L + time.tv_nsec )/1000000000.f;
258
+        double starttime = double( start.tv_sec*1000000000L + start.tv_nsec )/1000000000.f;
259
+        if ( curtime - starttime > gracetime ) {
260
+            if ( keyRepeat( XK_Up, curtime, 0.5, &pressedTime[ 0 ], &pressedMemory[ 0 ] ) ) {
261
+                yoffset -= 1;
262
+            }
263
+            if ( keyRepeat( XK_Down, curtime, 0.5, &pressedTime[ 1 ], &pressedMemory[ 1 ] ) ) {
264
+                yoffset += 1;
265
+            }
266
+            if ( keyRepeat( XK_Left, curtime, 0.5, &pressedTime[ 2 ], &pressedMemory[ 2 ] ) ) {
267
+                xoffset -= 1;
268
+            }
269
+            if ( keyRepeat( XK_Right, curtime, 0.5, &pressedTime[ 3 ], &pressedMemory[ 3 ] ) ) {
270
+                xoffset += 1;
271
+            }
272
+            // If we pressed enter we move the state onward.
273
+            if ( xengine->keyPressed( XK_Return ) ) {
274
+                // If we're highlight windows, just select the active window.
275
+                if ( state == 0 ) {
276
+                    state = 1;
277
+                // If we're making a custom selection, select the custom selection.
278
+                } else if ( state == 2 ) {
279
+                    state = 3;
280
+                }
281
+            }
282
+            // If we press any key other than the arrow keys or enter key, we shut down!
283
+            if ( !( xengine->keyPressed( XK_Up ) || xengine->keyPressed( XK_Down ) || xengine->keyPressed( XK_Left ) || xengine->keyPressed( XK_Right ) ) &&
284
+                !( xengine->keyPressed( XK_Return ) ) &&
285
+                ( ( xengine->anyKeyPressed() && keyboard ) || xengine->mouseDown( 3 ) ) ) {
235
                 printSelection( format, true, 0, 0, 0, 0, None );
286
                 printSelection( format, true, 0, 0, 0, 0, None );
236
                 fprintf( stderr, "User pressed key. Canceled selection.\n" );
287
                 fprintf( stderr, "User pressed key. Canceled selection.\n" );
237
                 state = -1;
288
                 state = -1;
278
                 // Set the mouse position of where we clicked, used so that click tolerance doesn't affect the rectangle's position.
329
                 // Set the mouse position of where we clicked, used so that click tolerance doesn't affect the rectangle's position.
279
                 cx = xengine->m_mousex;
330
                 cx = xengine->m_mousex;
280
                 cy = xengine->m_mousey;
331
                 cy = xengine->m_mousey;
332
+                // Make sure we don't have un-seen applied offsets.
333
+                xoffset = 0;
334
+                yoffset = 0;
281
                 // Also remember where the original selection was
335
                 // Also remember where the original selection was
282
                 if ( selection ) {
336
                 if ( selection ) {
283
                     xmem = selection->m_x;
337
                     xmem = selection->m_x;
343
                 int sx, sy, ex, ey;
397
                 int sx, sy, ex, ey;
344
                 constrain( cx, cy, xengine->m_mousex, xengine->m_mousey, padding, minimumsize, maximumsize, &sx, &sy, &ex, &ey );
398
                 constrain( cx, cy, xengine->m_mousex, xengine->m_mousey, padding, minimumsize, maximumsize, &sx, &sy, &ex, &ey );
345
                 // Set the selection rectangle's dimensions to mouse movement.
399
                 // Set the selection rectangle's dimensions to mouse movement.
346
-                selection->setGeo( sx, sy, ex, ey );
400
+                selection->setGeo( sx + xoffset, sy + yoffset, ex, ey );
347
                 break;
401
                 break;
348
             }
402
             }
349
             case 3: {
403
             case 3: {

+ 5
- 0
src/options.ggo View File

85
 text "    $ Y=$(echo $slopoutput | awk '{print $2}')\n"
85
 text "    $ Y=$(echo $slopoutput | awk '{print $2}')\n"
86
 text "    $ W=$(echo $slopoutput | awk '{print $3}')\n"
86
 text "    $ W=$(echo $slopoutput | awk '{print $3}')\n"
87
 text "    $ H=$(echo $slopoutput | awk '{print $4}')\n"
87
 text "    $ H=$(echo $slopoutput | awk '{print $4}')\n"
88
+
89
+text "\nTips\n"
90
+text "    * You can use the arrow keys to move the starting point of a drag-selection, just in case you missed it by a few pixels.\n"
91
+text "    * If you don't like a selection: you can cancel it by right-clicking regardless of which options are enabled or disabled for slop.\n"
92
+text "    * If slop doesn't seem to select a window accurately, the problem could be because of decorations getting in the way. Try enabling the --nodecorations flag.\n"

+ 13
- 0
src/x.cpp View File

102
     return EXIT_SUCCESS;
102
     return EXIT_SUCCESS;
103
 }
103
 }
104
 
104
 
105
+bool slop::XEngine::keyPressed( KeySym key ) {
106
+    KeyCode keycode = XKeysymToKeycode( m_display, key );
107
+    if ( keycode != 0 ) {
108
+        // Get the whole keyboard state
109
+        char keys[32];
110
+        XQueryKeymap( m_display, keys );
111
+        // Check our keycode
112
+        return ( keys[ keycode / 8 ] & ( 1 << ( keycode % 8 ) ) ) != 0;
113
+    } else {
114
+        return false;
115
+    }
116
+}
117
+
105
 bool slop::XEngine::anyKeyPressed() {
118
 bool slop::XEngine::anyKeyPressed() {
106
     if ( !m_good ) {
119
     if ( !m_good ) {
107
         return false;
120
         return false;

+ 1
- 0
src/x.hpp View File

73
     int                 grabCursor( slop::CursorType type );
73
     int                 grabCursor( slop::CursorType type );
74
     int                 grabKeyboard();
74
     int                 grabKeyboard();
75
     bool                anyKeyPressed();
75
     bool                anyKeyPressed();
76
+    bool                keyPressed( KeySym key );
76
     int                 releaseCursor();
77
     int                 releaseCursor();
77
     int                 releaseKeyboard();
78
     int                 releaseKeyboard();
78
     void                setCursor( slop::CursorType type );
79
     void                setCursor( slop::CursorType type );