I liked this howto because it allowed me to get the back/forward buttons working in firefox AND nautilus. However, I missed imwheel's ability to specify different key events for different applications/windows. So I decided to write my own hack to solve this problem.
First I wrote a little program to query window information. If anyone is interested and know of a free file storage location I'll upload the program.
For the curious/ambitious, the source is posted at the end. The name of the program is 'qawn' (Query Active Window Name).
So this is what my .xbindkeysrc looks like:
Code:
# Back Button
"/usr/local/bin/mouse-back-button.sh"
b:8
# Forward Button
"/usr/local/bin/mouse-forward-button.sh"
b:9
And here is the mouse-back-button.sh script:
Code:
#!/bin/bash
#
# generate key events based on window criteria
# Control_L + Page_Up
qawn -p | egrep -i "gnome-terminal"
if [ $? -eq 0 ]; then
/usr/bin/xvkbd -xsendevent -text "\[Control_L]\[Page_Up]" &
exit 0
fi
# Default: Alt_L + Left
/usr/bin/xvkbd -xsendevent -text "\[Alt_L]\[Left]" &
exit 0
The mouse-forward-button.sh looks identical except for the key events that it generates. So now when I want to bind the back/forward buttons for a new application I just have to edit these two scripts. It's pretty nifty because I can have my cake (firefox + nautilus) and eat it too (gnome-terminal et al).
Here is the source:
Code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
void usage(char *progname)
{
char *shortname = rindex(progname, '/');
if (!shortname) {
shortname = progname;
}
else {
shortname++;
}
printf("%s <options>\n", shortname);
printf(" -p --process-name Query for the active window's process name\n");
printf(" -c --process-class Query for the active window's process class\n");
printf(" -n --name Query for the active window's name (title)\n");
}
typedef enum {
PROCESS_NAME,
PROCESS_CLASS,
NAME,
UNKNOWN
} QUERY_TYPE;
int main(int argc, char **argv)
{
if (argc != 2) {
usage(argv[0]);
exit(1);
}
QUERY_TYPE qt = UNKNOWN;
if (!strcmp(argv[1], "--process-name") || !strcmp(argv[1], "-p")) {
qt = PROCESS_NAME;
}
else if (!strcmp(argv[1], "--process-class") || !strcmp(argv[1], "-c")) {
qt = PROCESS_CLASS;
}
else if (!strcmp(argv[1], "--name") || !strcmp(argv[1], "-n")) {
qt = NAME;
}
if (qt == UNKNOWN) {
usage(argv[0]);
exit(1);
}
Display *display;
char *envDisplay = getenv("DISPLAY");
if (!envDisplay) {
fprintf(stderr, "Unable to query DISPLAY environment variable!\n");
exit(1);
}
display = XOpenDisplay(envDisplay);
if (!display) {
fprintf(stderr, "Unable to open display (%s)!\n", envDisplay);
exit(1);
}
Window w;
int rtr;
XGetInputFocus(display, &w, &rtr);
if (qt == PROCESS_NAME || qt == PROCESS_CLASS) {
XClassHint xch;
Status rc = XGetClassHint(display, w, &xch);
if (rc == BadWindow) {
fprintf(stderr, "XGetClassHint returned BadWindow error!\n");
exit(1);
}
// output what we've found
if (qt == PROCESS_NAME && xch.res_name) {
printf("%s\n", xch.res_name);
}
else if (xch.res_class) {
printf("%s\n", xch.res_class);
}
if (xch.res_name) {
XFree(xch.res_name);
}
if (xch.res_class) {
XFree(xch.res_class);
}
}
else if (qt == NAME) {
char *name;
Status rc = XFetchName(display, w, &name);
if (rc == BadWindow) {
fprintf(stderr, "XFetchName returned BadWindow error!\n");
exit(1);
}
// output what we've found
if (name) {
printf("%s\n", name);
XFree(name);
}
}
// cleanup
XCloseDisplay(display);
return 0;
}
Here is the makefile:
Code:
all:
g++ main.cpp -g -o qawn `pkg-config --cflags --libs vte`
clean:
rm -f qawn
install: all
cp -f qawn /usr/local/bin
uninstall:
rm -f /usr/local/bin/qawn
Bookmarks