00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "x11GraphicsPipe.h"
00016 #include "x11GraphicsWindow.h"
00017 #include "config_x11display.h"
00018 #include "frameBufferProperties.h"
00019
00020 TypeHandle x11GraphicsPipe::_type_handle;
00021
00022 bool x11GraphicsPipe::_error_handlers_installed = false;
00023 x11GraphicsPipe::ErrorHandlerFunc *x11GraphicsPipe::_prev_error_handler;
00024 x11GraphicsPipe::IOErrorHandlerFunc *x11GraphicsPipe::_prev_io_error_handler;
00025 bool x11GraphicsPipe::_x_error_messages_enabled = true;
00026 int x11GraphicsPipe::_x_error_count = 0;
00027
00028 LightReMutex x11GraphicsPipe::_x_mutex;
00029
00030
00031
00032
00033
00034
00035 x11GraphicsPipe::
00036 x11GraphicsPipe(const string &display) {
00037 string display_spec = display;
00038 if (display_spec.empty()) {
00039 display_spec = display_cfg;
00040 }
00041 if (display_spec.empty()) {
00042 display_spec = ExecutionEnvironment::get_environment_variable("DISPLAY");
00043 }
00044 if (display_spec.empty()) {
00045 display_spec = ":0.0";
00046 }
00047
00048
00049
00050 setlocale(LC_ALL, "");
00051
00052
00053
00054
00055 setlocale(LC_NUMERIC, "C");
00056
00057 _is_valid = false;
00058 _supported_types = OT_window | OT_buffer | OT_texture_buffer;
00059 _display = NULL;
00060 _screen = 0;
00061 _root = (X11_Window)NULL;
00062 _im = (XIM)NULL;
00063 _hidden_cursor = None;
00064
00065 install_error_handlers();
00066
00067 _display = XOpenDisplay(display_spec.c_str());
00068 if (!_display) {
00069 x11display_cat.error()
00070 << "Could not open display \"" << display_spec << "\".\n";
00071 _is_valid = false;
00072 _screen = None;
00073 _root = None;
00074 _display_width = 0;
00075 _display_height = 0;
00076 return;
00077 }
00078
00079 if (!XSupportsLocale()) {
00080 x11display_cat.warning()
00081 << "X does not support locale " << setlocale(LC_ALL, NULL) << "\n";
00082 }
00083 XSetLocaleModifiers("");
00084
00085 _screen = DefaultScreen(_display);
00086 _root = RootWindow(_display, _screen);
00087 _display_width = DisplayWidth(_display, _screen);
00088 _display_height = DisplayHeight(_display, _screen);
00089 _is_valid = true;
00090
00091 #ifdef HAVE_XRANDR
00092
00093 int num_sizes, num_rates;
00094 XRRScreenSize *xrrs;
00095 xrrs = XRRSizes(_display, 0, &num_sizes);
00096 _display_information->_total_display_modes = 0;
00097 for (int i = 0; i < num_sizes; ++i) {
00098 XRRRates(_display, 0, i, &num_rates);
00099 _display_information->_total_display_modes += num_rates;
00100 }
00101
00102 short *rates;
00103 short counter = 0;
00104 _display_information->_display_mode_array = new DisplayMode[_display_information->_total_display_modes];
00105 for (int i = 0; i < num_sizes; ++i) {
00106 int num_rates;
00107 rates = XRRRates(_display, 0, i, &num_rates);
00108 for (int j = 0; j < num_rates; ++j) {
00109 DisplayMode* dm = _display_information->_display_mode_array + counter;
00110 dm->width = xrrs[i].width;
00111 dm->height = xrrs[i].height;
00112 dm->refresh_rate = rates[j];
00113 dm->bits_per_pixel = -1;
00114 dm->fullscreen_only = false;
00115 ++counter;
00116 }
00117 }
00118 #endif
00119
00120
00121
00122 _im = XOpenIM(_display, NULL, NULL, NULL);
00123 if (_im == (XIM)NULL) {
00124 x11display_cat.warning()
00125 << "Couldn't open input method.\n";
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 _wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
00143 _net_wm_window_type = XInternAtom(_display, "_NET_WM_WINDOW_TYPE", false);
00144 _net_wm_window_type_splash = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_SPLASH", false);
00145 _net_wm_window_type_fullscreen = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_FULLSCREEN", false);
00146 _net_wm_state = XInternAtom(_display, "_NET_WM_STATE", false);
00147 _net_wm_state_fullscreen = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", false);
00148 _net_wm_state_above = XInternAtom(_display, "_NET_WM_STATE_ABOVE", false);
00149 _net_wm_state_below = XInternAtom(_display, "_NET_WM_STATE_BELOW", false);
00150 _net_wm_state_add = XInternAtom(_display, "_NET_WM_STATE_ADD", false);
00151 _net_wm_state_remove = XInternAtom(_display, "_NET_WM_STATE_REMOVE", false);
00152 }
00153
00154
00155
00156
00157
00158
00159 x11GraphicsPipe::
00160 ~x11GraphicsPipe() {
00161 release_hidden_cursor();
00162 if (_im) {
00163 XCloseIM(_im);
00164 }
00165 if (_display) {
00166 XCloseDisplay(_display);
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 GraphicsPipe::PreferredWindowThread
00179 x11GraphicsPipe::get_preferred_window_thread() const {
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 return PWT_draw;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200 void x11GraphicsPipe::
00201 make_hidden_cursor() {
00202 nassertv(_hidden_cursor == None);
00203
00204 unsigned int x_size, y_size;
00205 XQueryBestCursor(_display, _root, 1, 1, &x_size, &y_size);
00206
00207 Pixmap empty = XCreatePixmap(_display, _root, x_size, y_size, 1);
00208
00209 XColor black;
00210 memset(&black, 0, sizeof(black));
00211
00212 _hidden_cursor = XCreatePixmapCursor(_display, empty, empty,
00213 &black, &black, x_size, y_size);
00214 XFreePixmap(_display, empty);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 void x11GraphicsPipe::
00224 release_hidden_cursor() {
00225 if (_hidden_cursor != None) {
00226 XFreeCursor(_display, _hidden_cursor);
00227 _hidden_cursor = None;
00228 }
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 void x11GraphicsPipe::
00243 install_error_handlers() {
00244 if (_error_handlers_installed) {
00245 return;
00246 }
00247
00248 _prev_error_handler = (ErrorHandlerFunc *)XSetErrorHandler(error_handler);
00249 _prev_io_error_handler = (IOErrorHandlerFunc *)XSetIOErrorHandler(io_error_handler);
00250 _error_handlers_installed = true;
00251 }
00252
00253
00254
00255
00256
00257
00258
00259 int x11GraphicsPipe::
00260 error_handler(X11_Display *display, XErrorEvent *error) {
00261 ++_x_error_count;
00262
00263 static const int msg_len = 80;
00264 char msg[msg_len];
00265 XGetErrorText(display, error->error_code, msg, msg_len);
00266
00267 if (!_x_error_messages_enabled) {
00268 if (x11display_cat.is_debug()) {
00269 x11display_cat.debug()
00270 << msg << "\n";
00271 }
00272 return 0;
00273 }
00274
00275 x11display_cat.error()
00276 << msg << "\n";
00277
00278 if (x_error_abort) {
00279 abort();
00280 }
00281
00282
00283
00284 return 0;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 int x11GraphicsPipe::
00294 io_error_handler(X11_Display *display) {
00295 x11display_cat.fatal()
00296 << "X fatal error on display " << (void *)display << "\n";
00297
00298
00299
00300
00301
00302 return 0;
00303 }