summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md28
-rw-r--r--config.h31
-rw-r--r--xmouseless.c83
3 files changed, 114 insertions, 28 deletions
diff --git a/README.md b/README.md
index 00d0389..1ad5b8c 100644
--- a/README.md
+++ b/README.md
@@ -2,15 +2,14 @@
This program is a replacement for the physical mouse in X11.
-It aims to be simple and efficient.
-
Features:
- move the mouse with different speeds
- click and grab
+- scroll
- execute shell commands
-## Installation
+## Installation
```
make
sudo make install
@@ -22,14 +21,25 @@ Debian based distros:
sudo apt-get install libx11-dev libxtst-dev
```
-## Configuration
-
-Edit config.h and reinstall. The configuration file should be self explaining.
-
## Usage
When starting xmouseless, it grabs the keyboard and all defined bindings are
available. When pressing an exit key, the program exits.
-You probably want to define a key binding for xmouseless in your desktop
-environment or window manager.
+The usage is quite intuitive and with some practice, you can move the pointer to
+a specific location very fast. Basically, you move the pointer by pressing some
+keys (the defaults are i, k, j and l for up, down, left and right)
+and change the speed by pressing modifier keys.
+The keys f, d and s (by default) are used to simulate mouse clicks and grabbing.
+With some other keys, you can scroll up, down, left and right and execute
+previously defined shell commands.
+
+You probably want to define a key binding to start xmouseless.
+
+
+## Configuration
+
+The configuration is done in config.h, which is a C header file,
+but you don't need any programming knowledge to edit it.
+After you edited the file, you have to run make again.
+
diff --git a/config.h b/config.h
index bd8b941..7164980 100644
--- a/config.h
+++ b/config.h
@@ -1,11 +1,14 @@
-/* the rate at which the mouse moves in Hz */
+/* the rate at which the mouse moves in Hz
+ * does not change its speed */
static const unsigned int move_rate = 50;
-/* the speed with no modifier (pixels per second) */
+/* the default speed of the mouse pointer
+ * in pixels per second */
static const unsigned int default_speed = 500;
-static SpeedBindings speed_bindings[] = {
+/* changes the speed of the mouse pointer */
+static SpeedBinding speed_bindings[] = {
/* key speed */
{ XK_Super_L, 3000 },
{ XK_Alt_L, 1500 },
@@ -13,7 +16,8 @@ static SpeedBindings speed_bindings[] = {
{ XK_Control_L, 10 },
};
-/* you can also add any other direction (e.g. diagonals) */
+/* moves the mouse pointer
+ * you can also add any other direction (e.g. diagonals) */
static MoveBinding move_bindings[] = {
/* key x y */
{ XK_j, -1, 0 },
@@ -24,19 +28,28 @@ static MoveBinding move_bindings[] = {
/* 1: left
* 2: middle
- * 3: right
- * 4: scroll up
- * 5: scroll down */
+ * 3: right */
static ClickBinding click_bindings[] = {
/* key button */
{ XK_space, 1 },
{ XK_f, 1 },
{ XK_d, 2 },
{ XK_s, 3 },
- { XK_plus, 4 },
- { XK_minus, 5 },
};
+/* scrolls up, down, left and right
+ * a higher value scrolls faster */
+static ScrollBinding scroll_bindings[] = {
+ /* key x y */
+ { XK_n, 0 , 25 },
+ { XK_p, 0 , -25 },
+ { XK_plus, 0 , 80 },
+ { XK_minus, 0 , -80 },
+ { XK_h, 25, 0 },
+ { XK_g, -25, 0 },
+};
+
+/* executes shell commands */
static ShellBinding shell_bindings[] = {
/* key command */
{ XK_b, "wmctrl -a firefox" },
diff --git a/xmouseless.c b/xmouseless.c
index 8a52bc3..a187890 100644
--- a/xmouseless.c
+++ b/xmouseless.c
@@ -27,8 +27,14 @@ typedef struct {
typedef struct {
KeySym keysym;
+ float x;
+ float y;
+} ScrollBinding;
+
+typedef struct {
+ KeySym keysym;
unsigned int speed;
-} SpeedBindings;
+} SpeedBinding;
typedef struct {
KeySym keysym;
@@ -52,10 +58,19 @@ struct {
float speed_y;
} mouseinfo;
+struct {
+ float x;
+ float y;
+ float speed_x;
+ float speed_y;
+} scrollinfo;
+
void get_pointer();
-void moverelative(float x, float y);
+void move_relative(float x, float y);
void click(unsigned int button, Bool is_press);
+void click_full(unsigned int button);
+void scroll(float x, float y);
void handle_key(XKeyEvent event);
void init_x();
void close_x();
@@ -71,7 +86,7 @@ void get_pointer() {
mouseinfo.y = y;
}
-void moverelative(float x, float y) {
+void move_relative(float x, float y) {
mouseinfo.x += x;
mouseinfo.y += y;
XWarpPointer(dpy, None, root, 0, 0, 0, 0,
@@ -80,10 +95,37 @@ void moverelative(float x, float y) {
}
void click(unsigned int button, Bool is_press) {
- XTestFakeButtonEvent(dpy, button, is_press, 0);
+ XTestFakeButtonEvent(dpy, button, is_press, CurrentTime);
+ XFlush(dpy);
+}
+
+void click_full(unsigned int button) {
+ XTestFakeButtonEvent(dpy, button, 1, CurrentTime);
+ XTestFakeButtonEvent(dpy, button, 0, CurrentTime);
XFlush(dpy);
}
+void scroll(float x, float y) {
+ scrollinfo.x += x;
+ scrollinfo.y += y;
+ while (scrollinfo.y <= -0.51) {
+ scrollinfo.y += 1;
+ click_full(4);
+ }
+ while (scrollinfo.y >= 0.51) {
+ scrollinfo.y -= 1;
+ click_full(5);
+ }
+ while (scrollinfo.x <= -0.51) {
+ scrollinfo.x += 1;
+ click_full(6);
+ }
+ while (scrollinfo.x >= 0.51) {
+ scrollinfo.x -= 1;
+ click_full(7);
+ }
+}
+
void init_x() {
int i;
int screen;
@@ -101,8 +143,9 @@ void init_x() {
/* grab keys until success */
for (i = 0; i < 100; i++) {
if (XGrabKeyboard(dpy, root, False, GrabModeAsync,
- GrabModeAsync, CurrentTime) == GrabSuccess)
+ GrabModeAsync, CurrentTime) == GrabSuccess) {
return;
+ }
usleep(10000);
}
@@ -118,12 +161,18 @@ void close_x(int exit_status) {
exit(exit_status);
}
-void *moveforever(void *val) {
+void *move_forever(void *val) {
/* this function is executed in a seperate thread */
while (1) {
+ /* move mouse? */
if (mouseinfo.speed_x != 0 || mouseinfo.speed_y != 0) {
- moverelative((float) mouseinfo.speed_x * speed / move_rate,
- (float) mouseinfo.speed_y * speed / move_rate);
+ move_relative((float) mouseinfo.speed_x * speed / move_rate,
+ (float) mouseinfo.speed_y * speed / move_rate);
+ }
+ /* scroll? */
+ if (scrollinfo.speed_x != 0 || scrollinfo.speed_y != 0) {
+ scroll((float) scrollinfo.speed_x / move_rate,
+ (float) scrollinfo.speed_y / move_rate);
}
usleep(1000000 / move_rate);
}
@@ -162,6 +211,15 @@ void handle_key(XKeyEvent event) {
}
}
+ /* scroll bindings */
+ for (i = 0; i < LENGTH(scroll_bindings); i++) {
+ if (scroll_bindings[i].keysym == keysym) {
+ int sign = is_press ? 1 : -1;
+ scrollinfo.speed_x += sign * scroll_bindings[i].x;
+ scrollinfo.speed_y += sign * scroll_bindings[i].y;
+ }
+ }
+
/* shell and exit bindings only on key release */
if (!is_press) {
/* shell bindings */
@@ -195,8 +253,13 @@ int main () {
mouseinfo.speed_y = 0;
speed = default_speed;
- // start the thread for mouse movement
- rc = pthread_create(&movethread, NULL, &moveforever, NULL);
+ scrollinfo.x = 0;
+ scrollinfo.y = 0;
+ scrollinfo.speed_x = 0;
+ scrollinfo.speed_y = 0;
+
+ /* start the thread for mouse movement and scrolling */
+ rc = pthread_create(&movethread, NULL, &move_forever, NULL);
if( rc != 0 ) {
printf("Unable to start thread.\n");
return EXIT_FAILURE;