handle icon and cursor filenames more robustly

This commit is contained in:
David Rose 2004-12-28 22:24:45 +00:00
parent ec81eaf841
commit 642dda0edd
22 changed files with 472 additions and 290 deletions

View File

@ -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<WindowProperties::ZOrder> 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

View File

@ -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<WindowProperties::ZOrder> z_order;
extern ConfigVariableString window_title;
extern ConfigVariableDouble background_color;
extern EXPCL_PANDA void init_libdisplay();
#endif /* CONFIG_DISPLAY_H */

View File

@ -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";
}
}
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -42,6 +42,8 @@ operator = (const WindowProperties &copy) {
_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() << " ";
}
}

View File

@ -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;
};

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -24,16 +24,12 @@
#include "keyboardButton.h"
#include "mouseButton.h"
#include "clockObject.h"
#include "config_util.h"
#include <tchar.h>
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<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
void PrintErrorMessage(DWORD msgID) {
LPTSTR pMessageBuffer;

View File

@ -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<HWND, WinGraphicsWindow *> 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<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:
static TypeHandle get_class_type() {
return _type_handle;