38using std::ostringstream;
43 int (*read)(XcursorFile *,
unsigned char *, int);
44 int (*write)(XcursorFile *,
unsigned char *, int);
45 int (*seek)(XcursorFile *, long, int);
48typedef struct _XcursorImage {
59static int xcursor_read(XcursorFile *file,
unsigned char *buf,
int len) {
60 istream* str = (istream*) file->closure;
61 str->read((
char*) buf, len);
65static int xcursor_write(XcursorFile *file,
unsigned char *buf,
int len) {
67 nassertr_always(
false, 0);
71static int xcursor_seek(XcursorFile *file,
long offset,
int whence) {
72 istream* str = (istream*) file->closure;
75 str->seekg(offset, istream::beg);
78 str->seekg(offset, istream::cur);
81 str->seekg(offset, istream::end);
100 GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
103 DCAST_INTO_V(x11_pipe, _pipe);
106 _xwindow = (X11_Window)
nullptr;
108 _visual_info =
nullptr;
111 if (x11_pipe->_have_xrandr) {
114 _XRRGetScreenInfo = x11_pipe->_XRRGetScreenInfo;
115 _XRRSetScreenConfig = x11_pipe->_XRRSetScreenConfig;
118 _awaiting_configure_since = -1;
119 _dga_mouse_enabled =
false;
120 _override_redirect = False;
121 _wm_delete_window = x11_pipe->_wm_delete_window;
124 add_input_device(device);
132~x11GraphicsWindow() {
145 nassertr(device >= 0 && device < (
int)_input_devices.size(),
MouseData());
151 if (device == 0 && !_dga_mouse_enabled && result._in_window &&
152 x11GraphicsPipe::_x_mutex.
try_lock()) {
154 if (_xwindow != None &&
155 XQueryPointer(_display, _xwindow, &event.xbutton.root,
156 &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
157 &event.xbutton.x, &event.xbutton.y, &event.xbutton.state)) {
159 result._xpos =
event.xbutton.x;
160 result._ypos =
event.xbutton.y;
163 x11GraphicsPipe::_x_mutex.
release();
190 if (!md.
get_in_window() || md.get_x() != x || md.get_y() != y) {
191 if (!_dga_mouse_enabled) {
193 XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y);
229 PStatTimer timer(_make_current_pcollector, current_thread);
231 begin_frame_spam(mode);
232 if (_gsg ==
nullptr) {
235 if (_awaiting_configure_since != -1) {
244 _gsg->reset_if_new();
246 if (mode == FM_render) {
248 clear_cube_map_selection();
252 return _gsg->begin_frame(current_thread);
262 end_frame_spam(mode);
263 nassertv(_gsg !=
nullptr);
265 if (mode == FM_render) {
270 _gsg->end_frame(current_thread);
272 if (mode == FM_render) {
274 clear_cube_map_selection();
291 if (_xwindow == (X11_Window)0) {
296 XKeyEvent keyrelease_event;
297 bool got_keyrelease_event =
false;
299 XConfigureEvent configure_event;
300 bool got_configure_event =
false;
303 bool changed_properties =
false;
305 while (XCheckIfEvent(_display, &event, check_event, (
char *)
this)) {
306 if (got_keyrelease_event) {
311 got_keyrelease_event =
false;
313 if (event.type == KeyPress &&
314 event.xkey.keycode == keyrelease_event.keycode &&
315 (event.xkey.time - keyrelease_event.time <= 1)) {
316 if (!XFilterEvent(&event, None)) {
319 handle_keystroke(event.xkey);
323 handle_keypress(event.xkey);
330 ButtonHandle raw_button = map_raw_button(keyrelease_event.keycode);
331 if (raw_button != ButtonHandle::none()) {
335 handle_keyrelease(keyrelease_event);
341 if (event.type == KeyPress) {
342 ButtonHandle raw_button = map_raw_button(event.xkey.keycode);
343 if (raw_button != ButtonHandle::none()) {
348 if (XFilterEvent(&event, None)) {
354 switch (event.type) {
358 case ConfigureNotify:
361 configure_event =
event.xconfigure;
362 got_configure_event =
true;
367 button = get_mouse_button(event.xbutton);
368 if (!_dga_mouse_enabled) {
375 button = get_mouse_button(event.xbutton);
376 if (!_dga_mouse_enabled) {
383 if (_dga_mouse_enabled) {
392 handle_keystroke(event.xkey);
393 handle_keypress(event.xkey);
400 keyrelease_event =
event.xkey;
401 got_keyrelease_event =
true;
405 if (_dga_mouse_enabled) {
419 changed_properties =
true;
425 changed_properties =
true;
430 changed_properties =
true;
435 changed_properties =
true;
438 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
442 if ((Atom)(event.xclient.data.l[0]) == _wm_delete_window) {
446 if (!close_request_event.empty()) {
449 throw_event(close_request_event);
458 system_changed_properties(properties);
466 x11display_cat.info()
467 <<
"DestroyNotify\n";
471 x11display_cat.warning()
472 <<
"unhandled X event type " <<
event.type <<
"\n";
476 if (got_configure_event) {
478 if (x11display_cat.is_debug() && _awaiting_configure_since != -1) {
479 unsigned long elapsed = (
unsigned long)(clock() - _awaiting_configure_since) / (CLOCKS_PER_SEC / 10000);
480 x11display_cat.debug()
481 <<
"Received ConfigureNotify event after "
482 << (elapsed / 10) <<
"." << (elapsed % 10) <<
" ms\n";
485 _awaiting_configure_since = -1;
492 properties.
set_origin(configure_event.x, configure_event.y);
493 properties.
set_size(configure_event.width, configure_event.height);
495 if (_properties.get_fixed_size()) {
501 if (configure_event.width != _fixed_size.get_x() ||
502 configure_event.height != _fixed_size.get_y()) {
503 XWindowChanges changes;
504 changes.width = _fixed_size.get_x();
505 changes.height = _fixed_size.get_y();
506 int value_mask = (CWWidth | CWHeight);
507 XConfigureWindow(_display, _xwindow, value_mask, &changes);
513 if (_properties.get_mouse_mode() == WindowProperties::M_confined) {
514 X11_Cursor cursor = None;
515 if (_properties.get_cursor_hidden()) {
517 DCAST_INTO_V(x11_pipe, _pipe);
521 XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync, GrabModeAsync,
522 _xwindow, cursor, CurrentTime);
525 changed_properties =
true;
527 else if (_awaiting_configure_since != -1) {
528 unsigned long elapsed = (clock() - _awaiting_configure_since);
529 if (elapsed > CLOCKS_PER_SEC / 10) {
531 if (x11display_cat.is_debug()) {
532 elapsed /= (CLOCKS_PER_SEC / 10000);
533 x11display_cat.debug()
534 <<
"Giving up on waiting for ConfigureNotify event after "
535 << (elapsed / 10) <<
"." << (elapsed % 10) <<
" ms\n";
537 _awaiting_configure_since = -1;
542 _properties.get_mouse_mode() == WindowProperties::M_confined ||
543 _dga_mouse_enabled)) {
545 DCAST_INTO_V(x11_pipe, _pipe);
550 X11_Cursor cursor = None;
551 if (_properties.get_cursor_hidden()) {
555 XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync, GrabModeAsync,
556 _xwindow, cursor, CurrentTime);
557 if (_dga_mouse_enabled) {
563 if (_dga_mouse_enabled) {
565 }
else if (_properties.get_mouse_mode() == WindowProperties::M_confined) {
566 XUngrabPointer(_display, CurrentTime);
571 if (changed_properties) {
572 system_changed_properties(properties);
575 if (got_keyrelease_event) {
578 ButtonHandle raw_button = map_raw_button(keyrelease_event.keycode);
579 if (raw_button != ButtonHandle::none()) {
583 handle_keyrelease(keyrelease_event);
601 if (_pipe ==
nullptr) {
608 DCAST_INTO_V(x11_pipe, _pipe);
614 bool is_fullscreen = _properties.has_fullscreen() && _properties.get_fullscreen();
617 if (want_fullscreen && properties.
has_origin()) {
623 if (want_fullscreen) {
627 LPoint2i center(0, 0);
628 if (_properties.has_origin()) {
629 center = _properties.get_origin();
630 if (_properties.has_size()) {
631 center += _properties.get_size() / 2;
634 int x, y, width, height;
638 int reqsizex, reqsizey;
642 }
else if (_properties.has_size()) {
643 reqsizex = _properties.get_x_size();
644 reqsizey = _properties.get_y_size();
656 || (width == reqsizex && height == reqsizey)
657 || !x11_pipe->_have_xrandr) {
663 if (x11display_cat.is_debug()) {
664 x11display_cat.debug()
665 <<
"Setting window to fullscreen on CRTC "
666 << width <<
"x" << height <<
"+" << x <<
"+" << y <<
"\n";
672 XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, _xwindow ? _xwindow : x11_pipe->
get_root());
673 SizeID old_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation);
674 SizeID new_size_id = (SizeID) -1;
678 xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes);
679 for (
int i = 0; i < num_sizes; ++i) {
680 if (xrrs[i].width == reqsizex &&
681 xrrs[i].height == reqsizey) {
685 if (new_size_id == (SizeID) -1) {
686 x11display_cat.error()
687 <<
"Videocard has no supported display resolutions at specified res ("
688 << reqsizex <<
" x " << reqsizey <<
")\n";
694 if (x11display_cat.is_debug()) {
695 x11display_cat.debug()
696 <<
"Switching to fullscreen with resolution "
697 << reqsizex <<
"x" << reqsizey <<
"\n";
700 if (new_size_id != old_size_id) {
701 _XRRSetScreenConfig(_display, conf, x11_pipe->
get_root(), new_size_id, _orig_rotation, CurrentTime);
702 if (_orig_size_id == (SizeID) -1) {
704 _orig_size_id = old_size_id;
716 if (_orig_size_id != (SizeID) -1) {
717 XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, x11_pipe->
get_root());
718 _XRRSetScreenConfig(_display, conf, x11_pipe->
get_root(), _orig_size_id, _orig_rotation, CurrentTime);
719 _orig_size_id = (SizeID) -1;
722 if (!properties.
has_origin() && _properties.has_origin()) {
723 properties.
set_origin(_properties.get_x_origin(), _properties.get_y_origin());
734 if (x_origin == -2) {
737 if (y_origin == -2) {
741 if (x_origin == -2) {
744 if (y_origin == -2) {
762 set_wm_properties(properties,
true);
767 _properties.set_title(properties.
get_title());
781 XWindowChanges changes;
784 if (_properties.get_fullscreen()) {
785 if (_properties.get_x_origin() != 0 ||
786 _properties.get_y_origin() != 0) {
789 value_mask |= CWX | CWY;
796 if (changes.x != -1) value_mask |= CWX;
797 if (changes.y != -1) value_mask |= CWY;
805 _fixed_size = _properties.get_size();
811 value_mask |= (CWWidth | CWHeight);
813 if (_properties.get_fixed_size()) {
814 _fixed_size = properties.
get_size();
825 case WindowProperties::Z_bottom:
826 changes.stack_mode = Below;
829 case WindowProperties::Z_normal:
830 changes.stack_mode = TopIf;
833 case WindowProperties::Z_top:
834 changes.stack_mode = Above;
838 value_mask |= (CWStackMode);
852 _properties.set_cursor_filename(cursor_filename);
856 _properties.set_cursor_filename(filename);
858 if (_properties.get_cursor_hidden()) {
861 }
else if (!cursor_filename.empty()) {
863 X11_Cursor cursor = get_cursor(cursor_filename);
864 XDefineCursor(_display, _xwindow, cursor);
867 XDefineCursor(_display, _xwindow, None);
871 if (!properties.has_mouse_mode() &&
872 _properties.get_mouse_mode() != WindowProperties::M_absolute) {
879 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
881 XSetInputFocus(_display, PointerRoot, RevertToPointerRoot, CurrentTime);
886 if (properties.has_mouse_mode()) {
888 case WindowProperties::M_absolute:
889 XUngrabPointer(_display, CurrentTime);
890 if (_dga_mouse_enabled) {
892 _dga_mouse_enabled =
false;
894 _properties.set_mouse_mode(WindowProperties::M_absolute);
898 case WindowProperties::M_relative:
899 if (!_dga_mouse_enabled) {
901 X11_Cursor cursor = None;
902 if (_properties.get_cursor_hidden()) {
904 DCAST_INTO_V(x11_pipe, _pipe);
908 if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
909 GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
910 x11display_cat.error() <<
"Failed to grab pointer!\n";
914 _properties.set_mouse_mode(WindowProperties::M_relative);
916 _dga_mouse_enabled =
true;
921 XQueryPointer(_display, _xwindow, &event.xbutton.root,
922 &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
923 &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
927 x11display_cat.warning()
928 <<
"XF86DGA extension not available, cannot enable relative mouse mode\n";
929 _dga_mouse_enabled =
false;
934 case WindowProperties::M_confined:
937 DCAST_INTO_V(x11_pipe, _pipe);
939 if (_dga_mouse_enabled) {
941 _dga_mouse_enabled =
false;
943 X11_Cursor cursor = None;
944 if (_properties.get_cursor_hidden()) {
948 if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
949 GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
950 x11display_cat.error() <<
"Failed to grab pointer!\n";
952 _properties.set_mouse_mode(WindowProperties::M_confined);
960 if (value_mask != 0) {
963 XReconfigureWMWindow(_display, _xwindow, _screen, value_mask, &changes);
966 _awaiting_configure_since = clock();
973void x11GraphicsWindow::
974mouse_mode_absolute() {
981void x11GraphicsWindow::
982mouse_mode_relative() {
989void x11GraphicsWindow::
991 if (_gsg !=
nullptr) {
996 if (_ic != (XIC)
nullptr) {
1001 if (_xwindow != (X11_Window)
nullptr) {
1002 XDestroyWindow(_display, _xwindow);
1003 _xwindow = (X11_Window)
nullptr;
1012 if (_orig_size_id != (SizeID) -1) {
1014 if (_pipe !=
nullptr) {
1016 DCAST_INTO_V(x11_pipe, _pipe);
1021 root = RootWindow(_display, _screen);
1023 XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, root);
1024 _XRRSetScreenConfig(_display, conf, root, _orig_size_id, _orig_rotation, CurrentTime);
1028 for (
auto item : _cursor_filenames) {
1029 XFreeCursor(_display, item.second);
1031 _cursor_filenames.clear();
1033 GraphicsWindow::close_window();
1040bool x11GraphicsWindow::
1042 if (_visual_info ==
nullptr) {
1044 x11display_cat.error()
1045 <<
"No X visual: cannot open window.\n";
1050 DCAST_INTO_R(x11_pipe, _pipe,
false);
1052 if (!_properties.has_origin()) {
1053 _properties.set_origin(0, 0);
1055 if (!_properties.has_size()) {
1056 _properties.set_size(100, 100);
1062 X11_Window parent_window = x11_pipe->
get_root();
1063 WindowHandle *window_handle = _properties.get_parent_window();
1064 if (window_handle !=
nullptr) {
1065 x11display_cat.info()
1066 <<
"Got parent_window " << *window_handle <<
"\n";
1068 if (os_handle !=
nullptr) {
1069 x11display_cat.info()
1070 <<
"os_handle type " << os_handle->get_type() <<
"\n";
1072 if (os_handle->
is_of_type(NativeWindowHandle::X11Handle::get_class_type())) {
1073 NativeWindowHandle::X11Handle *x11_handle = DCAST(NativeWindowHandle::X11Handle, os_handle);
1074 parent_window = x11_handle->get_handle();
1075 }
else if (os_handle->
is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
1077 parent_window = (X11_Window)int_handle->get_handle();
1081 _parent_window_handle = window_handle;
1084 ButtonPressMask | ButtonReleaseMask |
1085 KeyPressMask | KeyReleaseMask |
1086 EnterWindowMask | LeaveWindowMask |
1088 FocusChangeMask | StructureNotifyMask;
1091 XSetWindowAttributes wa;
1092 wa.background_pixel = XBlackPixel(_display, _screen);
1093 wa.border_pixel = 0;
1094 wa.colormap = _colormap;
1095 wa.event_mask = _event_mask;
1096 wa.override_redirect = _override_redirect;
1098 unsigned long attrib_mask =
1099 CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
1101 _xwindow = XCreateWindow
1102 (_display, parent_window,
1103 _properties.get_x_origin(), _properties.get_y_origin(),
1104 _properties.get_x_size(), _properties.get_y_size(),
1105 0, _visual_info->depth, InputOutput,
1106 _visual_info->visual, attrib_mask, &wa);
1108 if (_xwindow == (X11_Window)0) {
1109 x11display_cat.error()
1110 <<
"failed to create X window.\n";
1114 if (_properties.get_fixed_size()) {
1115 _fixed_size = _properties.get_size();
1118 set_wm_properties(_properties,
false);
1124 XIM im = x11_pipe->
get_im();
1127 _ic = XCreateIC(im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
1128 XNClientWindow, _xwindow,
nullptr);
1129 if (_ic == (XIC)
nullptr) {
1130 x11display_cat.warning()
1131 <<
"Couldn't create input context.\n";
1135 if (_properties.get_cursor_hidden()) {
1138 }
else if (_properties.has_cursor_filename() && !_properties.get_cursor_filename().empty()) {
1140 X11_Cursor cursor = get_cursor(_properties.get_cursor_filename());
1141 XDefineCursor(_display, _xwindow, cursor);
1144 XMapWindow(_display, _xwindow);
1146 if (_properties.get_raw_mice()) {
1149 if (x11display_cat.is_debug()) {
1150 x11display_cat.debug()
1151 <<
"Raw mice not requested.\n";
1156 _window_handle = NativeWindowHandle::make_x11(_xwindow);
1159 if (_parent_window_handle !=
nullptr) {
1160 _parent_window_handle->attach_child(_window_handle);
1178void x11GraphicsWindow::
1179set_wm_properties(
const WindowProperties &properties,
bool already_mapped) {
1181 DCAST_INTO_V(x11_pipe, _pipe);
1184 XTextProperty window_name;
1185 XTextProperty *window_name_p =
nullptr;
1187 const char *name = properties.
get_title().c_str();
1188 if (XStringListToTextProperty((
char **)&name, 1, &window_name) != 0) {
1189 window_name_p = &window_name;
1192#ifdef X_HAVE_UTF8_STRING
1193 XTextProperty wm_name;
1194 if (Xutf8TextListToTextProperty(_display, (
char **)&name, 1,
1195 XUTF8StringStyle, &wm_name) == Success) {
1196 XSetTextProperty(_display, _xwindow, &wm_name, x11_pipe->_net_wm_name);
1197 XFree(wm_name.value);
1204 XSizeHints *size_hints_p =
nullptr;
1206 size_hints_p = XAllocSizeHints();
1207 if (size_hints_p !=
nullptr) {
1211 size_hints_p->flags |= USPosition;
1213 LVecBase2i size = _properties.get_size();
1216 size_hints_p->width = size.get_x();
1217 size_hints_p->height = size.get_y();
1218 size_hints_p->flags |= USSize;
1221 size_hints_p->min_width = size.get_x();
1222 size_hints_p->min_height = size.get_y();
1223 size_hints_p->max_width = size.get_x();
1224 size_hints_p->max_height = size.get_y();
1225 size_hints_p->flags |= (PMinSize | PMaxSize);
1232 XWMHints *wm_hints_p =
nullptr;
1233 wm_hints_p = XAllocWMHints();
1234 if (wm_hints_p !=
nullptr) {
1236 wm_hints_p->initial_state = IconicState;
1238 wm_hints_p->initial_state = NormalState;
1240 wm_hints_p->flags = StateHint;
1246 static const int max_type_data = 32;
1247 int32_t type_data[max_type_data];
1248 int next_type_data = 0;
1250 static const int max_state_data = 32;
1251 int32_t state_data[max_state_data];
1252 int next_state_data = 0;
1254 static const int max_set_data = 32;
1257 inline SetAction() { }
1258 inline SetAction(Atom state, Atom action) : _state(state), _action(action) { }
1262 SetAction set_data[max_set_data];
1263 int next_set_data = 0;
1269 type_data[next_type_data++] = x11_pipe->_net_wm_window_type_fullscreen;
1272 state_data[next_state_data++] = x11_pipe->_net_wm_state_fullscreen;
1275 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 1);
1278 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0);
1291 XClassHint *class_hints_p =
nullptr;
1292 if (!x_wm_class.empty()) {
1294 class_hints_p = XAllocClassHint();
1295 class_hints_p->res_class = (
char*) x_wm_class.c_str();
1296 if (!x_wm_class_name.empty()) {
1297 class_hints_p->res_name = (
char*) x_wm_class_name.c_str();
1301 class_hints_p = XAllocClassHint();
1302 class_hints_p->res_class = (
char*)
"Undecorated";
1306 type_data[next_type_data++] = x11_pipe->_net_wm_window_type_splash;
1311 case WindowProperties::Z_bottom:
1312 state_data[next_state_data++] = x11_pipe->_net_wm_state_below;
1313 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1314 x11_pipe->_net_wm_state_add);
1315 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1316 x11_pipe->_net_wm_state_remove);
1319 case WindowProperties::Z_normal:
1320 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1321 x11_pipe->_net_wm_state_remove);
1322 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1323 x11_pipe->_net_wm_state_remove);
1326 case WindowProperties::Z_top:
1327 state_data[next_state_data++] = x11_pipe->_net_wm_state_above;
1328 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1329 x11_pipe->_net_wm_state_remove);
1330 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1331 x11_pipe->_net_wm_state_add);
1336 nassertv(next_type_data < max_type_data);
1337 nassertv(next_state_data < max_state_data);
1338 nassertv(next_set_data < max_set_data);
1341 int32_t pid = getpid();
1342 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_pid,
1343 XA_CARDINAL, 32, PropModeReplace,
1344 (
unsigned char *)&pid, 1);
1349 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_bypass_compositor,
1350 XA_CARDINAL, 32, PropModeReplace,
1351 (
unsigned char *)&compositor, 1);
1354 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_window_type,
1355 XA_ATOM, 32, PropModeReplace,
1356 (
unsigned char *)type_data, next_type_data);
1359 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_state,
1360 XA_ATOM, 32, PropModeReplace,
1361 (
unsigned char *)state_data, next_state_data);
1363 if (already_mapped) {
1369 DCAST_INTO_V(x11_pipe, _pipe);
1371 for (
int i = 0; i < next_set_data; ++i) {
1372 XClientMessageEvent event;
1373 memset(&event, 0,
sizeof(event));
1374 event.type = ClientMessage;
1375 event.send_event = True;
1376 event.display = _display;
1377 event.window = _xwindow;
1378 event.message_type = x11_pipe->_net_wm_state;
1380 event.data.l[0] = set_data[i]._action;
1381 event.data.l[1] = set_data[i]._state;
1382 event.data.l[2] = 0;
1383 event.data.l[3] = 1;
1385 XSendEvent(_display, x11_pipe->
get_root(), True, SubstructureNotifyMask | SubstructureRedirectMask, (XEvent *)&event);
1389 XSetWMProperties(_display, _xwindow, window_name_p, window_name_p,
1390 nullptr, 0, size_hints_p, wm_hints_p, class_hints_p);
1392 if (size_hints_p !=
nullptr) {
1393 XFree(size_hints_p);
1395 if (wm_hints_p !=
nullptr) {
1398 if (class_hints_p !=
nullptr) {
1399 XFree(class_hints_p);
1405 Atom protocols[] = {
1409 XSetWMProtocols(_display, _xwindow, protocols,
1410 sizeof(protocols) /
sizeof(Atom));
1417void x11GraphicsWindow::
1418setup_colormap(XVisualInfo *visual) {
1420 DCAST_INTO_V(x11_pipe, _pipe);
1421 X11_Window root_window = x11_pipe->
get_root();
1423 _colormap = XCreateColormap(_display, root_window,
1424 visual->visual, AllocNone);
1431void x11GraphicsWindow::
1433#ifdef PHAVE_LINUX_INPUT_H
1434 bool any_present =
false;
1435 bool any_mice =
false;
1437 for (
int i=0; i<64; i++) {
1439 fnb <<
"/dev/input/event" << i;
1440 string fn = fnb.str();
1441 int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0);
1443 EvdevInputDevice *device =
new EvdevInputDevice(
nullptr, fd);
1444 nassertd(device != NULL)
continue;
1446 if (device->has_pointer()) {
1447 add_input_device(device);
1449 x11display_cat.info()
1450 <<
"Raw mouse " << _input_devices.size()
1451 <<
" detected: " << device->get_name() <<
"\n";
1457 if (errno == ENOENT || errno == ENOTDIR) {
1461 x11display_cat.error()
1462 <<
"Opening raw mice: " << strerror(errno) <<
" " << fn <<
"\n";
1468 _properties.set_raw_mice(
true);
1470 }
else if (!any_present) {
1471 x11display_cat.error() <<
1472 "Opening raw mice: files not found: /dev/input/event*\n";
1475 x11display_cat.error() <<
1476 "Opening raw mice: no mouse devices detected in /dev/input/event*\n";
1479 x11display_cat.error() <<
1480 "Opening raw mice: panda not compiled with raw mouse support.\n";
1487void x11GraphicsWindow::
1488handle_keystroke(XKeyEvent &event) {
1489 if (!_dga_mouse_enabled) {
1495 static const int buffer_size = 256;
1496 wchar_t buffer[buffer_size];
1498 int len = XwcLookupString(_ic, &event, buffer, buffer_size,
nullptr,
1500 if (status == XBufferOverflow) {
1501 x11display_cat.error()
1502 <<
"Overflowed input buffer.\n";
1506 for (
int i = 0; i < len; i++) {
1522void x11GraphicsWindow::
1523handle_keypress(XKeyEvent &event) {
1524 if (!_dga_mouse_enabled) {
1530 if (button != ButtonHandle::none()) {
1531 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
1534 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
1537 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
1540 if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
1550void x11GraphicsWindow::
1551handle_keyrelease(XKeyEvent &event) {
1552 if (!_dga_mouse_enabled) {
1558 if (button != ButtonHandle::none()) {
1559 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
1560 _input->
button_up(KeyboardButton::control());
1562 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
1563 _input->
button_up(KeyboardButton::shift());
1565 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
1566 _input->
button_up(KeyboardButton::alt());
1568 if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
1569 _input->
button_up(KeyboardButton::meta());
1580get_button(XKeyEvent &key_event,
bool allow_shift) {
1581 KeySym key = XLookupKeysym(&key_event, 0);
1583 if ((key_event.state & Mod2Mask) != 0) {
1598 case XK_KP_Multiply:
1600 case XK_KP_Separator:
1601 case XK_KP_Subtract:
1624 k2 = XLookupKeysym(&key_event, 1);
1625 button = map_button(k2);
1626 if (button != ButtonHandle::none()) {
1640 if ((key_event.state & ShiftMask) != 0) {
1641 KeySym k2 = XLookupKeysym(&key_event, 1);
1643 if (button != ButtonHandle::none()) {
1651 if ((key_event.state & (ShiftMask | LockMask)) != 0) {
1652 if (key >= XK_a && key <= XK_z) {
1653 key += (XK_A - XK_a);
1658 return map_button(key);
1666map_button(KeySym key)
const {
1669 return ButtonHandle::none();
1671 return KeyboardButton::backspace();
1674 return KeyboardButton::tab();
1677 return KeyboardButton::enter();
1679 return KeyboardButton::escape();
1682 return KeyboardButton::space();
1703 case XK_KP_Multiply:
1709 case XK_KP_Separator:
1712 case XK_KP_Subtract:
1817 case XK_bracketleft:
1821 case XK_bracketright:
1823 case XK_asciicircum:
1892 return KeyboardButton::f1();
1895 return KeyboardButton::f2();
1898 return KeyboardButton::f3();
1901 return KeyboardButton::f4();
1903 return KeyboardButton::f5();
1905 return KeyboardButton::f6();
1907 return KeyboardButton::f7();
1909 return KeyboardButton::f8();
1911 return KeyboardButton::f9();
1913 return KeyboardButton::f10();
1915 return KeyboardButton::f11();
1917 return KeyboardButton::f12();
1920 return KeyboardButton::left();
1923 return KeyboardButton::up();
1926 return KeyboardButton::right();
1929 return KeyboardButton::down();
1932 return KeyboardButton::page_up();
1935 return KeyboardButton::page_down();
1938 return KeyboardButton::home();
1941 return KeyboardButton::end();
1944 return KeyboardButton::insert();
1947 return KeyboardButton::del();
1949 return KeyboardButton::num_lock();
1950 case XK_Scroll_Lock:
1951 return KeyboardButton::scroll_lock();
1953 return KeyboardButton::print_screen();
1955 return KeyboardButton::pause();
1957 return KeyboardButton::menu();
1959 return KeyboardButton::lshift();
1961 return KeyboardButton::rshift();
1963 return KeyboardButton::lcontrol();
1965 return KeyboardButton::rcontrol();
1967 return KeyboardButton::lalt();
1969 return KeyboardButton::ralt();
1972 return KeyboardButton::lmeta();
1975 return KeyboardButton::rmeta();
1977 return KeyboardButton::caps_lock();
1979 return KeyboardButton::shift_lock();
1981 if (x11display_cat.is_debug()) {
1982 x11display_cat.debug()
1983 <<
"Unrecognized keysym 0x" << std::hex << key << std::dec <<
"\n";
1985 return ButtonHandle::none();
1992map_raw_button(KeyCode key)
const {
1993#ifdef PHAVE_LINUX_INPUT_H
1998 int index = key - 8;
1999 if (index > 0 && index < 128) {
2000 return EvdevInputDevice::map_button(index);
2003 return ButtonHandle::none();
2011get_mouse_button(XButtonEvent &button_event) {
2012 int index = button_event.button;
2013 if (index == x_wheel_up_button) {
2015 }
else if (index == x_wheel_down_button) {
2017 }
else if (index == x_wheel_left_button) {
2019 }
else if (index == x_wheel_right_button) {
2021 }
else if (index >= 8) {
2033get_keyboard_map()
const {
2040 for (
int k = 9; k <= 135; ++k) {
2041 if (k >= 78 && k <= 91) {
2049 if (raw_button == ButtonHandle::none()) {
2053 KeySym sym = XkbKeycodeToKeysym(_display, k, 0, 0);
2059 if (sym >= XK_exclam && sym <= XK_asciitilde) {
2060 label = toupper((
char)sym);
2062 else if (sym >= XK_F1 && sym <= XK_F35) {
2063 label =
"F" + format_string(sym - XK_F1 + 1);
2065 else if (sym > 0x1000000 && sym < 0x1110000) {
2067 char32_t ch = sym & 0x0ffffff;
2068 if ((ch & ~0x7f) == 0) {
2069 label = string(1, (
char)ch);
2071 else if ((ch & ~0x7ff) == 0) {
2073 string(1, (
char)((ch >> 6) | 0xc0)) +
2074 string(1, (
char)((ch & 0x3f) | 0x80));
2076 else if ((ch & ~0xffff) == 0) {
2078 string(1, (
char)((ch >> 12) | 0xe0)) +
2079 string(1, (
char)(((ch >> 6) & 0x3f) | 0x80)) +
2080 string(1, (
char)((ch & 0x3f) | 0x80));
2084 string(1, (
char)((ch >> 18) | 0xf0)) +
2085 string(1, (
char)(((ch >> 12) & 0x3f) | 0x80)) +
2086 string(1, (
char)(((ch >> 6) & 0x3f) | 0x80)) +
2087 string(1, (
char)((ch & 0x3f) | 0x80));
2090 else if ((sym >= XK_exclamdown && sym <= XK_umacron)
2091 || (sym >= XK_OE && sym <= XK_Ydiaeresis)
2092 || (sym >= XK_Serbian_dje && sym <= XK_Cyrillic_HARDSIGN)
2093 || (sym >= XK_kana_fullstop && sym <= XK_semivoicedsound)
2094 || (sym >= XK_Arabic_comma && sym <= XK_Arabic_sukun)
2095 || (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_omega)
2096 || (sym >= XK_hebrew_doublelowline && sym <= XK_hebrew_taw)
2097 || (sym >= XK_Thai_kokai && sym <= XK_Thai_lekkao)
2098 || (sym >= XK_Hangul_Kiyeog && sym <= XK_Hangul_J_YeorinHieuh)
2099 || sym == XK_EuroSign
2100 || sym == XK_Korean_Won) {
2103 int nbytes = XkbTranslateKeySym(_display, &sym, 0, buffer, 255, 0);
2105 label.assign(buffer, nbytes);
2109 if (button == ButtonHandle::none() && label.empty()) {
2124Bool x11GraphicsWindow::
2125check_event(X11_Display *display, XEvent *event,
char *arg) {
2129 return (event->xany.window == self->_xwindow);
2136X11_Cursor x11GraphicsWindow::
2137get_cursor(
const Filename &filename) {
2139 DCAST_INTO_R(x11_pipe, _pipe, None);
2141 if (x11_pipe->_xcursor_size == -1) {
2142 x11display_cat.info()
2143 <<
"libXcursor.so.1 not available; cannot change mouse cursor.\n";
2149 if (fi != _cursor_filenames.end()) {
2158 x11display_cat.warning()
2159 <<
"Could not find cursor filename " << filename <<
"\n";
2162 fi = _cursor_filenames.find(resolved);
2163 if (fi != _cursor_filenames.end()) {
2169 if (str ==
nullptr) {
2170 x11display_cat.warning()
2171 <<
"Could not open cursor file " << filename <<
"\n";
2177 str->read(magic, 4);
2179 x11display_cat.warning()
2180 <<
"Could not read from cursor file " << filename <<
"\n";
2186 str->putback(magic[3]);
2187 str->putback(magic[2]);
2188 str->putback(magic[1]);
2189 str->putback(magic[0]);
2191 X11_Cursor h = None;
2192 if (memcmp(magic,
"Xcur", 4) == 0) {
2194 x11display_cat.debug()
2195 <<
"Loading X11 cursor " << filename <<
"\n";
2197 xcfile.closure = str;
2198 xcfile.read = &xcursor_read;
2199 xcfile.write = &xcursor_write;
2200 xcfile.seek = &xcursor_seek;
2202 XcursorImages *images = x11_pipe->_XcursorXcFileLoadImages(&xcfile, x11_pipe->_xcursor_size);
2203 if (images !=
nullptr) {
2204 h = x11_pipe->_XcursorImagesLoadCursor(_display, images);
2205 x11_pipe->_XcursorImagesDestroy(images);
2208 }
else if (memcmp(magic,
"\0\0\1\0", 4) == 0
2209 || memcmp(magic,
"\0\0\2\0", 4) == 0) {
2211 x11display_cat.debug()
2212 <<
"Loading Windows cursor " << filename <<
"\n";
2220 x11display_cat.warning()
2221 <<
"X11 cursor filename '" << resolved <<
"' could not be loaded!\n";
2224 _cursor_filenames[resolved] = h;
2232X11_Cursor x11GraphicsWindow::
2233read_ico(istream &ico) {
2235 DCAST_INTO_R(x11_pipe, _pipe, None);
2239 uint16_t reserved, type, count;
2243 uint8_t width, height, colorCount, reserved;
2244 uint16_t xhot, yhot;
2245 uint32_t bitmapSize, offset;
2249 uint32_t headerSize, width, height;
2250 uint16_t planes, bitsPerPixel;
2251 uint32_t compression, imageSize, xPixelsPerM, yPixelsPerM, colorsUsed, colorsImportant;
2255 uint8_t blue, green, red, reserved;
2259 unsigned int j, k, mask, shift;
2260 size_t colorCount, bitsPerPixel;
2262 IcoInfoHeader infoHeader;
2263 IcoEntry *entries =
nullptr;
2264 IcoColor color, *palette =
nullptr;
2266 size_t xorBmpSize, andBmpSize;
2267 char *curXor, *curAnd;
2268 char *xorBmp =
nullptr, *andBmp =
nullptr;
2269 XcursorImage *image =
nullptr;
2270 X11_Cursor ret = None;
2272 int def_size = x11_pipe->_xcursor_size;
2275 ico.read(
reinterpret_cast<char *
>(&header),
sizeof(IcoHeader));
2276 if (!ico.good())
goto cleanup;
2277 if (header.type != 1 && header.type != 2)
goto cleanup;
2278 if (header.count < 1)
goto cleanup;
2281 entries =
new IcoEntry[header.count];
2282 ico.read(
reinterpret_cast<char *
>(entries), header.count *
sizeof(IcoEntry));
2283 if (!ico.good())
goto cleanup;
2284 for (i = 1; i < header.count; i++) {
2285 if (entries[i].width == def_size && entries[i].height == def_size) {
2290 if (entries[i].width > entries[entry].width ||
2291 entries[i].height > entries[entry].height)
2296 ico.seekg(entries[entry].offset);
2297 if (!ico.good())
goto cleanup;
2299 if (ico.peek() == 0x89) {
2313 unsigned int *dest = image->pixels;
2315 if (alpha !=
nullptr) {
2316 for (
size_t p = 0; p < num_pixels; ++p) {
2317 *dest++ = (*alpha << 24U) | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
2322 for (
size_t p = 0; p < num_pixels; ++p) {
2323 *dest++ = 0xff000000U | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
2329 ico.read(
reinterpret_cast<char *
>(&infoHeader),
sizeof(IcoInfoHeader));
2330 if (!ico.good())
goto cleanup;
2331 bitsPerPixel = infoHeader.bitsPerPixel;
2333 if (infoHeader.compression != 0)
goto cleanup;
2336 if (bitsPerPixel != 24 && bitsPerPixel != 32) {
2337 colorCount = 1 << bitsPerPixel;
2338 palette =
new IcoColor[colorCount];
2339 ico.read(
reinterpret_cast<char *
>(palette), colorCount *
sizeof(IcoColor));
2340 if (!ico.good())
goto cleanup;
2343 int and_stride = ((infoHeader.width >> 3) + 3) & ~0x03;
2346 xorBmpSize = (infoHeader.width * (infoHeader.height / 2) * bitsPerPixel) / 8;
2347 andBmpSize = and_stride * (infoHeader.height / 2);
2348 curXor = xorBmp =
new char[xorBmpSize];
2349 curAnd = andBmp =
new char[andBmpSize];
2350 ico.read(xorBmp, xorBmpSize);
2351 if (!ico.good())
goto cleanup;
2352 ico.read(andBmp, andBmpSize);
2353 if (!ico.good())
goto cleanup;
2355 image = x11_pipe->_XcursorImageCreate(infoHeader.width, infoHeader.height / 2);
2358 switch (bitsPerPixel) {
2364 mask = ((1 << bitsPerPixel) - 1);
2365 for (i = image->height - 1; i >= 0; i--) {
2366 for (j = 0; j < image->width; j += 8 / bitsPerPixel) {
2367 for (k = 0; k < 8 / bitsPerPixel; k++) {
2368 shift = 8 - ((k + 1) * bitsPerPixel);
2369 color = palette[(*curXor & (mask << shift)) >> shift];
2370 image->pixels[(i * image->width) + j + k] = (color.red << 16) +
2371 (color.green << 8) +
2379 for (j = 0; j < image->width; j += 8) {
2380 for (k = 0; k < 8; k++) {
2382 image->pixels[(i * image->width) + j + k] |=
2383 ((*curAnd & (1 << shift)) >> shift) ? 0x0 : (0xff << 24);
2393 for (i = image->height - 1; i >= 0; i--) {
2394 for (j = 0; j < image->width; j++) {
2395 shift = 7 - (j & 0x7);
2396 uint32_t alpha = (curAnd[j >> 3] & (1 << shift)) ? 0 : 0xff000000U;
2397 image->pixels[(i * image->width) + j] = (uint8_t)curXor[0]
2398 | ((uint8_t)curXor[1] << 8u)
2399 | ((uint8_t)curXor[2] << 16u)
2403 curAnd += and_stride;
2409 for (i = image->height - 1; i >= 0; i--) {
2410 for (j = 0; j < image->width; j++) {
2411 image->pixels[(i * image->width) + j] = (*(curXor + 3) << 24) +
2412 (*(curXor + 2) << 16) +
2413 (*(curXor + 1) << 8) +
2426 if (header.type == 2) {
2427 image->xhot = entries[entry].xhot;
2428 image->yhot = entries[entry].yhot;
2434 ret = x11_pipe->_XcursorImageLoadCursor(_display, image);
2437 x11_pipe->_XcursorImageDestroy(image);
get_real_time
Returns the actual number of seconds elapsed since the ClockObject was created, or since it was last ...
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
virtual bool is_any_clear_active() const
Returns true if any of the clear types (so far there are just color or depth) have been set active,...
The name of a file, such as a texture file or an Egg file.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
virtual void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
An object to create GraphicsOutputs that share a particular 3-D API.
get_display_width
Returns the width of the entire display, if it is known.
get_display_height
Returns the height of the entire display, if it is known.
Encapsulates all the communication with a particular instance of a given rendering backend.
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
bool is_fullscreen() const
Returns true if the window has been opened as a fullscreen window, false otherwise.
get_close_request_event
Returns the name of the event set via set_close_request_event().
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
Similar to MutexHolder, but for a light mutex.
bool try_lock()
Alias for try_acquire() to match C++11 semantics.
void release() const
Releases the lightReMutex.
Similar to MutexHolder, but for a light reentrant mutex.
This class maintains the set of all known PNMFileTypes in the universe.
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
PNMFileType * get_type_from_extension(const std::string &filename) const
Tries to determine what the PNMFileType is likely to be for a particular image file based on its exte...
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
void set_maxval(xelval maxval)
Rescales the image to the indicated maxval.
bool read(const Filename &filename, PNMFileType *type=nullptr, bool report_unknown_type=true)
Reads the indicated image filename.
xel * get_array()
Directly access the underlying PNMImage array.
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Holds the data that might be generated by a 2-d pointer input device, such as the mouse in the Graphi...
get_in_window
If this returns false, the pointer is not currently present in the window and the values returned by ...
A thread; that is, a lightweight process.
TypeHandle is the identifier used to differentiate C++ class types.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
A hierarchy of directories and files that appears to be one continuous file system,...
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
std::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,...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
This object represents a window on the desktop, not necessarily a Panda window.
get_os_handle
Returns the OS-specific handle stored internally to the WindowHandle wrapper.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
clear_cursor_filename
Removes the cursor_filename specification from the properties.
has_cursor_filename
Returns true if set_cursor_filename() has been specified.
get_title
Returns the window's title.
get_undecorated
Returns true if the window has no border.
clear_cursor_hidden
Removes the cursor_hidden specification from the properties.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
set_mouse_mode
Specifies the mode in which the window is to operate its mouse pointer.
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
int get_y_origin() const
Returns the y coordinate of the window's top-left corner, not including decorations.
clear_z_order
Removes the z_order specification from the properties.
get_minimized
Returns true if the window is minimized.
clear_mouse_mode
Removes the mouse_mode specification from the properties.
has_fullscreen
Returns true if set_fullscreen() has been specified.
has_size
Returns true if the window size has been specified, false otherwise.
clear_title
Removes the title specification from the properties.
get_size
Returns size in pixels of the useful part of the window, not including decorations.
clear_origin
Removes the origin specification from the properties.
has_minimized
Returns true if set_minimized() has been specified.
set_size
Specifies the requested size of the window, in pixels.
get_foreground
Returns true if the window is in the foreground.
has_fixed_size
Returns true if set_fixed_size() has been specified.
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
clear_fixed_size
Removes the fixed_size specification from the properties.
clear_fullscreen
Removes the fullscreen specification from the properties.
set_foreground
Specifies whether the window should be opened in the foreground (true), or left in the background (fa...
clear_size
Removes the size specification from the properties.
set_open
Specifies whether the window should be open.
get_z_order
Returns the window's z_order.
get_fullscreen
Returns true if the window is in fullscreen mode.
has_title
Returns true if the window title has been specified, false otherwise.
get_mouse_mode
See set_mouse_mode().
has_origin
Returns true if the window origin has been specified, false otherwise.
has_foreground
Returns true if set_foreground() has been specified.
clear_foreground
Removes the foreground specification from the properties.
get_cursor_filename
Returns the icon filename associated with the mouse cursor.
get_cursor_hidden
Returns true if the mouse cursor is invisible.
has_cursor_hidden
Returns true if set_cursor_hidden() has been specified.
set_minimized
Specifies whether the window should be created minimized (true), or normal (false).
has_z_order
Returns true if the window z_order has been specified, false otherwise.
get_fixed_size
Returns true if the window cannot be resized by the user, false otherwise.
int get_x_origin() const
Returns the x coordinate of the window's top-left corner, not including decorations.
set_origin
Specifies the origin on the screen (in pixels, relative to the top-left corner) at which the window s...
This is our own Panda specialization on the default STL map.
This graphics pipe represents the interface for creating graphics windows on an X-based client.
X11_Window get_root() const
Returns the handle to the root window on the pipe's display.
X11_Display * get_display() const
Returns a pointer to the X display associated with the pipe: the display on which to create the windo...
RRCrtc find_fullscreen_crtc(const LPoint2i &point, int &x, int &y, int &width, int &height)
Finds a CRTC for going fullscreen to, at the given origin.
int get_screen() const
Returns the X screen number associated with the pipe.
XIM get_im() const
Returns the input method opened for the pipe, or NULL if the input method could not be opened for som...
bool supports_relative_mouse() const
Returns true if relative mouse mode is supported on this display.
bool enable_relative_mouse()
Enables relative mouse mode for this display.
X11_Cursor get_hidden_cursor()
Returns an invisible Cursor suitable for assigning to windows that have the cursor_hidden property se...
void disable_relative_mouse()
Disables relative mouse mode for this display.
Interfaces to the X11 window system.
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.
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
virtual void clear(Thread *current_thread)
Clears the entire framebuffer before rendering, according to the settings of get_color_clear_active()...
virtual bool move_pointer(int device, int x, int y)
Forces the pointer to the indicated position within the window, if possible.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
virtual MouseData get_pointer(int device) const
Returns the MouseData associated with the nth input device's pointer.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BEGIN_PUBLISH typedef PointerData MouseData
Deprecated alias for PointerData.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.