Panda3D

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