1 /*
2 * Copyright (c) 2002-2008 LWJGL Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'LWJGL' nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /**
34 * $Id$
35 *
36 * Linux specific display functions.
37 *
38 * @author elias_naur <elias_naur@users.sourceforge.net>
39 * @version $Revision$
40 */
41
42 #include <X11/X.h>
43 #include <X11/Xlib.h>
44 #include <X11/Xutil.h>
45 #include <X11/extensions/xf86vmode.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <assert.h>
49 #include <jni.h>
50 #include <jawt_md.h>
51 #include "common_tools.h"
52 #include "extgl.h"
53 #include "extgl_glx.h"
54 #include "context.h"
55 #include "org_lwjgl_opengl_LinuxDisplay.h"
56 #include "org_lwjgl_opengl_LinuxDisplayPeerInfo.h"
57 #include "org_lwjgl_LinuxSysImplementation.h"
58
59 #define ERR_MSG_SIZE 1024
60
61 typedef struct {
62 unsigned long flags;
63 unsigned long functions;
64 unsigned long decorations;
65 long input_mode;
66 unsigned long status;
67 } MotifWmHints;
68
69 #define MWM_HINTS_DECORATIONS (1L << 1)
70
71 static GLXWindow glx_window = None;
72
73 static Colormap cmap;
74 static int current_depth;
75
76 static Visual *current_visual;
77
checkXError(JNIEnv * env,Display * disp)78 static bool checkXError(JNIEnv *env, Display *disp) {
79 XSync(disp, False);
80 return (*env)->ExceptionCheck(env) == JNI_FALSE;
81 }
82
global_error_handler(Display * disp,XErrorEvent * error)83 static int global_error_handler(Display *disp, XErrorEvent *error) {
84 JNIEnv *env = getThreadEnv();
85 if (env != NULL) {
86 jclass org_lwjgl_LinuxDisplay_class = (*env)->FindClass(env, "org/lwjgl/opengl/LinuxDisplay");
87 if (org_lwjgl_LinuxDisplay_class == NULL) {
88 // Don't propagate error
89 (*env)->ExceptionClear(env);
90 return 0;
91 }
92 jmethodID handler_method = (*env)->GetStaticMethodID(env, org_lwjgl_LinuxDisplay_class, "globalErrorHandler", "(JJJJJJJ)I");
93 if (handler_method == NULL)
94 return 0;
95 return (*env)->CallStaticIntMethod(env, org_lwjgl_LinuxDisplay_class, handler_method, (jlong)(intptr_t)disp, (jlong)(intptr_t)error,
96 (jlong)(intptr_t)error->display, (jlong)error->serial, (jlong)error->error_code, (jlong)error->request_code, (jlong)error->minor_code);
97 } else
98 return 0;
99 }
100
openDisplay(JNIEnv * env)101 static jlong openDisplay(JNIEnv *env) {
102 Display *display_connection = XOpenDisplay(NULL);
103 if (display_connection == NULL) {
104 throwException(env, "Could not open X display connection");
105 return (intptr_t)NULL;
106 }
107 return (intptr_t)display_connection;
108 }
109
Java_org_lwjgl_DefaultSysImplementation_getJNIVersion(JNIEnv * env,jobject ignored)110 JNIEXPORT jint JNICALL Java_org_lwjgl_DefaultSysImplementation_getJNIVersion
111 (JNIEnv *env, jobject ignored) {
112 return org_lwjgl_LinuxSysImplementation_JNI_VERSION;
113 }
114
Java_org_lwjgl_opengl_LinuxDisplay_getErrorText(JNIEnv * env,jclass unused,jlong display_ptr,jlong error_code)115 JNIEXPORT jstring JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getErrorText(JNIEnv *env, jclass unused, jlong display_ptr, jlong error_code) {
116 Display *disp = (Display *)(intptr_t)display_ptr;
117 char err_msg_buffer[ERR_MSG_SIZE];
118 XGetErrorText(disp, error_code, err_msg_buffer, ERR_MSG_SIZE);
119 err_msg_buffer[ERR_MSG_SIZE - 1] = '\0';
120 return NewStringNativeWithLength(env, err_msg_buffer, strlen(err_msg_buffer));
121 }
122
Java_org_lwjgl_opengl_LinuxDisplay_callErrorHandler(JNIEnv * env,jclass unused,jlong handler_ptr,jlong display_ptr,jlong event_ptr)123 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_callErrorHandler(JNIEnv *env, jclass unused, jlong handler_ptr, jlong display_ptr, jlong event_ptr) {
124 XErrorHandler handler = (XErrorHandler)(intptr_t)handler_ptr;
125 Display *disp = (Display *)(intptr_t)display_ptr;
126 XErrorEvent *event = (XErrorEvent *)(intptr_t)event_ptr;
127 return (jint)handler(disp, event);
128 }
129
Java_org_lwjgl_opengl_LinuxDisplay_setErrorHandler(JNIEnv * env,jclass unused)130 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_setErrorHandler(JNIEnv *env, jclass unused) {
131 return (intptr_t)XSetErrorHandler(global_error_handler);
132 }
133
Java_org_lwjgl_opengl_LinuxDisplay_resetErrorHandler(JNIEnv * env,jclass unused,jlong handler_ptr)134 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_resetErrorHandler(JNIEnv *env, jclass unused, jlong handler_ptr) {
135 XErrorHandler handler = (XErrorHandler)(intptr_t)handler_ptr;
136 return (intptr_t)XSetErrorHandler(handler);
137 }
138
Java_org_lwjgl_opengl_LinuxDisplay_nSync(JNIEnv * env,jclass unused,jlong display_ptr,jboolean throw_away_events)139 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSync(JNIEnv *env, jclass unused, jlong display_ptr, jboolean throw_away_events) {
140 Display *disp = (Display *)(intptr_t)display_ptr;
141 XSync(disp, throw_away_events ? True : False);
142 }
143
Java_org_lwjgl_opengl_LinuxDisplay_sync(JNIEnv * env,jclass unused,jlong display_ptr,jboolean throw_away_events)144 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_sync(JNIEnv *env, jclass unused, jlong display_ptr, jboolean throw_away_events) {
145 Display *disp = (Display *)(intptr_t)display_ptr;
146 XSync(disp, throw_away_events ? True : False);
147 }
148
Java_org_lwjgl_opengl_LinuxDisplay_nGetDefaultScreen(JNIEnv * env,jclass unused,jlong display_ptr)149 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetDefaultScreen(JNIEnv *env, jclass unused, jlong display_ptr) {
150 Display *disp = (Display *)(intptr_t)display_ptr;
151 return XDefaultScreen(disp);
152 }
153
Java_org_lwjgl_opengl_LinuxDisplay_nInternAtom(JNIEnv * env,jclass unused,jlong display_ptr,jstring atom_name_obj,jboolean only_if_exists)154 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nInternAtom(JNIEnv *env, jclass unused, jlong display_ptr, jstring atom_name_obj, jboolean only_if_exists) {
155 Display *disp = (Display *)(intptr_t)display_ptr;
156 char *atom_name = GetStringNativeChars(env, atom_name_obj);
157 if (atom_name == NULL)
158 return 0;
159 Atom atom = XInternAtom(disp, atom_name, only_if_exists ? True : False);
160 free(atom_name);
161 return atom;
162 }
163
setDecorations(Display * disp,Window window,int dec)164 static void setDecorations(Display *disp, Window window, int dec) {
165 Atom motif_hints_atom = XInternAtom(disp, "_MOTIF_WM_HINTS", False);
166 MotifWmHints motif_hints;
167 motif_hints.flags = MWM_HINTS_DECORATIONS;
168 motif_hints.decorations = dec;
169 XChangeProperty(disp, window, motif_hints_atom, motif_hints_atom, 32, PropModeReplace, (unsigned char *)&motif_hints, sizeof(MotifWmHints)/sizeof(long));
170 }
171
isLegacyFullscreen(jint window_mode)172 static bool isLegacyFullscreen(jint window_mode) {
173 return window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_LEGACY;
174 }
175
setWindowTitle(Display * disp,Window window,jlong title,jint len)176 static void setWindowTitle(Display *disp, Window window, jlong title, jint len) {
177 Atom UTF8_STRING = XInternAtom(disp, "UTF8_STRING", True);
178 Atom _NET_WM_NAME = XInternAtom(disp, "_NET_WM_NAME", True);
179 Atom _NET_WM_ICON_NAME = XInternAtom(disp, "_NET_WM_ICON_NAME", True);
180
181 // ASCII fallback if XChangeProperty fails.
182 XmbSetWMProperties(disp, window, (const char *)(intptr_t)title, (const char *)(intptr_t)title, NULL, 0, NULL, NULL, NULL);
183
184 // Set the UTF-8 encoded title
185 if ( _NET_WM_NAME )
186 XChangeProperty(
187 disp, window, _NET_WM_NAME, UTF8_STRING,
188 8, PropModeReplace, (const unsigned char *)(intptr_t)title, len
189 );
190
191 if ( _NET_WM_ICON_NAME )
192 XChangeProperty(
193 disp, window, _NET_WM_ICON_NAME, UTF8_STRING,
194 8, PropModeReplace, (const unsigned char *)(intptr_t)title, len
195 );
196 }
197
setClassHint(Display * disp,Window window,jlong wm_name,jlong wm_class)198 static void setClassHint(Display *disp, Window window, jlong wm_name, jlong wm_class) {
199 XClassHint* hint = XAllocClassHint();
200
201 hint->res_name = (char *)(intptr_t)wm_name;
202 hint->res_class = (char *)(intptr_t)wm_class;
203
204 XSetClassHint(disp, window, hint);
205
206 XFree(hint);
207 }
208
Java_org_lwjgl_opengl_LinuxDisplay_openDisplay(JNIEnv * env,jclass clazz)209 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_openDisplay(JNIEnv *env, jclass clazz) {
210 return openDisplay(env);
211 }
212
Java_org_lwjgl_opengl_LinuxDisplay_closeDisplay(JNIEnv * env,jclass clazz,jlong display)213 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_closeDisplay(JNIEnv *env, jclass clazz, jlong display) {
214 Display *disp = (Display *)(intptr_t)display;
215 XCloseDisplay(disp);
216 }
217
Java_org_lwjgl_opengl_LinuxDisplayPeerInfo_initDrawable(JNIEnv * env,jclass clazz,jlong window,jobject peer_info_handle)218 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplayPeerInfo_initDrawable(JNIEnv *env, jclass clazz, jlong window, jobject peer_info_handle) {
219 X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle);
220 if (peer_info->glx13)
221 peer_info->drawable = glx_window;
222 else
223 peer_info->drawable = window;
224 }
225
Java_org_lwjgl_opengl_LinuxDisplayPeerInfo_initDefaultPeerInfo(JNIEnv * env,jclass clazz,jlong display,jint screen,jobject peer_info_handle,jobject pixel_format)226 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplayPeerInfo_initDefaultPeerInfo(JNIEnv *env, jclass clazz, jlong display, jint screen, jobject peer_info_handle, jobject pixel_format) {
227 Display *disp = (Display *)(intptr_t)display;
228 initPeerInfo(env, peer_info_handle, disp, screen, pixel_format, true, GLX_WINDOW_BIT, true, false);
229 }
230
Java_org_lwjgl_opengl_LinuxDisplay_nSetTitle(JNIEnv * env,jclass clazz,jlong display,jlong window_ptr,jlong title,jint len)231 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetTitle(JNIEnv * env, jclass clazz, jlong display, jlong window_ptr, jlong title, jint len) {
232 Display *disp = (Display *)(intptr_t)display;
233 Window window = (Window)window_ptr;
234 setWindowTitle(disp, window, title, len);
235 }
236
Java_org_lwjgl_opengl_LinuxDisplay_nSetClassHint(JNIEnv * env,jclass clazz,jlong display,jlong window_ptr,jlong wm_name,jlong wm_class)237 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetClassHint(JNIEnv * env, jclass clazz, jlong display, jlong window_ptr, jlong wm_name, jlong wm_class) {
238 Display *disp = (Display *)(intptr_t)display;
239 Window window = (Window)window_ptr;
240 setClassHint(disp, window, wm_name, wm_class);
241 }
242
destroyWindow(JNIEnv * env,Display * disp,Window window)243 static void destroyWindow(JNIEnv *env, Display *disp, Window window) {
244 if (glx_window != None) {
245 lwjgl_glXDestroyWindow(disp, glx_window);
246 glx_window = None;
247 }
248 XDestroyWindow(disp, window);
249 XFreeColormap(disp, cmap);
250 }
251
isNetWMFullscreenSupported(JNIEnv * env,Display * disp,int screen)252 static bool isNetWMFullscreenSupported(JNIEnv *env, Display *disp, int screen) {
253 unsigned long nitems;
254 Atom actual_type;
255 int actual_format;
256 unsigned long bytes_after;
257 Atom *supported_list;
258 Atom netwm_supported_atom = XInternAtom(disp, "_NET_SUPPORTED", False);
259 int result = XGetWindowProperty(disp, RootWindow(disp, screen), netwm_supported_atom, 0, 10000, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, (void *)&supported_list);
260 if (result != Success) {
261 throwException(env, "Unable to query _NET_SUPPORTED window property");
262 return false;
263 }
264 Atom fullscreen_atom = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False);
265 bool supported = false;
266 unsigned long i;
267 for (i = 0; i < nitems; i++) {
268 if (fullscreen_atom == supported_list[i]) {
269 supported = true;
270 break;
271 }
272 }
273 XFree(supported_list);
274 return supported;
275 }
276
Java_org_lwjgl_opengl_LinuxDisplay_nIsNetWMFullscreenSupported(JNIEnv * env,jclass unused,jlong display,jint screen)277 JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsNetWMFullscreenSupported(JNIEnv *env, jclass unused, jlong display, jint screen) {
278 Display *disp = (Display *)(intptr_t)display;
279 return isNetWMFullscreenSupported(env, disp, screen) ? JNI_TRUE : JNI_FALSE;
280 }
281
Java_org_lwjgl_opengl_LinuxDisplay_nReshape(JNIEnv * env,jclass clazz,jlong display,jlong window_ptr,jint x,jint y,jint width,jint height)282 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReshape(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr, jint x, jint y, jint width, jint height) {
283 Display *disp = (Display *)(intptr_t)display;
284 Window window = (Window)window_ptr;
285 XMoveWindow(disp, window, x, y);
286 XResizeWindow(disp, window, width, height);
287 }
288
Java_org_lwjgl_opengl_LinuxDisplay_synchronize(JNIEnv * env,jclass clazz,jlong display,jboolean synchronize)289 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_synchronize(JNIEnv *env, jclass clazz, jlong display, jboolean synchronize) {
290 Display *disp = (Display *)(intptr_t)display;
291 XSynchronize(disp, synchronize ? True : False);
292 }
293
Java_org_lwjgl_opengl_LinuxDisplay_getRootWindow(JNIEnv * env,jclass clazz,jlong display,jint screen)294 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getRootWindow(JNIEnv *env, jclass clazz, jlong display, jint screen) {
295 Display *disp = (Display *)(intptr_t)display;
296 return RootWindow(disp, screen);
297 }
298
getCurrentWindow(JNIEnv * env,jlong display_ptr,jlong window_ptr)299 static Window getCurrentWindow(JNIEnv *env, jlong display_ptr, jlong window_ptr) {
300 Display *disp = (Display *)(intptr_t)display_ptr;
301
302 Window parent = (Window)window_ptr;
303 Window win, root;
304
305 Window *children;
306 unsigned int nchildren;
307
308 do {
309 win = parent;
310
311 if (XQueryTree(disp, win, &root, &parent, &children, &nchildren) == 0) {
312 throwException(env, "XQueryTree failed");
313 return 0;
314 }
315
316 if (children != NULL) XFree(children);
317 } while (parent != root);
318
319 return win;
320 }
321
Java_org_lwjgl_opengl_LinuxDisplay_nGetX(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr)322 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetX(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
323 Display *disp = (Display *)(intptr_t)display_ptr;
324 Window win = getCurrentWindow(env, display_ptr, window_ptr);
325
326 XWindowAttributes win_attribs;
327 XGetWindowAttributes(disp, win, &win_attribs);
328
329 return win_attribs.x;
330 }
331
Java_org_lwjgl_opengl_LinuxDisplay_nGetY(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr)332 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetY(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
333 Display *disp = (Display *)(intptr_t)display_ptr;
334 Window win = getCurrentWindow(env, display_ptr, window_ptr);
335
336 XWindowAttributes win_attribs;
337 XGetWindowAttributes(disp, win, &win_attribs);
338
339 return win_attribs.y;
340 }
341
Java_org_lwjgl_opengl_LinuxDisplay_nGetWidth(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr)342 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetWidth(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
343 Display *disp = (Display *)(intptr_t)display_ptr;
344 Window win = (Window)window_ptr;
345 XWindowAttributes win_attribs;
346
347 XGetWindowAttributes(disp, win, &win_attribs);
348
349 return win_attribs.width;
350 }
351
Java_org_lwjgl_opengl_LinuxDisplay_nGetHeight(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr)352 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetHeight(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
353 Display *disp = (Display *)(intptr_t)display_ptr;
354 Window win = (Window)window_ptr;
355 XWindowAttributes win_attribs;
356
357 XGetWindowAttributes(disp, win, &win_attribs);
358
359 return win_attribs.height;
360 }
361
updateWindowHints(JNIEnv * env,Display * disp,Window window)362 static void updateWindowHints(JNIEnv *env, Display *disp, Window window) {
363 XWMHints* win_hints = XAllocWMHints();
364 if (win_hints == NULL) {
365 throwException(env, "XAllocWMHints failed");
366 return;
367 }
368
369 win_hints->flags = InputHint;
370 win_hints->input = True;
371
372 XSetWMHints(disp, window, win_hints);
373 XFree(win_hints);
374 XFlush(disp);
375 }
376
updateWindowBounds(Display * disp,Window win,int x,int y,int width,int height,jboolean position,jboolean resizable)377 static void updateWindowBounds(Display *disp, Window win, int x, int y, int width, int height, jboolean position, jboolean resizable) {
378 XSizeHints *window_hints = XAllocSizeHints();
379
380 if (position) {
381 window_hints->flags |= PPosition;
382 window_hints->x = x;
383 window_hints->y = y;
384 }
385
386 if (!resizable) {
387 window_hints->flags |= PMinSize | PMaxSize;
388 window_hints->min_width = width;
389 window_hints->max_width = width;
390 window_hints->min_height = height;
391 window_hints->max_height = height;
392 }
393
394 XSetWMNormalHints(disp, win, window_hints);
395 XFree(window_hints);
396 }
397
createWindow(JNIEnv * env,Display * disp,int screen,jint window_mode,X11PeerInfo * peer_info,int x,int y,int width,int height,jboolean undecorated,long parent_handle,jboolean resizable)398 static Window createWindow(JNIEnv* env, Display *disp, int screen, jint window_mode, X11PeerInfo *peer_info, int x, int y, int width, int height, jboolean undecorated, long parent_handle, jboolean resizable) {
399 Window parent = (Window)parent_handle;
400 Window win;
401 XSetWindowAttributes attribs;
402 int attribmask;
403
404 XVisualInfo *vis_info = getVisualInfoFromPeerInfo(env, peer_info);
405 if (vis_info == NULL)
406 return false;
407 cmap = XCreateColormap(disp, parent, vis_info->visual, AllocNone);
408 attribs.colormap = cmap;
409 attribs.border_pixel = 0;
410 attribs.event_mask = ExposureMask | FocusChangeMask | VisibilityChangeMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask| EnterWindowMask | LeaveWindowMask;
411 attribmask = CWColormap | CWEventMask | CWBorderPixel;
412 if (isLegacyFullscreen(window_mode)) {
413 attribmask |= CWOverrideRedirect;
414 attribs.override_redirect = True;
415 }
416 win = XCreateWindow(disp, parent, x, y, width, height, 0, vis_info->depth, InputOutput, vis_info->visual, attribmask, &attribs);
417
418 current_depth = vis_info->depth;
419 current_visual = vis_info->visual;
420
421 XFree(vis_info);
422 if (!checkXError(env, disp)) {
423 XFreeColormap(disp, cmap);
424 return false;
425 }
426 // printfDebugJava(env, "Created window");
427 if (undecorated) {
428 // Use Motif decoration hint property and hope the window manager respects them
429 setDecorations(disp, win, 0);
430 }
431
432 if (RootWindow(disp, screen) == parent_handle) { // only set hints when Display.setParent isn't used
433 updateWindowBounds(disp, win, x, y, width, height, JNI_TRUE, resizable);
434 updateWindowHints(env, disp, win);
435 }
436
437 #define NUM_ATOMS 1
438 Atom protocol_atoms[NUM_ATOMS] = {XInternAtom(disp, "WM_DELETE_WINDOW", False)/*, XInternAtom(disp, "WM_TAKE_FOCUS", False)*/};
439 XSetWMProtocols(disp, win, protocol_atoms, NUM_ATOMS);
440 if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) {
441 Atom fullscreen_atom = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False);
442 XChangeProperty(disp, win, XInternAtom(disp, "_NET_WM_STATE", False),
443 XInternAtom(disp, "ATOM", False), 32, PropModeReplace, (const unsigned char*)&fullscreen_atom, 1);
444 }
445 if (!checkXError(env, disp)) {
446 destroyWindow(env, disp, win);
447 return 0;
448 }
449 return win;
450 }
451
Java_org_lwjgl_opengl_LinuxDisplay_reparentWindow(JNIEnv * env,jclass unused,jlong display,jlong window_ptr,jlong parent_ptr,jint x,jint y)452 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_reparentWindow(JNIEnv *env, jclass unused, jlong display, jlong window_ptr, jlong parent_ptr, jint x, jint y) {
453 Display *disp = (Display *)(intptr_t)display;
454 Window window = (Window)window_ptr;
455 Window parent = (Window)parent_ptr;
456 XReparentWindow(disp, window, parent, x, y);
457 }
458
Java_org_lwjgl_opengl_LinuxDisplay_mapRaised(JNIEnv * env,jclass unused,jlong display,jlong window_ptr)459 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_mapRaised(JNIEnv *env, jclass unused, jlong display, jlong window_ptr) {
460 Display *disp = (Display *)(intptr_t)display;
461 Window window = (Window)window_ptr;
462 XMapRaised(disp, window);
463 }
464
Java_org_lwjgl_opengl_LinuxDisplay_getParentWindow(JNIEnv * env,jclass unused,jlong display,jlong window_ptr)465 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getParentWindow(JNIEnv *env, jclass unused, jlong display, jlong window_ptr) {
466 Display *disp = (Display *)(intptr_t)display;
467 Window window = (Window)window_ptr;
468 Window root, parent;
469 Window *children;
470 unsigned int nchildren;
471 if (XQueryTree(disp, window, &root, &parent, &children, &nchildren) == 0) {
472 throwException(env, "XQueryTree failed");
473 return None;
474 }
475 if (children != NULL)
476 XFree(children);
477 return parent;
478 }
479
Java_org_lwjgl_opengl_LinuxDisplay_getChildCount(JNIEnv * env,jclass unused,jlong display,jlong window_ptr)480 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_getChildCount(JNIEnv *env, jclass unused, jlong display, jlong window_ptr) {
481 Display *disp = (Display *)(intptr_t)display;
482 Window window = (Window)window_ptr;
483 Window root, parent;
484 Window *children;
485 unsigned int nchildren;
486 if (XQueryTree(disp, window, &root, &parent, &children, &nchildren) == 0) {
487 throwException(env, "XQueryTree failed");
488 return None;
489 }
490 if (children != NULL)
491 XFree(children);
492
493 return nchildren;
494 }
495
Java_org_lwjgl_opengl_LinuxDisplay_hasProperty(JNIEnv * env,jclass unusued,jlong display,jlong window_ptr,jlong property_ptr)496 JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_hasProperty(JNIEnv *env, jclass unusued, jlong display, jlong window_ptr, jlong property_ptr) {
497 Display *disp = (Display *)(intptr_t)display;
498 Window window = (Window)window_ptr;
499 Atom property = (Atom)property_ptr;
500 int num_props;
501 Atom *properties = XListProperties(disp, window, &num_props);
502 if (properties == NULL)
503 return JNI_FALSE;
504 jboolean result = JNI_FALSE;
505 for (int i = 0; i < num_props; i++) {
506 if (properties[i] == property) {
507 result = JNI_TRUE;
508 break;
509 }
510 }
511 XFree(properties);
512 return result;
513 }
514
Java_org_lwjgl_opengl_LinuxDisplay_nGetInputFocus(JNIEnv * env,jclass unused,jlong display_ptr)515 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetInputFocus(JNIEnv *env, jclass unused, jlong display_ptr) {
516 Display *disp = (Display *)(intptr_t)display_ptr;
517 int revert_mode;
518 Window win;
519 XGetInputFocus(disp, &win, &revert_mode);
520 return win;
521 }
522
Java_org_lwjgl_opengl_LinuxDisplay_nSetInputFocus(JNIEnv * env,jclass clazz,jlong display,jlong window_ptr,jlong time)523 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetInputFocus(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr, jlong time) {
524 Display *disp = (Display *)(intptr_t)display;
525 Window window = (Window)window_ptr;
526 XSetInputFocus(disp, window, RevertToParent, time);
527 }
528
Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv * env,jclass clazz,jlong display,jint screen,jobject peer_info_handle,jobject mode,jint window_mode,jint x,jint y,jboolean undecorated,jlong parent_handle,jboolean resizable)529 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jlong display, jint screen, jobject peer_info_handle, jobject mode, jint window_mode, jint x, jint y, jboolean undecorated, jlong parent_handle, jboolean resizable) {
530 Display *disp = (Display *)(intptr_t)display;
531 X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle);
532 GLXFBConfig *fb_config = NULL;
533 if (peer_info->glx13) {
534 fb_config = getFBConfigFromPeerInfo(env, peer_info);
535 if (fb_config == NULL)
536 return 0;
537 }
538 jclass cls_displayMode = (*env)->GetObjectClass(env, mode);
539 jfieldID fid_width = (*env)->GetFieldID(env, cls_displayMode, "width", "I");
540 jfieldID fid_height = (*env)->GetFieldID(env, cls_displayMode, "height", "I");
541 int width = (*env)->GetIntField(env, mode, fid_width);
542 int height = (*env)->GetIntField(env, mode, fid_height);
543 Window win = createWindow(env, disp, screen, window_mode, peer_info, x, y, width, height, undecorated, parent_handle, resizable);
544 if ((*env)->ExceptionOccurred(env)) {
545 return 0;
546 }
547 if (peer_info->glx13) {
548 glx_window = lwjgl_glXCreateWindow(disp, *fb_config, win, NULL);
549 XFree(fb_config);
550 }
551 if (!checkXError(env, disp)) {
552 lwjgl_glXDestroyWindow(disp, glx_window);
553 destroyWindow(env, disp, win);
554 }
555 return win;
556 }
557
Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowSize(JNIEnv * env,jclass clazz,jlong display,jlong window_ptr,jint width,jint height,jboolean resizable)558 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowSize(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr, jint width, jint height, jboolean resizable) {
559 Display *disp = (Display *)(intptr_t)display;
560 Window win = (Window)window_ptr;
561 updateWindowBounds(disp, win, 0, 0, width, height, JNI_FALSE, resizable);
562 }
563
Java_org_lwjgl_opengl_LinuxDisplay_nDestroyWindow(JNIEnv * env,jclass clazz,jlong display,jlong window_ptr)564 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyWindow(JNIEnv *env, jclass clazz, jlong display, jlong window_ptr) {
565 Display *disp = (Display *)(intptr_t)display;
566 Window window = (Window)window_ptr;
567 destroyWindow(env, disp, window);
568 }
569
Java_org_lwjgl_opengl_LinuxDisplay_nLockAWT(JNIEnv * env,jclass clazz)570 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nLockAWT(JNIEnv *env, jclass clazz) {
571 JAWT jawt;
572 jawt.version = JAWT_VERSION_1_4;
573 if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
574 throwException(env, "GetAWT failed");
575 return;
576 }
577 jawt.Lock(env);
578 }
579
Java_org_lwjgl_opengl_LinuxDisplay_nUnlockAWT(JNIEnv * env,jclass clazz)580 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUnlockAWT(JNIEnv *env, jclass clazz) {
581 JAWT jawt;
582 jawt.version = JAWT_VERSION_1_4;
583 if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) {
584 throwException(env, "GetAWT failed");
585 return;
586 }
587 jawt.Unlock(env);
588 }
589
Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowIcon(JNIEnv * env,jclass clazz,jlong display,jlong window_ptr,jobject icons_buffer,jint icons_buffer_size)590 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowIcon
591 (JNIEnv *env, jclass clazz, jlong display, jlong window_ptr, jobject icons_buffer, jint icons_buffer_size)
592 {
593 Display *disp = (Display *)(intptr_t)display;
594 Window window = (Window)window_ptr;
595 const unsigned char *icons_char_buffer = (const unsigned char *)(*env)->GetDirectBufferAddress(env, icons_buffer);
596
597 int length = icons_buffer_size/4;
598 unsigned long icons_long_buffer[length];
599 int i = 0;
600
601 // copy byte array to long array
602 for (i = 0; i < icons_buffer_size; i += 4) {
603 unsigned long argb = (icons_char_buffer[i] << 24) |
604 (icons_char_buffer[i+1] << 16) |
605 (icons_char_buffer[i+2] << 8) |
606 (icons_char_buffer[i+3]);
607 icons_long_buffer[i/4] = argb;
608 }
609
610 XChangeProperty(disp, window,
611 XInternAtom(disp, "_NET_WM_ICON", False),
612 XInternAtom(disp, "CARDINAL", False),
613 32, PropModeReplace, (const unsigned char*) icons_long_buffer, length);
614 }
615
Java_org_lwjgl_opengl_LinuxDisplay_nUngrabKeyboard(JNIEnv * env,jclass unused,jlong display_ptr)616 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUngrabKeyboard(JNIEnv *env, jclass unused, jlong display_ptr) {
617 Display *disp = (Display *)(intptr_t)display_ptr;
618 return XUngrabKeyboard(disp, CurrentTime);
619 }
620
Java_org_lwjgl_opengl_LinuxDisplay_nGrabKeyboard(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr)621 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabKeyboard(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
622 Display *disp = (Display *)(intptr_t)display_ptr;
623 Window win = (Window)window_ptr;
624 return XGrabKeyboard(disp, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
625 }
626
Java_org_lwjgl_opengl_LinuxDisplay_nGrabPointer(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr,jlong cursor_ptr)627 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabPointer(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jlong cursor_ptr) {
628 Display *disp = (Display *)(intptr_t)display_ptr;
629 Window win = (Window)window_ptr;
630 Cursor cursor = (Cursor)cursor_ptr;
631 int grab_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
632 return XGrabPointer(disp, win, False, grab_mask, GrabModeAsync, GrabModeAsync, win, cursor, CurrentTime);
633 }
634
Java_org_lwjgl_opengl_LinuxDisplay_nSetViewPort(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr,jint screen)635 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetViewPort(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jint screen) {
636 Display *disp = (Display *)(intptr_t)display_ptr;
637 Window win = (Window)window_ptr;
638 XWindowAttributes win_attribs;
639
640 XGetWindowAttributes(disp, win, &win_attribs);
641 XF86VidModeSetViewPort(disp, screen, win_attribs.x, win_attribs.y);
642 }
643
Java_org_lwjgl_opengl_LinuxDisplay_nUngrabPointer(JNIEnv * env,jclass unused,jlong display_ptr)644 JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUngrabPointer(JNIEnv *env, jclass unused, jlong display_ptr) {
645 Display *disp = (Display *)(intptr_t)display_ptr;
646 return XUngrabPointer(disp, CurrentTime);
647 }
648
Java_org_lwjgl_opengl_LinuxDisplay_nDefineCursor(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr,jlong cursor_ptr)649 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDefineCursor(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jlong cursor_ptr) {
650 Display *disp = (Display *)(intptr_t)display_ptr;
651 Window win = (Window)window_ptr;
652 Cursor cursor = (Cursor)cursor_ptr;
653 XDefineCursor(disp, win, cursor);
654 }
655
Java_org_lwjgl_opengl_LinuxDisplay_nCreateBlankCursor(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr)656 JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateBlankCursor(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr) {
657 Display *disp = (Display *)(intptr_t)display_ptr;
658 Window win = (Window)window_ptr;
659 unsigned int best_width, best_height;
660 if (XQueryBestCursor(disp, win, 1, 1, &best_width, &best_height) == 0) {
661 throwException(env, "Could not query best cursor size");
662 return false;
663 }
664 Pixmap mask = XCreatePixmap(disp, win, best_width, best_height, 1);
665 XGCValues gc_values;
666 gc_values.foreground = 0;
667 GC gc = XCreateGC(disp, mask, GCForeground, &gc_values);
668 XFillRectangle(disp, mask, gc, 0, 0, best_width, best_height);
669 XFreeGC(disp, gc);
670 XColor dummy_color;
671 Cursor cursor = XCreatePixmapCursor(disp, mask, mask, &dummy_color, &dummy_color, 0, 0);
672 XFreePixmap(disp, mask);
673 return cursor;
674 }
675
Java_org_lwjgl_opengl_LinuxDisplay_nIconifyWindow(JNIEnv * env,jclass unused,jlong display_ptr,jlong window_ptr,jint screen)676 JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIconifyWindow(JNIEnv *env, jclass unused, jlong display_ptr, jlong window_ptr, jint screen) {
677 Display *disp = (Display *)(intptr_t)display_ptr;
678 Window win = (Window)window_ptr;
679 XIconifyWindow(disp, win, screen);
680 }
681