15 #include "x11GraphicsWindow.h" 16 #include "config_x11display.h" 17 #include "x11GraphicsPipe.h" 19 #include "graphicsPipe.h" 20 #include "keyboardButton.h" 21 #include "mouseButton.h" 22 #include "buttonMap.h" 23 #include "clockObject.h" 24 #include "pStatTimer.h" 25 #include "textEncoder.h" 26 #include "throw_event.h" 27 #include "lightReMutexHolder.h" 28 #include "nativeWindowHandle.h" 29 #include "virtualFileSystem.h" 32 #include "pnmFileTypeRegistry.h" 38 #ifdef PHAVE_LINUX_INPUT_H 39 #include <linux/input.h> 43 static int xcursor_read(XcursorFile *file,
unsigned char *buf,
int len) {
44 istream* str = (istream*) file->closure;
45 str->read((
char*) buf, len);
49 static int xcursor_write(XcursorFile *file,
unsigned char *buf,
int len) {
51 nassertr_always(
false, 0);
55 static int xcursor_seek(XcursorFile *file,
long offset,
int whence) {
56 istream* str = (istream*) file->closure;
59 str->seekg(offset, istream::beg);
62 str->seekg(offset, istream::cur);
65 str->seekg(offset, istream::end);
74 #define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7))) 89 GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
92 DCAST_INTO_V(x11_pipe, _pipe);
95 _xwindow = (X11_Window)NULL;
102 _have_xrandr = XRRQueryExtension(_display, &event, &error);
104 _have_xrandr =
false;
107 _awaiting_configure =
false;
108 _dga_mouse_enabled =
false;
109 _wm_delete_window = x11_pipe->_wm_delete_window;
113 add_input_device(device);
122 ~x11GraphicsWindow() {
125 for (it = _cursor_filenames.begin(); it != _cursor_filenames.end(); it++) {
126 XFreeCursor(_display, it->second);
146 if (!_properties.get_foreground() ||
147 !_input_devices[0].get_pointer().get_in_window()) {
153 const MouseData &md = _input_devices[0].get_pointer();
154 if (!md.get_in_window() || md.get_x() != x || md.get_y() != y) {
155 if (!_dga_mouse_enabled) {
156 XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y);
158 _input_devices[0].set_pointer_in_window(x, y);
163 if ((device < 1)||(device >= _input_devices.size())) {
166 _input_devices[device].set_pointer_in_window(x, y);
182 PStatTimer timer(_make_current_pcollector, current_thread);
184 begin_frame_spam(mode);
188 if (_awaiting_configure) {
197 _gsg->reset_if_new();
199 if (mode == FM_render) {
201 clear_cube_map_selection();
205 return _gsg->begin_frame(current_thread);
217 end_frame_spam(mode);
220 if (mode == FM_render) {
225 _gsg->end_frame(current_thread);
227 if (mode == FM_render) {
229 clear_cube_map_selection();
249 if (_xwindow == (X11_Window)0) {
256 XKeyEvent keyrelease_event;
257 bool got_keyrelease_event =
false;
259 XConfigureEvent configure_event;
260 bool got_configure_event =
false;
263 bool changed_properties =
false;
265 while (XCheckIfEvent(_display, &event, check_event, (
char *)
this)) {
266 if (XFilterEvent(&event, None)) {
270 if (got_keyrelease_event) {
276 got_keyrelease_event =
false;
278 if (event.type == KeyPress &&
279 event.xkey.keycode == keyrelease_event.keycode &&
280 (event.xkey.time - keyrelease_event.time <= 1)) {
283 handle_keystroke(event.xkey);
287 handle_keypress(event.xkey);
293 handle_keyrelease(keyrelease_event);
299 switch (event.type) {
303 case ConfigureNotify:
307 configure_event =
event.xconfigure;
308 got_configure_event =
true;
313 button = get_mouse_button(event.xbutton);
314 if (!_dga_mouse_enabled) {
315 _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
317 _input_devices[0].button_down(button);
321 button = get_mouse_button(event.xbutton);
322 if (!_dga_mouse_enabled) {
323 _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
325 _input_devices[0].button_up(button);
329 if (_dga_mouse_enabled) {
330 const MouseData &md = _input_devices[0].get_raw_pointer();
331 _input_devices[0].set_pointer_in_window(md.get_x() +
event.xmotion.x_root, md.get_y() +
event.xmotion.y_root);
333 _input_devices[0].set_pointer_in_window(event.xmotion.x, event.xmotion.y);
338 handle_keystroke(event.xkey);
339 handle_keypress(event.xkey);
346 keyrelease_event =
event.xkey;
347 got_keyrelease_event =
true;
351 if (_dga_mouse_enabled) {
352 const MouseData &md = _input_devices[0].get_raw_pointer();
353 _input_devices[0].set_pointer_in_window(md.get_x(), md.get_y());
355 _input_devices[0].set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
360 _input_devices[0].set_pointer_out_of_window();
365 changed_properties =
true;
369 _input_devices[0].focus_lost();
371 changed_properties =
true;
376 changed_properties =
true;
381 changed_properties =
true;
384 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
388 if ((Atom)(event.xclient.data.l[0]) == _wm_delete_window) {
392 if (!close_request_event.empty()) {
395 throw_event(close_request_event);
404 system_changed_properties(properties);
413 x11display_cat.info()
414 <<
"DestroyNotify\n";
418 x11display_cat.warning()
419 <<
"unhandled X event type " <<
event.type <<
"\n";
423 if (got_configure_event) {
425 _awaiting_configure =
false;
433 properties.
set_origin(configure_event.x, configure_event.y);
434 properties.
set_size(configure_event.width, configure_event.height);
436 if (_properties.get_fixed_size()) {
443 if (configure_event.width != _fixed_size.get_x() ||
444 configure_event.height != _fixed_size.get_y()) {
445 XWindowChanges changes;
446 changes.width = _fixed_size.get_x();
447 changes.height = _fixed_size.get_y();
448 int value_mask = (CWWidth | CWHeight);
449 XConfigureWindow(_display, _xwindow, value_mask, &changes);
452 changed_properties =
true;
455 if (changed_properties) {
456 system_changed_properties(properties);
459 if (got_keyrelease_event) {
462 handle_keyrelease(keyrelease_event);
492 DCAST_INTO_V(x11_pipe, _pipe);
496 bool is_fullscreen = _properties.has_fullscreen() && _properties.get_fullscreen();
499 if (is_fullscreen != want_fullscreen || (is_fullscreen && properties.
has_size())) {
500 if (want_fullscreen) {
503 XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->
get_root());
504 SizeID old_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation);
505 SizeID new_size_id = (SizeID) -1;
506 int num_sizes = 0, reqsizex, reqsizey;
511 reqsizex = _properties.get_x_size();
512 reqsizey = _properties.get_y_size();
515 xrrs = XRRSizes(_display, 0, &num_sizes);
516 for (
int i = 0; i < num_sizes; ++i) {
517 if (xrrs[i].width == reqsizex &&
518 xrrs[i].height == reqsizey) {
522 if (new_size_id == (SizeID) -1) {
523 x11display_cat.error()
524 <<
"Videocard has no supported display resolutions at specified res (" 525 << reqsizex <<
" x " << reqsizey <<
")\n";
527 if (new_size_id != old_size_id) {
529 XRRSetScreenConfig(_display, conf, x11_pipe->
get_root(), new_size_id, _orig_rotation, CurrentTime);
530 if (_orig_size_id == (SizeID) -1) {
532 _orig_size_id = old_size_id;
547 if (_have_xrandr && _orig_size_id != (SizeID) -1) {
548 XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->
get_root());
549 XRRSetScreenConfig(_display, conf, x11_pipe->
get_root(), _orig_size_id, _orig_rotation, CurrentTime);
550 _orig_size_id = (SizeID) -1;
554 if (!properties.
has_origin() && _properties.has_origin()) {
555 properties.
set_origin(_properties.get_x_origin(), _properties.get_y_origin());
566 if (x_origin == -2) {
569 if (y_origin == -2) {
573 if (x_origin == -2) {
576 if (y_origin == -2) {
594 set_wm_properties(properties,
true);
599 _properties.set_title(properties.
get_title());
613 XWindowChanges changes;
616 if (_properties.get_fullscreen()) {
619 value_mask |= CWX | CWY;
625 if (changes.x != -1) value_mask |= CWX;
626 if (changes.y != -1) value_mask |= CWY;
634 _fixed_size = _properties.get_size();
640 value_mask |= (CWWidth | CWHeight);
642 if (_properties.get_fixed_size()) {
643 _fixed_size = properties.
get_size();
655 case WindowProperties::Z_bottom:
656 changes.stack_mode = Below;
659 case WindowProperties::Z_normal:
660 changes.stack_mode = TopIf;
663 case WindowProperties::Z_top:
664 changes.stack_mode = Above;
668 value_mask |= (CWStackMode);
682 _properties.set_cursor_filename(cursor_filename);
686 _properties.set_cursor_filename(filename);
688 if (_properties.get_cursor_hidden()) {
691 }
else if (!cursor_filename.empty()) {
693 X11_Cursor cursor = get_cursor(cursor_filename);
694 XDefineCursor(_display, _xwindow, cursor);
697 XDefineCursor(_display, _xwindow, None);
703 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
705 XSetInputFocus(_display, PointerRoot, RevertToPointerRoot, CurrentTime);
710 if (properties.has_mouse_mode()) {
712 case WindowProperties::M_absolute:
713 XUngrabPointer(_display, CurrentTime);
715 if (_dga_mouse_enabled) {
716 x11display_cat.info() <<
"Disabling relative mouse using XF86DGA extension\n";
717 XF86DGADirectVideo(_display, _screen, 0);
718 _dga_mouse_enabled =
false;
721 _properties.set_mouse_mode(WindowProperties::M_absolute);
725 case WindowProperties::M_relative:
727 if (!_dga_mouse_enabled) {
728 int major_ver, minor_ver;
729 if (XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
731 X11_Cursor cursor = None;
732 if (_properties.get_cursor_hidden()) {
734 DCAST_INTO_V(x11_pipe, _pipe);
738 if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
739 GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
740 x11display_cat.error() <<
"Failed to grab pointer!\n";
742 x11display_cat.info() <<
"Enabling relative mouse using XF86DGA extension\n";
743 XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse);
745 _properties.set_mouse_mode(WindowProperties::M_relative);
747 _dga_mouse_enabled =
true;
752 XQueryPointer(_display, _xwindow, &event.xbutton.root,
753 &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
754 &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
755 _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
758 x11display_cat.info() <<
"XF86DGA extension not available\n";
759 _dga_mouse_enabled =
false;
765 case WindowProperties::M_confined:
768 if (_dga_mouse_enabled) {
769 XF86DGADirectVideo(_display, _screen, 0);
770 _dga_mouse_enabled =
false;
773 X11_Cursor cursor = None;
774 if (_properties.get_cursor_hidden()) {
776 DCAST_INTO_V(x11_pipe, _pipe);
780 if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
781 GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
782 x11display_cat.error() <<
"Failed to grab pointer!\n";
784 _properties.set_mouse_mode(WindowProperties::M_confined);
792 if (value_mask != 0) {
795 XReconfigureWMWindow(_display, _xwindow, _screen, value_mask, &changes);
798 _awaiting_configure =
true;
807 void x11GraphicsWindow::
808 mouse_mode_absolute() {
817 void x11GraphicsWindow::
818 mouse_mode_relative() {
828 void x11GraphicsWindow::
834 if (_ic != (XIC)NULL) {
839 if (_xwindow != (X11_Window)NULL) {
840 XDestroyWindow(_display, _xwindow);
841 _xwindow = (X11_Window)NULL;
851 if (_have_xrandr && _orig_size_id != (SizeID) -1) {
855 DCAST_INTO_V(x11_pipe, _pipe);
861 root = RootWindow(_display, _screen);
863 XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, root);
864 XRRSetScreenConfig(_display, conf, root, _orig_size_id, _orig_rotation, CurrentTime);
869 GraphicsWindow::close_window();
879 bool x11GraphicsWindow::
881 if (_visual_info == NULL) {
883 x11display_cat.error()
884 <<
"No X visual: cannot open window.\n";
889 DCAST_INTO_R(x11_pipe, _pipe,
false);
891 if (!_properties.has_origin()) {
892 _properties.set_origin(0, 0);
894 if (!_properties.has_size()) {
895 _properties.set_size(100, 100);
899 if (_properties.get_fullscreen() && _have_xrandr) {
900 XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->
get_root());
901 if (_orig_size_id == (SizeID) -1) {
902 _orig_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation);
904 int num_sizes, new_size_id = -1;
906 xrrs = XRRSizes(_display, 0, &num_sizes);
907 for (
int i = 0; i < num_sizes; ++i) {
908 if (xrrs[i].width == _properties.get_x_size() &&
909 xrrs[i].height == _properties.get_y_size()) {
913 if (new_size_id == -1) {
914 x11display_cat.error()
915 <<
"Videocard has no supported display resolutions at specified res (" 916 << _properties.get_x_size() <<
" x " << _properties.get_y_size() <<
")\n";
920 if (new_size_id != _orig_size_id) {
921 XRRSetScreenConfig(_display, conf, x11_pipe->
get_root(), new_size_id, _orig_rotation, CurrentTime);
928 X11_Window parent_window = x11_pipe->
get_root();
929 WindowHandle *window_handle = _properties.get_parent_window();
930 if (window_handle != NULL) {
931 x11display_cat.info()
932 <<
"Got parent_window " << *window_handle <<
"\n";
934 if (os_handle != NULL) {
935 x11display_cat.info()
936 <<
"os_handle type " << os_handle->get_type() <<
"\n";
938 if (os_handle->
is_of_type(NativeWindowHandle::X11Handle::get_class_type())) {
939 NativeWindowHandle::X11Handle *x11_handle = DCAST(NativeWindowHandle::X11Handle, os_handle);
940 parent_window = x11_handle->get_handle();
941 }
else if (os_handle->
is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
943 parent_window = (X11_Window)int_handle->get_handle();
947 _parent_window_handle = window_handle;
950 ButtonPressMask | ButtonReleaseMask |
951 KeyPressMask | KeyReleaseMask |
952 EnterWindowMask | LeaveWindowMask |
954 FocusChangeMask | StructureNotifyMask;
957 XSetWindowAttributes wa;
958 wa.background_pixel = XBlackPixel(_display, _screen);
960 wa.colormap = _colormap;
961 wa.event_mask = _event_mask;
963 unsigned long attrib_mask =
964 CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
966 _xwindow = XCreateWindow
967 (_display, parent_window,
968 _properties.get_x_origin(), _properties.get_y_origin(),
969 _properties.get_x_size(), _properties.get_y_size(),
970 0, _visual_info->depth, InputOutput,
971 _visual_info->visual, attrib_mask, &wa);
973 if (_xwindow == (X11_Window)0) {
974 x11display_cat.error()
975 <<
"failed to create X window.\n";
979 if (_properties.get_fixed_size()) {
980 _fixed_size = _properties.get_size();
983 set_wm_properties(_properties,
false);
989 XIM im = x11_pipe->
get_im();
994 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
996 if (_ic == (XIC)NULL) {
997 x11display_cat.warning()
998 <<
"Couldn't create input context.\n";
1002 if (_properties.get_cursor_hidden()) {
1005 }
else if (_properties.has_cursor_filename() && !_properties.get_cursor_filename().empty()) {
1007 X11_Cursor cursor = get_cursor(_properties.get_cursor_filename());
1008 XDefineCursor(_display, _xwindow, cursor);
1011 XMapWindow(_display, _xwindow);
1013 if (_properties.get_raw_mice()) {
1016 if (x11display_cat.is_debug()) {
1017 x11display_cat.debug()
1018 <<
"Raw mice not requested.\n";
1023 _window_handle = NativeWindowHandle::make_x11(_xwindow);
1027 _parent_window_handle->attach_child(_window_handle);
1046 void x11GraphicsWindow::
1047 set_wm_properties(
const WindowProperties &properties,
bool already_mapped) {
1049 DCAST_INTO_V(x11_pipe, _pipe);
1052 XTextProperty window_name;
1053 XTextProperty *window_name_p = (XTextProperty *)NULL;
1055 const char *name = properties.
get_title().c_str();
1056 if (XStringListToTextProperty((
char **)&name, 1, &window_name) != 0) {
1057 window_name_p = &window_name;
1063 XSizeHints *size_hints_p = NULL;
1065 size_hints_p = XAllocSizeHints();
1066 if (size_hints_p != (XSizeHints *)NULL) {
1068 if (_properties.get_fullscreen()) {
1069 size_hints_p->x = 0;
1070 size_hints_p->y = 0;
1075 size_hints_p->flags |= USPosition;
1080 size_hints_p->width = size.get_x();
1081 size_hints_p->height = size.get_y();
1082 size_hints_p->flags |= USSize;
1085 size_hints_p->min_width = size.get_x();
1086 size_hints_p->min_height = size.get_y();
1087 size_hints_p->max_width = size.get_x();
1088 size_hints_p->max_height = size.get_y();
1089 size_hints_p->flags |= (PMinSize | PMaxSize);
1096 XWMHints *wm_hints_p = NULL;
1097 wm_hints_p = XAllocWMHints();
1098 if (wm_hints_p != (XWMHints *)NULL) {
1100 wm_hints_p->initial_state = IconicState;
1102 wm_hints_p->initial_state = NormalState;
1104 wm_hints_p->flags = StateHint;
1110 static const int max_type_data = 32;
1111 PN_int32 type_data[max_type_data];
1112 int next_type_data = 0;
1114 static const int max_state_data = 32;
1115 PN_int32 state_data[max_state_data];
1116 int next_state_data = 0;
1118 static const int max_set_data = 32;
1121 inline SetAction() { }
1122 inline SetAction(Atom state, Atom action) : _state(state), _action(action) { }
1126 SetAction set_data[max_set_data];
1127 int next_set_data = 0;
1133 type_data[next_type_data++] = x11_pipe->_net_wm_window_type_fullscreen;
1136 state_data[next_state_data++] = x11_pipe->_net_wm_state_fullscreen;
1139 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 1);
1142 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0);
1155 XClassHint *class_hints_p = NULL;
1156 if (!x_wm_class.empty()) {
1158 class_hints_p = XAllocClassHint();
1159 class_hints_p->res_class = (
char*) x_wm_class.c_str();
1160 if (!x_wm_class_name.empty()) {
1161 class_hints_p->res_name = (
char*) x_wm_class_name.c_str();
1165 class_hints_p = XAllocClassHint();
1166 class_hints_p->res_class = (
char*)
"Undecorated";
1170 type_data[next_type_data++] = x11_pipe->_net_wm_window_type_splash;
1175 case WindowProperties::Z_bottom:
1176 state_data[next_state_data++] = x11_pipe->_net_wm_state_below;
1177 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1178 x11_pipe->_net_wm_state_add);
1179 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1180 x11_pipe->_net_wm_state_remove);
1183 case WindowProperties::Z_normal:
1184 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1185 x11_pipe->_net_wm_state_remove);
1186 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1187 x11_pipe->_net_wm_state_remove);
1190 case WindowProperties::Z_top:
1191 state_data[next_state_data++] = x11_pipe->_net_wm_state_above;
1192 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1193 x11_pipe->_net_wm_state_remove);
1194 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1195 x11_pipe->_net_wm_state_add);
1200 nassertv(next_type_data < max_type_data);
1201 nassertv(next_state_data < max_state_data);
1202 nassertv(next_set_data < max_set_data);
1205 PN_int32 pid = getpid();
1206 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_pid,
1207 XA_CARDINAL, 32, PropModeReplace,
1208 (
unsigned char *)&pid, 1);
1210 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_window_type,
1211 XA_ATOM, 32, PropModeReplace,
1212 (
unsigned char *)type_data, next_type_data);
1215 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_state,
1216 XA_ATOM, 32, PropModeReplace,
1217 (
unsigned char *)state_data, next_state_data);
1219 if (already_mapped) {
1225 DCAST_INTO_V(x11_pipe, _pipe);
1227 for (
int i = 0; i < next_set_data; ++i) {
1228 XClientMessageEvent event;
1229 memset(&event, 0,
sizeof(event));
1230 event.type = ClientMessage;
1231 event.send_event = True;
1232 event.display = _display;
1233 event.window = _xwindow;
1234 event.message_type = x11_pipe->_net_wm_state;
1236 event.data.l[0] = set_data[i]._action;
1237 event.data.l[1] = set_data[i]._state;
1238 event.data.l[2] = 0;
1239 event.data.l[3] = 1;
1241 XSendEvent(_display, x11_pipe->
get_root(), True, SubstructureNotifyMask | SubstructureRedirectMask, (XEvent *)&event);
1245 XSetWMProperties(_display, _xwindow, window_name_p, window_name_p,
1246 NULL, 0, size_hints_p, wm_hints_p, class_hints_p);
1248 if (size_hints_p != (XSizeHints *)NULL) {
1249 XFree(size_hints_p);
1251 if (wm_hints_p != (XWMHints *)NULL) {
1254 if (class_hints_p != (XClassHint *)NULL) {
1255 XFree(class_hints_p);
1262 Atom protocols[] = {
1266 XSetWMProtocols(_display, _xwindow, protocols,
1267 sizeof(protocols) /
sizeof(Atom));
1276 void x11GraphicsWindow::
1277 setup_colormap(XVisualInfo *visual) {
1279 DCAST_INTO_V(x11_pipe, _pipe);
1280 X11_Window root_window = x11_pipe->
get_root();
1282 _colormap = XCreateColormap(_display, root_window,
1283 visual->visual, AllocNone);
1291 void x11GraphicsWindow::
1293 #ifdef PHAVE_LINUX_INPUT_H 1294 bool any_present =
false;
1295 bool any_mice =
false;
1297 for (
int i=0; i<64; i++) {
1298 uint8_t evtypes[EV_MAX/8 + 1];
1300 fnb <<
"/dev/input/event" << i;
1301 string fn = fnb.str();
1302 int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0);
1308 if ((ioctl(fd, EVIOCGNAME(
sizeof(name)), name) < 0)||
1309 (ioctl(fd, EVIOCGPHYS(
sizeof(phys)), phys) < 0)||
1310 (ioctl(fd, EVIOCGPHYS(
sizeof(uniq)), uniq) < 0)||
1311 (ioctl(fd, EVIOCGBIT(0, EV_MAX), &evtypes) < 0)) {
1313 x11display_cat.error() <<
1314 "Opening raw mice: ioctl failed on " << fn <<
"\n";
1316 if (test_bit(EV_REL, evtypes) || test_bit(EV_ABS, evtypes)) {
1317 for (
char *p=name; *p; p++) {
1318 if (((*p<
'a')||(*p>
'z')) && ((*p<
'A')||(*p>
'Z')) && ((*p<
'0')||(*p>
'9'))) {
1322 for (
char *p=uniq; *p; p++) {
1323 if (((*p<
'a')||(*p>
'z')) && ((*p<
'A')||(*p>
'Z')) && ((*p<
'0')||(*p>
'9'))) {
1327 string full_id = ((string)name) +
"." + uniq;
1328 MouseDeviceInfo inf;
1330 inf._input_device_index = _input_devices.size();
1331 inf._io_buffer =
"";
1332 _mouse_device_info.push_back(inf);
1335 add_input_device(device);
1336 x11display_cat.info() <<
"Raw mouse " <<
1337 inf._input_device_index <<
" detected: " << full_id <<
"\n";
1344 if ((errno == ENOENT)||(errno == ENOTDIR)) {
1348 x11display_cat.error() <<
1349 "Opening raw mice: " << strerror(errno) <<
" " << fn <<
"\n";
1355 x11display_cat.error() <<
1356 "Opening raw mice: files not found: /dev/input/event*\n";
1357 }
else if (!any_mice) {
1358 x11display_cat.error() <<
1359 "Opening raw mice: no mouse devices detected in /dev/input/event*\n";
1362 x11display_cat.error() <<
1363 "Opening raw mice: panda not compiled with raw mouse support.\n";
1372 void x11GraphicsWindow::
1374 #ifdef PHAVE_LINUX_INPUT_H 1375 for (
int di = 0; di < _mouse_device_info.size(); ++di) {
1376 MouseDeviceInfo &inf = _mouse_device_info[di];
1382 int nread = read(inf._fd, tbuf,
sizeof(tbuf));
1384 inf._io_buffer += string(tbuf, nread);
1386 if ((nread < 0) && ((errno == EWOULDBLOCK) || (errno==EAGAIN))) {
1397 int nevents = inf._io_buffer.size() /
sizeof(
struct input_event);
1401 const input_event *events = (
const input_event *)(inf._io_buffer.c_str());
1405 for (
int i = 0; i < nevents; i++) {
1406 if (events[i].type == EV_REL) {
1407 if (events[i].code == REL_X) x += events[i].value;
1408 if (events[i].code == REL_Y) y += events[i].value;
1409 }
else if (events[i].type == EV_ABS) {
1410 if (events[i].code == ABS_X) x = events[i].value;
1411 if (events[i].code == ABS_Y) y = events[i].value;
1412 }
else if (events[i].type == EV_KEY) {
1413 if ((events[i].code >= BTN_MOUSE) && (events[i].code < BTN_MOUSE + 8)) {
1414 int btn = events[i].code - BTN_MOUSE;
1416 if (events[i].value) {
1424 inf._io_buffer.erase(0, nevents *
sizeof(
struct input_event));
1436 void x11GraphicsWindow::
1437 handle_keystroke(XKeyEvent &event) {
1438 if (!_dga_mouse_enabled) {
1439 _input_devices[0].set_pointer_in_window(event.x, event.y);
1444 static const int buffer_size = 256;
1445 wchar_t buffer[buffer_size];
1447 int len = XwcLookupString(_ic, &event, buffer, buffer_size, NULL,
1449 if (status == XBufferOverflow) {
1450 x11display_cat.error()
1451 <<
"Overflowed input buffer.\n";
1456 for (
int i = 0; i < len; i++) {
1457 _input_devices[0].keystroke(buffer[i]);
1475 void x11GraphicsWindow::
1476 handle_keypress(XKeyEvent &event) {
1477 if (!_dga_mouse_enabled) {
1478 _input_devices[0].set_pointer_in_window(event.x, event.y);
1484 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
1485 _input_devices[0].button_down(KeyboardButton::control());
1487 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
1488 _input_devices[0].button_down(KeyboardButton::shift());
1490 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
1491 _input_devices[0].button_down(KeyboardButton::alt());
1493 if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
1494 _input_devices[0].button_down(KeyboardButton::meta());
1496 _input_devices[0].button_down(button);
1499 ButtonHandle raw_button = map_raw_button(event.keycode);
1501 _input_devices[0].raw_button_down(raw_button);
1511 void x11GraphicsWindow::
1512 handle_keyrelease(XKeyEvent &event) {
1513 if (!_dga_mouse_enabled) {
1514 _input_devices[0].set_pointer_in_window(event.x, event.y);
1520 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
1521 _input_devices[0].button_up(KeyboardButton::control());
1523 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
1524 _input_devices[0].button_up(KeyboardButton::shift());
1526 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
1527 _input_devices[0].button_up(KeyboardButton::alt());
1529 if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
1530 _input_devices[0].button_up(KeyboardButton::meta());
1532 _input_devices[0].button_up(button);
1535 ButtonHandle raw_button = map_raw_button(event.keycode);
1537 _input_devices[0].raw_button_up(raw_button);
1548 get_button(XKeyEvent &key_event,
bool allow_shift) {
1549 KeySym key = XLookupKeysym(&key_event, 0);
1551 if ((key_event.state & Mod2Mask) != 0) {
1566 case XK_KP_Multiply:
1568 case XK_KP_Separator:
1569 case XK_KP_Subtract:
1592 k2 = XLookupKeysym(&key_event, 1);
1593 button = map_button(k2);
1608 if ((key_event.state & ShiftMask) != 0) {
1609 KeySym k2 = XLookupKeysym(&key_event, 1);
1619 if ((key_event.state & (ShiftMask | LockMask)) != 0) {
1620 if (key >= XK_a and key <= XK_z) {
1621 key += (XK_A - XK_a);
1626 return map_button(key);
1636 map_button(KeySym key)
const {
1641 return KeyboardButton::backspace();
1644 return KeyboardButton::tab();
1647 return KeyboardButton::enter();
1649 return KeyboardButton::escape();
1652 return KeyboardButton::space();
1673 case XK_KP_Multiply:
1679 case XK_KP_Separator:
1682 case XK_KP_Subtract:
1787 case XK_bracketleft:
1791 case XK_bracketright:
1793 case XK_asciicircum:
1862 return KeyboardButton::f1();
1865 return KeyboardButton::f2();
1868 return KeyboardButton::f3();
1871 return KeyboardButton::f4();
1873 return KeyboardButton::f5();
1875 return KeyboardButton::f6();
1877 return KeyboardButton::f7();
1879 return KeyboardButton::f8();
1881 return KeyboardButton::f9();
1883 return KeyboardButton::f10();
1885 return KeyboardButton::f11();
1887 return KeyboardButton::f12();
1890 return KeyboardButton::left();
1893 return KeyboardButton::up();
1896 return KeyboardButton::right();
1899 return KeyboardButton::down();
1902 return KeyboardButton::page_up();
1905 return KeyboardButton::page_down();
1908 return KeyboardButton::home();
1911 return KeyboardButton::end();
1914 return KeyboardButton::insert();
1917 return KeyboardButton::del();
1919 return KeyboardButton::num_lock();
1920 case XK_Scroll_Lock:
1921 return KeyboardButton::scroll_lock();
1923 return KeyboardButton::print_screen();
1925 return KeyboardButton::pause();
1927 return KeyboardButton::menu();
1929 return KeyboardButton::lshift();
1931 return KeyboardButton::rshift();
1933 return KeyboardButton::lcontrol();
1935 return KeyboardButton::rcontrol();
1937 return KeyboardButton::lalt();
1939 return KeyboardButton::ralt();
1942 return KeyboardButton::lmeta();
1945 return KeyboardButton::rmeta();
1947 return KeyboardButton::caps_lock();
1949 return KeyboardButton::shift_lock();
1951 if (x11display_cat.is_debug()) {
1952 x11display_cat.debug()
1953 <<
"Unrecognized keysym 0x" << hex << key << dec <<
"\n";
1964 map_raw_button(KeyCode key)
const {
1966 case 9:
return KeyboardButton::escape();
1979 case 22:
return KeyboardButton::backspace();
1980 case 23:
return KeyboardButton::tab();
1993 case 36:
return KeyboardButton::enter();
1994 case 37:
return KeyboardButton::lcontrol();
2007 case 50:
return KeyboardButton::lshift();
2019 case 62:
return KeyboardButton::rshift();
2021 case 64:
return KeyboardButton::lalt();
2022 case 65:
return KeyboardButton::space();
2023 case 66:
return KeyboardButton::caps_lock();
2024 case 67:
return KeyboardButton::f1();
2025 case 68:
return KeyboardButton::f2();
2026 case 69:
return KeyboardButton::f3();
2027 case 70:
return KeyboardButton::f4();
2028 case 71:
return KeyboardButton::f5();
2029 case 72:
return KeyboardButton::f6();
2030 case 73:
return KeyboardButton::f7();
2031 case 74:
return KeyboardButton::f8();
2032 case 75:
return KeyboardButton::f9();
2033 case 76:
return KeyboardButton::f10();
2034 case 77:
return KeyboardButton::num_lock();
2035 case 78:
return KeyboardButton::scroll_lock();
2050 case 95:
return KeyboardButton::f11();
2051 case 96:
return KeyboardButton::f12();
2053 case 104:
return KeyboardButton::enter();
2054 case 105:
return KeyboardButton::rcontrol();
2056 case 107:
return KeyboardButton::print_screen();
2057 case 108:
return KeyboardButton::ralt();
2059 case 110:
return KeyboardButton::home();
2060 case 111:
return KeyboardButton::up();
2061 case 112:
return KeyboardButton::page_up();
2062 case 113:
return KeyboardButton::left();
2063 case 114:
return KeyboardButton::right();
2064 case 115:
return KeyboardButton::end();
2065 case 116:
return KeyboardButton::down();
2066 case 117:
return KeyboardButton::page_down();
2067 case 118:
return KeyboardButton::insert();
2068 case 119:
return KeyboardButton::del();
2070 case 127:
return KeyboardButton::pause();
2072 case 133:
return KeyboardButton::lmeta();
2073 case 134:
return KeyboardButton::rmeta();
2074 case 135:
return KeyboardButton::menu();
2086 get_mouse_button(XButtonEvent &button_event) {
2087 int index = button_event.button;
2088 if (index == x_wheel_up_button) {
2090 }
else if (index == x_wheel_down_button) {
2092 }
else if (index == x_wheel_left_button) {
2094 }
else if (index == x_wheel_right_button) {
2108 get_keyboard_map()
const {
2113 for (
int k = 9; k <= 135; ++k) {
2119 KeySym sym = XKeycodeToKeysym(_display, k, 0);
2139 Bool x11GraphicsWindow::
2140 check_event(X11_Display *display, XEvent *event,
char *arg) {
2144 return (event->xany.window == self->_xwindow);
2154 X11_Cursor x11GraphicsWindow::
2155 get_cursor(
const Filename &filename) {
2156 #ifndef HAVE_XCURSOR 2157 x11display_cat.info()
2158 <<
"XCursor support not enabled in build; cannot change mouse cursor.\n";
2160 #else // HAVE_XCURSOR 2163 if (fi != _cursor_filenames.end()) {
2172 x11display_cat.warning()
2173 <<
"Could not find cursor filename " << filename <<
"\n";
2176 fi = _cursor_filenames.find(resolved);
2177 if (fi != _cursor_filenames.end()) {
2184 x11display_cat.warning()
2185 <<
"Could not open cursor file " << filename <<
"\n";
2191 str->read(magic, 4);
2193 x11display_cat.warning()
2194 <<
"Could not read from cursor file " << filename <<
"\n";
2197 str->seekg(0, istream::beg);
2199 X11_Cursor h = None;
2200 if (memcmp(magic,
"Xcur", 4) == 0) {
2202 x11display_cat.debug()
2203 <<
"Loading X11 cursor " << filename <<
"\n";
2205 xcfile.closure = str;
2206 xcfile.read = &xcursor_read;
2207 xcfile.write = &xcursor_write;
2208 xcfile.seek = &xcursor_seek;
2210 XcursorImages *images = XcursorXcFileLoadImages(&xcfile, XcursorGetDefaultSize(_display));
2211 if (images != NULL) {
2212 h = XcursorImagesLoadCursor(_display, images);
2213 XcursorImagesDestroy(images);
2216 }
else if (memcmp(magic,
"\0\0\1\0", 4) == 0
2217 || memcmp(magic,
"\0\0\2\0", 4) == 0) {
2219 x11display_cat.debug()
2220 <<
"Loading Windows cursor " << filename <<
"\n";
2228 x11display_cat.warning()
2229 <<
"X11 cursor filename '" << resolved <<
"' could not be loaded!\n";
2232 _cursor_filenames[resolved] = h;
2234 #endif // HAVE_XCURSOR 2245 X11_Cursor x11GraphicsWindow::
2246 read_ico(istream &ico) {
2249 uint16_t reserved, type, count;
2253 uint8_t width, height, colorCount, reserved;
2254 uint16_t xhot, yhot;
2255 uint32_t bitmapSize, offset;
2259 uint32_t headerSize, width, height;
2260 uint16_t planes, bitsPerPixel;
2261 uint32_t compression, imageSize, xPixelsPerM, yPixelsPerM, colorsUsed, colorsImportant;
2265 uint8_t blue, green, red, reserved;
2269 unsigned int j, k, mask, shift;
2270 size_t colorCount, bitsPerPixel;
2272 IcoInfoHeader infoHeader;
2273 IcoEntry *entries = NULL;
2274 IcoColor
color, *palette = NULL;
2276 size_t xorBmpSize, andBmpSize;
2277 char *curXor, *curAnd;
2278 char *xorBmp = NULL, *andBmp = NULL;
2279 XcursorImage *image = NULL;
2280 X11_Cursor ret = None;
2282 int def_size = XcursorGetDefaultSize(_display);
2285 ico.read(reinterpret_cast<char *>(&header),
sizeof(IcoHeader));
2286 if (!ico.good())
goto cleanup;
2287 if (header.type != 1 && header.type != 2)
goto cleanup;
2288 if (header.count < 1)
goto cleanup;
2291 entries =
new IcoEntry[header.count];
2292 ico.read(reinterpret_cast<char *>(entries), header.count *
sizeof(IcoEntry));
2293 if (!ico.good())
goto cleanup;
2294 for (i = 1; i < header.count; i++) {
2295 if (entries[i].width == def_size && entries[i].height == def_size) {
2300 if (entries[i].width > entries[entry].width ||
2301 entries[i].height > entries[entry].height)
2306 ico.seekg(entries[entry].offset);
2307 if (!ico.good())
goto cleanup;
2309 if (ico.peek() == 0x89) {
2323 unsigned int *dest = image->pixels;
2325 if (alpha != NULL) {
2326 for (
size_t p = 0; p < num_pixels; ++p) {
2327 *dest++ = (*alpha << 24U) | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
2332 for (
size_t p = 0; p < num_pixels; ++p) {
2333 *dest++ = 0xff000000U | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
2339 ico.read(reinterpret_cast<char *>(&infoHeader),
sizeof(IcoInfoHeader));
2340 if (!ico.good())
goto cleanup;
2341 bitsPerPixel = infoHeader.bitsPerPixel;
2343 if (infoHeader.compression != 0)
goto cleanup;
2346 if (bitsPerPixel != 24 && bitsPerPixel != 32) {
2347 colorCount = 1 << bitsPerPixel;
2348 palette =
new IcoColor[colorCount];
2349 ico.read(reinterpret_cast<char *>(palette), colorCount *
sizeof(IcoColor));
2350 if (!ico.good())
goto cleanup;
2354 xorBmpSize = (infoHeader.width * (infoHeader.height / 2) * bitsPerPixel) / 8;
2355 andBmpSize = (infoHeader.width * (infoHeader.height / 2)) / 8;
2356 curXor = xorBmp =
new char[xorBmpSize];
2357 curAnd = andBmp =
new char[andBmpSize];
2358 ico.read(xorBmp, xorBmpSize);
2359 if (!ico.good())
goto cleanup;
2360 ico.read(andBmp, andBmpSize);
2361 if (!ico.good())
goto cleanup;
2363 image = XcursorImageCreate(infoHeader.width, infoHeader.height / 2);
2366 switch (bitsPerPixel) {
2372 mask = ((1 << bitsPerPixel) - 1);
2373 for (i = image->height - 1; i >= 0; i--) {
2374 for (j = 0; j < image->width; j += 8 / bitsPerPixel) {
2375 for (k = 0; k < 8 / bitsPerPixel; k++) {
2376 shift = 8 - ((k + 1) * bitsPerPixel);
2377 color = palette[(*curXor & (mask << shift)) >> shift];
2378 image->pixels[(i * image->width) + j + k] = (color.red << 16) +
2379 (color.green << 8) +
2387 for (j = 0; j < image->width; j += 8) {
2388 for (k = 0; k < 8; k++) {
2390 image->pixels[(i * image->width) + j + k] |=
2391 ((*curAnd & (1 << shift)) >> shift) ? 0x0 : (0xff << 24);
2401 for (i = image->height - 1; i >= 0; i--) {
2402 for (j = 0; j < image->width; j++) {
2403 image->pixels[(i * image->width) + j] = (*(curXor + 2) << 16) +
2404 (*(curXor + 1) << 8) + (*curXor);
2409 for (j = 0; j < image->width; j += 8) {
2410 for (k = 0; k < 8; k++) {
2412 image->pixels[(i * image->width) + j + k] |=
2413 ((*curAnd & (1 << shift)) >> shift) ? 0x0 : (0xff << 24);
2423 for (i = image->height - 1; i >= 0; i--) {
2424 for (j = 0; j < image->width; j++) {
2425 image->pixels[(i * image->width) + j] = (*(curXor + 3) << 24) +
2426 (*(curXor + 2) << 16) +
2427 (*(curXor + 1) << 8) +
2440 if (header.type == 2) {
2441 image->xhot = entries[entry].xhot;
2442 image->yhot = entries[entry].yhot;
2448 ret = XcursorImageLoadCursor(_display, image);
2451 XcursorImageDestroy(image);
2459 #endif // HAVE_XCURSOR
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
int get_display_width() const
Returns the width of the entire display, if it is known.
XIM get_im() const
Returns the input method opened for the pipe, or NULL if the input method could not be opened for som...
MouseMode get_mouse_mode() const
See set_mouse_mode().
virtual bool move_pointer(int device, int x, int y)
Forces the pointer to the indicated position within the window, if possible.
This graphics pipe represents the interface for creating graphics windows on an X-based client...
This is our own Panda specialization on the default STL map.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
This object represents a window on the desktop, not necessarily a Panda window.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
bool get_foreground() const
Returns true if the window is in the foreground.
void clear_foreground()
Removes the foreground specification from the properties.
bool get_fixed_size() const
Returns true if the window cannot be resized by the user, false otherwise.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
void clear_origin()
Removes the origin specification from the properties.
istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read...
ZOrder get_z_order() const
Returns the window's z_order.
bool get_undecorated() const
Returns true if the window has no border.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
bool get_minimized() const
Returns true if the window is minimized.
bool read(const Filename &filename, PNMFileType *type=NULL, bool report_unknown_type=true)
Reads the indicated image filename.
This is the base class for all two-component vectors and points.
void set_size(const LVector2i &size)
Specifies the requested size of the window, in pixels.
bool has_origin() const
Returns true if the window origin has been specified, false otherwise.
bool has_fixed_size() const
Returns true if set_fixed_size() has been specified.
int get_display_height() const
Returns the height of the entire display, if it is known.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
void clear_title()
Removes the title specification from the properties.
X11_Window get_root() const
Returns the handle to the root window on the pipe's display.
xel * get_array()
Directly access the underlying PNMImage array.
const string & get_title() const
Returns the window's title.
int get_y_origin() const
Returns the y coordinate of the window's top-left corner, not including decorations.
string get_close_request_event() const
Returns the name of the event set via set_close_request_event().
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
bool has_fullscreen() const
Returns true if set_fullscreen() has been specified.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
The name of a file, such as a texture file or an Egg file.
int get_screen() const
Returns the X screen number associated with the pipe.
OSHandle * get_os_handle() const
Returns the OS-specific handle stored internally to the WindowHandle wrapper.
bool get_fullscreen() const
Returns true if the window is in fullscreen mode.
void clear_mouse_mode()
Removes the mouse_mode specification from the properties.
void clear_size()
Removes the size specification from the properties.
An object to create GraphicsOutputs that share a particular 3-D API.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
X11_Cursor get_hidden_cursor()
Returns an invisible Cursor suitable for assigning to windows that have the cursor_hidden property se...
X11_Display * get_display() const
Returns a pointer to the X display associated with the pipe: the display on which to create the windo...
const Filename & get_cursor_filename() const
Returns the icon filename associated with the mouse cursor.
void set_origin(const LPoint2i &origin)
Specifies the origin on the screen (in pixels, relative to the top-left corner) at which the window s...
bool has_foreground() const
Returns true if set_foreground() has been specified.
const LVector2i & get_size() const
Returns size in pixels of the useful part of the window, not including decorations.
void clear_fixed_size()
Removes the fixed_size specification from the properties.
bool has_cursor_hidden() const
Returns true if set_cursor_hidden() has been specified.
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
PNMFileType * get_type_from_extension(const string &filename) const
Tries to determine what the PNMFileType is likely to be for a particular image file based on its exte...
This is a base class for the various different classes that represent the result of a frame of render...
Similar to MutexHolder, but for a light reentrant mutex.
bool has_z_order() const
Returns true if the window z_order has been specified, false otherwise.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
bool get_cursor_hidden() const
Returns true if the mouse cursor is invisible.
Holds the data that might be generated by a 2-d pointer input device, such as the mouse in the Graphi...
This class maintains the set of all known PNMFileTypes in the universe.
void set_foreground(bool foreground)
Specifies whether the window should be opened in the foreground (true), or left in the background (fa...
void clear_z_order()
Removes the z_order specification from the properties.
bool has_cursor_filename() const
Returns true if set_cursor_filename() has been specified.
A thread; that is, a lightweight process.
void clear_cursor_hidden()
Removes the cursor_hidden specification from the properties.
void set_minimized(bool minimized)
Specifies whether the window should be created minimized (true), or normal (false).
bool has_minimized() const
Returns true if set_minimized() has been specified.
Encapsulates all the communication with a particular instance of a given rendering backend...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
This class is the main interface to controlling the render process.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
void set_maxval(xelval maxval)
Rescales the image to the indicated maxval.
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
bool has_title() const
Returns true if the window title has been specified, false otherwise.
TypeHandle is the identifier used to differentiate C++ class types.
void clear_cursor_filename()
Removes the cursor_filename specification from the properties.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
bool has_size() const
Returns true if the window size has been specified, false otherwise.
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame...
bool is_fullscreen() const
Returns true if the window has been opened as a fullscreen window, false otherwise.
void set_open(bool open)
Specifies whether the window should be open.
int get_x_origin() const
Returns the x coordinate of the window's top-left corner, not including decorations.
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
void clear_fullscreen()
Removes the fullscreen specification from the properties.
Interfaces to the X11 window system.
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.