Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/freeglut/src/x11/fg_init_x11.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * fg_init_x11.c | |
| 3 * | |
| 4 * Various freeglut initialization functions. | |
| 5 * | |
| 6 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. | |
| 7 * Written by Pawel W. Olszta, <olszta@sourceforge.net> | |
| 8 * Copied for Platform code by Evan Felix <karcaw at gmail.com> | |
| 9 * Creation date: Thur Feb 2 2012 | |
| 10 * | |
| 11 * Permission is hereby granted, free of charge, to any person obtaining a | |
| 12 * copy of this software and associated documentation files (the "Software"), | |
| 13 * to deal in the Software without restriction, including without limitation | |
| 14 * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 15 * and/or sell copies of the Software, and to permit persons to whom the | |
| 16 * Software is furnished to do so, subject to the following conditions: | |
| 17 * | |
| 18 * The above copyright notice and this permission notice shall be included | |
| 19 * in all copies or substantial portions of the Software. | |
| 20 * | |
| 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 24 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |
| 25 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| 26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 27 */ | |
| 28 | |
| 29 #define FREEGLUT_BUILDING_LIB | |
| 30 #include <limits.h> /* LONG_MAX */ | |
| 31 #include <GL/freeglut.h> | |
| 32 #include "fg_internal.h" | |
| 33 #include "fg_init.h" | |
| 34 #include "egl/fg_init_egl.h" | |
| 35 | |
| 36 #include <locale.h> | |
| 37 | |
| 38 /* Return the atom associated with "name". */ | |
| 39 static Atom fghGetAtom(const char * name) | |
| 40 { | |
| 41 return XInternAtom(fgDisplay.pDisplay.Display, name, False); | |
| 42 } | |
| 43 | |
| 44 char *fgClipboardBuffer[3] = { NULL, NULL, NULL }; | |
| 45 | |
| 46 /* | |
| 47 * Check if "property" is set on "window". The property's values are returned | |
| 48 * through "data". If the property is set and is of type "type", return the | |
| 49 * number of elements in "data". Return zero otherwise. In both cases, use | |
| 50 * "Xfree()" to free "data". | |
| 51 */ | |
| 52 static int fghGetWindowProperty(Window window, | |
| 53 Atom property, | |
| 54 Atom type, | |
| 55 unsigned char ** data) | |
| 56 { | |
| 57 /* | |
| 58 * Caller always has to use "Xfree()" to free "data", since | |
| 59 * "XGetWindowProperty() always allocates one extra byte in prop_return | |
| 60 * [i.e. "data"] (even if the property is zero length) [..]". | |
| 61 */ | |
| 62 | |
| 63 int status; /* Returned by "XGetWindowProperty". */ | |
| 64 | |
| 65 Atom type_returned; | |
| 66 int temp_format; /* Not used. */ | |
| 67 unsigned long number_of_elements; | |
| 68 unsigned long temp_bytes_after; /* Not used. */ | |
| 69 | |
| 70 | |
| 71 status = XGetWindowProperty(fgDisplay.pDisplay.Display, | |
| 72 window, | |
| 73 property, | |
| 74 0, | |
| 75 LONG_MAX, | |
| 76 False, | |
| 77 type, | |
| 78 &type_returned, | |
| 79 &temp_format, | |
| 80 &number_of_elements, | |
| 81 &temp_bytes_after, | |
| 82 data); | |
| 83 | |
| 84 FREEGLUT_INTERNAL_ERROR_EXIT(status == Success, | |
| 85 "XGetWindowProperty failled", | |
| 86 "fghGetWindowProperty"); | |
| 87 | |
| 88 if (type_returned != type) | |
| 89 { | |
| 90 number_of_elements = 0; | |
| 91 } | |
| 92 | |
| 93 return number_of_elements; | |
| 94 } | |
| 95 | |
| 96 /* Check if the window manager is NET WM compliant. */ | |
| 97 static int fghNetWMSupported(void) | |
| 98 { | |
| 99 Atom wm_check; | |
| 100 Window ** window_ptr_1; | |
| 101 | |
| 102 int number_of_windows; | |
| 103 int net_wm_supported; | |
| 104 | |
| 105 | |
| 106 net_wm_supported = 0; | |
| 107 | |
| 108 wm_check = fghGetAtom("_NET_SUPPORTING_WM_CHECK"); | |
| 109 window_ptr_1 = malloc(sizeof(Window *)); | |
| 110 | |
| 111 /* | |
| 112 * Check that the window manager has set this property on the root window. | |
| 113 * The property must be the ID of a child window. | |
| 114 */ | |
| 115 number_of_windows = fghGetWindowProperty(fgDisplay.pDisplay.RootWindow, | |
| 116 wm_check, | |
| 117 XA_WINDOW, | |
| 118 (unsigned char **) window_ptr_1); | |
| 119 if (number_of_windows == 1) | |
| 120 { | |
| 121 Window ** window_ptr_2; | |
| 122 | |
| 123 window_ptr_2 = malloc(sizeof(Window *)); | |
| 124 | |
| 125 /* Check that the window has the same property set to the same value. */ | |
| 126 number_of_windows = fghGetWindowProperty(**window_ptr_1, | |
| 127 wm_check, | |
| 128 XA_WINDOW, | |
| 129 (unsigned char **) window_ptr_2); | |
| 130 if ((number_of_windows == 1) && (**window_ptr_1 == **window_ptr_2)) | |
| 131 { | |
| 132 /* NET WM compliant */ | |
| 133 net_wm_supported = 1; | |
| 134 } | |
| 135 | |
| 136 XFree(*window_ptr_2); | |
| 137 free(window_ptr_2); | |
| 138 } | |
| 139 | |
| 140 XFree(*window_ptr_1); | |
| 141 free(window_ptr_1); | |
| 142 | |
| 143 return net_wm_supported; | |
| 144 } | |
| 145 | |
| 146 /* Check if "hint" is present in "property" for "window". */ | |
| 147 int fgHintPresent(Window window, Atom property, Atom hint) | |
| 148 { | |
| 149 Atom *atoms; | |
| 150 int number_of_atoms; | |
| 151 int supported; | |
| 152 int i; | |
| 153 | |
| 154 supported = 0; | |
| 155 | |
| 156 number_of_atoms = fghGetWindowProperty(window, | |
| 157 property, | |
| 158 XA_ATOM, | |
| 159 (unsigned char **) &atoms); | |
| 160 for (i = 0; i < number_of_atoms; i++) | |
| 161 { | |
| 162 if (atoms[i] == hint) | |
| 163 { | |
| 164 supported = 1; | |
| 165 break; | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 XFree(atoms); | |
| 170 return supported; | |
| 171 } | |
| 172 | |
| 173 /* | |
| 174 * A call to this function should initialize all the display stuff... | |
| 175 */ | |
| 176 void fgPlatformInitialize( const char* displayName ) | |
| 177 { | |
| 178 fgDisplay.pDisplay.Display = XOpenDisplay( displayName ); | |
| 179 | |
| 180 if( fgDisplay.pDisplay.Display == NULL ) | |
| 181 fgError( "failed to open display '%s'", XDisplayName( displayName ) ); | |
| 182 | |
| 183 if ( fgState.XSyncSwitch ) | |
| 184 XSynchronize(fgDisplay.pDisplay.Display, True); | |
| 185 | |
| 186 #ifdef EGL_VERSION_1_0 | |
| 187 fghPlatformInitializeEGL(); | |
| 188 #else | |
| 189 if( !glXQueryExtension( fgDisplay.pDisplay.Display, NULL, NULL ) ) | |
| 190 fgError( "OpenGL GLX extension not supported by display '%s'", | |
| 191 XDisplayName( displayName ) ); | |
| 192 | |
| 193 /* This forces AMD Catalyst drivers to initialize and register a shutdown | |
| 194 * function, which must be done before our own call to atexit to prevent | |
| 195 * a crash if glutMainLoop is not called or is not exited cleanly. | |
| 196 * (see bug #206) | |
| 197 */ | |
| 198 glXQueryExtensionsString( fgDisplay.pDisplay.Display, | |
| 199 DefaultScreen( fgDisplay.pDisplay.Display )); | |
| 200 #endif | |
| 201 | |
| 202 fgDisplay.pDisplay.Screen = DefaultScreen( fgDisplay.pDisplay.Display ); | |
| 203 fgDisplay.pDisplay.RootWindow = RootWindow( | |
| 204 fgDisplay.pDisplay.Display, | |
| 205 fgDisplay.pDisplay.Screen | |
| 206 ); | |
| 207 | |
| 208 fgDisplay.ScreenWidth = DisplayWidth( | |
| 209 fgDisplay.pDisplay.Display, | |
| 210 fgDisplay.pDisplay.Screen | |
| 211 ); | |
| 212 fgDisplay.ScreenHeight = DisplayHeight( | |
| 213 fgDisplay.pDisplay.Display, | |
| 214 fgDisplay.pDisplay.Screen | |
| 215 ); | |
| 216 | |
| 217 fgDisplay.ScreenWidthMM = DisplayWidthMM( | |
| 218 fgDisplay.pDisplay.Display, | |
| 219 fgDisplay.pDisplay.Screen | |
| 220 ); | |
| 221 fgDisplay.ScreenHeightMM = DisplayHeightMM( | |
| 222 fgDisplay.pDisplay.Display, | |
| 223 fgDisplay.pDisplay.Screen | |
| 224 ); | |
| 225 | |
| 226 fgDisplay.pDisplay.Connection = ConnectionNumber( fgDisplay.pDisplay.Display ); | |
| 227 | |
| 228 /* Create the window deletion atom */ | |
| 229 fgDisplay.pDisplay.DeleteWindow = fghGetAtom("WM_DELETE_WINDOW"); | |
| 230 | |
| 231 /* Create the state and full screen atoms */ | |
| 232 fgDisplay.pDisplay.State = None; | |
| 233 fgDisplay.pDisplay.StateFullScreen = None; | |
| 234 fgDisplay.pDisplay.NetWMPid = None; | |
| 235 fgDisplay.pDisplay.ClientMachine = None; | |
| 236 | |
| 237 fgDisplay.pDisplay.NetWMSupported = fghNetWMSupported(); | |
| 238 | |
| 239 if (fgDisplay.pDisplay.NetWMSupported) | |
| 240 { | |
| 241 const Atom supported = fghGetAtom("_NET_SUPPORTED"); | |
| 242 const Atom state = fghGetAtom("_NET_WM_STATE"); | |
| 243 | |
| 244 /* Check if the state hint is supported. */ | |
| 245 if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, state)) | |
| 246 { | |
| 247 const Atom full_screen = fghGetAtom("_NET_WM_STATE_FULLSCREEN"); | |
| 248 | |
| 249 fgDisplay.pDisplay.State = state; | |
| 250 | |
| 251 /* Check if the window manager supports full screen. */ | |
| 252 /** Check "_NET_WM_ALLOWED_ACTIONS" on our window instead? **/ | |
| 253 if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, full_screen)) | |
| 254 { | |
| 255 fgDisplay.pDisplay.StateFullScreen = full_screen; | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 fgDisplay.pDisplay.NetWMPid = fghGetAtom("_NET_WM_PID"); | |
| 260 fgDisplay.pDisplay.ClientMachine = fghGetAtom("WM_CLIENT_MACHINE"); | |
| 261 } | |
| 262 | |
| 263 /* Open an input method */ | |
| 264 setlocale(LC_ALL, ""); /* ugh! but we can't force the client to do it for us... */ | |
| 265 if (!XSupportsLocale()) | |
| 266 fgWarning("X doesn't support the current locale."); | |
| 267 if (!XSetLocaleModifiers("")) | |
| 268 fgWarning("Couldn't set X locale modifiers."); | |
| 269 fgDisplay.pDisplay.IM = XOpenIM(fgDisplay.pDisplay.Display, NULL, NULL, NULL); | |
| 270 if (!fgDisplay.pDisplay.IM) | |
| 271 fgWarning("Couldn't open X input method."); | |
| 272 else | |
| 273 { | |
| 274 XIMStyles *styles; | |
| 275 XIMStyle supported = XIMPreeditNothing | XIMStatusNothing; | |
| 276 XIMStyle best = 0; | |
| 277 unsigned int i; | |
| 278 char *res = XGetIMValues(fgDisplay.pDisplay.IM, XNQueryInputStyle, &styles, NULL); | |
| 279 if (res) | |
| 280 fgWarning("Couldn't get input method style: %s.", res); | |
| 281 else | |
| 282 { | |
| 283 for (i = 0; i < styles->count_styles; ++i) | |
| 284 { | |
| 285 XIMStyle style = styles->supported_styles[i]; | |
| 286 if ((style & supported) == style) | |
| 287 best = style; | |
| 288 } | |
| 289 fgDisplay.pDisplay.InputStyle = best; | |
| 290 } | |
| 291 XFree(styles); | |
| 292 if (best == 0) | |
| 293 { | |
| 294 fgWarning("Couldn't find a usable input method style."); | |
| 295 XCloseIM(fgDisplay.pDisplay.IM); | |
| 296 fgDisplay.pDisplay.IM = NULL; | |
| 297 } | |
| 298 } | |
| 299 | |
| 300 /* Get start time */ | |
| 301 fgState.Time = fgSystemTime(); | |
| 302 | |
| 303 fgState.Initialised = GL_TRUE; | |
| 304 | |
| 305 atexit(fgDeinitialize); | |
| 306 | |
| 307 /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */ | |
| 308 fgInitialiseInputDevices(); | |
| 309 } | |
| 310 | |
| 311 void fgPlatformDeinitialiseInputDevices ( void ) | |
| 312 { | |
| 313 fghCloseInputDevices (); | |
| 314 | |
| 315 fgState.JoysticksInitialised = GL_FALSE; | |
| 316 fgState.InputDevsInitialised = GL_FALSE; | |
| 317 } | |
| 318 | |
| 319 | |
| 320 void fgPlatformCloseDisplay ( void ) | |
| 321 { | |
| 322 int i; | |
| 323 | |
| 324 /* | |
| 325 * Make sure all X-client data we have created will be destroyed on | |
| 326 * display closing | |
| 327 */ | |
| 328 XSetCloseDownMode( fgDisplay.pDisplay.Display, DestroyAll ); | |
| 329 | |
| 330 if (fgDisplay.pDisplay.IM) | |
| 331 XCloseIM(fgDisplay.pDisplay.IM); | |
| 332 | |
| 333 /* | |
| 334 * Close the display connection, destroying all windows we have | |
| 335 * created so far | |
| 336 */ | |
| 337 XCloseDisplay( fgDisplay.pDisplay.Display ); | |
| 338 | |
| 339 for (i = 0; i < 3; ++i) | |
| 340 { | |
| 341 free(fgClipboardBuffer[i]); | |
| 342 fgClipboardBuffer[i] = NULL; | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 | |
| 347 #ifndef EGL_VERSION_1_0 | |
| 348 void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext ) | |
| 349 { | |
| 350 /* Note that the MVisualInfo is not owned by the MenuContext! */ | |
| 351 glXDestroyContext( pDisplay.Display, MContext ); | |
| 352 } | |
| 353 #endif |
