Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/glxdisplay/glxGraphicsWindow.cxx

Go to the documentation of this file.
00001 // Filename: glxGraphicsWindow.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "glxGraphicsWindow.h"
00020 #include "glxGraphicsStateGuardian.h"
00021 #include "config_glxdisplay.h"
00022 #include "glxGraphicsPipe.h"
00023 
00024 #include "graphicsPipe.h"
00025 #include "keyboardButton.h"
00026 #include "mouseButton.h"
00027 #include "glGraphicsStateGuardian.h"
00028 #include "clockObject.h"
00029 
00030 #include <errno.h>
00031 #include <sys/time.h>
00032 #include <X11/keysym.h>
00033 #include <X11/Xutil.h>
00034 
00035 TypeHandle glxGraphicsWindow::_type_handle;
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: glxGraphicsWindow::Constructor
00039 //       Access: Public
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 glxGraphicsWindow::
00043 glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
00044   GraphicsWindow(pipe, gsg) 
00045 {
00046   glxGraphicsPipe *glx_pipe;
00047   DCAST_INTO_V(glx_pipe, _pipe);
00048   _display = glx_pipe->get_display();
00049   _screen = glx_pipe->get_screen();
00050   _xwindow = (Window)NULL;
00051   _awaiting_configure = false;
00052   _wm_delete_window = glx_pipe->get_wm_delete_window();
00053 
00054   GraphicsWindowInputDevice device =
00055     GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
00056   _input_devices.push_back(device);
00057 }
00058 
00059 ////////////////////////////////////////////////////////////////////
00060 //     Function: glxGraphicsWindow::Destructor
00061 //       Access: Public, Virtual
00062 //  Description:
00063 ////////////////////////////////////////////////////////////////////
00064 glxGraphicsWindow::
00065 ~glxGraphicsWindow() {
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: glxGraphicsWindow::make_current
00070 //       Access: Public, Virtual
00071 //  Description: This function will be called within the draw thread
00072 //               during begin_frame() to ensure the graphics context
00073 //               is ready for drawing.
00074 ////////////////////////////////////////////////////////////////////
00075 void glxGraphicsWindow::
00076 make_current() {
00077   glxGraphicsStateGuardian *glxgsg;
00078   DCAST_INTO_V(glxgsg, _gsg);
00079   glXMakeCurrent(_display, _xwindow, glxgsg->_context);
00080 
00081   // Now that we have made the context current to a window, we can
00082   // reset the GSG state if this is the first time it has been used.
00083   // (We can't just call reset() when we construct the GSG, because
00084   // reset() requires having a current context.)
00085   glxgsg->reset_if_new();
00086 }
00087 
00088 ////////////////////////////////////////////////////////////////////
00089 //     Function: glxGraphicsWindow::release_gsg
00090 //       Access: Public
00091 //  Description: Releases the current GSG pointer, if it is currently
00092 //               held, and resets the GSG to NULL.  The window will be
00093 //               permanently unable to render; this is normally called
00094 //               only just before destroying the window.  This should
00095 //               only be called from within the draw thread.
00096 ////////////////////////////////////////////////////////////////////
00097 void glxGraphicsWindow::
00098 release_gsg() {
00099   glXMakeCurrent(_display, None, NULL);
00100   GraphicsWindow::release_gsg();
00101 }
00102 
00103 ////////////////////////////////////////////////////////////////////
00104 //     Function: glxGraphicsWindow::begin_frame
00105 //       Access: Public, Virtual
00106 //  Description: This function will be called within the draw thread
00107 //               before beginning rendering for a given frame.  It
00108 //               should do whatever setup is required, and return true
00109 //               if the frame should be rendered, or false if it
00110 //               should be skipped.
00111 ////////////////////////////////////////////////////////////////////
00112 bool glxGraphicsWindow::
00113 begin_frame() {
00114   if (_awaiting_configure) {
00115     // Don't attempt to draw while we have just reconfigured the
00116     // window and we haven't got the notification back yet.
00117     return false;
00118   }
00119 
00120   return GraphicsWindow::begin_frame();
00121 }
00122 
00123 ////////////////////////////////////////////////////////////////////
00124 //     Function: glxGraphicsWindow::begin_flip
00125 //       Access: Public, Virtual
00126 //  Description: This function will be called within the draw thread
00127 //               after end_frame() has been called on all windows, to
00128 //               initiate the exchange of the front and back buffers.
00129 //
00130 //               This should instruct the window to prepare for the
00131 //               flip at the next video sync, but it should not wait.
00132 //
00133 //               We have the two separate functions, begin_flip() and
00134 //               end_flip(), to make it easier to flip all of the
00135 //               windows at the same time.
00136 ////////////////////////////////////////////////////////////////////
00137 void glxGraphicsWindow::
00138 begin_flip() {
00139   if (_gsg != (GraphicsStateGuardian *)NULL) {
00140     make_current();
00141     glXSwapBuffers(_display, _xwindow);
00142   }
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: glxGraphicsWindow::process_events
00147 //       Access: Public, Virtual
00148 //  Description: Do whatever processing is necessary to ensure that
00149 //               the window responds to user events.  Also, honor any
00150 //               requests recently made via request_properties()
00151 //
00152 //               This function is called only within the window
00153 //               thread.
00154 ////////////////////////////////////////////////////////////////////
00155 void glxGraphicsWindow::
00156 process_events() {
00157   GraphicsWindow::process_events();
00158 
00159   if (_xwindow == (Window)0) {
00160     return;
00161   }
00162 
00163   XEvent event;
00164   while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
00165     WindowProperties properties;
00166     ButtonHandle button;
00167 
00168     switch (event.type) {
00169     case ReparentNotify:
00170       break;
00171 
00172     case ConfigureNotify:
00173       _awaiting_configure = false;
00174       properties.set_size(event.xconfigure.width, event.xconfigure.height);
00175       system_changed_properties(properties);
00176       break;
00177 
00178     case ButtonPress:
00179       // This refers to the mouse buttons.
00180       button = MouseButton::button(event.xbutton.button - 1);
00181       _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
00182       _input_devices[0].button_down(button);
00183       break;
00184       
00185     case ButtonRelease:
00186       button = MouseButton::button(event.xbutton.button - 1);
00187       _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
00188       _input_devices[0].button_up(button);
00189       break;
00190 
00191     case MotionNotify:
00192       _input_devices[0].set_pointer_in_window(event.xmotion.x, event.xmotion.y);
00193       break;
00194 
00195     case KeyPress:
00196       {
00197         _input_devices[0].set_pointer_in_window(event.xkey.x, event.xkey.y);
00198         int index = ((event.xkey.state & ShiftMask) != 0) ? 1 : 0;
00199 
00200         // First, get the keystroke, as modified by the shift key.
00201         KeySym key = XLookupKeysym(&event.xkey, index);
00202         if (key > 0 && key < 128) {
00203           // If it's an ASCII key, press it.
00204           _input_devices[0].keystroke(key);
00205         }
00206 
00207         // Now get the raw unshifted button.
00208         ButtonHandle button = get_button(&event.xkey);
00209         if (button != ButtonHandle::none()) {
00210           _input_devices[0].button_down(button);
00211         }
00212       }
00213       break;
00214 
00215     case KeyRelease:
00216       button = get_button(&event.xkey);
00217       if (button != ButtonHandle::none()) {
00218         _input_devices[0].button_up(button);
00219       }
00220       break;
00221 
00222     case EnterNotify:
00223       _input_devices[0].set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
00224       break;
00225 
00226     case LeaveNotify:
00227       _input_devices[0].set_pointer_out_of_window();
00228       break;
00229 
00230     case FocusIn:
00231       properties.set_foreground(true);
00232       system_changed_properties(properties);
00233       break;
00234 
00235     case FocusOut:
00236       properties.set_foreground(false);
00237       system_changed_properties(properties);
00238       break;
00239 
00240     case UnmapNotify:
00241       properties.set_minimized(true);
00242       system_changed_properties(properties);
00243       break;
00244 
00245     case MapNotify:
00246       properties.set_minimized(false);
00247       system_changed_properties(properties);
00248       break;
00249 
00250     case ClientMessage:
00251       if (event.xclient.data.l[0] == _wm_delete_window) {
00252         // This is a message from the window manager indicating that
00253         // the user has requested to close the window.  Honor the
00254         // request.
00255         // TODO: don't call release_gsg() in the window thread.
00256         release_gsg();
00257         close_window();
00258         properties.set_open(false);
00259         system_changed_properties(properties);
00260       }
00261       break;
00262 
00263     case DestroyNotify:
00264       // Apparently, we never get a DestroyNotify on a toplevel
00265       // window.  Instead, we rely on hints from the window manager
00266       // (see above).
00267       glxdisplay_cat.info()
00268         << "DestroyNotify\n";
00269       break;
00270 
00271     default:
00272       glxdisplay_cat.error()
00273         << "unhandled X event type " << event.type << "\n";
00274     }
00275   }
00276 }
00277 
00278 ////////////////////////////////////////////////////////////////////
00279 //     Function: glxGraphicsWindow::set_properties_now
00280 //       Access: Public, Virtual
00281 //  Description: Applies the requested set of properties to the
00282 //               window, if possible, for instance to request a change
00283 //               in size or minimization status.
00284 //
00285 //               The window properties are applied immediately, rather
00286 //               than waiting until the next frame.  This implies that
00287 //               this method may *only* be called from within the
00288 //               window thread.
00289 //
00290 //               The return value is true if the properties are set,
00291 //               false if they are ignored.  This is mainly useful for
00292 //               derived classes to implement extensions to this
00293 //               function.
00294 ////////////////////////////////////////////////////////////////////
00295 void glxGraphicsWindow::
00296 set_properties_now(WindowProperties &properties) {
00297   GraphicsWindow::set_properties_now(properties);
00298   if (!properties.is_any_specified()) {
00299     // The base class has already handled this case.
00300     return;
00301   }
00302 
00303   // The window is already open; we are limited to what we can change
00304   // on the fly.
00305 
00306   // The window title may be changed by issuing another hint request.
00307   // Assume this will be honored.
00308   if (properties.has_title()) {
00309     WindowProperties wm_properties;
00310     wm_properties.set_title(properties.get_title());
00311     _properties.set_title(properties.get_title());
00312     set_wm_properties(wm_properties);
00313     properties.clear_title();
00314   }
00315 
00316   // The size and position of an already-open window are changed via
00317   // explicit X calls.  These may still get intercepted by the window
00318   // manager.  Rather than changing _properties immediately, we'll
00319   // wait for the ConfigureNotify message to come back.
00320   XWindowChanges changes;
00321   int value_mask = 0;
00322 
00323   if (properties.has_origin()) {
00324     changes.x = properties.get_x_origin();
00325     changes.y = properties.get_y_origin();
00326     value_mask |= (CWX | CWY);
00327     properties.clear_origin();
00328   }
00329   if (properties.has_size()) {
00330     changes.width = properties.get_x_size();
00331     changes.height = properties.get_y_size();
00332     value_mask |= (CWWidth | CWHeight);
00333     properties.clear_size();
00334   }
00335 
00336   if (value_mask != 0) {
00337     XConfigureWindow(_display, _xwindow, value_mask, &changes);
00338 
00339     // Don't draw anything until this is done reconfiguring.
00340     _awaiting_configure = true;
00341   }
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: glxGraphicsWindow::close_window
00346 //       Access: Protected, Virtual
00347 //  Description: Closes the window right now.  Called from the window
00348 //               thread.
00349 ////////////////////////////////////////////////////////////////////
00350 void glxGraphicsWindow::
00351 close_window() {
00352   if (_xwindow != (Window)NULL) {
00353     XDestroyWindow(_display, _xwindow);
00354     _xwindow = (Window)0;
00355 
00356     // This may be necessary if we just closed the last X window in an
00357     // application, so the server hears the close request.
00358     XFlush(_display);
00359   }
00360 }
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: glxGraphicsWindow::open_window
00364 //       Access: Protected, Virtual
00365 //  Description: Opens the window right now.  Called from the window
00366 //               thread.  Returns true if the window is successfully
00367 //               opened, or false if there was a problem.
00368 ////////////////////////////////////////////////////////////////////
00369 bool glxGraphicsWindow::
00370 open_window() {
00371   if (_properties.get_fullscreen()) {
00372     // We don't support fullscreen windows.
00373     return false;
00374   }
00375 
00376   if (!_properties.has_origin()) {
00377     _properties.set_origin(0, 0);
00378   }
00379   if (!_properties.has_size()) {
00380     _properties.set_size(100, 100);
00381   }
00382 
00383   glxGraphicsPipe *glx_pipe;
00384   DCAST_INTO_R(glx_pipe, _pipe, false);
00385   glxGraphicsStateGuardian *glxgsg;
00386   DCAST_INTO_R(glxgsg, _gsg, false);
00387 
00388   Window root_window = glx_pipe->get_root();
00389 
00390   setup_colormap(glxgsg->_visual);
00391 
00392   _event_mask =
00393     ButtonPressMask | ButtonReleaseMask |
00394     KeyPressMask | KeyReleaseMask |
00395     EnterWindowMask | LeaveWindowMask |
00396     PointerMotionMask |
00397     FocusChangeMask |
00398     StructureNotifyMask;
00399 
00400   // Initialize window attributes
00401   XSetWindowAttributes wa;
00402   wa.background_pixel = XBlackPixel(_display, _screen);
00403   wa.border_pixel = 0;
00404   wa.colormap = _colormap;
00405   wa.event_mask = _event_mask;
00406 
00407   unsigned long attrib_mask = 
00408     CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00409 
00410   _xwindow = XCreateWindow
00411     (_display, root_window,
00412      _properties.get_x_origin(), _properties.get_y_origin(),
00413      _properties.get_x_size(), _properties.get_y_size(),
00414      0,
00415      glxgsg->_visual->depth, InputOutput, glxgsg->_visual->visual, 
00416      attrib_mask, &wa);
00417 
00418   if (_xwindow == (Window)0) {
00419     glxdisplay_cat.error()
00420       << "failed to create X window.\n";
00421     return false;
00422   }
00423   set_wm_properties(_properties);
00424 
00425   XMapWindow(_display, _xwindow);
00426 
00427   return true;
00428 }
00429 
00430 ////////////////////////////////////////////////////////////////////
00431 //     Function: glxGraphicsWindow::set_wm_properties
00432 //       Access: Private
00433 //  Description: Asks the window manager to set the appropriate
00434 //               properties.  In X, these properties cannot be
00435 //               specified directly by the application; they must be
00436 //               requested via the window manager, which may or may
00437 //               not choose to honor the request.
00438 ////////////////////////////////////////////////////////////////////
00439 void glxGraphicsWindow::
00440 set_wm_properties(const WindowProperties &properties) {
00441   // Name the window if there is a name
00442   XTextProperty window_name;
00443   XTextProperty *window_name_p = (XTextProperty *)NULL;
00444   if (properties.has_title()) {
00445     char *name = (char *)properties.get_title().c_str();
00446     if (XStringListToTextProperty(&name, 1, &window_name) != 0) {
00447       window_name_p = &window_name;
00448     }
00449   }
00450 
00451   // The size hints request a window of a particular size and/or a
00452   // particular placement onscreen.
00453   XSizeHints *size_hints_p = NULL;
00454   if (properties.has_origin() || properties.has_size()) {
00455     size_hints_p = XAllocSizeHints();
00456     if (size_hints_p != (XSizeHints *)NULL) {
00457       if (properties.has_origin()) {
00458         size_hints_p->x = properties.get_x_origin();
00459         size_hints_p->y = properties.get_y_origin();
00460         size_hints_p->flags |= USPosition;
00461       }
00462       if (properties.has_size()) {
00463         size_hints_p->width = properties.get_x_size();
00464         size_hints_p->height = properties.get_y_size();
00465         size_hints_p->flags |= USSize;
00466       }
00467     }
00468   }
00469 
00470   // The window manager hints include requests to the window manager
00471   // other than those specific to window geometry.
00472   XWMHints *wm_hints_p = NULL;
00473   wm_hints_p = XAllocWMHints();
00474   if (wm_hints_p != (XWMHints *)NULL) {
00475     if (properties.has_minimized() && properties.get_minimized()) {
00476       wm_hints_p->initial_state = IconicState;
00477     } else {
00478       wm_hints_p->initial_state = NormalState;
00479     }
00480     wm_hints_p->flags = StateHint;
00481   }
00482 
00483   // If we asked for a window without a border, there's no good way to
00484   // arrange that.  It completely depends on the user's window manager
00485   // of choice.  Instead, we'll totally punt and just set the window's
00486   // Class to "Undecorated", and let the user configure his/her window
00487   // manager not to put a border around windows of this class.
00488   XClassHint *class_hints_p = NULL;
00489   if (properties.get_undecorated()) {
00490     class_hints_p = XAllocClassHint();
00491     class_hints_p->res_class = "Undecorated";
00492   }
00493 
00494   XSetWMProperties(_display, _xwindow, window_name_p, window_name_p,
00495                    NULL, 0, size_hints_p, wm_hints_p, class_hints_p);
00496 
00497   if (size_hints_p != (XSizeHints *)NULL) {
00498     XFree(size_hints_p);
00499   }
00500   if (wm_hints_p != (XWMHints *)NULL) {
00501     XFree(wm_hints_p);
00502   }
00503   if (class_hints_p != (XClassHint *)NULL) {
00504     XFree(class_hints_p);
00505   }
00506 
00507   // Also, indicate to the window manager that we'd like to get a
00508   // chance to close our windows cleanly, rather than being rudely
00509   // disconnected from the X server if the user requests a window
00510   // close.
00511   Atom protocols[] = {
00512     _wm_delete_window,
00513   };
00514 
00515   XSetWMProtocols(_display, _xwindow, protocols, 
00516                   sizeof(protocols) / sizeof(Atom));
00517 }
00518 
00519 ////////////////////////////////////////////////////////////////////
00520 //     Function: glxGraphicsWindow::setup_colormap
00521 //       Access: Private
00522 //  Description: Allocates a colormap appropriate to the visual and
00523 //               stores in in the _colormap method.
00524 ////////////////////////////////////////////////////////////////////
00525 void glxGraphicsWindow::
00526 setup_colormap(XVisualInfo *visual) {
00527   glxGraphicsPipe *glx_pipe;
00528   DCAST_INTO_V(glx_pipe, _pipe);
00529   Window root_window = glx_pipe->get_root();
00530 
00531   int visual_class = visual->c_class;
00532   int rc, is_rgb;
00533 
00534   switch (visual_class) {
00535     case PseudoColor:
00536       rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb);
00537       if (rc == 0 && is_rgb) {
00538         glxdisplay_cat.warning()
00539           << "mesa pseudocolor not supported.\n";
00540         // this is a terrible terrible hack, but it seems to work
00541         _colormap = (Colormap)0;
00542 
00543       } else {
00544         _colormap = XCreateColormap(_display, root_window,
00545                                     visual->visual, AllocAll);
00546       }
00547       break;
00548     case TrueColor:
00549     case DirectColor:
00550       _colormap = XCreateColormap(_display, root_window,
00551                                   visual->visual, AllocNone);
00552       break;
00553     case StaticColor:
00554     case StaticGray:
00555     case GrayScale:
00556       _colormap = XCreateColormap(_display, root_window,
00557                                   visual->visual, AllocNone);
00558       break;
00559     default:
00560       glxdisplay_cat.error()
00561         << "Could not allocate a colormap for visual class "
00562         << visual_class << ".\n";
00563       break;
00564   }
00565 }
00566 
00567 ////////////////////////////////////////////////////////////////////
00568 //     Function: glxGraphicsWindow::get_button
00569 //       Access: Private
00570 //  Description: Returns the Panda ButtonHandle corresponding to the
00571 //               keyboard button indicated by the given key event.
00572 ////////////////////////////////////////////////////////////////////
00573 ButtonHandle glxGraphicsWindow::
00574 get_button(XKeyEvent *key_event) {
00575   KeySym key = XLookupKeysym(key_event, 0);
00576 
00577   switch (key) {
00578   case XK_BackSpace:
00579     return KeyboardButton::backspace();
00580   case XK_Tab:
00581     return KeyboardButton::tab();
00582   case XK_Return:
00583     return KeyboardButton::enter();
00584   case XK_Escape:
00585     return KeyboardButton::escape();
00586   case XK_space:
00587     return KeyboardButton::space();
00588   case XK_exclam:
00589     return KeyboardButton::ascii_key('!');
00590   case XK_quotedbl:
00591     return KeyboardButton::ascii_key('"');
00592   case XK_numbersign:
00593     return KeyboardButton::ascii_key('#');
00594   case XK_dollar:
00595     return KeyboardButton::ascii_key('$');
00596   case XK_percent:
00597     return KeyboardButton::ascii_key('%');
00598   case XK_ampersand:
00599     return KeyboardButton::ascii_key('&');
00600   case XK_apostrophe: // == XK_quoteright
00601     return KeyboardButton::ascii_key('\'');
00602   case XK_parenleft:
00603     return KeyboardButton::ascii_key('(');
00604   case XK_parenright:
00605     return KeyboardButton::ascii_key(')');
00606   case XK_asterisk:
00607     return KeyboardButton::ascii_key('*');
00608   case XK_plus:
00609     return KeyboardButton::ascii_key('+');
00610   case XK_comma:
00611     return KeyboardButton::ascii_key(',');
00612   case XK_minus:
00613     return KeyboardButton::ascii_key('-');
00614   case XK_period:
00615     return KeyboardButton::ascii_key('.');
00616   case XK_slash:
00617     return KeyboardButton::ascii_key('/');
00618   case XK_0:
00619     return KeyboardButton::ascii_key('0');
00620   case XK_1:
00621     return KeyboardButton::ascii_key('1');
00622   case XK_2:
00623     return KeyboardButton::ascii_key('2');
00624   case XK_3:
00625     return KeyboardButton::ascii_key('3');
00626   case XK_4:
00627     return KeyboardButton::ascii_key('4');
00628   case XK_5:
00629     return KeyboardButton::ascii_key('5');
00630   case XK_6:
00631     return KeyboardButton::ascii_key('6');
00632   case XK_7:
00633     return KeyboardButton::ascii_key('7');
00634   case XK_8:
00635     return KeyboardButton::ascii_key('8');
00636   case XK_9:
00637     return KeyboardButton::ascii_key('9');
00638   case XK_colon:
00639     return KeyboardButton::ascii_key(':');
00640   case XK_semicolon:
00641     return KeyboardButton::ascii_key(';');
00642   case XK_less:
00643     return KeyboardButton::ascii_key('<');
00644   case XK_equal:
00645     return KeyboardButton::ascii_key('=');
00646   case XK_greater:
00647     return KeyboardButton::ascii_key('>');
00648   case XK_question:
00649     return KeyboardButton::ascii_key('?');
00650   case XK_at:
00651     return KeyboardButton::ascii_key('@');
00652   case XK_A:
00653     return KeyboardButton::ascii_key('A');
00654   case XK_B:
00655     return KeyboardButton::ascii_key('B');
00656   case XK_C:
00657     return KeyboardButton::ascii_key('C');
00658   case XK_D:
00659     return KeyboardButton::ascii_key('D');
00660   case XK_E:
00661     return KeyboardButton::ascii_key('E');
00662   case XK_F:
00663     return KeyboardButton::ascii_key('F');
00664   case XK_G:
00665     return KeyboardButton::ascii_key('G');
00666   case XK_H:
00667     return KeyboardButton::ascii_key('H');
00668   case XK_I:
00669     return KeyboardButton::ascii_key('I');
00670   case XK_J:
00671     return KeyboardButton::ascii_key('J');
00672   case XK_K:
00673     return KeyboardButton::ascii_key('K');
00674   case XK_L:
00675     return KeyboardButton::ascii_key('L');
00676   case XK_M:
00677     return KeyboardButton::ascii_key('M');
00678   case XK_N:
00679     return KeyboardButton::ascii_key('N');
00680   case XK_O:
00681     return KeyboardButton::ascii_key('O');
00682   case XK_P:
00683     return KeyboardButton::ascii_key('P');
00684   case XK_Q:
00685     return KeyboardButton::ascii_key('Q');
00686   case XK_R:
00687     return KeyboardButton::ascii_key('R');
00688   case XK_S:
00689     return KeyboardButton::ascii_key('S');
00690   case XK_T:
00691     return KeyboardButton::ascii_key('T');
00692   case XK_U:
00693     return KeyboardButton::ascii_key('U');
00694   case XK_V:
00695     return KeyboardButton::ascii_key('V');
00696   case XK_W:
00697     return KeyboardButton::ascii_key('W');
00698   case XK_X:
00699     return KeyboardButton::ascii_key('X');
00700   case XK_Y:
00701     return KeyboardButton::ascii_key('Y');
00702   case XK_Z:
00703     return KeyboardButton::ascii_key('Z');
00704   case XK_bracketleft:
00705     return KeyboardButton::ascii_key('[');
00706   case XK_backslash:
00707     return KeyboardButton::ascii_key('\\');
00708   case XK_bracketright:
00709     return KeyboardButton::ascii_key(']');
00710   case XK_asciicircum:
00711     return KeyboardButton::ascii_key('^');
00712   case XK_underscore:
00713     return KeyboardButton::ascii_key('_');
00714   case XK_grave: // == XK_quoteleft
00715     return KeyboardButton::ascii_key('`');
00716   case XK_a:
00717     return KeyboardButton::ascii_key('a');
00718   case XK_b:
00719     return KeyboardButton::ascii_key('b');
00720   case XK_c:
00721     return KeyboardButton::ascii_key('c');
00722   case XK_d:
00723     return KeyboardButton::ascii_key('d');
00724   case XK_e:
00725     return KeyboardButton::ascii_key('e');
00726   case XK_f:
00727     return KeyboardButton::ascii_key('f');
00728   case XK_g:
00729     return KeyboardButton::ascii_key('g');
00730   case XK_h:
00731     return KeyboardButton::ascii_key('h');
00732   case XK_i:
00733     return KeyboardButton::ascii_key('i');
00734   case XK_j:
00735     return KeyboardButton::ascii_key('j');
00736   case XK_k:
00737     return KeyboardButton::ascii_key('k');
00738   case XK_l:
00739     return KeyboardButton::ascii_key('l');
00740   case XK_m:
00741     return KeyboardButton::ascii_key('m');
00742   case XK_n:
00743     return KeyboardButton::ascii_key('n');
00744   case XK_o:
00745     return KeyboardButton::ascii_key('o');
00746   case XK_p:
00747     return KeyboardButton::ascii_key('p');
00748   case XK_q:
00749     return KeyboardButton::ascii_key('q');
00750   case XK_r:
00751     return KeyboardButton::ascii_key('r');
00752   case XK_s:
00753     return KeyboardButton::ascii_key('s');
00754   case XK_t:
00755     return KeyboardButton::ascii_key('t');
00756   case XK_u:
00757     return KeyboardButton::ascii_key('u');
00758   case XK_v:
00759     return KeyboardButton::ascii_key('v');
00760   case XK_w:
00761     return KeyboardButton::ascii_key('w');
00762   case XK_x:
00763     return KeyboardButton::ascii_key('x');
00764   case XK_y:
00765     return KeyboardButton::ascii_key('y');
00766   case XK_z:
00767     return KeyboardButton::ascii_key('z');
00768   case XK_braceleft:
00769     return KeyboardButton::ascii_key('{');
00770   case XK_bar:
00771     return KeyboardButton::ascii_key('|');
00772   case XK_braceright:
00773     return KeyboardButton::ascii_key('}');
00774   case XK_asciitilde:
00775     return KeyboardButton::ascii_key('~');
00776   case XK_F1:
00777     return KeyboardButton::f1();
00778   case XK_F2:
00779     return KeyboardButton::f2();
00780   case XK_F3:
00781     return KeyboardButton::f3();
00782   case XK_F4:
00783     return KeyboardButton::f4();
00784   case XK_F5:
00785     return KeyboardButton::f5();
00786   case XK_F6:
00787     return KeyboardButton::f6();
00788   case XK_F7:
00789     return KeyboardButton::f7();
00790   case XK_F8:
00791     return KeyboardButton::f8();
00792   case XK_F9:
00793     return KeyboardButton::f9();
00794   case XK_F10:
00795     return KeyboardButton::f10();
00796   case XK_F11:
00797     return KeyboardButton::f11();
00798   case XK_F12:
00799     return KeyboardButton::f12();
00800   case XK_KP_Left:
00801   case XK_Left:
00802     return KeyboardButton::left();
00803   case XK_KP_Up:
00804   case XK_Up:
00805     return KeyboardButton::up();
00806   case XK_KP_Right:
00807   case XK_Right:
00808     return KeyboardButton::right();
00809   case XK_KP_Down:
00810   case XK_Down:
00811     return KeyboardButton::down();
00812   case XK_KP_Prior:
00813   case XK_Prior:
00814     return KeyboardButton::page_up();
00815   case XK_KP_Next:
00816   case XK_Next:
00817     return KeyboardButton::page_down();
00818   case XK_KP_Home:
00819   case XK_Home:
00820     return KeyboardButton::home();
00821   case XK_KP_End:
00822   case XK_End:
00823     return KeyboardButton::end();
00824   case XK_KP_Insert:
00825   case XK_Insert:
00826     return KeyboardButton::insert();
00827   case XK_KP_Delete:
00828   case XK_Delete:
00829     return KeyboardButton::del();
00830   case XK_Shift_L:
00831   case XK_Shift_R:
00832     return KeyboardButton::shift();
00833   case XK_Control_L:
00834   case XK_Control_R:
00835     return KeyboardButton::control();
00836   case XK_Alt_L:
00837   case XK_Alt_R:
00838     return KeyboardButton::alt();
00839   case XK_Meta_L:
00840   case XK_Meta_R:
00841     return KeyboardButton::meta();
00842   case XK_Caps_Lock:
00843     return KeyboardButton::caps_lock();
00844   case XK_Shift_Lock:
00845     return KeyboardButton::shift_lock();
00846   }
00847 
00848   return ButtonHandle::none();
00849 }
00850 
00851 ////////////////////////////////////////////////////////////////////
00852 //     Function: glxGraphicsWindow::check_event
00853 //       Access: Private, Static
00854 //  Description: This function is used as a predicate to
00855 //               XCheckIfEvent() to determine if the indicated queued
00856 //               X event is relevant and should be returned to this
00857 //               window.
00858 ////////////////////////////////////////////////////////////////////
00859 Bool glxGraphicsWindow::
00860 check_event(Display *display, XEvent *event, char *arg) {
00861   const glxGraphicsWindow *self = (glxGraphicsWindow *)arg;
00862 
00863   // We accept any event that is sent to our window.
00864   return (event->xany.window == self->_xwindow);
00865 }

Generated on Fri May 2 00:39:14 2003 for Panda by doxygen1.3