Browse Source

Merge remote-tracking branch 'eswartz/support-mouse-confinement-cocoa' into release/1.9.x
Closes: #20

rdb 10 years ago
parent
commit
573af61636

+ 47 - 3
panda/src/cocoadisplay/cocoaGraphicsWindow.mm

@@ -1026,6 +1026,23 @@ set_properties_now(WindowProperties &properties) {
     }
     properties.clear_z_order();
   }
+
+  if (properties.has_mouse_mode()) {
+    switch (properties.get_mouse_mode()) {
+    case WindowProperties::M_absolute:
+    case WindowProperties::M_confined:  // confined is maintained in mouse move event
+      CGAssociateMouseAndMouseCursorPosition(true);
+      _properties.set_mouse_mode(properties.get_mouse_mode());
+      properties.clear_mouse_mode();
+      break;
+
+    case WindowProperties::M_relative:
+      CGAssociateMouseAndMouseCursorPosition(false);
+      _properties.set_mouse_mode(properties.get_mouse_mode());
+      properties.clear_mouse_mode();
+      break;
+    }
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1674,6 +1691,8 @@ handle_mouse_button_event(int button, bool down) {
 ////////////////////////////////////////////////////////////////////
 void CocoaGraphicsWindow::
 handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
+  double nx, ny;
+
   if (absolute) {
     if (cocoadisplay_cat.is_spam()) {
       if (in_window != _input_devices[0].get_pointer().get_in_window()) {
@@ -1686,15 +1705,40 @@ handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
     }
 
     // Strangely enough, in Cocoa, mouse Y coordinates are 1-based.
-    _input_devices[0].set_pointer(in_window, x, y - 1,
-      ClockObject::get_global_clock()->get_frame_time());
+    nx = x;
+    ny = y - 1;
 
   } else {
     // We received deltas, so add it to the current mouse position.
     MouseData md = _input_devices[0].get_pointer();
-    _input_devices[0].set_pointer_in_window(md.get_x() + x, md.get_y() + y);
+    nx = md.get_x() + x;
+    ny = md.get_y() + y;
   }
 
+  if (_properties.get_mouse_mode() == WindowProperties::M_confined
+      && !in_window) {
+    CGPoint point;
+
+    nx = std::max(0., std::min((double) get_x_size() - 1, nx));
+    ny = std::max(0., std::min((double) get_y_size() - 1, ny));
+
+    if (_properties.get_fullscreen()) {
+      point = CGPointMake(nx, ny + 1);
+    } else {
+      point = CGPointMake(nx + _properties.get_x_origin(),
+                          ny + _properties.get_y_origin() + 1);
+    }
+
+    if (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
+      in_window = true;
+    } else {
+      cocoadisplay_cat.warning() << "Failed to return mouse pointer to window\n";
+    }
+  }
+
+  _input_devices[0].set_pointer(in_window, nx, ny,
+      ClockObject::get_global_clock()->get_frame_time());
+
   if (in_window != _mouse_hidden && _properties.get_cursor_hidden()) {
     // Hide the cursor if the mouse enters the window,
     // and unhide it when the mouse leaves the window.

+ 4 - 1
panda/src/cocoadisplay/cocoaPandaView.mm

@@ -118,7 +118,10 @@
   NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
   BOOL inside = [self mouse:loc inRect:[self bounds]];
 
-  if (_graphicsWindow->get_properties().get_mouse_mode() == WindowProperties::M_relative) {
+  // the correlation between mouse deltas and location
+  // are "debounced" apparently, so send deltas for both
+  // relative and confined modes
+  if (_graphicsWindow->get_properties().get_mouse_mode() != WindowProperties::M_absolute) {
     _graphicsWindow->handle_mouse_moved_event(inside, [event deltaX], [event deltaY], false);
   } else {
     _graphicsWindow->handle_mouse_moved_event(inside, loc.x, loc.y, true);

+ 19 - 0
panda/src/osxdisplay/osxGraphicsWindow.mm

@@ -2064,6 +2064,25 @@ set_properties_now(WindowProperties &properties) {
     properties.clear_minimized();
   }
 
+  if (properties.has_mouse_mode()) {
+    switch (properties.get_mouse_mode()) {
+    case WindowProperties::M_absolute:
+      CGAssociateMouseAndMouseCursorPosition(true);
+      _properties.set_mouse_mode(WindowProperties::M_absolute);
+      properties.clear_mouse_mode();
+      break;
+
+    case WindowProperties::M_relative:
+      CGAssociateMouseAndMouseCursorPosition(false);
+      _properties.set_mouse_mode(WindowProperties::M_relative);
+      properties.clear_mouse_mode();
+      break;
+
+    case WindowProperties::M_confined:
+      break;
+    }
+  }
+
   if (osxdisplay_cat.is_debug()) {
     osxdisplay_cat.debug()
       << "set_properties_now Out....." << _properties << "\n";

+ 6 - 4
samples/mouse-modes/main.py

@@ -34,7 +34,8 @@ class App(ShowBase):
         # Disable the camera trackball controls.
         self.disableMouse()
         
-        self.mouseMagnitude = 144
+        # control mapping of mouse movement to box movement
+        self.mouseMagnitude = 1
 
         self.rotateX, self.rotateY = 0, 0
 
@@ -146,7 +147,8 @@ class App(ShowBase):
         if self.manualRecenterMouse:
             # move mouse back to center
             self.recenterMouse()             
-
+            self.lastMouseX, self.lastMouseY = 0, 0  
+                
         # scale position and delta to pixels for user
         w, h = self.win.getSize()
         
@@ -158,8 +160,8 @@ class App(ShowBase):
              int(dx*w), int(dy*h))) 
 
         # rotate box by delta
-        self.rotateX += dx * 10
-        self.rotateY += dy * 10
+        self.rotateX += dx * 10 * self.mouseMagnitude
+        self.rotateY += dy * 10 * self.mouseMagnitude
 
         self.positionText.setText("Model rotation: {0}, {1}".format(
              int(self.rotateX*1000)/1000., int(self.rotateY*1000)/1000.))