Panda3D
graphicsWindow.cxx
1 // Filename: graphicsWindow.cxx
2 // Created by: mike (09Jan97)
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 #include "graphicsWindow.h"
16 #include "graphicsPipe.h"
17 #include "config_display.h"
18 #include "mouseButton.h"
19 #include "keyboardButton.h"
20 #include "lightMutexHolder.h"
21 #include "lightReMutexHolder.h"
22 #include "throw_event.h"
23 #include "string_utils.h"
24 
25 TypeHandle GraphicsWindow::_type_handle;
26 
27 ////////////////////////////////////////////////////////////////////
28 // Function: GraphicsWindow::Constructor
29 // Access: Protected
30 // Description: Normally, the GraphicsWindow constructor is not
31 // called directly; these are created instead via the
32 // GraphicsEngine::make_window() function.
33 ////////////////////////////////////////////////////////////////////
34 GraphicsWindow::
35 GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
36  const string &name,
37  const FrameBufferProperties &fb_prop,
38  const WindowProperties &win_prop,
39  int flags,
41  GraphicsOutput *host) :
42  GraphicsOutput(engine, pipe, name, fb_prop, win_prop, flags, gsg, host, true),
43  _input_lock("GraphicsWindow::_input_lock"),
44  _properties_lock("GraphicsWindow::_properties_lock")
45 {
46 #ifdef DO_MEMORY_USAGE
47  MemoryUsage::update_type(this, this);
48 #endif
49 
50  if (display_cat.is_debug()) {
51  display_cat.debug()
52  << "Creating new window " << get_name() << "\n";
53  }
54 
55  _properties.set_open(false);
56  _properties.set_undecorated(false);
57  _properties.set_fullscreen(false);
58  _properties.set_minimized(false);
59  _properties.set_cursor_hidden(false);
60 
62  request_properties(win_prop);
63 
64  _window_event = "window-event";
65  _got_expose_event = false;
66  _unexposed_draw = win_unexposed_draw;
67  set_pixel_zoom(pixel_zoom);
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: GraphicsWindow::Destructor
72 // Access: Published, Virtual
73 // Description:
74 ////////////////////////////////////////////////////////////////////
75 GraphicsWindow::
76 ~GraphicsWindow() {
77  // Clean up python event handlers.
78 #ifdef HAVE_PYTHON
79  PythonWinProcClasses::iterator iter;
80  for (iter = _python_window_proc_classes.begin();
81  iter != _python_window_proc_classes.end();
82  ++iter) {
83  delete *iter;
84  }
85 #endif
86 }
87 
88 ////////////////////////////////////////////////////////////////////
89 // Function: GraphicsWindow::get_properties
90 // Access: Published
91 // Description: Returns the current properties of the window.
92 ////////////////////////////////////////////////////////////////////
94 get_properties() const {
95  WindowProperties result;
96  {
97  LightReMutexHolder holder(_properties_lock);
98  result = _properties;
99  }
100  return result;
101 }
102 
103 ////////////////////////////////////////////////////////////////////
104 // Function: GraphicsWindow::get_requested_properties
105 // Access: Published
106 // Description: Returns the properties of the window that are
107 // currently requested. These properties will be
108 // applied to the window (if valid) at the next
109 // execution of process_events().
110 ////////////////////////////////////////////////////////////////////
113  WindowProperties result;
114  {
115  LightReMutexHolder holder(_properties_lock);
116  result = _requested_properties;
117  }
118  return result;
119 }
120 
121 ////////////////////////////////////////////////////////////////////
122 // Function: GraphicsWindow::clear_rejected_properties
123 // Access: Published
124 // Description: Empties the set of failed properties that will be
125 // returned by get_rejected_properties().
126 ////////////////////////////////////////////////////////////////////
127 void GraphicsWindow::
129  LightReMutexHolder holder(_properties_lock);
130  _rejected_properties.clear();
131 }
132 
133 ////////////////////////////////////////////////////////////////////
134 // Function: GraphicsWindow::get_rejected_properties
135 // Access: Published
136 // Description: Returns the set of properties that have recently been
137 // requested, but could not be applied to the window for
138 // some reason. This set of properties will remain
139 // unchanged until they are changed by a new failed
140 // request, or clear_rejected_properties() is called.
141 ////////////////////////////////////////////////////////////////////
144  WindowProperties result;
145  {
146  LightReMutexHolder holder(_properties_lock);
147  result = _rejected_properties;
148  }
149  return result;
150 }
151 
152 ////////////////////////////////////////////////////////////////////
153 // Function: GraphicsWindow::request_properties
154 // Access: Published
155 // Description: Requests a property change on the window. For
156 // example, use this method to request a window change
157 // size or minimize or something.
158 //
159 // The change is not made immediately; rather, the
160 // request is saved and will be applied the next time
161 // the window task is run (probably at the next frame).
162 ////////////////////////////////////////////////////////////////////
163 void GraphicsWindow::
164 request_properties(const WindowProperties &requested_properties) {
165  LightReMutexHolder holder(_properties_lock);
166  _requested_properties.add_properties(requested_properties);
167 
168  if (!_has_size && _requested_properties.has_size()) {
169  // If we just requested a particular size, anticipate that it will
170  // stick. This is helpful for the MultitexReducer, which needs to
171  // know the size of the textures that it will be working with,
172  // even if the texture hasn't been fully generated yet.
173  _size = _requested_properties.get_size();
174 
175  // Don't set _has_size yet, because we don't really know yet.
176  }
177 }
178 
179 ////////////////////////////////////////////////////////////////////
180 // Function: GraphicsWindow::is_active
181 // Access: Published, Virtual
182 // Description: Returns true if the window is ready to be rendered
183 // into, false otherwise.
184 ////////////////////////////////////////////////////////////////////
185 bool GraphicsWindow::
186 is_active() const {
187  // Make this smarter?
188  return GraphicsOutput::is_active() && _properties.get_open() && !_properties.get_minimized();
189 }
190 
191 ////////////////////////////////////////////////////////////////////
192 // Function: GraphicsWindow::set_window_event
193 // Access: Published
194 // Description: Changes the name of the event that is generated when
195 // this window is modified externally, e.g. to be
196 // resized or closed by the user.
197 //
198 // By default, all windows have the same window event
199 // unless they are explicitly changed. When the event
200 // is generated, it includes one parameter: the window
201 // itself.
202 ////////////////////////////////////////////////////////////////////
203 void GraphicsWindow::
204 set_window_event(const string &window_event) {
205  LightReMutexHolder holder(_properties_lock);
206  _window_event = window_event;
207 }
208 
209 ////////////////////////////////////////////////////////////////////
210 // Function: GraphicsWindow::get_window_event
211 // Access: Published
212 // Description: Returns the name of the event that is generated when
213 // this window is modified externally, e.g. to be
214 // resized or closed by the user. See set_window_event().
215 ////////////////////////////////////////////////////////////////////
216 string GraphicsWindow::
218  string result;
219  LightReMutexHolder holder(_properties_lock);
220  result = _window_event;
221  return result;
222 }
223 
224 ////////////////////////////////////////////////////////////////////
225 // Function: GraphicsWindow::set_close_request_event
226 // Access: Published
227 // Description: Sets the event that is triggered when the user
228 // requests to close the window, e.g. via alt-F4, or
229 // clicking on the close box.
230 //
231 // The default for each window is for this event to be
232 // the empty string, which means the window-close
233 // request is handled immediately by Panda (and the
234 // window will be closed without the app getting a
235 // chance to intervene). If you set this to a nonempty
236 // string, then the window is not closed, but instead
237 // the event is thrown. It is then up to the app to
238 // respond appropriately, for instance by presenting an
239 // "are you sure?" dialog box, and eventually calling
240 // close_window() when the user is sure.
241 //
242 // It is considered poor form to set this string and
243 // then not handle the event. This can frustrate the
244 // user by making it difficult for him to cleanly shut
245 // down the application (and may force the user to
246 // hard-kill the app, or reboot the machine).
247 ////////////////////////////////////////////////////////////////////
248 void GraphicsWindow::
249 set_close_request_event(const string &close_request_event) {
250  LightReMutexHolder holder(_properties_lock);
251  _close_request_event = close_request_event;
252 }
253 
254 ////////////////////////////////////////////////////////////////////
255 // Function: GraphicsWindow::get_close_request_event
256 // Access: Published
257 // Description: Returns the name of the event set via
258 // set_close_request_event(). If this string is
259 // nonempty, then when the user requests to close
260 // window, this event will be generated instead. See
261 // set_close_request_event().
262 ////////////////////////////////////////////////////////////////////
263 string GraphicsWindow::
265  string result;
266  LightReMutexHolder holder(_properties_lock);
267  result = _close_request_event;
268  return result;
269 }
270 
271 ////////////////////////////////////////////////////////////////////
272 // Function: GraphicsWindow::get_num_input_devices
273 // Access: Published
274 // Description: Returns the number of separate input devices
275 // associated with the window. Typically, a window will
276 // have exactly one input device: the keyboard/mouse
277 // pair. However, some windows may have no input
278 // devices, and others may add additional devices, for
279 // instance for a joystick.
280 ////////////////////////////////////////////////////////////////////
283  int result;
284  {
285  LightMutexHolder holder(_input_lock);
286  result = _input_devices.size();
287  }
288  return result;
289 }
290 
291 ////////////////////////////////////////////////////////////////////
292 // Function: GraphicsWindow::get_input_device_name
293 // Access: Published
294 // Description: Returns the name of the nth input device.
295 ////////////////////////////////////////////////////////////////////
296 string GraphicsWindow::
297 get_input_device_name(int device) const {
298  string result;
299  {
300  LightMutexHolder holder(_input_lock);
301  nassertr(device >= 0 && device < (int)_input_devices.size(), "");
302  result = _input_devices[device].get_name();
303  }
304  return result;
305 }
306 
307 ////////////////////////////////////////////////////////////////////
308 // Function: GraphicsWindow::has_pointer
309 // Access: Published
310 // Description: Returns true if the nth input device has a
311 // screen-space pointer (for instance, a mouse), false
312 // otherwise.
313 ////////////////////////////////////////////////////////////////////
314 bool GraphicsWindow::
315 has_pointer(int device) const {
316  bool result;
317  {
318  LightMutexHolder holder(_input_lock);
319  nassertr(device >= 0 && device < (int)_input_devices.size(), false);
320  result = _input_devices[device].has_pointer();
321  }
322  return result;
323 }
324 
325 ////////////////////////////////////////////////////////////////////
326 // Function: GraphicsWindow::has_keyboard
327 // Access: Published
328 // Description: Returns true if the nth input device has a keyboard,
329 // false otherwise.
330 ////////////////////////////////////////////////////////////////////
331 bool GraphicsWindow::
332 has_keyboard(int device) const {
333  bool result;
334  {
335  LightMutexHolder holder(_input_lock);
336  nassertr(device >= 0 && device < (int)_input_devices.size(), false);
337  result = _input_devices[device].has_keyboard();
338  }
339  return result;
340 }
341 
342 ////////////////////////////////////////////////////////////////////
343 // Function: x11GraphicsWindow::get_keyboard_map
344 // Access: Published, Virtual
345 // Description: Returns a ButtonMap containing the association
346 // between raw buttons and virtual buttons.
347 ////////////////////////////////////////////////////////////////////
350  return NULL;
351 }
352 
353 ////////////////////////////////////////////////////////////////////
354 // Function: GraphicsWindow::enable_pointer_events
355 // Access: Published
356 // Description: Turn on the generation of pointer events.
357 ////////////////////////////////////////////////////////////////////
358 void GraphicsWindow::
360  LightMutexHolder holder(_input_lock);
361  nassertv(device >= 0 && device < (int)_input_devices.size());
362  _input_devices[device].enable_pointer_events();
363 }
364 
365 ////////////////////////////////////////////////////////////////////
366 // Function: GraphicsWindow::disable_pointer_events
367 // Access: Published
368 // Description: Turn off the generation of pointer events.
369 ////////////////////////////////////////////////////////////////////
370 void GraphicsWindow::
372  LightMutexHolder holder(_input_lock);
373  nassertv(device >= 0 && device < (int)_input_devices.size());
374  _input_devices[device].disable_pointer_events();
375 }
376 
377 ////////////////////////////////////////////////////////////////////
378 // Function: GraphicsWindow::enable_pointer_mode
379 // Access: Published
380 // Description: See GraphicsWindowInputDevice::enable_pointer_mode
381 ////////////////////////////////////////////////////////////////////
382 void GraphicsWindow::
383 enable_pointer_mode(int device, double speed) {
384  LightMutexHolder holder(_input_lock);
385  nassertv(device >= 0 && device < (int)_input_devices.size());
386  _input_devices[device].enable_pointer_mode(speed);
387 }
388 
389 ////////////////////////////////////////////////////////////////////
390 // Function: GraphicsWindow::disable_pointer_events
391 // Access: Published
392 // Description: See GraphicsWindowInputDevice::disable_pointer_mode
393 ////////////////////////////////////////////////////////////////////
394 void GraphicsWindow::
395 disable_pointer_mode(int device) {
396  LightMutexHolder holder(_input_lock);
397  nassertv(device >= 0 && device < (int)_input_devices.size());
398  _input_devices[device].disable_pointer_mode();
399 }
400 
401 ////////////////////////////////////////////////////////////////////
402 // Function: GraphicsWindow::get_pointer
403 // Access: Published
404 // Description: Returns the MouseData associated with the nth
405 // input device's pointer. This is deprecated; use
406 // get_pointer_device().get_pointer() instead, or for
407 // raw mice, use the InputDeviceManager interface.
408 ////////////////////////////////////////////////////////////////////
410 get_pointer(int device) const {
411  MouseData result;
412  {
413  LightMutexHolder holder(_input_lock);
414  nassertr(device >= 0 && device < (int)_input_devices.size(), MouseData());
415  result = _input_devices[device].get_pointer();
416  }
417  return result;
418 }
419 
420 ////////////////////////////////////////////////////////////////////
421 // Function: GraphicsWindow::move_pointer
422 // Access: Published, Virtual
423 // Description: Forces the pointer to the indicated position within
424 // the window, if possible.
425 //
426 // Returns true if successful, false on failure. This
427 // may fail if the mouse is not currently within the
428 // window, or if the API doesn't support this operation.
429 ////////////////////////////////////////////////////////////////////
430 bool GraphicsWindow::
431 move_pointer(int, int, int) {
432  return false;
433 }
434 
435 ////////////////////////////////////////////////////////////////////
436 // Function: GraphicsWindow::close_ime
437 // Access: Published, Virtual
438 // Description: Forces the ime window to close if any
439 //
440 ////////////////////////////////////////////////////////////////////
441 void GraphicsWindow::
443  return;
444 }
445 
446 ////////////////////////////////////////////////////////////////////
447 // Function: GraphicsWindow::has_button_event
448 // Access: Public
449 // Description: Returns true if the indicated device has a pending
450 // button event (a mouse button or keyboard button
451 // down/up), false otherwise. If this returns true, the
452 // particular event may be extracted via
453 // get_button_event().
454 ////////////////////////////////////////////////////////////////////
455 bool GraphicsWindow::
456 has_button_event(int device) const {
457  bool result;
458  {
459  LightMutexHolder holder(_input_lock);
460  nassertr(device >= 0 && device < (int)_input_devices.size(), false);
461  result = _input_devices[device].has_button_event();
462  }
463  return result;
464 }
465 
466 ////////////////////////////////////////////////////////////////////
467 // Function: GraphicsWindow::get_button_event
468 // Access: Public
469 // Description: Assuming a previous call to has_button_event()
470 // returned true, this returns the pending button event.
471 ////////////////////////////////////////////////////////////////////
473 get_button_event(int device) {
474  ButtonEvent result;
475  {
476  LightMutexHolder holder(_input_lock);
477  nassertr(device >= 0 && device < (int)_input_devices.size(), ButtonEvent());
478  nassertr(_input_devices[device].has_button_event(), ButtonEvent());
479  result = _input_devices[device].get_button_event();
480  }
481  return result;
482 }
483 
484 ////////////////////////////////////////////////////////////////////
485 // Function: GraphicsWindow::has_pointer_event
486 // Access: Public
487 // Description: Returns true if the indicated device has a pending
488 // pointer event (a mouse movement). If this returns
489 // true, the particular event may be extracted via
490 // get_pointer_events().
491 ////////////////////////////////////////////////////////////////////
492 bool GraphicsWindow::
493 has_pointer_event(int device) const {
494  bool result;
495  {
496  LightMutexHolder holder(_input_lock);
497  nassertr(device >= 0 && device < (int)_input_devices.size(), false);
498  result = _input_devices[device].has_pointer_event();
499  }
500  return result;
501 }
502 
503 ////////////////////////////////////////////////////////////////////
504 // Function: GraphicsWindow::get_pointer_events
505 // Access: Public
506 // Description: Assuming a previous call to has_pointer_event()
507 // returned true, this returns the pending pointer event list.
508 ////////////////////////////////////////////////////////////////////
509 PT(PointerEventList) GraphicsWindow::
510 get_pointer_events(int device) {
511  PT(PointerEventList) result;
512  {
513  LightMutexHolder holder(_input_lock);
514  nassertr(device >= 0 && device < (int)_input_devices.size(), NULL);
515  nassertr(_input_devices[device].has_pointer_event(), NULL);
516  result = _input_devices[device].get_pointer_events();
517  }
518  return result;
519 }
520 
521 ////////////////////////////////////////////////////////////////////
522 // Function: GraphicsWindow::verify_window_sizes
523 // Access: Public, Virtual
524 // Description: Determines which of the indicated window sizes are
525 // supported by available hardware (e.g. in fullscreen
526 // mode).
527 //
528 // On entry, dimen is an array containing contiguous x,y
529 // pairs specifying possible display sizes; it is
530 // numsizes*2 words long. The function will zero out
531 // any invalid x,y size pairs. The return value is the
532 // number of valid sizes that were found.
533 //
534 // Note this doesn't guarantee a resize attempt will
535 // work; you still need to check the return value.
536 //
537 // (It might be better to implement some sort of query
538 // interface that returns an array of supported sizes,
539 // but this way is somewhat simpler and will do the job
540 // on most cards, assuming they handle the std sizes the
541 // app knows about.)
542 ////////////////////////////////////////////////////////////////////
544 verify_window_sizes(int numsizes, int *dimen) {
545  return numsizes;
546 }
547 
548 ////////////////////////////////////////////////////////////////////
549 // Function: GraphicsWindow::request_open
550 // Access: Public, Virtual
551 // Description: This is called by the GraphicsEngine to request that
552 // the window (or whatever) open itself or, in general,
553 // make itself valid, at the next call to
554 // process_events().
555 ////////////////////////////////////////////////////////////////////
556 void GraphicsWindow::
558  WindowProperties open_properties;
559  open_properties.set_open(true);
560  request_properties(open_properties);
561 }
562 
563 ////////////////////////////////////////////////////////////////////
564 // Function: GraphicsWindow::request_close
565 // Access: Public, Virtual
566 // Description: This is called by the GraphicsEngine to request that
567 // the window (or whatever) close itself or, in general,
568 // make itself invalid, at the next call to
569 // process_events(). By that time we promise the gsg
570 // pointer will be cleared.
571 ////////////////////////////////////////////////////////////////////
572 void GraphicsWindow::
574  WindowProperties close_properties;
575  close_properties.set_open(false);
576  request_properties(close_properties);
577 }
578 
579 ////////////////////////////////////////////////////////////////////
580 // Function: GraphicsWindow::set_close_now
581 // Access: Public, Virtual
582 // Description: This is called by the GraphicsEngine to insist that
583 // the window be closed immediately. This is only
584 // called from the window thread.
585 ////////////////////////////////////////////////////////////////////
586 void GraphicsWindow::
588  WindowProperties close_properties;
589  close_properties.set_open(false);
590  set_properties_now(close_properties);
591 }
592 
593 ////////////////////////////////////////////////////////////////////
594 // Function: GraphicsWindow::process_events
595 // Access: Public, Virtual
596 // Description: Do whatever processing is necessary to ensure that
597 // the window responds to user events. Also, honor any
598 // requests recently made via request_properties().
599 //
600 // This function is called only within the window
601 // thread.
602 ////////////////////////////////////////////////////////////////////
603 void GraphicsWindow::
605  if (_requested_properties.is_any_specified()) {
606  // We don't bother to grab the mutex until after we have already
607  // checked whether any properties have been specified. This is
608  // technically sloppy, but it ought to be o.k. since it's just a
609  // bitmask after all.
610  WindowProperties properties;
611  {
612  LightReMutexHolder holder(_properties_lock);
613  properties = _requested_properties;
614  _requested_properties.clear();
615 
616  set_properties_now(properties);
617  if (properties.is_any_specified()) {
618  display_cat.info()
619  << "Unable to set window properties: " << properties << "\n";
620  _rejected_properties.add_properties(properties);
621  }
622  }
623  }
624 }
625 
626 ////////////////////////////////////////////////////////////////////
627 // Function: GraphicsWindow::set_properties_now
628 // Access: Public, Virtual
629 // Description: Applies the requested set of properties to the
630 // window, if possible, for instance to request a change
631 // in size or minimization status.
632 //
633 // The window properties are applied immediately, rather
634 // than waiting until the next frame. This implies that
635 // this method may *only* be called from within the
636 // window thread.
637 //
638 // The properties that have been applied are cleared
639 // from the structure by this function; so on return,
640 // whatever remains in the properties structure are
641 // those that were unchanged for some reason (probably
642 // because the underlying interface does not support
643 // changing that property on an open window).
644 ////////////////////////////////////////////////////////////////////
645 void GraphicsWindow::
647  if (properties.has_open() &&
648  properties.get_open() != _properties.get_open()) {
649  // Open or close a new window. In this case we can get all of the
650  // properties at once.
651 
652  _properties.add_properties(properties);
653  properties.clear();
654 
655  if (_properties.get_open()) {
656  if (open_window()) {
657  // When the window is first opened, force its size to be
658  // broadcast to its display regions.
659  _is_valid = true;
660  set_size_and_recalc(_properties.get_x_size(),
661  _properties.get_y_size());
662  } else {
663  // Since we can't even open the window, tag the
664  // _rejected_properties with all of the window properties that
665  // failed.
666  _rejected_properties.add_properties(_properties);
667 
668  // And mark the window closed.
669  _properties.set_open(false);
670  _is_valid = false;
671  }
672 
673  } else {
674  // We used to resist closing a window before its GSG has been
675  // released. Now it seems we never release a GSG, so go ahead
676  // and close the window.
677  close_window();
678  _is_valid = false;
679  }
680  return;
681  }
682 
683  if (!_properties.get_open()) {
684  // The window is not currently open; we can set properties at
685  // will.
686  _properties.add_properties(properties);
687  properties.clear();
688  return;
689  }
690 
691  properties.clear_open();
692 
693  // The window is already open; we are limited to what we can change
694  // on the fly.
695 
696  if (properties.has_size() || properties.has_origin()) {
697  // Consider changing the window's size and/or position.
698  WindowProperties reshape_props;
699  if (properties.has_size()) {
700  reshape_props.set_size(properties.get_x_size(), properties.get_y_size());
701  } else {
702  reshape_props.set_size(_properties.get_x_size(), _properties.get_y_size());
703  }
704 
705  if (properties.has_origin() && !is_fullscreen()) {
706  reshape_props.set_origin(properties.get_x_origin(), properties.get_y_origin());
707  } else if (_properties.has_origin()) {
708  reshape_props.set_origin(_properties.get_x_origin(), _properties.get_y_origin());
709  }
710 
711  bool has_origin = reshape_props.has_origin();
712  int x_origin = 0, y_origin = 0;
713  if (has_origin) {
714  x_origin = reshape_props.get_x_origin();
715  y_origin = reshape_props.get_y_origin();
716  }
717 
718  if (reshape_props.get_x_size() != _properties.get_x_size() ||
719  reshape_props.get_y_size() != _properties.get_y_size() ||
720  (has_origin && (x_origin != _properties.get_x_origin() ||
721  y_origin != _properties.get_y_origin()))) {
722  if (do_reshape_request(x_origin, y_origin, has_origin,
723  reshape_props.get_x_size(),
724  reshape_props.get_y_size())) {
725  properties.clear_size();
726  properties.clear_origin();
727  }
728  } else {
729  properties.clear_size();
730  properties.clear_origin();
731  }
732  }
733 
734  if (properties.has_fullscreen() &&
735  properties.get_fullscreen() == _properties.get_fullscreen()) {
736  // Fullscreen property specified, but unchanged.
737  properties.clear_fullscreen();
738  }
739  if (properties.has_mouse_mode() &&
740  properties.get_mouse_mode() == _properties.get_mouse_mode()) {
741  // Mouse mode specified, but unchanged.
742  properties.clear_mouse_mode();
743  }
744 }
745 
746 ////////////////////////////////////////////////////////////////////
747 // Function: GraphicsWindow::close_window
748 // Access: Protected, Virtual
749 // Description: Closes the window right now. Called from the window
750 // thread.
751 ////////////////////////////////////////////////////////////////////
752 void GraphicsWindow::
753 close_window() {
754  display_cat.info()
755  << "Closing " << get_type() << "\n";
756 
757  // Tell our parent window (if any) that we're no longer its child.
758  if (_window_handle != (WindowHandle *)NULL &&
759  _parent_window_handle != (WindowHandle *)NULL) {
760  _parent_window_handle->detach_child(_window_handle);
761  }
762 
763  _window_handle = NULL;
764  _parent_window_handle = NULL;
765  _is_valid = false;
766 }
767 
768 ////////////////////////////////////////////////////////////////////
769 // Function: GraphicsWindow::open_window
770 // Access: Protected, Virtual
771 // Description: Opens the window right now. Called from the window
772 // thread. Returns true if the window is successfully
773 // opened, or false if there was a problem.
774 ////////////////////////////////////////////////////////////////////
775 bool GraphicsWindow::
776 open_window() {
777  return false;
778 }
779 
780 ////////////////////////////////////////////////////////////////////
781 // Function: GraphicsWindow::reset_window
782 // Access: Protected, Virtual
783 // Description: resets the window framebuffer from its derived
784 // children. Does nothing here.
785 ////////////////////////////////////////////////////////////////////
786 void GraphicsWindow::
787 reset_window(bool swapchain) {
788  display_cat.info()
789  << "Resetting " << get_type() << "\n";
790 }
791 
792 ////////////////////////////////////////////////////////////////////
793 // Function: GraphicsWindow::do_reshape_request
794 // Access: Protected, Virtual
795 // Description: Called from the window thread in response to a request
796 // from within the code (via request_properties()) to
797 // change the size and/or position of the window.
798 // Returns true if the window is successfully changed,
799 // or false if there was a problem.
800 ////////////////////////////////////////////////////////////////////
801 bool GraphicsWindow::
802 do_reshape_request(int x_origin, int y_origin, bool has_origin,
803  int x_size, int y_size) {
804  return false;
805 }
806 
807 ////////////////////////////////////////////////////////////////////
808 // Function: GraphicsWindow::system_changed_properties
809 // Access: Protected
810 // Description: Should be called (from within the window thread) when
811 // process_events() detects an external change in some
812 // important window property; for instance, when the
813 // user resizes the window.
814 ////////////////////////////////////////////////////////////////////
815 void GraphicsWindow::
816 system_changed_properties(const WindowProperties &properties) {
817  if (display_cat.is_debug()) {
818  display_cat.debug()
819  << "system_changed_properties(" << properties << ")\n";
820  }
821 
822  LightReMutexHolder holder(_properties_lock);
823 
824  if (properties.has_size()) {
825  system_changed_size(properties.get_x_size(), properties.get_y_size());
826  }
827 
828  WindowProperties old_properties = _properties;
829  _properties.add_properties(properties);
830  if (_properties != old_properties) {
831  throw_event(_window_event, this);
832  }
833 }
834 
835 ////////////////////////////////////////////////////////////////////
836 // Function: GraphicsWindow::system_changed_size
837 // Access: Protected
838 // Description: An internal function to update all the DisplayRegions
839 // with the new size of the window. This should always
840 // be called before changing the _size members of the
841 // _properties structure.
842 ////////////////////////////////////////////////////////////////////
843 void GraphicsWindow::
844 system_changed_size(int x_size, int y_size) {
845  if (display_cat.is_debug()) {
846  display_cat.debug()
847  << "system_changed_size(" << x_size << ", " << y_size << ")\n";
848  }
849 
850  if (!_properties.has_size() || (x_size != _properties.get_x_size() ||
851  y_size != _properties.get_y_size())) {
852  set_size_and_recalc(x_size, y_size);
853  }
854 }
855 
856 ////////////////////////////////////////////////////////////////////
857 // Function: GraphicsWindow::add_input_device
858 // Access: Protected
859 // Description: Adds a GraphicsWindowInputDevice to the vector.
860 // Returns the index of the new device.
861 ////////////////////////////////////////////////////////////////////
862 int GraphicsWindow::
863 add_input_device(const GraphicsWindowInputDevice &device) {
864  LightMutexHolder holder(_input_lock);
865  int index = (int)_input_devices.size();
866  _input_devices.push_back(device);
867  _input_devices.back().set_device_index(index);
868  return index;
869 }
870 
871 ////////////////////////////////////////////////////////////////////
872 // Function: GraphicsWindow::mouse_mode_relative
873 // Access: Protected, Virtual
874 // Description: detaches mouse. Only mouse delta from now on.
875 //
876 ////////////////////////////////////////////////////////////////////
877 void GraphicsWindow::
878 mouse_mode_relative() {
879 }
880 
881 ////////////////////////////////////////////////////////////////////
882 // Function: GraphicsWindow::mouse_mode_absolute
883 // Access: Protected, Virtual
884 // Description: reattaches mouse to location
885 //
886 ////////////////////////////////////////////////////////////////////
887 void GraphicsWindow::
888 mouse_mode_absolute() {
889 
890 }
891 
892 ////////////////////////////////////////////////////////////////////
893 // Function: GraphicsWindow::is_touch_event
894 // Access: Published, Virtual
895 // Description: Returns whether the specified event msg is a touch message.
896 //
897 ////////////////////////////////////////////////////////////////////
898 bool GraphicsWindow::
900  return false;
901 }
902 
903 ////////////////////////////////////////////////////////////////////
904 // Function: GraphicsWindow::get_num_touches
905 // Access: Published, Virtual
906 // Description: Returns the current number of touches on this window.
907 //
908 ////////////////////////////////////////////////////////////////////
911  return 0;
912 }
913 
914 ////////////////////////////////////////////////////////////////////
915 // Function: GraphicsWindow::get_touch_info
916 // Access: Published, Virtual
917 // Description: Returns the TouchInfo object describing the specified touch.
918 //
919 ////////////////////////////////////////////////////////////////////
921 get_touch_info(int index){
922  return TouchInfo();
923 }
924 
925 ////////////////////////////////////////////////////////////////////
926 // Function: GraphicsWindow::supports_window_procs
927 // Access: Published, Virtual
928 // Description: Returns whether this window supports adding of Windows proc handlers.
929 //
930 ////////////////////////////////////////////////////////////////////
932  return false;
933 }
bool has_keyboard(int device) const
Returns true if the nth input device has a keyboard, false otherwise.
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
This specialization on CallbackData is passed when the callback is initiated from from an implementat...
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
MouseMode get_mouse_mode() const
See set_mouse_mode().
void set_size_and_recalc(int x, int y)
Changes the x_size and y_size, then recalculates structures that depend on size.
void clear()
Unsets all properties that have been specified so far, and resets the WindowProperties structure to i...
void set_cursor_hidden(bool cursor_hidden)
Specifies whether the mouse cursor should be visible.
virtual void close_ime()
Forces the ime window to close if any.
bool has_button_event(int device) const
Returns true if the indicated device has a pending button event (a mouse button or keyboard button do...
This object represents a window on the desktop, not necessarily a Panda window.
Definition: windowHandle.h:40
bool has_open() const
Returns true if set_open() has been specified.
bool has_pointer_event(int device) const
Returns true if the indicated device has a pending pointer event (a mouse movement).
virtual bool move_pointer(int device, int x, int y)
Forces the pointer to the indicated position within the window, if possible.
virtual int get_num_touches()
Returns the current number of touches on this window.
void disable_pointer_mode(int device)
See GraphicsWindowInputDevice::disable_pointer_mode.
void clear_origin()
Removes the origin specification from the properties.
MouseData get_pointer(int device) const
Returns the MouseData associated with the nth input device&#39;s pointer.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
bool get_minimized() const
Returns true if the window is minimized.
string get_input_device_name(int device) const
Returns the name of the nth input device.
void set_size(const LVector2i &size)
Specifies the requested size of the window, in pixels.
void set_window_event(const string &window_event)
Changes the name of the event that is generated when this window is modified externally, e.g.
bool has_origin() const
Returns true if the window origin has been specified, false otherwise.
virtual bool is_active() const
Returns true if the window is ready to be rendered into, false otherwise.
Records a set of pointer events that happened recently.
void set_fullscreen(bool fullscreen)
Specifies whether the window should be opened in fullscreen mode (true) or normal windowed mode (fals...
void request_properties(const WindowProperties &requested_properties)
Requests a property change on the window.
int get_y_origin() const
Returns the y coordinate of the window&#39;s top-left corner, not including decorations.
Records a button event of some kind.
Definition: buttonEvent.h:53
string get_close_request_event() const
Returns the name of the event set via set_close_request_event().
virtual void request_close()
This is called by the GraphicsEngine to request that the window (or whatever) close itself or...
const WindowProperties get_properties() const
Returns the current properties of the window.
string get_window_event() const
Returns the name of the event that is generated when this window is modified externally, e.g.
virtual bool is_active() const
Returns true if the window is ready to be rendered into, false otherwise.
bool has_fullscreen() const
Returns true if set_fullscreen() has been specified.
void set_undecorated(bool undecorated)
Specifies whether the window should be created with a visible title and border (false, the default) or not (true).
A container for the various kinds of properties we might ask to have on a graphics window before we o...
ButtonEvent get_button_event(int device)
Assuming a previous call to has_button_event() returned true, this returns the pending button event...
const WindowProperties get_requested_properties() const
Returns the properties of the window that are currently requested.
Stores information for a single touch event.
Definition: touchInfo.h:24
bool get_open() const
Returns true if the window is open.
bool get_fullscreen() const
Returns true if the window is in fullscreen mode.
void clear_mouse_mode()
Removes the mouse_mode specification from the properties.
static WindowProperties get_default()
Returns the "default" WindowProperties.
Similar to MutexHolder, but for a light mutex.
void clear_size()
Removes the size specification from the properties.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
virtual bool supports_window_procs() const
Returns whether this window supports adding of Windows proc handlers.
virtual int verify_window_sizes(int numsizes, int *dimen)
Determines which of the indicated window sizes are supported by available hardware (e...
void set_origin(const LPoint2i &origin)
Specifies the origin on the screen (in pixels, relative to the top-left corner) at which the window s...
void enable_pointer_mode(int device, double speed)
See GraphicsWindowInputDevice::enable_pointer_mode.
This is a structure representing a single input device that may be associated with a window...
void clear_open()
Removes the open specification from the properties.
const LVector2i & get_size() const
Returns size in pixels of the useful part of the window, not including decorations.
This is a base class for the various different classes that represent the result of a frame of render...
Similar to MutexHolder, but for a light reentrant mutex.
virtual TouchInfo get_touch_info(int index)
Returns the TouchInfo object describing the specified touch.
Holds the data that might be generated by a 2-d pointer input device, such as the mouse in the Graphi...
Definition: mouseData.h:28
void add_properties(const WindowProperties &other)
Sets any properties that are explicitly specified in other on this object.
virtual void set_pixel_zoom(PN_stdfloat pixel_zoom)
Sets the amount by which the pixels of the region are scaled internally when filling the image intera...
void enable_pointer_events(int device)
Turn on the generation of pointer events.
virtual void set_close_now()
This is called by the GraphicsEngine to insist that the window be closed immediately.
void set_minimized(bool minimized)
Specifies whether the window should be created minimized (true), or normal (false).
Encapsulates all the communication with a particular instance of a given rendering backend...
const string & get_name() const
Returns the name that was passed to the GraphicsOutput constructor.
void clear_rejected_properties()
Empties the set of failed properties that will be returned by get_rejected_properties().
virtual ButtonMap * get_keyboard_map() const
Returns a ButtonMap containing the association between raw buttons and virtual buttons.
This class is the main interface to controlling the render process.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
virtual bool is_touch_event(GraphicsWindowProcCallbackData *callbackData)
Returns whether the specified event msg is a touch message.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void disable_pointer_events(int device)
Turn off the generation of pointer events.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
bool has_size() const
Returns true if the window size has been specified, false otherwise.
int get_num_input_devices() const
Returns the number of separate input devices associated with the window.
bool is_fullscreen() const
Returns true if the window has been opened as a fullscreen window, false otherwise.
void set_open(bool open)
Specifies whether the window should be open.
int get_x_origin() const
Returns the x coordinate of the window&#39;s top-left corner, not including decorations.
This class represents a map containing all of the buttons of a (keyboard) device, though it can also ...
Definition: buttonMap.h:33
bool has_pointer(int device) const
Returns true if the nth input device has a screen-space pointer (for instance, a mouse), false otherwise.
void clear_fullscreen()
Removes the fullscreen specification from the properties.
virtual void request_open()
This is called by the GraphicsEngine to request that the window (or whatever) open itself or...
WindowProperties get_rejected_properties() const
Returns the set of properties that have recently been requested, but could not be applied to the wind...
void set_close_request_event(const string &close_request_event)
Sets the event that is triggered when the user requests to close the window, e.g. ...