Przeglądaj źródła

Apply patch from launchpad user mjkoo to add custom mouse cursor support on X11

Maxwell J. Koo 15 lat temu
rodzic
commit
40b487d3fa

+ 8 - 1
dtool/Config.pp

@@ -709,13 +709,20 @@
 #define XF86DGA_LIBS Xxf86dga
 #defer HAVE_XF86DGA $[libtest $[XF86DGA_LPATH],$[XF86DGA_LIBS]]
 
-// This defines if we have XF86DGA installed. This
+// This defines if we have XRANDR installed. This
 // enables resolution switching in x11display.
 #define XRANDR_IPATH /usr/include/X11/extensions
 #define XRANDR_LPATH /usr/lib
 #define XRANDR_LIBS Xrandr
 #defer HAVE_XRANDR $[libtest $[XRANDR_LPATH],$[XRANDR_LIBS]]
 
+// This defines if we have XCURSOR installed. This
+// enables resolution switching in x11display.
+#define XCURSOR_IPATH /usr/include/X11/extensions
+#define XCURSOR_LPATH /usr/lib
+#define XCURSOR_LIBS Xcursor
+#defer HAVE_XCURSOR $[libtest $[XCURSOR_LPATH],$[XCURSOR_LIBS]]
+
 // How about GLX?
 #define GLX_IPATH
 #define GLX_LPATH

+ 3 - 0
dtool/LocalSetup.pp

@@ -413,6 +413,9 @@ $[cdefine HAVE_XF86DGA]
 /* Define if we have the XRandR extension. */
 $[cdefine HAVE_XRANDR]
 
+/* Define if we have the XCursor extension. */
+$[cdefine HAVE_XCURSOR]
+
 /* Define if we want to compile the threading code.  */
 $[cdefine HAVE_THREADS]
 

+ 7 - 0
dtool/pptempl/Global.pp

@@ -171,6 +171,13 @@
   #define xrandr_libs $[XRANDR_LIBS]
 #endif
 
+#if $[HAVE_XCURSOR]
+  #define xcursor_ipath $[wildcard $[XCURSOR_IPATH]]
+  #define xcursor_lpath $[wildcard $[XCURSOR_LPATH]]
+  #define xcursor_cflags $[XCURSOR_CFLAGS]
+  #define xcursor_libs $[XCURSOR_LIBS]
+#endif
+
 #if $[HAVE_MESA]
   #define mesa_ipath $[wildcard $[MESA_IPATH]]
   #define mesa_lpath $[wildcard $[MESA_LPATH]]

+ 9 - 5
makepanda/makepanda.py

@@ -69,7 +69,7 @@ PkgListSet(["PYTHON", "DIRECT",                        # Python support
   "ARTOOLKIT", "OPENCV", "DIRECTCAM",                  # Augmented Reality
   "NPAPI", "AWESOMIUM",                                # Browser embedding
   "GTK2", "WX",                                        # Toolkit support
-  "OSMESA", "X11", "XF86DGA", "XRANDR",                # Unix platform support
+  "OSMESA", "X11", "XF86DGA", "XRANDR", "XCURSOR",     # Unix platform support
   "PANDATOOL", "PVIEW", "DEPLOYTOOLS",                 # Toolchain
   "CONTRIB"                                            # Experimental
 ])
@@ -356,6 +356,7 @@ if (COMPILER=="MSVC"):
     PkgDisable("X11")
     PkgDisable("XRANDR")
     PkgDisable("XF86DGA")
+    PkgDisable("XCURSOR")
     PkgDisable("GLES")
     PkgDisable("GLES2")
     PkgDisable("EGL")
@@ -572,6 +573,7 @@ if (COMPILER=="LINUX"):
             SmartPkgEnable("X11",   "x11", "X11", ("X11", "X11/Xlib.h"))
             SmartPkgEnable("XRANDR", "xrandr", "Xrandr", "X11/extensions/Xrandr.h")
             SmartPkgEnable("XF86DGA", "xxf86dga", "Xxf86dga", "X11/extensions/xf86dga.h")
+            SmartPkgEnable("XCURSOR", "xcursor", "Xcursor", "X11/Xcursor/Xcursor.h")
 
     if (RUNTIME):
         # For the runtime, all packages are required
@@ -1410,6 +1412,7 @@ DTOOL_CONFIG=[
     ("HAVE_X11",                       'UNDEF',                  '1'),
     ("HAVE_XRANDR",                    'UNDEF',                  '1'),
     ("HAVE_XF86DGA",                   'UNDEF',                  '1'),
+    ("HAVE_XCURSOR",                   'UNDEF',                  '1'),
     ("IS_LINUX",                       'UNDEF',                  '1'),
     ("IS_OSX",                         'UNDEF',                  'UNDEF'),
     ("IS_FREEBSD",                     'UNDEF',                  'UNDEF'),
@@ -1518,6 +1521,7 @@ def WriteConfigSettings():
         dtool_config["HAVE_X11"] = 'UNDEF'  # We might have X11, but we don't need it.
         dtool_config["HAVE_XRANDR"] = 'UNDEF'
         dtool_config["HAVE_XF86DGA"] = 'UNDEF'
+        dtool_config["HAVE_XCURSOR"] = 'UNDEF'
         dtool_config["HAVE_GLX"] = 'UNDEF'
         dtool_config["IS_LINUX"] = 'UNDEF'
         dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF'
@@ -3316,7 +3320,7 @@ if (sys.platform != "win32" and sys.platform != "darwin" and PkgSkip("GL")==0 an
   TargetAdd('libpandagl.dll', input='glxdisplay_composite.obj')
   TargetAdd('libpandagl.dll', input='libp3glstuff.dll')
   TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11', 'XRANDR', 'XF86DGA'])
+  TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
 
 #
 # DIRECTORY: panda/src/osxdisplay/
@@ -3375,7 +3379,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTI
   TargetAdd('libpandagles.dll', input='pandagles_egldisplay_composite1.obj')
   TargetAdd('libpandagles.dll', input='libp3glstuff.dll')
   TargetAdd('libpandagles.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11', 'XRANDR', 'XF86DGA'])
+  TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
 
 #
 # DIRECTORY: panda/src/egldisplay/
@@ -3395,7 +3399,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0 and not RUNT
   TargetAdd('libpandagles2.dll', input='pandagles2_egldisplay_composite1.obj')
   TargetAdd('libpandagles2.dll', input='libp3glstuff.dll')
   TargetAdd('libpandagles2.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11', 'XRANDR', 'XF86DGA'])
+  TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
 
 #
 # DIRECTORY: panda/src/ode/
@@ -3574,7 +3578,7 @@ if (not RUNTIME and (sys.platform == "win32" or sys.platform == "darwin" or PkgS
     TargetAdd('libtinydisplay.dll', opts=['WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM'])
   else:
     TargetAdd('libtinydisplay.dll', input='x11display_composite.obj')
-    TargetAdd('libtinydisplay.dll', opts=['X11', 'XRANDR', 'XF86DGA'])
+    TargetAdd('libtinydisplay.dll', opts=['X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
   TargetAdd('libtinydisplay.dll', input='tinydisplay_composite1.obj')
   TargetAdd('libtinydisplay.dll', input='tinydisplay_composite2.obj')
   TargetAdd('libtinydisplay.dll', input='tinydisplay_ztriangle_1.obj')

+ 1 - 1
panda/src/x11display/Sources.pp

@@ -2,7 +2,7 @@
 
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m
-#define USE_PACKAGES x11 xf86dga xrandr
+#define USE_PACKAGES x11 xf86dga xrandr xcursor
 
 #begin lib_target
   #define TARGET x11display

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

@@ -32,6 +32,11 @@
 #include <X11/keysym.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
+
+#ifdef HAVE_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
+
 #ifdef HAVE_XF86DGA
 #include <X11/extensions/xf86dga.h>
 #endif
@@ -624,7 +629,21 @@ set_properties_now(WindowProperties &properties) {
     _awaiting_configure = true;
   }
 
+  // Load a custom cursor from a file.
+  if (properties.has_cursor_filename()) {
+    Filename filename = properties.get_cursor_filename();
+    Cursor cursor = get_cursor(filename);
+
+    _properties.set_cursor_filename(filename);
+    // Note that if the cursor fails to load, cursor will be None
+    XDefineCursor(_display, _xwindow, cursor);
+
+    properties.clear_cursor_filename();
+  }
+
   // We hide the cursor by setting it to an invisible pixmap.
+  // Do this check after setting the custom cursor, to hide the
+  // custom cursor if necessary.
   if (properties.has_cursor_hidden()) {
     _properties.set_cursor_hidden(properties.get_cursor_hidden());
     if (properties.get_cursor_hidden()) {
@@ -1803,6 +1822,7 @@ get_mouse_button(XButtonEvent &button_event) {
     return MouseButton::button(index - 1);
   }
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: x11GraphicsWindow::check_event
 //       Access: Private, Static
@@ -1818,3 +1838,53 @@ check_event(Display *display, XEvent *event, char *arg) {
   // We accept any event that is sent to our window.
   return (event->xany.window == self->_xwindow);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: x11GraphicsWindow::get_cursor
+//       Access: Private
+//  Description: Loads and returns an Cursor corresponding to the
+//               indicated filename.  If the file cannot be loaded,
+//               returns None.
+////////////////////////////////////////////////////////////////////
+Cursor x11GraphicsWindow::
+get_cursor(const Filename &filename) {
+  // First, look for the unresolved filename in our index.
+  pmap<Filename, Cursor>::iterator fi = _cursor_filenames.find(filename);
+  if (fi != _cursor_filenames.end()) {
+    return fi->second;
+  }
+
+  // If it wasn't found, resolve the filename and search for that.
+  Filename resolved = filename;
+  if (!resolved.resolve_filename(get_model_path())) {
+    // The filename doesn't exist.
+    x11display_cat.warning()
+      << "Could not find cursor filename " << filename << "\n";
+    return None;
+  }
+  fi = _cursor_filenames.find(resolved);
+  if (fi != _cursor_filenames.end()) {
+    _cursor_filenames[filename] = (*fi).second;
+    return fi->second;
+  }
+
+  Filename os = resolved.to_os_specific();
+
+#ifdef HAVE_XCURSOR
+  Cursor h = XcursorFilenameLoadCursor(_display, os.c_str());
+
+  if (h == None) {
+    x11display_cat.warning()
+      << "x11 cursor filename '" << os << "' could not be loaded!!\n";
+  }
+#else
+  // Can't support loading cursor from image, so fall back to default
+  Cursor h = None;
+#endif
+
+  _cursor_filenames[filename] = h;
+  _cursor_filenames[resolved] = h;
+  return h;
+}
+
+ 

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

@@ -73,6 +73,9 @@ protected:
 
   void open_raw_mice();
   void poll_raw_mice();
+
+private:
+  Cursor get_cursor(const Filename &filename);
   
 protected:
   Display *_display;
@@ -124,6 +127,11 @@ public:
 
 private:
   static TypeHandle _type_handle;
+  
+  // 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.
+  pmap<Filename, Cursor> _cursor_filenames;
 };
 
 #include "x11GraphicsWindow.I"