You are not logged in.

#1 2014-09-13 05:38:08

whoops
Member
Registered: 2009-03-19
Posts: 891

Mouse / screen edge => hotkeys (as compiz replacement)?

Hi!

I'm looking for something that lets me configure commands / keyboard shortcuts to be executed when I move my mouse to the screen edges / corners
P.E.: "top edge + mouse4 => [meta+x]; "top edge + mouse5" => [meta+y]; hover / touch top right corner: [alt+something]

(... because compiz lets me configure plugins like this but kde doesn't. And I need to replace compiz with something for a long while now because It's been falling apart more and more over the last few years. )

Offline

#2 2014-09-13 12:17:59

emeres
Member
Registered: 2013-10-08
Posts: 1,570

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

 Have you looked into xmousepos? A script with an infinite loops should take care of that.

Offline

#3 2014-09-13 13:02:35

whoops
Member
Registered: 2009-03-19
Posts: 891

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

Oh, yes, sorry, I forgot to mention that.

I already wasted many hours trying to write small shell scripts that catch mouse position + buttons + sending keyboard events. The result was always rather glitchy or CPU-intensive. I came to the conclusion that this should probably be handled by a program that is able to catch exactly the mouse events that are intended for it instead of all of them. And after trying to figure out how to open a panel-like qt-window that can send key combinations to kwin and failing miserably at writing even a simple test window that compiled properly I gave up. And now I'm here (again :3 I've been looking for a clean solution on and off again since https://bbs.archlinux.org/viewtopic.php?pid=1114383  ).

So there's no "real" / more elaborate program for that sort of thing?

Last edited by whoops (2014-09-13 13:04:02)

Offline

#4 2014-09-13 13:23:17

emeres
Member
Registered: 2013-10-08
Posts: 1,570

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

 Show what you have written so far. I am not aware of such a tool. Why not take a look at compiz source code concerning those events? I would also go through the source code of xmousepos and xdotool. If you get no further response here, either ask a moderator to move this thread to Programming and Scripting or start one there and reference to here.

Last edited by emeres (2014-09-13 13:24:12)

Offline

#5 2014-09-13 14:34:46

whoops
Member
Registered: 2009-03-19
Posts: 891

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

I didn't really get that far, just tried out a lot of different cmd tools that either catch or send x mouse/keyboard events. And I didn't manage to do anything usefull with them. Just from many failed experiments it looks to me as if the sort of program that could smoothly provide such "screen edge controls" would be WAY bigger and more complicated than what I'm able to scrap together.

Which is why I stopped trying to write something and started searching for a finished program that offers a solution.

Offline

#6 2014-09-13 15:46:17

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,456
Website

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

A program to provide such controls should not need to be that big.  I've only minimally tested this - so don't expect it to be of any use as is.  But this might be a starting point if you want to learn to work with Xlib:

/* compile: gcc -o program_name this_file.c -lX11 */
/* All code released to public domain ... use it to learn, don't expect
 * it to work */

#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>

static void buttonpress(XEvent *);
static void motionnotify(XEvent *);

static Display *dpy;
static Window root;
static int sw, sh;
static void (*handler[LASTEvent]) (XEvent *) = {
	[ButtonPress]       = buttonpress,
	[MotionNotify]      = motionnotify,
};

int main(int argc, const char **argv) {
	if (!(dpy=XOpenDisplay(0x0))) return 1;
	root = DefaultRootWindow(dpy);
	int scr = DefaultScreen(dpy);
	sw = DisplayWidth(dpy, scr);
	sh = DisplayHeight(dpy, scr);
	XSelectInput(dpy, root, ButtonPressMask | PointerMotionMask);
	XEvent ev;
	while (!XNextEvent(dpy,&ev))
		if (handler[ev.type])
			handler[ev.type](&ev);
	XCloseDisplay(dpy);
	return 0;
}

void buttonpress(XEvent *ev) {
	XButtonEvent *e = &ev->xbutton;
	if (e->window != root) return;
}

void motionnotify(XEvent *ev) {
	XMotionEvent *e = &ev->xmotion;
	static Time last = 0;
	Time now = e->time;
	if (now < last + 500) return; /* 500ms timeout between allowed events */
	last = now;
	if (e->window != root) return;
	else if (e->y > sh - 10) /* bottom of sreen */
		system("urxvt &");
	else if (e->x < 10 && e->y > 100 && e->y < sh - 100) /* left side middle */
		system("firefox &");
	XSync(dpy, True); /* discard 'repeats' */
}

EDIT: I'm not sure why I left buttonpress there as it does nothing - but it may be useful as the skeleton to add something that only responds to button presses at certain coordinates.  Also, I'm not sure how other programs such as a WM may interfere with the event reporting.  But I did test this as is on my WM, and I can launch both urxvt and firefox from their respective screen-edges.  These are admittedly quote artificial actions to chose, but personally I have no use for this, so I wasn't sure what actions might be useful - these were suitable for some basic testing.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#7 2014-09-13 15:48:04

emeres
Member
Registered: 2013-10-08
Posts: 1,570

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

 I am compiling right now, so it would be troublesome to determine accurate usage of ressources. Try this:

#!/bin/bash
RATE=0.25; TOL=2; LOOP=1;
RES=$(xrandr --current | awk '/*/{print $1}')
RESX=$(echo $RES | awk -F x '{print $1}')
RESY=$(echo $RES | awk -F x '{print $2}')
echo Resolution $RESX x $RESY;
while [ $LOOP ]; do
	POS=$(xmousepos | tr ' ' '|');
	POSX=$(echo $POS | awk -F \| '{print $1}');
	POSY=$(echo $POS | awk -F \| '{print $2}');
#	POSU=$(echo $POS | awk -F \| '{print $3}');
#	POSV=$(echo $POS | awk -F \| '{print $4}');
#	echo x$POSX y$POSY u$POSU v$POSV;
	sleep $RATE;
#	if [ $POSX -le $TOL ]; then echo Event mouse left edge; fi
	if [ $POSX -le $TOL ]; then echo Event mouse left edge; unset LOOP; fi
	if [ $POSX -ge $((RESX-TOL)) ]; then echo Event mouse right edge; fi
	if [ $POSY -le $TOL ]; then echo Event mouse top edge; fi
	if [ $POSY -ge $((RESY-TOL)) ]; then echo Event mouse bottom edge; fi
done;

 Adjust to your needs. It probably could be simplified.

Edit: Ah, Trilby took care of that.

Last edited by emeres (2014-09-13 15:49:02)

Offline

#8 2014-09-13 15:50:19

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,456
Website

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

Emeres, I think that would be a horrible resource drain as is.  But it does give me an idea for a much better approach to doing this with Xlib.  Stand by ...

--mod note: moving to programming & scripting--

EDIT: the following is a different approach than my previous example.  It is a bit simpler in code, but it may be more resource intensive as it is polling for the pointer position every 250ms.  The first version above, didn't poll, but depending on the 'average' amount of mouse movement it could also be inefficient as it responds to every single mouse motion event then figures out if it should care about them.

/* compile: gcc -o program_name this_file.c -lX11 */
/* All code released to public domain ... use it to learn, don't expect
 * it to work */

#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>

int main(int argc, const char **argv) {
	Display *dpy;
	if (!(dpy=XOpenDisplay(0x0))) return 1;
	int scr, sw, sh, x, y, ig, px, py;
	Window root, wig;
	scr = DefaultScreen(dpy);
	root = DefaultRootWindow(dpy);
	sw = DisplayWidth(dpy, scr);
	sh = DisplayHeight(dpy, scr);
	for (;;) {
		XQueryPointer(dpy, root, &wig, &wig, &x, &y, &ig, &ig, &ig);
		if (x == px && y == py) { /* hasn't moved */
			/* for now ignore "hovering"; return to avoid repeating next checks */
			continue;
		}
		px = x; py = y;
		if (y > sh - 10) system("urxvt &");
		else if (x < 10) system("firefox &");
		usleep(250000);
	}
	XCloseDisplay(dpy);
	return 0;
}

Last edited by Trilby (2014-09-13 16:06:36)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#9 2014-09-13 18:31:47

emeres
Member
Registered: 2013-10-08
Posts: 1,570

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

 @Trilby I am not fluent in Xlib and similar, is there a function that checks for events reported from X? Like mouse movement? If I read it correctly, that would run non-stop the if conjunction. I would add the usleep before continue also, or move it at the beginning of the loop, but that would slow does the first reaction, although probably irrelevant.

Edit: clarification.

Last edited by emeres (2014-09-13 18:32:34)

Offline

#10 2014-09-13 19:01:43

whoops
Member
Registered: 2009-03-19
Posts: 891

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

Thanks!


Regarding shell implementations: It's been a while, but I'll try to remember some of the problems I ran into and which made me come to the conclusion that a script isn't the right angle to tackle the problem:
- The poll intervall that is needed so button presses aren't missed is too low to be cpu friendly
- Mouse wheel is even worse. Needs some kind of buffer + limiter too, because otherwise something between the program that sends the keyboard events and the window manager or whatever it is that catches them might oveflow / freeze / something
- Leads to all kind of weird behaviour when applications try to grab raw input
- Goes totally nuts / needs to kill itself if an application sets mouse to that wrap around mode thing that I don't know how it's called or works...
- Various weird behaviour on resolution changes need to be considered depending on which shell tools are used and how
- Also there were lots of other small issues
- And the more problems I solved, the more cpu it needed until in the end it was absolutely unviable and I had to start over / quit

And regarding a potential xlib c (or is that c++?) implementation: I'll needs to look at that snippet for a few hours before I can tell for sure, but on a first glance I'm almost sure I'm falling about 2 years worth of regular C / graphical / whatever programming experience short of being able to work with xlib + raw input stuff or whatever that is and reading some xlib docs for a few hours probably won't put a dent in that. I briefly tried modifying "xev" to suit my needs about a year ago and that didn't go too well - gave up because I was fairly certain that by the time I'd be finished learning x + xlib stuff everyone'd be using wayland. (I'm NOT that sort of "programmer"; more of a "scripter" if at all. As a rule of thumb: if it's supposed to be run on a headless server, parses text, moves files or writes into a database, I might be able to modify it or even write it. If on the other hand it has "pointers" or "h-files", then as soon as I change the code in any way it will never ever compile again no matter for how long I google the error message. :3 )

So... I guess that means noone knows if there's a "hot-bar-panel" or anything that captures mouse input on the screen edge hiding somewhere in AUR or on github? hmm

Last edited by whoops (2014-09-13 19:06:38)

Offline

#11 2014-09-13 19:15:48

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,456
Website

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

@Emeres, in the first example XNextEvent is the function that grabs (as the name implies) the next event available from the XServer.  Before this function will do anything, though, the program must register what kind of events it's interested in receiving.  This was done with XSelectInput.  In the second example I bypassed all of this and followed a logic just like your script, but using xlib directly rather than a script calling a program to open a connection to xlib, access xlib, close the connection to xlib, and repeat over and over.  The XQueryPointer funtion Queries the XServer for information about the location of the mouse pointer.

@Whoops, there is 'brightside' in the AUR that seems to be for this purpose - but I know nothing about it.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#12 2014-09-13 19:26:21

emeres
Member
Registered: 2013-10-08
Posts: 1,570

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

 Right, for unknown reasons I concentrated only on your second example, which is much easier to follow. Testing brightside now, looks promising, although it concentrates on corners only apparently*.

Edit: *At least for the [custom] functions.

Edit2: By the way whoops, have you seen easystroke? Maybe that would work for you. It can recognize applications in focus, making it even more customizable, but obviously uses gestures and buttons as input.

Last edited by emeres (2014-09-13 19:50:22)

Offline

#13 2014-09-14 08:20:22

whoops
Member
Registered: 2009-03-19
Posts: 891

Re: Mouse / screen edge => hotkeys (as compiz replacement)?

The last time I tried brightside it wouldn't compile and then I forgot about it... I'll give it another go, thanks!

easystroke or using mouse gestures in general might be worth a try too... I'm very accustomed to used the top edge quickly for various things, but I guess gestures are still better than having to switch to some older LTS once compiz stops working for good with arch... so I'll broaden my search and try all the mouse gesture programs I can find next.

Offline

Board footer

Powered by FluxBB