So, being a Windows luser, I enjoy being able to use the menu key to run things and also open the menu. I wanted to make the Pandora key do something similar, but I ran into a few stumbling blocks. The event daemon only runs key scripts when you release the key, so I had to modify that a little. Also, I am not a programmer, so my implementation is probably very stupid and inefficient. I will post it here though, so you guys can use it or make improvements or whatever.
For those who don't want to muck about with compiling things, I will attach both files (pndevmapperd and pndhotkey) in an archive. You will want to
You will want to edit your /etc/pandora/conf/eventmap file to run the pndhotkey immediately when the pandora key is pressed. To do this just change the 'pandora' line:
here.
/usr/pandora/scripts/snapsnap.sh
(That is a 'negative one' for the hold time, indicating it will be run on key down instead of up.)
Then, you will need to create a configuration file for pndhotkey at /etc/pandora/conf/pndhotkey.conf
I currently have the following (and you can add whatever else you like):
Then, you'll need to create any of those scripts you'd like to include in the config file. You will definitely want the menu toggle (or some replacement). Don't forget to chmod a+x on all script files you create yourself.
(These were shamelessly stolen from skeezix's premade scripts.)
/usr/pandora/scripts/op_menu_toggle.sh
/usr/pandora/scripts/op_pndkillall.sh
/usr/pandora/scripts/op_xfcekill.sh
This one was stolen from SomeGuy99's guide
So, hopefully people will find some use in this. I will post the source here for pndhotkey and also the changes I made to pndevmapperd.
Again, just to make it absolutely clear, I am not a programmer (or a very good scripter, really), so please don't expect too much.
pndhotkey.c
pndevmapperd.c changes:
For those who don't want to muck about with compiling things, I will attach both files (pndevmapperd and pndhotkey) in an archive. You will want to
Code:
sudo tar -xzf hotkey.tar.gz /usr/bin/
You will want to edit your /etc/pandora/conf/eventmap file to run the pndhotkey immediately when the pandora key is pressed. To do this just change the 'pandora' line:
here.
/usr/pandora/scripts/snapsnap.sh
Code:
pandora /usr/bin/pndhotkey -1
(That is a 'negative one' for the hold time, indicating it will be run on key down instead of up.)
Then, you will need to create a configuration file for pndhotkey at /etc/pandora/conf/pndhotkey.conf
I currently have the following (and you can add whatever else you like):
Code:
# pndhotkey configuration file - keys listed under minimenu will only run
# under minimenu, under desktop will only
# run under xfce/whatever, and general will
# run in either
[config]
# this is the command to check if the full desktop is up
desktop-check pidof xfce4-session
# this is the command to run in order to show/hide the desktop menu
desktop-menu /usr/pandora/scripts/op_menu_toggle.sh
[minimenu]
Q /usr/pandora/scripts/op_pndkillall.sh
[desktop]
R xfrun4
L xflock4
K /usr/pandora/scripts/op_xfcekill.sh
T Terminal
[general]
W sudo /usr/pandora/scripts/op_wifi.sh
B sudo /usr/pandora/scripts/op_bluetooth.sh
S /usr/pandora/scripts/snapsnap.sh
Then, you'll need to create any of those scripts you'd like to include in the config file. You will definitely want the menu toggle (or some replacement). Don't forget to chmod a+x on all script files you create yourself.
(These were shamelessly stolen from skeezix's premade scripts.)
/usr/pandora/scripts/op_menu_toggle.sh
Code:
#!/bin/bash
# this script determines whether the popup menu is displayed,
# and shows/hides it
# note that this doesn't actually work, since xfce4-popup-menu
# does not stay resident. i have yet to find a work-around, but
# i'm still investigating some things
popuppid=$(pidof xfce4-popup-menu)
if [ $popuppid ]; then
# menu is open, let's close it
kill $popupid
else
# no open menu found
/bin/bash -c 'DISPLAY=:0.0 xfce4-popup-menu'
fi
/usr/pandora/scripts/op_pndkillall.sh
Code:
#!/bin/bash
# this script kills all processes that were launched
# with the pnd_run script
pidlist=$(pstree -lpA | grep pnd_run.sh | sed -ne 's/.*(\([0-9]\+\))/\1/p')
for PID in $pidlist
do
kill -9 $PID
done
/usr/pandora/scripts/op_xfcekill.sh
Code:
#!/bin/bash
# this script opens a list of running apps and prompts
# the user to terminate any of them
pidlist=$(pstree -lpA | grep pnd_run.sh | sed -ne 's/.*-\(.*\)(\([0-9]\+\))/\2\n \1/p' | /bin/bash -c 'DISPLAY=:0.0 zenity --list --multiple --column "pid" --column "name" --title "kill" --text "which apps should be killed"' | sed 's/|/\n/')
for PID in $pidlist
do
kill -9 $PID
done
This one was stolen from SomeGuy99's guide
Code:
#!/bin/bash
# this script saves a timestamped screen shot
# to the current user's home folder
fbgrab -d /dev/fb0 ~/screen`date +%y%m%d-%H%M%S`-00.png
fbgrab -d /dev/fb1 ~/screen`date +%y%m%d-%H%M%S`-01.png
notify-send snapsnap
# EDIT: Seems like most games (SDL?) are using fb1 instead
# of the default. Easy fix, just grab both and sort them
# later, although it will cause more nand writes. Someone
# can come up with a better system, I'm sure.
So, hopefully people will find some use in this. I will post the source here for pndhotkey and also the changes I made to pndevmapperd.
Again, just to make it absolutely clear, I am not a programmer (or a very good scripter, really), so please don't expect too much.
pndhotkey.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <time.h>
#include <string.h>
#include <X11/Xlib.h>
#include "pnd_conf.h"
#include "pnd_container.h"
#include "pnd_pxml.h"
#include "pnd_utility.h"
#define KEY_PRESSED(key,map) (map[key / 8] & (1 << (key % 8)))
typedef struct {
int keycode;
char *keyname;
} keycode_t;
keycode_t keycodes[] = {
{ KEY_A, "A" }, { KEY_B, "B" }, { KEY_C, "C" }, { KEY_D, "D" },
{ KEY_E, "E" }, { KEY_F, "F" }, { KEY_G, "G" }, { KEY_H, "H" },
{ KEY_I, "I" }, { KEY_J, "J" }, { KEY_K, "K" }, { KEY_L, "L" },
{ KEY_M, "M" }, { KEY_N, "N" }, { KEY_O, "O" }, { KEY_P, "P" },
{ KEY_Q, "Q" }, { KEY_R, "R" }, { KEY_S, "S" }, { KEY_T, "T" },
{ KEY_U, "U" }, { KEY_V, "V" }, { KEY_W, "W" }, { KEY_X, "X" },
{ KEY_Y, "Y" }, { KEY_Z, "Z" }, { KEY_1, "1" }, { KEY_2, "2" },
{ KEY_3, "3" }, { KEY_4, "4" }, { KEY_5, "5" }, { KEY_6, "6" },
{ KEY_7, "7" }, { KEY_8, "8" }, { KEY_9, "9" }, { KEY_0, "0" },
{ KEY_COMMA, "COMMA" }, { KEY_DOT, "FULLSTOP" }, { KEY_ENTER, "ENTER" },
{ KEY_DELETE, "DELETE" }, { KEY_UP, "UP" }, { KEY_DOWN, "DOWN" },
{ KEY_LEFT, "LEFT" }, { KEY_RIGHT, "RIGHT" }, { KEY_HOME, "BUTTONA" },
{ KEY_END, "BUTTONB" }, { KEY_PAGEDOWN, "BUTTONX" }, { KEY_PAGEUP, "BUTTONY" },
{ KEY_RIGHTSHIFT, "BUTTONL" }, { KEY_RIGHTCTRL, "BUTTONR" },
{ KEY_LEFTALT, "SELECT" }, { KEY_LEFTCTRL, "START" }, { -1, NULL }
};
char username[128];
keycode_t* getKeyCode(char *keystr) {
keycode_t *p = keycodes;
while (p->keycode != -1) {
if (strcasecmp (p->keyname,keystr) == 0 ) {
return p;
}
p++;
}
return p;
}
int main(int argc, char *argv[])
{
FILE *log;
// shut off logging unless -l switch is used
if (argc > 1 && strncmp(argv[1], "-", 1) == 0) {
if (strcmp(argv[1], "-l") == 0 || strcmp(argv[1], "--log") == 0) {
log = fopen("/tmp/pndhotkey.log", "w");
} else {
printf("Unknown option: %s\nUsage: pndhotkey [options]\nCurrent options:\n-l, --log Enable logging to /tmp/pndhotkey.log\n", argv[1]);
exit(0);
}
} else {
log = fopen("/dev/null", "w");
}
stdout = log;
stderr = log;
//fprintf(log, "Begin logging...\n");
FILE *keypad;
FILE *gpio;
keypad = fopen("/dev/input/by-path/platform-i2c_omap.1-platform-twl4030_keypad-event", "r");
gpio = fopen("/dev/input/by-path/platform-gpio-keys-event", "r");
if (keypad == NULL) {
fprintf(log, "Failed to open keypad input, exiting.");
exit(1);
} else if (gpio == NULL) {
fprintf(log, "Failed to open gpio input, exiting.");
exit(1);
}
char keypadmap[KEY_MAX/8 + 1];
char gpiomap[KEY_MAX/8 + 1];
memset(keypadmap, 0, sizeof(keypadmap));
memset(gpiomap, 0, sizeof(gpiomap));
if (ioctl(fileno(keypad), EVIOCGKEY(sizeof(keypadmap)), keypadmap) == -1) {
fprintf(log, "Can't get keypad state using EVIOCGKEY, exiting.");
exit(1);
}
if (ioctl(fileno(gpio), EVIOCGKEY(sizeof(gpiomap)), gpiomap) == -1) {
fprintf(log, "Can't get gpio state using EVIOCGKEY, exiting.");
exit(1);
}
pnd_conf_handle hotkeyconf;
hotkeyconf = pnd_conf_fetch_by_path("/etc/pandora/conf/pndhotkey.conf");
if (!hotkeyconf) {
fprintf(log, "Failed getting handle to conf file, exiting.");
exit(1);
}
// determine whether we are running with wm
void *node;
node = pnd_box_find_by_key(hotkeyconf, "config.desktop-check");
int wmcheck;
char wmcmd[(strlen((char*)node) + 13)];
sprintf(wmcmd, "%s > /dev/null", (char*)node);
wmcheck = system(wmcmd);
// check if process could not be created or if file not found
if (wmcheck == -1 || wmcheck == 32512) {
node = pnd_box_find_by_key(hotkeyconf, "config.desktop-check");
fprintf(log, "Could not launch window manager check [%s], exiting.", (char*)node);
exit(1);
} else {
wmcheck = !wmcheck;
}
// check username to run commands as
pnd_check_login(username, 127);
struct timespec ts;
// we are grabbing all keys
Display *dpy;
fprintf(log, "Begin capture of X Display\n");
if ((dpy = XOpenDisplay(":0.0")) == NULL) {
// possibly first run, might not be able to connect as root
fprintf(log, "Could not open default X Display, attempting to run xhost...\n");
char xhostcmd[(strlen(username) + 50)];
sprintf(xhostcmd, "su -c 'DISPLAY=:0.0 /usr/bin/xhost local:root' - %s", username);
system(xhostcmd);
if ((dpy = XOpenDisplay(":0.0")) == NULL) {
fprintf(log, "Could not open default X Display, exiting");
exit(1);
}
}
XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeAsync, GrabModeAsync, CurrentTime);
// loop while pandora key is held
while (KEY_PRESSED(KEY_MENU,gpiomap)) {
node = pnd_box_get_head(hotkeyconf);
// loop through conf entries looking for keys
while (node) {
char *key = pnd_box_get_key(node);
//fprintf(log, "Key: %s => %s\n", key, (char*)node);
if (wmcheck && (strncmp(key,"desktop.",8) == 0)) {
key += 8;
} else if (!wmcheck && (strncmp(key,"minimenu.",9) == 0)) {
key += 9;
} else if (strncmp(key,"general.",8) == 0) {
key += 8;
} else {
key = NULL;
}
// if we found a valid hotkey, check if it is pressed and run it
if (key != NULL) {
keycode_t *code = getKeyCode(key);
if (code != NULL && (KEY_PRESSED(code->keycode,keypadmap) || KEY_PRESSED(code->keycode,gpiomap))) {
fprintf(log, "Found hotkey [%s] for [%s].\n", key, (char*)node);
char cmd[(strlen((char*)node) + strlen(username) + 54)];
// this is a stupid fix because 'su' munges the path, would be better
// to detect full path from .profile or .bashrc or something (??)
// also, would probably be more elegant to fork instead of using '&'
sprintf(cmd, "su -c 'DISPLAY=:0.0 PATH=$PATH:/sbin:/usr/sbin %s &' - %s", (char*)node, username);
int result = system(cmd);
XUngrabKeyboard(dpy, CurrentTime);
if (result == -1 || result == 32512) {
fprintf(log, "Could not launch [%s] - exit status [%i] - exiting.", cmd, result);
exit(1);
} else {
exit(0);
}
}
}
node = pnd_box_get_next(node);
}
// don't want to lock our pandy up while key is held, we'll wait 10ms
ts.tv_sec = 0;
ts.tv_nsec = 10000000;
nanosleep(&ts, NULL);
// refresh the global keystate
memset(keypadmap, 0, sizeof(keypadmap));
memset(gpiomap, 0, sizeof(gpiomap));
ioctl(fileno(keypad), EVIOCGKEY(sizeof(keypadmap)), keypadmap);
ioctl(fileno(gpio), EVIOCGKEY(sizeof(gpiomap)), gpiomap);
}
// if we're still running at this point, user has released pandora key
// without pressing any other key, we should open the menu if wm is running
if (wmcheck) {
node = pnd_box_find_by_key(hotkeyconf, "config.desktop-menu");
if ((wmcheck = system((char*)node)) == -1 || wmcheck == 32512) {
fprintf(log, "Could not launch window manager menu toggle [%s] - exit status [%i] - exiting.", (char*)node, wmcheck);
XUngrabKeyboard(dpy, CurrentTime);
exit(1);
}
}
XUngrabKeyboard(dpy, CurrentTime);
exit(0);
}
pndevmapperd.c changes:
Code:
(line 105?) change:
unsigned int maxhold;
to:
int maxhold;
(line 687?) add:
if ( g_evmap [ i ].maxhold < 0 ) {
invoke_it = 1;
}
before:
g_evmap [ i ].keydown_time = time ( NULL );
Attachments
Last edited by a moderator: