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 */

Reply via email to