Browse Source

handle icon and cursor filenames more robustly

David Rose 21 years ago
parent
commit
642dda0edd

+ 25 - 4
panda/src/display/config_display.cxx

@@ -119,17 +119,27 @@ ConfigVariableBool window_inverted
           "they will render upside-down and backwards.  Normally this is useful only "
           "they will render upside-down and backwards.  Normally this is useful only "
           "for debugging."));
           "for debugging."));
 
 
+ConfigVariableInt win_size
+("win-size", "640 480",
+ PRC_DESC("This is the default size at which to open a new window.  This "
+          "replaces the deprecated win-width and win-height variables."));
+
+ConfigVariableInt win_origin
+("win-origin", "0 0",
+ PRC_DESC("This is the default position at which to open a new window.  This "
+          "replaces the deprecated win-origin-x and win-origin-y variables."));
+
 ConfigVariableInt win_width
 ConfigVariableInt win_width
-("win-width", 640);
+("win-width", 0);
 
 
 ConfigVariableInt win_height
 ConfigVariableInt win_height
-("win-height", 480);
+("win-height", 0);
 
 
 ConfigVariableInt win_origin_x
 ConfigVariableInt win_origin_x
-("win-origin-x", -1);
+("win-origin-x", 0);
 
 
 ConfigVariableInt win_origin_y
 ConfigVariableInt win_origin_y
-("win-origin-y", -1);
+("win-origin-y", 0);
 
 
 ConfigVariableBool fullscreen
 ConfigVariableBool fullscreen
 ("fullscreen", false);
 ("fullscreen", false);
@@ -140,12 +150,23 @@ ConfigVariableBool undecorated
 ConfigVariableBool cursor_hidden
 ConfigVariableBool cursor_hidden
 ("cursor-hidden", false);
 ("cursor-hidden", false);
 
 
+ConfigVariableFilename icon_filename
+("icon-filename", "");
+
+ConfigVariableFilename cursor_filename
+("cursor-filename", "");
+
 ConfigVariableEnum<WindowProperties::ZOrder> z_order
 ConfigVariableEnum<WindowProperties::ZOrder> z_order
 ("z-order", WindowProperties::Z_normal);
 ("z-order", WindowProperties::Z_normal);
 
 
 ConfigVariableString window_title
 ConfigVariableString window_title
 ("window-title", "Panda");
 ("window-title", "Panda");
 
 
+ConfigVariableDouble background_color
+("background-color", "0.41 0.41 0.41",
+ PRC_DESC("Specifies the rgb(a) value of the default background color for a "
+          "new window or offscreen buffer."));
+
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: init_libdisplay
 //     Function: init_libdisplay

+ 8 - 0
panda/src/display/config_display.h

@@ -27,6 +27,7 @@
 #include "configVariableList.h"
 #include "configVariableList.h"
 #include "configVariableInt.h"
 #include "configVariableInt.h"
 #include "configVariableEnum.h"
 #include "configVariableEnum.h"
+#include "configVariableFilename.h"
 #include "dconfig.h"
 #include "dconfig.h"
 
 
 #include "pvector.h"
 #include "pvector.h"
@@ -53,6 +54,8 @@ extern ConfigVariableBool prefer_single_buffer;
 extern ConfigVariableBool copy_texture_inverted;
 extern ConfigVariableBool copy_texture_inverted;
 extern ConfigVariableBool window_inverted;
 extern ConfigVariableBool window_inverted;
 
 
+extern ConfigVariableInt win_size;
+extern ConfigVariableInt win_origin;
 extern ConfigVariableInt win_width;
 extern ConfigVariableInt win_width;
 extern ConfigVariableInt win_height;
 extern ConfigVariableInt win_height;
 extern ConfigVariableInt win_origin_x;
 extern ConfigVariableInt win_origin_x;
@@ -60,9 +63,14 @@ extern ConfigVariableInt win_origin_y;
 extern ConfigVariableBool fullscreen;
 extern ConfigVariableBool fullscreen;
 extern ConfigVariableBool undecorated;
 extern ConfigVariableBool undecorated;
 extern ConfigVariableBool cursor_hidden;
 extern ConfigVariableBool cursor_hidden;
+extern ConfigVariableFilename icon_filename;
+extern ConfigVariableFilename cursor_filename;
 extern ConfigVariableEnum<WindowProperties::ZOrder> z_order;
 extern ConfigVariableEnum<WindowProperties::ZOrder> z_order;
 extern ConfigVariableString window_title;
 extern ConfigVariableString window_title;
 
 
+extern ConfigVariableDouble background_color;
+
+
 extern EXPCL_PANDA void init_libdisplay();
 extern EXPCL_PANDA void init_libdisplay();
 
 
 #endif /* CONFIG_DISPLAY_H */
 #endif /* CONFIG_DISPLAY_H */

+ 23 - 0
panda/src/display/graphicsOutput.cxx

@@ -79,6 +79,29 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
   // depth.
   // depth.
   set_clear_color_active(true);
   set_clear_color_active(true);
   set_clear_depth_active(true);
   set_clear_depth_active(true);
+
+  switch (background_color.get_num_words()) {
+  case 1:
+    set_clear_color(Colorf(background_color[0], background_color[0], background_color[0], 1.0f));
+    break;
+
+  case 2:
+    set_clear_color(Colorf(background_color[0], background_color[0], background_color[0], background_color[1]));
+    break;
+
+  case 3:
+    set_clear_color(Colorf(background_color[0], background_color[1], background_color[2], 1.0f));
+    break;
+
+  case 4:
+    set_clear_color(Colorf(background_color[0], background_color[1], background_color[2], background_color[3]));
+    break;
+
+  default:
+    display_cat.warning()
+      << "Invalid background-color specification: " 
+      << background_color.get_string_value() << "\n";
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 93 - 1
panda/src/display/windowProperties.I

@@ -531,7 +531,7 @@ set_cursor_hidden(bool cursor_hidden) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: WindowProperties::set_cursor_hidden
+//     Function: WindowProperties::get_cursor_hidden
 //       Access: Published
 //       Access: Published
 //  Description: Returns true if the mouse cursor is invisible.
 //  Description: Returns true if the mouse cursor is invisible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -561,6 +561,98 @@ clear_cursor_hidden() {
   _flags &= ~F_cursor_hidden;
   _flags &= ~F_cursor_hidden;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::set_icon_filename
+//       Access: Published
+//  Description: Specifies the file that contains the icon to
+//               associate with the window when it is minimized.
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+set_icon_filename(const Filename &icon_filename) {
+  _icon_filename = icon_filename;
+  _specified |= S_icon_filename;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::get_icon_filename
+//       Access: Published
+//  Description: Returns the icon filename associated with the window.
+////////////////////////////////////////////////////////////////////
+INLINE const Filename &WindowProperties::
+get_icon_filename() const {
+  return _icon_filename;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::has_icon_filename
+//       Access: Published
+//  Description: Returns true if set_icon_filename() has been
+//               specified.
+////////////////////////////////////////////////////////////////////
+INLINE bool WindowProperties::
+has_icon_filename() const {
+  return ((_specified & S_icon_filename) != 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::clear_icon_filename
+//       Access: Published
+//  Description: Removes the icon_filename specification from the
+//               properties.
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+clear_icon_filename() {
+  _specified &= ~S_icon_filename;
+  _icon_filename = Filename();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::set_cursor_filename
+//       Access: Published
+//  Description: Specifies the file that contains the icon to
+//               associate with the mouse cursor when it is within the
+//               window (and visible).
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+set_cursor_filename(const Filename &cursor_filename) {
+  _cursor_filename = cursor_filename;
+  _specified |= S_cursor_filename;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::get_cursor_filename
+//       Access: Published
+//  Description: Returns the icon filename associated with the mouse
+//               cursor.
+////////////////////////////////////////////////////////////////////
+INLINE const Filename &WindowProperties::
+get_cursor_filename() const {
+  return _cursor_filename;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::has_cursor_filename
+//       Access: Published
+//  Description: Returns true if set_cursor_filename() has been
+//               specified.
+////////////////////////////////////////////////////////////////////
+INLINE bool WindowProperties::
+has_cursor_filename() const {
+  return ((_specified & S_cursor_filename) != 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::clear_cursor_filename
+//       Access: Published
+//  Description: Removes the cursor_filename specification from the
+//               properties.
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+clear_cursor_filename() {
+  _specified &= ~S_cursor_filename;
+  _cursor_filename = Filename();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowProperties::set_z_order
 //     Function: WindowProperties::set_z_order
 //       Access: Published
 //       Access: Published

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

@@ -42,6 +42,8 @@ operator = (const WindowProperties &copy) {
   _x_size = copy._x_size;
   _x_size = copy._x_size;
   _y_size = copy._y_size;
   _y_size = copy._y_size;
   _title = copy._title;
   _title = copy._title;
+  _icon_filename = copy._icon_filename;
+  _cursor_filename = copy._cursor_filename;
   _z_order = copy._z_order;
   _z_order = copy._z_order;
   _flags = copy._flags;
   _flags = copy._flags;
 }
 }
@@ -58,14 +60,37 @@ get_default() {
   WindowProperties props;
   WindowProperties props;
 
 
   props.set_open(true);
   props.set_open(true);
-  props.set_size(win_width, win_height);
-  if (win_origin_x >= 0 && win_origin_y >= 0) {
+
+  if (win_width.has_value() && win_height.has_value() &&
+      !win_size.has_value()) {
+    props.set_size(win_width, win_height);
+
+  } else {
+    if (win_size.get_num_words() == 1) {
+      props.set_size(win_size[0], win_size[0]);
+    } else {
+      props.set_size(win_size[0], win_size[1]);
+    }
+  }
+
+  if (win_origin_x.has_value() && win_origin_y.has_value() && 
+      !win_origin.has_value()) {
     props.set_origin(win_origin_x, win_origin_y);
     props.set_origin(win_origin_x, win_origin_y);
+
+  } else {
+    props.set_origin(win_origin[0], win_origin[1]);
   }
   }
+
   props.set_fullscreen(fullscreen);
   props.set_fullscreen(fullscreen);
   props.set_undecorated(undecorated);
   props.set_undecorated(undecorated);
   props.set_cursor_hidden(cursor_hidden);
   props.set_cursor_hidden(cursor_hidden);
-  if (z_order != WindowProperties::Z_normal) {
+  if (icon_filename.has_value()) {
+    props.set_icon_filename(icon_filename);
+  }
+  if (cursor_filename.has_value()) {
+    props.set_cursor_filename(cursor_filename);
+  }
+  if (z_order.has_value()) {
     props.set_z_order(z_order);
     props.set_z_order(z_order);
   }
   }
   props.set_title(window_title);
   props.set_title(window_title);
@@ -87,7 +112,9 @@ operator == (const WindowProperties &other) const {
           _x_size == other._x_size &&
           _x_size == other._x_size &&
           _y_size == other._y_size &&
           _y_size == other._y_size &&
           _z_order == other._z_order &&
           _z_order == other._z_order &&
-          _title == other._title);
+          _title == other._title &&
+          _icon_filename == other._icon_filename &&
+          _cursor_filename == other._cursor_filename);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -105,6 +132,8 @@ clear() {
   _x_size = 0;
   _x_size = 0;
   _y_size = 0;
   _y_size = 0;
   _title = string();
   _title = string();
+  _icon_filename = Filename();
+  _cursor_filename = Filename();
   _z_order = Z_normal;
   _z_order = Z_normal;
   _flags = 0;
   _flags = 0;
 }
 }
@@ -148,6 +177,12 @@ add_properties(const WindowProperties &other) {
   if (other.has_cursor_hidden()) {
   if (other.has_cursor_hidden()) {
     set_cursor_hidden(other.get_cursor_hidden());
     set_cursor_hidden(other.get_cursor_hidden());
   }
   }
+  if (other.has_icon_filename()) {
+    set_icon_filename(other.get_icon_filename());
+  }
+  if (other.has_cursor_filename()) {
+    set_cursor_filename(other.get_cursor_filename());
+  }
   if (other.has_z_order()) {
   if (other.has_z_order()) {
     set_z_order(other.get_z_order());
     set_z_order(other.get_z_order());
   }
   }
@@ -192,7 +227,14 @@ output(ostream &out) const {
   if (has_cursor_hidden()) {
   if (has_cursor_hidden()) {
     out << (get_cursor_hidden() ? "cursor_hidden " : "!cursor_hidden ");
     out << (get_cursor_hidden() ? "cursor_hidden " : "!cursor_hidden ");
   }
   }
+  if (has_icon_filename()) {
+    out << "icon:" << get_icon_filename() << " ";
+  }
+  if (has_cursor_filename()) {
+    out << "cursor:" << get_cursor_filename() << " ";
+  }
   if (has_z_order()) {
   if (has_z_order()) {
+    out << get_z_order() << " ";
   }
   }
 }
 }
 
 

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

@@ -20,6 +20,7 @@
 #define WINDOWPROPERTIES_H
 #define WINDOWPROPERTIES_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
+#include "filename.h"
 #include "notify.h"
 #include "notify.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -102,6 +103,16 @@ PUBLISHED:
   INLINE bool has_cursor_hidden() const;
   INLINE bool has_cursor_hidden() const;
   INLINE void clear_cursor_hidden();
   INLINE void clear_cursor_hidden();
 
 
+  INLINE void set_icon_filename(const Filename &icon_filename);
+  INLINE const Filename &get_icon_filename() const;
+  INLINE bool has_icon_filename() const;
+  INLINE void clear_icon_filename();
+
+  INLINE void set_cursor_filename(const Filename &cursor_filename);
+  INLINE const Filename &get_cursor_filename() const;
+  INLINE bool has_cursor_filename() const;
+  INLINE void clear_cursor_filename();
+
   INLINE void set_z_order(ZOrder z_order);
   INLINE void set_z_order(ZOrder z_order);
   INLINE ZOrder get_z_order() const;
   INLINE ZOrder get_z_order() const;
   INLINE bool has_z_order() const;
   INLINE bool has_z_order() const;
@@ -127,6 +138,8 @@ private:
     S_cursor_hidden    = 0x0100,
     S_cursor_hidden    = 0x0100,
     S_fixed_size       = 0x0200,
     S_fixed_size       = 0x0200,
     S_z_order          = 0x0400,
     S_z_order          = 0x0400,
+    S_icon_filename    = 0x0800,
+    S_cursor_filename  = 0x1000,
   };
   };
 
 
   // This bitmask represents the true/false settings for various
   // This bitmask represents the true/false settings for various
@@ -148,6 +161,8 @@ private:
   int _x_size;
   int _x_size;
   int _y_size;
   int _y_size;
   string _title;
   string _title;
+  Filename _cursor_filename;
+  Filename _icon_filename;
   ZOrder _z_order;
   ZOrder _z_order;
   int _flags;
   int _flags;
 };
 };

+ 0 - 5
panda/src/dxgsg8/config_dxgsg8.cxx

@@ -133,11 +133,6 @@ ConfigVariableBool dx_debug_view_mipmaps
 ("dx-debug-view-mipmaps", false);
 ("dx-debug-view-mipmaps", false);
 #endif
 #endif
 
 
-// use dx8 or GDI mouse cursor in fullscreen mode?
-// Nvidia dx8 cursor is invisible as of 28.32 drivers, so using GDI in fullscrn by default for now
-ConfigVariableBool dx_use_dx_cursor
-("dx-use-dx-cursor", false);
-
 ConfigVariableBool dx_force_anisotropic_filtering
 ConfigVariableBool dx_force_anisotropic_filtering
 ("dx-force-anisotropic-filtering", false);
 ("dx-force-anisotropic-filtering", false);
 
 

+ 0 - 1
panda/src/dxgsg8/config_dxgsg8.h

@@ -40,7 +40,6 @@ extern ConfigVariableBool dx_use_rangebased_fog;
 extern ConfigVariableBool link_tristrips;
 extern ConfigVariableBool link_tristrips;
 extern ConfigVariableInt dx_multisample_antialiasing_level;
 extern ConfigVariableInt dx_multisample_antialiasing_level;
 extern ConfigVariableBool dx_use_triangle_mipgen_filter;
 extern ConfigVariableBool dx_use_triangle_mipgen_filter;
-extern ConfigVariableBool dx_use_dx_cursor;
 
 
 
 
 // debug flags we might want to use in full optimized build
 // debug flags we might want to use in full optimized build

+ 0 - 45
panda/src/dxgsg8/wdxGraphicsWindow8.cxx

@@ -465,20 +465,6 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     int x, y, width, height;
     int x, y, width, height;
 
 
     switch(msg) {
     switch(msg) {
-        case WM_SETCURSOR: {
-            // Turn off any GDI window cursor
-            //  dx8 cursor not working yet
-
-            if(dx_use_dx_cursor && is_fullscreen()) {
-                //            SetCursor( NULL );
-            //                _dxgsg->scrn.pD3DDevice->ShowCursor(true);
-
-                set_cursor_visibility(true);
-                return TRUE; // prevent Windows from setting cursor to window class cursor (see docs on WM_SETCURSOR)
-            }
-            break;
-        }
-
         case WM_PAINT: {
         case WM_PAINT: {
            // primarily seen when app window is 'uncovered'
            // primarily seen when app window is 'uncovered'
            if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) {
            if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) {
@@ -1682,12 +1668,6 @@ init_resized_window() {
   _dxgsg->set_context(&_wcontext); 
   _dxgsg->set_context(&_wcontext); 
   // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts
   // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts
   _dxgsg->dx_init();
   _dxgsg->dx_init();
-
-  if(dx_use_dx_cursor && is_fullscreen()) {
-      hr = CreateDX8Cursor(_wcontext.pD3DDevice,_mouse_cursor,dx_show_cursor_watermark);
-      if(FAILED(hr))
-          wdxdisplay8_cat.error() << "CreateDX8Cursor failed!" <<  D3DERRORSTRING(hr);
-  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1846,30 +1826,5 @@ open_window(void) {
 bool wdxGraphicsWindow8::
 bool wdxGraphicsWindow8::
 handle_mouse_motion(int x, int y) {
 handle_mouse_motion(int x, int y) {
   (void) WinGraphicsWindow::handle_mouse_motion(x,y);
   (void) WinGraphicsWindow::handle_mouse_motion(x,y);
-  if(dx_use_dx_cursor && is_fullscreen() && (_wcontext.pD3DDevice!=NULL)) {
-      _wcontext.pD3DDevice->SetCursorPosition(x,y,D3DCURSOR_IMMEDIATE_UPDATE);
-      // return true to indicate wind_proc should return 0 instead of going to DefaultWindowProc
-      return true;
-  }
   return false;
   return false;
 }
 }
-
-#if 0
-// does NOT override _props._bCursorIsVisible
-INLINE void wdxGraphicsWindow::
-set_cursor_visibility(bool bVisible) {
-  if(_props._bCursorIsVisible) {
-      if(dx_use_dx_cursor) {
-          ShowCursor(false);
-          if(IS_VALID_PTR(_wcontext.pD3DDevice))
-              _dxgsg->scrn.pD3DDevice->ShowCursor(bVisible);
-      } else {
-         ShowCursor(bVisible);
-      }
-  } else {
-      ShowCursor(false);
-      if(dx_use_dx_cursor && IS_VALID_PTR(_wcontext.pD3DDevice))
-          _dxgsg->scrn.pD3DDevice->ShowCursor(false);
-  }
-}
-#endif

+ 0 - 5
panda/src/dxgsg9/config_dxgsg9.cxx

@@ -133,11 +133,6 @@ ConfigVariableBool dx_debug_view_mipmaps
 ("dx-debug-view-mipmaps", false);
 ("dx-debug-view-mipmaps", false);
 #endif
 #endif
 
 
-// use dx9 or GDI mouse cursor in fullscreen mode?
-// Nvidia dx9 cursor is invisible as of 28.32 drivers, so using GDI in fullscrn by default for now
-ConfigVariableBool dx_use_dx_cursor
-("dx-use-dx-cursor", false);
-
 ConfigVariableBool dx_force_anisotropic_filtering
 ConfigVariableBool dx_force_anisotropic_filtering
 ("dx-force-anisotropic-filtering", false);
 ("dx-force-anisotropic-filtering", false);
 
 

+ 0 - 1
panda/src/dxgsg9/config_dxgsg9.h

@@ -40,7 +40,6 @@ extern ConfigVariableBool dx_use_rangebased_fog;
 extern ConfigVariableBool link_tristrips;
 extern ConfigVariableBool link_tristrips;
 extern ConfigVariableInt dx_multisample_antialiasing_level;
 extern ConfigVariableInt dx_multisample_antialiasing_level;
 extern ConfigVariableBool dx_use_triangle_mipgen_filter;
 extern ConfigVariableBool dx_use_triangle_mipgen_filter;
-extern ConfigVariableBool dx_use_dx_cursor;
 
 
 
 
 // debug flags we might want to use in full optimized build
 // debug flags we might want to use in full optimized build

+ 0 - 45
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -454,20 +454,6 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     int x, y, width, height;
     int x, y, width, height;
 
 
     switch(msg) {
     switch(msg) {
-        case WM_SETCURSOR: {
-            // Turn off any GDI window cursor
-            //  dx9 cursor not working yet
-
-            if(dx_use_dx_cursor && is_fullscreen()) {
-                //            SetCursor( NULL );
-            //                _dxgsg->scrn.pD3DDevice->ShowCursor(true);
-
-                set_cursor_visibility(true);
-                return TRUE; // prevent Windows from setting cursor to window class cursor (see docs on WM_SETCURSOR)
-            }
-            break;
-        }
-
         case WM_PAINT: {
         case WM_PAINT: {
            // primarily seen when app window is 'uncovered'
            // primarily seen when app window is 'uncovered'
            if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) {
            if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) {
@@ -1667,12 +1653,6 @@ init_resized_window() {
   _dxgsg->set_context(&_wcontext); 
   _dxgsg->set_context(&_wcontext); 
   // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts
   // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts
   _dxgsg->dx_init();
   _dxgsg->dx_init();
-
-  if(dx_use_dx_cursor && is_fullscreen()) {
-      hr = CreateDX9Cursor(_wcontext.pD3DDevice,_mouse_cursor,dx_show_cursor_watermark);
-      if(FAILED(hr))
-          wdxdisplay9_cat.error() << "CreateDX9Cursor failed!" <<  D3DERRORSTRING(hr);
-  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1831,30 +1811,5 @@ open_window(void) {
 bool wdxGraphicsWindow9::
 bool wdxGraphicsWindow9::
 handle_mouse_motion(int x, int y) {
 handle_mouse_motion(int x, int y) {
   (void) WinGraphicsWindow::handle_mouse_motion(x,y);
   (void) WinGraphicsWindow::handle_mouse_motion(x,y);
-  if(dx_use_dx_cursor && is_fullscreen() && (_wcontext.pD3DDevice!=NULL)) {
-      _wcontext.pD3DDevice->SetCursorPosition(x,y,D3DCURSOR_IMMEDIATE_UPDATE);
-      // return true to indicate wind_proc should return 0 instead of going to DefaultWindowProc
-      return true;
-  }
   return false;
   return false;
 }
 }
-
-#if 0
-// does NOT override _props._bCursorIsVisible
-INLINE void wdxGraphicsWindow::
-set_cursor_visibility(bool bVisible) {
-  if(_props._bCursorIsVisible) {
-      if(dx_use_dx_cursor) {
-          ShowCursor(false);
-          if(IS_VALID_PTR(_wcontext.pD3DDevice))
-              _dxgsg->scrn.pD3DDevice->ShowCursor(bVisible);
-      } else {
-         ShowCursor(bVisible);
-      }
-  } else {
-      ShowCursor(false);
-      if(dx_use_dx_cursor && IS_VALID_PTR(_wcontext.pD3DDevice))
-          _dxgsg->scrn.pD3DDevice->ShowCursor(false);
-  }
-}
-#endif

+ 0 - 8
panda/src/framework/config_framework.cxx

@@ -29,14 +29,6 @@ ConfigVariableDouble aspect_ratio
 ConfigVariableBool show_frame_rate_meter
 ConfigVariableBool show_frame_rate_meter
 ("show-frame-rate-meter", false);
 ("show-frame-rate-meter", false);
 
 
-// The default window background color.
-ConfigVariableDouble win_background_r
-("win-background-r", 0.41);
-ConfigVariableDouble win_background_g
-("win-background-g", 0.41);
-ConfigVariableDouble win_background_b
-("win-background-b", 0.41);
-
 ConfigVariableString record_session
 ConfigVariableString record_session
 ("record-session", "");
 ("record-session", "");
 ConfigVariableString playback_session
 ConfigVariableString playback_session

+ 0 - 4
panda/src/framework/config_framework.h

@@ -32,10 +32,6 @@ NotifyCategoryDecl(framework, EXPCL_FRAMEWORK, EXPTP_FRAMEWORK);
 extern ConfigVariableDouble aspect_ratio;
 extern ConfigVariableDouble aspect_ratio;
 extern ConfigVariableBool show_frame_rate_meter;
 extern ConfigVariableBool show_frame_rate_meter;
 
 
-extern ConfigVariableDouble win_background_r;
-extern ConfigVariableDouble win_background_g;
-extern ConfigVariableDouble win_background_b;
-
 extern ConfigVariableString record_session;
 extern ConfigVariableString record_session;
 extern ConfigVariableString playback_session;
 extern ConfigVariableString playback_session;
 
 

+ 3 - 2
panda/src/framework/pandaFramework.cxx

@@ -48,7 +48,7 @@ PandaFramework() :
   _texture_enabled = true;
   _texture_enabled = true;
   _two_sided_enabled = false;
   _two_sided_enabled = false;
   _lighting_enabled = false;
   _lighting_enabled = false;
-  _background_type = WindowFramework::BT_gray;
+  _background_type = WindowFramework::BT_default;
   _highlight_wireframe = NodePath("wireframe");
   _highlight_wireframe = NodePath("wireframe");
   _highlight_wireframe.set_render_mode_wireframe(1);
   _highlight_wireframe.set_render_mode_wireframe(1);
   _highlight_wireframe.set_color(1.0f, 0.0f, 0.0f, 1.0f, 1);
   _highlight_wireframe.set_color(1.0f, 0.0f, 0.0f, 1.0f, 1);
@@ -1206,9 +1206,10 @@ event_comma(CPT_Event event, void *) {
 
 
     switch (wf->get_background_type()) {
     switch (wf->get_background_type()) {
     case WindowFramework::BT_other:
     case WindowFramework::BT_other:
+    case WindowFramework::BT_none:
       break;
       break;
       
       
-    case WindowFramework::BT_none:
+    case WindowFramework::BT_white:
       wf->set_background_type(WindowFramework::BT_default);
       wf->set_background_type(WindowFramework::BT_default);
       break;
       break;
       
       

+ 12 - 6
panda/src/framework/windowFramework.cxx

@@ -868,12 +868,18 @@ set_background_type(WindowFramework::BackgroundType type) {
   switch (_background_type) {
   switch (_background_type) {
   case BT_other:
   case BT_other:
     break;
     break;
-    
+
   case BT_default:
   case BT_default:
     _display_region_3d->set_clear_color_active(true);
     _display_region_3d->set_clear_color_active(true);
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_depth_active(true);
-    _display_region_3d->set_clear_color(Colorf(win_background_r, win_background_g, 
-                                               win_background_b, 1.0f));
+    _display_region_3d->set_clear_color(_window->get_clear_color());
+    _display_region_3d->set_clear_depth(_window->get_clear_depth());
+    break;
+    
+  case BT_black:
+    _display_region_3d->set_clear_color_active(true);
+    _display_region_3d->set_clear_depth_active(true);
+    _display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 1.0f));
     _display_region_3d->set_clear_depth(1.0f);
     _display_region_3d->set_clear_depth(1.0f);
     break;
     break;
     
     
@@ -884,12 +890,12 @@ set_background_type(WindowFramework::BackgroundType type) {
     _display_region_3d->set_clear_depth(1.0f);
     _display_region_3d->set_clear_depth(1.0f);
     break;
     break;
     
     
-  case BT_black:
+  case BT_white:
     _display_region_3d->set_clear_color_active(true);
     _display_region_3d->set_clear_color_active(true);
     _display_region_3d->set_clear_depth_active(true);
     _display_region_3d->set_clear_depth_active(true);
-    _display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 1.0f));
+    _display_region_3d->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
     _display_region_3d->set_clear_depth(1.0f);
     _display_region_3d->set_clear_depth(1.0f);
-      break;
+    break;
 
 
   case BT_none:
   case BT_none:
     _display_region_3d->set_clear_color_active(false);
     _display_region_3d->set_clear_color_active(false);

+ 2 - 1
panda/src/framework/windowFramework.h

@@ -92,8 +92,9 @@ public:
   enum BackgroundType {
   enum BackgroundType {
     BT_other = 0,
     BT_other = 0,
     BT_default,
     BT_default,
-    BT_gray,
     BT_black,
     BT_black,
+    BT_gray,
+    BT_white,
     BT_none
     BT_none
   };
   };
 
 

+ 0 - 9
panda/src/windisplay/config_windisplay.cxx

@@ -28,15 +28,6 @@ ConfigureFn(config_windisplay) {
   init_libwindisplay();
   init_libwindisplay();
 }
 }
 
 
-ConfigVariableFilename icon_filename
-("win32-window-icon", "");
-
-ConfigVariableFilename color_cursor_filename
-("win32-color-cursor", "");
-
-ConfigVariableFilename mono_cursor_filename
-("win32-mono-cursor", "");
-
 ConfigVariableBool responsive_minimized_fullscreen_window
 ConfigVariableBool responsive_minimized_fullscreen_window
 ("responsive-minimized-fullscreen-window",false);
 ("responsive-minimized-fullscreen-window",false);
 
 

+ 0 - 5
panda/src/windisplay/config_windisplay.h

@@ -22,15 +22,10 @@
 #include "pandabase.h"
 #include "pandabase.h"
 #include "filename.h"
 #include "filename.h"
 #include "notifyCategoryProxy.h"
 #include "notifyCategoryProxy.h"
-#include "configVariableFilename.h"
 #include "configVariableBool.h"
 #include "configVariableBool.h"
 
 
 NotifyCategoryDecl(windisplay, EXPCL_PANDAWIN, EXPTP_PANDAWIN);
 NotifyCategoryDecl(windisplay, EXPCL_PANDAWIN, EXPTP_PANDAWIN);
 
 
-extern ConfigVariableFilename icon_filename;
-extern ConfigVariableFilename color_cursor_filename;
-extern ConfigVariableFilename mono_cursor_filename;
-
 extern ConfigVariableBool responsive_minimized_fullscreen_window;
 extern ConfigVariableBool responsive_minimized_fullscreen_window;
 extern ConfigVariableBool hold_keys_across_windows;
 extern ConfigVariableBool hold_keys_across_windows;
 extern ConfigVariableBool do_vidmemsize_check;
 extern ConfigVariableBool do_vidmemsize_check;

+ 24 - 0
panda/src/windisplay/winGraphicsWindow.I

@@ -137,3 +137,27 @@ get_ime_hwnd() {
   else
   else
     return NULL;
     return NULL;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::WindowClass::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE WinGraphicsWindow::WindowClass::
+WindowClass(const WindowProperties &props) :
+  _icon(0)
+{
+  if (props.has_icon_filename()) {
+    _icon = get_icon(props.get_icon_filename());
+  }
+}
+  
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::WindowClass::operator <
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool WinGraphicsWindow::WindowClass::
+operator < (const WinGraphicsWindow::WindowClass &other) const {
+  return _icon < other._icon;
+}

+ 190 - 135
panda/src/windisplay/winGraphicsWindow.cxx

@@ -24,16 +24,12 @@
 #include "keyboardButton.h"
 #include "keyboardButton.h"
 #include "mouseButton.h"
 #include "mouseButton.h"
 #include "clockObject.h"
 #include "clockObject.h"
+#include "config_util.h"
 
 
 #include <tchar.h>
 #include <tchar.h>
 
 
 TypeHandle WinGraphicsWindow::_type_handle;
 TypeHandle WinGraphicsWindow::_type_handle;
 
 
-bool WinGraphicsWindow::_loaded_custom_cursor;
-HCURSOR WinGraphicsWindow::_mouse_cursor;
-const char * const WinGraphicsWindow::_window_class_name = "WinGraphicsWindow";
-bool WinGraphicsWindow::_window_class_registered = false;
-
 WinGraphicsWindow::WindowHandles WinGraphicsWindow::_window_handles;
 WinGraphicsWindow::WindowHandles WinGraphicsWindow::_window_handles;
 WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
 WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
 
 
@@ -48,6 +44,12 @@ int WinGraphicsWindow::_saved_mouse_trails;
 BOOL WinGraphicsWindow::_saved_cursor_shadow;
 BOOL WinGraphicsWindow::_saved_cursor_shadow;
 BOOL WinGraphicsWindow::_saved_mouse_vanish;
 BOOL WinGraphicsWindow::_saved_mouse_vanish;
 
 
+WinGraphicsWindow::IconFilenames WinGraphicsWindow::_icon_filenames;
+WinGraphicsWindow::IconFilenames WinGraphicsWindow::_cursor_filenames;
+
+WinGraphicsWindow::WindowClasses WinGraphicsWindow::_window_classes;
+int WinGraphicsWindow::_window_class_index = 0;
+
 static const char * const errorbox_title = "Panda3D Error";
 static const char * const errorbox_title = "Panda3D Error";
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -245,6 +247,22 @@ set_properties_now(WindowProperties &properties) {
     properties.clear_cursor_hidden();
     properties.clear_cursor_hidden();
   }
   }
 
 
+  if (properties.has_cursor_filename()) {
+    Filename filename = properties.get_cursor_filename();
+    _properties.set_cursor_filename(filename);
+
+    _cursor = get_cursor(filename);
+    if (_cursor == 0) {
+      _cursor = LoadCursor(NULL, IDC_ARROW);
+    }
+
+    if (_cursor_window == this) {
+      SetCursor(_cursor);
+    }
+
+    properties.clear_cursor_filename();
+  }
+
   if (properties.has_z_order()) {
   if (properties.has_z_order()) {
     WindowProperties::ZOrder last_z_order = _properties.get_z_order();
     WindowProperties::ZOrder last_z_order = _properties.get_z_order();
     _properties.set_z_order(properties.get_z_order());
     _properties.set_z_order(properties.get_z_order());
@@ -287,6 +305,13 @@ close_window() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool WinGraphicsWindow::
 bool WinGraphicsWindow::
 open_window() {
 open_window() {
+  if (_properties.has_cursor_filename()) {
+    _cursor = get_cursor(_properties.get_cursor_filename());
+  }
+  if (_cursor == 0) {
+    _cursor = LoadCursor(NULL, IDC_ARROW);
+  }
+
   // Store the current window pointer in _creating_window, so we can
   // Store the current window pointer in _creating_window, so we can
   // call CreateWindow() and know which window it is sending events to
   // call CreateWindow() and know which window it is sending events to
   // even before it gives us a handle.  Warning: this is not thread
   // even before it gives us a handle.  Warning: this is not thread
@@ -595,11 +620,11 @@ open_fullscreen_window() {
   // I'd prefer to CreateWindow after DisplayChange in case it messes
   // I'd prefer to CreateWindow after DisplayChange in case it messes
   // up GL somehow, but I need the window's black background to cover
   // up GL somehow, but I need the window's black background to cover
   // up the desktop during the mode change
   // up the desktop during the mode change
-  register_window_class();
+  const WindowClass &wclass = register_window_class(_properties);
   HINSTANCE hinstance = GetModuleHandle(NULL);
   HINSTANCE hinstance = GetModuleHandle(NULL);
-  _hWnd = CreateWindow(_window_class_name, title.c_str(), window_style,
-                          0, 0, dwWidth, dwHeight, 
-                          hDesktopWindow, NULL, hinstance, 0);
+  _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style,
+                       0, 0, dwWidth, dwHeight, 
+                       hDesktopWindow, NULL, hinstance, 0);
   if (!_hWnd) {
   if (!_hWnd) {
     windisplay_cat.error()
     windisplay_cat.error()
       << "CreateWindow() failed!" << endl;
       << "CreateWindow() failed!" << endl;
@@ -686,13 +711,13 @@ open_regular_window() {
     title = _properties.get_title();
     title = _properties.get_title();
   }
   }
 
 
-  register_window_class();
+  const WindowClass &wclass = register_window_class(_properties);
   HINSTANCE hinstance = GetModuleHandle(NULL);
   HINSTANCE hinstance = GetModuleHandle(NULL);
-  _hWnd = CreateWindow(_window_class_name, title.c_str(), window_style, 
-                          win_rect.left, win_rect.top,
-                          win_rect.right - win_rect.left,
-                          win_rect.bottom - win_rect.top,
-                          NULL, NULL, hinstance, 0);
+  _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style, 
+                       win_rect.left, win_rect.top,
+                       win_rect.right - win_rect.left,
+                       win_rect.bottom - win_rect.top,
+                       NULL, NULL, hinstance, 0);
 
 
   if (!_hWnd) {
   if (!_hWnd) {
     windisplay_cat.error()
     windisplay_cat.error()
@@ -836,30 +861,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
         set_cursor_out_of_window();
         set_cursor_out_of_window();
         break;
         break;
     
     
-      // if cursor is invisible, make it visible when moving in the window bars & menus, so user can use click in them
-      case WM_NCMOUSEMOVE: {
-            if(!_properties.get_cursor_hidden()) {
-                if(!_bCursor_in_WindowClientArea) {
-                    // SetCursor(_pParentWindowGroup->_hMouseCursor);
-                    hide_or_show_cursor(false);
-                    _bCursor_in_WindowClientArea=true;
-                }
-            }
-            break;
-      }
-    
-      case WM_NCMOUSELEAVE: {
-            if(!_properties.get_cursor_hidden()) {
-                hide_or_show_cursor(true);
-                // SetCursor(NULL);
-                _bCursor_in_WindowClientArea=false;
-            }
-            break;
-      }
-    
       case WM_CREATE: {
       case WM_CREATE: {
         track_mouse_leaving(hwnd);
         track_mouse_leaving(hwnd);
-        _bCursor_in_WindowClientArea=false;
         ClearToBlack(hwnd,_properties);
         ClearToBlack(hwnd,_properties);
     
     
         POINT cpos;
         POINT cpos;
@@ -1600,8 +1603,10 @@ update_cursor_window(WinGraphicsWindow *to_window) {
       SystemParametersInfo(SPI_SETCURSORSHADOW, NULL, (PVOID)false, NULL);
       SystemParametersInfo(SPI_SETCURSORSHADOW, NULL, (PVOID)false, NULL);
       SystemParametersInfo(SPI_SETMOUSEVANISH, NULL, (PVOID)false, NULL);
       SystemParametersInfo(SPI_SETMOUSEVANISH, NULL, (PVOID)false, NULL);
     }
     }
-  }
 
 
+    SetCursor(to_window->_cursor);
+  }
+  
   hide_or_show_cursor(hide_cursor);
   hide_or_show_cursor(hide_cursor);
 
 
   _cursor_window = to_window;
   _cursor_window = to_window;
@@ -1629,103 +1634,6 @@ hide_or_show_cursor(bool hide_cursor) {
     }
     }
   }
   }
 }
 }
-  
-////////////////////////////////////////////////////////////////////
-//     Function: WinGraphicsWindow::register_window_class
-//       Access: Private, Static
-//  Description: Registers a Window class for all WinGraphicsWindows.
-//               This only needs to be done once per session.
-////////////////////////////////////////////////////////////////////
-void WinGraphicsWindow::
-register_window_class() {
-  if (_window_class_registered) {
-    return;
-  }
-
-  WNDCLASS wc;
-
-  HINSTANCE instance = GetModuleHandle(NULL);
-
-  // Clear before filling in window structure!
-  ZeroMemory(&wc, sizeof(WNDCLASS));
-  wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
-  wc.lpfnWndProc = (WNDPROC)static_window_proc;
-  wc.hInstance = instance;
-
-  // Might be nice to move these properties into the WindowProperties
-  // structure, so they don't have to be global for all windows.
-  string windows_icon_filename = icon_filename.get_value().to_os_specific();
-  string windows_mono_cursor_filename = mono_cursor_filename.get_value().to_os_specific();
-
-  if (!windows_icon_filename.empty()) {
-    // Note: LoadImage seems to cause win2k internal heap corruption
-    // (outputdbgstr warnings) if icon is more than 8bpp
-
-    // loads a .ico fmt file
-    wc.hIcon = (HICON)LoadImage(NULL, windows_icon_filename.c_str(),
-                                IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
-
-    if (wc.hIcon == NULL) {
-      windisplay_cat.warning()
-        << "windows icon filename '" << windows_icon_filename
-        << "' not found!!\n";
-    }
-  } else {
-    wc.hIcon = NULL; // use default app icon
-  }
-
-  _loaded_custom_cursor = false;
-  if (!windows_mono_cursor_filename.empty()) {
-    // Note: LoadImage seems to cause win2k internal heap corruption
-    // (outputdbgstr warnings) if icon is more than 8bpp (because it
-    // was 'mapping' 16bpp colors to the device?)
-    
-    DWORD load_flags = LR_LOADFROMFILE;
-
-    /*
-    if (_props._fullscreen) {
-      // I think cursors should use LR_CREATEDIBSECTION since they
-      // should not be mapped to the device palette (in the case of
-      // 256-color cursors) since they are not going to be used on the
-      // desktop
-      load_flags |= LR_CREATEDIBSECTION;
-
-      // Of course, we can't make this determination here because one
-      // window class is used for all windows, fullscreen as well as
-      // desktop windows.
-    }
-    */
-
-    // loads a .cur fmt file
-    _mouse_cursor = (HCURSOR) LoadImage(NULL, windows_mono_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, load_flags);
-    
-    if (_mouse_cursor == NULL) {
-      windisplay_cat.warning()
-        << "windows cursor filename '" << windows_mono_cursor_filename
-        << "' not found!!\n";
-    } else {
-      _loaded_custom_cursor = true;
-    }
-  }
-
-  if (!_loaded_custom_cursor) {
-    _mouse_cursor = LoadCursor(NULL, IDC_ARROW);
-  }
-
-  // even if cursor isnt visible, we need to load it so its visible
-  // in client-area window border
-  wc.hCursor = _mouse_cursor;  
-  wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
-  wc.lpszMenuName = NULL;
-  wc.lpszClassName = _window_class_name;
-  
-  if (!RegisterClass(&wc)) {
-    windisplay_cat.error()
-      << "could not register window class!" << endl;
-    return;
-  }
-  _window_class_registered = true;
-}
 
 
 // dont pick any video modes < MIN_REFRESH_RATE Hz
 // dont pick any video modes < MIN_REFRESH_RATE Hz
 #define MIN_REFRESH_RATE 60
 #define MIN_REFRESH_RATE 60
@@ -1897,6 +1805,153 @@ handle_mouse_exit() {
   _input_devices[0].set_pointer_out_of_window();
   _input_devices[0].set_pointer_out_of_window();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::get_icon
+//       Access: Private, Static
+//  Description: Loads and returns an HICON corresponding to the
+//               indicated filename.  If the file cannot be loaded,
+//               returns 0.
+////////////////////////////////////////////////////////////////////
+HICON WinGraphicsWindow::
+get_icon(const Filename &filename) {
+  // First, look for the unresolved filename in our index.
+  IconFilenames::iterator fi = _icon_filenames.find(filename);
+  if (fi != _icon_filenames.end()) {
+    return (HICON)((*fi).second);
+  }
+
+  // If it wasn't found, resolve the filename and search for that.
+
+  // Since we have to use a Windows call to load the image from a
+  // filename, we can't load a virtual file and we can't use the
+  // virtual file system.
+  Filename resolved = filename;
+  if (!resolved.resolve_filename(model_path)) {
+    // The filename doesn't exist.
+    windisplay_cat.warning()
+      << "Could not find icon filename " << filename << "\n";
+    return 0;
+  }
+  fi = _icon_filenames.find(resolved);
+  if (fi != _icon_filenames.end()) {
+    _icon_filenames[filename] = (*fi).second;
+    return (HICON)((*fi).second);
+  }
+
+  Filename os = resolved.to_os_specific();
+
+  HANDLE h = LoadImage(NULL, os.c_str(),
+                       IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
+  if (h == 0) {
+    windisplay_cat.warning()
+      << "windows icon filename '" << os << "' could not be loaded!!\n";
+    show_error_message();
+  }
+
+  _icon_filenames[filename] = h;
+  _icon_filenames[resolved] = h;
+  return (HICON)h;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::get_cursor
+//       Access: Private, Static
+//  Description: Loads and returns an HCURSOR corresponding to the
+//               indicated filename.  If the file cannot be loaded,
+//               returns 0.
+////////////////////////////////////////////////////////////////////
+HCURSOR WinGraphicsWindow::
+get_cursor(const Filename &filename) {
+  // First, look for the unresolved filename in our index.
+  IconFilenames::iterator fi = _cursor_filenames.find(filename);
+  if (fi != _cursor_filenames.end()) {
+    return (HCURSOR)((*fi).second);
+  }
+
+  // If it wasn't found, resolve the filename and search for that.
+
+  // Since we have to use a Windows call to load the image from a
+  // filename, we can't load a virtual file and we can't use the
+  // virtual file system.
+  Filename resolved = filename;
+  if (!resolved.resolve_filename(model_path)) {
+    // The filename doesn't exist.
+    windisplay_cat.warning()
+      << "Could not find cursor filename " << filename << "\n";
+    return 0;
+  }
+  fi = _cursor_filenames.find(resolved);
+  if (fi != _cursor_filenames.end()) {
+    _cursor_filenames[filename] = (*fi).second;
+    return (HCURSOR)((*fi).second);
+  }
+
+  Filename os = resolved.to_os_specific();
+
+  HANDLE h = LoadImage(NULL, os.c_str(),
+                       IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
+  if (h == 0) {
+    windisplay_cat.warning()
+      << "windows cursor filename '" << os << "' could not be loaded!!\n";
+    show_error_message();
+  }
+
+  _cursor_filenames[filename] = h;
+  _cursor_filenames[resolved] = h;
+  return (HCURSOR)h;
+}
+
+static HCURSOR get_cursor(const Filename &filename);
+  
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::register_window_class
+//       Access: Private, Static
+//  Description: Registers a Window class appropriate for the
+//               indicated properties.  This class may be shared by
+//               multiple windows.
+////////////////////////////////////////////////////////////////////
+const WinGraphicsWindow::WindowClass &WinGraphicsWindow::
+register_window_class(const WindowProperties &props) {
+  pair<WindowClasses::iterator, bool> found = 
+    _window_classes.insert(WindowClass(props));
+  WindowClass &wclass = (*found.first);
+
+  if (!found.second) {
+    // We have already created a window class.
+    return wclass;
+  }
+
+  // We have not yet created this window class.
+  ostringstream wclass_name;
+  wclass_name << "WinGraphicsWindow" << _window_class_index;
+  _window_class_index++;
+  wclass._name = wclass_name.str();
+
+  WNDCLASS wc;
+
+  HINSTANCE instance = GetModuleHandle(NULL);
+
+  // Clear before filling in window structure!
+  ZeroMemory(&wc, sizeof(WNDCLASS));
+  wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+  wc.lpfnWndProc = (WNDPROC)static_window_proc;
+  wc.hInstance = instance;
+
+  wc.hIcon = wclass._icon;
+
+  wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+  wc.lpszMenuName = NULL;
+  wc.lpszClassName = wclass._name.c_str();
+  
+  if (!RegisterClass(&wc)) {
+    windisplay_cat.error()
+      << "could not register window class " << wclass._name << "!" << endl;
+    return wclass;
+  }
+
+  return wclass;
+}
+
 // pops up MsgBox w/system error msg
 // pops up MsgBox w/system error msg
 void PrintErrorMessage(DWORD msgID) {
 void PrintErrorMessage(DWORD msgID) {
   LPTSTR pMessageBuffer;
   LPTSTR pMessageBuffer;

+ 30 - 8
panda/src/windisplay/winGraphicsWindow.h

@@ -103,7 +103,6 @@ private:
   static void update_cursor_window(WinGraphicsWindow *to_window);
   static void update_cursor_window(WinGraphicsWindow *to_window);
   static void hide_or_show_cursor(bool hide_cursor);
   static void hide_or_show_cursor(bool hide_cursor);
 
 
-  static void register_window_class();
   static bool find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight,
   static bool find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight,
                                            DWORD bpp, DEVMODE &dm);
                                            DWORD bpp, DEVMODE &dm);
   static void show_error_message(DWORD message_id = 0);
   static void show_error_message(DWORD message_id = 0);
@@ -118,7 +117,7 @@ private:
   bool _ime_composition_w;
   bool _ime_composition_w;
   bool _tracking_mouse_leaving;
   bool _tracking_mouse_leaving;
   bool _maximized;
   bool _maximized;
-  bool _bCursor_in_WindowClientArea;
+  HCURSOR _cursor;
   DEVMODE _fullscreen_display_mode;
   DEVMODE _fullscreen_display_mode;
 
 
   // This is used to remember the state of the keyboard when keyboard
   // This is used to remember the state of the keyboard when keyboard
@@ -137,12 +136,6 @@ private:
   BYTE _keyboard_state[num_virtual_keys];
   BYTE _keyboard_state[num_virtual_keys];
   bool _lost_keypresses;
   bool _lost_keypresses;
 
 
-protected:
-  static bool _loaded_custom_cursor;
-  static HCURSOR _mouse_cursor;
-  static const char * const _window_class_name;
-  static bool _window_class_registered;
-
 private:
 private:
   // We need this map to support per-window calls to window_proc().
   // We need this map to support per-window calls to window_proc().
   typedef map<HWND, WinGraphicsWindow *> WindowHandles;
   typedef map<HWND, WinGraphicsWindow *> WindowHandles;
@@ -168,6 +161,35 @@ private:
   static BOOL _saved_cursor_shadow;
   static BOOL _saved_cursor_shadow;
   static BOOL _saved_mouse_vanish;
   static BOOL _saved_mouse_vanish;
 
 
+  // 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.
+  typedef pmap<Filename, HANDLE> IconFilenames;
+  static IconFilenames _icon_filenames;
+  static IconFilenames _cursor_filenames;
+
+  static HICON get_icon(const Filename &filename);
+  static HCURSOR get_cursor(const Filename &filename);
+
+  // The table of window classes we have registered.  We need to
+  // register a different window class for each different window icon
+  // (the cursor we can specify dynamically, later).  We might have
+  // other requirements too, later.
+  class WindowClass {
+  public:
+    INLINE WindowClass(const WindowProperties &props);
+    INLINE bool operator < (const WindowClass &other) const;
+
+    string _name;
+    HICON _icon;
+  };
+
+  typedef pset<WindowClass> WindowClasses;
+  static WindowClasses _window_classes;
+  static int _window_class_index;
+
+  static const WindowClass &register_window_class(const WindowProperties &props);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;