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 9 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,7 +3,7 @@ cmake_minimum_required( VERSION 2.8 )
3 3
 project( "slop" )
4 4
 set( slop_VERSION_MAJOR 3 )
5 5
 set( slop_VERSION_MINOR 1 )
6
-set( slop_VERSION_PATCH 9 )
6
+set( slop_VERSION_PATCH 10 )
7 7
 
8 8
 set( BIN_TARGET     "${PROJECT_NAME}" )
9 9
 set( CMAKE_INSTALL_PREFIX "/usr/bin" )

+ 10
- 1
README.md View File

@@ -82,7 +82,7 @@ Make sure to check out and install [maim](https://github.com/naelstrof/maim) too
82 82
 help
83 83
 ----
84 84
 ```text
85
-slop v3.1.9
85
+slop v3.1.10
86 86
 
87 87
 Copyright (C) 2014 Dalton Nell, Slop Contributors
88 88
 (https://github.com/naelstrof/slop/graphs/contributors)
@@ -152,4 +152,13 @@ Examples
152 152
     $ Y=$(echo $slopoutput | awk '{print $2}')
153 153
     $ W=$(echo $slopoutput | awk '{print $3}')
154 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,7 +49,7 @@ const char *gengetopt_args_info_help[] = {
49 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 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 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 53
     0
54 54
 };
55 55
 

+ 59
- 5
src/main.cpp View File

@@ -20,6 +20,7 @@
20 20
 #include <unistd.h>
21 21
 #include <cstdio>
22 22
 #include <sstream>
23
+
23 24
 #include "x.hpp"
24 25
 #include "rectangle.hpp"
25 26
 #include "cmdline.h"
@@ -161,6 +162,23 @@ void constrain( int sx, int sy, int ex, int ey, int padding, int minimumsize, in
161 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 182
 int app( int argc, char** argv ) {
165 183
     gengetopt_args_info options;
166 184
     int err = cmdline_parser( argc, argv, &options );
@@ -192,6 +210,8 @@ int app( int argc, char** argv ) {
192 210
     bool keyboard = !options.nokeyboard_flag;
193 211
     bool decorations = !options.nodecorations_flag;
194 212
     timespec start, time;
213
+    int xoffset = 0;
214
+    int yoffset = 0;
195 215
     int cx = 0;
196 216
     int cy = 0;
197 217
     int xmem = 0;
@@ -200,6 +220,12 @@ int app( int argc, char** argv ) {
200 220
     int hmem = 0;
201 221
     int minimumsize = options.min_arg;
202 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 229
     std::string format = options.format_arg;
204 230
     cmdline_parser_free( &options );
205 231
 
@@ -228,10 +254,35 @@ int app( int argc, char** argv ) {
228 254
         xengine->tick();
229 255
         // If the user presses any key on the keyboard, exit the application.
230 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 286
                 printSelection( format, true, 0, 0, 0, 0, None );
236 287
                 fprintf( stderr, "User pressed key. Canceled selection.\n" );
237 288
                 state = -1;
@@ -278,6 +329,9 @@ int app( int argc, char** argv ) {
278 329
                 // Set the mouse position of where we clicked, used so that click tolerance doesn't affect the rectangle's position.
279 330
                 cx = xengine->m_mousex;
280 331
                 cy = xengine->m_mousey;
332
+                // Make sure we don't have un-seen applied offsets.
333
+                xoffset = 0;
334
+                yoffset = 0;
281 335
                 // Also remember where the original selection was
282 336
                 if ( selection ) {
283 337
                     xmem = selection->m_x;
@@ -343,7 +397,7 @@ int app( int argc, char** argv ) {
343 397
                 int sx, sy, ex, ey;
344 398
                 constrain( cx, cy, xengine->m_mousex, xengine->m_mousey, padding, minimumsize, maximumsize, &sx, &sy, &ex, &ey );
345 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 401
                 break;
348 402
             }
349 403
             case 3: {

+ 5
- 0
src/options.ggo View File

@@ -85,3 +85,8 @@ text "    $ X=$(echo $slopoutput | awk '{print $1}')\n"
85 85
 text "    $ Y=$(echo $slopoutput | awk '{print $2}')\n"
86 86
 text "    $ W=$(echo $slopoutput | awk '{print $3}')\n"
87 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,6 +102,19 @@ int slop::XEngine::init( std::string display ) {
102 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 118
 bool slop::XEngine::anyKeyPressed() {
106 119
     if ( !m_good ) {
107 120
         return false;

+ 1
- 0
src/x.hpp View File

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