Browse Source

First attempt at code for raw mice under Linux

Josh Yelon 19 years ago
parent
commit
d3b05dc48c

+ 1 - 1
direct/src/showbase/ShowBase.py

@@ -201,7 +201,7 @@ class ShowBase(DirectObject.DirectObject):
         # Open the default rendering window.
         # Open the default rendering window.
         if self.windowType != 'none':
         if self.windowType != 'none':
 	    props = WindowProperties.getDefault()
 	    props = WindowProperties.getDefault()
-	    if (self.config.GetBool('read-raw-mice', 1)):
+	    if (self.config.GetBool('read-raw-mice', 0)):
 	        props.setRawMice(1)
 	        props.setRawMice(1)
             self.openDefaultWindow(startDirect = False, props=props)
             self.openDefaultWindow(startDirect = False, props=props)
 
 

+ 2 - 1
doc/makepanda/makepanda.py

@@ -1627,6 +1627,7 @@ DEFAULT_SETTINGS=[
     ("HAVE_GETOPT",                    'UNDEF',                  '1'),
     ("HAVE_GETOPT",                    'UNDEF',                  '1'),
     ("HAVE_GETOPT_LONG_ONLY",          'UNDEF',                  '1'),
     ("HAVE_GETOPT_LONG_ONLY",          'UNDEF',                  '1'),
     ("HAVE_GETOPT_H",                  'UNDEF',                  '1'),
     ("HAVE_GETOPT_H",                  'UNDEF',                  '1'),
+    ("HAVE_LINUX_INPUT_H",             'UNDEF',                  '1'),
     ("IOCTL_TERMINAL_WIDTH",           'UNDEF',                  '1'),
     ("IOCTL_TERMINAL_WIDTH",           'UNDEF',                  '1'),
     ("HAVE_STREAMSIZE",                '1',                      '1'),
     ("HAVE_STREAMSIZE",                '1',                      '1'),
     ("HAVE_IOS_TYPEDEFS",              '1',                      '1'),
     ("HAVE_IOS_TYPEDEFS",              '1',                      '1'),
@@ -1857,8 +1858,8 @@ if (sys.platform != "win32"):
     confautoprc = confautoprc.replace("aux-display pandadx8","")
     confautoprc = confautoprc.replace("aux-display pandadx8","")
     confautoprc = confautoprc.replace("aux-display pandadx7","")
     confautoprc = confautoprc.replace("aux-display pandadx7","")
 
 
-ConditionalWriteFile("built/etc/Confauto.prc", confautoprc)
 ConditionalWriteFile("built/etc/Config.prc", configprc)
 ConditionalWriteFile("built/etc/Config.prc", configprc)
+ConditionalWriteFile("built/etc/Confauto.prc", confautoprc)
 
 
 ##########################################################################################
 ##########################################################################################
 #
 #

+ 6 - 0
panda/src/display/windowProperties.cxx

@@ -182,6 +182,9 @@ add_properties(const WindowProperties &other) {
   if (other.has_minimized()) {
   if (other.has_minimized()) {
     set_minimized(other.get_minimized());
     set_minimized(other.get_minimized());
   }
   }
+  if (other.has_raw_mice()) {
+    set_raw_mice(other.get_raw_mice());
+  }
   if (other.has_open()) {
   if (other.has_open()) {
     set_open(other.get_open());
     set_open(other.get_open());
   }
   }
@@ -241,6 +244,9 @@ output(ostream &out) const {
   if (has_minimized()) {
   if (has_minimized()) {
     out << (get_minimized() ? "minimized " : "!minimized ");
     out << (get_minimized() ? "minimized " : "!minimized ");
   }
   }
+  if (has_raw_mice()) {
+    out << (get_raw_mice() ? "raw_mice " : "!raw_mice ");
+  }
   if (has_open()) {
   if (has_open()) {
     out << (get_open() ? "open " : "!open ");
     out << (get_open() ? "open " : "!open ");
   }
   }

+ 150 - 1
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -37,8 +37,14 @@
 #include <X11/Xutil.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
 #include <X11/Xatom.h>
 
 
+#ifdef HAVE_LINUX_INPUT_H
+#include <linux/input.h>
+#endif
+
 TypeHandle glxGraphicsWindow::_type_handle;
 TypeHandle glxGraphicsWindow::_type_handle;
 
 
+#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7)))
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsWindow::Constructor
 //     Function: glxGraphicsWindow::Constructor
 //       Access: Public
 //       Access: Public
@@ -235,7 +241,9 @@ process_events() {
   if (_xwindow == (Window)0) {
   if (_xwindow == (Window)0) {
     return;
     return;
   }
   }
-
+  
+  poll_raw_mice();
+  
   XEvent event;
   XEvent event;
   XKeyEvent keyrelease_event;
   XKeyEvent keyrelease_event;
   bool got_keyrelease_event = false;
   bool got_keyrelease_event = false;
@@ -683,6 +691,13 @@ open_window() {
   
   
   XMapWindow(_display, _xwindow);
   XMapWindow(_display, _xwindow);
 
 
+  if (_properties.get_raw_mice()) {
+    open_raw_mice();
+  } else {
+    glxdisplay_cat.error() <<
+      "Raw mice not requested.\n";
+  }
+  
   return true;
   return true;
 }
 }
 
 
@@ -1003,6 +1018,140 @@ setup_colormap(XVisualInfo *visual) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsWindow::open_raw_mice
+//       Access: Private
+//  Description: Adds raw mice to the _input_devices list.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsWindow::
+open_raw_mice()
+{
+#ifdef HAVE_LINUX_INPUT_H
+  bool any_present = false;
+  bool any_mice = false;
+  
+  for (int i=0; i<64; i++) {
+    uint8_t evtypes[EV_MAX/8 + 1];
+    ostringstream fnb;
+    fnb << "/dev/input/event" << i;
+    string fn = fnb.str();
+    int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0);
+    if (fd >= 0) {
+      any_present = true;
+      char name[256];
+      char phys[256];
+      char uniq[256];
+      if ((ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0)||
+	  (ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0)||
+	  (ioctl(fd, EVIOCGPHYS(sizeof(uniq)), uniq) < 0)||
+	  (ioctl(fd, EVIOCGBIT(0, EV_MAX), &evtypes) < 0)) {
+	close(fd);
+	glxdisplay_cat.error() <<
+	  "Opening raw mice: ioctl failed on " << fn << "\n";
+      } else {
+	if (test_bit(EV_REL, evtypes) || test_bit(EV_ABS, evtypes)) {
+	  string full_id = ((string)name) + " " + uniq;
+	  MouseDeviceInfo inf;
+	  inf._fd = fd;
+	  inf._input_device_index = _input_devices.size();
+	  inf._io_buffer = "";
+	  _mouse_device_info.push_back(inf);
+	  GraphicsWindowInputDevice device =
+	    GraphicsWindowInputDevice::pointer_only(full_id);
+	  _input_devices.push_back(device);
+	  any_mice = true;
+	} else {
+	  close(fd);
+	}
+      }
+    } else {
+      if ((errno == ENOENT)||(errno == ENOTDIR)) {
+	break;
+      } else {
+	any_present = true;
+	glxdisplay_cat.error() << 
+	  "Opening raw mice: " << strerror(errno) << " " << fn << "\n";
+      }
+    }
+  }
+  
+  if (!any_present) {
+    glxdisplay_cat.error() << 
+      "Opening raw mice: files not found: /dev/input/event*\n";
+  } else if (!any_mice) {
+    glxdisplay_cat.error() << 
+      "Opening raw mice: no mouse devices detected in /dev/input/event*\n";
+  }
+#else
+  glxdisplay_cat.error() <<
+    "Opening raw mice: panda not compiled with raw mouse support.\n";
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsWindow::poll_raw_mice
+//       Access: Private
+//  Description: Reads events from the raw mouse device files.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsWindow::
+poll_raw_mice()
+{
+#ifdef HAVE_LINUX_INPUT_H
+  for (int dev=0; dev<_mouse_device_info.size(); dev++) {
+    MouseDeviceInfo &inf = _mouse_device_info[dev];
+
+    // Read all bytes into buffer.
+    if (inf._fd >= 0) {
+      while (1) {
+	char tbuf[1024];
+	int nread = read(inf._fd, tbuf, sizeof(tbuf));
+	if (nread > 0) {
+	  inf._io_buffer += string(tbuf, nread);
+	} else {
+	  if ((nread < 0)&&((errno == EWOULDBLOCK) || (errno==EAGAIN))) {
+	    break;
+	  }
+	  close(inf._fd);
+	  inf._fd = -1;
+	  break;
+	}
+      }
+    }
+
+    // Process events.
+    int nevents = inf._io_buffer.size() / sizeof(struct input_event);
+    if (nevents == 0) {
+      continue;
+    }
+    const input_event *events = (const input_event *)(inf._io_buffer.c_str());
+    GraphicsWindowInputDevice &dev = _input_devices[inf._input_device_index];
+    int x = dev.get_pointer().get_x();
+    int y = dev.get_pointer().get_y();
+    for (int i=0; i<nevents; i++) {
+      if (events[i].type == EV_REL) {
+	if (events[i].code == REL_X) x += events[i].value;
+	if (events[i].code == REL_Y) y += events[i].value;
+      } else if (events[i].type == EV_ABS) {
+	if (events[i].code == ABS_X) x = events[i].value;
+	if (events[i].code == ABS_Y) y = events[i].value;
+      } else if (events[i].type == EV_KEY) {
+	if ((events[i].code >= BTN_MOUSE)&&(events[i].code < BTN_MOUSE+8)) {
+	  int btn = events[i].code - BTN_MOUSE;
+	  dev.set_pointer_in_window(x,y);
+	  if (events[i].value) {
+	    dev.button_down(MouseButton::button(btn));
+	  } else {
+	    dev.button_up(MouseButton::button(btn));
+	  }
+	}
+      }
+    }
+    inf._io_buffer.erase(0,nevents*sizeof(struct input_event));
+    dev.set_pointer_in_window(x,y);
+  }
+#endif
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsWindow::handle_keystroke
 //     Function: glxGraphicsWindow::handle_keystroke
 //       Access: Private
 //       Access: Private

+ 10 - 0
panda/src/glxdisplay/glxGraphicsWindow.h

@@ -70,6 +70,9 @@ private:
 
 
   static Bool check_event(Display *display, XEvent *event, char *arg);
   static Bool check_event(Display *display, XEvent *event, char *arg);
 
 
+  void open_raw_mice();
+  void poll_raw_mice();
+  
 private:
 private:
   Display *_display;
   Display *_display;
   int _screen;
   int _screen;
@@ -90,6 +93,13 @@ private:
   Atom _net_wm_state_add;
   Atom _net_wm_state_add;
   Atom _net_wm_state_remove;
   Atom _net_wm_state_remove;
 
 
+  struct MouseDeviceInfo {
+    int    _fd;
+    int    _input_device_index;
+    string _io_buffer;
+  };
+  pvector<MouseDeviceInfo> _mouse_device_info;
+  
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;