Browse Source

Raw button event support, with X11 implementation (untransformed QWERTY)

rdb 11 years ago
parent
commit
85a5be984f

+ 22 - 0
panda/src/display/graphicsWindowInputDevice.cxx

@@ -365,3 +365,25 @@ focus_lost(double time) {
   }
   }
   _buttons_held.clear();
   _buttons_held.clear();
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::raw_button_down
+//       Access: Public
+//  Description: Records that the indicated button has been depressed.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindowInputDevice::
+raw_button_down(ButtonHandle button, double time) {
+  LightMutexHolder holder(_lock);
+  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_down, time));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::raw_button_up
+//       Access: Public
+//  Description: Records that the indicated button has been released.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindowInputDevice::
+raw_button_up(ButtonHandle button, double time) {
+  LightMutexHolder holder(_lock);
+  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_up, time));
+}

+ 12 - 10
panda/src/display/graphicsWindowInputDevice.h

@@ -45,27 +45,27 @@ public:
   static GraphicsWindowInputDevice pointer_only(GraphicsWindow *host, const string &name);
   static GraphicsWindowInputDevice pointer_only(GraphicsWindow *host, const string &name);
   static GraphicsWindowInputDevice keyboard_only(GraphicsWindow *host, const string &name);
   static GraphicsWindowInputDevice keyboard_only(GraphicsWindow *host, const string &name);
   static GraphicsWindowInputDevice pointer_and_keyboard(GraphicsWindow *host, const string &name);
   static GraphicsWindowInputDevice pointer_and_keyboard(GraphicsWindow *host, const string &name);
-  
+
   INLINE GraphicsWindowInputDevice();
   INLINE GraphicsWindowInputDevice();
   GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy);
   GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy);
   void operator = (const GraphicsWindowInputDevice &copy);
   void operator = (const GraphicsWindowInputDevice &copy);
   ~GraphicsWindowInputDevice();
   ~GraphicsWindowInputDevice();
-  
+
   INLINE string get_name() const;
   INLINE string get_name() const;
   INLINE bool has_pointer() const;
   INLINE bool has_pointer() const;
   INLINE bool has_keyboard() const;
   INLINE bool has_keyboard() const;
 
 
   INLINE void set_device_index(int index);
   INLINE void set_device_index(int index);
-  
+
   INLINE MouseData get_pointer() const;
   INLINE MouseData get_pointer() const;
   INLINE MouseData get_raw_pointer() const;
   INLINE MouseData get_raw_pointer() const;
-  
+
   INLINE void enable_pointer_events();
   INLINE void enable_pointer_events();
   INLINE void disable_pointer_events();
   INLINE void disable_pointer_events();
-  
+
   void enable_pointer_mode(double speed);
   void enable_pointer_mode(double speed);
   void disable_pointer_mode();
   void disable_pointer_mode();
-  
+
   bool has_button_event() const;
   bool has_button_event() const;
   ButtonEvent get_button_event();
   ButtonEvent get_button_event();
   bool has_pointer_event() const;
   bool has_pointer_event() const;
@@ -81,6 +81,8 @@ PUBLISHED:
   void candidate(const wstring &candidate_string, size_t highlight_start, 
   void candidate(const wstring &candidate_string, size_t highlight_start, 
                  size_t highlight_end, size_t cursor_pos);
                  size_t highlight_end, size_t cursor_pos);
   void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time());
   void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time());
+  void raw_button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
+  void raw_button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
 
 
   INLINE void set_pointer_in_window(double x, double y, double time = ClockObject::get_global_clock()->get_frame_time());
   INLINE void set_pointer_in_window(double x, double y, double time = ClockObject::get_global_clock()->get_frame_time());
   INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time());
   INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time());
@@ -102,17 +104,17 @@ private:
   typedef pdeque<ButtonEvent> ButtonEvents;
   typedef pdeque<ButtonEvent> ButtonEvents;
 
 
   LightMutex _lock;
   LightMutex _lock;
-  
+
   GraphicsWindow *_host;
   GraphicsWindow *_host;
-  
+
   string _name;
   string _name;
   int _flags;
   int _flags;
   int _device_index;
   int _device_index;
   int _event_sequence;
   int _event_sequence;
-  
+
   bool   _pointer_mode_enable;
   bool   _pointer_mode_enable;
   double _pointer_speed;
   double _pointer_speed;
-  
+
   bool _enable_pointer_events;
   bool _enable_pointer_events;
   MouseData _mouse_data;
   MouseData _mouse_data;
   MouseData _true_mouse_data;
   MouseData _true_mouse_data;

+ 8 - 0
panda/src/event/buttonEvent.cxx

@@ -55,6 +55,14 @@ output(ostream &out) const {
   case T_move:
   case T_move:
     out << "move";
     out << "move";
     break;
     break;
+
+  case T_raw_down:
+    out << "raw button " << _button << " down";
+    break;
+
+  case T_raw_up:
+    out << "raw button " << _button << " up";
+    break;
   }
   }
 }
 }
 
 

+ 8 - 1
panda/src/event/buttonEvent.h

@@ -81,10 +81,17 @@ public:
     // from a menu.
     // from a menu.
     T_candidate,
     T_candidate,
 
 
-    // T_move is used to indicate that the mouse has moved within the 
+    // T_move is used to indicate that the mouse has moved within the
     // current region. Button drag mode needs this, others may ignore
     // current region. Button drag mode needs this, others may ignore
     // this event
     // this event
     T_move,
     T_move,
+
+    // T_raw_down is usually sent together with T_down, except that
+    // this is the original, untransformed scan key sent by the keyboard.
+    // It is not altered by modifier keys and acts as if the user is
+    // using the US (qwerty) keyboard layout.
+    T_raw_down,
+    T_raw_up,
   };
   };
 
 
   INLINE ButtonEvent();
   INLINE ButtonEvent();

+ 47 - 0
panda/src/tform/buttonThrower.I

@@ -200,6 +200,53 @@ get_move_event() const {
   return _move_event;
   return _move_event;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ButtonThrower::set_raw_button_down_event
+//       Access: Published
+//  Description: Like set_button_down_event, but uses the raw,
+//               untransformed scan key from the operating system.
+//               This uses buttons that are independent of the
+//               user's selected keyboard layout.
+////////////////////////////////////////////////////////////////////
+INLINE void ButtonThrower::
+set_raw_button_down_event(const string &raw_button_down_event) {
+  _raw_button_down_event = raw_button_down_event;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ButtonThrower::get_raw_button_down_event
+//       Access: Published
+//  Description: Returns the raw_button_down_event that has been set on
+//               this ButtonThrower.  See set_raw_button_down_event().
+////////////////////////////////////////////////////////////////////
+INLINE const string &ButtonThrower::
+get_raw_button_down_event() const {
+  return _raw_button_down_event;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ButtonThrower::set_raw_button_up_event
+//       Access: Published
+//  Description: Specifies the generic event that is generated (if
+//               any) each time a key or button is released.  See
+//               set_raw_button_down_event().
+////////////////////////////////////////////////////////////////////
+INLINE void ButtonThrower::
+set_raw_button_up_event(const string &raw_button_up_event) {
+  _raw_button_up_event = raw_button_up_event;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ButtonThrower::get_raw_button_up_event
+//       Access: Published
+//  Description: Returns the raw_button_up_event that has been set on
+//               this ButtonThrower.  See set_raw_button_up_event().
+////////////////////////////////////////////////////////////////////
+INLINE const string &ButtonThrower::
+get_raw_button_up_event() const {
+  return _raw_button_up_event;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ButtonThrower::set_prefix
 //     Function: ButtonThrower::set_prefix
 //       Access: Published
 //       Access: Published

+ 43 - 5
panda/src/tform/buttonThrower.cxx

@@ -268,16 +268,16 @@ void ButtonThrower::
 do_specific_event(const string &event_name, double time) {
 do_specific_event(const string &event_name, double time) {
   if (_specific_flag) {
   if (_specific_flag) {
     PT(Event) event = new Event(_prefix + event_name);
     PT(Event) event = new Event(_prefix + event_name);
-    
+
     if (_time_flag) {
     if (_time_flag) {
       event->add_parameter(time);
       event->add_parameter(time);
     }
     }
-    
+
     ParameterList::const_iterator pi;
     ParameterList::const_iterator pi;
     for (pi = _parameters.begin(); pi != _parameters.end(); ++pi) {
     for (pi = _parameters.begin(); pi != _parameters.end(); ++pi) {
       event->add_parameter(*pi);
       event->add_parameter(*pi);
     }
     }
-    
+
     throw_event(event);
     throw_event(event);
   }
   }
 }
 }
@@ -318,6 +318,14 @@ do_general_event(const ButtonEvent &button_event, const string &button_name) {
   case ButtonEvent::T_move:
   case ButtonEvent::T_move:
     event_name = _move_event;
     event_name = _move_event;
     break;
     break;
+
+  case ButtonEvent::T_raw_down:
+    event_name = _raw_button_down_event;
+    break;
+
+  case ButtonEvent::T_raw_up:
+    event_name = _raw_button_up_event;
+    break;
   }
   }
   if (event_name.empty()) {
   if (event_name.empty()) {
     // This general event is not configured.
     // This general event is not configured.
@@ -336,6 +344,8 @@ do_general_event(const ButtonEvent &button_event, const string &button_name) {
   case ButtonEvent::T_resume_down:
   case ButtonEvent::T_resume_down:
   case ButtonEvent::T_up:
   case ButtonEvent::T_up:
   case ButtonEvent::T_repeat:
   case ButtonEvent::T_repeat:
+  case ButtonEvent::T_raw_down:
+  case ButtonEvent::T_raw_up:
     event->add_parameter(button_name);
     event->add_parameter(button_name);
     break;
     break;
 
 
@@ -405,7 +415,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
             do_specific_event(event_name, be._time);
             do_specific_event(event_name, be._time);
           }
           }
           do_general_event(be, event_name);
           do_general_event(be, event_name);
-          
+
         } else {
         } else {
           // Don't process this button; instead, pass it down to future
           // Don't process this button; instead, pass it down to future
           // generations.
           // generations.
@@ -418,7 +428,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
         // throw an event now (since we already missed it), but do
         // throw an event now (since we already missed it), but do
         // make sure our modifiers are up-to-date.
         // make sure our modifiers are up-to-date.
         _mods.button_down(be._button);
         _mods.button_down(be._button);
-          
+
       } else if (be._type == ButtonEvent::T_up) {
       } else if (be._type == ButtonEvent::T_up) {
         // Button up.
         // Button up.
         _mods.button_up(be._button);
         _mods.button_up(be._button);
@@ -438,6 +448,34 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
           _button_events->add_event(be);
           _button_events->add_event(be);
         }
         }
 
 
+      } else if (be._type == ButtonEvent::T_raw_down) {
+        // Raw button down.
+        if (!_throw_buttons_active || has_throw_button(be._button)) {
+          // Process this button.
+          do_specific_event("raw-" + event_name, be._time);
+          do_general_event(be, event_name);
+
+        } else {
+          // Don't process this button; instead, pass it down to future
+          // generations.
+          _button_events->add_event(be);
+        }
+
+      } else if (be._type == ButtonEvent::T_raw_up) {
+        // Raw button up.
+        if (!_throw_buttons_active || has_throw_button(be._button)) {
+          // Process this button.
+          do_specific_event("raw-" + event_name + "-up", be._time);
+          do_general_event(be, event_name);
+        }
+        if (_throw_buttons_active) {
+          // Now pass the event on to future generations.  We always
+          // pass "up" events, even if we are intercepting this
+          // particular button; unless we're processing all buttons in
+          // which case it doesn't matter.
+          _button_events->add_event(be);
+        }
+
       } else {
       } else {
         // Some other kind of button event (e.g. keypress).  Don't
         // Some other kind of button event (e.g. keypress).  Don't
         // throw an event for this, but do pass it down.
         // throw an event for this, but do pass it down.

+ 7 - 2
panda/src/tform/buttonThrower.h

@@ -53,6 +53,10 @@ PUBLISHED:
   INLINE const string &get_candidate_event() const;
   INLINE const string &get_candidate_event() const;
   INLINE void set_move_event(const string &move_event);
   INLINE void set_move_event(const string &move_event);
   INLINE const string &get_move_event() const;
   INLINE const string &get_move_event() const;
+  INLINE void set_raw_button_down_event(const string &raw_button_down_event);
+  INLINE const string &get_raw_button_down_event() const;
+  INLINE void set_raw_button_up_event(const string &raw_button_up_event);
+  INLINE const string &get_raw_button_up_event() const;
 
 
   INLINE void set_prefix(const string &prefix);
   INLINE void set_prefix(const string &prefix);
   INLINE const string &get_prefix() const;
   INLINE const string &get_prefix() const;
@@ -61,7 +65,6 @@ PUBLISHED:
 
 
   INLINE void set_time_flag(bool time_flag);
   INLINE void set_time_flag(bool time_flag);
   INLINE bool get_time_flag() const;
   INLINE bool get_time_flag() const;
-  
 
 
   void add_parameter(const EventParameter &obj);
   void add_parameter(const EventParameter &obj);
   int get_num_parameters() const;
   int get_num_parameters() const;
@@ -85,7 +88,7 @@ public:
 
 
 private:
 private:
   void do_specific_event(const string &event_name, double time);
   void do_specific_event(const string &event_name, double time);
-  void do_general_event(const ButtonEvent &button_event, 
+  void do_general_event(const ButtonEvent &button_event,
                         const string &event_name);
                         const string &event_name);
 
 
 private:
 private:
@@ -95,6 +98,8 @@ private:
   string _keystroke_event;
   string _keystroke_event;
   string _candidate_event;
   string _candidate_event;
   string _move_event;
   string _move_event;
+  string _raw_button_up_event;
+  string _raw_button_down_event;
   bool _specific_flag;
   bool _specific_flag;
   string _prefix;
   string _prefix;
   bool _time_flag;
   bool _time_flag;

+ 6 - 0
panda/src/tform/mouseWatcher.cxx

@@ -1539,6 +1539,12 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
       case ButtonEvent::T_move:
       case ButtonEvent::T_move:
         // This is handled below.
         // This is handled below.
         break;
         break;
+
+      case ButtonEvent::T_raw_down:
+      case ButtonEvent::T_raw_up:
+        // These are passed through.
+        new_button_events.add_event(be);
+        break;
       }
       }
     }
     }
   }
   }

+ 131 - 0
panda/src/x11display/x11GraphicsWindow.cxx

@@ -1404,6 +1404,11 @@ handle_keypress(XKeyEvent &event) {
   if (button != ButtonHandle::none()) {
   if (button != ButtonHandle::none()) {
     _input_devices[0].button_down(button);
     _input_devices[0].button_down(button);
   }
   }
+
+  ButtonHandle raw_button = map_raw_button(event.keycode);
+  if (raw_button != ButtonHandle::none()) {
+    _input_devices[0].raw_button_down(raw_button);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1432,6 +1437,11 @@ handle_keyrelease(XKeyEvent &event) {
   if (button != ButtonHandle::none()) {
   if (button != ButtonHandle::none()) {
     _input_devices[0].button_up(button);
     _input_devices[0].button_up(button);
   }
   }
+
+  ButtonHandle raw_button = map_raw_button(event.keycode);
+  if (raw_button != ButtonHandle::none()) {
+    _input_devices[0].raw_button_up(raw_button);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1839,6 +1849,127 @@ map_button(KeySym key) {
   return ButtonHandle::none();
   return ButtonHandle::none();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: x11GraphicsWindow::map_raw_button
+//       Access: Private
+//  Description: Maps from a single X keycode to Panda's ButtonHandle.
+////////////////////////////////////////////////////////////////////
+ButtonHandle x11GraphicsWindow::
+map_raw_button(KeyCode key) {
+  switch (key) {
+  case 9:  return KeyboardButton::escape();
+  case 10: return KeyboardButton::ascii_key('1');
+  case 11: return KeyboardButton::ascii_key('2');
+  case 12: return KeyboardButton::ascii_key('3');
+  case 13: return KeyboardButton::ascii_key('4');
+  case 14: return KeyboardButton::ascii_key('5');
+  case 15: return KeyboardButton::ascii_key('6');
+  case 16: return KeyboardButton::ascii_key('7');
+  case 17: return KeyboardButton::ascii_key('8');
+  case 18: return KeyboardButton::ascii_key('9');
+  case 19: return KeyboardButton::ascii_key('0');
+  case 20: return KeyboardButton::ascii_key('-');
+  case 21: return KeyboardButton::ascii_key('=');
+  case 22: return KeyboardButton::backspace();
+  case 23: return KeyboardButton::tab();
+  case 24: return KeyboardButton::ascii_key('q');
+  case 25: return KeyboardButton::ascii_key('w');
+  case 26: return KeyboardButton::ascii_key('e');
+  case 27: return KeyboardButton::ascii_key('r');
+  case 28: return KeyboardButton::ascii_key('t');
+  case 29: return KeyboardButton::ascii_key('y');
+  case 30: return KeyboardButton::ascii_key('u');
+  case 31: return KeyboardButton::ascii_key('i');
+  case 32: return KeyboardButton::ascii_key('o');
+  case 33: return KeyboardButton::ascii_key('p');
+  case 34: return KeyboardButton::ascii_key('[');
+  case 35: return KeyboardButton::ascii_key(']');
+  case 36: return KeyboardButton::enter();
+  case 37: return KeyboardButton::lcontrol();
+  case 38: return KeyboardButton::ascii_key('a');
+  case 39: return KeyboardButton::ascii_key('s');
+  case 40: return KeyboardButton::ascii_key('d');
+  case 41: return KeyboardButton::ascii_key('f');
+  case 42: return KeyboardButton::ascii_key('g');
+  case 43: return KeyboardButton::ascii_key('h');
+  case 44: return KeyboardButton::ascii_key('j');
+  case 45: return KeyboardButton::ascii_key('k');
+  case 46: return KeyboardButton::ascii_key('l');
+  case 47: return KeyboardButton::ascii_key(';');
+  case 48: return KeyboardButton::ascii_key('\'');
+  case 49: return KeyboardButton::ascii_key('`');
+  case 50: return KeyboardButton::lshift();
+  case 51: return KeyboardButton::ascii_key('\\');
+  case 52: return KeyboardButton::ascii_key('z');
+  case 53: return KeyboardButton::ascii_key('x');
+  case 54: return KeyboardButton::ascii_key('c');
+  case 55: return KeyboardButton::ascii_key('v');
+  case 56: return KeyboardButton::ascii_key('b');
+  case 57: return KeyboardButton::ascii_key('n');
+  case 58: return KeyboardButton::ascii_key('m');
+  case 59: return KeyboardButton::ascii_key(',');
+  case 60: return KeyboardButton::ascii_key('.');
+  case 61: return KeyboardButton::ascii_key('/');
+  case 62: return KeyboardButton::rshift();
+  case 63: return KeyboardButton::ascii_key('*');
+  case 64: return KeyboardButton::lalt();
+  case 65: return KeyboardButton::space();
+  case 66: return KeyboardButton::caps_lock();
+  case 67: return KeyboardButton::f1();
+  case 68: return KeyboardButton::f2();
+  case 69: return KeyboardButton::f3();
+  case 70: return KeyboardButton::f4();
+  case 71: return KeyboardButton::f5();
+  case 72: return KeyboardButton::f6();
+  case 73: return KeyboardButton::f7();
+  case 74: return KeyboardButton::f8();
+  case 75: return KeyboardButton::f9();
+  case 76: return KeyboardButton::f10();
+  case 77: return KeyboardButton::num_lock();
+  case 78: return KeyboardButton::scroll_lock();
+  case 79: return KeyboardButton::ascii_key('7');
+  case 80: return KeyboardButton::ascii_key('8');
+  case 81: return KeyboardButton::ascii_key('9');
+  case 82: return KeyboardButton::ascii_key('-');
+  case 83: return KeyboardButton::ascii_key('4');
+  case 84: return KeyboardButton::ascii_key('5');
+  case 85: return KeyboardButton::ascii_key('6');
+  case 86: return KeyboardButton::ascii_key('+');
+  case 87: return KeyboardButton::ascii_key('1');
+  case 88: return KeyboardButton::ascii_key('2');
+  case 89: return KeyboardButton::ascii_key('3');
+  case 90: return KeyboardButton::ascii_key('0');
+  case 91: return KeyboardButton::ascii_key('.');
+
+  case 95: return KeyboardButton::f11();
+  case 96: return KeyboardButton::f12();
+
+  case 104: return KeyboardButton::enter();
+  case 105: return KeyboardButton::rcontrol();
+  case 106: return KeyboardButton::ascii_key('/');
+  case 107: return KeyboardButton::print_screen();
+  case 108: return KeyboardButton::ralt();
+
+  case 110: return KeyboardButton::home();
+  case 111: return KeyboardButton::up();
+  case 112: return KeyboardButton::page_up();
+  case 113: return KeyboardButton::left();
+  case 114: return KeyboardButton::right();
+  case 115: return KeyboardButton::end();
+  case 116: return KeyboardButton::down();
+  case 117: return KeyboardButton::page_down();
+  case 118: return KeyboardButton::insert();
+  case 119: return KeyboardButton::del();
+
+  case 127: return KeyboardButton::pause();
+
+  //case 133: return KeyboardButton::lmeta();
+  //case 134: return KeyboardButton::rmeta();
+  //case 135: return KeyboardButton::menu();
+  }
+  return ButtonHandle::none();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: x11GraphicsWindow::get_mouse_button
 //     Function: x11GraphicsWindow::get_mouse_button
 //       Access: Private
 //       Access: Private

+ 1 - 0
panda/src/x11display/x11GraphicsWindow.h

@@ -67,6 +67,7 @@ protected:
 
 
   ButtonHandle get_button(XKeyEvent &key_event, bool allow_shift);
   ButtonHandle get_button(XKeyEvent &key_event, bool allow_shift);
   ButtonHandle map_button(KeySym key);
   ButtonHandle map_button(KeySym key);
+  ButtonHandle map_raw_button(KeyCode key);
   ButtonHandle get_mouse_button(XButtonEvent &button_event);
   ButtonHandle get_mouse_button(XButtonEvent &button_event);
 
 
   static Bool check_event(X11_Display *display, XEvent *event, char *arg);
   static Bool check_event(X11_Display *display, XEvent *event, char *arg);