Installation of oS 12.1 with KDE on a Thinkpad T520 up to know really nice!
Linux 3.1.9-1.4-desktop x86_64
openSUSE 12.1 (x86_64)
KDE: 4.7.2 (4.7.2) “release 5”
With the help of khotkeys all Thinkpad hotkeys worked - all but one: Fn-F8 !
Trying to assign Fn-F8, which is recognized as XF86TouchpadToggle by xev, is not supported by Qt, and therefore leads to a message like “the key you pressed is not supported by Qt” (Sorry, don’t know the exact message in English since I installed DE language support) in the synaptics applet.
This pulls us back to basics: acpi_hotkey
Unfortunately a previous solution Thinkpad Fn-F8: Toggle Touchpad Example does not work any more since I was not able to get the display settings and credentials for X11 fixed in /usr/lib/acpid/thinkpad_handler.
Because of this probably all attempts with xvkbd failed as well.
Searching for a solution (I need to get this touchpad disabled while typing text and especially while scrolling with the Thinkstick ) I found acpi_fakekey. However here also a apparently deprecated method using /dev/input/event0 (which is the keyboard on my machine) was used.
So finally I found a solution using /dev/uinput that I would like to share.
It still kind of strange: We intercept the Fn-F8 key event, which is ignored by Qt and inject instead an Ctrl-Alt-T event into Qt, which is mapped by the synaptic applet in KDE.
/* $Id: acpi_fake_alt-ctrl-t.c,v 1.8 2012/03/10 20:11:01 root Exp $ */
#ifndef lint
static char vcid] = "$Id: acpi_fake_alt-ctrl-t.c,v 1.8 2012/03/10 20:11:01 root Exp $";
#endif /* lint */
/*
Boundary conditions:
- KDE environment
- synaptics driver active
- ALT-CTRL-T defined as ToggleTouchpad command in synaptics applet
- Fn-F8 ignored by Qt (thats why can't simply redefine it)
Feed in the three keys acc. /usr/include/linux/input.h
KEY_T, KEY_LEFTALT, KEY_LEFTCTRL
*/
/* based on
acpi_fakekey.c nach
http://en.gentoo-wiki.com/wiki/ACPI/Map_events_to_keyboard_shortcut
changed to use /dev/uinput based on
http://www.linuxforums.org/forum/ubuntu-linux/161718-its-no-effect-when-using-uinput.html
http://www.einfochips.com/download/dash_jan_tip.pdf
http://thiemonge.org/getting-started-with-uinput
https://launchpadlibrarian.net/19907781/acpi_fakekey.c
*/
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <syslog.h>
int main() {
int fd;
int key;
struct input_event event;
struct uinput_user_dev dev;
openlog("fake_alt-ctrl-t: ", LOG_PID, LOG_SYSLOG);
syslog(LOG_NOTICE, "faking ALT-CTRL-T");
fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
if (fd < 0) {
syslog(LOG_NOTICE, "%m");
exit(EXIT_FAILURE);
}
memset(&dev, 0, sizeof(dev));
strncpy(dev.name, "ACPI Virtual Keyboard Device", UINPUT_MAX_NAME_SIZE);
dev.id.version = 4;
dev.id.bustype = BUS_USB;
dev.id.product = 1; // dummy
dev.id.vendor = 1; // dummy
ioctl(fd, UI_SET_EVBIT, EV_KEY);
// we somehow need to 'enable' the keys we want to use
ioctl(fd, UI_SET_KEYBIT, KEY_T);
ioctl(fd, UI_SET_KEYBIT, KEY_LEFTALT);
ioctl(fd, UI_SET_KEYBIT, KEY_LEFTCTRL);
write(fd, &dev, sizeof(dev));
if (ioctl(fd, UI_DEV_CREATE)) {
syslog(LOG_NOTICE, "%m");
return EXIT_FAILURE;
}
if (!fd) {
syslog(LOG_NOTICE, "%m");
return 2;
}
sleep(1);
event.type = EV_KEY;
event.value = 1;
event.code = KEY_LEFTCTRL;
write(fd, &event, sizeof event);
event.code = KEY_LEFTALT;
write(fd, &event, sizeof event);
event.code = KEY_T;
write(fd, &event, sizeof event);
event.value = 0;
event.code = KEY_T;
write(fd, &event, sizeof event);
event.code = KEY_LEFTALT;
write(fd, &event, sizeof event);
event.code = KEY_LEFTCTRL;
write(fd, &event, sizeof event);
ioctl(fd, UI_DEV_DESTROY);
close (fd);
closelog();
return EXIT_SUCCESS;
}
This program is called in usr/lib/acpid/thinkpad_handler as follows:
# XF86ToggleTouchpad
if "$WHAT" = "00000080" -a "$SERIAL" = "00001008" ]; then
# Fn+F8
/usr/local/bin/acpi_fake_alt-ctrl-t
fi
/PiNy