From 642dda0edd1866f17dab816d870c460a7c6dc2b6 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 28 Dec 2004 22:24:45 +0000 Subject: [PATCH] handle icon and cursor filenames more robustly --- panda/src/display/config_display.cxx | 29 +- panda/src/display/config_display.h | 8 + panda/src/display/graphicsOutput.cxx | 23 ++ panda/src/display/windowProperties.I | 94 +++++- panda/src/display/windowProperties.cxx | 52 +++- panda/src/display/windowProperties.h | 15 + panda/src/dxgsg8/config_dxgsg8.cxx | 5 - panda/src/dxgsg8/config_dxgsg8.h | 1 - panda/src/dxgsg8/wdxGraphicsWindow8.cxx | 45 --- panda/src/dxgsg9/config_dxgsg9.cxx | 5 - panda/src/dxgsg9/config_dxgsg9.h | 1 - panda/src/dxgsg9/wdxGraphicsWindow9.cxx | 45 --- panda/src/framework/config_framework.cxx | 8 - panda/src/framework/config_framework.h | 4 - panda/src/framework/pandaFramework.cxx | 5 +- panda/src/framework/windowFramework.cxx | 18 +- panda/src/framework/windowFramework.h | 3 +- panda/src/windisplay/config_windisplay.cxx | 9 - panda/src/windisplay/config_windisplay.h | 5 - panda/src/windisplay/winGraphicsWindow.I | 24 ++ panda/src/windisplay/winGraphicsWindow.cxx | 325 ++++++++++++--------- panda/src/windisplay/winGraphicsWindow.h | 38 ++- 22 files changed, 472 insertions(+), 290 deletions(-) diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index 0d09efe007..547a31f878 100644 --- a/panda/src/display/config_display.cxx +++ b/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 " "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 -("win-width", 640); +("win-width", 0); ConfigVariableInt win_height -("win-height", 480); +("win-height", 0); ConfigVariableInt win_origin_x -("win-origin-x", -1); +("win-origin-x", 0); ConfigVariableInt win_origin_y -("win-origin-y", -1); +("win-origin-y", 0); ConfigVariableBool fullscreen ("fullscreen", false); @@ -140,12 +150,23 @@ ConfigVariableBool undecorated ConfigVariableBool cursor_hidden ("cursor-hidden", false); +ConfigVariableFilename icon_filename +("icon-filename", ""); + +ConfigVariableFilename cursor_filename +("cursor-filename", ""); + ConfigVariableEnum z_order ("z-order", WindowProperties::Z_normal); ConfigVariableString window_title ("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 diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index 3d88ca6014..f51c44b272 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -27,6 +27,7 @@ #include "configVariableList.h" #include "configVariableInt.h" #include "configVariableEnum.h" +#include "configVariableFilename.h" #include "dconfig.h" #include "pvector.h" @@ -53,6 +54,8 @@ extern ConfigVariableBool prefer_single_buffer; extern ConfigVariableBool copy_texture_inverted; extern ConfigVariableBool window_inverted; +extern ConfigVariableInt win_size; +extern ConfigVariableInt win_origin; extern ConfigVariableInt win_width; extern ConfigVariableInt win_height; extern ConfigVariableInt win_origin_x; @@ -60,9 +63,14 @@ extern ConfigVariableInt win_origin_y; extern ConfigVariableBool fullscreen; extern ConfigVariableBool undecorated; extern ConfigVariableBool cursor_hidden; +extern ConfigVariableFilename icon_filename; +extern ConfigVariableFilename cursor_filename; extern ConfigVariableEnum z_order; extern ConfigVariableString window_title; +extern ConfigVariableDouble background_color; + + extern EXPCL_PANDA void init_libdisplay(); #endif /* CONFIG_DISPLAY_H */ diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 666864a8f2..3bb6358002 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -79,6 +79,29 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, // depth. set_clear_color_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"; + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/windowProperties.I b/panda/src/display/windowProperties.I index 2cab0b1fa4..bcdeeff224 100644 --- a/panda/src/display/windowProperties.I +++ b/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 // Description: Returns true if the mouse cursor is invisible. //////////////////////////////////////////////////////////////////// @@ -561,6 +561,98 @@ clear_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 // Access: Published diff --git a/panda/src/display/windowProperties.cxx b/panda/src/display/windowProperties.cxx index 67164e53cf..e145dc0a35 100644 --- a/panda/src/display/windowProperties.cxx +++ b/panda/src/display/windowProperties.cxx @@ -42,6 +42,8 @@ operator = (const WindowProperties ©) { _x_size = copy._x_size; _y_size = copy._y_size; _title = copy._title; + _icon_filename = copy._icon_filename; + _cursor_filename = copy._cursor_filename; _z_order = copy._z_order; _flags = copy._flags; } @@ -58,14 +60,37 @@ get_default() { WindowProperties props; props.set_open(true); - props.set_size(win_width, win_height); - if (win_origin_x >= 0 && win_origin_y >= 0) { - props.set_origin(win_origin_x, win_origin_y); + + 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); + + } else { + props.set_origin(win_origin[0], win_origin[1]); + } + props.set_fullscreen(fullscreen); props.set_undecorated(undecorated); 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_title(window_title); @@ -87,7 +112,9 @@ operator == (const WindowProperties &other) const { _x_size == other._x_size && _y_size == other._y_size && _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; _y_size = 0; _title = string(); + _icon_filename = Filename(); + _cursor_filename = Filename(); _z_order = Z_normal; _flags = 0; } @@ -148,6 +177,12 @@ add_properties(const WindowProperties &other) { if (other.has_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()) { set_z_order(other.get_z_order()); } @@ -192,7 +227,14 @@ output(ostream &out) const { if (has_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()) { + out << get_z_order() << " "; } } diff --git a/panda/src/display/windowProperties.h b/panda/src/display/windowProperties.h index 3d5dd8cd15..8f53c78a6e 100644 --- a/panda/src/display/windowProperties.h +++ b/panda/src/display/windowProperties.h @@ -20,6 +20,7 @@ #define WINDOWPROPERTIES_H #include "pandabase.h" +#include "filename.h" #include "notify.h" //////////////////////////////////////////////////////////////////// @@ -102,6 +103,16 @@ PUBLISHED: INLINE bool has_cursor_hidden() const; 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 ZOrder get_z_order() const; INLINE bool has_z_order() const; @@ -127,6 +138,8 @@ private: S_cursor_hidden = 0x0100, S_fixed_size = 0x0200, S_z_order = 0x0400, + S_icon_filename = 0x0800, + S_cursor_filename = 0x1000, }; // This bitmask represents the true/false settings for various @@ -148,6 +161,8 @@ private: int _x_size; int _y_size; string _title; + Filename _cursor_filename; + Filename _icon_filename; ZOrder _z_order; int _flags; }; diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx index 2622bf54dc..6224a0d193 100644 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ b/panda/src/dxgsg8/config_dxgsg8.cxx @@ -133,11 +133,6 @@ ConfigVariableBool dx_debug_view_mipmaps ("dx-debug-view-mipmaps", false); #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 ("dx-force-anisotropic-filtering", false); diff --git a/panda/src/dxgsg8/config_dxgsg8.h b/panda/src/dxgsg8/config_dxgsg8.h index 24dc0eebdf..909a8a62f0 100644 --- a/panda/src/dxgsg8/config_dxgsg8.h +++ b/panda/src/dxgsg8/config_dxgsg8.h @@ -40,7 +40,6 @@ extern ConfigVariableBool dx_use_rangebased_fog; extern ConfigVariableBool link_tristrips; extern ConfigVariableInt dx_multisample_antialiasing_level; extern ConfigVariableBool dx_use_triangle_mipgen_filter; -extern ConfigVariableBool dx_use_dx_cursor; // debug flags we might want to use in full optimized build diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx index 0317ee5630..9deeed14f5 100644 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx @@ -465,20 +465,6 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { int x, y, width, height; 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: { // primarily seen when app window is 'uncovered' if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) { @@ -1682,12 +1668,6 @@ init_resized_window() { _dxgsg->set_context(&_wcontext); // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts _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:: handle_mouse_motion(int x, int 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; } - -#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 diff --git a/panda/src/dxgsg9/config_dxgsg9.cxx b/panda/src/dxgsg9/config_dxgsg9.cxx index 2fa5b59a1d..aacdd32003 100755 --- a/panda/src/dxgsg9/config_dxgsg9.cxx +++ b/panda/src/dxgsg9/config_dxgsg9.cxx @@ -133,11 +133,6 @@ ConfigVariableBool dx_debug_view_mipmaps ("dx-debug-view-mipmaps", false); #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 ("dx-force-anisotropic-filtering", false); diff --git a/panda/src/dxgsg9/config_dxgsg9.h b/panda/src/dxgsg9/config_dxgsg9.h index 5ec31502a3..a313d2e0a8 100755 --- a/panda/src/dxgsg9/config_dxgsg9.h +++ b/panda/src/dxgsg9/config_dxgsg9.h @@ -40,7 +40,6 @@ extern ConfigVariableBool dx_use_rangebased_fog; extern ConfigVariableBool link_tristrips; extern ConfigVariableInt dx_multisample_antialiasing_level; extern ConfigVariableBool dx_use_triangle_mipgen_filter; -extern ConfigVariableBool dx_use_dx_cursor; // debug flags we might want to use in full optimized build diff --git a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx index 489ddae790..e5bb534969 100755 --- a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx @@ -454,20 +454,6 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { int x, y, width, height; 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: { // primarily seen when app window is 'uncovered' if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) { @@ -1667,12 +1653,6 @@ init_resized_window() { _dxgsg->set_context(&_wcontext); // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts _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:: handle_mouse_motion(int x, int 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; } - -#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 diff --git a/panda/src/framework/config_framework.cxx b/panda/src/framework/config_framework.cxx index 9ede2d25d6..12be4892a9 100644 --- a/panda/src/framework/config_framework.cxx +++ b/panda/src/framework/config_framework.cxx @@ -29,14 +29,6 @@ ConfigVariableDouble aspect_ratio ConfigVariableBool show_frame_rate_meter ("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 ("record-session", ""); ConfigVariableString playback_session diff --git a/panda/src/framework/config_framework.h b/panda/src/framework/config_framework.h index 0123b1654d..f38a486dc2 100644 --- a/panda/src/framework/config_framework.h +++ b/panda/src/framework/config_framework.h @@ -32,10 +32,6 @@ NotifyCategoryDecl(framework, EXPCL_FRAMEWORK, EXPTP_FRAMEWORK); extern ConfigVariableDouble aspect_ratio; 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 playback_session; diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 0b5e5e2913..76ce7e7420 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -48,7 +48,7 @@ PandaFramework() : _texture_enabled = true; _two_sided_enabled = false; _lighting_enabled = false; - _background_type = WindowFramework::BT_gray; + _background_type = WindowFramework::BT_default; _highlight_wireframe = NodePath("wireframe"); _highlight_wireframe.set_render_mode_wireframe(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()) { case WindowFramework::BT_other: + case WindowFramework::BT_none: break; - case WindowFramework::BT_none: + case WindowFramework::BT_white: wf->set_background_type(WindowFramework::BT_default); break; diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index 127e4c25c0..db2c07b759 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -868,12 +868,18 @@ set_background_type(WindowFramework::BackgroundType type) { switch (_background_type) { case BT_other: break; - + case BT_default: _display_region_3d->set_clear_color_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); break; @@ -884,12 +890,12 @@ set_background_type(WindowFramework::BackgroundType type) { _display_region_3d->set_clear_depth(1.0f); break; - case BT_black: + case BT_white: _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_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); _display_region_3d->set_clear_depth(1.0f); - break; + break; case BT_none: _display_region_3d->set_clear_color_active(false); diff --git a/panda/src/framework/windowFramework.h b/panda/src/framework/windowFramework.h index 0de09c81bf..c8a795f6f8 100644 --- a/panda/src/framework/windowFramework.h +++ b/panda/src/framework/windowFramework.h @@ -92,8 +92,9 @@ public: enum BackgroundType { BT_other = 0, BT_default, - BT_gray, BT_black, + BT_gray, + BT_white, BT_none }; diff --git a/panda/src/windisplay/config_windisplay.cxx b/panda/src/windisplay/config_windisplay.cxx index cb7b9c4e21..b6b2abfed6 100644 --- a/panda/src/windisplay/config_windisplay.cxx +++ b/panda/src/windisplay/config_windisplay.cxx @@ -28,15 +28,6 @@ ConfigureFn(config_windisplay) { 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 ("responsive-minimized-fullscreen-window",false); diff --git a/panda/src/windisplay/config_windisplay.h b/panda/src/windisplay/config_windisplay.h index fe5ec07cf6..ea95f1fd89 100644 --- a/panda/src/windisplay/config_windisplay.h +++ b/panda/src/windisplay/config_windisplay.h @@ -22,15 +22,10 @@ #include "pandabase.h" #include "filename.h" #include "notifyCategoryProxy.h" -#include "configVariableFilename.h" #include "configVariableBool.h" 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 hold_keys_across_windows; extern ConfigVariableBool do_vidmemsize_check; diff --git a/panda/src/windisplay/winGraphicsWindow.I b/panda/src/windisplay/winGraphicsWindow.I index 2a020db86b..493ff80834 100644 --- a/panda/src/windisplay/winGraphicsWindow.I +++ b/panda/src/windisplay/winGraphicsWindow.I @@ -137,3 +137,27 @@ get_ime_hwnd() { else 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; +} diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index daca2560f8..fc5844706c 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -24,16 +24,12 @@ #include "keyboardButton.h" #include "mouseButton.h" #include "clockObject.h" +#include "config_util.h" #include 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 *WinGraphicsWindow::_creating_window = NULL; @@ -48,6 +44,12 @@ int WinGraphicsWindow::_saved_mouse_trails; BOOL WinGraphicsWindow::_saved_cursor_shadow; 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"; //////////////////////////////////////////////////////////////////// @@ -245,6 +247,22 @@ set_properties_now(WindowProperties &properties) { 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()) { WindowProperties::ZOrder last_z_order = _properties.get_z_order(); _properties.set_z_order(properties.get_z_order()); @@ -287,6 +305,13 @@ close_window() { //////////////////////////////////////////////////////////////////// bool WinGraphicsWindow:: 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 // call CreateWindow() and know which window it is sending events to // 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 // up GL somehow, but I need the window's black background to cover // up the desktop during the mode change - register_window_class(); + const WindowClass &wclass = register_window_class(_properties); 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) { windisplay_cat.error() << "CreateWindow() failed!" << endl; @@ -686,13 +711,13 @@ open_regular_window() { title = _properties.get_title(); } - register_window_class(); + const WindowClass &wclass = register_window_class(_properties); 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) { windisplay_cat.error() @@ -836,30 +861,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { set_cursor_out_of_window(); 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: { track_mouse_leaving(hwnd); - _bCursor_in_WindowClientArea=false; ClearToBlack(hwnd,_properties); POINT cpos; @@ -1600,8 +1603,10 @@ update_cursor_window(WinGraphicsWindow *to_window) { SystemParametersInfo(SPI_SETCURSORSHADOW, NULL, (PVOID)false, NULL); SystemParametersInfo(SPI_SETMOUSEVANISH, NULL, (PVOID)false, NULL); } - } + SetCursor(to_window->_cursor); + } + hide_or_show_cursor(hide_cursor); _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 #define MIN_REFRESH_RATE 60 @@ -1897,6 +1805,153 @@ handle_mouse_exit() { _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 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 void PrintErrorMessage(DWORD msgID) { LPTSTR pMessageBuffer; diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 96dfac7381..7330068a30 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -103,7 +103,6 @@ private: static void update_cursor_window(WinGraphicsWindow *to_window); static void hide_or_show_cursor(bool hide_cursor); - static void register_window_class(); static bool find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp, DEVMODE &dm); static void show_error_message(DWORD message_id = 0); @@ -118,7 +117,7 @@ private: bool _ime_composition_w; bool _tracking_mouse_leaving; bool _maximized; - bool _bCursor_in_WindowClientArea; + HCURSOR _cursor; DEVMODE _fullscreen_display_mode; // This is used to remember the state of the keyboard when keyboard @@ -137,12 +136,6 @@ private: BYTE _keyboard_state[num_virtual_keys]; 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: // We need this map to support per-window calls to window_proc(). typedef map WindowHandles; @@ -168,6 +161,35 @@ private: static BOOL _saved_cursor_shadow; 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 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 WindowClasses; + static WindowClasses _window_classes; + static int _window_class_index; + + static const WindowClass ®ister_window_class(const WindowProperties &props); + public: static TypeHandle get_class_type() { return _type_handle;