Browse Source

osx plugin key events etc

David Rose 16 years ago
parent
commit
a181e471be

+ 61 - 2
direct/src/plugin/p3dInstance.cxx

@@ -485,24 +485,58 @@ handle_event(P3D_event_data event) {
   case mouseDown:
   case mouseDown:
   case mouseUp:
   case mouseUp:
     {
     {
+      // Need to ensure we have the correct port set, in order to
+      // convert the mouse coordinates successfully via
+      // GlobalToLocal().
+      GrafPtr out_port = _wparams.get_parent_window()._port;
+      GrafPtr portSave = NULL;
+      Boolean portChanged = QDSwapPort(out_port, &portSave);
+
       Point pt = er->where;
       Point pt = er->where;
       GlobalToLocal(&pt);
       GlobalToLocal(&pt);
       P3D_window_handle window = _wparams.get_parent_window();
       P3D_window_handle window = _wparams.get_parent_window();
       cerr << "mouse " << pt.h << " " << pt.v << "\n";
       cerr << "mouse " << pt.h << " " << pt.v << "\n";
       if (_swbuffer != NULL) {
       if (_swbuffer != NULL) {
         SubprocessWindowBuffer::Event swb_event;
         SubprocessWindowBuffer::Event swb_event;
-        swb_event._up = (er->what == mouseUp);
+        swb_event._source = SubprocessWindowBuffer::ES_mouse;
+        swb_event._code = 0;
+        if (er->what == mouseUp) {
+          swb_event._trans = SubprocessWindowBuffer::BT_up;
+        } else {
+          swb_event._trans = SubprocessWindowBuffer::BT_down;
+        }
         swb_event._x = pt.h;
         swb_event._x = pt.h;
         swb_event._y = pt.v;
         swb_event._y = pt.v;
+        swb_event._flags = SubprocessWindowBuffer::EF_mouse_position;
+        add_modifier_flags(swb_event._flags, er->modifiers);
         _swbuffer->add_event(swb_event);
         _swbuffer->add_event(swb_event);
       }
       }
+
+      if (portChanged) {
+        QDSwapPort(portSave, NULL);
+      }
     }
     }
     break;
     break;
 
 
   case keyDown:
   case keyDown:
   case keyUp:
   case keyUp:
   case autoKey:
   case autoKey:
-    cerr << "keycode: " << (er->message & 0xffff) << "\n";
+    cerr << "keycode: " << hex << (er->message & 0xffff) << dec << "\n";
+    if (_swbuffer != NULL) {
+      SubprocessWindowBuffer::Event swb_event;
+      swb_event._source = SubprocessWindowBuffer::ES_keyboard;
+      swb_event._code = er->message;
+      if (er->what == keyUp) {
+        swb_event._trans = SubprocessWindowBuffer::BT_up;
+      } else if (er->what == keyDown) {
+        swb_event._trans = SubprocessWindowBuffer::BT_down;
+      } else {
+        swb_event._trans = SubprocessWindowBuffer::BT_again;
+      }
+      swb_event._flags = 0;
+      add_modifier_flags(swb_event._flags, er->modifiers);
+      _swbuffer->add_event(swb_event);
+    }
     break;
     break;
 
 
   case updateEvt:
   case updateEvt:
@@ -1005,6 +1039,31 @@ paint_window() {
 #endif  // __APPLE__  
 #endif  // __APPLE__  
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::add_modifier_flags
+//       Access: Private
+//  Description: OSX only: adds the appropriate bits to the Event flag
+//               bitmask to correspond to the modifier buttons held in
+//               the MacOS-style EventRecord::modifiers mask.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+add_modifier_flags(unsigned int &swb_flags, int modifiers) {
+#ifdef __APPLE__
+  if (modifiers & cmdKey) {
+    swb_flags |= SubprocessWindowBuffer::EF_meta_held;
+  }
+  if (modifiers & shiftKey) {
+    swb_flags |= SubprocessWindowBuffer::EF_shift_held;
+  }
+  if (modifiers & optionKey) {
+    swb_flags |= SubprocessWindowBuffer::EF_alt_held;
+  }
+  if (modifiers & controlKey) {
+    swb_flags |= SubprocessWindowBuffer::EF_control_held;
+  }
+#endif  // __APPLE__
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::SplashDownload::Constructor
 //     Function: P3DInstance::SplashDownload::Constructor
 //       Access: Public
 //       Access: Public

+ 1 - 0
direct/src/plugin/p3dInstance.h

@@ -108,6 +108,7 @@ private:
   void install_progress(P3DPackage *package, double progress);
   void install_progress(P3DPackage *package, double progress);
 
 
   void paint_window();
   void paint_window();
+  void add_modifier_flags(unsigned int &swb_flags, int modifiers);
 
 
   P3D_request_ready_func *_func;
   P3D_request_ready_func *_func;
   P3D_object *_browser_script_object;
   P3D_object *_browser_script_object;

+ 187 - 26
panda/src/display/subprocessWindow.cxx

@@ -63,6 +63,7 @@ SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
   _mmap_size = 0;
   _mmap_size = 0;
   _filename = filename;
   _filename = filename;
   _swbuffer = NULL;
   _swbuffer = NULL;
+  _last_event_flags = 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -93,14 +94,45 @@ process_events() {
   GraphicsWindow::process_events();
   GraphicsWindow::process_events();
 
 
   if (_swbuffer != NULL) {
   if (_swbuffer != NULL) {
-    SubprocessWindowBuffer::Event event;
-    while (_swbuffer->get_event(event)) {
-      // Deal with this event.  For now, we only have mouse down/up.
-      _input_devices[0].set_pointer_in_window(event._x, event._y);
-      if (event._up) {
-        _input_devices[0].button_up(MouseButton::one());
+    SubprocessWindowBuffer::Event swb_event;
+    while (_swbuffer->get_event(swb_event)) {
+      // Deal with this event.
+      if (swb_event._flags & SubprocessWindowBuffer::EF_mouse_position) {
+        _input_devices[0].set_pointer_in_window(swb_event._x, swb_event._y);
+      }
+
+      unsigned int diff = swb_event._flags ^ _last_event_flags;
+      _last_event_flags = swb_event._flags;
+
+      if (diff & SubprocessWindowBuffer::EF_shift_held) {
+        transition_button(swb_event._flags & SubprocessWindowBuffer::EF_shift_held, KeyboardButton::shift());
+      }
+      if (diff & SubprocessWindowBuffer::EF_control_held) {
+        transition_button(swb_event._flags & SubprocessWindowBuffer::EF_control_held, KeyboardButton::control());
+      }
+      if (diff & SubprocessWindowBuffer::EF_alt_held) {
+        transition_button(swb_event._flags & SubprocessWindowBuffer::EF_alt_held, KeyboardButton::alt());
+      }
+      if (diff & SubprocessWindowBuffer::EF_meta_held) {
+        transition_button(swb_event._flags & SubprocessWindowBuffer::EF_meta_held, KeyboardButton::meta());
+      }
+
+      ButtonHandle button;
+      if (swb_event._source == SubprocessWindowBuffer::ES_mouse) {
+        button = MouseButton::button(swb_event._code);
+
       } else {
       } else {
-        _input_devices[0].button_down(MouseButton::one());
+        int keycode;
+        button = translate_key(keycode, swb_event._code, swb_event._flags);
+        if (keycode != 0 && swb_event._trans != SubprocessWindowBuffer::BT_up) {
+          _input_devices[0].keystroke(keycode);
+        }
+      }
+
+      if (swb_event._trans == SubprocessWindowBuffer::BT_up) {
+        _input_devices[0].button_up(button);
+      } else if (swb_event._trans == SubprocessWindowBuffer::BT_down) {
+        _input_devices[0].button_down(button);
       }
       }
     }
     }
   }
   }
@@ -249,27 +281,156 @@ open_window() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: SubprocessWindow::set_properties_now
-//       Access: Public, Virtual
-//  Description: Applies the requested set of properties to the
-//               window, if possible, for instance to request a change
-//               in size or minimization status.
-//
-//               The window properties are applied immediately, rather
-//               than waiting until the next frame.  This implies that
-//               this method may *only* be called from within the
-//               window thread.
-//
-//               The properties that have been applied are cleared
-//               from the structure by this function; so on return,
-//               whatever remains in the properties structure are
-//               those that were unchanged for some reason (probably
-//               because the underlying interface does not support
-//               changing that property on an open window).
+//     Function: SubprocessWindow::translate_key
+//       Access: Private
+//  Description: Converts the os-specific keycode into the appropriate
+//               ButtonHandle object.  Also stores the corresponding
+//               Unicode keycode in keycode, if any; or 0 otherwise.
+////////////////////////////////////////////////////////////////////
+ButtonHandle SubprocessWindow::
+translate_key(int &keycode, int os_code, unsigned int flags) const {
+  keycode = 0;
+  ButtonHandle nk = ButtonHandle::none();
+
+#ifdef __APPLE__
+  switch ((os_code >> 8) & 0xff) {
+  case   0: nk = KeyboardButton::ascii_key('a'); break;
+  case  11: nk = KeyboardButton::ascii_key('b'); break;
+  case   8: nk = KeyboardButton::ascii_key('c'); break;
+  case   2: nk = KeyboardButton::ascii_key('d'); break;
+  case  14: nk = KeyboardButton::ascii_key('e'); break;
+  case   3: nk = KeyboardButton::ascii_key('f'); break;
+  case   5: nk = KeyboardButton::ascii_key('g'); break;
+  case   4: nk = KeyboardButton::ascii_key('h'); break;
+  case  34: nk = KeyboardButton::ascii_key('i'); break;
+  case  38: nk = KeyboardButton::ascii_key('j'); break;
+  case  40: nk = KeyboardButton::ascii_key('k'); break;
+  case  37: nk = KeyboardButton::ascii_key('l'); break;
+  case  46: nk = KeyboardButton::ascii_key('m'); break;
+  case  45: nk = KeyboardButton::ascii_key('n'); break;
+  case  31: nk = KeyboardButton::ascii_key('o'); break;
+  case  35: nk = KeyboardButton::ascii_key('p'); break;
+  case  12: nk = KeyboardButton::ascii_key('q'); break;
+  case  15: nk = KeyboardButton::ascii_key('r'); break;
+  case   1: nk = KeyboardButton::ascii_key('s'); break;
+  case  17: nk = KeyboardButton::ascii_key('t'); break;
+  case  32: nk = KeyboardButton::ascii_key('u'); break;
+  case   9: nk = KeyboardButton::ascii_key('v'); break;
+  case  13: nk = KeyboardButton::ascii_key('w'); break;
+  case   7: nk = KeyboardButton::ascii_key('x'); break;
+  case  16: nk = KeyboardButton::ascii_key('y'); break;
+  case   6: nk = KeyboardButton::ascii_key('z'); break;
+
+    // top row numbers
+  case  29: nk = KeyboardButton::ascii_key('0'); break;
+  case  18: nk = KeyboardButton::ascii_key('1'); break;
+  case  19: nk = KeyboardButton::ascii_key('2'); break;
+  case  20: nk = KeyboardButton::ascii_key('3'); break;
+  case  21: nk = KeyboardButton::ascii_key('4'); break;
+  case  23: nk = KeyboardButton::ascii_key('5'); break;
+  case  22: nk = KeyboardButton::ascii_key('6'); break;
+  case  26: nk = KeyboardButton::ascii_key('7'); break;
+  case  28: nk = KeyboardButton::ascii_key('8'); break;
+  case  25: nk = KeyboardButton::ascii_key('9'); break;
+
+    // key pad ... do they really map to the top number in panda ?
+  case  82: nk = KeyboardButton::ascii_key('0'); break;
+  case  83: nk = KeyboardButton::ascii_key('1'); break;
+  case  84: nk = KeyboardButton::ascii_key('2'); break;
+  case  85: nk = KeyboardButton::ascii_key('3'); break;
+  case  86: nk = KeyboardButton::ascii_key('4'); break;
+  case  87: nk = KeyboardButton::ascii_key('5'); break;
+  case  88: nk = KeyboardButton::ascii_key('6'); break;
+  case  89: nk = KeyboardButton::ascii_key('7'); break;
+  case  91: nk = KeyboardButton::ascii_key('8'); break;
+  case  92: nk = KeyboardButton::ascii_key('9'); break;
+
+    // case  36: nk = KeyboardButton::ret(); break; // no return in panda ???
+  case  49: nk = KeyboardButton::space(); break;
+  case  51: nk = KeyboardButton::backspace(); break;
+  case  48: nk = KeyboardButton::tab(); break;
+  case  53: nk = KeyboardButton::escape(); break;
+  case  76: nk = KeyboardButton::enter(); break; 
+  case  36: nk = KeyboardButton::enter(); break; 
+
+  case 123: nk = KeyboardButton::left(); break;
+  case 124: nk = KeyboardButton::right(); break;
+  case 125: nk = KeyboardButton::down(); break;
+  case 126: nk = KeyboardButton::up(); break;
+  case 116: nk = KeyboardButton::page_up(); break;
+  case 121: nk = KeyboardButton::page_down(); break;
+  case 115: nk = KeyboardButton::home(); break;
+  case 119: nk = KeyboardButton::end(); break;
+  case 114: nk = KeyboardButton::help(); break; 
+  case 117: nk = KeyboardButton::del(); break; 
+
+    // case  71: nk = KeyboardButton::num_lock() break; 
+
+  case 122: nk = KeyboardButton::f1(); break;
+  case 120: nk = KeyboardButton::f2(); break;
+  case  99: nk = KeyboardButton::f3(); break;
+  case 118: nk = KeyboardButton::f4(); break;
+  case  96: nk = KeyboardButton::f5(); break;
+  case  97: nk = KeyboardButton::f6(); break;
+  case  98: nk = KeyboardButton::f7(); break;
+  case 100: nk = KeyboardButton::f8(); break;
+  case 101: nk = KeyboardButton::f9(); break;
+  case 109: nk = KeyboardButton::f10(); break;
+  case 103: nk = KeyboardButton::f11(); break;
+  case 111: nk = KeyboardButton::f12(); break;
+
+  case 105: nk = KeyboardButton::f13(); break;
+  case 107: nk = KeyboardButton::f14(); break;
+  case 113: nk = KeyboardButton::f15(); break;
+  case 106: nk = KeyboardButton::f16(); break;
+
+    // shiftable chartablet 
+  case  50: nk = KeyboardButton::ascii_key('`'); break;
+  case  27: nk = KeyboardButton::ascii_key('-'); break;
+  case  24: nk = KeyboardButton::ascii_key('='); break;
+  case  33: nk = KeyboardButton::ascii_key('['); break;
+  case  30: nk = KeyboardButton::ascii_key(']'); break;
+  case  42: nk = KeyboardButton::ascii_key('\\'); break;
+  case  41: nk = KeyboardButton::ascii_key(';'); break;
+  case  39: nk = KeyboardButton::ascii_key('\''); break;
+  case  43: nk = KeyboardButton::ascii_key(','); break;
+  case  47: nk = KeyboardButton::ascii_key('.'); break;
+  case  44: nk = KeyboardButton::ascii_key('/'); break;
+
+  default:
+    // Punt.
+    nk = KeyboardButton::ascii_key(os_code & 0xff); 
+  }
+
+  if (nk.has_ascii_equivalent()) {
+    // If we assigned an ASCII button, then get the original ASCII
+    // code from the event (it will include shift et al).
+
+    // TODO: is it possible to get any international characters via
+    // this old EventRecord interface?
+    keycode = os_code & 0xff;
+  }
+  
+#endif __APPLE__
+
+  return nk;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubprocessWindow::transition_button
+//       Access: Private
+//  Description: Sends the appropriate up/down transition for the
+//               indicated modifier key, as determined implicitly from
+//               the flags.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SubprocessWindow::
 void SubprocessWindow::
-set_properties_now(WindowProperties &properties) {
-  GraphicsWindow::set_properties_now(properties);
+transition_button(unsigned int flags, ButtonHandle button) {
+  if (flags) {
+    _input_devices[0].button_down(button);
+  } else {  
+    _input_devices[0].button_up(button);
+  }
 }
 }
 
 
+
 #endif  // SUPPORT_SUBPROCESS_WINDOW
 #endif  // SUPPORT_SUBPROCESS_WINDOW

+ 6 - 2
panda/src/display/subprocessWindow.h

@@ -65,12 +65,14 @@ public:
   virtual void end_frame(FrameMode mode, Thread *current_thread);
   virtual void end_frame(FrameMode mode, Thread *current_thread);
   virtual void begin_flip();
   virtual void begin_flip();
 
 
-  virtual void set_properties_now(WindowProperties &properties);
-
 protected:
 protected:
   virtual void close_window();
   virtual void close_window();
   virtual bool open_window();
   virtual bool open_window();
 
 
+private:
+  ButtonHandle translate_key(int &keycode, int os_code, unsigned int flags) const;
+  void transition_button(unsigned int flag, ButtonHandle button);
+
 private:
 private:
   PT(GraphicsBuffer) _buffer;
   PT(GraphicsBuffer) _buffer;
   PT(Texture) _texture;
   PT(Texture) _texture;
@@ -80,6 +82,8 @@ private:
   string _filename;
   string _filename;
   SubprocessWindowBuffer *_swbuffer;
   SubprocessWindowBuffer *_swbuffer;
 
 
+  unsigned int _last_event_flags;
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 25 - 3
panda/src/display/subprocessWindowBuffer.h

@@ -75,11 +75,33 @@ public:
   inline void *open_write_framebuffer();
   inline void *open_write_framebuffer();
   inline void close_write_framebuffer();
   inline void close_write_framebuffer();
 
 
+  enum EventSource {
+    ES_mouse,
+    ES_keyboard
+  };
+  
+  enum ButtonTransition {
+    BT_down,
+    BT_up,
+    BT_again  // if supported
+  };
+
+  enum EventFlags {
+    EF_mouse_position = 0x0001,
+    EF_shift_held     = 0x0002,
+    EF_control_held   = 0x0004,
+    EF_alt_held       = 0x0008,
+    EF_meta_held      = 0x0010,
+    EF_caps_lock      = 0x0020,
+  };
+
   class Event {
   class Event {
   public:
   public:
-    // int _key;  TODO.
-    bool _up;
-    int _x, _y;  // position of mouse at the time of the event
+    EventSource _source;
+    int _code;  // mouse button, or os-specific keycode.
+    ButtonTransition _trans;
+    int _x, _y;  // position of mouse at the time of the event, if EF_mouse_position is set
+    unsigned int _flags;
   };
   };
 
 
   inline bool add_event(const Event &event);
   inline bool add_event(const Event &event);