diff --git a/src/keyboard.cpp b/src/keyboard.cpp index cd91d94..0458f0a 100644 --- a/src/keyboard.cpp +++ b/src/keyboard.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include "keyboard.hpp" bool slop::Keyboard::getKey( KeySym key ) { @@ -24,20 +26,19 @@ bool slop::Keyboard::anyKeyDown() { void slop::Keyboard::update() { char keys[32]; + KeyCode keycode; XQueryKeymap( x11->display, keys ); + // We first delete the arrow key buttons from the mapping. // This allows the user to press the arrow keys without triggering anyKeyDown - KeyCode keycode = XKeysymToKeycode( x11->display, XK_Left ); - keys[ keycode / 8 ] = keys[ keycode / 8 ] & ~( 1 << ( keycode % 8 ) ); - keycode = XKeysymToKeycode( x11->display, XK_Right ); - keys[ keycode / 8 ] = keys[ keycode / 8 ] & ~( 1 << ( keycode % 8 ) ); - keycode = XKeysymToKeycode( x11->display, XK_Up ); - keys[ keycode / 8 ] = keys[ keycode / 8 ] & ~( 1 << ( keycode % 8 ) ); - keycode = XKeysymToKeycode( x11->display, XK_Down ); - keys[ keycode / 8 ] = keys[ keycode / 8 ] & ~( 1 << ( keycode % 8 ) ); + for ( size_t i = 0; i < 4; i++) { + keycode = XKeysymToKeycode( x11->display, keyAdjust.at(i)); + keys[ keycode / 8 ] = keys[ keycode / 8 ] & ~( 1 << ( keycode % 8 ) ); + } // Also deleting Space for move operation - keycode = XKeysymToKeycode( x11->display, XK_space ); + keycode = XKeysymToKeycode( x11->display, keyMove ); keys[ keycode / 8 ] = keys[ keycode / 8 ] & ~( 1 << ( keycode % 8 ) ); + keyDown = false; for ( int i=0;i<32;i++ ) { if ( deltaState[i] == keys[i] ) { @@ -56,8 +57,10 @@ void slop::Keyboard::update() { } } -slop::Keyboard::Keyboard( X11* x11 ) { +slop::Keyboard::Keyboard( X11* x11 , KeySym keyMove, std::vector keyAdjust) { this->x11 = x11; + this->keyMove = keyMove; + this->keyAdjust = keyAdjust; int err = XGrabKeyboard( x11->display, x11->root, False, GrabModeAsync, GrabModeAsync, CurrentTime ); int tries = 0; while( err != GrabSuccess && tries < 5 ) { diff --git a/src/keyboard.hpp b/src/keyboard.hpp index 61d22eb..41196b7 100644 --- a/src/keyboard.hpp +++ b/src/keyboard.hpp @@ -23,8 +23,10 @@ #define XK_MISCELLANY #define XK_LATIN1 // for XK_space -#include +#define XK_MISCELLANY // for modifier KeySyms +#include +#include #include "x.hpp" namespace slop { @@ -34,8 +36,15 @@ class Keyboard { char deltaState[32]; X11* x11; bool keyDown; + + // KeySym to move the selection window + KeySym keyMove; + + // KeySyms to adjust selection window + // in the order of Left Down Up Right + std::vector keyAdjust; public: - Keyboard( X11* x11 ); + Keyboard( X11* x11 , KeySym keyMove, std::vector keyAdjust); ~Keyboard(); void update(); bool getKey( KeySym key ); diff --git a/src/main.cpp b/src/main.cpp index 4bcb4ec..62d3610 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,8 +27,61 @@ #include "slop.hpp" #include "cxxopts.hpp" +#include +#include "x.hpp" + using namespace slop; +std::vector parseAdjustKeys( std::string value ) { + std::string valuecopy = value; + std::vector found; + std::string delimiter = ","; + std::string::size_type sz; + std::string keysymString; + char* keysymChars; + KeySym keysym; + bool validity = true; + try { + sz = value.find(delimiter); + keysymString = value.substr(0, sz); + keysymChars = &keysymString[0]; + keysym = XStringToKeysym(keysymChars); + found.push_back(keysym); + value = value.substr(sz + delimiter.size()); + validity = validity && keysym; + + sz = value.find(delimiter); + keysymString = value.substr(0, sz); + keysymChars = &keysymString[0]; + keysym = XStringToKeysym(keysymChars); + found.push_back(keysym); + value = value.substr(sz + delimiter.size()); + validity = validity && keysym; + + sz = value.find(delimiter); + keysymString = value.substr(0, sz); + keysymChars = &keysymString[0]; + keysym = XStringToKeysym(keysymChars); + found.push_back(keysym); + value = value.substr(sz + delimiter.size()); + validity = validity && keysym; + + keysymString = value; + keysymChars = &keysymString[0]; + keysym = XStringToKeysym(keysymChars); + found.push_back(keysym); + validity = validity && keysym; + + if ( !validity ) throw std::runtime_error("dur"); + } catch ( ... ) { + throw std::invalid_argument("Unable to parse value `" + + valuecopy + + "` as a series of keysyms. Should be something like Left,Down,Up,Right"); + } + + return found; +} + glm::vec4 parseColor( std::string value ) { std::string valuecopy = value; glm::vec4 found; @@ -108,6 +161,20 @@ SlopOptions* getOptions( cxxopts::Options& options ) { throw std::invalid_argument( "--nodecorations must be between 0 and 2. Or be used as a flag." ); } } + if ( options.count( "movekey" ) > 0 ) { + const char* keyMove = &options["movekey"].as()[0]; + KeySym keysym = XStringToKeysym(keyMove); + foo->keyMove = keysym; + if ( keysym == 0 ) + throw std::invalid_argument("Unable to parse value `" + + options["movekey"].as() + + "` as a keysym."); + } + std::vector keyAdjust { XK_Up, XK_Down, XK_Up, XK_Right }; + if ( options.count( "adjustkey" ) > 0 ) { + keyAdjust = parseAdjustKeys( options["adjustkey"].as() ); + } + foo->keyAdjust = keyAdjust; return foo; } @@ -203,6 +270,11 @@ void printHelp() { std::cout << " and %% for a literal percent sign.\n"; std::cout << " (default=`%g')\n"; std::cout << " -o, --noopengl Disable graphics acceleration.\n"; + std::cout << " -m, --keymove=KEYSYM Set move key, hold move key while selecting\n"; + std::cout << " to move selection box.\n"; + std::cout << " -a, --keyadjust=KEYSYM,KEYSYM,KEYSYM,KEYSYM\n"; + std::cout << " Set adjustment key, moves the corner\n"; + std::cout << " opposite to the mouse corner.\n"; std::cout << "Examples\n"; std::cout << " $ # Gray, thick, transparent border for maximum visiblity.\n"; std::cout << " $ slop -b 20 -c 0.5,0.5,0.5,0.8\n"; @@ -246,6 +318,8 @@ int app( int argc, char** argv ) { ("q,quiet", "Disable any unnecessary cerr output. Any warnings or info simply won't print.") ("k,nokeyboard", "Disables the ability to cancel selections with the keyboard.") ("o,noopengl", "Disables graphics hardware acceleration.") + ("m,movekey", "Set move key, hold move key while selecting to move selection box", cxxopts::value()) + ("a,adjustkey", "Set adjustment key, moves the corner opposite to the mouse corner", cxxopts::value()) ("positional", "Positional parameters", cxxopts::value>()) ; options.parse_positional("positional"); diff --git a/src/slop.cpp b/src/slop.cpp index 1181f81..c09ad44 100644 --- a/src/slop.cpp +++ b/src/slop.cpp @@ -111,7 +111,7 @@ slop::SlopSelection slop::SlopSelect( slop::SlopOptions* options ) { x11 = new X11(options->xdisplay); if ( !options->nokeyboard ) { XErrorHandler ph = XSetErrorHandler(slop::TmpXError); - keyboard = new Keyboard( x11 ); + keyboard = new Keyboard( x11, options->keyMove, options->keyAdjust ); XSetErrorHandler(ph); } #ifdef SLOP_OPENGL diff --git a/src/slop.hpp b/src/slop.hpp index 6b40946..07ecacb 100644 --- a/src/slop.hpp +++ b/src/slop.hpp @@ -20,6 +20,9 @@ #ifndef N_SLOP_H_ #define N_SLOP_H_ +#include +#include "x.hpp" +#include // Here we make some C-styled structs and function definitions, // allows other people to have a pure C interface to slop. @@ -74,6 +77,8 @@ class SlopOptions { float b; float a; char* xdisplay; + KeySym keyMove; + std::vector keyAdjust; }; class SlopSelection { diff --git a/src/slopstates.cpp b/src/slopstates.cpp index 503d38d..1b3517a 100644 --- a/src/slopstates.cpp +++ b/src/slopstates.cpp @@ -3,6 +3,8 @@ using namespace slop; slop::SlopMemory::SlopMemory( SlopOptions* options, Rectangle* rect ) { + this->keyMove = options->keyMove; + this->keyAdjust = options->keyAdjust; up = false; running = true; state = (SlopState*)new SlopStart(); @@ -128,13 +130,13 @@ void slop::SlopStartDrag::update( SlopMemory& memory, double dt ) { } if ( keyboard ) { - if ( keyboard->getKey(XK_space) ) { + if ( keyboard->getKey(memory.keyMove) ) { memory.setState( (SlopState*)new SlopStartMove( startPoint, mouse->getMousePos() ) ); return; } int arrows[2]; - arrows[0] = keyboard->getKey(XK_Down)-keyboard->getKey(XK_Up); - arrows[1] = keyboard->getKey(XK_Right)-keyboard->getKey(XK_Left); + arrows[0] = keyboard->getKey(memory.keyAdjust[1])-keyboard->getKey(memory.keyAdjust[2]); + arrows[1] = keyboard->getKey(memory.keyAdjust[3])-keyboard->getKey(memory.keyAdjust[0]); if ( arrows[0] || arrows[1] ) { if ( repeatTimer == 0 || repeatTimer > .4 ) { startPoint.y += arrows[0]*multiplier; @@ -179,7 +181,7 @@ void slop::SlopStartMove::update( SlopMemory& memory, double dt ) { // space or mouse1 released, return to drag // if mouse1 is released then drag will end also - if ( !keyboard->getKey(XK_space) or (!mouse->getButton( 1 ) && !memory.nodrag) ) { + if ( !keyboard->getKey(memory.keyMove) or (!mouse->getButton( 1 ) && !memory.nodrag) ) { // clip rectangle on edges of screen. startPoint.x = glm::min((int)startPoint.x, WidthOfScreen(x11->screen)); startPoint.x = glm::max((int)startPoint.x, 0); diff --git a/src/slopstates.hpp b/src/slopstates.hpp index 4e2ce4f..ff99937 100644 --- a/src/slopstates.hpp +++ b/src/slopstates.hpp @@ -27,6 +27,10 @@ #include "rectangle.hpp" +#include +#include +#include "x.hpp" + namespace slop { class SlopMemory; @@ -57,7 +61,7 @@ class SlopStartDrag : SlopState { float repeatTimer; float multiplier; public: - SlopStartDrag( glm::vec2 point ); + SlopStartDrag( glm::vec2 point); virtual void onEnter( SlopMemory& memory ); virtual void update( SlopMemory& memory, double dt ); }; @@ -90,6 +94,8 @@ class SlopMemory { bool nodrag; bool up; Rectangle* rectangle; + KeySym keyMove; + std::vector keyAdjust; void setState( SlopState* state ); void update( double dt ); void draw( glm::mat4& matrix );