/** * PANDA 3D SOFTWARE * Copyright (c) Carnegie Mellon University. All rights reserved. * * All use of this software is subject to the terms of the revised BSD * license. You should have received a copy of this license along * with this source code in a file named "LICENSE." * * @file graphicsWindowInputDevice.cxx * @author drose * @date 2000-05-24 */ #include "graphicsWindowInputDevice.h" #include "graphicsWindow.h" #include "mouseButton.h" #include "keyboardButton.h" TypeHandle GraphicsWindowInputDevice::_type_handle; using std::string; /** * Defines a new InputDevice for the window. Most windows will have exactly * one InputDevice: a keyboard/mouse pair. Some may also add joystick data, * or additional mice or something. * * This private constructor is only used internally by the named constructors, * below. */ GraphicsWindowInputDevice:: GraphicsWindowInputDevice(GraphicsWindow *host, const string &name, bool pointer, bool keyboard) : InputDevice(name, DeviceClass::VIRTUAL) { if (pointer) { enable_feature(Feature::POINTER); add_pointer(PointerType::MOUSE, 0); } if (keyboard) { enable_feature(Feature::KEYBOARD); } } /** * This named constructor returns an input device that only has a pointing * device, no keyboard. */ PT(GraphicsWindowInputDevice) GraphicsWindowInputDevice:: pointer_only(GraphicsWindow *host, const string &name) { return new GraphicsWindowInputDevice(host, name, true, false); } /** * This named constructor returns an input device that only has a keyboard, no * pointing device. */ PT(GraphicsWindowInputDevice) GraphicsWindowInputDevice:: keyboard_only(GraphicsWindow *host, const string &name) { return new GraphicsWindowInputDevice(host, name, false, true); } /** * This named constructor returns an input device that has both a keyboard and * pointer. */ PT(GraphicsWindowInputDevice) GraphicsWindowInputDevice:: pointer_and_keyboard(GraphicsWindow *host, const string &name) { return new GraphicsWindowInputDevice(host, name, true, true); } /** * Records that the indicated button has been depressed. */ void GraphicsWindowInputDevice:: button_down(ButtonHandle button, double time) { LightMutexHolder holder(_lock); _button_events->add_event(ButtonEvent(button, ButtonEvent::T_down, time)); _buttons_held.insert(button); } /** * 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, double time) { LightMutexHolder holder(_lock); _button_events->add_event(ButtonEvent(button, ButtonEvent::T_resume_down, time)); _buttons_held.insert(button); } /** * Records that the indicated button has been released. */ void GraphicsWindowInputDevice:: button_up(ButtonHandle button, double time) { LightMutexHolder holder(_lock); _button_events->add_event(ButtonEvent(button, ButtonEvent::T_up, time)); _buttons_held.erase(button); } /** * Records that the indicated keystroke has been generated. */ void GraphicsWindowInputDevice:: keystroke(int keycode, double time) { LightMutexHolder holder(_lock); _button_events->add_event(ButtonEvent(keycode, time)); } /** * Records that the indicated candidate string has been highlighted. This is * used to implement IME support for typing in international languages, * especially Chinese/Japanese/Korean. */ void GraphicsWindowInputDevice:: candidate(const std::wstring &candidate_string, size_t highlight_start, size_t highlight_end, size_t cursor_pos) { LightMutexHolder holder(_lock); _button_events->add_event(ButtonEvent(candidate_string, highlight_start, highlight_end, cursor_pos)); } /** * This should be called when the window focus is lost, so that we may miss * upcoming button events (especially "up" events) for the next period of * time. It generates keyboard and mouse "up" events for those buttons that * we previously sent unpaired "down" events, so that the Panda application * will believe all buttons are now released. */ void GraphicsWindowInputDevice:: focus_lost(double time) { LightMutexHolder holder(_lock); ButtonsHeld::iterator bi; for (bi = _buttons_held.begin(); bi != _buttons_held.end(); ++bi) { _button_events->add_event(ButtonEvent(*bi, ButtonEvent::T_up, time)); } _buttons_held.clear(); } /** * Records that the indicated button has been depressed. */ void GraphicsWindowInputDevice:: raw_button_down(ButtonHandle button, double time) { LightMutexHolder holder(_lock); _button_events->add_event(ButtonEvent(button, ButtonEvent::T_raw_down, time)); } /** * Records that the indicated button has been released. */ void GraphicsWindowInputDevice:: raw_button_up(ButtonHandle button, double time) { LightMutexHolder holder(_lock); _button_events->add_event(ButtonEvent(button, ButtonEvent::T_raw_up, time)); } /** * To be called by a particular kind of GraphicsWindow to indicate that the * pointer is within the window, at the given pixel coordinates. */ void GraphicsWindowInputDevice:: set_pointer_in_window(double x, double y, double time) { LightMutexHolder holder(_lock); PointerData data = _pointers[0]; data._id = 0; data._type = PointerType::MOUSE; data._xpos = x; data._ypos = y; data._in_window = true; InputDevice::update_pointer(data, time); } /** * To be called by a particular kind of GraphicsWindow to indicate that the * pointer is no longer within the window. */ void GraphicsWindowInputDevice:: set_pointer_out_of_window(double time) { LightMutexHolder holder(_lock); if (_pointers.empty()) { return; } _pointers[0]._in_window = false; _pointers[0]._pressure = 0.0; if (_enable_pointer_events) { int seq = _event_sequence++; if (_pointer_events.is_null()) { _pointer_events = new PointerEventList(); } _pointer_events->add_event(_pointers[0]._in_window, _pointers[0]._xpos, _pointers[0]._ypos, seq, time); } }