25 bool x11GraphicsPipe::_error_handlers_installed =
false;
26 x11GraphicsPipe::ErrorHandlerFunc *x11GraphicsPipe::_prev_error_handler;
27 x11GraphicsPipe::IOErrorHandlerFunc *x11GraphicsPipe::_prev_io_error_handler;
28 bool x11GraphicsPipe::_x_error_messages_enabled =
true;
29 int x11GraphicsPipe::_x_error_count = 0;
37 x11GraphicsPipe(
const std::string &display) :
40 _XF86DGADirectVideo(nullptr) {
42 std::string display_spec = display;
43 if (display_spec.empty()) {
44 display_spec = display_cfg;
46 if (display_spec.empty()) {
49 if (display_spec.empty()) {
50 display_spec =
":0.0";
55 setlocale(LC_ALL,
"");
60 setlocale(LC_NUMERIC,
"C");
63 _supported_types = OT_window | OT_buffer | OT_texture_buffer;
66 _root = (X11_Window)
nullptr;
68 _hidden_cursor = None;
76 install_error_handlers();
78 _display = XOpenDisplay(display_spec.c_str());
80 x11display_cat.error()
81 <<
"Could not open display \"" << display_spec <<
"\".\n";
90 if (!XSupportsLocale()) {
91 x11display_cat.warning()
92 <<
"X does not support locale " << setlocale(LC_ALL,
nullptr) <<
"\n";
94 XSetLocaleModifiers(
"");
96 _screen = DefaultScreen(_display);
97 _root = RootWindow(_display, _screen);
98 _display_width = DisplayWidth(_display, _screen);
99 _display_height = DisplayHeight(_display, _screen);
103 void *xf86dga = dlopen(
"libXxf86dga.so.1", RTLD_NOW | RTLD_LOCAL);
104 if (xf86dga !=
nullptr) {
105 pfn_XF86DGAQueryVersion _XF86DGAQueryVersion = (pfn_XF86DGAQueryVersion)dlsym(xf86dga,
"XF86DGAQueryVersion");
106 _XF86DGADirectVideo = (pfn_XF86DGADirectVideo)dlsym(xf86dga,
"XF86DGADirectVideo");
108 int major_ver, minor_ver;
109 if (_XF86DGAQueryVersion ==
nullptr || _XF86DGADirectVideo ==
nullptr) {
110 x11display_cat.warning()
111 <<
"libXxf86dga.so.1 does not provide required functions; relative mouse mode will not work.\n";
113 }
else if (!_XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
114 _XF86DGADirectVideo =
nullptr;
117 _XF86DGADirectVideo =
nullptr;
118 if (x11display_cat.is_debug()) {
119 x11display_cat.debug()
120 <<
"cannot dlopen libXxf86dga.so.1; cursor changing will not work.\n";
125 void *xcursor = dlopen(
"libXcursor.so.1", RTLD_NOW | RTLD_LOCAL);
126 if (xcursor !=
nullptr) {
127 pfn_XcursorGetDefaultSize _XcursorGetDefaultSize = (pfn_XcursorGetDefaultSize)dlsym(xcursor,
"XcursorGetDefaultSize");
128 _XcursorXcFileLoadImages = (pfn_XcursorXcFileLoadImages)dlsym(xcursor,
"XcursorXcFileLoadImages");
129 _XcursorImagesLoadCursor = (pfn_XcursorImagesLoadCursor)dlsym(xcursor,
"XcursorImagesLoadCursor");
130 _XcursorImagesDestroy = (pfn_XcursorImagesDestroy)dlsym(xcursor,
"XcursorImagesDestroy");
131 _XcursorImageCreate = (pfn_XcursorImageCreate)dlsym(xcursor,
"XcursorImageCreate");
132 _XcursorImageLoadCursor = (pfn_XcursorImageLoadCursor)dlsym(xcursor,
"XcursorImageLoadCursor");
133 _XcursorImageDestroy = (pfn_XcursorImageDestroy)dlsym(xcursor,
"XcursorImageDestroy");
135 if (_XcursorGetDefaultSize ==
nullptr || _XcursorXcFileLoadImages ==
nullptr ||
136 _XcursorImagesLoadCursor ==
nullptr || _XcursorImagesDestroy ==
nullptr ||
137 _XcursorImageCreate ==
nullptr || _XcursorImageLoadCursor ==
nullptr ||
138 _XcursorImageDestroy ==
nullptr) {
140 x11display_cat.warning()
141 <<
"libXcursor.so.1 does not provide required functions; cursor changing will not work.\n";
143 }
else if (x_cursor_size.
get_value() >= 0) {
144 _xcursor_size = x_cursor_size;
146 _xcursor_size = _XcursorGetDefaultSize(_display);
150 if (x11display_cat.is_debug()) {
151 x11display_cat.debug()
152 <<
"cannot dlopen libXcursor.so.1; cursor changing will not work.\n";
157 void *xrandr = dlopen(
"libXrandr.so.2", RTLD_NOW | RTLD_LOCAL);
158 if (xrandr !=
nullptr) {
159 pfn_XRRQueryExtension _XRRQueryExtension = (pfn_XRRQueryExtension)dlsym(xrandr,
"XRRQueryExtension");
160 pfn_XRRQueryVersion _XRRQueryVersion = (pfn_XRRQueryVersion)dlsym(xrandr,
"XRRQueryVersion");
162 _XRRSizes = (pfn_XRRSizes)dlsym(xrandr,
"XRRSizes");
163 _XRRRates = (pfn_XRRRates)dlsym(xrandr,
"XRRRates");
164 _XRRGetScreenInfo = (pfn_XRRGetScreenInfo)dlsym(xrandr,
"XRRGetScreenInfo");
165 _XRRConfigCurrentConfiguration = (pfn_XRRConfigCurrentConfiguration)dlsym(xrandr,
"XRRConfigCurrentConfiguration");
166 _XRRSetScreenConfig = (pfn_XRRSetScreenConfig)dlsym(xrandr,
"XRRSetScreenConfig");
168 int event, error, major, minor;
169 if (_XRRQueryExtension ==
nullptr || _XRRSizes ==
nullptr || _XRRRates ==
nullptr ||
170 _XRRGetScreenInfo ==
nullptr || _XRRConfigCurrentConfiguration ==
nullptr ||
171 _XRRSetScreenConfig ==
nullptr || _XRRQueryVersion ==
nullptr) {
172 _have_xrandr =
false;
173 x11display_cat.warning()
174 <<
"libXrandr.so.2 does not provide required functions; resolution setting will not work.\n";
176 else if (_XRRQueryExtension(_display, &event, &error) &&
177 _XRRQueryVersion(_display, &major, &minor)) {
179 if (x11display_cat.is_debug()) {
180 x11display_cat.debug()
181 <<
"Found RandR extension " << major <<
"." << minor <<
"\n";
184 if (major > 1 || (major == 1 && minor >= 2)) {
185 if (major > 1 || (major == 1 && minor >= 3)) {
186 _XRRGetScreenResourcesCurrent = (pfn_XRRGetScreenResources)
187 dlsym(xrandr,
"XRRGetScreenResourcesCurrent");
190 _XRRGetScreenResourcesCurrent = (pfn_XRRGetScreenResources)
191 dlsym(xrandr,
"XRRGetScreenResources");
194 _XRRFreeScreenResources = (pfn_XRRFreeScreenResources)dlsym(xrandr,
"XRRFreeScreenResources");
195 _XRRGetCrtcInfo = (pfn_XRRGetCrtcInfo)dlsym(xrandr,
"XRRGetCrtcInfo");
196 _XRRFreeCrtcInfo = (pfn_XRRFreeCrtcInfo)dlsym(xrandr,
"XRRFreeCrtcInfo");
198 _XRRGetScreenResourcesCurrent =
nullptr;
199 _XRRFreeScreenResources =
nullptr;
200 _XRRGetCrtcInfo =
nullptr;
201 _XRRFreeCrtcInfo =
nullptr;
204 _have_xrandr =
false;
205 if (x11display_cat.is_debug()) {
206 x11display_cat.debug()
207 <<
"RandR extension not supported; resolution setting will not work.\n";
211 _have_xrandr =
false;
212 if (x11display_cat.is_debug()) {
213 x11display_cat.debug()
214 <<
"cannot dlopen libXrandr.so.2; resolution setting will not work.\n";
222 if (
auto res = get_screen_resources()) {
223 if (x11display_cat.is_debug()) {
224 x11display_cat.debug()
225 <<
"Using XRRScreenResources to obtain display modes\n";
227 _display_information->_total_display_modes = res->nmode;
228 _display_information->_display_mode_array =
new DisplayMode[res->nmode];
229 for (
int i = 0; i < res->nmode; ++i) {
232 DisplayMode *dm = _display_information->_display_mode_array + i;
233 dm->width = mode.width;
234 dm->height = mode.height;
235 dm->bits_per_pixel = -1;
236 dm->fullscreen_only =
false;
238 if (mode.hTotal && mode.vTotal) {
239 dm->refresh_rate = (double)mode.dotClock /
240 ((
double)mode.hTotal * (double)mode.vTotal);
242 dm->refresh_rate = 0;
246 if (x11display_cat.is_debug()) {
247 x11display_cat.debug()
248 <<
"Using XRRSizes and XRRRates to obtain display modes\n";
251 int num_sizes, num_rates;
253 xrrs = _XRRSizes(_display, 0, &num_sizes);
254 _display_information->_total_display_modes = 0;
255 for (
int i = 0; i < num_sizes; ++i) {
256 _XRRRates(_display, 0, i, &num_rates);
257 _display_information->_total_display_modes += num_rates;
262 _display_information->_display_mode_array =
new DisplayMode[_display_information->_total_display_modes];
263 for (
int i = 0; i < num_sizes; ++i) {
265 rates = _XRRRates(_display, 0, i, &num_rates);
266 for (
int j = 0; j < num_rates; ++j) {
267 DisplayMode* dm = _display_information->_display_mode_array + counter;
268 dm->width = xrrs[i].width;
269 dm->height = xrrs[i].height;
270 dm->refresh_rate = rates[j];
271 dm->bits_per_pixel = -1;
272 dm->fullscreen_only =
false;
280 _im = XOpenIM(_display,
nullptr,
nullptr,
nullptr);
281 if (_im == (XIM)
nullptr) {
283 XSetLocaleModifiers(
"@im=none");
284 _im = XOpenIM(_display,
nullptr,
nullptr,
nullptr);
285 if (_im == (XIM)
nullptr) {
286 x11display_cat.warning()
287 <<
"Couldn't open input method.\n";
304 const char *dpi = XGetDefault(_display,
"Xft",
"dpi");
305 if (dpi !=
nullptr) {
306 char *endptr =
nullptr;
307 double result =
pstrtod(dpi, &endptr);
308 if (result != 0 && !cnan(result) && endptr[0] ==
'\0') {
310 set_detected_display_zoom(result);
312 if (x11display_cat.is_debug()) {
313 x11display_cat.debug()
314 <<
"Determined display zoom to be " << result
315 <<
" based on specified Xft.dpi " << dpi <<
"\n";
318 x11display_cat.warning()
319 <<
"Unable to determine display zoom because Xft.dpi is invalid: "
322 }
else if (x11display_cat.is_debug()) {
323 x11display_cat.debug()
324 <<
"Unable to determine display zoom because Xft.dpi was not set.\n";
328 _wm_delete_window = XInternAtom(_display,
"WM_DELETE_WINDOW",
false);
329 _net_wm_pid = XInternAtom(_display,
"_NET_WM_PID",
false);
330 _net_wm_window_type = XInternAtom(_display,
"_NET_WM_WINDOW_TYPE",
false);
331 _net_wm_window_type_splash = XInternAtom(_display,
"_NET_WM_WINDOW_TYPE_SPLASH",
false);
332 _net_wm_window_type_fullscreen = XInternAtom(_display,
"_NET_WM_WINDOW_TYPE_FULLSCREEN",
false);
333 _net_wm_state = XInternAtom(_display,
"_NET_WM_STATE",
false);
334 _net_wm_state_fullscreen = XInternAtom(_display,
"_NET_WM_STATE_FULLSCREEN",
false);
335 _net_wm_state_above = XInternAtom(_display,
"_NET_WM_STATE_ABOVE",
false);
336 _net_wm_state_below = XInternAtom(_display,
"_NET_WM_STATE_BELOW",
false);
337 _net_wm_state_add = XInternAtom(_display,
"_NET_WM_STATE_ADD",
false);
338 _net_wm_state_remove = XInternAtom(_display,
"_NET_WM_STATE_REMOVE",
false);
339 _net_wm_bypass_compositor = XInternAtom(_display,
"_NET_WM_BYPASS_COMPOSITOR",
false);
347 release_hidden_cursor();
352 XCloseDisplay(_display);
363 if (_have_xrandr && _XRRGetScreenResourcesCurrent !=
nullptr) {
364 res = _XRRGetScreenResourcesCurrent(_display, _root);
367 return std::unique_ptr<XRRScreenResources, pfn_XRRFreeScreenResources>(res, _XRRFreeScreenResources);
377 if (_have_xrandr && _XRRGetCrtcInfo !=
nullptr) {
378 info = _XRRGetCrtcInfo(_display, res, crtc);
381 return std::unique_ptr<XRRCrtcInfo, pfn_XRRFreeCrtcInfo>(info, _XRRFreeCrtcInfo);
393 int &x,
int &y,
int &width,
int &height) {
396 width = DisplayWidth(_display, _screen);
397 height = DisplayHeight(_display, _screen);
400 for (
int i = 0; i < res->ncrtc; ++i) {
401 RRCrtc crtc = res->crtcs[i];
403 if (point[0] >= info->x && point[0] < info->x + (
int)info->width &&
404 point[1] >= info->y && point[1] < info->y + (
int)info->height) {
408 width = (int)info->width;
409 height = (
int)info->height;
424 GraphicsPipe::PreferredWindowThread
443 void x11GraphicsPipe::
444 make_hidden_cursor() {
445 nassertv(_hidden_cursor == None);
447 unsigned int x_size, y_size;
448 XQueryBestCursor(_display, _root, 1, 1, &x_size, &y_size);
450 Pixmap empty = XCreatePixmap(_display, _root, x_size, y_size, 1);
453 memset(&black, 0,
sizeof(black));
455 _hidden_cursor = XCreatePixmapCursor(_display, empty, empty,
456 &black, &black, x_size, y_size);
457 XFreePixmap(_display, empty);
464 void x11GraphicsPipe::
465 release_hidden_cursor() {
466 if (_hidden_cursor != None) {
467 XFreeCursor(_display, _hidden_cursor);
468 _hidden_cursor = None;
479 void x11GraphicsPipe::
480 install_error_handlers() {
481 if (_error_handlers_installed) {
485 _prev_error_handler = (ErrorHandlerFunc *)XSetErrorHandler(error_handler);
486 _prev_io_error_handler = (IOErrorHandlerFunc *)XSetIOErrorHandler(io_error_handler);
487 _error_handlers_installed =
true;
493 int x11GraphicsPipe::
494 error_handler(X11_Display *display, XErrorEvent *error) {
497 static const int msg_len = 80;
499 XGetErrorText(display, error->error_code, msg, msg_len);
501 if (!_x_error_messages_enabled) {
502 if (x11display_cat.is_debug()) {
503 x11display_cat.debug()
509 x11display_cat.error()
524 int x11GraphicsPipe::
525 io_error_handler(X11_Display *display) {
526 x11display_cat.fatal()
527 <<
"X fatal error on display " << (
void *)display <<
"\n";
get_value
Returns the variable's value.
get_environment_variable
Returns the definition of the indicated environment variable, or the empty string if the variable is ...
A lightweight reentrant mutex.
TypeHandle is the identifier used to differentiate C++ class types.
std::unique_ptr< XRRScreenResources, pfn_XRRFreeScreenResources > get_screen_resources() const
Returns an XRRScreenResources object, or null if RandR 1.2 is not supported.
std::unique_ptr< XRRCrtcInfo, pfn_XRRFreeCrtcInfo > get_crtc_info(XRRScreenResources *res, RRCrtc crtc) const
Returns an XRRCrtcInfo object, or null if RandR 1.2 is not supported.
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.
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
double pstrtod(const char *nptr, char **endptr)
This function re-implements strtod, to avoid the problems that occur when the LC_NUMERIC locale gets ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.