24 bool x11GraphicsPipe::_error_handlers_installed =
false;
25 x11GraphicsPipe::ErrorHandlerFunc *x11GraphicsPipe::_prev_error_handler;
26 x11GraphicsPipe::IOErrorHandlerFunc *x11GraphicsPipe::_prev_io_error_handler;
27 bool x11GraphicsPipe::_x_error_messages_enabled =
true;
28 int x11GraphicsPipe::_x_error_count = 0;
36 x11GraphicsPipe(
const std::string &display) :
39 _XF86DGADirectVideo(nullptr) {
41 std::string display_spec = display;
42 if (display_spec.empty()) {
43 display_spec = display_cfg;
45 if (display_spec.empty()) {
48 if (display_spec.empty()) {
49 display_spec =
":0.0";
54 setlocale(LC_ALL,
"");
59 setlocale(LC_NUMERIC,
"C");
62 _supported_types = OT_window | OT_buffer | OT_texture_buffer;
65 _root = (X11_Window)
nullptr;
67 _hidden_cursor = None;
75 install_error_handlers();
77 _display = XOpenDisplay(display_spec.c_str());
79 x11display_cat.error()
80 <<
"Could not open display \"" << display_spec <<
"\".\n";
89 if (!XSupportsLocale()) {
90 x11display_cat.warning()
91 <<
"X does not support locale " << setlocale(LC_ALL,
nullptr) <<
"\n";
93 XSetLocaleModifiers(
"");
95 _screen = DefaultScreen(_display);
96 _root = RootWindow(_display, _screen);
97 _display_width = DisplayWidth(_display, _screen);
98 _display_height = DisplayHeight(_display, _screen);
102 void *xf86dga = dlopen(
"libXxf86dga.so.1", RTLD_NOW | RTLD_LOCAL);
103 if (xf86dga !=
nullptr) {
104 pfn_XF86DGAQueryVersion _XF86DGAQueryVersion = (pfn_XF86DGAQueryVersion)dlsym(xf86dga,
"XF86DGAQueryVersion");
105 _XF86DGADirectVideo = (pfn_XF86DGADirectVideo)dlsym(xf86dga,
"XF86DGADirectVideo");
107 int major_ver, minor_ver;
108 if (_XF86DGAQueryVersion ==
nullptr || _XF86DGADirectVideo ==
nullptr) {
109 x11display_cat.warning()
110 <<
"libXxf86dga.so.1 does not provide required functions; relative mouse mode will not work.\n";
112 }
else if (!_XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
113 _XF86DGADirectVideo =
nullptr;
116 _XF86DGADirectVideo =
nullptr;
117 if (x11display_cat.is_debug()) {
118 x11display_cat.debug()
119 <<
"cannot dlopen libXxf86dga.so.1; cursor changing will not work.\n";
124 void *xcursor = dlopen(
"libXcursor.so.1", RTLD_NOW | RTLD_LOCAL);
125 if (xcursor !=
nullptr) {
126 pfn_XcursorGetDefaultSize _XcursorGetDefaultSize = (pfn_XcursorGetDefaultSize)dlsym(xcursor,
"XcursorGetDefaultSize");
127 _XcursorXcFileLoadImages = (pfn_XcursorXcFileLoadImages)dlsym(xcursor,
"XcursorXcFileLoadImages");
128 _XcursorImagesLoadCursor = (pfn_XcursorImagesLoadCursor)dlsym(xcursor,
"XcursorImagesLoadCursor");
129 _XcursorImagesDestroy = (pfn_XcursorImagesDestroy)dlsym(xcursor,
"XcursorImagesDestroy");
130 _XcursorImageCreate = (pfn_XcursorImageCreate)dlsym(xcursor,
"XcursorImageCreate");
131 _XcursorImageLoadCursor = (pfn_XcursorImageLoadCursor)dlsym(xcursor,
"XcursorImageLoadCursor");
132 _XcursorImageDestroy = (pfn_XcursorImageDestroy)dlsym(xcursor,
"XcursorImageDestroy");
134 if (_XcursorGetDefaultSize ==
nullptr || _XcursorXcFileLoadImages ==
nullptr ||
135 _XcursorImagesLoadCursor ==
nullptr || _XcursorImagesDestroy ==
nullptr ||
136 _XcursorImageCreate ==
nullptr || _XcursorImageLoadCursor ==
nullptr ||
137 _XcursorImageDestroy ==
nullptr) {
139 x11display_cat.warning()
140 <<
"libXcursor.so.1 does not provide required functions; cursor changing will not work.\n";
142 }
else if (x_cursor_size.
get_value() >= 0) {
143 _xcursor_size = x_cursor_size;
145 _xcursor_size = _XcursorGetDefaultSize(_display);
149 if (x11display_cat.is_debug()) {
150 x11display_cat.debug()
151 <<
"cannot dlopen libXcursor.so.1; cursor changing will not work.\n";
156 void *xrandr = dlopen(
"libXrandr.so.2", RTLD_NOW | RTLD_LOCAL);
157 if (xrandr !=
nullptr) {
158 pfn_XRRQueryExtension _XRRQueryExtension = (pfn_XRRQueryExtension)dlsym(xrandr,
"XRRQueryExtension");
159 _XRRSizes = (pfn_XRRSizes)dlsym(xrandr,
"XRRSizes");
160 _XRRRates = (pfn_XRRRates)dlsym(xrandr,
"XRRRates");
161 _XRRGetScreenInfo = (pfn_XRRGetScreenInfo)dlsym(xrandr,
"XRRGetScreenInfo");
162 _XRRConfigCurrentConfiguration = (pfn_XRRConfigCurrentConfiguration)dlsym(xrandr,
"XRRConfigCurrentConfiguration");
163 _XRRSetScreenConfig = (pfn_XRRSetScreenConfig)dlsym(xrandr,
"XRRSetScreenConfig");
165 if (_XRRQueryExtension ==
nullptr || _XRRSizes ==
nullptr || _XRRRates ==
nullptr ||
166 _XRRGetScreenInfo ==
nullptr || _XRRConfigCurrentConfiguration ==
nullptr ||
167 _XRRSetScreenConfig ==
nullptr) {
168 _have_xrandr =
false;
169 x11display_cat.warning()
170 <<
"libXrandr.so.2 does not provide required functions; resolution setting will not work.\n";
173 _have_xrandr = _XRRQueryExtension(_display, &event, &error);
176 _have_xrandr =
false;
177 if (x11display_cat.is_debug()) {
178 x11display_cat.debug()
179 <<
"cannot dlopen libXrandr.so.2; resolution setting will not work.\n";
185 int num_sizes, num_rates;
187 xrrs = _XRRSizes(_display, 0, &num_sizes);
188 _display_information->_total_display_modes = 0;
189 for (
int i = 0; i < num_sizes; ++i) {
190 _XRRRates(_display, 0, i, &num_rates);
191 _display_information->_total_display_modes += num_rates;
196 _display_information->_display_mode_array =
new DisplayMode[_display_information->_total_display_modes];
197 for (
int i = 0; i < num_sizes; ++i) {
199 rates = _XRRRates(_display, 0, i, &num_rates);
200 for (
int j = 0; j < num_rates; ++j) {
201 DisplayMode* dm = _display_information->_display_mode_array + counter;
202 dm->width = xrrs[i].width;
203 dm->height = xrrs[i].height;
204 dm->refresh_rate = rates[j];
205 dm->bits_per_pixel = -1;
206 dm->fullscreen_only =
false;
213 _im = XOpenIM(_display,
nullptr,
nullptr,
nullptr);
214 if (_im == (XIM)
nullptr) {
215 x11display_cat.warning()
216 <<
"Couldn't open input method.\n";
233 _wm_delete_window = XInternAtom(_display,
"WM_DELETE_WINDOW",
false);
234 _net_wm_pid = XInternAtom(_display,
"_NET_WM_PID",
false);
235 _net_wm_window_type = XInternAtom(_display,
"_NET_WM_WINDOW_TYPE",
false);
236 _net_wm_window_type_splash = XInternAtom(_display,
"_NET_WM_WINDOW_TYPE_SPLASH",
false);
237 _net_wm_window_type_fullscreen = XInternAtom(_display,
"_NET_WM_WINDOW_TYPE_FULLSCREEN",
false);
238 _net_wm_state = XInternAtom(_display,
"_NET_WM_STATE",
false);
239 _net_wm_state_fullscreen = XInternAtom(_display,
"_NET_WM_STATE_FULLSCREEN",
false);
240 _net_wm_state_above = XInternAtom(_display,
"_NET_WM_STATE_ABOVE",
false);
241 _net_wm_state_below = XInternAtom(_display,
"_NET_WM_STATE_BELOW",
false);
242 _net_wm_state_add = XInternAtom(_display,
"_NET_WM_STATE_ADD",
false);
243 _net_wm_state_remove = XInternAtom(_display,
"_NET_WM_STATE_REMOVE",
false);
244 _net_wm_bypass_compositor = XInternAtom(_display,
"_NET_WM_BYPASS_COMPOSITOR",
false);
252 release_hidden_cursor();
257 XCloseDisplay(_display);
266 GraphicsPipe::PreferredWindowThread
285 void x11GraphicsPipe::
286 make_hidden_cursor() {
287 nassertv(_hidden_cursor == None);
289 unsigned int x_size, y_size;
290 XQueryBestCursor(_display, _root, 1, 1, &x_size, &y_size);
292 Pixmap empty = XCreatePixmap(_display, _root, x_size, y_size, 1);
295 memset(&black, 0,
sizeof(black));
297 _hidden_cursor = XCreatePixmapCursor(_display, empty, empty,
298 &black, &black, x_size, y_size);
299 XFreePixmap(_display, empty);
306 void x11GraphicsPipe::
307 release_hidden_cursor() {
308 if (_hidden_cursor != None) {
309 XFreeCursor(_display, _hidden_cursor);
310 _hidden_cursor = None;
321 void x11GraphicsPipe::
322 install_error_handlers() {
323 if (_error_handlers_installed) {
327 _prev_error_handler = (ErrorHandlerFunc *)XSetErrorHandler(error_handler);
328 _prev_io_error_handler = (IOErrorHandlerFunc *)XSetIOErrorHandler(io_error_handler);
329 _error_handlers_installed =
true;
335 int x11GraphicsPipe::
336 error_handler(X11_Display *display, XErrorEvent *error) {
339 static const int msg_len = 80;
341 XGetErrorText(display, error->error_code, msg, msg_len);
343 if (!_x_error_messages_enabled) {
344 if (x11display_cat.is_debug()) {
345 x11display_cat.debug()
351 x11display_cat.error()
366 int x11GraphicsPipe::
367 io_error_handler(X11_Display *display) {
368 x11display_cat.fatal()
369 <<
"X fatal error on display " << (
void *)display <<
"\n";
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight reentrant mutex.
get_value
Returns the variable's value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_environment_variable
Returns the definition of the indicated environment variable, or the empty string if the variable is ...