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 =
false;
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() {
133 if (!_cursor_filenames.empty()) {
135 for (
auto item : _cursor_filenames) {
136 XFreeCursor(_display, item.second);
151 nassertr(device >= 0 && device < (
int)_input_devices.size(),
MouseData());
157 if (device == 0 && !_dga_mouse_enabled && result._in_window &&
158 x11GraphicsPipe::_x_mutex.
try_lock()) {
160 if (_xwindow != None &&
161 XQueryPointer(_display, _xwindow, &event.xbutton.root,
162 &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
163 &event.xbutton.x, &event.xbutton.y, &event.xbutton.state)) {
165 result._xpos =
event.xbutton.x;
166 result._ypos =
event.xbutton.y;
169 x11GraphicsPipe::_x_mutex.
release();
196 if (!md.
get_in_window() || md.get_x() != x || md.get_y() != y) {
197 if (!_dga_mouse_enabled) {
199 XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y);
235 PStatTimer timer(_make_current_pcollector, current_thread);
237 begin_frame_spam(mode);
238 if (_gsg ==
nullptr) {
241 if (_awaiting_configure) {
250 _gsg->reset_if_new();
252 if (mode == FM_render) {
254 clear_cube_map_selection();
258 return _gsg->begin_frame(current_thread);
268 end_frame_spam(mode);
269 nassertv(_gsg !=
nullptr);
271 if (mode == FM_render) {
276 _gsg->end_frame(current_thread);
278 if (mode == FM_render) {
280 clear_cube_map_selection();
297 if (_xwindow == (X11_Window)0) {
302 XKeyEvent keyrelease_event;
303 bool got_keyrelease_event =
false;
305 XConfigureEvent configure_event;
306 bool got_configure_event =
false;
309 bool changed_properties =
false;
311 while (XCheckIfEvent(_display, &event, check_event, (
char *)
this)) {
312 if (got_keyrelease_event) {
317 got_keyrelease_event =
false;
319 if (event.type == KeyPress &&
320 event.xkey.keycode == keyrelease_event.keycode &&
321 (event.xkey.time - keyrelease_event.time <= 1)) {
322 if (!XFilterEvent(&event, None)) {
325 handle_keystroke(event.xkey);
329 handle_keypress(event.xkey);
336 ButtonHandle raw_button = map_raw_button(keyrelease_event.keycode);
337 if (raw_button != ButtonHandle::none()) {
341 handle_keyrelease(keyrelease_event);
347 if (event.type == KeyPress) {
348 ButtonHandle raw_button = map_raw_button(event.xkey.keycode);
349 if (raw_button != ButtonHandle::none()) {
354 if (XFilterEvent(&event, None)) {
360 switch (event.type) {
364 case ConfigureNotify:
367 configure_event =
event.xconfigure;
368 got_configure_event =
true;
373 button = get_mouse_button(event.xbutton);
374 if (!_dga_mouse_enabled) {
381 button = get_mouse_button(event.xbutton);
382 if (!_dga_mouse_enabled) {
389 if (_dga_mouse_enabled) {
398 handle_keystroke(event.xkey);
399 handle_keypress(event.xkey);
406 keyrelease_event =
event.xkey;
407 got_keyrelease_event =
true;
411 if (_dga_mouse_enabled) {
425 changed_properties =
true;
431 changed_properties =
true;
436 changed_properties =
true;
441 changed_properties =
true;
444 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
448 if ((Atom)(event.xclient.data.l[0]) == _wm_delete_window) {
452 if (!close_request_event.empty()) {
455 throw_event(close_request_event);
464 system_changed_properties(properties);
472 x11display_cat.info()
473 <<
"DestroyNotify\n";
477 x11display_cat.warning()
478 <<
"unhandled X event type " <<
event.type <<
"\n";
482 if (got_configure_event) {
484 _awaiting_configure =
false;
491 properties.
set_origin(configure_event.x, configure_event.y);
492 properties.
set_size(configure_event.width, configure_event.height);
494 if (_properties.get_fixed_size()) {
500 if (configure_event.width != _fixed_size.get_x() ||
501 configure_event.height != _fixed_size.get_y()) {
502 XWindowChanges changes;
503 changes.width = _fixed_size.get_x();
504 changes.height = _fixed_size.get_y();
505 int value_mask = (CWWidth | CWHeight);
506 XConfigureWindow(_display, _xwindow, value_mask, &changes);
512 if (_properties.get_mouse_mode() == WindowProperties::M_confined) {
513 X11_Cursor cursor = None;
514 if (_properties.get_cursor_hidden()) {
516 DCAST_INTO_V(x11_pipe, _pipe);
520 XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync, GrabModeAsync,
521 _xwindow, cursor, CurrentTime);
524 changed_properties =
true;
528 _properties.get_mouse_mode() == WindowProperties::M_confined ||
529 _dga_mouse_enabled)) {
531 DCAST_INTO_V(x11_pipe, _pipe);
536 X11_Cursor cursor = None;
537 if (_properties.get_cursor_hidden()) {
541 XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync, GrabModeAsync,
542 _xwindow, cursor, CurrentTime);
543 if (_dga_mouse_enabled) {
549 if (_dga_mouse_enabled) {
551 }
else if (_properties.get_mouse_mode() == WindowProperties::M_confined) {
552 XUngrabPointer(_display, CurrentTime);
557 if (changed_properties) {
558 system_changed_properties(properties);
561 if (got_keyrelease_event) {
564 ButtonHandle raw_button = map_raw_button(keyrelease_event.keycode);
565 if (raw_button != ButtonHandle::none()) {
569 handle_keyrelease(keyrelease_event);
587 if (_pipe ==
nullptr) {
594 DCAST_INTO_V(x11_pipe, _pipe);
600 bool is_fullscreen = _properties.has_fullscreen() && _properties.get_fullscreen();
603 if (want_fullscreen && properties.
has_origin()) {
609 if (want_fullscreen) {
613 LPoint2i center(0, 0);
614 if (_properties.has_origin()) {
615 center = _properties.get_origin();
616 if (_properties.has_size()) {
617 center += _properties.get_size() / 2;
620 int x, y, width, height;
624 int reqsizex, reqsizey;
628 }
else if (_properties.has_size()) {
629 reqsizex = _properties.get_x_size();
630 reqsizey = _properties.get_y_size();
642 || (width == reqsizex && height == reqsizey)
643 || !x11_pipe->_have_xrandr) {
649 if (x11display_cat.is_debug()) {
650 x11display_cat.debug()
651 <<
"Setting window to fullscreen on CRTC "
652 << width <<
"x" << height <<
"+" << x <<
"+" << y <<
"\n";
658 XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, _xwindow ? _xwindow : x11_pipe->
get_root());
659 SizeID old_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation);
660 SizeID new_size_id = (SizeID) -1;
664 xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes);
665 for (
int i = 0; i < num_sizes; ++i) {
666 if (xrrs[i].width == reqsizex &&
667 xrrs[i].height == reqsizey) {
671 if (new_size_id == (SizeID) -1) {
672 x11display_cat.error()
673 <<
"Videocard has no supported display resolutions at specified res ("
674 << reqsizex <<
" x " << reqsizey <<
")\n";
680 if (x11display_cat.is_debug()) {
681 x11display_cat.debug()
682 <<
"Switching to fullscreen with resolution "
683 << reqsizex <<
"x" << reqsizey <<
"\n";
686 if (new_size_id != old_size_id) {
687 _XRRSetScreenConfig(_display, conf, x11_pipe->
get_root(), new_size_id, _orig_rotation, CurrentTime);
688 if (_orig_size_id == (SizeID) -1) {
690 _orig_size_id = old_size_id;
702 if (_orig_size_id != (SizeID) -1) {
703 XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, x11_pipe->
get_root());
704 _XRRSetScreenConfig(_display, conf, x11_pipe->
get_root(), _orig_size_id, _orig_rotation, CurrentTime);
705 _orig_size_id = (SizeID) -1;
708 if (!properties.
has_origin() && _properties.has_origin()) {
709 properties.
set_origin(_properties.get_x_origin(), _properties.get_y_origin());
720 if (x_origin == -2) {
723 if (y_origin == -2) {
727 if (x_origin == -2) {
730 if (y_origin == -2) {
748 set_wm_properties(properties,
true);
753 _properties.set_title(properties.
get_title());
767 XWindowChanges changes;
770 if (_properties.get_fullscreen()) {
771 if (_properties.get_x_origin() != 0 ||
772 _properties.get_y_origin() != 0) {
775 value_mask |= CWX | CWY;
782 if (changes.x != -1) value_mask |= CWX;
783 if (changes.y != -1) value_mask |= CWY;
791 _fixed_size = _properties.get_size();
797 value_mask |= (CWWidth | CWHeight);
799 if (_properties.get_fixed_size()) {
800 _fixed_size = properties.
get_size();
811 case WindowProperties::Z_bottom:
812 changes.stack_mode = Below;
815 case WindowProperties::Z_normal:
816 changes.stack_mode = TopIf;
819 case WindowProperties::Z_top:
820 changes.stack_mode = Above;
824 value_mask |= (CWStackMode);
838 _properties.set_cursor_filename(cursor_filename);
842 _properties.set_cursor_filename(filename);
844 if (_properties.get_cursor_hidden()) {
847 }
else if (!cursor_filename.empty()) {
849 X11_Cursor cursor = get_cursor(cursor_filename);
850 XDefineCursor(_display, _xwindow, cursor);
853 XDefineCursor(_display, _xwindow, None);
857 if (!properties.has_mouse_mode() &&
858 _properties.get_mouse_mode() != WindowProperties::M_absolute) {
865 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
867 XSetInputFocus(_display, PointerRoot, RevertToPointerRoot, CurrentTime);
872 if (properties.has_mouse_mode()) {
874 case WindowProperties::M_absolute:
875 XUngrabPointer(_display, CurrentTime);
876 if (_dga_mouse_enabled) {
878 _dga_mouse_enabled =
false;
880 _properties.set_mouse_mode(WindowProperties::M_absolute);
884 case WindowProperties::M_relative:
885 if (!_dga_mouse_enabled) {
887 X11_Cursor cursor = None;
888 if (_properties.get_cursor_hidden()) {
890 DCAST_INTO_V(x11_pipe, _pipe);
894 if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
895 GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
896 x11display_cat.error() <<
"Failed to grab pointer!\n";
900 _properties.set_mouse_mode(WindowProperties::M_relative);
902 _dga_mouse_enabled =
true;
907 XQueryPointer(_display, _xwindow, &event.xbutton.root,
908 &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
909 &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
913 x11display_cat.warning()
914 <<
"XF86DGA extension not available, cannot enable relative mouse mode\n";
915 _dga_mouse_enabled =
false;
920 case WindowProperties::M_confined:
923 DCAST_INTO_V(x11_pipe, _pipe);
925 if (_dga_mouse_enabled) {
927 _dga_mouse_enabled =
false;
929 X11_Cursor cursor = None;
930 if (_properties.get_cursor_hidden()) {
934 if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
935 GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
936 x11display_cat.error() <<
"Failed to grab pointer!\n";
938 _properties.set_mouse_mode(WindowProperties::M_confined);
946 if (value_mask != 0) {
949 XReconfigureWMWindow(_display, _xwindow, _screen, value_mask, &changes);
952 _awaiting_configure =
true;
959void x11GraphicsWindow::
960mouse_mode_absolute() {
967void x11GraphicsWindow::
968mouse_mode_relative() {
975void x11GraphicsWindow::
977 if (_gsg !=
nullptr) {
982 if (_ic != (XIC)
nullptr) {
987 if (_xwindow != (X11_Window)
nullptr) {
988 XDestroyWindow(_display, _xwindow);
989 _xwindow = (X11_Window)
nullptr;
998 if (_orig_size_id != (SizeID) -1) {
1000 if (_pipe !=
nullptr) {
1002 DCAST_INTO_V(x11_pipe, _pipe);
1007 root = RootWindow(_display, _screen);
1009 XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, root);
1010 _XRRSetScreenConfig(_display, conf, root, _orig_size_id, _orig_rotation, CurrentTime);
1014 GraphicsWindow::close_window();
1021bool x11GraphicsWindow::
1023 if (_visual_info ==
nullptr) {
1025 x11display_cat.error()
1026 <<
"No X visual: cannot open window.\n";
1031 DCAST_INTO_R(x11_pipe, _pipe,
false);
1033 if (!_properties.has_origin()) {
1034 _properties.set_origin(0, 0);
1036 if (!_properties.has_size()) {
1037 _properties.set_size(100, 100);
1043 X11_Window parent_window = x11_pipe->
get_root();
1044 WindowHandle *window_handle = _properties.get_parent_window();
1045 if (window_handle !=
nullptr) {
1046 x11display_cat.info()
1047 <<
"Got parent_window " << *window_handle <<
"\n";
1049 if (os_handle !=
nullptr) {
1050 x11display_cat.info()
1051 <<
"os_handle type " << os_handle->get_type() <<
"\n";
1053 if (os_handle->
is_of_type(NativeWindowHandle::X11Handle::get_class_type())) {
1054 NativeWindowHandle::X11Handle *x11_handle = DCAST(NativeWindowHandle::X11Handle, os_handle);
1055 parent_window = x11_handle->get_handle();
1056 }
else if (os_handle->
is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
1058 parent_window = (X11_Window)int_handle->get_handle();
1062 _parent_window_handle = window_handle;
1065 ButtonPressMask | ButtonReleaseMask |
1066 KeyPressMask | KeyReleaseMask |
1067 EnterWindowMask | LeaveWindowMask |
1069 FocusChangeMask | StructureNotifyMask;
1072 XSetWindowAttributes wa;
1073 wa.background_pixel = XBlackPixel(_display, _screen);
1074 wa.border_pixel = 0;
1075 wa.colormap = _colormap;
1076 wa.event_mask = _event_mask;
1077 wa.override_redirect = _override_redirect;
1079 unsigned long attrib_mask =
1080 CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
1082 _xwindow = XCreateWindow
1083 (_display, parent_window,
1084 _properties.get_x_origin(), _properties.get_y_origin(),
1085 _properties.get_x_size(), _properties.get_y_size(),
1086 0, _visual_info->depth, InputOutput,
1087 _visual_info->visual, attrib_mask, &wa);
1089 if (_xwindow == (X11_Window)0) {
1090 x11display_cat.error()
1091 <<
"failed to create X window.\n";
1095 if (_properties.get_fixed_size()) {
1096 _fixed_size = _properties.get_size();
1099 set_wm_properties(_properties,
false);
1105 XIM im = x11_pipe->
get_im();
1108 _ic = XCreateIC(im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
1109 XNClientWindow, _xwindow,
nullptr);
1110 if (_ic == (XIC)
nullptr) {
1111 x11display_cat.warning()
1112 <<
"Couldn't create input context.\n";
1116 if (_properties.get_cursor_hidden()) {
1119 }
else if (_properties.has_cursor_filename() && !_properties.get_cursor_filename().empty()) {
1121 X11_Cursor cursor = get_cursor(_properties.get_cursor_filename());
1122 XDefineCursor(_display, _xwindow, cursor);
1125 XMapWindow(_display, _xwindow);
1127 if (_properties.get_raw_mice()) {
1130 if (x11display_cat.is_debug()) {
1131 x11display_cat.debug()
1132 <<
"Raw mice not requested.\n";
1137 _window_handle = NativeWindowHandle::make_x11(_xwindow);
1140 if (_parent_window_handle !=
nullptr) {
1141 _parent_window_handle->attach_child(_window_handle);
1159void x11GraphicsWindow::
1160set_wm_properties(
const WindowProperties &properties,
bool already_mapped) {
1162 DCAST_INTO_V(x11_pipe, _pipe);
1165 XTextProperty window_name;
1166 XTextProperty *window_name_p =
nullptr;
1168 const char *name = properties.
get_title().c_str();
1169 if (XStringListToTextProperty((
char **)&name, 1, &window_name) != 0) {
1170 window_name_p = &window_name;
1176 XSizeHints *size_hints_p =
nullptr;
1178 size_hints_p = XAllocSizeHints();
1179 if (size_hints_p !=
nullptr) {
1183 size_hints_p->flags |= USPosition;
1185 LVecBase2i size = _properties.get_size();
1188 size_hints_p->width = size.get_x();
1189 size_hints_p->height = size.get_y();
1190 size_hints_p->flags |= USSize;
1193 size_hints_p->min_width = size.get_x();
1194 size_hints_p->min_height = size.get_y();
1195 size_hints_p->max_width = size.get_x();
1196 size_hints_p->max_height = size.get_y();
1197 size_hints_p->flags |= (PMinSize | PMaxSize);
1204 XWMHints *wm_hints_p =
nullptr;
1205 wm_hints_p = XAllocWMHints();
1206 if (wm_hints_p !=
nullptr) {
1208 wm_hints_p->initial_state = IconicState;
1210 wm_hints_p->initial_state = NormalState;
1212 wm_hints_p->flags = StateHint;
1218 static const int max_type_data = 32;
1219 int32_t type_data[max_type_data];
1220 int next_type_data = 0;
1222 static const int max_state_data = 32;
1223 int32_t state_data[max_state_data];
1224 int next_state_data = 0;
1226 static const int max_set_data = 32;
1229 inline SetAction() { }
1230 inline SetAction(Atom state, Atom action) : _state(state), _action(action) { }
1234 SetAction set_data[max_set_data];
1235 int next_set_data = 0;
1241 type_data[next_type_data++] = x11_pipe->_net_wm_window_type_fullscreen;
1244 state_data[next_state_data++] = x11_pipe->_net_wm_state_fullscreen;
1247 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 1);
1250 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0);
1263 XClassHint *class_hints_p =
nullptr;
1264 if (!x_wm_class.empty()) {
1266 class_hints_p = XAllocClassHint();
1267 class_hints_p->res_class = (
char*) x_wm_class.c_str();
1268 if (!x_wm_class_name.empty()) {
1269 class_hints_p->res_name = (
char*) x_wm_class_name.c_str();
1273 class_hints_p = XAllocClassHint();
1274 class_hints_p->res_class = (
char*)
"Undecorated";
1278 type_data[next_type_data++] = x11_pipe->_net_wm_window_type_splash;
1283 case WindowProperties::Z_bottom:
1284 state_data[next_state_data++] = x11_pipe->_net_wm_state_below;
1285 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1286 x11_pipe->_net_wm_state_add);
1287 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1288 x11_pipe->_net_wm_state_remove);
1291 case WindowProperties::Z_normal:
1292 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1293 x11_pipe->_net_wm_state_remove);
1294 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1295 x11_pipe->_net_wm_state_remove);
1298 case WindowProperties::Z_top:
1299 state_data[next_state_data++] = x11_pipe->_net_wm_state_above;
1300 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
1301 x11_pipe->_net_wm_state_remove);
1302 set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
1303 x11_pipe->_net_wm_state_add);
1308 nassertv(next_type_data < max_type_data);
1309 nassertv(next_state_data < max_state_data);
1310 nassertv(next_set_data < max_set_data);
1313 int32_t pid = getpid();
1314 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_pid,
1315 XA_CARDINAL, 32, PropModeReplace,
1316 (
unsigned char *)&pid, 1);
1321 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_bypass_compositor,
1322 XA_CARDINAL, 32, PropModeReplace,
1323 (
unsigned char *)&compositor, 1);
1326 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_window_type,
1327 XA_ATOM, 32, PropModeReplace,
1328 (
unsigned char *)type_data, next_type_data);
1331 XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_state,
1332 XA_ATOM, 32, PropModeReplace,
1333 (
unsigned char *)state_data, next_state_data);
1335 if (already_mapped) {
1341 DCAST_INTO_V(x11_pipe, _pipe);
1343 for (
int i = 0; i < next_set_data; ++i) {
1344 XClientMessageEvent event;
1345 memset(&event, 0,
sizeof(event));
1346 event.type = ClientMessage;
1347 event.send_event = True;
1348 event.display = _display;
1349 event.window = _xwindow;
1350 event.message_type = x11_pipe->_net_wm_state;
1352 event.data.l[0] = set_data[i]._action;
1353 event.data.l[1] = set_data[i]._state;
1354 event.data.l[2] = 0;
1355 event.data.l[3] = 1;
1357 XSendEvent(_display, x11_pipe->
get_root(), True, SubstructureNotifyMask | SubstructureRedirectMask, (XEvent *)&event);
1361 XSetWMProperties(_display, _xwindow, window_name_p, window_name_p,
1362 nullptr, 0, size_hints_p, wm_hints_p, class_hints_p);
1364 if (size_hints_p !=
nullptr) {
1365 XFree(size_hints_p);
1367 if (wm_hints_p !=
nullptr) {
1370 if (class_hints_p !=
nullptr) {
1371 XFree(class_hints_p);
1377 Atom protocols[] = {
1381 XSetWMProtocols(_display, _xwindow, protocols,
1382 sizeof(protocols) /
sizeof(Atom));
1389void x11GraphicsWindow::
1390setup_colormap(XVisualInfo *visual) {
1392 DCAST_INTO_V(x11_pipe, _pipe);
1393 X11_Window root_window = x11_pipe->
get_root();
1395 _colormap = XCreateColormap(_display, root_window,
1396 visual->visual, AllocNone);
1403void x11GraphicsWindow::
1405#ifdef PHAVE_LINUX_INPUT_H
1406 bool any_present =
false;
1407 bool any_mice =
false;
1409 for (
int i=0; i<64; i++) {
1411 fnb <<
"/dev/input/event" << i;
1412 string fn = fnb.str();
1413 int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0);
1415 EvdevInputDevice *device =
new EvdevInputDevice(
nullptr, fd);
1416 nassertd(device != NULL)
continue;
1418 if (device->has_pointer()) {
1419 add_input_device(device);
1421 x11display_cat.info()
1422 <<
"Raw mouse " << _input_devices.size()
1423 <<
" detected: " << device->get_name() <<
"\n";
1429 if (errno == ENOENT || errno == ENOTDIR) {
1433 x11display_cat.error()
1434 <<
"Opening raw mice: " << strerror(errno) <<
" " << fn <<
"\n";
1440 _properties.set_raw_mice(
true);
1442 }
else if (!any_present) {
1443 x11display_cat.error() <<
1444 "Opening raw mice: files not found: /dev/input/event*\n";
1447 x11display_cat.error() <<
1448 "Opening raw mice: no mouse devices detected in /dev/input/event*\n";
1451 x11display_cat.error() <<
1452 "Opening raw mice: panda not compiled with raw mouse support.\n";
1459void x11GraphicsWindow::
1460handle_keystroke(XKeyEvent &event) {
1461 if (!_dga_mouse_enabled) {
1467 static const int buffer_size = 256;
1468 wchar_t buffer[buffer_size];
1470 int len = XwcLookupString(_ic, &event, buffer, buffer_size,
nullptr,
1472 if (status == XBufferOverflow) {
1473 x11display_cat.error()
1474 <<
"Overflowed input buffer.\n";
1478 for (
int i = 0; i < len; i++) {
1494void x11GraphicsWindow::
1495handle_keypress(XKeyEvent &event) {
1496 if (!_dga_mouse_enabled) {
1502 if (button != ButtonHandle::none()) {
1503 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
1506 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
1509 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
1512 if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
1522void x11GraphicsWindow::
1523handle_keyrelease(XKeyEvent &event) {
1524 if (!_dga_mouse_enabled) {
1530 if (button != ButtonHandle::none()) {
1531 if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
1532 _input->
button_up(KeyboardButton::control());
1534 if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
1535 _input->
button_up(KeyboardButton::shift());
1537 if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
1538 _input->
button_up(KeyboardButton::alt());
1540 if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
1541 _input->
button_up(KeyboardButton::meta());
1552get_button(XKeyEvent &key_event,
bool allow_shift) {
1553 KeySym key = XLookupKeysym(&key_event, 0);
1555 if ((key_event.state & Mod2Mask) != 0) {
1570 case XK_KP_Multiply:
1572 case XK_KP_Separator:
1573 case XK_KP_Subtract:
1596 k2 = XLookupKeysym(&key_event, 1);
1597 button = map_button(k2);
1598 if (button != ButtonHandle::none()) {
1612 if ((key_event.state & ShiftMask) != 0) {
1613 KeySym k2 = XLookupKeysym(&key_event, 1);
1615 if (button != ButtonHandle::none()) {
1623 if ((key_event.state & (ShiftMask | LockMask)) != 0) {
1624 if (key >= XK_a && key <= XK_z) {
1625 key += (XK_A - XK_a);
1630 return map_button(key);
1638map_button(KeySym key)
const {
1641 return ButtonHandle::none();
1643 return KeyboardButton::backspace();
1646 return KeyboardButton::tab();
1649 return KeyboardButton::enter();
1651 return KeyboardButton::escape();
1654 return KeyboardButton::space();
1675 case XK_KP_Multiply:
1681 case XK_KP_Separator:
1684 case XK_KP_Subtract:
1789 case XK_bracketleft:
1793 case XK_bracketright:
1795 case XK_asciicircum:
1864 return KeyboardButton::f1();
1867 return KeyboardButton::f2();
1870 return KeyboardButton::f3();
1873 return KeyboardButton::f4();
1875 return KeyboardButton::f5();
1877 return KeyboardButton::f6();
1879 return KeyboardButton::f7();
1881 return KeyboardButton::f8();
1883 return KeyboardButton::f9();
1885 return KeyboardButton::f10();
1887 return KeyboardButton::f11();
1889 return KeyboardButton::f12();
1892 return KeyboardButton::left();
1895 return KeyboardButton::up();
1898 return KeyboardButton::right();
1901 return KeyboardButton::down();
1904 return KeyboardButton::page_up();
1907 return KeyboardButton::page_down();
1910 return KeyboardButton::home();
1913 return KeyboardButton::end();
1916 return KeyboardButton::insert();
1919 return KeyboardButton::del();
1921 return KeyboardButton::num_lock();
1922 case XK_Scroll_Lock:
1923 return KeyboardButton::scroll_lock();
1925 return KeyboardButton::print_screen();
1927 return KeyboardButton::pause();
1929 return KeyboardButton::menu();
1931 return KeyboardButton::lshift();
1933 return KeyboardButton::rshift();
1935 return KeyboardButton::lcontrol();
1937 return KeyboardButton::rcontrol();
1939 return KeyboardButton::lalt();
1941 return KeyboardButton::ralt();
1944 return KeyboardButton::lmeta();
1947 return KeyboardButton::rmeta();
1949 return KeyboardButton::caps_lock();
1951 return KeyboardButton::shift_lock();
1953 if (x11display_cat.is_debug()) {
1954 x11display_cat.debug()
1955 <<
"Unrecognized keysym 0x" << std::hex << key << std::dec <<
"\n";
1957 return ButtonHandle::none();
1964map_raw_button(KeyCode key)
const {
1965#ifdef PHAVE_LINUX_INPUT_H
1970 int index = key - 8;
1971 if (index > 0 && index < 128) {
1972 return EvdevInputDevice::map_button(index);
1975 return ButtonHandle::none();
1983get_mouse_button(XButtonEvent &button_event) {
1984 int index = button_event.button;
1985 if (index == x_wheel_up_button) {
1987 }
else if (index == x_wheel_down_button) {
1989 }
else if (index == x_wheel_left_button) {
1991 }
else if (index == x_wheel_right_button) {
1993 }
else if (index >= 8) {
2005get_keyboard_map()
const {
2012 for (
int k = 9; k <= 135; ++k) {
2013 if (k >= 78 && k <= 91) {
2021 if (raw_button == ButtonHandle::none()) {
2025 KeySym sym = XkbKeycodeToKeysym(_display, k, 0, 0);
2031 if (sym >= XK_exclam && sym <= XK_asciitilde) {
2032 label = toupper((
char)sym);
2034 else if (sym >= XK_F1 && sym <= XK_F35) {
2035 label =
"F" + format_string(sym - XK_F1 + 1);
2037 else if (sym > 0x1000000 && sym < 0x1110000) {
2039 char32_t ch = sym & 0x0ffffff;
2040 if ((ch & ~0x7f) == 0) {
2041 label = string(1, (
char)ch);
2043 else if ((ch & ~0x7ff) == 0) {
2045 string(1, (
char)((ch >> 6) | 0xc0)) +
2046 string(1, (
char)((ch & 0x3f) | 0x80));
2048 else if ((ch & ~0xffff) == 0) {
2050 string(1, (
char)((ch >> 12) | 0xe0)) +
2051 string(1, (
char)(((ch >> 6) & 0x3f) | 0x80)) +
2052 string(1, (
char)((ch & 0x3f) | 0x80));
2056 string(1, (
char)((ch >> 18) | 0xf0)) +
2057 string(1, (
char)(((ch >> 12) & 0x3f) | 0x80)) +
2058 string(1, (
char)(((ch >> 6) & 0x3f) | 0x80)) +
2059 string(1, (
char)((ch & 0x3f) | 0x80));
2062 else if ((sym >= XK_exclamdown && sym <= XK_umacron)
2063 || (sym >= XK_OE && sym <= XK_Ydiaeresis)
2064 || (sym >= XK_Serbian_dje && sym <= XK_Cyrillic_HARDSIGN)
2065 || (sym >= XK_kana_fullstop && sym <= XK_semivoicedsound)
2066 || (sym >= XK_Arabic_comma && sym <= XK_Arabic_sukun)
2067 || (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_omega)
2068 || (sym >= XK_hebrew_doublelowline && sym <= XK_hebrew_taw)
2069 || (sym >= XK_Thai_kokai && sym <= XK_Thai_lekkao)
2070 || (sym >= XK_Hangul_Kiyeog && sym <= XK_Hangul_J_YeorinHieuh)
2071 || sym == XK_EuroSign
2072 || sym == XK_Korean_Won) {
2075 int nbytes = XkbTranslateKeySym(_display, &sym, 0, buffer, 255, 0);
2077 label.assign(buffer, nbytes);
2081 if (button == ButtonHandle::none() && label.empty()) {
2096Bool x11GraphicsWindow::
2097check_event(X11_Display *display, XEvent *event,
char *arg) {
2101 return (event->xany.window == self->_xwindow);
2108X11_Cursor x11GraphicsWindow::
2109get_cursor(
const Filename &filename) {
2111 DCAST_INTO_R(x11_pipe, _pipe, None);
2113 if (x11_pipe->_xcursor_size == -1) {
2114 x11display_cat.info()
2115 <<
"libXcursor.so.1 not available; cannot change mouse cursor.\n";
2121 if (fi != _cursor_filenames.end()) {
2130 x11display_cat.warning()
2131 <<
"Could not find cursor filename " << filename <<
"\n";
2134 fi = _cursor_filenames.find(resolved);
2135 if (fi != _cursor_filenames.end()) {
2141 if (str ==
nullptr) {
2142 x11display_cat.warning()
2143 <<
"Could not open cursor file " << filename <<
"\n";
2149 str->read(magic, 4);
2151 x11display_cat.warning()
2152 <<
"Could not read from cursor file " << filename <<
"\n";
2158 str->putback(magic[3]);
2159 str->putback(magic[2]);
2160 str->putback(magic[1]);
2161 str->putback(magic[0]);
2163 X11_Cursor h = None;
2164 if (memcmp(magic,
"Xcur", 4) == 0) {
2166 x11display_cat.debug()
2167 <<
"Loading X11 cursor " << filename <<
"\n";
2169 xcfile.closure = str;
2170 xcfile.read = &xcursor_read;
2171 xcfile.write = &xcursor_write;
2172 xcfile.seek = &xcursor_seek;
2174 XcursorImages *images = x11_pipe->_XcursorXcFileLoadImages(&xcfile, x11_pipe->_xcursor_size);
2175 if (images !=
nullptr) {
2176 h = x11_pipe->_XcursorImagesLoadCursor(_display, images);
2177 x11_pipe->_XcursorImagesDestroy(images);
2180 }
else if (memcmp(magic,
"\0\0\1\0", 4) == 0
2181 || memcmp(magic,
"\0\0\2\0", 4) == 0) {
2183 x11display_cat.debug()
2184 <<
"Loading Windows cursor " << filename <<
"\n";
2192 x11display_cat.warning()
2193 <<
"X11 cursor filename '" << resolved <<
"' could not be loaded!\n";
2196 _cursor_filenames[resolved] = h;
2204X11_Cursor x11GraphicsWindow::
2205read_ico(istream &ico) {
2207 DCAST_INTO_R(x11_pipe, _pipe, None);
2211 uint16_t reserved, type, count;
2215 uint8_t width, height, colorCount, reserved;
2216 uint16_t xhot, yhot;
2217 uint32_t bitmapSize, offset;
2221 uint32_t headerSize, width, height;
2222 uint16_t planes, bitsPerPixel;
2223 uint32_t compression, imageSize, xPixelsPerM, yPixelsPerM, colorsUsed, colorsImportant;
2227 uint8_t blue, green, red, reserved;
2231 unsigned int j, k, mask, shift;
2232 size_t colorCount, bitsPerPixel;
2234 IcoInfoHeader infoHeader;
2235 IcoEntry *entries =
nullptr;
2236 IcoColor color, *palette =
nullptr;
2238 size_t xorBmpSize, andBmpSize;
2239 char *curXor, *curAnd;
2240 char *xorBmp =
nullptr, *andBmp =
nullptr;
2241 XcursorImage *image =
nullptr;
2242 X11_Cursor ret = None;
2244 int def_size = x11_pipe->_xcursor_size;
2247 ico.read(
reinterpret_cast<char *
>(&header),
sizeof(IcoHeader));
2248 if (!ico.good())
goto cleanup;
2249 if (header.type != 1 && header.type != 2)
goto cleanup;
2250 if (header.count < 1)
goto cleanup;
2253 entries =
new IcoEntry[header.count];
2254 ico.read(
reinterpret_cast<char *
>(entries), header.count *
sizeof(IcoEntry));
2255 if (!ico.good())
goto cleanup;
2256 for (i = 1; i < header.count; i++) {
2257 if (entries[i].width == def_size && entries[i].height == def_size) {
2262 if (entries[i].width > entries[entry].width ||
2263 entries[i].height > entries[entry].height)
2268 ico.seekg(entries[entry].offset);
2269 if (!ico.good())
goto cleanup;
2271 if (ico.peek() == 0x89) {
2285 unsigned int *dest = image->pixels;
2287 if (alpha !=
nullptr) {
2288 for (
size_t p = 0; p < num_pixels; ++p) {
2289 *dest++ = (*alpha << 24U) | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
2294 for (
size_t p = 0; p < num_pixels; ++p) {
2295 *dest++ = 0xff000000U | (ptr->r << 16U) | (ptr->g << 8U) | (ptr->b);
2301 ico.read(
reinterpret_cast<char *
>(&infoHeader),
sizeof(IcoInfoHeader));
2302 if (!ico.good())
goto cleanup;
2303 bitsPerPixel = infoHeader.bitsPerPixel;
2305 if (infoHeader.compression != 0)
goto cleanup;
2308 if (bitsPerPixel != 24 && bitsPerPixel != 32) {
2309 colorCount = 1 << bitsPerPixel;
2310 palette =
new IcoColor[colorCount];
2311 ico.read(
reinterpret_cast<char *
>(palette), colorCount *
sizeof(IcoColor));
2312 if (!ico.good())
goto cleanup;
2315 int and_stride = ((infoHeader.width >> 3) + 3) & ~0x03;
2318 xorBmpSize = (infoHeader.width * (infoHeader.height / 2) * bitsPerPixel) / 8;
2319 andBmpSize = and_stride * (infoHeader.height / 2);
2320 curXor = xorBmp =
new char[xorBmpSize];
2321 curAnd = andBmp =
new char[andBmpSize];
2322 ico.read(xorBmp, xorBmpSize);
2323 if (!ico.good())
goto cleanup;
2324 ico.read(andBmp, andBmpSize);
2325 if (!ico.good())
goto cleanup;
2327 image = x11_pipe->_XcursorImageCreate(infoHeader.width, infoHeader.height / 2);
2330 switch (bitsPerPixel) {
2336 mask = ((1 << bitsPerPixel) - 1);
2337 for (i = image->height - 1; i >= 0; i--) {
2338 for (j = 0; j < image->width; j += 8 / bitsPerPixel) {
2339 for (k = 0; k < 8 / bitsPerPixel; k++) {
2340 shift = 8 - ((k + 1) * bitsPerPixel);
2341 color = palette[(*curXor & (mask << shift)) >> shift];
2342 image->pixels[(i * image->width) + j + k] = (color.red << 16) +
2343 (color.green << 8) +
2351 for (j = 0; j < image->width; j += 8) {
2352 for (k = 0; k < 8; k++) {
2354 image->pixels[(i * image->width) + j + k] |=
2355 ((*curAnd & (1 << shift)) >> shift) ? 0x0 : (0xff << 24);
2365 for (i = image->height - 1; i >= 0; i--) {
2366 for (j = 0; j < image->width; j++) {
2367 shift = 7 - (j & 0x7);
2368 uint32_t alpha = (curAnd[j >> 3] & (1 << shift)) ? 0 : 0xff000000U;
2369 image->pixels[(i * image->width) + j] = (uint8_t)curXor[0]
2370 | ((uint8_t)curXor[1] << 8u)
2371 | ((uint8_t)curXor[2] << 16u)
2375 curAnd += and_stride;
2381 for (i = image->height - 1; i >= 0; i--) {
2382 for (j = 0; j < image->width; j++) {
2383 image->pixels[(i * image->width) + j] = (*(curXor + 3) << 24) +
2384 (*(curXor + 2) << 16) +
2385 (*(curXor + 1) << 8) +
2398 if (header.type == 2) {
2399 image->xhot = entries[entry].xhot;
2400 image->yhot = entries[entry].yhot;
2406 ret = x11_pipe->_XcursorImageLoadCursor(_display, image);
2409 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.