Panda3D
 All Classes Functions Variables Enumerations
subprocessWindow.cxx
1 // Filename: subprocessWindow.cxx
2 // Created by: drose (11Jul09)
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 "subprocessWindow.h"
16 
17 #ifdef SUPPORT_SUBPROCESS_WINDOW
18 
19 #include "graphicsEngine.h"
20 #include "config_display.h"
21 #include "nativeWindowHandle.h"
22 
23 TypeHandle SubprocessWindow::_type_handle;
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: SubprocessWindow::Constructor
27 // Access: Protected
28 // Description: Normally, the SubprocessWindow constructor is not
29 // called directly; these are created instead via the
30 // GraphicsEngine::make_window() function.
31 ////////////////////////////////////////////////////////////////////
32 SubprocessWindow::
33 SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
34  const string &name,
35  const FrameBufferProperties &fb_prop,
36  const WindowProperties &win_prop,
37  int flags,
39  GraphicsOutput *host) :
40  GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
41 {
44  _input_devices.push_back(device);
45 
46  // This will be an offscreen buffer that we use to render the actual
47  // contents.
48  _buffer = NULL;
49 
50  // Create a texture to receive the contents of the framebuffer from
51  // the offscreen buffer.
52  _texture = new Texture(name);
53 
54  _fd = -1;
55  _mmap_size = 0;
56  _filename = string();
57  _swbuffer = NULL;
58  _last_event_flags = 0;
59 }
60 
61 ////////////////////////////////////////////////////////////////////
62 // Function: SubprocessWindow::Destructor
63 // Access: Published, Virtual
64 // Description:
65 ////////////////////////////////////////////////////////////////////
66 SubprocessWindow::
67 ~SubprocessWindow() {
68  nassertv(_buffer == NULL);
69  nassertv(_swbuffer == NULL);
70 }
71 
72 ////////////////////////////////////////////////////////////////////
73 // Function: SubprocessWindow::process_events
74 // Access: Public, Virtual
75 // Description: Do whatever processing is necessary to ensure that
76 // the window responds to user events. Also, honor any
77 // requests recently made via request_properties().
78 //
79 // This function is called only within the window
80 // thread.
81 ////////////////////////////////////////////////////////////////////
82 void SubprocessWindow::
83 process_events() {
85 
86  if (_swbuffer != NULL) {
88  while (_swbuffer->get_event(swb_event)) {
89  // Deal with this event.
90  if (swb_event._flags & SubprocessWindowBuffer::EF_mouse_position) {
91  _input_devices[0].set_pointer_in_window(swb_event._x, swb_event._y);
92  } else if ((swb_event._flags & SubprocessWindowBuffer::EF_has_mouse) == 0) {
93  _input_devices[0].set_pointer_out_of_window();
94  }
95 
96  unsigned int diff = swb_event._flags ^ _last_event_flags;
97  _last_event_flags = swb_event._flags;
98 
99  if (diff & SubprocessWindowBuffer::EF_shift_held) {
100  transition_button(swb_event._flags & SubprocessWindowBuffer::EF_shift_held, KeyboardButton::shift());
101  }
102  if (diff & SubprocessWindowBuffer::EF_control_held) {
103  transition_button(swb_event._flags & SubprocessWindowBuffer::EF_control_held, KeyboardButton::control());
104  }
105  if (diff & SubprocessWindowBuffer::EF_alt_held) {
106  transition_button(swb_event._flags & SubprocessWindowBuffer::EF_alt_held, KeyboardButton::alt());
107  }
108  if (diff & SubprocessWindowBuffer::EF_meta_held) {
109  transition_button(swb_event._flags & SubprocessWindowBuffer::EF_meta_held, KeyboardButton::meta());
110  }
111 
112  ButtonHandle button = ButtonHandle::none();
113  if (swb_event._source == SubprocessWindowBuffer::ES_mouse) {
114  button = MouseButton::button(swb_event._code);
115 
116  } else if (swb_event._source == SubprocessWindowBuffer::ES_keyboard) {
117  int keycode;
118  button = translate_key(keycode, swb_event._code, swb_event._flags);
119  if (keycode != 0 && swb_event._type != SubprocessWindowBuffer::ET_button_up) {
120  _input_devices[0].keystroke(keycode);
121  }
122  }
123 
124  if (swb_event._type == SubprocessWindowBuffer::ET_button_up) {
125  _input_devices[0].button_up(button);
126  } else if (swb_event._type == SubprocessWindowBuffer::ET_button_down) {
127  _input_devices[0].button_down(button);
128  }
129  }
130  }
131 }
132 
133 ////////////////////////////////////////////////////////////////////
134 // Function: SubprocessWindow::begin_frame
135 // Access: Public, Virtual
136 // Description: This function will be called within the draw thread
137 // before beginning rendering for a given frame. It
138 // should do whatever setup is required, and return true
139 // if the frame should be rendered, or false if it
140 // should be skipped.
141 ////////////////////////////////////////////////////////////////////
142 bool SubprocessWindow::
143 begin_frame(FrameMode mode, Thread *current_thread) {
144  if (_swbuffer == NULL || _buffer == NULL) {
145  return false;
146  }
147 
148  bool result = _buffer->begin_frame(mode, current_thread);
149  return result;
150 }
151 
152 ////////////////////////////////////////////////////////////////////
153 // Function: SubprocessWindow::end_frame
154 // Access: Public, Virtual
155 // Description: This function will be called within the draw thread
156 // after rendering is completed for a given frame. It
157 // should do whatever finalization is required.
158 ////////////////////////////////////////////////////////////////////
159 void SubprocessWindow::
160 end_frame(FrameMode mode, Thread *current_thread) {
161  _buffer->end_frame(mode, current_thread);
162 
163  if (mode == FM_render) {
164  _flip_ready = true;
165  }
166 }
167 
168 ////////////////////////////////////////////////////////////////////
169 // Function: SubprocessWindow::begin_flip
170 // Access: Public, Virtual
171 // Description: This function will be called within the draw thread
172 // after end_frame() has been called on all windows, to
173 // initiate the exchange of the front and back buffers.
174 //
175 // This should instruct the window to prepare for the
176 // flip at the next video sync, but it should not wait.
177 //
178 // We have the two separate functions, begin_flip() and
179 // end_flip(), to make it easier to flip all of the
180 // windows at the same time.
181 ////////////////////////////////////////////////////////////////////
182 void SubprocessWindow::
183 begin_flip() {
184  nassertv(_buffer != (GraphicsBuffer *)NULL);
185  if (_swbuffer == NULL) {
186  return;
187  }
188 
189  RenderBuffer buffer(_gsg, DrawableRegion::get_renderbuffer_type(RTP_color));
190  buffer = _gsg->get_render_buffer(_buffer->get_draw_buffer_type(),
191  _buffer->get_fb_properties());
192 
193  bool copied =
194  _gsg->framebuffer_copy_to_ram(_texture, 0, -1,
195  _overlay_display_region, buffer);
196 
197  if (copied) {
198  CPTA_uchar image = _texture->get_ram_image();
199  size_t framebuffer_size = _swbuffer->get_framebuffer_size();
200  nassertv(image.size() == framebuffer_size);
201 
202  if (!_swbuffer->ready_for_write()) {
203  // We have to wait for the other end to remove the last frame we
204  // rendered. We only wait so long before we give up, so we
205  // don't completely starve the Python process just because the
206  // render window is offscreen or something.
207 
209  double start = clock->get_real_time();
210  while (!_swbuffer->ready_for_write()) {
212  double now = clock->get_real_time();
213  if (now - start > subprocess_window_max_wait) {
214  // Never mind.
215  return;
216  }
217  }
218  }
219 
220  // We're ready to go. Copy the image to our shared framebuffer.
221  void *target = _swbuffer->open_write_framebuffer();
222  memcpy(target, image.p(), framebuffer_size);
223  _swbuffer->close_write_framebuffer();
224  }
225 }
226 
227 ////////////////////////////////////////////////////////////////////
228 // Function: SubprocessWindow::set_properties_now
229 // Access: Public, Virtual
230 // Description: Applies the requested set of properties to the
231 // window, if possible, for instance to request a change
232 // in size or minimization status.
233 //
234 // The window properties are applied immediately, rather
235 // than waiting until the next frame. This implies that
236 // this method may *only* be called from within the
237 // window thread.
238 //
239 // The properties that have been applied are cleared
240 // from the structure by this function; so on return,
241 // whatever remains in the properties structure are
242 // those that were unchanged for some reason (probably
243 // because the underlying interface does not support
244 // changing that property on an open window).
245 ////////////////////////////////////////////////////////////////////
246 void SubprocessWindow::
247 set_properties_now(WindowProperties &properties) {
248  Filename filename;
249  WindowHandle *window_handle = properties.get_parent_window();
250  if (window_handle != NULL) {
251  WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
252  if (os_handle != NULL) {
253  if (os_handle->is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
254  NativeWindowHandle::SubprocessHandle *subprocess_handle = DCAST(NativeWindowHandle::SubprocessHandle, os_handle);
255  filename = subprocess_handle->get_filename();
256  }
257  }
258  }
259 
260  if (!filename.empty() && filename != _filename) {
261  // We're changing the subprocess buffer filename; that means we
262  // might as well completely close and re-open the window.
263  display_cat.info() << "Re-opening SubprocessWindow\n";
264  internal_close_window();
265 
266  _properties.add_properties(properties);
267  properties.clear();
268 
269  internal_open_window();
270  set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size());
271  throw_event(get_window_event(), this);
272  return;
273  }
274 
276  if (!properties.is_any_specified()) {
277  // The base class has already handled this case.
278  return;
279  }
280 
281  if (properties.has_parent_window()) {
282  // Redundant parent-window specification.
283  properties.clear_parent_window();
284  }
285 }
286 
287 ////////////////////////////////////////////////////////////////////
288 // Function: SubprocessWindow::close_window
289 // Access: Protected, Virtual
290 // Description: Closes the window right now. Called from the window
291 // thread.
292 ////////////////////////////////////////////////////////////////////
293 void SubprocessWindow::
294 close_window() {
295  internal_close_window();
296 
297  WindowProperties properties;
298  properties.set_open(false);
299  properties.set_foreground(false);
300  system_changed_properties(properties);
301 }
302 
303 ////////////////////////////////////////////////////////////////////
304 // Function: SubprocessWindow::open_window
305 // Access: Protected, Virtual
306 // Description: Opens the window right now. Called from the window
307 // thread. Returns true if the window is successfully
308 // opened, or false if there was a problem.
309 ////////////////////////////////////////////////////////////////////
310 bool SubprocessWindow::
311 open_window() {
312  if (!internal_open_window()) {
313  return false;
314  }
315 
316  WindowProperties properties;
317  properties.set_open(true);
318  properties.set_foreground(true);
319  system_changed_properties(properties);
320 
321  return true;
322 }
323 
324 ////////////////////////////////////////////////////////////////////
325 // Function: SubprocessWindow::internal_close_window
326 // Access: Private
327 // Description: Closes the "window" and resets the buffer, without
328 // changing the WindowProperties.
329 ////////////////////////////////////////////////////////////////////
330 void SubprocessWindow::
331 internal_close_window() {
332  if (_swbuffer != NULL) {
334  (_fd, _mmap_size, _filename.to_os_specific(), _swbuffer);
335  _fd = -1;
336  _filename = string();
337 
338  _swbuffer = NULL;
339  }
340 
341  if (_buffer != NULL) {
342  _buffer->request_close();
343  _buffer->process_events();
344  _engine->remove_window(_buffer);
345  _buffer = NULL;
346  }
347 
348  // Tell our parent window (if any) that we're no longer its child.
349  if (_window_handle != (WindowHandle *)NULL &&
350  _parent_window_handle != (WindowHandle *)NULL) {
351  _parent_window_handle->detach_child(_window_handle);
352  }
353 
354  _window_handle = NULL;
355  _parent_window_handle = NULL;
356  _is_valid = false;
357 }
358 
359 ////////////////////////////////////////////////////////////////////
360 // Function: SubprocessWindow::internal_open_window
361 // Access: Private
362 // Description: Opens the "window" and the associated offscreen
363 // buffer, without changing the WindowProperties.
364 ////////////////////////////////////////////////////////////////////
365 bool SubprocessWindow::
366 internal_open_window() {
367  nassertr(_buffer == NULL, false);
368 
369  // Create a buffer with the same properties as the window.
370  int flags = _creation_flags;
371  flags = ((flags & ~GraphicsPipe::BF_require_window) | GraphicsPipe::BF_refuse_window);
372  WindowProperties win_props = WindowProperties::size(_properties.get_x_size(), _properties.get_y_size());
373 
374  GraphicsOutput *buffer =
375  _engine->make_output(_pipe, _name, 0, _fb_properties, win_props,
376  flags, _gsg, _host);
377  if (buffer != NULL) {
378  _buffer = DCAST(GraphicsBuffer, buffer);
379  // However, the buffer is not itself intended to be rendered. We
380  // only render it indirectly, via callbacks in here.
381  _buffer->set_active(false);
382 
383  _buffer->request_open();
384  _buffer->process_events();
385 
386  _is_valid = _buffer->is_valid();
387  }
388 
389  if (!_is_valid) {
390  display_cat.error()
391  << "Failed to open SubprocessWindowBuffer's internal offscreen buffer.\n";
392  return false;
393  }
394 
395  _gsg = _buffer->get_gsg();
396 
397  WindowHandle *window_handle = _properties.get_parent_window();
398  if (window_handle != NULL) {
399  WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
400  if (os_handle != NULL) {
401  if (os_handle->is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
402  NativeWindowHandle::SubprocessHandle *subprocess_handle = DCAST(NativeWindowHandle::SubprocessHandle, os_handle);
403  _filename = subprocess_handle->get_filename();
404  }
405  }
406  }
407  _parent_window_handle = window_handle;
408 
409  if (_filename.empty()) {
410  _is_valid = false;
411  display_cat.error()
412  << "No filename given to SubprocessWindow.\n";
413  return false;
414  }
415 
417  (_fd, _mmap_size, _filename.to_os_specific());
418 
419  if (_swbuffer == NULL) {
420  close(_fd);
421  _fd = -1;
422  _filename = string();
423  _is_valid = false;
424  display_cat.error()
425  << "Failed to open SubprocessWindowBuffer's shared-memory buffer "
426  << _filename << "\n";
427  return false;
428  }
429 
430  if (display_cat.is_debug()) {
431  display_cat.debug()
432  << "SubprocessWindow reading " << _filename << "\n";
433  }
434 
435  // Create a WindowHandle for ourselves
436  _window_handle = NativeWindowHandle::make_subprocess(_filename);
437 
438  // And tell our parent window that we're now its child.
439  if (_parent_window_handle != (WindowHandle *)NULL) {
440  _parent_window_handle->attach_child(_window_handle);
441  }
442 
443  return true;
444 }
445 
446 ////////////////////////////////////////////////////////////////////
447 // Function: SubprocessWindow::translate_key
448 // Access: Private
449 // Description: Converts the os-specific keycode into the appropriate
450 // ButtonHandle object. Also stores the corresponding
451 // Unicode keycode in keycode, if any; or 0 otherwise.
452 ////////////////////////////////////////////////////////////////////
453 ButtonHandle SubprocessWindow::
454 translate_key(int &keycode, int os_code, unsigned int flags) const {
455  keycode = 0;
457 
458 #ifdef __APPLE__
459  switch ((os_code >> 8) & 0xff) {
460  case 0: nk = KeyboardButton::ascii_key('a'); break;
461  case 11: nk = KeyboardButton::ascii_key('b'); break;
462  case 8: nk = KeyboardButton::ascii_key('c'); break;
463  case 2: nk = KeyboardButton::ascii_key('d'); break;
464  case 14: nk = KeyboardButton::ascii_key('e'); break;
465  case 3: nk = KeyboardButton::ascii_key('f'); break;
466  case 5: nk = KeyboardButton::ascii_key('g'); break;
467  case 4: nk = KeyboardButton::ascii_key('h'); break;
468  case 34: nk = KeyboardButton::ascii_key('i'); break;
469  case 38: nk = KeyboardButton::ascii_key('j'); break;
470  case 40: nk = KeyboardButton::ascii_key('k'); break;
471  case 37: nk = KeyboardButton::ascii_key('l'); break;
472  case 46: nk = KeyboardButton::ascii_key('m'); break;
473  case 45: nk = KeyboardButton::ascii_key('n'); break;
474  case 31: nk = KeyboardButton::ascii_key('o'); break;
475  case 35: nk = KeyboardButton::ascii_key('p'); break;
476  case 12: nk = KeyboardButton::ascii_key('q'); break;
477  case 15: nk = KeyboardButton::ascii_key('r'); break;
478  case 1: nk = KeyboardButton::ascii_key('s'); break;
479  case 17: nk = KeyboardButton::ascii_key('t'); break;
480  case 32: nk = KeyboardButton::ascii_key('u'); break;
481  case 9: nk = KeyboardButton::ascii_key('v'); break;
482  case 13: nk = KeyboardButton::ascii_key('w'); break;
483  case 7: nk = KeyboardButton::ascii_key('x'); break;
484  case 16: nk = KeyboardButton::ascii_key('y'); break;
485  case 6: nk = KeyboardButton::ascii_key('z'); break;
486 
487  // top row numbers
488  case 29: nk = KeyboardButton::ascii_key('0'); break;
489  case 18: nk = KeyboardButton::ascii_key('1'); break;
490  case 19: nk = KeyboardButton::ascii_key('2'); break;
491  case 20: nk = KeyboardButton::ascii_key('3'); break;
492  case 21: nk = KeyboardButton::ascii_key('4'); break;
493  case 23: nk = KeyboardButton::ascii_key('5'); break;
494  case 22: nk = KeyboardButton::ascii_key('6'); break;
495  case 26: nk = KeyboardButton::ascii_key('7'); break;
496  case 28: nk = KeyboardButton::ascii_key('8'); break;
497  case 25: nk = KeyboardButton::ascii_key('9'); break;
498 
499  // key pad ... do they really map to the top number in panda ?
500  case 82: nk = KeyboardButton::ascii_key('0'); break;
501  case 83: nk = KeyboardButton::ascii_key('1'); break;
502  case 84: nk = KeyboardButton::ascii_key('2'); break;
503  case 85: nk = KeyboardButton::ascii_key('3'); break;
504  case 86: nk = KeyboardButton::ascii_key('4'); break;
505  case 87: nk = KeyboardButton::ascii_key('5'); break;
506  case 88: nk = KeyboardButton::ascii_key('6'); break;
507  case 89: nk = KeyboardButton::ascii_key('7'); break;
508  case 91: nk = KeyboardButton::ascii_key('8'); break;
509  case 92: nk = KeyboardButton::ascii_key('9'); break;
510 
511  // case 36: nk = KeyboardButton::ret(); break; // no return in panda ???
512  case 49: nk = KeyboardButton::space(); break;
513  case 51: nk = KeyboardButton::backspace(); break;
514  case 48: nk = KeyboardButton::tab(); break;
515  case 53: nk = KeyboardButton::escape(); break;
516  case 76: nk = KeyboardButton::enter(); break;
517  case 36: nk = KeyboardButton::enter(); break;
518 
519  case 123: nk = KeyboardButton::left(); break;
520  case 124: nk = KeyboardButton::right(); break;
521  case 125: nk = KeyboardButton::down(); break;
522  case 126: nk = KeyboardButton::up(); break;
523  case 116: nk = KeyboardButton::page_up(); break;
524  case 121: nk = KeyboardButton::page_down(); break;
525  case 115: nk = KeyboardButton::home(); break;
526  case 119: nk = KeyboardButton::end(); break;
527  case 114: nk = KeyboardButton::help(); break;
528  case 117: nk = KeyboardButton::del(); break;
529 
530  // case 71: nk = KeyboardButton::num_lock() break;
531 
532  case 122: nk = KeyboardButton::f1(); break;
533  case 120: nk = KeyboardButton::f2(); break;
534  case 99: nk = KeyboardButton::f3(); break;
535  case 118: nk = KeyboardButton::f4(); break;
536  case 96: nk = KeyboardButton::f5(); break;
537  case 97: nk = KeyboardButton::f6(); break;
538  case 98: nk = KeyboardButton::f7(); break;
539  case 100: nk = KeyboardButton::f8(); break;
540  case 101: nk = KeyboardButton::f9(); break;
541  case 109: nk = KeyboardButton::f10(); break;
542  case 103: nk = KeyboardButton::f11(); break;
543  case 111: nk = KeyboardButton::f12(); break;
544 
545  case 105: nk = KeyboardButton::f13(); break;
546  case 107: nk = KeyboardButton::f14(); break;
547  case 113: nk = KeyboardButton::f15(); break;
548  case 106: nk = KeyboardButton::f16(); break;
549 
550  // shiftable chartablet
551  case 50: nk = KeyboardButton::ascii_key('`'); break;
552  case 27: nk = KeyboardButton::ascii_key('-'); break;
553  case 24: nk = KeyboardButton::ascii_key('='); break;
554  case 33: nk = KeyboardButton::ascii_key('['); break;
555  case 30: nk = KeyboardButton::ascii_key(']'); break;
556  case 42: nk = KeyboardButton::ascii_key('\\'); break;
557  case 41: nk = KeyboardButton::ascii_key(';'); break;
558  case 39: nk = KeyboardButton::ascii_key('\''); break;
559  case 43: nk = KeyboardButton::ascii_key(','); break;
560  case 47: nk = KeyboardButton::ascii_key('.'); break;
561  case 44: nk = KeyboardButton::ascii_key('/'); break;
562 
563  default:
564  // Punt.
565  nk = KeyboardButton::ascii_key(os_code & 0xff);
566  }
567 
568  if (nk.has_ascii_equivalent()) {
569  // If we assigned an ASCII button, then get the original ASCII
570  // code from the event (it will include shift et al).
571 
572  // TODO: is it possible to get any international characters via
573  // this old EventRecord interface?
574  keycode = os_code & 0xff;
575  }
576 
577 #endif // __APPLE__
578 
579  return nk;
580 }
581 
582 ////////////////////////////////////////////////////////////////////
583 // Function: SubprocessWindow::transition_button
584 // Access: Private
585 // Description: Sends the appropriate up/down transition for the
586 // indicated modifier key, as determined implicitly from
587 // the flags.
588 ////////////////////////////////////////////////////////////////////
589 void SubprocessWindow::
590 transition_button(unsigned int flags, ButtonHandle button) {
591  if (flags) {
592  _input_devices[0].button_down(button);
593  } else {
594  _input_devices[0].button_up(button);
595  }
596 }
597 
598 
599 #endif // SUPPORT_SUBPROCESS_WINDOW
static GraphicsWindowInputDevice pointer_and_keyboard(GraphicsWindow *host, const string &name)
This named constructor returns an input device that has both a keyboard and pointer.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
static int get_renderbuffer_type(int plane)
Returns the RenderBuffer::Type that corresponds to a RenderTexturePlane.
static ButtonHandle none()
Returns a special zero-valued ButtonHandle that is used to indicate no button.
Definition: buttonHandle.I:205
const Element * p() const
Function p() is similar to the function from ConstPointerTo.
void clear()
Unsets all properties that have been specified so far, and resets the WindowProperties structure to i...
This object represents a window on the desktop, not necessarily a Panda window.
Definition: windowHandle.h:40
static WindowProperties size(int x_size, int y_size)
Returns a WindowProperties structure with only the size specified.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:75
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
void clear_parent_window()
Removes the S_parent_window specification from the properties.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
Definition: thread.I:248
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_parent_window() const
Checks the S_parent_window specification from the properties.
static void close_buffer(int fd, size_t mmap_size, const string &filename, SubprocessWindowBuffer *buffer)
Closes a buffer object created via a previous call to open_buffer().
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An offscreen buffer for rendering into.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
static ButtonHandle button(int button_number)
Returns the ButtonHandle associated with the particular numbered mouse button (zero-based), if there is one, or ButtonHandle::none() if there is not.
Definition: mouseButton.cxx:36
A ClockObject keeps track of elapsed real time and discrete time.
Definition: clockObject.h:66
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
This is a structure representing a single input device that may be associated with a window...
WindowHandle * get_parent_window() const
Returns the parent window specification, or NULL if there is no parent window specified.
This is a base class for the various different classes that represent the result of a frame of render...
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
void set_foreground(bool foreground)
Specifies whether the window should be opened in the foreground (true), or left in the background (fa...
A thread; that is, a lightweight process.
Definition: thread.h:51
Encapsulates all the communication with a particular instance of a given rendering backend...
This class is the main interface to controlling the render process.
double get_real_time() const
Returns the actual number of seconds elapsed since the ClockObject was created, or since it was last ...
Definition: clockObject.I:68
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
OSHandle * get_os_handle() const
Returns the OS-specific handle stored internally to the WindowHandle wrapper.
Definition: windowHandle.I:41
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
static ButtonHandle ascii_key(char ascii_equivalent)
Returns the ButtonHandle associated with the particular ASCII character, if there is one...
void set_open(bool open)
Specifies whether the window should be open.
static SubprocessWindowBuffer * open_buffer(int &fd, size_t &mmap_size, const string &filename)
Call this method to open a reference to an existing buffer in shared memory space.
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer, etc.) of a drawing region.
Definition: renderBuffer.h:30
bool has_ascii_equivalent() const
Returns true if the button was created with an ASCII equivalent code (e.g.
Definition: buttonHandle.I:140