diff --git a/panda/src/wgldisplay/wglGraphicsWindow.cxx b/panda/src/wgldisplay/wglGraphicsWindow.cxx index dcfd0bee0f..dab842656e 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.cxx +++ b/panda/src/wgldisplay/wglGraphicsWindow.cxx @@ -47,9 +47,6 @@ TypeHandle wglGraphicsWindow::_type_handle; static bool wc_registered = false; -#define MOUSE_ENTERED 0 -#define MOUSE_EXITED 1 - #define FONT_BITMAP_OGLDISPLAYLISTNUM 1000 // an arbitrary ID # #define LAST_ERROR 0 @@ -333,10 +330,6 @@ void wglGraphicsWindow::config() { _bIsLowVidMemCard = false; _active_minimized_fullscreen = false; _PandaPausedTimer = NULL; - _mouse_input_enabled = false; - _mouse_motion_enabled = false; - _mouse_passive_motion_enabled = false; - _mouse_entry_enabled = false; _context = NULL; _hdc = NULL; _window_inactive = false; @@ -348,6 +341,13 @@ void wglGraphicsWindow::config() { WNDCLASS wc; + // these fns arent defined on win95, so get dynamic ptrs to them to avoid + // ugly DLL loader failures on w95 + HINSTANCE hUser32 = (HINSTANCE) LoadLibrary("user32.dll"); + assert(hUser32); + _pfnTrackMouseEvent = (PFN_TRACKMOUSEEVENT) GetProcAddress(hUser32, "TrackMouseEvent"); + FreeLibrary(hUser32); + // Clear before filling in window structure! ZeroMemory(&wc, sizeof(WNDCLASS)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; @@ -576,11 +576,6 @@ void wglGraphicsWindow::config() { ShowWindow(_mwindow, SW_SHOWNORMAL); ShowWindow(_mwindow, SW_SHOWNORMAL); - // Enable detection of mouse input - enable_mouse_input(true); - enable_mouse_motion(true); - enable_mouse_passive_motion(true); - // Now indicate that we have our keyboard/mouse device ready. GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse"); @@ -1245,16 +1240,15 @@ void wglGraphicsWindow::handle_mouse_motion(int x, int y) { } //////////////////////////////////////////////////////////////////// -// Function: handle_mouse_entry +// Function: handle_mouse_exit // Access: // Description: //////////////////////////////////////////////////////////////////// -void wglGraphicsWindow::handle_mouse_entry(int state) { - if (state == MOUSE_EXITED) { +void wglGraphicsWindow::handle_mouse_exit(void) { + // note: 'mouse_motion' is considered the 'entry' event if (!_input_devices.empty()) { _input_devices[0].set_pointer_out_of_window(); } - } } //////////////////////////////////////////////////////////////////// @@ -1369,33 +1363,6 @@ void wglGraphicsWindow::update() { #endif } -//////////////////////////////////////////////////////////////////// -// Function: enable_mouse_input -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -void wglGraphicsWindow::enable_mouse_input(bool val) { - _mouse_input_enabled = val; -} - -//////////////////////////////////////////////////////////////////// -// Function: enable_mouse_motion -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -void wglGraphicsWindow::enable_mouse_motion(bool val) { - _mouse_motion_enabled = val; -} - -//////////////////////////////////////////////////////////////////// -// Function: enable_mouse_passive_motion -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -void wglGraphicsWindow::enable_mouse_passive_motion(bool val) { - _mouse_passive_motion_enabled = val; -} - //////////////////////////////////////////////////////////////////// // Function: make_current // Access: Public @@ -1592,6 +1559,23 @@ void wglGraphicsWindow::reactivate_window() { } } +// Note: could use _TrackMouseEvent in comctrl32.dll (part of IE 3.0+) which emulates +// TrackMouseEvent on w95, but that requires another 500K of memory to hold that DLL, +// which is lame just to support w95, which probably has other issues anyway +INLINE void wglGraphicsWindow:: +track_mouse_leaving(HWND hwnd) { + if(_pfnTrackMouseEvent==NULL) + return; + + TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT),TME_LEAVE,hwnd,0}; + BOOL bSucceeded = _pfnTrackMouseEvent(&tme); // tell win32 to post WM_MOUSELEAVE msgs + + if((!bSucceeded) && wgldisplay_cat.is_debug()) + wgldisplay_cat.debug() << "TrackMouseEvent failed!, LastError=" << GetLastError() << endl; + + _tracking_mouse_leaving=true; +} + //////////////////////////////////////////////////////////////////// // Function: window_proc // Access: @@ -1603,8 +1587,62 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { int x, y; switch (msg) { - case WM_CREATE: + + case WM_MOUSEMOVE: + // Win32 doesn't return the same numbers as X does when the mouse + // goes beyond the upper or left side of the window + #define SET_MOUSE_COORD(iVal,VAL) { \ + iVal = VAL; \ + if(iVal & 0x8000) \ + iVal -= 0x10000; \ + } + + if(!_tracking_mouse_leaving) { + // need to re-call TrackMouseEvent every time mouse re-enters window + track_mouse_leaving(hwnd); + } + + SET_MOUSE_COORD(x,LOWORD(lparam)); + SET_MOUSE_COORD(y,HIWORD(lparam)); + + if(wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) { + handle_mouse_motion(x, y); + } + break; + + // if cursor is invisible, make it visible when moving in the window bars,etc + case WM_NCMOUSEMOVE: { + if(!_props._bCursorIsVisible) { + if(!_cursor_in_windowclientarea) { + ShowCursor(true); + _cursor_in_windowclientarea=true; + } + } + break; + } + + case WM_NCMOUSELEAVE: { + if(!_props._bCursorIsVisible) { + ShowCursor(false); + _cursor_in_windowclientarea=false; + } + break; + } + + case WM_MOUSELEAVE: { + _tracking_mouse_leaving=false; + handle_mouse_exit(); + break; + } + + case WM_CREATE: { + track_mouse_leaving(hwnd); + + _cursor_in_windowclientarea=false; + if(!_props._bCursorIsVisible) + ShowCursor(false); break; + } case WM_CLOSE: close_window(); @@ -1842,18 +1880,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (button < 0) button = 2; SetCapture(hwnd); - // Win32 doesn't return the same numbers as X does when the mouse - // goes beyond the upper or left side of the window - #define SET_MOUSE_COORD(iVal,VAL) { \ - iVal = VAL; \ - if (iVal & 0x8000) \ - iVal -= 0x10000; \ - } - SET_MOUSE_COORD(x,LOWORD(lparam)); SET_MOUSE_COORD(y,HIWORD(lparam)); - - // make_current(); what does OGL have to do with mouse input?? handle_keypress(MouseButton::button(button), x, y); break; case WM_LBUTTONUP: @@ -1868,33 +1896,14 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { #if 0 SET_MOUSE_COORD(x,LOWORD(lparam)); SET_MOUSE_COORD(y,HIWORD(lparam)); - // make_current(); what does OGL have to do with mouse input?? #endif handle_keyrelease(MouseButton::button(button)); break; - case WM_MOUSEMOVE: - SET_MOUSE_COORD(x,LOWORD(lparam)); - SET_MOUSE_COORD(y,HIWORD(lparam)); - - if (mouse_motion_enabled() && - (wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) { - // make_current(); what does OGL have to do with mouse input?? - handle_mouse_motion(x, y); - } else if (mouse_passive_motion_enabled() && - ((wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)) { - // make_current(); what does OGL have to do with mouse input?? - handle_mouse_motion(x, y); - } - break; - case WM_SETFOCUS: { // wgldisplay_cat.info() << "got WM_SETFOCUS\n"; - if (_mouse_entry_enabled) { - make_current(); - handle_mouse_entry(MOUSE_ENTERED); - } + make_current(); POINT point; GetCursorPos(&point); @@ -1905,8 +1914,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // a key-down. it would be better to know the exact set of ModifierButtons the // user is using, since we may miss some here - int i; - for(i=0;i -#include +// include win32 defns for everything up to XP, and assume I'm smart enough to +// use GetProcAddress for backward compat on w95/w98 for newer fns +#define _WIN32_WINNT 0x0501 + #define WINDOWS_LEAN_AND_MEAN #include #undef WINDOWS_LEAN_AND_MEAN +#include +#include + //////////////////////////////////////////////////////////////////// // Defines //////////////////////////////////////////////////////////////////// @@ -76,33 +81,17 @@ public: public: virtual void make_current(); virtual void unmake_current(); - - INLINE bool mouse_entry_enabled() { return _mouse_entry_enabled; } - INLINE bool mouse_motion_enabled() { return _mouse_motion_enabled; } - INLINE bool mouse_passive_motion_enabled() { - return _mouse_passive_motion_enabled; - } -// void handle_reshape(int w, int h); - void handle_mouse_motion(int x, int y); - void handle_mouse_entry(int state); + void handle_mouse_exit(void); + INLINE void track_mouse_leaving(HWND hwnd); void handle_keypress(ButtonHandle key, int x, int y); void handle_keyrelease(ButtonHandle key); protected: -// PIXELFORMATDESCRIPTOR* try_for_visual(wglGraphicsPipe *pipe, -// int mask, int want_depth_bits = 1, int want_color_bits = 1); -// static void get_config(PIXELFORMATDESCRIPTOR* visual, int attrib, int *value); int choose_visual(void); int find_pixfmtnum(bool bLookforHW); virtual void config(); void setup_colormap(void); - - void enable_mouse_input(bool val); - void enable_mouse_motion(bool val); - void enable_mouse_passive_motion(bool val); - void enable_mouse_entry(bool val); - void handle_reshape(); void process_events(); @@ -126,11 +115,8 @@ private: bool _active_minimized_fullscreen; bool _return_control_to_app; bool _exiting_window; - - bool _mouse_input_enabled; - bool _mouse_motion_enabled; - bool _mouse_passive_motion_enabled; - bool _mouse_entry_enabled; + bool _cursor_in_windowclientarea; + bool _tracking_mouse_leaving; bool _ime_open; bool _ime_active; bool _ime_composition_w; @@ -143,6 +129,9 @@ private: string _extensions_str; + typedef BOOL (WINAPI* PFN_TRACKMOUSEEVENT)(LPTRACKMOUSEEVENT); + PFN_TRACKMOUSEEVENT _pfnTrackMouseEvent; + public: static TypeHandle get_class_type(); static void init_type();