Browse Source

Merge branch 'release/1.9.x'

rdb 10 years ago
parent
commit
24ec0d6c46

+ 8 - 0
direct/src/plugin/p3dCert.cxx

@@ -157,6 +157,10 @@ AuthDialog(const string &cert_filename, const string &cert_dir) :
   _stack = NULL;
   _verify_result = -1;
 
+  // Center the window on the screen.
+  position((Fl::w() - w()) / 2, (Fl::h() - h()) / 2);
+  set_modal();
+
   read_cert_file(cert_filename);
   get_friendly_name();
   verify_cert();
@@ -583,6 +587,10 @@ ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) :
   _auth_dialog(auth_dialog),
   _cert(cert)
 {
+  // Center the window on the screen.
+  position((Fl::w() - w()) / 2, (Fl::h() - h()) / 2);
+  set_modal();
+
   layout();
 }
 

+ 17 - 9
panda/src/display/get_x11.h

@@ -17,7 +17,7 @@
 
 #include "pandabase.h"
 
-#ifdef HAVE_X11 
+#ifdef HAVE_X11
 // This header file is designed to help work around some of the
 // namespace spamming that X11 causes, by renaming the symbols that
 // X11 declares that are known to conflict with other library names
@@ -30,14 +30,21 @@
 #ifdef CPPPARSER
 // A simple hack so interrogate can get all of the necessary
 // typenames.
-typedef int X11_Display;
-typedef int X11_Window;
-typedef int X11_Cursor;
-typedef int XErrorEvent;
-typedef int XVisualInfo;
-typedef int Atom;
-typedef int XIM;
-typedef int XIC;
+typedef struct _XDisplay X11_Display;
+typedef unsigned int XID;
+typedef unsigned int Atom;
+typedef unsigned int Cardinal;
+typedef XID Colormap;
+typedef XID X11_Window;
+typedef XID X11_Cursor;
+typedef struct _XIM *XIM;
+typedef struct _XIC *XIC;
+struct XErrorEvent;
+struct XVisualInfo;
+#define Bool int
+#define Status int
+#define True 1
+#define False 0
 #else
 
 #include "pre_x11_include.h"
@@ -45,6 +52,7 @@ typedef int XIC;
 #include <X11/Xutil.h>
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
 
 #ifdef HAVE_XRANDR
 #include <X11/extensions/Xrandr.h>

+ 48 - 0
panda/src/display/graphicsOutput.I

@@ -207,6 +207,20 @@ get_y_size() const {
   return _size.get_y();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_fb_size
+//       Access: Published
+//  Description: Returns the internal size of the window or buffer.
+//               This is almost always the same as get_size(),
+//               except when a pixel_zoom is in effect--see
+//               set_pixel_zoom().
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase2i GraphicsOutput::
+get_fb_size() const {
+  return LVecBase2i(max(int(_size.get_x() * get_pixel_factor()), 1),
+                    max(int(_size.get_y() * get_pixel_factor()), 1));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::get_fb_x_size
 //       Access: Published
@@ -233,6 +247,23 @@ get_fb_y_size() const {
   return max(int(_size.get_y() * get_pixel_factor()), 1);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_sbs_left_size
+//       Access: Published
+//  Description: If side-by-side stereo is enabled, this returns the
+//               pixel size of the left eye, based on scaling
+//               get_size() by get_sbs_left_dimensions().  If
+//               side-by-side stereo is not enabled, this returns the
+//               same as get_size().
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase2i GraphicsOutput::
+get_sbs_left_size() const {
+  PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
+  PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
+  return LVecBase2i(max(int(_size.get_x() * left_w), 1),
+                    max(int(_size.get_y() * left_h), 1));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::get_sbs_left_x_size
 //       Access: Published
@@ -263,6 +294,23 @@ get_sbs_left_y_size() const {
   return max(int(_size.get_y() * left_h), 1);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_sbs_right_size
+//       Access: Published
+//  Description: If side-by-side stereo is enabled, this returns the
+//               pixel size of the right eye, based on scaling
+//               get_size() by get_sbs_right_dimensions().  If
+//               side-by-side stereo is not enabled, this returns the
+//               same as get_size().
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase2i GraphicsOutput::
+get_sbs_right_size() const {
+  PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
+  PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
+  return LVecBase2i(max(int(_size.get_x() * right_w), 1),
+                    max(int(_size.get_y() * right_h), 1));
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::get_sbs_right_x_size
 //       Access: Published

+ 3 - 0
panda/src/display/graphicsOutput.h

@@ -135,10 +135,13 @@ PUBLISHED:
   INLINE const LVecBase2i &get_size() const;
   INLINE int get_x_size() const;
   INLINE int get_y_size() const;
+  INLINE LVecBase2i get_fb_size() const;
   INLINE int get_fb_x_size() const;
   INLINE int get_fb_y_size() const;
+  INLINE LVecBase2i get_sbs_left_size() const;
   INLINE int get_sbs_left_x_size() const;
   INLINE int get_sbs_left_y_size() const;
+  INLINE LVecBase2i get_sbs_right_size() const;
   INLINE int get_sbs_right_x_size() const;
   INLINE int get_sbs_right_y_size() const;
   INLINE bool has_size() const;

+ 4 - 18
panda/src/display/graphicsWindow.cxx

@@ -736,24 +736,10 @@ set_properties_now(WindowProperties &properties) {
     // Fullscreen property specified, but unchanged.
     properties.clear_fullscreen();
   }
-  if (properties.has_mouse_mode() ) {
-    
-    if (properties.get_mouse_mode() == _properties.get_mouse_mode()) {  
-      properties.clear_mouse_mode();
-    }
-    else {
-      if(properties.get_mouse_mode() == WindowProperties::M_absolute) {
-        _properties.set_mouse_mode(WindowProperties::M_absolute);
-        mouse_mode_absolute();
-        properties.clear_mouse_mode();
-      }
-      else
-      {
-        _properties.set_mouse_mode(WindowProperties::M_relative);
-        mouse_mode_relative();
-        properties.clear_mouse_mode();        
-      }    
-    }
+  if (properties.has_mouse_mode() &&
+      properties.get_mouse_mode() == _properties.get_mouse_mode()) {
+    // Mouse mode specified, but unchanged.
+    properties.clear_mouse_mode();
   }
 }
 

+ 23 - 12
panda/src/display/windowProperties.I

@@ -798,19 +798,30 @@ clear_z_order() {
 //     Function: WindowProperties::set_mouse_mode
 //       Access: Published
 //  Description: Specifies the mode in which the window is to operate
-//               its mouse pointer.  The default is M_absolute, which
-//               is the normal mode in which a mouse pointer operates;
-//               but you can also set M_relative, which is
-//               particularly useful for FPS-style mouse movements
-//               where you have hidden the mouse pointer and are are
-//               more interested in how fast the mouse is moving,
-//               rather than precisely where the pointer is hovering.
+//               its mouse pointer.
+//
+//               M_absolute: the normal mode in which a mouse pointer
+//               operates, where the mouse can move outside the window
+//               and the mouse coordinates are relative to its
+//               position in the window.
+//
+//               M_relative (OSX or Unix/X11 only): a mode where only
+//               relative movements are reported; particularly useful
+//               for FPS-style mouse movements where you have hidden
+//               the mouse pointer and are are more interested in how
+//               fast the mouse is moving, rather than precisely where
+//               the pointer is hovering.
+//
+//               This has no effect on Windows.  On Unix/X11, this
+//               requires the Xxf86dga extension to be available.
+//
+//               M_confined: this mode reports absolute mouse
+//               positions, but confines the mouse pointer to
+//               the window boundary.  It can portably replace
+//               M_relative for an FPS, but you need to periodically
+//               move the pointer to the center of the window
+//               and track movement deltas.
 //
-//               This has no effect on Windows, which does not
-//               have this concept; but is important to do on OSX
-//               and Unix/X11 to properly enable a smooth FPS-style
-//               mouselook mode.  On Unix/X11, this requires the
-//               Xxf86dga extension to be available.
 ////////////////////////////////////////////////////////////////////
 INLINE void WindowProperties::
 set_mouse_mode(MouseMode mode) {

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

@@ -400,6 +400,8 @@ operator << (ostream &out, WindowProperties::MouseMode mode) {
     return out << "absolute";
   case WindowProperties::M_relative:
     return out << "relative";
+  case WindowProperties::M_confined:
+    return out << "confined";
   }
   return out << "**invalid WindowProperties::MouseMode(" << (int)mode << ")**";
 }
@@ -413,6 +415,8 @@ operator >> (istream &in, WindowProperties::MouseMode &mode) {
     mode = WindowProperties::M_absolute;
   } else if (word == "relative") {
     mode = WindowProperties::M_relative;
+  } else if (word == "confined") {
+    mode = WindowProperties::M_confined;
   } else {
     display_cat.warning()
       << "Unknown mouse mode: " << word << "\n";

+ 1 - 0
panda/src/display/windowProperties.h

@@ -40,6 +40,7 @@ PUBLISHED:
   enum MouseMode {
     M_absolute,
     M_relative,
+    M_confined,
   };
 
   WindowProperties();

+ 8 - 4
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -6979,16 +6979,20 @@ query_gl_version() {
       _gl_shadlang_ver_major = 1;
       _gl_shadlang_ver_minor = 1;
       const char *verstr = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
-      if (verstr == NULL || sscanf(verstr, "%d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2) {
-        GLCAT.warning()  << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
+      if (verstr == NULL ||
+          sscanf(verstr, "%d.%d", &_gl_shadlang_ver_major,
+                                  &_gl_shadlang_ver_minor) != 2) {
+        GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
       }
     }
 #elif defined(OPENGLES_2)
     _gl_shadlang_ver_major = 1;
     _gl_shadlang_ver_minor = 0;
     const char *verstr = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
-    if (verstr == NULL || sscanf(verstr, "OpenGL ES GLSL %d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2) {
-      GLCAT.warning()  << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
+    if (verstr == NULL ||
+        sscanf(verstr, "OpenGL ES GLSL %d.%d", &_gl_shadlang_ver_major,
+                                               &_gl_shadlang_ver_minor) != 2) {
+      GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
     }
 #endif
   }

+ 1 - 1
panda/src/gobj/config_gobj.cxx

@@ -279,7 +279,7 @@ ConfigVariableBool vertices_float64
           "slower."));
 
 ConfigVariableInt vertex_column_alignment
-("vertex-column-alignment", 1,
+("vertex-column-alignment", 4,
  PRC_DESC("This specifies the default byte alignment for each column of "
           "data within a GeomVertexData when it is assembled using the default "
           "interfaces.  Normally, you should not change this config variable "

+ 2 - 0
panda/src/mathutil/boundingVolume.h

@@ -56,12 +56,14 @@ PUBLISHED:
 
   INLINE_MATHUTIL bool extend_by(const BoundingVolume *vol);
 
+public:
   // It might be nice to make these template member functions so we
   // could have true STL-style first/last iterators, but that's
   // impossible for virtual functions.
   bool around(const BoundingVolume **first,
               const BoundingVolume **last);
 
+PUBLISHED:
   // The contains() functions return the union of one or more of these
   // bits.
   enum IntersectionFlags {

+ 2 - 0
panda/src/mathutil/geometricBoundingVolume.h

@@ -36,6 +36,7 @@ PUBLISHED:
   INLINE_MATHUTIL bool extend_by(const GeometricBoundingVolume *vol);
   INLINE_MATHUTIL bool extend_by(const LPoint3 &point);
 
+public:
   // It might be nice to make these template member functions so we
   // could have true STL-style first/last iterators, but that's
   // impossible for virtual functions.
@@ -43,6 +44,7 @@ PUBLISHED:
                               const GeometricBoundingVolume **last);
   INLINE_MATHUTIL bool around(const LPoint3 *first, const LPoint3 *last);
 
+PUBLISHED:
   INLINE_MATHUTIL int contains(const GeometricBoundingVolume *vol) const;
   INLINE_MATHUTIL int contains(const LPoint3 &point) const;
   INLINE_MATHUTIL int contains(const LPoint3 &a, const LPoint3 &b) const;

+ 44 - 0
panda/src/windisplay/winGraphicsWindow.cxx

@@ -35,6 +35,8 @@ WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
 WinGraphicsWindow *WinGraphicsWindow::_cursor_window = NULL;
 bool WinGraphicsWindow::_cursor_hidden = false;
 
+RECT WinGraphicsWindow::_mouse_unconfined_cliprect;
+
 // These are used to save the previous state of the fancy Win2000
 // effects that interfere with rendering when the mouse wanders into a
 // window's client area.
@@ -359,6 +361,48 @@ set_properties_now(WindowProperties &properties) {
       }
     }
   }
+
+  if (properties.has_mouse_mode()) {
+    if (properties.get_mouse_mode() != _properties.get_mouse_mode()) {
+      switch (properties.get_mouse_mode()) {
+      case WindowProperties::M_absolute:
+      case WindowProperties::M_relative:    // not implemented, treat as absolute
+
+        if (_properties.get_mouse_mode() == WindowProperties::M_confined) {
+          ClipCursor(NULL);
+          windisplay_cat.info() << "Unconfining cursor from window\n";
+        }
+        _properties.set_mouse_mode(WindowProperties::M_absolute);
+        break;
+
+      case WindowProperties::M_confined:
+        {
+          RECT clip;
+
+          if (!GetWindowRect(_hWnd, &clip)) {
+            windisplay_cat.warning()
+                << "GetWindowRect() failed in set_properties_now.  Cannot confine cursor.\n";
+          } else {
+            windisplay_cat.info()
+                    << "ClipCursor() to " << clip.left << "," << clip.top << " to "
+                    << clip.right << "," << clip.bottom << endl;
+
+            GetClipCursor(&_mouse_unconfined_cliprect);
+            if (!ClipCursor(&clip)) {
+              windisplay_cat.warning()
+                      << "ClipCursor() failed in set_properties_now.  Ignoring.\n";
+            } else {
+              _properties.set_mouse_mode(WindowProperties::M_confined);
+              windisplay_cat.info() << "Confining cursor to window\n";
+            }
+          }
+        }
+        break;
+      }
+    }
+    properties.clear_mouse_mode();
+  }
+
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/windisplay/winGraphicsWindow.h

@@ -214,6 +214,9 @@ private:
   static BOOL _saved_cursor_shadow;
   static BOOL _saved_mouse_vanish;
 
+  // The mouse constraints before applying mouse mode M_confined.
+  static RECT _mouse_unconfined_cliprect;
+
   // Since the Panda API requests icons and cursors by filename, we
   // need a table mapping filenames to handles, so we can avoid
   // re-reading the file each time we change icons.

+ 1 - 0
panda/src/x11display/x11GraphicsPipe.cxx

@@ -140,6 +140,7 @@ x11GraphicsPipe(const string &display) {
 
   // Get some X atom numbers.
   _wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
+  _net_wm_pid = XInternAtom(_display, "_NET_WM_PID", false);
   _net_wm_window_type = XInternAtom(_display, "_NET_WM_WINDOW_TYPE", false);
   _net_wm_window_type_splash = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_SPLASH", false);
   _net_wm_window_type_fullscreen = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_FULLSCREEN", false);

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

@@ -52,6 +52,7 @@ public:
 public:
   // Atom specifications.
   Atom _wm_delete_window;
+  Atom _net_wm_pid;
   Atom _net_wm_window_type;
   Atom _net_wm_window_type_splash;
   Atom _net_wm_window_type_fullscreen;

+ 115 - 70
panda/src/x11display/x11GraphicsWindow.cxx

@@ -105,15 +105,6 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
   _awaiting_configure = false;
   _dga_mouse_enabled = false;
   _wm_delete_window = x11_pipe->_wm_delete_window;
-  _net_wm_window_type = x11_pipe->_net_wm_window_type;
-  _net_wm_window_type_splash = x11_pipe->_net_wm_window_type_splash;
-  _net_wm_window_type_fullscreen = x11_pipe->_net_wm_window_type_fullscreen;
-  _net_wm_state = x11_pipe->_net_wm_state;
-  _net_wm_state_fullscreen = x11_pipe->_net_wm_state_fullscreen;
-  _net_wm_state_above = x11_pipe->_net_wm_state_above;
-  _net_wm_state_below = x11_pipe->_net_wm_state_below;
-  _net_wm_state_add = x11_pipe->_net_wm_state_add;
-  _net_wm_state_remove = x11_pipe->_net_wm_state_remove;
 
   GraphicsWindowInputDevice device =
     GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
@@ -175,7 +166,6 @@ move_pointer(int device, int x, int y) {
   }
 }
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: x11GraphicsWindow::begin_frame
 //       Access: Public, Virtual
@@ -711,6 +701,88 @@ set_properties_now(WindowProperties &properties) {
     properties.clear_foreground();
   }
 
+  if (properties.has_mouse_mode()) {
+    switch (properties.get_mouse_mode()) {
+    case WindowProperties::M_absolute:
+      XUngrabPointer(_display, CurrentTime);
+#ifdef HAVE_XF86DGA
+      if (_dga_mouse_enabled) {
+        x11display_cat.info() << "Disabling relative mouse using XF86DGA extension\n";
+        XF86DGADirectVideo(_display, _screen, 0);
+        _dga_mouse_enabled = false;
+      }
+#endif
+      _properties.set_mouse_mode(WindowProperties::M_absolute);
+      properties.clear_mouse_mode();
+      break;
+
+    case WindowProperties::M_relative:
+#ifdef HAVE_XF86DGA
+      if (!_dga_mouse_enabled) {
+        int major_ver, minor_ver;
+        if (XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
+
+          X11_Cursor cursor = None;
+          if (_properties.get_cursor_hidden()) {
+            x11GraphicsPipe *x11_pipe;
+            DCAST_INTO_V(x11_pipe, _pipe);
+            cursor = x11_pipe->get_hidden_cursor();
+          }
+
+          if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
+              GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
+            x11display_cat.error() << "Failed to grab pointer!\n";
+          } else {
+            x11display_cat.info() << "Enabling relative mouse using XF86DGA extension\n";
+            XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse);
+
+            _properties.set_mouse_mode(WindowProperties::M_relative);
+            properties.clear_mouse_mode();
+            _dga_mouse_enabled = true;
+
+            // Get the real mouse position, so we can add/subtract
+            // our relative coordinates later.
+            XEvent event;
+            XQueryPointer(_display, _xwindow, &event.xbutton.root,
+              &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
+              &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
+            _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
+          }
+        } else {
+          x11display_cat.info() << "XF86DGA extension not available\n";
+          _dga_mouse_enabled = false;
+        }
+      }
+#endif
+      break;
+
+    case WindowProperties::M_confined:
+      {
+#ifdef HAVE_XF86DGA
+        if (_dga_mouse_enabled) {
+          XF86DGADirectVideo(_display, _screen, 0);
+          _dga_mouse_enabled = false;
+        }
+#endif
+        X11_Cursor cursor = None;
+        if (_properties.get_cursor_hidden()) {
+          x11GraphicsPipe *x11_pipe;
+          DCAST_INTO_V(x11_pipe, _pipe);
+          cursor = x11_pipe->get_hidden_cursor();
+        }
+
+        if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
+            GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
+          x11display_cat.error() << "Failed to grab pointer!\n";
+        } else {
+          _properties.set_mouse_mode(WindowProperties::M_confined);
+          properties.clear_mouse_mode();
+        }
+      }
+      break;
+    }
+  }
+
   set_wm_properties(wm_properties, true);
 }
 
@@ -721,14 +793,7 @@ set_properties_now(WindowProperties &properties) {
 ////////////////////////////////////////////////////////////////////
 void x11GraphicsWindow::
 mouse_mode_absolute() {
-#ifdef HAVE_XF86DGA
-  if (!_dga_mouse_enabled) return;
-
-  XUngrabPointer(_display, CurrentTime);
-  x11display_cat.info() << "Disabling relative mouse using XF86DGA extension\n";
-  XF86DGADirectVideo(_display, _screen, 0);
-  _dga_mouse_enabled = false;
-#endif
+  // unused: remove in 1.10!
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -738,42 +803,7 @@ mouse_mode_absolute() {
 ////////////////////////////////////////////////////////////////////
 void x11GraphicsWindow::
 mouse_mode_relative() {
-#ifdef HAVE_XF86DGA
-  if (_dga_mouse_enabled) return;
-
-  int major_ver, minor_ver;
-  if (XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
-
-    X11_Cursor cursor = None;
-    if (_properties.get_cursor_hidden()) {
-      x11GraphicsPipe *x11_pipe;
-      DCAST_INTO_V(x11_pipe, _pipe);
-      cursor = x11_pipe->get_hidden_cursor();
-    }
-
-    if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
-        GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
-      x11display_cat.error() << "Failed to grab pointer!\n";
-      return;
-    }
-
-    x11display_cat.info() << "Enabling relative mouse using XF86DGA extension\n";
-    XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse);
-
-    _dga_mouse_enabled = true;
-  } else {
-    x11display_cat.info() << "XF86DGA extension not available\n";
-    _dga_mouse_enabled = false;
-  }
-
-  // Get the real mouse position, so we can add/subtract
-  // our relative coordinates later.
-  XEvent event;
-  XQueryPointer(_display, _xwindow, &event.xbutton.root,
-    &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
-    &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
-  _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
-#endif
+  // unused: remove in 1.10!
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -997,6 +1027,9 @@ open_window() {
 ////////////////////////////////////////////////////////////////////
 void x11GraphicsWindow::
 set_wm_properties(const WindowProperties &properties, bool already_mapped) {
+  x11GraphicsPipe *x11_pipe;
+  DCAST_INTO_V(x11_pipe, _pipe);
+
   // Name the window if there is a name
   XTextProperty window_name;
   XTextProperty *window_name_p = (XTextProperty *)NULL;
@@ -1077,15 +1110,15 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
   if (properties.get_fullscreen()) {
     // For a "fullscreen" request, we pass this through, hoping the
     // window manager will support EWMH.
-    type_data[next_type_data++] = _net_wm_window_type_fullscreen;
+    type_data[next_type_data++] = x11_pipe->_net_wm_window_type_fullscreen;
 
     // We also request it as a state.
-    state_data[next_state_data++] = _net_wm_state_fullscreen;
+    state_data[next_state_data++] = x11_pipe->_net_wm_state_fullscreen;
     // Don't ask me why this has to be 1/0 and not _net_wm_state_add.
     // It doesn't seem to work otherwise.
-    set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, 1);
+    set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 1);
   } else {
-    set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, 0);
+    set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0);
   }
 
   // If we asked for a window without a border, there's no excellent
@@ -1112,26 +1145,32 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
   }
 
   if (properties.get_undecorated() && !properties.get_fullscreen()) {
-    type_data[next_type_data++] = _net_wm_window_type_splash;
+    type_data[next_type_data++] = x11_pipe->_net_wm_window_type_splash;
   }
 
   if (properties.has_z_order()) {
     switch (properties.get_z_order()) {
     case WindowProperties::Z_bottom:
-      state_data[next_state_data++] = _net_wm_state_below;
-      set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_add);
-      set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove);
+      state_data[next_state_data++] = x11_pipe->_net_wm_state_below;
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
+                                            x11_pipe->_net_wm_state_add);
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
+                                            x11_pipe->_net_wm_state_remove);
       break;
 
     case WindowProperties::Z_normal:
-      set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove);
-      set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove);
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
+                                            x11_pipe->_net_wm_state_remove);
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
+                                            x11_pipe->_net_wm_state_remove);
       break;
 
     case WindowProperties::Z_top:
-      state_data[next_state_data++] = _net_wm_state_above;
-      set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove);
-      set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_add);
+      state_data[next_state_data++] = x11_pipe->_net_wm_state_above;
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
+                                            x11_pipe->_net_wm_state_remove);
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
+                                            x11_pipe->_net_wm_state_add);
       break;
     }
   }
@@ -1140,12 +1179,18 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
   nassertv(next_state_data < max_state_data);
   nassertv(next_set_data < max_set_data);
 
-  XChangeProperty(_display, _xwindow, _net_wm_window_type,
+  // Add the process ID as a convenience for other applications.
+  Cardinal pid = getpid();
+  XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_pid,
+                  XA_CARDINAL, 32, PropModeReplace,
+                  (unsigned char *)&pid, 1);
+
+  XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_window_type,
                   XA_ATOM, 32, PropModeReplace,
                   (unsigned char *)type_data, next_type_data);
 
   // Request the state properties all at once.
-  XChangeProperty(_display, _xwindow, _net_wm_state,
+  XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_state,
                   XA_ATOM, 32, PropModeReplace,
                   (unsigned char *)state_data, next_state_data);
 
@@ -1164,7 +1209,7 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
       event.send_event = True;
       event.display = _display;
       event.window = _xwindow;
-      event.message_type = _net_wm_state;
+      event.message_type = x11_pipe->_net_wm_state;
       event.format = 32;
       event.data.l[0] = set_data[i]._action;
       event.data.l[1] = set_data[i]._state;

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

@@ -100,15 +100,6 @@ protected:
   bool _awaiting_configure;
   bool _dga_mouse_enabled;
   Atom _wm_delete_window;
-  Atom _net_wm_window_type;
-  Atom _net_wm_window_type_splash;
-  Atom _net_wm_window_type_fullscreen;
-  Atom _net_wm_state;
-  Atom _net_wm_state_fullscreen;
-  Atom _net_wm_state_above;
-  Atom _net_wm_state_below;
-  Atom _net_wm_state_add;
-  Atom _net_wm_state_remove;
 
   struct MouseDeviceInfo {
     int    _fd;

+ 172 - 0
samples/mouse-modes/main.py

@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+'''
+Demonstrate different mouse modes
+'''
+
+# from panda3d.core import loadPrcFileData
+# 
+# loadPrcFileData("", "notify-level-x11display debug") 
+# loadPrcFileData("", "notify-level-windisplay debug") 
+#
+# loadPrcFileData("", "load-display p3tinydisplay") 
+
+from panda3d.core import WindowProperties, TextNode
+from direct.task.TaskManagerGlobal import taskMgr
+from direct.gui.OnscreenText import OnscreenText
+from direct.task import Task
+from direct.showbase.ShowBase import ShowBase
+
+import sys
+
+class App(ShowBase):
+    def __init__(self):
+        ShowBase.__init__(self)
+        self.base = self
+        self.setup()
+
+    def genLabelText(self, text, i):
+        text = OnscreenText(text = text, pos = (-1.3, .5-.05*i), fg=(0,1,0,1),
+                      align = TextNode.ALeft, scale = .05)
+        return text
+    
+        
+    def setup(self):
+        # Disable the camera trackball controls.
+        self.disableMouse()
+        
+        self.mouseMagnitude = 144
+
+        self.rotateX, self.rotateY = 0, 0
+
+        self.genLabelText("[0] Absolute mode, [1] Relative mode, [2] Confined mode", 0)      
+        
+        self.base.accept('0', lambda: self.setMouseMode(WindowProperties.M_absolute))       
+        self.base.accept('1', lambda: self.setMouseMode(WindowProperties.M_relative))       
+        self.base.accept('2', lambda: self.setMouseMode(WindowProperties.M_confined))
+        
+        self.genLabelText("[C] Manually re-center mouse on each tick", 1)      
+        self.base.accept('C', lambda: self.toggleRecenter())
+        self.base.accept('c', lambda: self.toggleRecenter())
+               
+        self.genLabelText("[S] Show mouse", 2)      
+        self.base.accept('S', lambda: self.toggleMouse())
+        self.base.accept('s', lambda: self.toggleMouse())
+               
+        self.base.accept('escape', sys.exit, [0])       
+        
+        self.mouseText = self.genLabelText("", 5)      
+        self.deltaText = self.genLabelText("", 6)      
+        self.positionText = self.genLabelText("", 8)
+        
+        self.lastMouseX, self.lastMouseY = None, None
+        
+        self.hideMouse = False
+        
+        self.setMouseMode(WindowProperties.M_absolute)
+        self.manualRecenterMouse = True
+
+        # make a box to move with the mouse
+        self.model = self.loader.loadModel("box.egg")
+        self.model.reparentTo(self.render)
+        
+        self.cam.setPos(0, -5, 0)
+        self.cam.lookAt(0, 0, 0)
+        
+        self.mouseTask = taskMgr.add(self.mouseTask, "Mouse Task")
+        
+    def setMouseMode(self, mode):
+        print "Changing mode to",mode
+        
+        self.mouseMode = mode
+        
+        wp = WindowProperties()
+        wp.setMouseMode(mode)
+        self.base.win.requestProperties(wp)
+        
+        # these changes may require a tick to apply
+        self.base.taskMgr.doMethodLater(0, self.resolveMouse, "Resolve mouse setting")
+        
+    def resolveMouse(self, t):
+        wp = self.base.win.getProperties()
+        
+        actualMode = wp.getMouseMode()
+        if self.mouseMode != actualMode:
+            print "ACTUAL MOUSE MODE:", actualMode
+            
+        self.mouseMode = actualMode
+        
+        self.rotateX, self.rotateY = -.5, -.5
+        self.lastMouseX, self.lastMouseY = None, None
+        self.recenterMouse()
+
+    def recenterMouse(self):
+        self.base.win.movePointer(0, 
+              int(self.base.win.getProperties().getXSize() / 2),
+              int(self.base.win.getProperties().getYSize() / 2))
+            
+
+    def toggleRecenter(self):
+        print "Toggling re-center behavior"
+        self.manualRecenterMouse = not self.manualRecenterMouse
+        
+    def toggleMouse(self):
+        print "Toggling mouse visibility"
+
+        self.hideMouse = not self.hideMouse
+        
+        wp = WindowProperties()
+        wp.setCursorHidden(self.hideMouse)
+        self.base.win.requestProperties(wp)
+        
+    def mouseTask(self, task):
+        mw = self.base.mouseWatcherNode
+
+        hasMouse = mw.hasMouse()
+        if hasMouse:
+            # get the window manager's idea of the mouse position
+            x, y = mw.getMouseX(), mw.getMouseY()
+            
+            if self.lastMouseX is not None:
+                # get the delta
+                if self.manualRecenterMouse:
+                    # when recentering, the position IS the delta
+                    # since the center is reported as 0, 0
+                    dx, dy = x, y 
+                else:
+                    dx, dy = x - self.lastMouseX, y - self.lastMouseY
+            else:
+                # no data to compare with yet
+                dx, dy = 0, 0
+                 
+            self.lastMouseX, self.lastMouseY = x, y
+                
+        else:
+            x, y, dx, dy = 0, 0, 0, 0
+
+        if self.manualRecenterMouse:
+            # move mouse back to center
+            self.recenterMouse()             
+
+        # scale position and delta to pixels for user
+        w, h = self.win.getSize()
+        
+        self.mouseText.setText("Mode: {0}, Recenter: {1}  |  Mouse: {2}, {3}  |  hasMouse: {4}".format(
+             self.mouseMode, self.manualRecenterMouse,
+             int(x*w), int(y*h), 
+             hasMouse))             
+        self.deltaText.setText("Delta: {0}, {1}".format(
+             int(dx*w), int(dy*h))) 
+
+        # rotate box by delta
+        self.rotateX += dx * 10
+        self.rotateY += dy * 10
+
+        self.positionText.setText("Model rotation: {0}, {1}".format(
+             int(self.rotateX*1000)/1000., int(self.rotateY*1000)/1000.))        
+        
+        self.model.setH(self.rotateX)
+        self.model.setP(self.rotateY)
+        return Task.cont
+    
+app = App()
+app.run()