diff --git a/panda/src/display/graphicsWindowInputDevice.cxx b/panda/src/display/graphicsWindowInputDevice.cxx index 53807e68e9..df63a2a0f3 100644 --- a/panda/src/display/graphicsWindowInputDevice.cxx +++ b/panda/src/display/graphicsWindowInputDevice.cxx @@ -158,6 +158,19 @@ button_down(ButtonHandle button) { _button_events.push_back(ButtonEvent(button, ButtonEvent::T_down)); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindowInputDevice::button_resume_down +// Access: Public +// Description: Records that the indicated button was depressed +// earlier, and we only just detected the event after +// the fact. This is mainly useful for tracking the +// state of modifier keys. +//////////////////////////////////////////////////////////////////// +void GraphicsWindowInputDevice:: +button_resume_down(ButtonHandle button) { + _button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down)); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsWindowInputDevice::button_up // Access: Public diff --git a/panda/src/display/graphicsWindowInputDevice.h b/panda/src/display/graphicsWindowInputDevice.h index 6c0c2540ac..1f1589097a 100644 --- a/panda/src/display/graphicsWindowInputDevice.h +++ b/panda/src/display/graphicsWindowInputDevice.h @@ -62,6 +62,7 @@ public: // The following interface is for the various kinds of // GraphicsWindows to record the data incoming on the device. void button_down(ButtonHandle button); + void button_resume_down(ButtonHandle button); void button_up(ButtonHandle button); void keystroke(int keycode); INLINE void set_pointer_in_window(int x, int y); diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.h b/panda/src/dxgsg8/wdxGraphicsPipe8.h index 3ff301baa8..9a0a13c24a 100644 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.h +++ b/panda/src/dxgsg8/wdxGraphicsPipe8.h @@ -101,6 +101,7 @@ public: private: static TypeHandle _type_handle; + friend class wdxGraphicsWindow8; }; diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx index e86d901a9e..1801ee1d58 100644 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx @@ -137,8 +137,8 @@ wdxGraphicsWindow8:: //////////////////////////////////////////////////////////////////// void wdxGraphicsWindow8:: make_gsg() { - wdxGraphicsPipe8 *pipe8; - DCAST_INTO_V(pipe8, _pipe); + wdxGraphicsPipe8 *dxpipe; + DCAST_INTO_V(dxpipe, _pipe); nassertv(_gsg == (GraphicsStateGuardian *)NULL); _dxgsg = new DXGraphicsStateGuardian8(this); @@ -164,10 +164,10 @@ make_gsg() { if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); _dxgsg->scrn.bIsDX81 = true; - pD3D8 = (*pipe8->_Direct3DCreate8)(D3D_SDK_VERSION_8_1); + pD3D8 = (*dxpipe->_Direct3DCreate8)(D3D_SDK_VERSION_8_1); } else { _dxgsg->scrn.bIsDX81 = false; - pD3D8 = (*pipe8->_Direct3DCreate8)(D3D_SDK_VERSION_8_0); + pD3D8 = (*dxpipe->_Direct3DCreate8)(D3D_SDK_VERSION_8_0); } if (pD3D8 == NULL) { @@ -703,8 +703,8 @@ choose_adapter(LPDIRECT3D8 pD3D8) { //////////////////////////////////////////////////////////////////// bool wdxGraphicsWindow8:: search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { - wdxGraphicsPipe8 *pipe8; - DCAST_INTO_R(pipe8, _pipe, false); + wdxGraphicsPipe8 *dxpipe; + DCAST_INTO_R(dxpipe, _pipe, false); DWORD dwRenderWidth = get_properties().get_x_size(); DWORD dwRenderHeight = get_properties().get_y_size(); @@ -763,20 +763,20 @@ search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info) { UINT IDnum; // simple linear search to match DX7 card info w/DX8 card ID - for (IDnum=0; IDnum < pipe8->_card_ids.size(); IDnum++) { + for (IDnum=0; IDnum < dxpipe->_card_ids.size(); IDnum++) { // wdxdisplay8_cat.info() - // << "comparing '" << pipe8->_card_ids[IDnum].Driver + // << "comparing '" << dxpipe->_card_ids[IDnum].Driver // << "' to '" << _dxgsg->scrn.DXDeviceID.Driver << "'\n"; - if (//(stricmp(pipe8->_card_ids[IDnum].szDriver,device_info->szDriver)==0) && - (device_info->VendorID==pipe8->_card_ids[IDnum].VendorID) && - (device_info->DeviceID==pipe8->_card_ids[IDnum].DeviceID) && - (device_info->hMon==pipe8->_card_ids[IDnum].hMon)) + if (//(stricmp(dxpipe->_card_ids[IDnum].szDriver,device_info->szDriver)==0) && + (device_info->VendorID==dxpipe->_card_ids[IDnum].VendorID) && + (device_info->DeviceID==dxpipe->_card_ids[IDnum].DeviceID) && + (device_info->hMon==dxpipe->_card_ids[IDnum].hMon)) break; } - if (IDnum < pipe8->_card_ids.size()) { - _dxgsg->scrn.MaxAvailVidMem = pipe8->_card_ids[IDnum].MaxAvailVidMem; - _dxgsg->scrn.bIsLowVidMemCard = pipe8->_card_ids[IDnum].bIsLowVidMemCard; + if (IDnum < dxpipe->_card_ids.size()) { + _dxgsg->scrn.MaxAvailVidMem = dxpipe->_card_ids[IDnum].MaxAvailVidMem; + _dxgsg->scrn.bIsLowVidMemCard = dxpipe->_card_ids[IDnum].bIsLowVidMemCard; } else { wdxdisplay8_cat.error() << "Error: couldnt find a CardID match in DX7 info, assuming card is not a lowmem card\n"; diff --git a/panda/src/putil/buttonEvent.cxx b/panda/src/putil/buttonEvent.cxx index ca5a724f7d..7a77957776 100644 --- a/panda/src/putil/buttonEvent.cxx +++ b/panda/src/putil/buttonEvent.cxx @@ -30,6 +30,10 @@ output(ostream &out) const { out << "button " << _button << " down"; break; + case T_resume_down: + out << "button " << _button << " resume down"; + break; + case T_up: out << "button " << _button << " up"; break; diff --git a/panda/src/putil/buttonEvent.h b/panda/src/putil/buttonEvent.h index 09023b4319..482099be76 100644 --- a/panda/src/putil/buttonEvent.h +++ b/panda/src/putil/buttonEvent.h @@ -52,8 +52,21 @@ class EXPCL_PANDA ButtonEvent { public: enum Type { + // T_down and T_up represent a button changing state + // correspondingly. T_resume_down is a special event that is only + // thrown when focus is returned to a window and a button is + // detected as being held down at that point; it indicates that + // the button should be considered down now (if it wasn't + // already), but it didn't just get pressed down at this moment, + // it was depressed some time ago. It's mainly used for correct + // tracking of modifier keys like shift and control, and can be + // ignored for other keys. T_down, + T_resume_down, T_up, + + // T_keystroke is a special keystroke event, and is sent along + // with a Unicode keycode value, not a ButtonHandle. T_keystroke }; @@ -69,7 +82,8 @@ public: void output(ostream &out) const; - // _button will be filled in if type is T_down or T_up. + // _button will be filled in if type is T_down, T_resume_down, or + // T_up. ButtonHandle _button; // _keycode will be filled in if type is T_keystroke. It will be diff --git a/panda/src/tform/buttonThrower.cxx b/panda/src/tform/buttonThrower.cxx index 7576f5d9ff..8b27f0071a 100644 --- a/panda/src/tform/buttonThrower.cxx +++ b/panda/src/tform/buttonThrower.cxx @@ -369,6 +369,13 @@ do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) { // generations. _button_events->add_event(be); } + + } else if (be._type == ButtonEvent::T_resume_down) { + // Button resume down. The button was pressed at some earlier + // time, and the event was only just now detected. Don't + // throw an event now (since we already missed it), but do + // make sure our modifiers are up-to-date. + _mods.button_down(be._button); } else if (be._type == ButtonEvent::T_up) { // Button up. diff --git a/panda/src/windisplay/winGraphicsWindow.I b/panda/src/windisplay/winGraphicsWindow.I index 335db1421e..c56b970f92 100644 --- a/panda/src/windisplay/winGraphicsWindow.I +++ b/panda/src/windisplay/winGraphicsWindow.I @@ -51,6 +51,20 @@ handle_keypress(ButtonHandle key, int x, int y) { } } +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::handle_keyresume +// Access: Private +// Description: Indicates we detected a key was already down when the +// focus is restored to the window. Mainly useful for +// tracking the state of modifier keys. +//////////////////////////////////////////////////////////////////// +INLINE void WinGraphicsWindow:: +handle_keyresume(ButtonHandle key) { + if (key != ButtonHandle::none()) { + _input_devices[0].button_resume_down(key); + } +} + //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::handle_keyrelease // Access: Private @@ -58,7 +72,9 @@ handle_keypress(ButtonHandle key, int x, int y) { //////////////////////////////////////////////////////////////////// INLINE void WinGraphicsWindow:: handle_keyrelease(ButtonHandle key) { - _input_devices[0].button_up(key); + if (key != ButtonHandle::none()) { + _input_devices[0].button_up(key); + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 8b8ea6b1c7..3b782e1431 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -953,10 +953,6 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { case WM_SETFOCUS: { - POINT point; - GetCursorPos(&point); - ScreenToClient(hwnd, &point); - // When we lose focus, the app may miss key-up events for keys // that were formerly held down (and vice-versa). Therefore, // when focus is regained, compare the state of the keyboard to @@ -976,7 +972,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // This key has changed state. if ((new_keyboard_state[i] & 0x80) != 0) { // The key is now held down. - handle_keypress(lookup_key(i), point.x, point.y); + handle_keyresume(lookup_key(i)); } else { // The key is now released. handle_keyrelease(lookup_key(i)); diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 70ee9548c0..a25acb49a2 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -83,6 +83,7 @@ private: INLINE void handle_mouse_motion(int x, int y); INLINE void handle_mouse_exit(void); INLINE void handle_keypress(ButtonHandle key, int x, int y); + INLINE void handle_keyresume(ButtonHandle key); INLINE void handle_keyrelease(ButtonHandle key); ButtonHandle lookup_key(WPARAM wparam) const; INLINE int translate_mouse(int pos) const;