00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eglGraphicsWindow.h"
00016 #include "eglGraphicsStateGuardian.h"
00017 #include "config_egldisplay.h"
00018 #include "eglGraphicsPipe.h"
00019
00020 #include "graphicsPipe.h"
00021 #include "keyboardButton.h"
00022 #include "mouseButton.h"
00023 #include "clockObject.h"
00024 #include "pStatTimer.h"
00025 #include "textEncoder.h"
00026 #include "throw_event.h"
00027 #include "lightReMutexHolder.h"
00028 #include "nativeWindowHandle.h"
00029 #include "get_x11.h"
00030
00031 #include <errno.h>
00032 #include <sys/time.h>
00033
00034 #ifdef HAVE_LINUX_INPUT_H
00035 #include <linux/input.h>
00036 #endif
00037
00038 TypeHandle eglGraphicsWindow::_type_handle;
00039
00040 #define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7)))
00041
00042
00043
00044
00045
00046
00047 eglGraphicsWindow::
00048 eglGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
00049 const string &name,
00050 const FrameBufferProperties &fb_prop,
00051 const WindowProperties &win_prop,
00052 int flags,
00053 GraphicsStateGuardian *gsg,
00054 GraphicsOutput *host) :
00055 GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00056 {
00057 eglGraphicsPipe *egl_pipe;
00058 DCAST_INTO_V(egl_pipe, _pipe);
00059 _display = egl_pipe->get_display();
00060 _screen = egl_pipe->get_screen();
00061 _xwindow = (X11_Window)NULL;
00062 _ic = (XIC)NULL;
00063 _egl_display = egl_pipe->_egl_display;
00064 _egl_surface = 0;
00065 _awaiting_configure = false;
00066 _wm_delete_window = egl_pipe->_wm_delete_window;
00067 _net_wm_window_type = egl_pipe->_net_wm_window_type;
00068 _net_wm_window_type_splash = egl_pipe->_net_wm_window_type_splash;
00069 _net_wm_window_type_fullscreen = egl_pipe->_net_wm_window_type_fullscreen;
00070 _net_wm_state = egl_pipe->_net_wm_state;
00071 _net_wm_state_fullscreen = egl_pipe->_net_wm_state_fullscreen;
00072 _net_wm_state_above = egl_pipe->_net_wm_state_above;
00073 _net_wm_state_below = egl_pipe->_net_wm_state_below;
00074 _net_wm_state_add = egl_pipe->_net_wm_state_add;
00075 _net_wm_state_remove = egl_pipe->_net_wm_state_remove;
00076
00077 GraphicsWindowInputDevice device =
00078 GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
00079 add_input_device(device);
00080 }
00081
00082
00083
00084
00085
00086
00087 eglGraphicsWindow::
00088 ~eglGraphicsWindow() {
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 bool eglGraphicsWindow::
00102 move_pointer(int device, int x, int y) {
00103
00104
00105 if (device == 0) {
00106
00107 if (!_properties.get_foreground() ||
00108 !_input_devices[0].get_pointer().get_in_window()) {
00109
00110
00111 return false;
00112 }
00113
00114 const MouseData &md = _input_devices[0].get_pointer();
00115 if (!md.get_in_window() || md.get_x() != x || md.get_y() != y) {
00116 XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y);
00117 _input_devices[0].set_pointer_in_window(x, y);
00118 }
00119 return true;
00120 } else {
00121
00122 if ((device < 1)||(device >= _input_devices.size())) {
00123 return false;
00124 }
00125 _input_devices[device].set_pointer_in_window(x, y);
00126 return true;
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 bool eglGraphicsWindow::
00141 begin_frame(FrameMode mode, Thread *current_thread) {
00142 PStatTimer timer(_make_current_pcollector, current_thread);
00143
00144 begin_frame_spam(mode);
00145 if (_gsg == (GraphicsStateGuardian *)NULL) {
00146 return false;
00147 }
00148 if (_awaiting_configure) {
00149
00150
00151 return false;
00152 }
00153
00154 eglGraphicsStateGuardian *eglgsg;
00155 DCAST_INTO_R(eglgsg, _gsg, false);
00156 {
00157 LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
00158
00159 if (eglGetCurrentDisplay() == _egl_display &&
00160 eglGetCurrentSurface(EGL_READ) == _egl_surface &&
00161 eglGetCurrentSurface(EGL_DRAW) == _egl_surface &&
00162 eglGetCurrentContext() == eglgsg->_context) {
00163
00164
00165 } else {
00166
00167 if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context)) {
00168 egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
00169 << get_egl_error_string(eglGetError()) << "\n";
00170 }
00171 }
00172 }
00173
00174
00175
00176
00177
00178 eglgsg->reset_if_new();
00179
00180 if (mode == FM_render) {
00181
00182 clear_cube_map_selection();
00183 }
00184
00185 _gsg->set_current_properties(&get_fb_properties());
00186 return _gsg->begin_frame(current_thread);
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196 void eglGraphicsWindow::
00197 end_frame(FrameMode mode, Thread *current_thread) {
00198 end_frame_spam(mode);
00199 nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00200
00201 if (mode == FM_render) {
00202
00203 copy_to_textures();
00204 }
00205
00206 _gsg->end_frame(current_thread);
00207
00208 if (mode == FM_render) {
00209 trigger_flip();
00210 clear_cube_map_selection();
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 void eglGraphicsWindow::
00225 end_flip() {
00226 if (_gsg != (GraphicsStateGuardian *)NULL && _flip_ready) {
00227
00228
00229
00230
00231
00232
00233
00234 LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
00235 eglSwapBuffers(_egl_display, _egl_surface);
00236 }
00237 GraphicsWindow::end_flip();
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 void eglGraphicsWindow::
00251 process_events() {
00252 LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
00253
00254 GraphicsWindow::process_events();
00255
00256 if (_xwindow == (X11_Window)0) {
00257 return;
00258 }
00259
00260 poll_raw_mice();
00261
00262 XEvent event;
00263 XKeyEvent keyrelease_event;
00264 bool got_keyrelease_event = false;
00265
00266 while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
00267 if (XFilterEvent(&event, None)) {
00268 continue;
00269 }
00270
00271 if (got_keyrelease_event) {
00272
00273
00274
00275
00276
00277 got_keyrelease_event = false;
00278
00279 if (event.type == KeyPress &&
00280 event.xkey.keycode == keyrelease_event.keycode &&
00281 (event.xkey.time - keyrelease_event.time <= 1)) {
00282
00283
00284 handle_keystroke(event.xkey);
00285
00286
00287
00288 handle_keypress(event.xkey);
00289 continue;
00290
00291 } else {
00292
00293
00294 handle_keyrelease(keyrelease_event);
00295 }
00296 }
00297
00298 WindowProperties properties;
00299 ButtonHandle button;
00300
00301 switch (event.type) {
00302 case ReparentNotify:
00303 break;
00304
00305 case ConfigureNotify:
00306 _awaiting_configure = false;
00307 if (_properties.get_fixed_size()) {
00308
00309
00310
00311
00312
00313
00314 WindowProperties current_props = get_properties();
00315 if (event.xconfigure.width != current_props.get_x_size() ||
00316 event.xconfigure.height != current_props.get_y_size()) {
00317 XWindowChanges changes;
00318 changes.width = current_props.get_x_size();
00319 changes.height = current_props.get_y_size();
00320 int value_mask = (CWWidth | CWHeight);
00321 XConfigureWindow(_display, _xwindow, value_mask, &changes);
00322 }
00323
00324 } else {
00325
00326 properties.set_size(event.xconfigure.width, event.xconfigure.height);
00327 system_changed_properties(properties);
00328 }
00329 break;
00330
00331 case ButtonPress:
00332
00333 button = get_mouse_button(event.xbutton);
00334 _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
00335 _input_devices[0].button_down(button);
00336 break;
00337
00338 case ButtonRelease:
00339 button = get_mouse_button(event.xbutton);
00340 _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
00341 _input_devices[0].button_up(button);
00342 break;
00343
00344 case MotionNotify:
00345 _input_devices[0].set_pointer_in_window(event.xmotion.x, event.xmotion.y);
00346 break;
00347
00348 case KeyPress:
00349 handle_keystroke(event.xkey);
00350 handle_keypress(event.xkey);
00351 break;
00352
00353 case KeyRelease:
00354
00355
00356
00357 keyrelease_event = event.xkey;
00358 got_keyrelease_event = true;
00359 break;
00360
00361 case EnterNotify:
00362 _input_devices[0].set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
00363 break;
00364
00365 case LeaveNotify:
00366 _input_devices[0].set_pointer_out_of_window();
00367 break;
00368
00369 case FocusIn:
00370 properties.set_foreground(true);
00371 system_changed_properties(properties);
00372 break;
00373
00374 case FocusOut:
00375 properties.set_foreground(false);
00376 system_changed_properties(properties);
00377 break;
00378
00379 case UnmapNotify:
00380 properties.set_minimized(true);
00381 system_changed_properties(properties);
00382 break;
00383
00384 case MapNotify:
00385 properties.set_minimized(false);
00386 system_changed_properties(properties);
00387
00388
00389 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
00390 break;
00391
00392 case ClientMessage:
00393 if ((Atom)(event.xclient.data.l[0]) == _wm_delete_window) {
00394
00395
00396 string close_request_event = get_close_request_event();
00397 if (!close_request_event.empty()) {
00398
00399
00400 throw_event(close_request_event);
00401
00402 } else {
00403
00404
00405
00406
00407 close_window();
00408 properties.set_open(false);
00409 system_changed_properties(properties);
00410 }
00411 }
00412 break;
00413
00414 case DestroyNotify:
00415
00416
00417
00418 egldisplay_cat.info()
00419 << "DestroyNotify\n";
00420 break;
00421
00422 default:
00423 egldisplay_cat.error()
00424 << "unhandled X event type " << event.type << "\n";
00425 }
00426 }
00427
00428 if (got_keyrelease_event) {
00429
00430
00431 handle_keyrelease(keyrelease_event);
00432 }
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 void eglGraphicsWindow::
00453 set_properties_now(WindowProperties &properties) {
00454 if (_pipe == (GraphicsPipe *)NULL) {
00455
00456 GraphicsWindow::set_properties_now(properties);
00457 return;
00458 }
00459
00460 eglGraphicsPipe *egl_pipe;
00461 DCAST_INTO_V(egl_pipe, _pipe);
00462
00463
00464
00465
00466
00467
00468 if (properties.get_fullscreen()) {
00469 properties.set_undecorated(true);
00470 properties.set_origin(0, 0);
00471 properties.set_size(egl_pipe->get_display_width(),
00472 egl_pipe->get_display_height());
00473 }
00474
00475 GraphicsWindow::set_properties_now(properties);
00476 if (!properties.is_any_specified()) {
00477
00478 return;
00479 }
00480
00481
00482
00483
00484
00485 WindowProperties wm_properties = _properties;
00486 wm_properties.add_properties(properties);
00487
00488
00489
00490 if (properties.has_title()) {
00491 _properties.set_title(properties.get_title());
00492 properties.clear_title();
00493 }
00494
00495
00496 if (properties.has_fullscreen()) {
00497 _properties.set_fullscreen(properties.get_fullscreen());
00498 properties.clear_fullscreen();
00499 }
00500
00501
00502
00503
00504
00505 XWindowChanges changes;
00506 int value_mask = 0;
00507
00508 if (properties.has_origin()) {
00509 changes.x = properties.get_x_origin();
00510 changes.y = properties.get_y_origin();
00511 value_mask |= (CWX | CWY);
00512 properties.clear_origin();
00513 }
00514 if (properties.has_size()) {
00515 changes.width = properties.get_x_size();
00516 changes.height = properties.get_y_size();
00517 value_mask |= (CWWidth | CWHeight);
00518 properties.clear_size();
00519 }
00520 if (properties.has_z_order()) {
00521
00522
00523
00524
00525 _properties.set_z_order(properties.get_z_order());
00526 switch (properties.get_z_order()) {
00527 case WindowProperties::Z_bottom:
00528 changes.stack_mode = Below;
00529 break;
00530
00531 case WindowProperties::Z_normal:
00532 changes.stack_mode = TopIf;
00533 break;
00534
00535 case WindowProperties::Z_top:
00536 changes.stack_mode = Above;
00537 break;
00538 }
00539
00540 value_mask |= (CWStackMode);
00541 properties.clear_z_order();
00542 }
00543
00544 if (value_mask != 0) {
00545 XReconfigureWMWindow(_display, _xwindow, _screen, value_mask, &changes);
00546
00547
00548 _awaiting_configure = true;
00549 }
00550
00551
00552 if (properties.has_cursor_hidden()) {
00553 _properties.set_cursor_hidden(properties.get_cursor_hidden());
00554 if (properties.get_cursor_hidden()) {
00555 XDefineCursor(_display, _xwindow, egl_pipe->get_hidden_cursor());
00556 } else {
00557 XDefineCursor(_display, _xwindow, None);
00558 }
00559 properties.clear_cursor_hidden();
00560 }
00561
00562 if (properties.has_foreground()) {
00563 if (properties.get_foreground()) {
00564 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
00565 } else {
00566 XSetInputFocus(_display, PointerRoot, RevertToPointerRoot, CurrentTime);
00567 }
00568 properties.clear_foreground();
00569 }
00570
00571 set_wm_properties(wm_properties, true);
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 void eglGraphicsWindow::
00581 close_window() {
00582 if (_gsg != (GraphicsStateGuardian *)NULL) {
00583 if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
00584 egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
00585 << get_egl_error_string(eglGetError()) << "\n";
00586 }
00587 _gsg.clear();
00588 }
00589
00590 if (_ic != (XIC)NULL) {
00591 XDestroyIC(_ic);
00592 _ic = (XIC)NULL;
00593 }
00594
00595 if (_egl_surface != 0) {
00596 if (!eglDestroySurface(_egl_display, _egl_surface)) {
00597 egldisplay_cat.error() << "Failed to destroy surface: "
00598 << get_egl_error_string(eglGetError()) << "\n";
00599 }
00600 }
00601
00602 if (_xwindow != (X11_Window)NULL) {
00603 XDestroyWindow(_display, _xwindow);
00604 _xwindow = (X11_Window)NULL;
00605
00606
00607
00608 XFlush(_display);
00609 }
00610 GraphicsWindow::close_window();
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620 bool eglGraphicsWindow::
00621 open_window() {
00622 eglGraphicsPipe *egl_pipe;
00623 DCAST_INTO_R(egl_pipe, _pipe, false);
00624
00625
00626 eglGraphicsStateGuardian *eglgsg;
00627 if (_gsg == 0) {
00628
00629 eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, NULL);
00630 eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false);
00631 _gsg = eglgsg;
00632 } else {
00633
00634
00635 DCAST_INTO_R(eglgsg, _gsg, false);
00636 if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
00637 eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
00638 eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false);
00639 _gsg = eglgsg;
00640 }
00641 }
00642
00643 XVisualInfo *visual_info = eglgsg->_visual;
00644 if (visual_info == NULL) {
00645
00646 egldisplay_cat.error()
00647 << "No X visual: cannot open window.\n";
00648 return false;
00649 }
00650 Visual *visual = visual_info->visual;
00651 int depth = visual_info->depth;
00652
00653 if (!_properties.has_origin()) {
00654 _properties.set_origin(0, 0);
00655 }
00656 if (!_properties.has_size()) {
00657 _properties.set_size(100, 100);
00658 }
00659
00660 X11_Window parent_window = egl_pipe->get_root();
00661 WindowHandle *window_handle = _properties.get_parent_window();
00662 if (window_handle != NULL) {
00663 egldisplay_cat.info()
00664 << "Got parent_window " << *window_handle << "\n";
00665 WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
00666 if (os_handle != NULL) {
00667 egldisplay_cat.info()
00668 << "os_handle type " << os_handle->get_type() << "\n";
00669
00670 if (os_handle->is_of_type(NativeWindowHandle::X11Handle::get_class_type())) {
00671 NativeWindowHandle::X11Handle *x11_handle = DCAST(NativeWindowHandle::X11Handle, os_handle);
00672 parent_window = x11_handle->get_handle();
00673 } else if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
00674 NativeWindowHandle::IntHandle *int_handle = DCAST(NativeWindowHandle::IntHandle, os_handle);
00675 parent_window = (X11_Window)int_handle->get_handle();
00676 }
00677 }
00678 }
00679 _parent_window_handle = window_handle;
00680
00681 setup_colormap(visual_info);
00682
00683 _event_mask =
00684 ButtonPressMask | ButtonReleaseMask |
00685 KeyPressMask | KeyReleaseMask |
00686 EnterWindowMask | LeaveWindowMask |
00687 PointerMotionMask |
00688 FocusChangeMask |
00689 StructureNotifyMask;
00690
00691
00692 XSetWindowAttributes wa;
00693 wa.background_pixel = XBlackPixel(_display, _screen);
00694 wa.border_pixel = 0;
00695 wa.colormap = _colormap;
00696 wa.event_mask = _event_mask;
00697
00698 unsigned long attrib_mask =
00699 CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00700
00701 _xwindow = XCreateWindow
00702 (_display, parent_window,
00703 _properties.get_x_origin(), _properties.get_y_origin(),
00704 _properties.get_x_size(), _properties.get_y_size(),
00705 0, depth, InputOutput, visual, attrib_mask, &wa);
00706
00707 if (_xwindow == (X11_Window)0) {
00708 egldisplay_cat.error()
00709 << "failed to create X window.\n";
00710 return false;
00711 }
00712 set_wm_properties(_properties, false);
00713
00714
00715
00716
00717
00718 XIM im = egl_pipe->get_im();
00719 _ic = NULL;
00720 if (im) {
00721 _ic = XCreateIC
00722 (im,
00723 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
00724 (void*)NULL);
00725 if (_ic == (XIC)NULL) {
00726 egldisplay_cat.warning()
00727 << "Couldn't create input context.\n";
00728 }
00729 }
00730
00731 if (_properties.get_cursor_hidden()) {
00732 XDefineCursor(_display, _xwindow, egl_pipe->get_hidden_cursor());
00733 }
00734
00735 _egl_surface = eglCreateWindowSurface(_egl_display, eglgsg->_fbconfig, (NativeWindowType) _xwindow, NULL);
00736 if (eglGetError() != EGL_SUCCESS) {
00737 egldisplay_cat.error()
00738 << "Failed to create window surface.\n";
00739 return false;
00740 }
00741
00742 if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context)) {
00743 egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
00744 << get_egl_error_string(eglGetError()) << "\n";
00745 }
00746 eglgsg->reset_if_new();
00747 if (!eglgsg->is_valid()) {
00748 close_window();
00749 return false;
00750 }
00751 if (!eglgsg->get_fb_properties().verify_hardware_software
00752 (_fb_properties, eglgsg->get_gl_renderer())) {
00753 close_window();
00754 return false;
00755 }
00756 _fb_properties = eglgsg->get_fb_properties();
00757
00758 XMapWindow(_display, _xwindow);
00759
00760 if (_properties.get_raw_mice()) {
00761 open_raw_mice();
00762 } else {
00763 if (egldisplay_cat.is_debug()) {
00764 egldisplay_cat.debug()
00765 << "Raw mice not requested.\n";
00766 }
00767 }
00768
00769
00770 _window_handle = NativeWindowHandle::make_x11(_xwindow);
00771
00772
00773 if (_parent_window_handle != (WindowHandle *)NULL) {
00774 _parent_window_handle->attach_child(_window_handle);
00775 }
00776
00777 return true;
00778 }
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 void eglGraphicsWindow::
00794 set_wm_properties(const WindowProperties &properties, bool already_mapped) {
00795
00796 XTextProperty window_name;
00797 XTextProperty *window_name_p = (XTextProperty *)NULL;
00798 if (properties.has_title()) {
00799 char *name = (char *)properties.get_title().c_str();
00800 if (XStringListToTextProperty(&name, 1, &window_name) != 0) {
00801 window_name_p = &window_name;
00802 }
00803 }
00804
00805
00806
00807 XSizeHints *size_hints_p = NULL;
00808 if (properties.has_origin() || properties.has_size()) {
00809 size_hints_p = XAllocSizeHints();
00810 if (size_hints_p != (XSizeHints *)NULL) {
00811 if (properties.has_origin()) {
00812 size_hints_p->x = properties.get_x_origin();
00813 size_hints_p->y = properties.get_y_origin();
00814 size_hints_p->flags |= USPosition;
00815 }
00816 if (properties.has_size()) {
00817 size_hints_p->width = properties.get_x_size();
00818 size_hints_p->height = properties.get_y_size();
00819 size_hints_p->flags |= USSize;
00820
00821 if (properties.get_fixed_size()) {
00822 size_hints_p->min_width = properties.get_x_size();
00823 size_hints_p->min_height = properties.get_y_size();
00824 size_hints_p->max_width = properties.get_x_size();
00825 size_hints_p->max_height = properties.get_y_size();
00826 size_hints_p->flags |= (PMinSize | PMaxSize);
00827 }
00828 }
00829 }
00830 }
00831
00832
00833
00834 XWMHints *wm_hints_p = NULL;
00835 wm_hints_p = XAllocWMHints();
00836 if (wm_hints_p != (XWMHints *)NULL) {
00837 if (properties.has_minimized() && properties.get_minimized()) {
00838 wm_hints_p->initial_state = IconicState;
00839 } else {
00840 wm_hints_p->initial_state = NormalState;
00841 }
00842 wm_hints_p->flags = StateHint;
00843 }
00844
00845
00846
00847
00848 static const int max_type_data = 32;
00849 PN_int32 type_data[max_type_data];
00850 int next_type_data = 0;
00851
00852 static const int max_state_data = 32;
00853 PN_int32 state_data[max_state_data];
00854 int next_state_data = 0;
00855
00856 static const int max_set_data = 32;
00857 class SetAction {
00858 public:
00859 inline SetAction() { }
00860 inline SetAction(Atom state, Atom action) : _state(state), _action(action) { }
00861 Atom _state;
00862 Atom _action;
00863 };
00864 SetAction set_data[max_set_data];
00865 int next_set_data = 0;
00866
00867 if (properties.get_fullscreen()) {
00868
00869
00870 type_data[next_type_data++] = _net_wm_window_type_fullscreen;
00871
00872
00873 state_data[next_state_data++] = _net_wm_state_fullscreen;
00874 set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, _net_wm_state_add);
00875 } else {
00876 set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, _net_wm_state_remove);
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 XClassHint *class_hints_p = NULL;
00889 if (properties.get_undecorated()) {
00890 class_hints_p = XAllocClassHint();
00891 class_hints_p->res_class = (char*) "Undecorated";
00892
00893 if (!properties.get_fullscreen()) {
00894 type_data[next_type_data++] = _net_wm_window_type_splash;
00895 }
00896 }
00897
00898 if (properties.has_z_order()) {
00899 switch (properties.get_z_order()) {
00900 case WindowProperties::Z_bottom:
00901 state_data[next_state_data++] = _net_wm_state_below;
00902 set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_add);
00903 set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove);
00904 break;
00905
00906 case WindowProperties::Z_normal:
00907 set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove);
00908 set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove);
00909 break;
00910
00911 case WindowProperties::Z_top:
00912 state_data[next_state_data++] = _net_wm_state_above;
00913 set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove);
00914 set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_add);
00915 break;
00916 }
00917 }
00918
00919 nassertv(next_type_data < max_type_data);
00920 nassertv(next_state_data < max_state_data);
00921 nassertv(next_set_data < max_set_data);
00922
00923 XChangeProperty(_display, _xwindow, _net_wm_window_type,
00924 XA_ATOM, 32, PropModeReplace,
00925 (unsigned char *)type_data, next_type_data);
00926
00927
00928 XChangeProperty(_display, _xwindow, _net_wm_state,
00929 XA_ATOM, 32, PropModeReplace,
00930 (unsigned char *)state_data, next_state_data);
00931
00932 if (already_mapped) {
00933
00934
00935
00936
00937 eglGraphicsPipe *egl_pipe;
00938 DCAST_INTO_V(egl_pipe, _pipe);
00939
00940 for (int i = 0; i < next_set_data; ++i) {
00941 XClientMessageEvent event;
00942 memset(&event, 0, sizeof(event));
00943
00944 event.type = ClientMessage;
00945 event.send_event = True;
00946 event.display = _display;
00947 event.window = _xwindow;
00948 event.message_type = _net_wm_state;
00949 event.format = 32;
00950 event.data.l[0] = set_data[i]._action;
00951 event.data.l[1] = set_data[i]._state;
00952 event.data.l[2] = 0;
00953 event.data.l[3] = 1;
00954
00955 XSendEvent(_display, egl_pipe->get_root(), True, 0, (XEvent *)&event);
00956 }
00957 }
00958
00959 XSetWMProperties(_display, _xwindow, window_name_p, window_name_p,
00960 NULL, 0, size_hints_p, wm_hints_p, class_hints_p);
00961
00962 if (size_hints_p != (XSizeHints *)NULL) {
00963 XFree(size_hints_p);
00964 }
00965 if (wm_hints_p != (XWMHints *)NULL) {
00966 XFree(wm_hints_p);
00967 }
00968 if (class_hints_p != (XClassHint *)NULL) {
00969 XFree(class_hints_p);
00970 }
00971
00972
00973
00974
00975
00976 Atom protocols[] = {
00977 _wm_delete_window,
00978 };
00979
00980 XSetWMProtocols(_display, _xwindow, protocols,
00981 sizeof(protocols) / sizeof(Atom));
00982 }
00983
00984
00985
00986
00987
00988
00989
00990 void eglGraphicsWindow::
00991 setup_colormap(XVisualInfo *visual) {
00992 eglGraphicsPipe *egl_pipe;
00993 DCAST_INTO_V(egl_pipe, _pipe);
00994 X11_Window root_window = egl_pipe->get_root();
00995
00996 int visual_class = visual->c_class;
00997 int rc, is_rgb;
00998
00999 switch (visual_class) {
01000 case PseudoColor:
01001 _colormap = XCreateColormap(_display, root_window,
01002 visual->visual, AllocAll);
01003 break;
01004 case TrueColor:
01005 case DirectColor:
01006 _colormap = XCreateColormap(_display, root_window,
01007 visual->visual, AllocNone);
01008 break;
01009 case StaticColor:
01010 case StaticGray:
01011 case GrayScale:
01012 _colormap = XCreateColormap(_display, root_window,
01013 visual->visual, AllocNone);
01014 break;
01015 default:
01016 egldisplay_cat.error()
01017 << "Could not allocate a colormap for visual class "
01018 << visual_class << ".\n";
01019 break;
01020 }
01021 }
01022
01023
01024
01025
01026
01027
01028 void eglGraphicsWindow::
01029 open_raw_mice()
01030 {
01031 #ifdef HAVE_LINUX_INPUT_H
01032 bool any_present = false;
01033 bool any_mice = false;
01034
01035 for (int i=0; i<64; i++) {
01036 uint8_t evtypes[EV_MAX/8 + 1];
01037 ostringstream fnb;
01038 fnb << "/dev/input/event" << i;
01039 string fn = fnb.str();
01040 int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0);
01041 if (fd >= 0) {
01042 any_present = true;
01043 char name[256];
01044 char phys[256];
01045 char uniq[256];
01046 if ((ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0)||
01047 (ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0)||
01048 (ioctl(fd, EVIOCGPHYS(sizeof(uniq)), uniq) < 0)||
01049 (ioctl(fd, EVIOCGBIT(0, EV_MAX), &evtypes) < 0)) {
01050 close(fd);
01051 egldisplay_cat.error() <<
01052 "Opening raw mice: ioctl failed on " << fn << "\n";
01053 } else {
01054 if (test_bit(EV_REL, evtypes) || test_bit(EV_ABS, evtypes)) {
01055 for (char *p=name; *p; p++) {
01056 if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) {
01057 *p = '_';
01058 }
01059 }
01060 for (char *p=uniq; *p; p++) {
01061 if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) {
01062 *p = '_';
01063 }
01064 }
01065 string full_id = ((string)name) + "." + uniq;
01066 MouseDeviceInfo inf;
01067 inf._fd = fd;
01068 inf._input_device_index = _input_devices.size();
01069 inf._io_buffer = "";
01070 _mouse_device_info.push_back(inf);
01071 GraphicsWindowInputDevice device =
01072 GraphicsWindowInputDevice::pointer_only(this, full_id);
01073 add_input_device(device);
01074 egldisplay_cat.info() << "Raw mouse " <<
01075 inf._input_device_index << " detected: " << full_id << "\n";
01076 any_mice = true;
01077 } else {
01078 close(fd);
01079 }
01080 }
01081 } else {
01082 if ((errno == ENOENT)||(errno == ENOTDIR)) {
01083 break;
01084 } else {
01085 any_present = true;
01086 egldisplay_cat.error() <<
01087 "Opening raw mice: " << strerror(errno) << " " << fn << "\n";
01088 }
01089 }
01090 }
01091
01092 if (!any_present) {
01093 egldisplay_cat.error() <<
01094 "Opening raw mice: files not found: /dev/input/event*\n";
01095 } else if (!any_mice) {
01096 egldisplay_cat.error() <<
01097 "Opening raw mice: no mouse devices detected in /dev/input/event*\n";
01098 }
01099 #else
01100 egldisplay_cat.error() <<
01101 "Opening raw mice: panda not compiled with raw mouse support.\n";
01102 #endif
01103 }
01104
01105
01106
01107
01108
01109
01110 void eglGraphicsWindow::
01111 poll_raw_mice()
01112 {
01113 #ifdef HAVE_LINUX_INPUT_H
01114 for (int dev=0; dev<_mouse_device_info.size(); dev++) {
01115 MouseDeviceInfo &inf = _mouse_device_info[dev];
01116
01117
01118 if (inf._fd >= 0) {
01119 while (1) {
01120 char tbuf[1024];
01121 int nread = read(inf._fd, tbuf, sizeof(tbuf));
01122 if (nread > 0) {
01123 inf._io_buffer += string(tbuf, nread);
01124 } else {
01125 if ((nread < 0)&&((errno == EWOULDBLOCK) || (errno==EAGAIN))) {
01126 break;
01127 }
01128 close(inf._fd);
01129 inf._fd = -1;
01130 break;
01131 }
01132 }
01133 }
01134
01135
01136 int nevents = inf._io_buffer.size() / sizeof(struct input_event);
01137 if (nevents == 0) {
01138 continue;
01139 }
01140 const input_event *events = (const input_event *)(inf._io_buffer.c_str());
01141 GraphicsWindowInputDevice &dev = _input_devices[inf._input_device_index];
01142 int x = dev.get_raw_pointer().get_x();
01143 int y = dev.get_raw_pointer().get_y();
01144 for (int i=0; i<nevents; i++) {
01145 if (events[i].type == EV_REL) {
01146 if (events[i].code == REL_X) x += events[i].value;
01147 if (events[i].code == REL_Y) y += events[i].value;
01148 } else if (events[i].type == EV_ABS) {
01149 if (events[i].code == ABS_X) x = events[i].value;
01150 if (events[i].code == ABS_Y) y = events[i].value;
01151 } else if (events[i].type == EV_KEY) {
01152 if ((events[i].code >= BTN_MOUSE)&&(events[i].code < BTN_MOUSE+8)) {
01153 int btn = events[i].code - BTN_MOUSE;
01154 dev.set_pointer_in_window(x,y);
01155 if (events[i].value) {
01156 dev.button_down(MouseButton::button(btn));
01157 } else {
01158 dev.button_up(MouseButton::button(btn));
01159 }
01160 }
01161 }
01162 }
01163 inf._io_buffer.erase(0,nevents*sizeof(struct input_event));
01164 dev.set_pointer_in_window(x,y);
01165 }
01166 #endif
01167 }
01168
01169
01170
01171
01172
01173
01174
01175 void eglGraphicsWindow::
01176 handle_keystroke(XKeyEvent &event) {
01177 _input_devices[0].set_pointer_in_window(event.x, event.y);
01178
01179 if (_ic) {
01180
01181 static const int buffer_size = 256;
01182 wchar_t buffer[buffer_size];
01183 Status status;
01184 int len = XwcLookupString(_ic, &event, buffer, buffer_size, NULL,
01185 &status);
01186 if (status == XBufferOverflow) {
01187 egldisplay_cat.error()
01188 << "Overflowed input buffer.\n";
01189 }
01190
01191
01192
01193 for (int i = 0; i < len; i++) {
01194 _input_devices[0].keystroke(buffer[i]);
01195 }
01196
01197 } else {
01198
01199 ButtonHandle button = get_button(event, true);
01200 if (button.has_ascii_equivalent()) {
01201 _input_devices[0].keystroke(button.get_ascii_equivalent());
01202 }
01203 }
01204 }
01205
01206
01207
01208
01209
01210
01211
01212 void eglGraphicsWindow::
01213 handle_keypress(XKeyEvent &event) {
01214 _input_devices[0].set_pointer_in_window(event.x, event.y);
01215
01216
01217 ButtonHandle button = get_button(event, false);
01218 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
01219 _input_devices[0].button_down(KeyboardButton::control());
01220 }
01221 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
01222 _input_devices[0].button_down(KeyboardButton::shift());
01223 }
01224 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
01225 _input_devices[0].button_down(KeyboardButton::alt());
01226 }
01227 if (button != ButtonHandle::none()) {
01228 _input_devices[0].button_down(button);
01229 }
01230 }
01231
01232
01233
01234
01235
01236
01237
01238 void eglGraphicsWindow::
01239 handle_keyrelease(XKeyEvent &event) {
01240 _input_devices[0].set_pointer_in_window(event.x, event.y);
01241
01242
01243 ButtonHandle button = get_button(event, false);
01244 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
01245 _input_devices[0].button_up(KeyboardButton::control());
01246 }
01247 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
01248 _input_devices[0].button_up(KeyboardButton::shift());
01249 }
01250 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
01251 _input_devices[0].button_up(KeyboardButton::alt());
01252 }
01253 if (button != ButtonHandle::none()) {
01254 _input_devices[0].button_up(button);
01255 }
01256 }
01257
01258
01259
01260
01261
01262
01263
01264 ButtonHandle eglGraphicsWindow::
01265 get_button(XKeyEvent &key_event, bool allow_shift) {
01266 KeySym key = XLookupKeysym(&key_event, 0);
01267
01268 if ((key_event.state & Mod2Mask) != 0) {
01269
01270
01271
01272 KeySym k2;
01273 ButtonHandle button;
01274 switch (key) {
01275 case XK_KP_Space:
01276 case XK_KP_Tab:
01277 case XK_KP_Enter:
01278 case XK_KP_F1:
01279 case XK_KP_F2:
01280 case XK_KP_F3:
01281 case XK_KP_F4:
01282 case XK_KP_Equal:
01283 case XK_KP_Multiply:
01284 case XK_KP_Add:
01285 case XK_KP_Separator:
01286 case XK_KP_Subtract:
01287 case XK_KP_Divide:
01288 case XK_KP_Left:
01289 case XK_KP_Up:
01290 case XK_KP_Right:
01291 case XK_KP_Down:
01292 case XK_KP_Begin:
01293 case XK_KP_Prior:
01294 case XK_KP_Next:
01295 case XK_KP_Home:
01296 case XK_KP_End:
01297 case XK_KP_Insert:
01298 case XK_KP_Delete:
01299 case XK_KP_0:
01300 case XK_KP_1:
01301 case XK_KP_2:
01302 case XK_KP_3:
01303 case XK_KP_4:
01304 case XK_KP_5:
01305 case XK_KP_6:
01306 case XK_KP_7:
01307 case XK_KP_8:
01308 case XK_KP_9:
01309 k2 = XLookupKeysym(&key_event, 1);
01310 button = map_button(k2);
01311 if (button != ButtonHandle::none()) {
01312 return button;
01313 }
01314
01315
01316 break;
01317
01318 default:
01319 break;
01320 }
01321 }
01322
01323 if (allow_shift) {
01324
01325 if ((key_event.state & ShiftMask) != 0) {
01326 KeySym k2 = XLookupKeysym(&key_event, 1);
01327 ButtonHandle button = map_button(k2);
01328 if (button != ButtonHandle::none()) {
01329 return button;
01330 }
01331 }
01332
01333
01334
01335
01336 if ((key_event.state & (ShiftMask | LockMask)) != 0) {
01337 if (key >= XK_a and key <= XK_z) {
01338 key += (XK_A - XK_a);
01339 }
01340 }
01341 }
01342
01343 return map_button(key);
01344 }
01345
01346
01347
01348
01349
01350
01351
01352 ButtonHandle eglGraphicsWindow::
01353 map_button(KeySym key) {
01354 switch (key) {
01355 case XK_BackSpace:
01356 return KeyboardButton::backspace();
01357 case XK_Tab:
01358 case XK_KP_Tab:
01359 return KeyboardButton::tab();
01360 case XK_Return:
01361 case XK_KP_Enter:
01362 return KeyboardButton::enter();
01363 case XK_Escape:
01364 return KeyboardButton::escape();
01365 case XK_KP_Space:
01366 case XK_space:
01367 return KeyboardButton::space();
01368 case XK_exclam:
01369 return KeyboardButton::ascii_key('!');
01370 case XK_quotedbl:
01371 return KeyboardButton::ascii_key('"');
01372 case XK_numbersign:
01373 return KeyboardButton::ascii_key('#');
01374 case XK_dollar:
01375 return KeyboardButton::ascii_key('$');
01376 case XK_percent:
01377 return KeyboardButton::ascii_key('%');
01378 case XK_ampersand:
01379 return KeyboardButton::ascii_key('&');
01380 case XK_apostrophe:
01381 return KeyboardButton::ascii_key('\'');
01382 case XK_parenleft:
01383 return KeyboardButton::ascii_key('(');
01384 case XK_parenright:
01385 return KeyboardButton::ascii_key(')');
01386 case XK_asterisk:
01387 case XK_KP_Multiply:
01388 return KeyboardButton::ascii_key('*');
01389 case XK_plus:
01390 case XK_KP_Add:
01391 return KeyboardButton::ascii_key('+');
01392 case XK_comma:
01393 case XK_KP_Separator:
01394 return KeyboardButton::ascii_key(',');
01395 case XK_minus:
01396 case XK_KP_Subtract:
01397 return KeyboardButton::ascii_key('-');
01398 case XK_period:
01399 case XK_KP_Decimal:
01400 return KeyboardButton::ascii_key('.');
01401 case XK_slash:
01402 case XK_KP_Divide:
01403 return KeyboardButton::ascii_key('/');
01404 case XK_0:
01405 case XK_KP_0:
01406 return KeyboardButton::ascii_key('0');
01407 case XK_1:
01408 case XK_KP_1:
01409 return KeyboardButton::ascii_key('1');
01410 case XK_2:
01411 case XK_KP_2:
01412 return KeyboardButton::ascii_key('2');
01413 case XK_3:
01414 case XK_KP_3:
01415 return KeyboardButton::ascii_key('3');
01416 case XK_4:
01417 case XK_KP_4:
01418 return KeyboardButton::ascii_key('4');
01419 case XK_5:
01420 case XK_KP_5:
01421 return KeyboardButton::ascii_key('5');
01422 case XK_6:
01423 case XK_KP_6:
01424 return KeyboardButton::ascii_key('6');
01425 case XK_7:
01426 case XK_KP_7:
01427 return KeyboardButton::ascii_key('7');
01428 case XK_8:
01429 case XK_KP_8:
01430 return KeyboardButton::ascii_key('8');
01431 case XK_9:
01432 case XK_KP_9:
01433 return KeyboardButton::ascii_key('9');
01434 case XK_colon:
01435 return KeyboardButton::ascii_key(':');
01436 case XK_semicolon:
01437 return KeyboardButton::ascii_key(';');
01438 case XK_less:
01439 return KeyboardButton::ascii_key('<');
01440 case XK_equal:
01441 case XK_KP_Equal:
01442 return KeyboardButton::ascii_key('=');
01443 case XK_greater:
01444 return KeyboardButton::ascii_key('>');
01445 case XK_question:
01446 return KeyboardButton::ascii_key('?');
01447 case XK_at:
01448 return KeyboardButton::ascii_key('@');
01449 case XK_A:
01450 return KeyboardButton::ascii_key('A');
01451 case XK_B:
01452 return KeyboardButton::ascii_key('B');
01453 case XK_C:
01454 return KeyboardButton::ascii_key('C');
01455 case XK_D:
01456 return KeyboardButton::ascii_key('D');
01457 case XK_E:
01458 return KeyboardButton::ascii_key('E');
01459 case XK_F:
01460 return KeyboardButton::ascii_key('F');
01461 case XK_G:
01462 return KeyboardButton::ascii_key('G');
01463 case XK_H:
01464 return KeyboardButton::ascii_key('H');
01465 case XK_I:
01466 return KeyboardButton::ascii_key('I');
01467 case XK_J:
01468 return KeyboardButton::ascii_key('J');
01469 case XK_K:
01470 return KeyboardButton::ascii_key('K');
01471 case XK_L:
01472 return KeyboardButton::ascii_key('L');
01473 case XK_M:
01474 return KeyboardButton::ascii_key('M');
01475 case XK_N:
01476 return KeyboardButton::ascii_key('N');
01477 case XK_O:
01478 return KeyboardButton::ascii_key('O');
01479 case XK_P:
01480 return KeyboardButton::ascii_key('P');
01481 case XK_Q:
01482 return KeyboardButton::ascii_key('Q');
01483 case XK_R:
01484 return KeyboardButton::ascii_key('R');
01485 case XK_S:
01486 return KeyboardButton::ascii_key('S');
01487 case XK_T:
01488 return KeyboardButton::ascii_key('T');
01489 case XK_U:
01490 return KeyboardButton::ascii_key('U');
01491 case XK_V:
01492 return KeyboardButton::ascii_key('V');
01493 case XK_W:
01494 return KeyboardButton::ascii_key('W');
01495 case XK_X:
01496 return KeyboardButton::ascii_key('X');
01497 case XK_Y:
01498 return KeyboardButton::ascii_key('Y');
01499 case XK_Z:
01500 return KeyboardButton::ascii_key('Z');
01501 case XK_bracketleft:
01502 return KeyboardButton::ascii_key('[');
01503 case XK_backslash:
01504 return KeyboardButton::ascii_key('\\');
01505 case XK_bracketright:
01506 return KeyboardButton::ascii_key(']');
01507 case XK_asciicircum:
01508 return KeyboardButton::ascii_key('^');
01509 case XK_underscore:
01510 return KeyboardButton::ascii_key('_');
01511 case XK_grave:
01512 return KeyboardButton::ascii_key('`');
01513 case XK_a:
01514 return KeyboardButton::ascii_key('a');
01515 case XK_b:
01516 return KeyboardButton::ascii_key('b');
01517 case XK_c:
01518 return KeyboardButton::ascii_key('c');
01519 case XK_d:
01520 return KeyboardButton::ascii_key('d');
01521 case XK_e:
01522 return KeyboardButton::ascii_key('e');
01523 case XK_f:
01524 return KeyboardButton::ascii_key('f');
01525 case XK_g:
01526 return KeyboardButton::ascii_key('g');
01527 case XK_h:
01528 return KeyboardButton::ascii_key('h');
01529 case XK_i:
01530 return KeyboardButton::ascii_key('i');
01531 case XK_j:
01532 return KeyboardButton::ascii_key('j');
01533 case XK_k:
01534 return KeyboardButton::ascii_key('k');
01535 case XK_l:
01536 return KeyboardButton::ascii_key('l');
01537 case XK_m:
01538 return KeyboardButton::ascii_key('m');
01539 case XK_n:
01540 return KeyboardButton::ascii_key('n');
01541 case XK_o:
01542 return KeyboardButton::ascii_key('o');
01543 case XK_p:
01544 return KeyboardButton::ascii_key('p');
01545 case XK_q:
01546 return KeyboardButton::ascii_key('q');
01547 case XK_r:
01548 return KeyboardButton::ascii_key('r');
01549 case XK_s:
01550 return KeyboardButton::ascii_key('s');
01551 case XK_t:
01552 return KeyboardButton::ascii_key('t');
01553 case XK_u:
01554 return KeyboardButton::ascii_key('u');
01555 case XK_v:
01556 return KeyboardButton::ascii_key('v');
01557 case XK_w:
01558 return KeyboardButton::ascii_key('w');
01559 case XK_x:
01560 return KeyboardButton::ascii_key('x');
01561 case XK_y:
01562 return KeyboardButton::ascii_key('y');
01563 case XK_z:
01564 return KeyboardButton::ascii_key('z');
01565 case XK_braceleft:
01566 return KeyboardButton::ascii_key('{');
01567 case XK_bar:
01568 return KeyboardButton::ascii_key('|');
01569 case XK_braceright:
01570 return KeyboardButton::ascii_key('}');
01571 case XK_asciitilde:
01572 return KeyboardButton::ascii_key('~');
01573 case XK_F1:
01574 case XK_KP_F1:
01575 return KeyboardButton::f1();
01576 case XK_F2:
01577 case XK_KP_F2:
01578 return KeyboardButton::f2();
01579 case XK_F3:
01580 case XK_KP_F3:
01581 return KeyboardButton::f3();
01582 case XK_F4:
01583 case XK_KP_F4:
01584 return KeyboardButton::f4();
01585 case XK_F5:
01586 return KeyboardButton::f5();
01587 case XK_F6:
01588 return KeyboardButton::f6();
01589 case XK_F7:
01590 return KeyboardButton::f7();
01591 case XK_F8:
01592 return KeyboardButton::f8();
01593 case XK_F9:
01594 return KeyboardButton::f9();
01595 case XK_F10:
01596 return KeyboardButton::f10();
01597 case XK_F11:
01598 return KeyboardButton::f11();
01599 case XK_F12:
01600 return KeyboardButton::f12();
01601 case XK_KP_Left:
01602 case XK_Left:
01603 return KeyboardButton::left();
01604 case XK_KP_Up:
01605 case XK_Up:
01606 return KeyboardButton::up();
01607 case XK_KP_Right:
01608 case XK_Right:
01609 return KeyboardButton::right();
01610 case XK_KP_Down:
01611 case XK_Down:
01612 return KeyboardButton::down();
01613 case XK_KP_Prior:
01614 case XK_Prior:
01615 return KeyboardButton::page_up();
01616 case XK_KP_Next:
01617 case XK_Next:
01618 return KeyboardButton::page_down();
01619 case XK_KP_Home:
01620 case XK_Home:
01621 return KeyboardButton::home();
01622 case XK_KP_End:
01623 case XK_End:
01624 return KeyboardButton::end();
01625 case XK_KP_Insert:
01626 case XK_Insert:
01627 return KeyboardButton::insert();
01628 case XK_KP_Delete:
01629 case XK_Delete:
01630 return KeyboardButton::del();
01631 case XK_Num_Lock:
01632 return KeyboardButton::num_lock();
01633 case XK_Scroll_Lock:
01634 return KeyboardButton::scroll_lock();
01635 case XK_Print:
01636 return KeyboardButton::print_screen();
01637 case XK_Pause:
01638 return KeyboardButton::pause();
01639 case XK_Shift_L:
01640 return KeyboardButton::lshift();
01641 case XK_Shift_R:
01642 return KeyboardButton::rshift();
01643 case XK_Control_L:
01644 return KeyboardButton::lcontrol();
01645 case XK_Control_R:
01646 return KeyboardButton::rcontrol();
01647 case XK_Alt_L:
01648 return KeyboardButton::lalt();
01649 case XK_Alt_R:
01650 return KeyboardButton::ralt();
01651 case XK_Meta_L:
01652 case XK_Meta_R:
01653 return KeyboardButton::meta();
01654 case XK_Caps_Lock:
01655 return KeyboardButton::caps_lock();
01656 case XK_Shift_Lock:
01657 return KeyboardButton::shift_lock();
01658 }
01659
01660 return ButtonHandle::none();
01661 }
01662
01663
01664
01665
01666
01667
01668
01669 ButtonHandle eglGraphicsWindow::
01670 get_mouse_button(XButtonEvent &button_event) {
01671 int index = button_event.button;
01672 if (index == x_wheel_up_button) {
01673 return MouseButton::wheel_up();
01674 } else if (index == x_wheel_down_button) {
01675 return MouseButton::wheel_down();
01676 } else if (index == x_wheel_left_button) {
01677 return MouseButton::wheel_left();
01678 } else if (index == x_wheel_right_button) {
01679 return MouseButton::wheel_right();
01680 } else {
01681 return MouseButton::button(index - 1);
01682 }
01683 }
01684
01685
01686
01687
01688
01689
01690
01691
01692 Bool eglGraphicsWindow::
01693 check_event(X11_Display *display, XEvent *event, char *arg) {
01694 const eglGraphicsWindow *self = (eglGraphicsWindow *)arg;
01695
01696
01697 return (event->xany.window == self->_xwindow);
01698 }