Package: mouseemu Version: 0.15-8 Severity: normal Tags: patch User: [email protected] Usertags: origin-ubuntu ubuntu-patch karmic
We've been installing mouseemu by default on Intel Macs in Ubuntu for a while (which is probably overkill, but that's a separate bug), and apparently this causes problems when the user actually has a mouse with more than three buttons. Here's the text of the original report (https://bugs.launchpad.net/ubuntu/+source/mouseemu/+bug/419947): Mouseemu creates an emulated "3-button scroll" mouse, i.e. left and right buttons, plus a clickable scrollwheel. This is useful when running on a system with this many buttons or less (e.g. a laptop touchpad) Unfortunately, mouseemu also swallows all events from the system's "real" mouse, including events caused by buttons outside the 3-button-scroll limitation. As a result, if your system has more buttons (e.g. side buttons, or a wheel with horizontal scroll) then the extra buttons are not used, as mouseemu does not forward those events. I've attached a dpatch to fix this; obviously it would also need to be added to 00list etc. Thanks, -- Colin Watson [[email protected]]
#! /bin/sh /usr/share/dpatch/dpatch-run ## more_mouse_buttons.dpatch by Colin Watson <[email protected]> ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Pass through any additional mouse buttons supported by real mouse ## DP: devices on the system. @DPATCH@ diff -urNad mouseemu-0.16~/mouseemu.c mouseemu-0.16/mouseemu.c --- mouseemu-0.16~/mouseemu.c 2009-08-27 20:18:25.000000000 +0100 +++ mouseemu-0.16/mouseemu.c 2009-08-27 20:22:25.000000000 +0100 @@ -209,7 +209,7 @@ { if (inp.type != EV_KEY && inp.type != EV_REL && inp.type != EV_SYN) return; - if (inp.type == EV_KEY && inp.code != BTN_LEFT && inp.code != BTN_MIDDLE && inp.code != BTN_RIGHT) + if (inp.type == EV_KEY && (inp.code < BTN_MISC || inp.code >= KEY_OK)) return; if (inp.type == EV_KEY && inp.code == BTN_LEFT) { @@ -227,7 +227,8 @@ //printf("inp.value %d\n", inp.value); } else { if ((inp.time.tv_sec*1000000+inp.time.tv_usec)-last_key > typing_block_delay*1000 - || inp.type == EV_REL) + || inp.type == EV_REL + || (inp.type == EV_KEY && inp.code != BTN_MIDDLE && inp.code != BTN_RIGHT)) passthrough(ui_mouse_fd, inp); } } @@ -254,8 +255,11 @@ for (n = 0, m = 0; n < EVENT_DEVS; n++) { sprintf(filename, "/dev/input/event%d", n); if ((fd = open(filename, O_RDONLY)) >= 0) { + unsigned long mousebtns[NBITS(KEY_MAX)], mouserels[NBITS(REL_MAX)]; + memset(mousebtns, 0, sizeof(mousebtns)); + memset(mouserels, 0, sizeof(mouserels)); mode = 0; - ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); + ioctl(fd, EVIOCGBIT(0, sizeof(bit)), bit); ioctl(fd, EVIOCGID, id); if (test_bit(EV_KEY, bit) && test_bit(EV_REP, bit)) { /* our own virtual keyboard (on rescans)*/ @@ -270,6 +274,7 @@ } } if (test_bit(EV_REL, bit)) { + int i; /* our own virtual mouse (on rescans)*/ if (id[ID_PRODUCT] == 0x1E && id[ID_VENDOR] == 0x1F) { close(fd); @@ -280,6 +285,16 @@ id[ID_VENDOR] != eventdevs[m].vendor) { debugf("mouse : fd %d event%d, vendor %4x product %4x\n", fd, n, id[ID_VENDOR], id[ID_PRODUCT]); } + ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(mousebtns)), mousebtns); + debugf("mouse : buttons:\n"); + for (i = BTN_MISC; i < KEY_OK; ++i) + if (((unsigned char *)mousebtns)[i / 8] & (1 << (i % 8))) + debugf(" 0x%x\n", i); + ioctl(fd, EVIOCGBIT(EV_REL, sizeof(mouserels)), mouserels); + debugf("mouse : relative events:\n"); + for (i = REL_X; i <= REL_MAX; ++i) + if (((unsigned char *)mouserels)[i / 8] & (1 << (i % 8))) + debugf(" 0x%x\n", i); } if (mode) { if (id[ID_PRODUCT] != eventdevs[m].product || @@ -291,6 +306,8 @@ eventdevs[m].handle= fd; eventdevs[m].product = id[ID_PRODUCT]; eventdevs[m].vendor = id[ID_VENDOR]; + memcpy(eventdevs[m].mousebtns, mousebtns, sizeof(mousebtns)); + memcpy(eventdevs[m].mouserels, mouserels, sizeof(mouserels)); register_inputhandler(mode, fd, event_handler, 1); } else close(fd); @@ -303,6 +320,8 @@ eventdevs[m].product = 0; eventdevs[m].vendor = 0; eventdevs[m].handle = -1; + memset(eventdevs[m].mousebtns, 0, sizeof(eventdevs[m].mousebtns)); + memset(eventdevs[m].mouserels, 0, sizeof(eventdevs[m].mouserels)); } } @@ -322,6 +341,8 @@ eventdevs[i].product = 0; eventdevs[i].vendor = 0; eventdevs[i].handle = -1; + memset(eventdevs[i].mousebtns, 0, sizeof(eventdevs[i].mousebtns)); + memset(eventdevs[i].mouserels, 0, sizeof(eventdevs[i].mouserels)); } usleep(100); scan_for_devs(); @@ -435,7 +456,7 @@ int uinput_setup(void) { struct uinput_user_dev device; - int i; + int i, j; memset(&device, 0, sizeof(struct uinput_user_dev)); /*setup keyboard device */ @@ -518,10 +539,32 @@ ioctl(ui_mouse_fd, UI_SET_RELBIT, REL_X); ioctl(ui_mouse_fd, UI_SET_RELBIT, REL_Y); ioctl(ui_mouse_fd, UI_SET_RELBIT, REL_WHEEL); + for (i = REL_X; i <= REL_MAX; ++i) { + if (i == REL_X || i == REL_Y || i == REL_WHEEL) + continue; + for (j = 0; j < EVENT_DEVS; ++j) { + if (((unsigned char *)eventdevs[j].mouserels)[i / 8] & (1 << (i % 8))) { + debugf("Enabling additional relative event 0x%x\n", i); + ioctl(ui_mouse_fd, UI_SET_RELBIT, i); + break; + } + } + } ioctl(ui_mouse_fd, UI_SET_KEYBIT, BTN_LEFT); ioctl(ui_mouse_fd, UI_SET_KEYBIT, BTN_RIGHT); ioctl(ui_mouse_fd, UI_SET_KEYBIT, BTN_MIDDLE); + for (i = BTN_MISC; i < KEY_OK; ++i) { + if (i == BTN_LEFT || i == BTN_RIGHT || i == BTN_MIDDLE) + continue; + for (j = 0; j < EVENT_DEVS; ++j) { + if (((unsigned char *)eventdevs[j].mousebtns)[i / 8] & (1 << (i % 8))) { + debugf("Enabling additional button 0x%x\n", i); + ioctl(ui_mouse_fd, UI_SET_KEYBIT, i); + break; + } + } + } ioctl(ui_mouse_fd, UI_DEV_CREATE, NULL); @@ -830,6 +873,8 @@ eventdevs[i].handle = -1; eventdevs[i].vendor = 0; eventdevs[i].product= 0; + memset(eventdevs[i].mousebtns, 0, sizeof(eventdevs[i].mousebtns)); + memset(eventdevs[i].mouserels, 0, sizeof(eventdevs[i].mouserels)); ihandler[i].handler=0; ihandler[i].mode=0; diff -urNad mouseemu-0.16~/mouseemu.h mouseemu-0.16/mouseemu.h --- mouseemu-0.16~/mouseemu.h 2009-08-27 20:18:25.000000000 +0100 +++ mouseemu-0.16/mouseemu.h 2009-08-27 20:18:25.000000000 +0100 @@ -41,6 +41,8 @@ int handle; unsigned short vendor; unsigned short product; + unsigned long mousebtns[NBITS(KEY_MAX)]; + unsigned long mouserels[NBITS(REL_MAX)]; } kdev; /* handler structure */

