From d3b05dc48cef2c92113bf9d55be4ed9925ec357b Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Fri, 23 Mar 2007 19:42:19 +0000 Subject: [PATCH] First attempt at code for raw mice under Linux --- direct/src/showbase/ShowBase.py | 2 +- doc/makepanda/makepanda.py | 3 +- panda/src/display/windowProperties.cxx | 6 + panda/src/glxdisplay/glxGraphicsWindow.cxx | 151 ++++++++++++++++++++- panda/src/glxdisplay/glxGraphicsWindow.h | 10 ++ 5 files changed, 169 insertions(+), 3 deletions(-) diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index f16c22994a..307fe74245 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -201,7 +201,7 @@ class ShowBase(DirectObject.DirectObject): # Open the default rendering window. if self.windowType != 'none': props = WindowProperties.getDefault() - if (self.config.GetBool('read-raw-mice', 1)): + if (self.config.GetBool('read-raw-mice', 0)): props.setRawMice(1) self.openDefaultWindow(startDirect = False, props=props) diff --git a/doc/makepanda/makepanda.py b/doc/makepanda/makepanda.py index 7c1ead6c86..7bfba39beb 100755 --- a/doc/makepanda/makepanda.py +++ b/doc/makepanda/makepanda.py @@ -1627,6 +1627,7 @@ DEFAULT_SETTINGS=[ ("HAVE_GETOPT", 'UNDEF', '1'), ("HAVE_GETOPT_LONG_ONLY", 'UNDEF', '1'), ("HAVE_GETOPT_H", 'UNDEF', '1'), + ("HAVE_LINUX_INPUT_H", 'UNDEF', '1'), ("IOCTL_TERMINAL_WIDTH", 'UNDEF', '1'), ("HAVE_STREAMSIZE", '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 pandadx7","") -ConditionalWriteFile("built/etc/Confauto.prc", confautoprc) ConditionalWriteFile("built/etc/Config.prc", configprc) +ConditionalWriteFile("built/etc/Confauto.prc", confautoprc) ########################################################################################## # diff --git a/panda/src/display/windowProperties.cxx b/panda/src/display/windowProperties.cxx index a42174a6ee..e9c35bcc0e 100644 --- a/panda/src/display/windowProperties.cxx +++ b/panda/src/display/windowProperties.cxx @@ -182,6 +182,9 @@ add_properties(const WindowProperties &other) { if (other.has_minimized()) { set_minimized(other.get_minimized()); } + if (other.has_raw_mice()) { + set_raw_mice(other.get_raw_mice()); + } if (other.has_open()) { set_open(other.get_open()); } @@ -241,6 +244,9 @@ output(ostream &out) const { if (has_minimized()) { out << (get_minimized() ? "minimized " : "!minimized "); } + if (has_raw_mice()) { + out << (get_raw_mice() ? "raw_mice " : "!raw_mice "); + } if (has_open()) { out << (get_open() ? "open " : "!open "); } diff --git a/panda/src/glxdisplay/glxGraphicsWindow.cxx b/panda/src/glxdisplay/glxGraphicsWindow.cxx index 6ec7243ec1..79069751e6 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.cxx +++ b/panda/src/glxdisplay/glxGraphicsWindow.cxx @@ -37,8 +37,14 @@ #include #include +#ifdef HAVE_LINUX_INPUT_H +#include +#endif + TypeHandle glxGraphicsWindow::_type_handle; +#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7))) + //////////////////////////////////////////////////////////////////// // Function: glxGraphicsWindow::Constructor // Access: Public @@ -235,7 +241,9 @@ process_events() { if (_xwindow == (Window)0) { return; } - + + poll_raw_mice(); + XEvent event; XKeyEvent keyrelease_event; bool got_keyrelease_event = false; @@ -683,6 +691,13 @@ open_window() { XMapWindow(_display, _xwindow); + if (_properties.get_raw_mice()) { + open_raw_mice(); + } else { + glxdisplay_cat.error() << + "Raw mice not requested.\n"; + } + 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= 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 // Access: Private diff --git a/panda/src/glxdisplay/glxGraphicsWindow.h b/panda/src/glxdisplay/glxGraphicsWindow.h index 9b3bb03e7e..eb731f8b77 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.h +++ b/panda/src/glxdisplay/glxGraphicsWindow.h @@ -70,6 +70,9 @@ private: static Bool check_event(Display *display, XEvent *event, char *arg); + void open_raw_mice(); + void poll_raw_mice(); + private: Display *_display; int _screen; @@ -90,6 +93,13 @@ private: Atom _net_wm_state_add; Atom _net_wm_state_remove; + struct MouseDeviceInfo { + int _fd; + int _input_device_index; + string _io_buffer; + }; + pvector _mouse_device_info; + public: static TypeHandle get_class_type() { return _type_handle;