Panda3D
graphicsWindowInputDevice.cxx
1 // Filename: graphicsWindowInputDevice.cxx
2 // Created by: drose (24May00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 
16 #include "graphicsWindowInputDevice.h"
17 #include "graphicsWindow.h"
18 #include "mouseButton.h"
19 #include "keyboardButton.h"
20 
21 #define EXPCL EXPCL_PANDA_DISPLAY
22 #define EXPTP EXPTP_PANDA_DISPLAY
23 #define TYPE GraphicsWindowInputDevice
24 #define NAME vector_GraphicsWindowInputDevice
25 
26 #include "vector_src.cxx"
27 
28 // Tell GCC that we'll take care of the instantiation explicitly here.
29 #ifdef __GNUC__
30 #pragma implementation
31 #endif
32 
33 ////////////////////////////////////////////////////////////////////
34 // Function: GraphicsWindowInputDevice::Constructor
35 // Access: Private
36 // Description: Defines a new InputDevice for the window. Most
37 // windows will have exactly one InputDevice: a
38 // keyboard/mouse pair. Some may also add joystick
39 // data, or additional mice or something.
40 //
41 // This private constructor is only used internally by
42 // the named constructors, below.
43 ////////////////////////////////////////////////////////////////////
44 GraphicsWindowInputDevice::
45 GraphicsWindowInputDevice(GraphicsWindow *host, const string &name, int flags) :
46  _host(host),
47  _name(name),
48  _flags(flags),
49  _device_index(0),
50  _event_sequence(0),
51  _pointer_mode_enable(false),
52  _pointer_speed(1.0),
53  _enable_pointer_events(false)
54 {
55 }
56 
57 ////////////////////////////////////////////////////////////////////
58 // Function: GraphicsWindowInputDevice::pointer_only
59 // Access: Public
60 // Description: This named constructor returns an input device that
61 // only has a pointing device, no keyboard.
62 ////////////////////////////////////////////////////////////////////
64 pointer_only(GraphicsWindow *host, const string &name) {
65  return GraphicsWindowInputDevice(host, name, IDF_has_pointer);
66 }
67 
68 ////////////////////////////////////////////////////////////////////
69 // Function: GraphicsWindowInputDevice::keyboard_only
70 // Access: Public
71 // Description: This named constructor returns an input device that
72 // only has a keyboard, no pointing device.
73 ////////////////////////////////////////////////////////////////////
75 keyboard_only(GraphicsWindow *host, const string &name) {
76  return GraphicsWindowInputDevice(host, name, IDF_has_keyboard);
77 }
78 
79 ////////////////////////////////////////////////////////////////////
80 // Function: GraphicsWindowInputDevice::pointer_and_keyboard
81 // Access: Public
82 // Description: This named constructor returns an input device that
83 // has both a keyboard and pointer.
84 ////////////////////////////////////////////////////////////////////
86 pointer_and_keyboard(GraphicsWindow *host, const string &name) {
87  return
88  GraphicsWindowInputDevice(host, name, IDF_has_pointer | IDF_has_keyboard);
89 }
90 
91 ////////////////////////////////////////////////////////////////////
92 // Function: GraphicsWindowInputDevice::Copy Constructor
93 // Access: Public
94 // Description:
95 ////////////////////////////////////////////////////////////////////
96 GraphicsWindowInputDevice::
97 GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
98 {
99  *this = copy;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: GraphicsWindowInputDevice::Copy Assignment Operator
104 // Access: Public
105 // Description:
106 ////////////////////////////////////////////////////////////////////
107 void GraphicsWindowInputDevice::
108 operator = (const GraphicsWindowInputDevice &copy)
109 {
110  LightMutexHolder holder(_lock);
111  LightMutexHolder holder1(copy._lock);
112  _host = copy._host;
113  _name = copy._name;
114  _flags = copy._flags;
115  _device_index = copy._device_index;
116  _event_sequence = copy._event_sequence;
117  _pointer_mode_enable = copy._pointer_mode_enable;
118  _pointer_speed = copy._pointer_speed;
119  _enable_pointer_events = copy._enable_pointer_events;
120  _mouse_data = copy._mouse_data;
121  _true_mouse_data = copy._true_mouse_data;
122  _button_events = copy._button_events;
123  _pointer_events = copy._pointer_events;
124 }
125 
126 ////////////////////////////////////////////////////////////////////
127 // Function: GraphicsWindowInputDevice::Destructor
128 // Access: Public
129 // Description:
130 ////////////////////////////////////////////////////////////////////
131 GraphicsWindowInputDevice::
132 ~GraphicsWindowInputDevice() {
133 }
134 
135 ////////////////////////////////////////////////////////////////////
136 // Function: GraphicsWindowInputDevice::has_button_event
137 // Access: Public
138 // Description: Returns true if this device has a pending button
139 // event (a mouse button or keyboard button down/up),
140 // false otherwise. If this returns true, the
141 // particular event may be extracted via
142 // get_button_event().
143 ////////////////////////////////////////////////////////////////////
146  LightMutexHolder holder(_lock);
147  return !_button_events.empty();
148 }
149 
150 ////////////////////////////////////////////////////////////////////
151 // Function: GraphicsWindowInputDevice::get_button_event
152 // Access: Public
153 // Description: Assuming a previous call to has_button_event()
154 // returned true, this returns the pending button event.
155 ////////////////////////////////////////////////////////////////////
158  LightMutexHolder holder(_lock);
159  ButtonEvent be = _button_events.front();
160  _button_events.pop_front();
161  return be;
162 }
163 
164 ////////////////////////////////////////////////////////////////////
165 // Function: GraphicsWindowInputDevice::has_pointer_event
166 // Access: Public
167 // Description: Returns true if this device has a pending pointer
168 // event (a mouse movement), or false otherwise. If
169 // this returns true, the particular event may be
170 // extracted via get_pointer_event().
171 ////////////////////////////////////////////////////////////////////
174  LightMutexHolder holder(_lock);
175  return (_pointer_events != 0);
176 }
177 
178 ////////////////////////////////////////////////////////////////////
179 // Function: GraphicsWindowInputDevice::get_pointer_events
180 // Access: Public
181 // Description: Returns a PointerEventList containing all the recent
182 // pointer events.
183 ////////////////////////////////////////////////////////////////////
184 PT(PointerEventList) GraphicsWindowInputDevice::
185 get_pointer_events() {
186  LightMutexHolder holder(_lock);
187  PT(PointerEventList) result = _pointer_events;
188  _pointer_events = 0;
189  return result;
190 }
191 
192 ////////////////////////////////////////////////////////////////////
193 // Function: GraphicsWindowInputDevice::enable_pointer_mode
194 // Access: Public
195 // Description: There are two modes: raw mode, and pointer mode.
196 // In pointer mode, the mouse stops when it reaches the
197 // edges of the window. In raw mode, the mouse ignores
198 // the screen boundaries and can continue indefinitely,
199 // even into negative coordinates. In raw mode, each
200 // "blip" from the mouse hardware corresponds to a
201 // change of 1 unit in the mouse's (x,y) coordinate.
202 // In pointer mode, a variety of speed adjustment factors
203 // and concepts like "mouse acceleration" may be applied.
204 //
205 // Mouse zero represents the system mouse pointer. This
206 // is by definition a pointer, not a raw mouse. It is
207 // an error to try to enable or disable pointer mode on
208 // mouse zero.
209 ////////////////////////////////////////////////////////////////////
211 enable_pointer_mode(double speed) {
212  LightMutexHolder holder(_lock);
213  nassertv(_device_index != 0);
214  _pointer_mode_enable = true;
215  _pointer_speed = speed;
216  _mouse_data._xpos = _host->get_x_size() * 0.5;
217  _mouse_data._ypos = _host->get_y_size() * 0.5;
218  _mouse_data._in_window = true;
219 }
220 
221 ////////////////////////////////////////////////////////////////////
222 // Function: GraphicsWindowInputDevice::disable_pointer_mode
223 // Access: Public
224 // Description: see enable_pointer_mode.
225 ////////////////////////////////////////////////////////////////////
228  LightMutexHolder holder(_lock);
229  nassertv(_device_index != 0);
230  _pointer_mode_enable = false;
231  _pointer_speed = 1.0;
232  _mouse_data = _true_mouse_data;
233 }
234 
235 ////////////////////////////////////////////////////////////////////
236 // Function: GraphicsWindowInputDevice::set_pointer
237 // Access: Published
238 // Description: Records that a mouse movement has taken place.
239 ////////////////////////////////////////////////////////////////////
241 set_pointer(bool inwin, double x, double y, double time) {
242  LightMutexHolder holder(_lock);
243 
244  double delta_x = x - _true_mouse_data._xpos;
245  double delta_y = y - _true_mouse_data._ypos;
246  _true_mouse_data._in_window = inwin;
247  _true_mouse_data._xpos = x;
248  _true_mouse_data._ypos = y;
249 
250  if (_pointer_mode_enable) {
251  double pointer_x = _mouse_data._xpos;
252  double pointer_y = _mouse_data._ypos;
253  pointer_x += (delta_x * _pointer_speed);
254  pointer_y += (delta_y * _pointer_speed);
255  double xhi = _host->get_x_size();
256  double yhi = _host->get_y_size();
257  if (pointer_x < 0.0) pointer_x = 0.0;
258  if (pointer_y < 0.0) pointer_y = 0.0;
259  if (pointer_x > xhi) pointer_x = xhi;
260  if (pointer_y > yhi) pointer_y = yhi;
261  _mouse_data._in_window = true;
262  _mouse_data._xpos = pointer_x;
263  _mouse_data._ypos = pointer_y;
264  } else {
265  _mouse_data = _true_mouse_data;
266  }
267 
268  if (_enable_pointer_events) {
269  int seq = _event_sequence++;
270  if (_pointer_events == 0) {
271  _pointer_events = new PointerEventList();
272  }
273  _pointer_events->add_event(_mouse_data._in_window,
274  _mouse_data._xpos,
275  _mouse_data._ypos,
276  seq, time);
277  }
278 }
279 
280 ////////////////////////////////////////////////////////////////////
281 // Function: GraphicsWindowInputDevice::button_down
282 // Access: Published
283 // Description: Records that the indicated button has been depressed.
284 ////////////////////////////////////////////////////////////////////
286 button_down(ButtonHandle button, double time) {
287  LightMutexHolder holder(_lock);
288  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_down, time));
289  _buttons_held.insert(button);
290 }
291 
292 ////////////////////////////////////////////////////////////////////
293 // Function: GraphicsWindowInputDevice::button_resume_down
294 // Access: Published
295 // Description: Records that the indicated button was depressed
296 // earlier, and we only just detected the event after
297 // the fact. This is mainly useful for tracking the
298 // state of modifier keys.
299 ////////////////////////////////////////////////////////////////////
301 button_resume_down(ButtonHandle button, double time) {
302  LightMutexHolder holder(_lock);
303  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time));
304  _buttons_held.insert(button);
305 }
306 
307 ////////////////////////////////////////////////////////////////////
308 // Function: GraphicsWindowInputDevice::button_up
309 // Access: Published
310 // Description: Records that the indicated button has been released.
311 ////////////////////////////////////////////////////////////////////
313 button_up(ButtonHandle button, double time) {
314  LightMutexHolder holder(_lock);
315  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_up, time));
316  _buttons_held.erase(button);
317 }
318 
319 ////////////////////////////////////////////////////////////////////
320 // Function: GraphicsWindowInputDevice::keystroke
321 // Access: Published
322 // Description: Records that the indicated keystroke has been
323 // generated.
324 ////////////////////////////////////////////////////////////////////
326 keystroke(int keycode, double time) {
327  LightMutexHolder holder(_lock);
328  _button_events.push_back(ButtonEvent(keycode, time));
329 }
330 
331 ////////////////////////////////////////////////////////////////////
332 // Function: GraphicsWindowInputDevice::candidate
333 // Access: Published
334 // Description: Records that the indicated candidate string has been
335 // highlighted. This is used to implement IME support
336 // for typing in international languages, especially
337 // Chinese/Japanese/Korean.
338 ////////////////////////////////////////////////////////////////////
340 candidate(const wstring &candidate_string, size_t highlight_start,
341  size_t highlight_end, size_t cursor_pos) {
342  LightMutexHolder holder(_lock);
343  _button_events.push_back(ButtonEvent(candidate_string,
344  highlight_start, highlight_end,
345  cursor_pos));
346 }
347 
348 ////////////////////////////////////////////////////////////////////
349 // Function: GraphicsWindowInputDevice::focus_lost
350 // Access: Published
351 // Description: This should be called when the window focus is lost,
352 // so that we may miss upcoming button events
353 // (especially "up" events) for the next period of time.
354 // It generates keyboard and mouse "up" events for those
355 // buttons that we previously sent unpaired "down"
356 // events, so that the Panda application will believe
357 // all buttons are now released.
358 ////////////////////////////////////////////////////////////////////
360 focus_lost(double time) {
361  LightMutexHolder holder(_lock);
362  ButtonsHeld::iterator bi;
363  for (bi = _buttons_held.begin(); bi != _buttons_held.end(); ++bi) {
364  _button_events.push_back(ButtonEvent(*bi, ButtonEvent::T_up, time));
365  }
366  _buttons_held.clear();
367 }
368 
369 ////////////////////////////////////////////////////////////////////
370 // Function: GraphicsWindowInputDevice::raw_button_down
371 // Access: Published
372 // Description: Records that the indicated button has been depressed.
373 ////////////////////////////////////////////////////////////////////
375 raw_button_down(ButtonHandle button, double time) {
376  LightMutexHolder holder(_lock);
377  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_down, time));
378 }
379 
380 ////////////////////////////////////////////////////////////////////
381 // Function: GraphicsWindowInputDevice::raw_button_up
382 // Access: Published
383 // Description: Records that the indicated button has been released.
384 ////////////////////////////////////////////////////////////////////
386 raw_button_up(ButtonHandle button, double time) {
387  LightMutexHolder holder(_lock);
388  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_up, time));
389 }
void button_up(ButtonHandle button)
Records that the indicated button has been released.
static GraphicsWindowInputDevice pointer_and_keyboard(GraphicsWindow *host, const string &name)
This named constructor returns an input device that has both a keyboard and pointer.
void raw_button_up(ButtonHandle button)
Records that the indicated button has been released.
ButtonEvent get_button_event()
Assuming a previous call to has_button_event() returned true, this returns the pending button event...
static GraphicsWindowInputDevice keyboard_only(GraphicsWindow *host, const string &name)
This named constructor returns an input device that only has a keyboard, no pointing device...
void button_down(ButtonHandle button)
Records that the indicated button has been depressed.
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
void set_pointer(bool inwin, double x, double y, double time)
Records that a mouse movement has taken place.
void focus_lost()
This should be called when the window focus is lost, so that we may miss upcoming button events (espe...
Records a set of pointer events that happened recently.
Records a button event of some kind.
Definition: buttonEvent.h:53
void button_resume_down(ButtonHandle button)
Records that the indicated button was depressed earlier, and we only just detected the event after th...
void keystroke(int keycode)
Records that the indicated keystroke has been generated.
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:28
bool has_pointer_event() const
Returns true if this device has a pending pointer event (a mouse movement), or false otherwise...
void candidate(const wstring &candidate_string, size_t highlight_start, size_t highlight_end, size_t cursor_pos)
Records that the indicated candidate string has been highlighted.
bool has_button_event() const
Returns true if this device has a pending button event (a mouse button or keyboard button down/up)...
Similar to MutexHolder, but for a light mutex.
This is a structure representing a single input device that may be associated with a window...
void disable_pointer_mode()
see enable_pointer_mode.
void raw_button_down(ButtonHandle button)
Records that the indicated button has been depressed.
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
void enable_pointer_mode(double speed)
There are two modes: raw mode, and pointer mode.
static GraphicsWindowInputDevice pointer_only(GraphicsWindow *host, const string &name)
This named constructor returns an input device that only has a pointing device, no keyboard...