Panda3D
 All Classes Functions Variables Enumerations
graphicsWindow.cxx
00001 // Filename: graphicsWindow.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "graphicsWindow.h"
00016 #include "graphicsPipe.h"
00017 #include "config_display.h"
00018 #include "mouseButton.h"
00019 #include "keyboardButton.h"
00020 #include "lightMutexHolder.h"
00021 #include "lightReMutexHolder.h"
00022 #include "throw_event.h"
00023 #include "string_utils.h"
00024 
00025 TypeHandle GraphicsWindow::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: GraphicsWindow::Constructor
00029 //       Access: Protected
00030 //  Description: Normally, the GraphicsWindow constructor is not
00031 //               called directly; these are created instead via the
00032 //               GraphicsEngine::make_window() function.
00033 ////////////////////////////////////////////////////////////////////
00034 GraphicsWindow::
00035 GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
00036                const string &name,
00037                const FrameBufferProperties &fb_prop,
00038                const WindowProperties &win_prop,
00039                int flags,
00040                GraphicsStateGuardian *gsg,
00041                GraphicsOutput *host) :
00042   GraphicsOutput(engine, pipe, name, fb_prop, win_prop, flags, gsg, host, true),
00043   _input_lock("GraphicsWindow::_input_lock"),
00044   _properties_lock("GraphicsWindow::_properties_lock")
00045 {
00046 #ifdef DO_MEMORY_USAGE
00047   MemoryUsage::update_type(this, this);
00048 #endif
00049 
00050   if (display_cat.is_debug()) {
00051     display_cat.debug()
00052       << "Creating new window " << get_name() << "\n";
00053   }
00054 
00055   _properties.set_open(false);
00056   _properties.set_undecorated(false);
00057   _properties.set_fullscreen(false);
00058   _properties.set_minimized(false);
00059   _properties.set_cursor_hidden(false);
00060 
00061   request_properties(WindowProperties::get_default());
00062   request_properties(win_prop);
00063 
00064   _window_event = "window-event";
00065   _got_expose_event = false;
00066   _unexposed_draw = win_unexposed_draw;
00067   set_pixel_zoom(pixel_zoom);
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: GraphicsWindow::Destructor
00072 //       Access: Published, Virtual
00073 //  Description:
00074 ////////////////////////////////////////////////////////////////////
00075 GraphicsWindow::
00076 ~GraphicsWindow() {
00077   // Clean up python event handlers.
00078 #ifdef HAVE_PYTHON
00079   PythonWinProcClasses::iterator iter;
00080   for (iter = _python_window_proc_classes.begin(); 
00081        iter != _python_window_proc_classes.end(); 
00082        ++iter) {
00083     delete *iter;
00084   }
00085 #endif
00086 }
00087 
00088 ////////////////////////////////////////////////////////////////////
00089 //     Function: GraphicsWindow::get_properties
00090 //       Access: Published
00091 //  Description: Returns the current properties of the window.
00092 ////////////////////////////////////////////////////////////////////
00093 const WindowProperties GraphicsWindow::
00094 get_properties() const {
00095   WindowProperties result;
00096   {
00097     LightReMutexHolder holder(_properties_lock);
00098     result = _properties;
00099   }
00100   return result;
00101 }
00102 
00103 ////////////////////////////////////////////////////////////////////
00104 //     Function: GraphicsWindow::get_requested_properties
00105 //       Access: Published
00106 //  Description: Returns the properties of the window that are
00107 //               currently requested.  These properties will be
00108 //               applied to the window (if valid) at the next
00109 //               execution of process_events().
00110 ////////////////////////////////////////////////////////////////////
00111 const WindowProperties GraphicsWindow::
00112 get_requested_properties() const {
00113   WindowProperties result;
00114   {
00115     LightReMutexHolder holder(_properties_lock);
00116     result = _requested_properties;
00117   }
00118   return result;
00119 }
00120 
00121 ////////////////////////////////////////////////////////////////////
00122 //     Function: GraphicsWindow::clear_rejected_properties
00123 //       Access: Published
00124 //  Description: Empties the set of failed properties that will be
00125 //               returned by get_rejected_properties().
00126 ////////////////////////////////////////////////////////////////////
00127 void GraphicsWindow::
00128 clear_rejected_properties() {
00129   LightReMutexHolder holder(_properties_lock);
00130   _rejected_properties.clear();
00131 }
00132 
00133 ////////////////////////////////////////////////////////////////////
00134 //     Function: GraphicsWindow::get_rejected_properties
00135 //       Access: Published
00136 //  Description: Returns the set of properties that have recently been
00137 //               requested, but could not be applied to the window for
00138 //               some reason.  This set of properties will remain
00139 //               unchanged until they are changed by a new failed
00140 //               request, or clear_rejected_properties() is called.
00141 ////////////////////////////////////////////////////////////////////
00142 WindowProperties GraphicsWindow::
00143 get_rejected_properties() const {
00144   WindowProperties result;
00145   {
00146     LightReMutexHolder holder(_properties_lock);
00147     result = _rejected_properties;
00148   }
00149   return result;
00150 }
00151 
00152 ////////////////////////////////////////////////////////////////////
00153 //     Function: GraphicsWindow::request_properties
00154 //       Access: Published
00155 //  Description: Requests a property change on the window.  For
00156 //               example, use this method to request a window change
00157 //               size or minimize or something.
00158 //
00159 //               The change is not made immediately; rather, the
00160 //               request is saved and will be applied the next time
00161 //               the window task is run (probably at the next frame).
00162 ////////////////////////////////////////////////////////////////////
00163 void GraphicsWindow::
00164 request_properties(const WindowProperties &requested_properties) {
00165   LightReMutexHolder holder(_properties_lock);
00166   _requested_properties.add_properties(requested_properties);
00167 
00168   if (!_has_size && _requested_properties.has_size()) {
00169     // If we just requested a particular size, anticipate that it will
00170     // stick.  This is helpful for the MultitexReducer, which needs to
00171     // know the size of the textures that it will be working with,
00172     // even if the texture hasn't been fully generated yet.
00173     _x_size = _requested_properties.get_x_size();
00174     _y_size = _requested_properties.get_y_size();
00175 
00176     // Don't set _has_size yet, because we don't really know yet.
00177   }
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: GraphicsWindow::is_active
00182 //       Access: Published, Virtual
00183 //  Description: Returns true if the window is ready to be rendered
00184 //               into, false otherwise.
00185 ////////////////////////////////////////////////////////////////////
00186 bool GraphicsWindow::
00187 is_active() const {
00188   // Make this smarter?
00189   return GraphicsOutput::is_active() && _properties.get_open() && !_properties.get_minimized();
00190 }
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: GraphicsWindow::set_window_event
00194 //       Access: Published
00195 //  Description: Changes the name of the event that is generated when
00196 //               this window is modified externally, e.g. to be
00197 //               resized or closed by the user.
00198 //
00199 //               By default, all windows have the same window event
00200 //               unless they are explicitly changed.  When the event
00201 //               is generated, it includes one parameter: the window
00202 //               itself.
00203 ////////////////////////////////////////////////////////////////////
00204 void GraphicsWindow::
00205 set_window_event(const string &window_event) {
00206   LightReMutexHolder holder(_properties_lock);
00207   _window_event = window_event;
00208 }
00209 
00210 ////////////////////////////////////////////////////////////////////
00211 //     Function: GraphicsWindow::get_window_event
00212 //       Access: Published
00213 //  Description: Returns the name of the event that is generated when
00214 //               this window is modified externally, e.g. to be
00215 //               resized or closed by the user.  See set_window_event().
00216 ////////////////////////////////////////////////////////////////////
00217 string GraphicsWindow::
00218 get_window_event() const {
00219   string result;
00220   LightReMutexHolder holder(_properties_lock);
00221   result = _window_event;
00222   return result;
00223 }
00224 
00225 ////////////////////////////////////////////////////////////////////
00226 //     Function: GraphicsWindow::set_close_request_event
00227 //       Access: Published
00228 //  Description: Sets the event that is triggered when the user
00229 //               requests to close the window, e.g. via alt-F4, or
00230 //               clicking on the close box.
00231 //
00232 //               The default for each window is for this event to be
00233 //               the empty string, which means the window-close
00234 //               request is handled immediately by Panda (and the
00235 //               window will be closed without the app getting a
00236 //               chance to intervene).  If you set this to a nonempty
00237 //               string, then the window is not closed, but instead
00238 //               the event is thrown.  It is then up to the app to
00239 //               respond appropriately, for instance by presenting an
00240 //               "are you sure?" dialog box, and eventually calling
00241 //               close_window() when the user is sure.
00242 //
00243 //               It is considered poor form to set this string and
00244 //               then not handle the event.  This can frustrate the
00245 //               user by making it difficult for him to cleanly shut
00246 //               down the application (and may force the user to
00247 //               hard-kill the app, or reboot the machine).
00248 ////////////////////////////////////////////////////////////////////
00249 void GraphicsWindow::
00250 set_close_request_event(const string &close_request_event) {
00251   LightReMutexHolder holder(_properties_lock);
00252   _close_request_event = close_request_event;
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: GraphicsWindow::get_close_request_event
00257 //       Access: Published
00258 //  Description: Returns the name of the event set via
00259 //               set_close_request_event().  If this string is
00260 //               nonempty, then when the user requests to close
00261 //               window, this event will be generated instead.  See
00262 //               set_close_request_event().
00263 ////////////////////////////////////////////////////////////////////
00264 string GraphicsWindow::
00265 get_close_request_event() const {
00266   string result;
00267   LightReMutexHolder holder(_properties_lock);
00268   result = _close_request_event;
00269   return result;
00270 }
00271 
00272 ////////////////////////////////////////////////////////////////////
00273 //     Function: GraphicsWindow::get_num_input_devices
00274 //       Access: Published
00275 //  Description: Returns the number of separate input devices
00276 //               associated with the window.  Typically, a window will
00277 //               have exactly one input device: the keyboard/mouse
00278 //               pair.  However, some windows may have no input
00279 //               devices, and others may add additional devices, for
00280 //               instance for a joystick.
00281 ////////////////////////////////////////////////////////////////////
00282 int GraphicsWindow::
00283 get_num_input_devices() const {
00284   int result;
00285   {
00286     LightMutexHolder holder(_input_lock);
00287     result = _input_devices.size();
00288   }
00289   return result;
00290 }
00291 
00292 ////////////////////////////////////////////////////////////////////
00293 //     Function: GraphicsWindow::get_input_device_name
00294 //       Access: Published
00295 //  Description: Returns the name of the nth input device.
00296 ////////////////////////////////////////////////////////////////////
00297 string GraphicsWindow::
00298 get_input_device_name(int device) const {
00299   string result;
00300   {
00301     LightMutexHolder holder(_input_lock);
00302     nassertr(device >= 0 && device < (int)_input_devices.size(), "");
00303     result = _input_devices[device].get_name();
00304   }
00305   return result;
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: GraphicsWindow::has_pointer
00310 //       Access: Published
00311 //  Description: Returns true if the nth input device has a
00312 //               screen-space pointer (for instance, a mouse), false
00313 //               otherwise.
00314 ////////////////////////////////////////////////////////////////////
00315 bool GraphicsWindow::
00316 has_pointer(int device) const {
00317   bool result;
00318   {
00319     LightMutexHolder holder(_input_lock);
00320     nassertr(device >= 0 && device < (int)_input_devices.size(), false);
00321     result = _input_devices[device].has_pointer();
00322   }
00323   return result;
00324 }
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: GraphicsWindow::has_keyboard
00328 //       Access: Published
00329 //  Description: Returns true if the nth input device has a keyboard,
00330 //               false otherwise.
00331 ////////////////////////////////////////////////////////////////////
00332 bool GraphicsWindow::
00333 has_keyboard(int device) const {
00334   bool result;
00335   {
00336     LightMutexHolder holder(_input_lock);
00337     nassertr(device >= 0 && device < (int)_input_devices.size(), false);
00338     result = _input_devices[device].has_keyboard();
00339   }
00340   return result;
00341 }
00342 
00343 ////////////////////////////////////////////////////////////////////
00344 //     Function: GraphicsWindow::enable_pointer_events
00345 //       Access: Published
00346 //  Description: Turn on the generation of pointer events.
00347 ////////////////////////////////////////////////////////////////////
00348 void GraphicsWindow::
00349 enable_pointer_events(int device) {
00350   LightMutexHolder holder(_input_lock);
00351   nassertv(device >= 0 && device < (int)_input_devices.size());
00352   _input_devices[device].enable_pointer_events();
00353 }
00354 
00355 ////////////////////////////////////////////////////////////////////
00356 //     Function: GraphicsWindow::disable_pointer_events
00357 //       Access: Published
00358 //  Description: Turn off the generation of pointer events.
00359 ////////////////////////////////////////////////////////////////////
00360 void GraphicsWindow::
00361 disable_pointer_events(int device) {
00362   LightMutexHolder holder(_input_lock);
00363   nassertv(device >= 0 && device < (int)_input_devices.size());
00364   _input_devices[device].disable_pointer_events();
00365 }
00366 
00367 ////////////////////////////////////////////////////////////////////
00368 //     Function: GraphicsWindow::enable_pointer_mode
00369 //       Access: Published
00370 //  Description: See GraphicsWindowInputDevice::enable_pointer_mode
00371 ////////////////////////////////////////////////////////////////////
00372 void GraphicsWindow::
00373 enable_pointer_mode(int device, double speed) {
00374   LightMutexHolder holder(_input_lock);
00375   nassertv(device >= 0 && device < (int)_input_devices.size());
00376   _input_devices[device].enable_pointer_mode(speed);
00377 }
00378 
00379 ////////////////////////////////////////////////////////////////////
00380 //     Function: GraphicsWindow::disable_pointer_events
00381 //       Access: Published
00382 //  Description: See GraphicsWindowInputDevice::disable_pointer_mode
00383 ////////////////////////////////////////////////////////////////////
00384 void GraphicsWindow::
00385 disable_pointer_mode(int device) {
00386   LightMutexHolder holder(_input_lock);
00387   nassertv(device >= 0 && device < (int)_input_devices.size());
00388   _input_devices[device].disable_pointer_mode();
00389 }
00390 
00391 ////////////////////////////////////////////////////////////////////
00392 //     Function: GraphicsWindow::get_pointer
00393 //       Access: Published
00394 //  Description: Returns the MouseData associated with the nth input
00395 //               device's pointer.
00396 ////////////////////////////////////////////////////////////////////
00397 MouseData GraphicsWindow::
00398 get_pointer(int device) const {
00399   MouseData result;
00400   {
00401     LightMutexHolder holder(_input_lock);
00402     nassertr(device >= 0 && device < (int)_input_devices.size(), MouseData());
00403     result = _input_devices[device].get_pointer();
00404   }
00405   return result;
00406 }
00407 
00408 ////////////////////////////////////////////////////////////////////
00409 //     Function: GraphicsWindow::move_pointer
00410 //       Access: Published, Virtual
00411 //  Description: Forces the pointer to the indicated position within
00412 //               the window, if possible.  
00413 //
00414 //               Returns true if successful, false on failure.  This
00415 //               may fail if the mouse is not currently within the
00416 //               window, or if the API doesn't support this operation.
00417 ////////////////////////////////////////////////////////////////////
00418 bool GraphicsWindow::
00419 move_pointer(int, int, int) {
00420   return false;
00421 }
00422 
00423 ////////////////////////////////////////////////////////////////////
00424 //     Function: GraphicsWindow::close_ime
00425 //       Access: Published, Virtual
00426 //  Description: Forces the ime window to close if any
00427 //
00428 ////////////////////////////////////////////////////////////////////
00429 void GraphicsWindow::
00430 close_ime() {
00431   return;
00432 }
00433 
00434 ////////////////////////////////////////////////////////////////////
00435 //     Function: GraphicsWindow::has_button_event
00436 //       Access: Public
00437 //  Description: Returns true if the indicated device has a pending
00438 //               button event (a mouse button or keyboard button
00439 //               down/up), false otherwise.  If this returns true, the
00440 //               particular event may be extracted via
00441 //               get_button_event().
00442 ////////////////////////////////////////////////////////////////////
00443 bool GraphicsWindow::
00444 has_button_event(int device) const {
00445   bool result;
00446   {
00447     LightMutexHolder holder(_input_lock);
00448     nassertr(device >= 0 && device < (int)_input_devices.size(), false);
00449     result = _input_devices[device].has_button_event();
00450   }
00451   return result;
00452 }
00453 
00454 ////////////////////////////////////////////////////////////////////
00455 //     Function: GraphicsWindow::get_button_event
00456 //       Access: Public
00457 //  Description: Assuming a previous call to has_button_event()
00458 //               returned true, this returns the pending button event.
00459 ////////////////////////////////////////////////////////////////////
00460 ButtonEvent GraphicsWindow::
00461 get_button_event(int device) {
00462   ButtonEvent result;
00463   {
00464     LightMutexHolder holder(_input_lock);
00465     nassertr(device >= 0 && device < (int)_input_devices.size(), ButtonEvent());
00466     nassertr(_input_devices[device].has_button_event(), ButtonEvent());
00467     result = _input_devices[device].get_button_event();
00468   }
00469   return result;
00470 }
00471 
00472 ////////////////////////////////////////////////////////////////////
00473 //     Function: GraphicsWindow::has_pointer_event
00474 //       Access: Public
00475 //  Description: Returns true if the indicated device has a pending
00476 //               pointer event (a mouse movement).  If this returns
00477 //               true, the particular event may be extracted via
00478 //               get_pointer_events().
00479 ////////////////////////////////////////////////////////////////////
00480 bool GraphicsWindow::
00481 has_pointer_event(int device) const {
00482   bool result;
00483   {
00484     LightMutexHolder holder(_input_lock);
00485     nassertr(device >= 0 && device < (int)_input_devices.size(), false);
00486     result = _input_devices[device].has_pointer_event();
00487   }
00488   return result;
00489 }
00490 
00491 ////////////////////////////////////////////////////////////////////
00492 //     Function: GraphicsWindow::get_pointer_events
00493 //       Access: Public
00494 //  Description: Assuming a previous call to has_pointer_event()
00495 //               returned true, this returns the pending pointer event list.
00496 ////////////////////////////////////////////////////////////////////
00497 PT(PointerEventList) GraphicsWindow::
00498 get_pointer_events(int device) {
00499   PT(PointerEventList) result;
00500   {
00501     LightMutexHolder holder(_input_lock);
00502     nassertr(device >= 0 && device < (int)_input_devices.size(), NULL);
00503     nassertr(_input_devices[device].has_pointer_event(), NULL);
00504     result = _input_devices[device].get_pointer_events();
00505   }
00506   return result;
00507 }
00508 
00509 ////////////////////////////////////////////////////////////////////
00510 //     Function: GraphicsWindow::verify_window_sizes
00511 //       Access: Public, Virtual
00512 //  Description: Determines which of the indicated window sizes are
00513 //               supported by available hardware (e.g. in fullscreen
00514 //               mode).
00515 //
00516 //               On entry, dimen is an array containing contiguous x,y
00517 //               pairs specifying possible display sizes; it is
00518 //               numsizes*2 words long.  The function will zero out
00519 //               any invalid x,y size pairs.  The return value is the
00520 //               number of valid sizes that were found.
00521 //
00522 //               Note this doesn't guarantee a resize attempt will
00523 //               work; you still need to check the return value.
00524 //
00525 //               (It might be better to implement some sort of query
00526 //               interface that returns an array of supported sizes,
00527 //               but this way is somewhat simpler and will do the job
00528 //               on most cards, assuming they handle the std sizes the
00529 //               app knows about.)
00530 ////////////////////////////////////////////////////////////////////
00531 int GraphicsWindow::
00532 verify_window_sizes(int numsizes, int *dimen) {
00533   return numsizes;
00534 }
00535  
00536 ////////////////////////////////////////////////////////////////////
00537 //     Function: GraphicsWindow::request_open
00538 //       Access: Public, Virtual
00539 //  Description: This is called by the GraphicsEngine to request that
00540 //               the window (or whatever) open itself or, in general,
00541 //               make itself valid, at the next call to
00542 //               process_events().
00543 ////////////////////////////////////////////////////////////////////
00544 void GraphicsWindow::
00545 request_open() {
00546   WindowProperties open_properties;
00547   open_properties.set_open(true);
00548   request_properties(open_properties);
00549 }
00550  
00551 ////////////////////////////////////////////////////////////////////
00552 //     Function: GraphicsWindow::request_close
00553 //       Access: Public, Virtual
00554 //  Description: This is called by the GraphicsEngine to request that
00555 //               the window (or whatever) close itself or, in general,
00556 //               make itself invalid, at the next call to
00557 //               process_events().  By that time we promise the gsg
00558 //               pointer will be cleared.
00559 ////////////////////////////////////////////////////////////////////
00560 void GraphicsWindow::
00561 request_close() {
00562   WindowProperties close_properties;
00563   close_properties.set_open(false);
00564   request_properties(close_properties);
00565 }
00566  
00567 ////////////////////////////////////////////////////////////////////
00568 //     Function: GraphicsWindow::set_close_now
00569 //       Access: Public, Virtual
00570 //  Description: This is called by the GraphicsEngine to insist that
00571 //               the window be closed immediately.  This is only
00572 //               called from the window thread.
00573 ////////////////////////////////////////////////////////////////////
00574 void GraphicsWindow::
00575 set_close_now() {
00576   WindowProperties close_properties;
00577   close_properties.set_open(false);
00578   set_properties_now(close_properties);
00579 }
00580 
00581 ////////////////////////////////////////////////////////////////////
00582 //     Function: GraphicsWindow::process_events
00583 //       Access: Public, Virtual
00584 //  Description: Do whatever processing is necessary to ensure that
00585 //               the window responds to user events.  Also, honor any
00586 //               requests recently made via request_properties().
00587 //
00588 //               This function is called only within the window
00589 //               thread.
00590 ////////////////////////////////////////////////////////////////////
00591 void GraphicsWindow::
00592 process_events() {
00593   if (_requested_properties.is_any_specified()) {
00594     // We don't bother to grab the mutex until after we have already
00595     // checked whether any properties have been specified.  This is
00596     // technically sloppy, but it ought to be o.k. since it's just a
00597     // bitmask after all.
00598     WindowProperties properties;
00599     {
00600       LightReMutexHolder holder(_properties_lock);
00601       properties = _requested_properties;
00602       _requested_properties.clear();
00603 
00604       set_properties_now(properties);
00605       if (properties.is_any_specified()) {
00606         display_cat.info()
00607           << "Unable to set window properties: " << properties << "\n";
00608         _rejected_properties.add_properties(properties);
00609       }
00610     }
00611   }
00612 }
00613 
00614 ////////////////////////////////////////////////////////////////////
00615 //     Function: GraphicsWindow::set_properties_now
00616 //       Access: Public, Virtual
00617 //  Description: Applies the requested set of properties to the
00618 //               window, if possible, for instance to request a change
00619 //               in size or minimization status.
00620 //
00621 //               The window properties are applied immediately, rather
00622 //               than waiting until the next frame.  This implies that
00623 //               this method may *only* be called from within the
00624 //               window thread.
00625 //
00626 //               The properties that have been applied are cleared
00627 //               from the structure by this function; so on return,
00628 //               whatever remains in the properties structure are
00629 //               those that were unchanged for some reason (probably
00630 //               because the underlying interface does not support
00631 //               changing that property on an open window).
00632 ////////////////////////////////////////////////////////////////////
00633 void GraphicsWindow::
00634 set_properties_now(WindowProperties &properties) {
00635   if (properties.has_open() && 
00636       properties.get_open() != _properties.get_open()) {
00637     // Open or close a new window.  In this case we can get all of the
00638     // properties at once.
00639 
00640     _properties.add_properties(properties);
00641     properties.clear();
00642 
00643     if (_properties.get_open()) {
00644       if (open_window()) {
00645         // When the window is first opened, force its size to be
00646         // broadcast to its display regions.
00647         _is_valid = true;
00648         set_size_and_recalc(_properties.get_x_size(),
00649                             _properties.get_y_size());
00650       } else {
00651         // Since we can't even open the window, tag the
00652         // _rejected_properties with all of the window properties that
00653         // failed.
00654         _rejected_properties.add_properties(_properties);
00655 
00656         // And mark the window closed.
00657         _properties.set_open(false);
00658         _is_valid = false;
00659       }
00660 
00661     } else {
00662       // We used to resist closing a window before its GSG has been
00663       // released.  Now it seems we never release a GSG, so go ahead
00664       // and close the window.
00665       close_window();
00666       _is_valid = false;
00667     }
00668     return;
00669   }
00670 
00671   if (!_properties.get_open()) {
00672     // The window is not currently open; we can set properties at
00673     // will.
00674     _properties.add_properties(properties);
00675     properties.clear();
00676     return;
00677   }
00678 
00679   properties.clear_open();
00680 
00681   // The window is already open; we are limited to what we can change
00682   // on the fly.
00683 
00684   if (properties.has_size() || properties.has_origin()) {
00685     // Consider changing the window's size and/or position.
00686     WindowProperties reshape_props;
00687     if (properties.has_size()) {
00688       reshape_props.set_size(properties.get_x_size(), properties.get_y_size());
00689     } else {
00690       reshape_props.set_size(_properties.get_x_size(), _properties.get_y_size());
00691     }
00692 
00693     if (properties.has_origin() && !is_fullscreen()) {
00694       reshape_props.set_origin(properties.get_x_origin(), properties.get_y_origin());
00695     } else if (_properties.has_origin()) {
00696       reshape_props.set_origin(_properties.get_x_origin(), _properties.get_y_origin());
00697     }
00698 
00699     bool has_origin = reshape_props.has_origin();
00700     int x_origin = 0, y_origin = 0;
00701     if (has_origin) {
00702       x_origin = reshape_props.get_x_origin();
00703       y_origin = reshape_props.get_y_origin();
00704     }
00705     
00706     if (reshape_props.get_x_size() != _properties.get_x_size() ||
00707         reshape_props.get_y_size() != _properties.get_y_size() ||
00708         (has_origin && (x_origin != _properties.get_x_origin() ||
00709                         y_origin != _properties.get_y_origin()))) {
00710       if (do_reshape_request(x_origin, y_origin, has_origin,
00711                              reshape_props.get_x_size(),
00712                              reshape_props.get_y_size())) {
00713         properties.clear_size();
00714         properties.clear_origin();
00715       }
00716     } else {
00717       properties.clear_size();
00718       properties.clear_origin();
00719     }
00720   }
00721 
00722   if (properties.has_fullscreen() && 
00723       properties.get_fullscreen() == _properties.get_fullscreen()) {
00724     // Fullscreen property specified, but unchanged.
00725     properties.clear_fullscreen();
00726   }
00727   if (properties.has_mouse_mode() ) {
00728     
00729     if (properties.get_mouse_mode() == _properties.get_mouse_mode()) {  
00730       properties.clear_mouse_mode();
00731     }
00732     else {
00733       if(properties.get_mouse_mode() == WindowProperties::M_absolute) {
00734         _properties.set_mouse_mode(WindowProperties::M_absolute);
00735         mouse_mode_absolute();
00736         properties.clear_mouse_mode();
00737       }
00738       else
00739       {
00740         _properties.set_mouse_mode(WindowProperties::M_relative);
00741         mouse_mode_relative();
00742         properties.clear_mouse_mode();        
00743       }    
00744     }
00745   }
00746 }
00747 
00748 ////////////////////////////////////////////////////////////////////
00749 //     Function: GraphicsWindow::close_window
00750 //       Access: Protected, Virtual
00751 //  Description: Closes the window right now.  Called from the window
00752 //               thread.
00753 ////////////////////////////////////////////////////////////////////
00754 void GraphicsWindow::
00755 close_window() {
00756   display_cat.info()
00757     << "Closing " << get_type() << "\n";
00758 
00759   // Tell our parent window (if any) that we're no longer its child.
00760   if (_window_handle != (WindowHandle *)NULL &&
00761       _parent_window_handle != (WindowHandle *)NULL) {
00762     _parent_window_handle->detach_child(_window_handle);
00763   }
00764 
00765   _window_handle = NULL;
00766   _parent_window_handle = NULL;
00767   _is_valid = false;
00768 }
00769 
00770 ////////////////////////////////////////////////////////////////////
00771 //     Function: GraphicsWindow::open_window
00772 //       Access: Protected, Virtual
00773 //  Description: Opens the window right now.  Called from the window
00774 //               thread.  Returns true if the window is successfully
00775 //               opened, or false if there was a problem.
00776 ////////////////////////////////////////////////////////////////////
00777 bool GraphicsWindow::
00778 open_window() {
00779   return false;
00780 }
00781 
00782 ////////////////////////////////////////////////////////////////////
00783 //     Function: GraphicsWindow::reset_window
00784 //       Access: Protected, Virtual
00785 //  Description: resets the window framebuffer from its derived
00786 //               children. Does nothing here.
00787 ////////////////////////////////////////////////////////////////////
00788 void GraphicsWindow::
00789 reset_window(bool swapchain) {
00790   display_cat.info()
00791     << "Resetting " << get_type() << "\n";
00792 }
00793 
00794 ////////////////////////////////////////////////////////////////////
00795 //     Function: GraphicsWindow::do_reshape_request
00796 //       Access: Protected, Virtual
00797 //  Description: Called from the window thread in response to a request
00798 //               from within the code (via request_properties()) to
00799 //               change the size and/or position of the window.
00800 //               Returns true if the window is successfully changed,
00801 //               or false if there was a problem.
00802 ////////////////////////////////////////////////////////////////////
00803 bool GraphicsWindow::
00804 do_reshape_request(int x_origin, int y_origin, bool has_origin,
00805                    int x_size, int y_size) {
00806   return false;
00807 }
00808 
00809 ////////////////////////////////////////////////////////////////////
00810 //     Function: GraphicsWindow::system_changed_properties
00811 //       Access: Protected
00812 //  Description: Should be called (from within the window thread) when
00813 //               process_events() detects an external change in some
00814 //               important window property; for instance, when the
00815 //               user resizes the window.
00816 ////////////////////////////////////////////////////////////////////
00817 void GraphicsWindow::
00818 system_changed_properties(const WindowProperties &properties) {
00819   if (display_cat.is_debug()) {
00820     display_cat.debug()
00821       << "system_changed_properties(" << properties << ")\n";
00822   }
00823 
00824   LightReMutexHolder holder(_properties_lock);
00825 
00826   if (properties.has_size()) {
00827     system_changed_size(properties.get_x_size(), properties.get_y_size());
00828   }
00829 
00830   WindowProperties old_properties = _properties;
00831   _properties.add_properties(properties);
00832   if (_properties != old_properties) {
00833     throw_event(_window_event, this);
00834   }
00835 }
00836 
00837 ////////////////////////////////////////////////////////////////////
00838 //     Function: GraphicsWindow::system_changed_size
00839 //       Access: Protected
00840 //  Description: An internal function to update all the DisplayRegions
00841 //               with the new size of the window.  This should always
00842 //               be called before changing the _size members of the
00843 //               _properties structure.
00844 ////////////////////////////////////////////////////////////////////
00845 void GraphicsWindow::
00846 system_changed_size(int x_size, int y_size) {
00847   if (display_cat.is_debug()) {
00848     display_cat.debug()
00849       << "system_changed_size(" << x_size << ", " << y_size << ")\n";
00850   }
00851   
00852   if (!_properties.has_size() || (x_size != _properties.get_x_size() || 
00853                                   y_size != _properties.get_y_size())) {
00854     set_size_and_recalc(x_size, y_size);
00855   }
00856 }
00857 
00858 ////////////////////////////////////////////////////////////////////
00859 //     Function: GraphicsWindow::add_input_device
00860 //       Access: Protected
00861 //  Description: Adds a GraphicsWindowInputDevice to the vector.
00862 //               Returns the index of the new device.
00863 ////////////////////////////////////////////////////////////////////
00864 int GraphicsWindow::
00865 add_input_device(const GraphicsWindowInputDevice &device) {
00866   LightMutexHolder holder(_input_lock);
00867   int index = (int)_input_devices.size();
00868   _input_devices.push_back(device);
00869   _input_devices.back().set_device_index(index);
00870   return index;
00871 }
00872 
00873 ////////////////////////////////////////////////////////////////////
00874 //     Function: GraphicsWindow::mouse_mode_relative
00875 //       Access: Protected, Virtual
00876 //  Description: detaches mouse. Only mouse delta from now on. 
00877 //               
00878 ////////////////////////////////////////////////////////////////////
00879 void GraphicsWindow::
00880 mouse_mode_relative() {
00881 }
00882 
00883 ////////////////////////////////////////////////////////////////////
00884 //     Function: GraphicsWindow::mouse_mode_absolute
00885 //       Access: Protected, Virtual
00886 //  Description: reattaches mouse to location
00887 //               
00888 ////////////////////////////////////////////////////////////////////
00889 void GraphicsWindow::
00890 mouse_mode_absolute() {
00891 
00892 }
00893 
00894 #ifdef HAVE_PYTHON
00895 
00896 ////////////////////////////////////////////////////////////////////
00897 //     Function: GraphicsWindow::add_custom_event_handler
00898 //       Access: Published
00899 //  Description: Adds a python event handler to be called
00900 //               when a window event occurs.
00901 //               
00902 ////////////////////////////////////////////////////////////////////
00903 void GraphicsWindow::
00904 add_python_event_handler(PyObject* handler, PyObject* name){
00905   PythonGraphicsWindowProc* pgwp = new PythonGraphicsWindowProc(handler, name);
00906   _python_window_proc_classes.insert(pgwp);
00907   add_window_proc(pgwp);
00908 }
00909 
00910 ////////////////////////////////////////////////////////////////////
00911 //     Function: GraphicsWindow::remove_custom_event_handler
00912 //       Access: Published
00913 //  Description: Removes the specified python event handler.
00914 //               
00915 ////////////////////////////////////////////////////////////////////
00916 void GraphicsWindow::
00917 remove_python_event_handler(PyObject* name){
00918   list<PythonGraphicsWindowProc*> toRemove;
00919   PythonWinProcClasses::iterator iter;
00920   for(iter = _python_window_proc_classes.begin(); iter != _python_window_proc_classes.end(); ++iter){
00921     PythonGraphicsWindowProc* pgwp = *iter;
00922     if(PyObject_Compare(pgwp->get_name(), name) == 0)
00923       toRemove.push_back(pgwp);
00924   }
00925   list<PythonGraphicsWindowProc*>::iterator iter2;
00926   for(iter2 = toRemove.begin(); iter2 != toRemove.end(); ++iter2){
00927     PythonGraphicsWindowProc* pgwp = *iter2;
00928     remove_window_proc(pgwp);
00929     _python_window_proc_classes.erase(pgwp);
00930     delete pgwp;
00931   }
00932 }
00933 
00934 #endif // HAVE_PYTHON
00935 
00936 ////////////////////////////////////////////////////////////////////
00937 //     Function: GraphicsWindow::is_touch_event
00938 //       Access: Published, Virtual
00939 //  Description: Returns whether the specified event msg is a touch message.
00940 //               
00941 ////////////////////////////////////////////////////////////////////
00942 bool GraphicsWindow::
00943 is_touch_event(GraphicsWindowProcCallbackData* callbackData){
00944   return false;
00945 }
00946 
00947 ////////////////////////////////////////////////////////////////////
00948 //     Function: GraphicsWindow::get_num_touches
00949 //       Access: Published, Virtual
00950 //  Description: Returns the current number of touches on this window.
00951 //               
00952 ////////////////////////////////////////////////////////////////////
00953 int GraphicsWindow::
00954 get_num_touches(){
00955   return 0;
00956 }
00957 
00958 ////////////////////////////////////////////////////////////////////
00959 //     Function: GraphicsWindow::get_touch_info
00960 //       Access: Published, Virtual
00961 //  Description: Returns the TouchInfo object describing the specified touch.
00962 //               
00963 ////////////////////////////////////////////////////////////////////
00964 TouchInfo GraphicsWindow::
00965 get_touch_info(int index){
00966   return TouchInfo();
00967 }
00968 
00969 ////////////////////////////////////////////////////////////////////
00970 //     Function: GraphicsWindow::supports_window_procs
00971 //       Access: Published, Virtual
00972 //  Description: Returns whether this window supports adding of Windows proc handlers.
00973 //               
00974 ////////////////////////////////////////////////////////////////////
00975 bool GraphicsWindow::supports_window_procs() const{
00976   return false;
00977 }
 All Classes Functions Variables Enumerations