1 /*
2 * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 #include "awt_p.h"
27 #include "awt.h"
28 #include "color.h"
29 #include <java_awt_DisplayMode.h>
30 #include <sun_awt_X11GraphicsEnvironment.h>
31 #include <sun_awt_X11GraphicsDevice.h>
32 #include <sun_awt_X11GraphicsConfig.h>
33 #ifndef HEADLESS
34 #include <X11/extensions/Xdbe.h>
35 #include <X11/XKBlib.h>
36 #include "Xrandr.h"
37 #include "GLXGraphicsConfig.h"
38 #endif /* !HEADLESS */
39
40 #include <jni.h>
41 #include <jni_util.h>
42 #include <jvm.h>
43 #include <jlong.h>
44
45 #include <stdlib.h>
46
47 #include "awt_GraphicsEnv.h"
48 #include "awt_Window.h"
49 #include "awt_util.h"
50 #include "gdefs.h"
51 #include <dlfcn.h>
52 #include "Trace.h"
53
54 #ifdef NETSCAPE
55 #include <signal.h>
56 extern int awt_init_xt;
57 #endif
58
59 #ifndef HEADLESS
60
61 int awt_numScreens; /* Xinerama-aware number of screens */
62
63 AwtScreenDataPtr x11Screens;
64
65 /*
66 * Set in initDisplay() to indicate whether we should attempt to initialize
67 * GLX for the default configuration.
68 */
69 static jboolean glxRequested = JNI_FALSE;
70
71 #endif /* !HEADLESS */
72
73 #ifdef HEADLESS
74 #define Display void
75 #endif /* HEADLESS */
76
77 Display *awt_display;
78
79 jclass tkClass = NULL;
80 jmethodID awtLockMID = NULL;
81 jmethodID awtUnlockMID = NULL;
82 jmethodID awtWaitMID = NULL;
83 jmethodID awtNotifyMID = NULL;
84 jmethodID awtNotifyAllMID = NULL;
85 jboolean awtLockInited = JNI_FALSE;
86
87 /** Convenience macro for loading the lock-related method IDs. */
88 #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \
89 do { \
90 method_id = (*env)->GetStaticMethodID(env, klass, \
91 method_name, method_sig); \
92 if (method_id == NULL) return NULL; \
93 } while (0)
94
95 struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
96 struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs;
97 extern struct WindowIDs mWindowIDs;
98 extern struct MWindowPeerIDs mWindowPeerIDs;
99
100 #ifndef HEADLESS
101 int awtCreateX11Colormap(AwtGraphicsConfigDataPtr adata);
102 #endif /* HEADLESS */
103
104 static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig";
105
106 /* AWT and Xinerama
107 *
108 * As of fix 4356756, AWT is Xinerama-aware. X11GraphicsDevices are created for
109 * each screen of a Xinerama setup, though X11 itself still only sees a single
110 * display.
111 * In many places where we talk to X11, a xinawareScreen variable is used to
112 * pass the correct Display value, depending on the circumstances (a single
113 * X display, multiple X displays, or a single X display with multiple
114 * Xinerama screens).
115 *
116 * Solaris and Linux differ in the functions used to access Xinerama-related
117 * data. This is in part because at this time, the X consortium has not
118 * finalized the "official" Xinerama API. Once this spec is available, and
119 * both OSes are conformant, one code base should be sufficient for Xinerama
120 * operation on both OSes. Until then, some of the Xinerama-related code
121 * is ifdef'd appropriately. -bchristi, 7/12/01
122 */
123
124 #define MAXFRAMEBUFFERS 16
125 #ifdef __linux__
126 typedef struct {
127 int screen_number;
128 short x_org;
129 short y_org;
130 short width;
131 short height;
132 } XineramaScreenInfo;
133
134 typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*);
135
136 #else /* SOLARIS */
137 typedef Status XineramaGetInfoFunc(Display* display, int screen_number,
138 XRectangle* framebuffer_rects, unsigned char* framebuffer_hints,
139 int* num_framebuffers);
140 typedef Status XineramaGetCenterHintFunc(Display* display, int screen_number,
141 int* x, int* y);
142
143 XineramaGetCenterHintFunc* XineramaSolarisCenterFunc = NULL;
144 #endif
145
146 Bool usingXinerama = False;
147 XRectangle fbrects[MAXFRAMEBUFFERS];
148
149 JNIEXPORT void JNICALL
150 Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls)
151 {
152 x11GraphicsConfigIDs.aData = NULL;
153 x11GraphicsConfigIDs.bitsPerPixel = NULL;
154 x11GraphicsConfigIDs.screen = NULL;
155
156 x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J");
157 x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I");
158 x11GraphicsConfigIDs.screen = (*env)->GetFieldID (env, cls, "screen", "Lsun/awt/X11GraphicsDevice;");
159
160 if (x11GraphicsConfigIDs.aData == NULL ||
161 x11GraphicsConfigIDs.bitsPerPixel == NULL ||
162 x11GraphicsConfigIDs.screen == NULL) {
163
164 JNU_ThrowNoSuchFieldError(env, "Can't find a field");
165 return;
166 }
167 }
168
169 JNIEXPORT void JNICALL
170 Java_sun_awt_X11GraphicsDevice_initIDs (JNIEnv *env, jclass cls)
171 {
172 x11GraphicsDeviceIDs.screen = NULL;
173 x11GraphicsDeviceIDs.screen = (*env)->GetFieldID (env, cls, "screen", "I");
174 DASSERT(x11GraphicsDeviceIDs.screen);
175 }
176
177 #ifndef HEADLESS
178
179 /*
180 * XIOErrorHandler
181 */
182 static int xioerror_handler(Display *disp)
183 {
184 if (awtLockInited) {
185 if (errno == EPIPE) {
186 jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL));
187 }
188 /*SignalError(lockedee->lastpc, lockedee, "fp/ade/gui/GUIException", "I/O error"); */
189 }
190 return 0;
191 }
192
193 static AwtGraphicsConfigDataPtr
194 findWithTemplate(XVisualInfo *vinfo,
195 long mask)
196 {
197
198 XVisualInfo *visualList;
199 XColor color;
200 AwtGraphicsConfigDataPtr defaultConfig;
201 int visualsMatched, i;
202
203 visualList = XGetVisualInfo(awt_display,
204 mask, vinfo, &visualsMatched);
205 if (visualList) {
206 defaultConfig = ZALLOC(_AwtGraphicsConfigData);
207 for (i = 0; i < visualsMatched; i++) {
208 memcpy(&defaultConfig->awt_visInfo, &visualList[i], sizeof(XVisualInfo));
209 defaultConfig->awt_depth = visualList[i].depth;
210
211 /* we can't use awtJNI_CreateColorData here, because it'll pull,
212 SystemColor, which in turn will cause toolkit to be reinitialized */
213 if (awtCreateX11Colormap(defaultConfig)) {
214 /* Allocate white and black pixels for this visual */
215 color.flags = DoRed | DoGreen | DoBlue;
216 color.red = color.green = color.blue = 0x0000;
217 XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
218 x11Screens[visualList[i].screen].blackpixel = color.pixel;
219 color.flags = DoRed | DoGreen | DoBlue;
220 color.red = color.green = color.blue = 0xffff;
221 XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
222 x11Screens[visualList[i].screen].whitepixel = color.pixel;
223
224 XFree(visualList);
225 return defaultConfig;
226 }
227 }
228 XFree(visualList);
229 free((void *)defaultConfig);
230 }
231 return NULL;
232 }
233
234 /* default config is based on X11 screen. All Xinerama screens of that X11
235 screen will have the same default config */
236 /* Need more notes about which fields of the structure are based on the X
237 screen, and which are based on the Xinerama screen */
238 static AwtGraphicsConfigDataPtr
239 makeDefaultConfig(JNIEnv *env, int screen) {
240
241 AwtGraphicsConfigDataPtr defaultConfig;
242 int xinawareScreen = 0;
243 VisualID forcedVisualID, defaultVisualID;
244 char *forcedVisualStr;
245 XVisualInfo vinfo;
246 long mask;
247
248 xinawareScreen = usingXinerama ? 0 : screen;
249 defaultVisualID =
250 XVisualIDFromVisual(DefaultVisual(awt_display, xinawareScreen));
251
252 memset(&vinfo, 0, sizeof(XVisualInfo));
253 vinfo.screen = xinawareScreen;
254
255 if ((forcedVisualStr = getenv("FORCEDEFVIS"))) {
256 mask = VisualIDMask | VisualScreenMask;
257 if (sscanf(forcedVisualStr, "%x", &forcedVisualID) > 0 &&
258 forcedVisualID > 0)
259 {
260 vinfo.visualid = forcedVisualID;
261 } else {
262 vinfo.visualid = defaultVisualID;
263 }
264 } else {
265 VisualID bestGLXVisualID;
266 if (glxRequested &&
267 (bestGLXVisualID = GLXGC_FindBestVisual(env, xinawareScreen)) > 0)
268 {
269 /* we've found the best visual for use with GLX, so use it */
270 vinfo.visualid = bestGLXVisualID;
271 mask = VisualIDMask | VisualScreenMask;
272 } else {
273 /* otherwise, continue looking for the best X11 visual */
274 vinfo.depth = 24;
275 vinfo.class = TrueColor;
276 mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
277 }
278 }
279
280 /* try the best, or forced visual */
281 defaultConfig = findWithTemplate(&vinfo, mask);
282 if (defaultConfig) {
283 return defaultConfig;
284 }
285
286 /* try the default visual */
287 vinfo.visualid = defaultVisualID;
288 mask = VisualIDMask | VisualScreenMask;
289 defaultConfig = findWithTemplate(&vinfo, mask);
290 if (defaultConfig) {
291 return defaultConfig;
292 }
293
294 /* try any TrueColor */
295 vinfo.class = TrueColor;
296 mask = VisualScreenMask | VisualClassMask;
297 defaultConfig = findWithTemplate(&vinfo, mask);
298 if (defaultConfig) {
299 return defaultConfig;
300 }
301
302 /* try 8-bit PseudoColor */
303 vinfo.depth = 8;
304 vinfo.class = PseudoColor;
305 mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
306 defaultConfig = findWithTemplate(&vinfo, mask);
307 if (defaultConfig) {
308 return defaultConfig;
309 }
310
311 /* try any 8-bit */
312 vinfo.depth = 8;
313 mask = VisualDepthMask | VisualScreenMask;
314 defaultConfig = findWithTemplate(&vinfo, mask);
315 if (defaultConfig) {
316 return defaultConfig;
317 }
318
319 /* we tried everything, give up */
320 JNU_ThrowInternalError(env, "Can't find supported visual");
321 XCloseDisplay(awt_display);
322 awt_display = NULL;
323 return NULL;
324 }
325
326 static void
327 getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) {
328
329 int i;
330 int n8p=0, n12p=0, n8s=0, n8gs=0, n8sg=0, n1sg=0, nTrue=0;
331 int nConfig;
332 XVisualInfo *pVI8p, *pVI12p, *pVI8s, *pVITrue, *pVI8gs,
333 *pVI8sg, *pVI1sg = NULL, viTmp;
334 AwtGraphicsConfigDataPtr *graphicsConfigs;
335 AwtGraphicsConfigDataPtr defaultConfig;
336 int ind;
337 char errmsg[128];
338 int xinawareScreen;
339 void* xrenderLibHandle = NULL;
340 XRenderFindVisualFormatFunc* xrenderFindVisualFormat = NULL;
341 int major_opcode, first_event, first_error;
342
343 if (usingXinerama) {
344 xinawareScreen = 0;
345 }
346 else {
347 xinawareScreen = screen;
348 }
349
350 AWT_LOCK ();
351
352 viTmp.screen = xinawareScreen;
353
354 viTmp.depth = 8;
355 viTmp.class = PseudoColor;
356 viTmp.colormap_size = 256;
357 pVI8p = XGetVisualInfo (awt_display,
358 VisualDepthMask | VisualClassMask |
359 VisualColormapSizeMask | VisualScreenMask,
360 &viTmp, &n8p);
361
362 viTmp.depth = 12;
363 viTmp.class = PseudoColor;
364 viTmp.colormap_size = 4096;
365 pVI12p = XGetVisualInfo (awt_display,
366 VisualDepthMask | VisualClassMask |
367 VisualColormapSizeMask | VisualScreenMask,
368 &viTmp, &n12p);
369
370 viTmp.class = TrueColor;
371 pVITrue = XGetVisualInfo (awt_display,
372 VisualClassMask |
373 VisualScreenMask,
374 &viTmp, &nTrue);
375
376 viTmp.depth = 8;
377 viTmp.class = StaticColor;
378 pVI8s = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask |
379 VisualScreenMask, &viTmp, &n8s);
380
381 viTmp.depth = 8;
382 viTmp.class = GrayScale;
383 viTmp.colormap_size = 256;
384 pVI8gs = XGetVisualInfo (awt_display,
385 VisualDepthMask | VisualClassMask |
386 VisualColormapSizeMask | VisualScreenMask,
387 &viTmp, &n8gs);
388 viTmp.depth = 8;
389 viTmp.class = StaticGray;
390 viTmp.colormap_size = 256;
391 pVI8sg = XGetVisualInfo (awt_display,
392 VisualDepthMask | VisualClassMask |
393 VisualColormapSizeMask | VisualScreenMask,
394 &viTmp, &n8sg);
395
396 /* REMIND.. remove when we have support for the color classes below */
397 /* viTmp.depth = 1; */
398 /* viTmp.class = StaticGray; */
399 /* pVI1sg = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask, */
400 /* viTmp, &n1sg); */
401
402 nConfig = n8p + n12p + n8s + n8gs + n8sg + n1sg + nTrue + 1;
403 graphicsConfigs = (AwtGraphicsConfigDataPtr *)
404 calloc(nConfig, sizeof(AwtGraphicsConfigDataPtr));
405 if (graphicsConfigs == NULL) {
406 JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
407 NULL);
408 AWT_UNLOCK();
409 return;
410 }
411
412 if (screenDataPtr->defaultConfig == NULL) {
413 /*
414 * After a display change event, the default config field will have
415 * been reset, so we need to recreate the default config here.
416 */
417 screenDataPtr->defaultConfig = makeDefaultConfig(env, screen);
418 }
419
420 defaultConfig = screenDataPtr->defaultConfig;
421 graphicsConfigs[0] = defaultConfig;
422 nConfig = 1; /* reserve index 0 for default config */
423
424 // Only use the RENDER extension if it is available on the X server
425 if (XQueryExtension(awt_display, "RENDER",
426 &major_opcode, &first_event, &first_error))
427 {
428 xrenderLibHandle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);
429
430 #ifndef __linux__ /* SOLARIS */
431 if (xrenderLibHandle == NULL) {
432 xrenderLibHandle = dlopen("/usr/sfw/lib/libXrender.so.1",
433 RTLD_LAZY | RTLD_GLOBAL);
434 }
435 #endif
436
437 if (xrenderLibHandle != NULL) {
438 xrenderFindVisualFormat =
439 (XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle,
440 "XRenderFindVisualFormat");
441 }
442 }
443
444 for (i = 0; i < nTrue; i++) {
445 if (XVisualIDFromVisual(pVITrue[i].visual) ==
446 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) ||
447 pVITrue[i].depth == 12) {
448 /* Skip the non-supported 12-bit TrueColor visual */
449 continue;
450 } else {
451 ind = nConfig++;
452 }
453 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
454 graphicsConfigs [ind]->awt_depth = pVITrue [i].depth;
455 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],
456 sizeof (XVisualInfo));
457 if (xrenderFindVisualFormat != NULL) {
458 XRenderPictFormat *format = XRenderFindVisualFormat (awt_display,
459 pVITrue [i].visual);
460 if (format &&
461 format->type == PictTypeDirect &&
462 format->direct.alphaMask)
463 {
464 graphicsConfigs [ind]->isTranslucencySupported = 1;
465 memcpy(&graphicsConfigs [ind]->renderPictFormat, format,
466 sizeof(*format));
467 }
468 }
469 }
470
471 if (xrenderLibHandle != NULL) {
472 dlclose(xrenderLibHandle);
473 xrenderLibHandle = NULL;
474 }
475
476 for (i = 0; i < n8p; i++) {
477 if (XVisualIDFromVisual(pVI8p[i].visual) ==
478 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
479 continue;
480 } else {
481 ind = nConfig++;
482 }
483 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
484 graphicsConfigs [ind]->awt_depth = pVI8p [i].depth;
485 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i],
486 sizeof (XVisualInfo));
487 }
488
489 for (i = 0; i < n12p; i++) {
490 if (XVisualIDFromVisual(pVI12p[i].visual) ==
491 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
492 continue;
493 } else {
494 ind = nConfig++;
495 }
496 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
497 graphicsConfigs [ind]->awt_depth = pVI12p [i].depth;
498 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI12p [i],
499 sizeof (XVisualInfo));
500 }
501
502 for (i = 0; i < n8s; i++) {
503 if (XVisualIDFromVisual(pVI8s[i].visual) ==
504 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
505 continue;
506 } else {
507 ind = nConfig++;
508 }
509 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
510 graphicsConfigs [ind]->awt_depth = pVI8s [i].depth;
511 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8s [i],
512 sizeof (XVisualInfo));
513 }
514
515 for (i = 0; i < n8gs; i++) {
516 if (XVisualIDFromVisual(pVI8gs[i].visual) ==
517 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
518 continue;
519 } else {
520 ind = nConfig++;
521 }
522 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
523 graphicsConfigs [ind]->awt_depth = pVI8gs [i].depth;
524 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8gs [i],
525 sizeof (XVisualInfo));
526 }
527
528 for (i = 0; i < n8sg; i++) {
529 if (XVisualIDFromVisual(pVI8sg[i].visual) ==
530 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
531 continue;
532 } else {
533 ind = nConfig++;
534 }
535 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
536 graphicsConfigs [ind]->awt_depth = pVI8sg [i].depth;
537 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8sg [i],
538 sizeof (XVisualInfo));
539 }
540
541 for (i = 0; i < n1sg; i++) {
542 if (XVisualIDFromVisual(pVI1sg[i].visual) ==
543 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
544 continue;
545 } else {
546 ind = nConfig++;
547 }
548 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
549 graphicsConfigs [ind]->awt_depth = pVI1sg [i].depth;
550 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI1sg [i],
551 sizeof (XVisualInfo));
552 }
553
554 if (n8p != 0)
555 XFree (pVI8p);
556 if (n12p != 0)
557 XFree (pVI12p);
558 if (n8s != 0)
559 XFree (pVI8s);
560 if (n8gs != 0)
561 XFree (pVI8gs);
562 if (n8sg != 0)
563 XFree (pVI8sg);
564 if (n1sg != 0)
565 XFree (pVI1sg);
566
567 screenDataPtr->numConfigs = nConfig;
568 screenDataPtr->configs = graphicsConfigs;
569
570 AWT_UNLOCK ();
571 }
572
573 /*
574 * Determing if this top-level has been moved onto another Xinerama screen.
575 * Called from awt_TopLevel.c
576 *
577 * ASSUME: wdata != null
578 */
579 #ifndef HEADLESS
580 void checkNewXineramaScreen(JNIEnv* env, jobject peer, struct FrameData* wdata,
581 int32_t newX, int32_t newY,
582 int32_t newWidth, int32_t newHeight) {
583 int i;
584 int amt;
585 int totAmt = 0;
586 int largestAmt = 0;
587 int largestAmtScr = 0;
588
589 int horiz;
590 int vert;
591
592 if (!usingXinerama) { return; }
593
594 totAmt = newWidth * newHeight;
595
596 /* assert that peer implements WindowPeer */
597 DASSERT(JNU_IsInstanceOfByName(env, peer, "java/awt/peer/WindowPeer"));
598
599 DTRACE_PRINTLN4("checkNewXineramaScreen() x=%i y=%i w=%i h=%i\n",newX, newY, newWidth, newHeight);
600
601 /* decide which screen we're on
602 * if we're spanning, figure out which screen we're most on
603 */
604 for (i = 0; i < awt_numScreens; i++) {
605 if (INTERSECTS(newX, newX + newWidth, newY, newY + newHeight,
606 fbrects[i].x, fbrects[i].x + fbrects[i].width,
607 fbrects[i].y, fbrects[i].y + fbrects[i].height)) {
608
609 /* calc how much of window is on this screen */
610 horiz = MIN(newX + newWidth, fbrects[i].x + fbrects[i].width) -
611 MAX(newX, fbrects[i].x);
612 vert = MIN(newY + newHeight, fbrects[i].y + fbrects[i].height) -
613 MAX(newY, fbrects[i].y);
614 DASSERT(horiz > 0);
615 DASSERT(vert > 0);
616
617 amt = horiz * vert;
618 if (amt == totAmt) {
619 /* completely on this screen - done! */
620 largestAmtScr = i;
621 break;
622 }
623 if (amt > largestAmt) {
624 largestAmt = amt;
625 largestAmtScr = i;
626 }
627 }
628 }
629
630 #ifndef XAWT
631 /* check if we're on a new screen */
632 if (largestAmtScr != wdata->screenNum) {
633 wdata->screenNum = largestAmtScr;
634 /* update peer, target Comp */
635 (*env)->CallVoidMethod(env, peer,
636 mWindowPeerIDs.draggedToScreenMID, largestAmtScr);
637 }
638 #endif /* XAWT */
639 }
640 #endif /* HEADLESS */
641
642 #ifndef HEADLESS
643 #ifdef __linux__
644 static void xinerama_init_linux()
645 {
646 void* libHandle = 0;
647 char* XineramaLibName= "libXinerama.so.1";
648 int32_t locNumScr = 0;
649 XineramaScreenInfo *xinInfo;
650 char* XineramaQueryScreensName = "XineramaQueryScreens";
651 XineramaQueryScreensFunc* XineramaQueryScreens = NULL;
652
653 /* load library */
654 libHandle = dlopen(XineramaLibName, RTLD_LAZY | RTLD_GLOBAL);
655 if (libHandle != 0) {
656 XineramaQueryScreens = (XineramaQueryScreensFunc*)
657 dlsym(libHandle, XineramaQueryScreensName);
658
659 if (XineramaQueryScreens != NULL) {
660 DTRACE_PRINTLN("calling XineramaQueryScreens func on Linux");
661 xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
662 if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
663 int32_t idx;
664 DTRACE_PRINTLN("Enabling Xinerama support");
665 usingXinerama = True;
666 /* set global number of screens */
667 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
668 awt_numScreens = locNumScr;
669
670 /* stuff values into fbrects */
671 for (idx = 0; idx < awt_numScreens; idx++) {
672 DASSERT(xinInfo[idx].screen_number == idx);
673
674 fbrects[idx].width = xinInfo[idx].width;
675 fbrects[idx].height = xinInfo[idx].height;
676 fbrects[idx].x = xinInfo[idx].x_org;
677 fbrects[idx].y = xinInfo[idx].y_org;
678 }
679 } else {
680 DTRACE_PRINTLN("calling XineramaQueryScreens didn't work");
681 }
682 } else {
683 DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");
684 }
685 dlclose(libHandle);
686 } else {
687 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
688 }
689 }
690 #endif
691 #ifndef __linux__ /* Solaris */
692 static void xinerama_init_solaris()
693 {
694 void* libHandle = 0;
695 char* XineramaLibName= "libXext.so";
696 unsigned char fbhints[MAXFRAMEBUFFERS];
697 int32_t locNumScr = 0;
698 /* load and run XineramaGetInfo */
699 char* XineramaGetInfoName = "XineramaGetInfo";
700 char* XineramaGetCenterHintName = "XineramaGetCenterHint";
701 XineramaGetInfoFunc* XineramaSolarisFunc = NULL;
702
703 /* load library */
704 libHandle = dlopen(XineramaLibName, RTLD_LAZY | RTLD_GLOBAL);
705 if (libHandle != 0) {
706 XineramaSolarisFunc = (XineramaGetInfoFunc*)dlsym(libHandle, XineramaGetInfoName);
707 XineramaSolarisCenterFunc =
708 (XineramaGetCenterHintFunc*)dlsym(libHandle, XineramaGetCenterHintName);
709
710 if (XineramaSolarisFunc != NULL) {
711 DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris");
712 if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0],
713 &fbhints[0], &locNumScr) != 0 &&
714 locNumScr > XScreenCount(awt_display))
715 {
716 DTRACE_PRINTLN("Enabling Xinerama support");
717 usingXinerama = True;
718 /* set global number of screens */
719 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
720 awt_numScreens = locNumScr;
721 } else {
722 DTRACE_PRINTLN("calling XineramaGetInfo didn't work");
723 }
724 } else {
725 DTRACE_PRINTLN("couldn't load XineramaGetInfo symbol");
726 }
727 dlclose(libHandle);
728 } else {
729 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
730 }
731 }
732 #endif
733
734 /*
735 * Checks if Xinerama is running and perform Xinerama-related
736 * platform dependent initialization.
737 */
738 static void xineramaInit(void) {
739 char* XinExtName = "XINERAMA";
740 int32_t major_opcode, first_event, first_error;
741 Bool gotXinExt = False;
742
743 gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,
744 &first_event, &first_error);
745
746 if (!gotXinExt) {
747 DTRACE_PRINTLN("Xinerama extension is not available");
748 return;
749 }
750
751 DTRACE_PRINTLN("Xinerama extension is available");
752 #ifdef __linux__
753 xinerama_init_linux();
754 #else /* Solaris */
755 xinerama_init_solaris();
756 #endif /* __linux__ */
757 }
758 #endif /* HEADLESS */
759
760 Display *
761 awt_init_Display(JNIEnv *env, jobject this)
762 {
763 jclass klass;
764 Display *dpy;
765 char errmsg[128];
766 int i;
767 #ifdef NETSCAPE
768 sigset_t alarm_set, oldset;
769 #endif
770
771 if (awt_display) {
772 return awt_display;
773 }
774
775 #ifdef NETSCAPE
776 /* Disable interrupts during XtOpenDisplay to avoid bugs in unix os select
777 code: some unix systems don't implement SA_RESTART properly and
778 because of this, select returns with EINTR. Most implementations of
779 gethostbyname don't cope with EINTR properly and as a result we get
780 stuck (forever) in the gethostbyname code
781 */
782 sigemptyset(&alarm_set);
783 sigaddset(&alarm_set, SIGALRM);
784 sigprocmask(SIG_BLOCK, &alarm_set, &oldset);
785 #endif
786
787 /* Load AWT lock-related methods in SunToolkit */
788 klass = (*env)->FindClass(env, "sun/awt/SunToolkit");
789 if (klass == NULL) return NULL;
790 GET_STATIC_METHOD(klass, awtLockMID, "awtLock", "()V");
791 GET_STATIC_METHOD(klass, awtUnlockMID, "awtUnlock", "()V");
792 GET_STATIC_METHOD(klass, awtWaitMID, "awtLockWait", "(J)V");
793 GET_STATIC_METHOD(klass, awtNotifyMID, "awtLockNotify", "()V");
794 GET_STATIC_METHOD(klass, awtNotifyAllMID, "awtLockNotifyAll", "()V");
795 tkClass = (*env)->NewGlobalRef(env, klass);
796 awtLockInited = JNI_TRUE;
797
798 if (getenv("_AWT_IGNORE_XKB") != NULL &&
799 strlen(getenv("_AWT_IGNORE_XKB")) > 0) {
800 if (XkbIgnoreExtension(True)) {
801 printf("Ignoring XKB.\n");
802 }
803 }
804
805 dpy = awt_display = XOpenDisplay(NULL);
806 #ifdef NETSCAPE
807 sigprocmask(SIG_SETMASK, &oldset, NULL);
808 #endif
809 if (!dpy) {
810 jio_snprintf(errmsg,
811 sizeof(errmsg),
812 "Can't connect to X11 window server using '%s' as the value of the DISPLAY variable.",
813 (getenv("DISPLAY") == NULL) ? ":0.0" : getenv("DISPLAY"));
814 JNU_ThrowInternalError(env, errmsg);
815 return NULL;
816 }
817
818 XSetIOErrorHandler(xioerror_handler);
819
820 /* set awt_numScreens, and whether or not we're using Xinerama */
821 xineramaInit();
822
823 if (!usingXinerama) {
824 awt_numScreens = XScreenCount(awt_display);
825 }
826
827 DTRACE_PRINTLN1("allocating %i screens\n", awt_numScreens);
828 /* Allocate screen data structure array */
829 x11Screens = calloc(awt_numScreens, sizeof(AwtScreenData));
830 if (x11Screens == NULL) {
831 JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
832 NULL);
833 return NULL;
834 }
835
836 for (i = 0; i < awt_numScreens; i++) {
837 if (usingXinerama) {
838 /* All Xinerama screens use the same X11 root for now */
839 x11Screens[i].root = RootWindow(awt_display, 0);
840 }
841 else {
842 x11Screens[i].root = RootWindow(awt_display, i);
843 }
844 x11Screens[i].defaultConfig = makeDefaultConfig(env, i);
845 }
846
847 return dpy;
848 }
849 #endif /* !HEADLESS */
850
851 /*
852 * Class: sun_awt_X11GraphicsEnvironment
853 * Method: getDefaultScreenNum
854 * Signature: ()I
855 */
856 JNIEXPORT jint JNICALL
857 Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum(
858 JNIEnv *env, jobject this)
859 {
860 #ifdef HEADLESS
861 return (jint)0;
862 #else
863 return DefaultScreen(awt_display);
864 #endif /* !HEADLESS */
865 }
866
867 #ifndef HEADLESS
868 static void ensureConfigsInited(JNIEnv* env, int screen) {
869 if (x11Screens[screen].numConfigs == 0) {
870 if (env == NULL) {
871 env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
872 }
873 getAllConfigs (env, screen, &(x11Screens[screen]));
874 }
875 }
876 #endif
877
878 #ifdef HEADLESS
879 void* getDefaultConfig(int screen) {
880 return NULL;
881 }
882 #else
883 AwtGraphicsConfigDataPtr
884 getDefaultConfig(int screen) {
885 ensureConfigsInited(NULL, screen);
886 return x11Screens[screen].defaultConfig;
887 }
888
889 AwtScreenDataPtr
890 getScreenData(int screen) {
891 return &(x11Screens[screen]);
892 }
893 #endif /* !HEADLESS */
894
895 /*
896 * Class: sun_awt_X11GraphicsEnvironment
897 * Method: initDisplay
898 * Signature: (Z)V
899 */
900 JNIEXPORT void JNICALL
901 Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this,
902 jboolean glxReq)
903 {
904 #ifndef HEADLESS
905 glxRequested = glxReq;
906 (void) awt_init_Display(env, this);
907 #endif /* !HEADLESS */
908 }
909
910 /*
911 * Class: sun_awt_X11GraphicsEnvironment
912 * Method: initGLX
913 * Signature: ()Z
914 */
915 JNIEXPORT jboolean JNICALL
916 Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge)
917 {
918 #ifndef HEADLESS
919 jboolean glxAvailable;
920
921 AWT_LOCK();
922 glxAvailable = GLXGC_IsGLXAvailable();
923 AWT_UNLOCK();
924
925 return glxAvailable;
926 #else
927 return JNI_FALSE;
928 #endif /* !HEADLESS */
929 }
930
931 /*
932 * Class: sun_awt_X11GraphicsEnvironment
933 * Method: getNumScreens
934 * Signature: ()I
935 */
936 JNIEXPORT jint JNICALL
937 Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this)
938 {
939 #ifdef HEADLESS
940 return (jint)0;
941 #else
942 return awt_numScreens;
943 #endif /* !HEADLESS */
944 }
945
946 /*
947 * Class: sun_awt_X11GraphicsDevice
948 * Method: getDisplay
949 * Signature: ()J
950 */
951 JNIEXPORT jlong JNICALL
952 Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this)
953 {
954 #ifdef HEADLESS
955 return NULL;
956 #else
957 return ptr_to_jlong(awt_display);
958 #endif /* !HEADLESS */
959 }
960
961 #ifdef MITSHM
962
963 static jint canUseShmExt = UNSET_MITSHM;
964 static jint canUseShmExtPixmaps = UNSET_MITSHM;
965 static jboolean xshmAttachFailed = JNI_FALSE;
966
967 int J2DXErrHandler(Display *display, XErrorEvent *xerr) {
968 int ret = 0;
969 if (xerr->minor_code == X_ShmAttach) {
970 xshmAttachFailed = JNI_TRUE;
971 } else {
972 ret = (*xerror_saved_handler)(display, xerr);
973 }
974 return ret;
975 }
976 jboolean isXShmAttachFailed() {
977 return xshmAttachFailed;
978 }
979 void resetXShmAttachFailed() {
980 xshmAttachFailed = JNI_FALSE;
981 }
982
983 void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
984 XShmSegmentInfo shminfo;
985 int XShmMajor, XShmMinor;
986 int a, b, c;
987
988 AWT_LOCK();
989 if (canUseShmExt != UNSET_MITSHM) {
990 *shmExt = canUseShmExt;
991 *shmPixmaps = canUseShmExtPixmaps;
992 AWT_UNLOCK();
993 return;
994 }
995
996 *shmExt = canUseShmExt = CANT_USE_MITSHM;
997 *shmPixmaps = canUseShmExtPixmaps = CANT_USE_MITSHM;
998
999 /**
1000 * XShmQueryExtension returns False in remote server case.
1001 * Unfortunately it also returns True in ssh case, so
1002 * we need to test that we can actually do XShmAttach.
1003 */
1004 if (XShmQueryExtension(awt_display)) {
1005 shminfo.shmid = shmget(IPC_PRIVATE, 0x10000, IPC_CREAT|0777);
1006 if (shminfo.shmid < 0) {
1007 AWT_UNLOCK();
1008 J2dRlsTraceLn1(J2D_TRACE_ERROR,
1009 "TryInitMITShm: shmget has failed: %s",
1010 strerror(errno));
1011 return;
1012 }
1013 shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0);
1014 if (shminfo.shmaddr == ((char *) -1)) {
1015 shmctl(shminfo.shmid, IPC_RMID, 0);
1016 AWT_UNLOCK();
1017 J2dRlsTraceLn1(J2D_TRACE_ERROR,
1018 "TryInitMITShm: shmat has failed: %s",
1019 strerror(errno));
1020 return;
1021 }
1022 shminfo.readOnly = True;
1023
1024 resetXShmAttachFailed();
1025 /**
1026 * The J2DXErrHandler handler will set xshmAttachFailed
1027 * to JNI_TRUE if any Shm error has occured.
1028 */
1029 EXEC_WITH_XERROR_HANDLER(J2DXErrHandler,
1030 XShmAttach(awt_display, &shminfo));
1031
1032 /**
1033 * Get rid of the id now to reduce chances of leaking
1034 * system resources.
1035 */
1036 shmctl(shminfo.shmid, IPC_RMID, 0);
1037
1038 if (isXShmAttachFailed() == JNI_FALSE) {
1039 canUseShmExt = CAN_USE_MITSHM;
1040 /* check if we can use shared pixmaps */
1041 XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,
1042 (Bool*)&canUseShmExtPixmaps);
1043 canUseShmExtPixmaps = canUseShmExtPixmaps &&
1044 (XShmPixmapFormat(awt_display) == ZPixmap);
1045 XShmDetach(awt_display, &shminfo);
1046 }
1047 shmdt(shminfo.shmaddr);
1048 *shmExt = canUseShmExt;
1049 *shmPixmaps = canUseShmExtPixmaps;
1050 }
1051 AWT_UNLOCK();
1052 }
1053 #endif /* MITSHM */
1054
1055 /*
1056 * Class: sun_awt_X11GraphicsEnvironment
1057 * Method: checkShmExt
1058 * Signature: ()I
1059 */
1060 JNIEXPORT jint JNICALL
1061 Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv *env, jobject this)
1062 {
1063
1064 int shmExt = NOEXT_MITSHM, shmPixmaps;
1065 #ifdef MITSHM
1066 TryInitMITShm(env, &shmExt, &shmPixmaps);
1067 #endif
1068 return shmExt;
1069 }
1070
1071 /*
1072 * Class: sun_awt_X11GraphicsEnvironment
1073 * Method: getDisplayString
1074 * Signature: ()Ljava/lang/String
1075 */
1076 JNIEXPORT jstring JNICALL
1077 Java_sun_awt_X11GraphicsEnvironment_getDisplayString
1078 (JNIEnv *env, jobject this)
1079 {
1080 #ifdef HEADLESS
1081 return (jstring)NULL;
1082 #else
1083 return (*env)->NewStringUTF(env, DisplayString(awt_display));
1084 #endif /* HEADLESS */
1085 }
1086
1087
1088 /*
1089 * Class: sun_awt_X11GraphicsDevice
1090 * Method: getNumConfigs
1091 * Signature: ()I
1092 */
1093 JNIEXPORT jint JNICALL
1094 Java_sun_awt_X11GraphicsDevice_getNumConfigs(
1095 JNIEnv *env, jobject this, jint screen)
1096 {
1097 #ifdef HEADLESS
1098 return (jint)0;
1099 #else
1100 ensureConfigsInited(env, screen);
1101 return x11Screens[screen].numConfigs;
1102 #endif /* !HEADLESS */
1103 }
1104
1105 /*
1106 * Class: sun_awt_X11GraphicsDevice
1107 * Method: getConfigVisualId
1108 * Signature: (I)I
1109 */
1110 JNIEXPORT jint JNICALL
1111 Java_sun_awt_X11GraphicsDevice_getConfigVisualId(
1112 JNIEnv *env, jobject this, jint index, jint screen)
1113 {
1114 #ifdef HEADLESS
1115 return (jint)0;
1116 #else
1117 int visNum;
1118
1119 ensureConfigsInited(env, screen);
1120 if (index == 0) {
1121 return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.visualid);
1122 } else {
1123 return ((jint)x11Screens[screen].configs[index]->awt_visInfo.visualid);
1124 }
1125 #endif /* !HEADLESS */
1126 }
1127
1128 /*
1129 * Class: sun_awt_X11GraphicsDevice
1130 * Method: getConfigDepth
1131 * Signature: (I)I
1132 */
1133 JNIEXPORT jint JNICALL
1134 Java_sun_awt_X11GraphicsDevice_getConfigDepth(
1135 JNIEnv *env, jobject this, jint index, jint screen)
1136 {
1137 #ifdef HEADLESS
1138 return (jint)0;
1139 #else
1140 int visNum;
1141
1142 ensureConfigsInited(env, screen);
1143 if (index == 0) {
1144 return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.depth);
1145 } else {
1146 return ((jint)x11Screens[screen].configs[index]->awt_visInfo.depth);
1147 }
1148 #endif /* !HEADLESS */
1149 }
1150
1151 /*
1152 * Class: sun_awt_X11GraphicsDevice
1153 * Method: getConfigColormap
1154 * Signature: (I)I
1155 */
1156 JNIEXPORT jint JNICALL
1157 Java_sun_awt_X11GraphicsDevice_getConfigColormap(
1158 JNIEnv *env, jobject this, jint index, jint screen)
1159 {
1160 #ifdef HEADLESS
1161 return (jint)0;
1162 #else
1163 int visNum;
1164
1165 ensureConfigsInited(env, screen);
1166 if (index == 0) {
1167 return ((jint)x11Screens[screen].defaultConfig->awt_cmap);
1168 } else {
1169 return ((jint)x11Screens[screen].configs[index]->awt_cmap);
1170 }
1171 #endif /* !HEADLESS */
1172 }
1173
1174 /*
1175 * Class: sun_awt_X11GraphicsDevice
1176 * Method: resetNativeData
1177 * Signature: (I)V
1178 */
1179 JNIEXPORT void JNICALL
1180 Java_sun_awt_X11GraphicsDevice_resetNativeData
1181 (JNIEnv *env, jclass x11gd, jint screen)
1182 {
1183 #ifndef HEADLESS
1184 /*
1185 * Reset references to the various configs; the actual native config data
1186 * will be free'd later by the Disposer mechanism when the Java-level
1187 * X11GraphicsConfig objects go away. By setting these values to NULL,
1188 * we ensure that they will be reinitialized as necessary (for example,
1189 * see the getNumConfigs() method).
1190 */
1191 if (x11Screens[screen].configs) {
1192 free(x11Screens[screen].configs);
1193 x11Screens[screen].configs = NULL;
1194 }
1195 x11Screens[screen].defaultConfig = NULL;
1196 x11Screens[screen].numConfigs = 0;
1197 #endif /* !HEADLESS */
1198 }
1199
1200 /*
1201 * Class: sun_awt_X11GraphicsConfig
1202 * Method: dispose
1203 * Signature: (J)V
1204 */
1205 JNIEXPORT void JNICALL
1206 Java_sun_awt_X11GraphicsConfig_dispose
1207 (JNIEnv *env, jclass x11gc, jlong configData)
1208 {
1209 #ifndef HEADLESS
1210 AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)
1211 jlong_to_ptr(configData);
1212
1213 if (aData == NULL) {
1214 return;
1215 }
1216
1217 AWT_LOCK();
1218 if (aData->awt_cmap) {
1219 XFreeColormap(awt_display, aData->awt_cmap);
1220 }
1221 if (aData->awtImage) {
1222 free(aData->awtImage);
1223 }
1224 if (aData->monoImage) {
1225 XFree(aData->monoImage);
1226 }
1227 if (aData->monoPixmap) {
1228 XFreePixmap(awt_display, aData->monoPixmap);
1229 }
1230 if (aData->monoPixmapGC) {
1231 XFreeGC(awt_display, aData->monoPixmapGC);
1232 }
1233 if (aData->color_data) {
1234 free(aData->color_data);
1235 }
1236 AWT_UNLOCK();
1237
1238 if (aData->glxInfo) {
1239 /*
1240 * The native GLXGraphicsConfig data needs to be disposed separately
1241 * on the OGL queue flushing thread (should not be called while
1242 * the AWT lock is held).
1243 */
1244 JNU_CallStaticMethodByName(env, NULL,
1245 "sun/java2d/opengl/OGLRenderQueue",
1246 "disposeGraphicsConfig", "(J)V",
1247 ptr_to_jlong(aData->glxInfo));
1248 }
1249
1250 free(aData);
1251 #endif /* !HEADLESS */
1252 }
1253
1254 /*
1255 * Class: sun_awt_X11GraphicsConfig
1256 * Method: getXResolution
1257 * Signature: ()I
1258 */
1259 JNIEXPORT jdouble JNICALL
1260 Java_sun_awt_X11GraphicsConfig_getXResolution(
1261 JNIEnv *env, jobject this, jint screen)
1262 {
1263 #ifdef HEADLESS
1264 return (jdouble)0;
1265 #else
1266 return ((DisplayWidth(awt_display, screen) * 25.4) /
1267 DisplayWidthMM(awt_display, screen));
1268 #endif /* !HEADLESS */
1269 }
1270
1271 /*
1272 * Class: sun_awt_X11GraphicsConfig
1273 * Method: getYResolution
1274 * Signature: ()I
1275 */
1276 JNIEXPORT jdouble JNICALL
1277 Java_sun_awt_X11GraphicsConfig_getYResolution(
1278 JNIEnv *env, jobject this, jint screen)
1279 {
1280 #ifdef HEADLESS
1281 return (jdouble)0;
1282 #else
1283 return ((DisplayHeight(awt_display, screen) * 25.4) /
1284 DisplayHeightMM(awt_display, screen));
1285 #endif /* !HEADLESS */
1286 }
1287
1288
1289 /*
1290 * Class: sun_awt_X11GraphicsConfig
1291 * Method: getNumColors
1292 * Signature: ()I
1293 */
1294 JNIEXPORT jint JNICALL
1295 Java_sun_awt_X11GraphicsConfig_getNumColors(
1296 JNIEnv *env, jobject this)
1297 {
1298 #ifdef HEADLESS
1299 return (jint)0;
1300 #else
1301 AwtGraphicsConfigData *adata;
1302
1303 adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,
1304 x11GraphicsConfigIDs.aData);
1305
1306 return adata->awt_num_colors;
1307 #endif /* !HEADLESS */
1308 }
1309
1310 /*
1311 * Class: sun_awt_X11GraphicsConfig
1312 * Method: init
1313 * Signature: (I)V
1314 */
1315 JNIEXPORT void JNICALL
1316 Java_sun_awt_X11GraphicsConfig_init(
1317 JNIEnv *env, jobject this, jint visualNum, jint screen)
1318 {
1319 #ifndef HEADLESS
1320 AwtGraphicsConfigData *adata = NULL;
1321 AwtScreenData asd = x11Screens[screen];
1322 int i, n;
1323 int depth;
1324 XImage * tempImage;
1325
1326 /* If haven't gotten all of the configs yet, do it now. */
1327 if (asd.numConfigs == 0) {
1328 getAllConfigs (env, screen, &asd);
1329 }
1330
1331 /* Check the graphicsConfig for this visual */
1332 for (i = 0; i < asd.numConfigs; i++) {
1333 AwtGraphicsConfigDataPtr agcPtr = asd.configs[i];
1334 if ((jint)agcPtr->awt_visInfo.visualid == visualNum) {
1335 adata = agcPtr;
1336 break;
1337 }
1338 }
1339
1340 /* If didn't find the visual, throw an exception... */
1341 if (adata == (AwtGraphicsConfigData *) NULL) {
1342 JNU_ThrowIllegalArgumentException(env, "Unknown Visual Specified");
1343 return;
1344 }
1345
1346 /* adata->awt_cmap initialization has been deferred to
1347 * makeColorModel call
1348 */
1349
1350 JNU_SetLongFieldFromPtr(env, this, x11GraphicsConfigIDs.aData, adata);
1351
1352 depth = adata->awt_visInfo.depth;
1353 tempImage = XCreateImage(awt_display,
1354 adata->awt_visInfo.visual,
1355 depth, ZPixmap, 0, NULL, 1, 1, 32, 0);
1356 adata->pixelStride = (tempImage->bits_per_pixel + 7) / 8;
1357 (*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel,
1358 (jint)tempImage->bits_per_pixel);
1359 XDestroyImage(tempImage);
1360 #endif /* !HEADLESS */
1361 }
1362
1363
1364
1365 /*
1366 * Class: sun_awt_X11GraphicsConfig
1367 * Method: makeColorModel
1368 * Signature: ()Ljava/awt/image/ColorModel
1369 */
1370 JNIEXPORT jobject JNICALL
1371 Java_sun_awt_X11GraphicsConfig_makeColorModel(
1372 JNIEnv *env, jobject this)
1373 {
1374 #ifdef HEADLESS
1375 return NULL;
1376 #else
1377 AwtGraphicsConfigData *adata;
1378 jobject colorModel;
1379
1380 /*
1381 * If awt is not locked yet, return null since the toolkit is not
1382 * initialized yet.
1383 */
1384 if (!awtLockInited) {
1385 return NULL;
1386 }
1387
1388 AWT_LOCK ();
1389
1390 adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,
1391 x11GraphicsConfigIDs.aData);
1392
1393 /* If colormap entry of adata is NULL, need to create it now */
1394 if (adata->awt_cmap == (Colormap) NULL) {
1395 awtJNI_CreateColorData (env, adata, 1);
1396 }
1397
1398 /* Make Color Model object for this GraphicsConfiguration */
1399 colorModel = awtJNI_GetColorModel (env, adata);
1400
1401 AWT_UNLOCK ();
1402
1403 return colorModel;
1404 #endif /* !HEADLESS */
1405 }
1406
1407
1408 /*
1409 * Class: sun_awt_X11GraphicsConfig
1410 * Method: getBounds
1411 * Signature: ()Ljava/awt/Rectangle
1412 */
1413 JNIEXPORT jobject JNICALL
1414 Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv *env, jobject this, jint screen)
1415 {
1416 #ifdef HEADLESS
1417 return NULL;
1418 #else
1419 jclass clazz;
1420 jmethodID mid;
1421 jobject bounds = NULL;
1422 AwtGraphicsConfigDataPtr adata;
1423
1424 adata = (AwtGraphicsConfigDataPtr)
1425 JNU_GetLongFieldAsPtr(env, this, x11GraphicsConfigIDs.aData);
1426
1427 clazz = (*env)->FindClass(env, "java/awt/Rectangle");
1428 mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");
1429 if (mid != NULL) {
1430 if (usingXinerama) {
1431 bounds = (*env)->NewObject(env, clazz, mid, fbrects[screen].x,
1432 fbrects[screen].y,
1433 fbrects[screen].width,
1434 fbrects[screen].height);
1435 }
1436 else {
1437 bounds = (*env)->NewObject(env, clazz, mid, 0, 0,
1438 DisplayWidth(awt_display,
1439 adata->awt_visInfo.screen),
1440 DisplayHeight(awt_display,
1441 adata->awt_visInfo.screen));
1442 }
1443
1444 if ((*env)->ExceptionOccurred(env)) {
1445 return NULL;
1446 }
1447 }
1448 return bounds;
1449 #endif /* !HEADLESS */
1450 }
1451
1452 /*
1453 * Class: sun_awt_X11GraphicsConfig
1454 * Method: createBackBuffer
1455 * Signature: (JI)J
1456 */
1457 JNIEXPORT jlong JNICALL
1458 Java_sun_awt_X11GraphicsConfig_createBackBuffer
1459 (JNIEnv *env, jobject this, jlong window, jint swapAction)
1460 {
1461 int32_t v1, v2;
1462 XdbeBackBuffer ret = (unsigned long) 0;
1463 Window w = (Window)window;
1464 AWT_LOCK();
1465 if (!XdbeQueryExtension(awt_display, &v1, &v2)) {
1466 JNU_ThrowByName(env, "java/lang/Exception",
1467 "Could not query double-buffer extension");
1468 AWT_UNLOCK();
1469 return (jlong)0;
1470 }
1471 ret = XdbeAllocateBackBufferName(awt_display, w,
1472 (XdbeSwapAction)swapAction);
1473 AWT_FLUSH_UNLOCK();
1474 return (jlong)ret;
1475 }
1476
1477 /*
1478 * Class: sun_awt_X11GraphicsConfig
1479 * Method: destroyBackBuffer
1480 * Signature: (J)V
1481 */
1482 JNIEXPORT void JNICALL
1483 Java_sun_awt_X11GraphicsConfig_destroyBackBuffer
1484 (JNIEnv *env, jobject this, jlong backBuffer)
1485 {
1486 AWT_LOCK();
1487 XdbeDeallocateBackBufferName(awt_display, (XdbeBackBuffer)backBuffer);
1488 AWT_FLUSH_UNLOCK();
1489 }
1490
1491 /*
1492 * Class: sun_awt_X11GraphicsConfig
1493 * Method: swapBuffers
1494 * Signature: (JI)V
1495 */
1496 JNIEXPORT void JNICALL
1497 Java_sun_awt_X11GraphicsConfig_swapBuffers
1498 (JNIEnv *env, jobject this,
1499 jlong window, jint swapAction)
1500 {
1501 XdbeSwapInfo swapInfo;
1502
1503 AWT_LOCK();
1504
1505 XdbeBeginIdiom(awt_display);
1506 swapInfo.swap_window = (Window)window;
1507 swapInfo.swap_action = (XdbeSwapAction)swapAction;
1508 if (!XdbeSwapBuffers(awt_display, &swapInfo, 1)) {
1509 JNU_ThrowInternalError(env, "Could not swap buffers");
1510 }
1511 XdbeEndIdiom(awt_display);
1512
1513 AWT_FLUSH_UNLOCK();
1514 }
1515
1516 /*
1517 * Class: sun_awt_X11GraphicsConfig
1518 * Method: isTranslucencyCapable
1519 * Signature: (J)V
1520 */
1521 JNIEXPORT jboolean JNICALL
1522 Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable
1523 (JNIEnv *env, jobject this, jlong configData)
1524 {
1525 #ifdef HEADLESS
1526 return JNI_FALSE;
1527 #else
1528 AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData);
1529 if (aData == NULL) {
1530 return JNI_FALSE;
1531 }
1532 return (jboolean)aData->isTranslucencySupported;
1533 #endif
1534 }
1535
1536 /*
1537 * Class: sun_awt_X11GraphicsDevice
1538 * Method: isDBESupported
1539 * Signature: ()Z
1540 */
1541 JNIEXPORT jboolean JNICALL
1542 Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this)
1543 {
1544 #ifdef HEADLESS
1545 return JNI_FALSE;
1546 #else
1547 int opcode = 0, firstEvent = 0, firstError = 0;
1548 jboolean ret;
1549
1550 AWT_LOCK();
1551 ret = (jboolean)XQueryExtension(awt_display, "DOUBLE-BUFFER",
1552 &opcode, &firstEvent, &firstError);
1553 AWT_FLUSH_UNLOCK();
1554 return ret;
1555 #endif /* !HEADLESS */
1556 }
1557
1558 /*
1559 * Class: sun_awt_X11GraphicsDevice
1560 * Method: getDoubleBufferVisuals
1561 * Signature: (I)V
1562 */
1563 JNIEXPORT void JNICALL
1564 Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env,
1565 jobject this, jint screen)
1566 {
1567 #ifndef HEADLESS
1568 jclass clazz;
1569 jmethodID midAddVisual;
1570 Window rootWindow;
1571 int i, n = 1;
1572 XdbeScreenVisualInfo* visScreenInfo;
1573 int xinawareScreen;
1574
1575 if (usingXinerama) {
1576 xinawareScreen = 0;
1577 }
1578 else {
1579 xinawareScreen = screen;
1580 }
1581
1582 clazz = (*env)->GetObjectClass(env, this);
1583 midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual",
1584 "(I)V");
1585
1586 AWT_LOCK();
1587 rootWindow = RootWindow(awt_display, xinawareScreen);
1588 visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n);
1589 if (visScreenInfo == NULL) {
1590 JNU_ThrowInternalError(env, "Could not get visual info");
1591 AWT_UNLOCK();
1592 return;
1593 }
1594 AWT_FLUSH_UNLOCK();
1595 for (i = 0; i < visScreenInfo->count; i++) {
1596 XdbeVisualInfo* visInfo = visScreenInfo->visinfo;
1597 (*env)->CallVoidMethod(env, this, midAddVisual, (visInfo[i]).visual);
1598 }
1599 #endif /* !HEADLESS */
1600 }
1601
1602 /*
1603 * Class: sun_awt_X11GraphicsEnvironment
1604 * Method: pRunningXinerama
1605 * Signature: ()Z
1606 */
1607 JNIEXPORT jboolean JNICALL
1608 Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env,
1609 jobject this)
1610 {
1611 #ifdef HEADLESS
1612 return false;
1613 #else
1614 return usingXinerama;
1615 #endif /* HEADLESS */
1616 }
1617
1618 /*
1619 * Can return NULL.
1620 *
1621 * Class: sun_awt_X11GraphicsEnvironment
1622 * Method: getXineramaCenterPoint
1623 * Signature: ()Ljava/awt/Point
1624 */
1625 JNIEXPORT jobject JNICALL
1626 Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env,
1627 jobject this)
1628 {
1629 jobject point = NULL;
1630 #ifndef HEADLESS /* return NULL in HEADLESS, Linux */
1631 #ifndef __linux__
1632 int x,y;
1633
1634 AWT_LOCK();
1635 DASSERT(usingXinerama);
1636 if (XineramaSolarisCenterFunc != NULL) {
1637 (XineramaSolarisCenterFunc)(awt_display, 0, &x, &y);
1638 point = JNU_NewObjectByName(env, "java/awt/Point","(II)V", x, y);
1639 DASSERT(point);
1640 } else {
1641 DTRACE_PRINTLN("unable to call XineramaSolarisCenterFunc: symbol is null");
1642 }
1643 AWT_FLUSH_UNLOCK();
1644 #endif /* __linux __ */
1645 #endif /* HEADLESS */
1646 return point;
1647 }
1648
1649
1650 /**
1651 * Begin DisplayMode/FullScreen support
1652 */
1653
1654 #ifndef HEADLESS
1655
1656 #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI
1657
1658 typedef Status
1659 (*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp);
1660 typedef XRRScreenConfiguration*
1661 (*XRRGetScreenInfoType)(Display *dpy, Drawable root);
1662 typedef void
1663 (*XRRFreeScreenConfigInfoType)(XRRScreenConfiguration *config);
1664 typedef short*
1665 (*XRRConfigRatesType)(XRRScreenConfiguration *config,
1666 int sizeID, int *nrates);
1667 typedef short
1668 (*XRRConfigCurrentRateType)(XRRScreenConfiguration *config);
1669 typedef XRRScreenSize*
1670 (*XRRConfigSizesType)(XRRScreenConfiguration *config,
1671 int *nsizes);
1672 typedef SizeID
1673 (*XRRConfigCurrentConfigurationType)(XRRScreenConfiguration *config,
1674 Rotation *rotation);
1675 typedef Status
1676 (*XRRSetScreenConfigAndRateType)(Display *dpy,
1677 XRRScreenConfiguration *config,
1678 Drawable draw,
1679 int size_index,
1680 Rotation rotation,
1681 short rate,
1682 Time timestamp);
1683
1684 static XRRQueryVersionType awt_XRRQueryVersion;
1685 static XRRGetScreenInfoType awt_XRRGetScreenInfo;
1686 static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;
1687 static XRRConfigRatesType awt_XRRConfigRates;
1688 static XRRConfigCurrentRateType awt_XRRConfigCurrentRate;
1689 static XRRConfigSizesType awt_XRRConfigSizes;
1690 static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration;
1691 static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate;
1692
1693 #define LOAD_XRANDR_FUNC(f) \
1694 do { \
1695 awt_##f = (f##Type)dlsym(pLibRandR, #f); \
1696 if (awt_##f == NULL) { \
1697 J2dRlsTraceLn1(J2D_TRACE_ERROR, \
1698 "X11GD_InitXrandrFuncs: Could not load %s", #f); \
1699 dlclose(pLibRandR); \
1700 return JNI_FALSE; \
1701 } \
1702 } while (0)
1703
1704 static jboolean
1705 X11GD_InitXrandrFuncs(JNIEnv *env)
1706 {
1707 int rr_maj_ver = 0, rr_min_ver = 0;
1708
1709 void *pLibRandR = dlopen("libXrandr.so.2", RTLD_LAZY | RTLD_LOCAL);
1710 if (pLibRandR == NULL) {
1711 J2dRlsTraceLn(J2D_TRACE_ERROR,
1712 "X11GD_InitXrandrFuncs: Could not open libXrandr.so.2");
1713 return JNI_FALSE;
1714 }
1715
1716 LOAD_XRANDR_FUNC(XRRQueryVersion);
1717
1718 if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) {
1719 J2dRlsTraceLn(J2D_TRACE_ERROR,
1720 "X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status");
1721 dlclose(pLibRandR);
1722 return JNI_FALSE;
1723 }
1724
1725 if (usingXinerama) {
1726 /*
1727 * We can proceed as long as this is RANDR 1.2 or above.
1728 * As of Xorg server 1.3 onwards the Xinerama backend may actually be
1729 * a fake one provided by RANDR itself. See Java bug 6636469 for info.
1730 */
1731 if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) {
1732 J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
1733 "Xinerama is active and Xrandr version is %d.%d",
1734 rr_maj_ver, rr_min_ver);
1735 dlclose(pLibRandR);
1736 return JNI_FALSE;
1737 }
1738
1739 /*
1740 * REMIND: Fullscreen mode doesn't work quite right with multi-monitor
1741 * setups and RANDR 1.2. So for now we also require a single screen.
1742 */
1743 if (awt_numScreens > 1 ) {
1744 J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
1745 "Multiple screens in use");
1746 dlclose(pLibRandR);
1747 return JNI_FALSE;
1748 }
1749 }
1750
1751 LOAD_XRANDR_FUNC(XRRGetScreenInfo);
1752 LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo);
1753 LOAD_XRANDR_FUNC(XRRConfigRates);
1754 LOAD_XRANDR_FUNC(XRRConfigCurrentRate);
1755 LOAD_XRANDR_FUNC(XRRConfigSizes);
1756 LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration);
1757 LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate);
1758
1759 return JNI_TRUE;
1760 }
1761
1762 static jobject
1763 X11GD_CreateDisplayMode(JNIEnv *env, jint width, jint height,
1764 jint bitDepth, jint refreshRate)
1765 {
1766 jclass displayModeClass;
1767 jmethodID cid;
1768
1769 displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode");
1770 if (JNU_IsNull(env, displayModeClass)) {
1771 JNU_ThrowInternalError(env,
1772 "Could not get display mode class");
1773 return NULL;
1774 }
1775
1776 cid = (*env)->GetMethodID(env, displayModeClass, "<init>", "(IIII)V");
1777 if (cid == NULL) {
1778 JNU_ThrowInternalError(env,
1779 "Could not get display mode constructor");
1780 return NULL;
1781 }
1782
1783 return (*env)->NewObject(env, displayModeClass, cid,
1784 width, height, bitDepth, refreshRate);
1785 }
1786
1787 static void
1788 X11GD_AddDisplayMode(JNIEnv *env, jobject arrayList,
1789 jint width, jint height,
1790 jint bitDepth, jint refreshRate)
1791 {
1792 jobject displayMode = X11GD_CreateDisplayMode(env, width, height,
1793 bitDepth, refreshRate);
1794 if (!JNU_IsNull(env, displayMode)) {
1795 jclass arrayListClass;
1796 jmethodID mid;
1797 arrayListClass = (*env)->GetObjectClass(env, arrayList);
1798 if (JNU_IsNull(env, arrayListClass)) {
1799 JNU_ThrowInternalError(env,
1800 "Could not get class java.util.ArrayList");
1801 return;
1802 }
1803 mid = (*env)->GetMethodID(env, arrayListClass, "add",
1804 "(Ljava/lang/Object;)Z");
1805 if (mid == NULL) {
1806 JNU_ThrowInternalError(env,
1807 "Could not get method java.util.ArrayList.add()");
1808 return;
1809 }
1810 (*env)->CallObjectMethod(env, arrayList, mid, displayMode);
1811 (*env)->DeleteLocalRef(env, displayMode);
1812 }
1813 }
1814
1815 static void
1816 X11GD_SetFullscreenMode(Window win, jboolean enabled)
1817 {
1818 Atom wmState = XInternAtom(awt_display, "_NET_WM_STATE", False);
1819 Atom wmStateFs = XInternAtom(awt_display,
1820 "_NET_WM_STATE_FULLSCREEN", False);
1821 Window root, parent, *children = NULL;
1822 unsigned int numchildren;
1823 XEvent event;
1824 Status status;
1825
1826 if (wmState == None || wmStateFs == None) {
1827 return;
1828 }
1829
1830 /*
1831 * Note: the Window passed to this method is typically the "content
1832 * window" of the top-level, but we need the actual shell window for
1833 * the purposes of constructing the XEvent. Therefore, we walk up the
1834 * window hierarchy here to find the true top-level.
1835 */
1836 do {
1837 if (!XQueryTree(awt_display, win,
1838 &root, &parent,
1839 &children, &numchildren))
1840 {
1841 return;
1842 }
1843
1844 if (children != NULL) {
1845 XFree(children);
1846 }
1847
1848 if (parent == root) {
1849 break;
1850 }
1851
1852 win = parent;
1853 } while (root != parent);
1854
1855 memset(&event, 0, sizeof(event));
1856 event.xclient.type = ClientMessage;
1857 event.xclient.message_type = wmState;
1858 event.xclient.display = awt_display;
1859 event.xclient.window = win;
1860 event.xclient.format = 32;
1861 event.xclient.data.l[0] = enabled ? 1 : 0; // 1==add, 0==remove
1862 event.xclient.data.l[1] = wmStateFs;
1863
1864 XSendEvent(awt_display, root, False,
1865 SubstructureRedirectMask | SubstructureNotifyMask,
1866 &event);
1867 XSync(awt_display, False);
1868 }
1869 #endif /* !HEADLESS */
1870
1871 /*
1872 * Class: sun_awt_X11GraphicsDevice
1873 * Method: initXrandrExtension
1874 * Signature: ()Z
1875 */
1876 JNIEXPORT jboolean JNICALL
1877 Java_sun_awt_X11GraphicsDevice_initXrandrExtension
1878 (JNIEnv *env, jclass x11gd)
1879 {
1880 #ifdef HEADLESS
1881 return JNI_FALSE;
1882 #else
1883 int opcode = 0, firstEvent = 0, firstError = 0;
1884 jboolean ret;
1885
1886 AWT_LOCK();
1887 ret = (jboolean)XQueryExtension(awt_display, "RANDR",
1888 &opcode, &firstEvent, &firstError);
1889 if (ret) {
1890 ret = X11GD_InitXrandrFuncs(env);
1891 }
1892 AWT_FLUSH_UNLOCK();
1893
1894 return ret;
1895 #endif /* HEADLESS */
1896 }
1897
1898 /*
1899 * Class: sun_awt_X11GraphicsDevice
1900 * Method: getCurrentDisplayMode
1901 * Signature: (I)Ljava/awt/DisplayMode;
1902 */
1903 JNIEXPORT jobject JNICALL
1904 Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode
1905 (JNIEnv* env, jclass x11gd, jint screen)
1906 {
1907 #ifdef HEADLESS
1908 return NULL;
1909 #else
1910 XRRScreenConfiguration *config;
1911 jobject displayMode = NULL;
1912
1913 AWT_LOCK();
1914
1915 config = awt_XRRGetScreenInfo(awt_display,
1916 RootWindow(awt_display, screen));
1917 if (config != NULL) {
1918 Rotation rotation;
1919 short curRate;
1920 SizeID curSizeIndex;
1921 XRRScreenSize *sizes;
1922 int nsizes;
1923
1924 curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation);
1925 sizes = awt_XRRConfigSizes(config, &nsizes);
1926 curRate = awt_XRRConfigCurrentRate(config);
1927
1928 if ((sizes != NULL) &&
1929 (curSizeIndex < nsizes) &&
1930 (curRate > 0))
1931 {
1932 XRRScreenSize curSize = sizes[curSizeIndex];
1933 displayMode = X11GD_CreateDisplayMode(env,
1934 curSize.width,
1935 curSize.height,
1936 BIT_DEPTH_MULTI,
1937 curRate);
1938 }
1939
1940 awt_XRRFreeScreenConfigInfo(config);
1941 }
1942
1943 AWT_FLUSH_UNLOCK();
1944
1945 return displayMode;
1946 #endif /* HEADLESS */
1947 }
1948
1949 /*
1950 * Class: sun_awt_X11GraphicsDevice
1951 * Method: enumDisplayModes
1952 * Signature: (ILjava/util/ArrayList;)V
1953 */
1954 JNIEXPORT void JNICALL
1955 Java_sun_awt_X11GraphicsDevice_enumDisplayModes
1956 (JNIEnv* env, jclass x11gd,
1957 jint screen, jobject arrayList)
1958 {
1959 #ifndef HEADLESS
1960 XRRScreenConfiguration *config;
1961
1962 AWT_LOCK();
1963
1964 config = awt_XRRGetScreenInfo(awt_display,
1965 RootWindow(awt_display, screen));
1966 if (config != NULL) {
1967 int nsizes, i, j;
1968 XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
1969
1970 if (sizes != NULL) {
1971 for (i = 0; i < nsizes; i++) {
1972 int nrates;
1973 XRRScreenSize size = sizes[i];
1974 short *rates = awt_XRRConfigRates(config, i, &nrates);
1975
1976 for (j = 0; j < nrates; j++) {
1977 X11GD_AddDisplayMode(env, arrayList,
1978 size.width,
1979 size.height,
1980 BIT_DEPTH_MULTI,
1981 rates[j]);
1982 }
1983 }
1984 }
1985
1986 awt_XRRFreeScreenConfigInfo(config);
1987 }
1988
1989 AWT_FLUSH_UNLOCK();
1990 #endif /* !HEADLESS */
1991 }
1992
1993 /*
1994 * Class: sun_awt_X11GraphicsDevice
1995 * Method: configDisplayMode
1996 * Signature: (IIII)V
1997 */
1998 JNIEXPORT void JNICALL
1999 Java_sun_awt_X11GraphicsDevice_configDisplayMode
2000 (JNIEnv* env, jclass x11gd,
2001 jint screen, jint width, jint height, jint refreshRate)
2002 {
2003 #ifndef HEADLESS
2004 jboolean success = JNI_FALSE;
2005 XRRScreenConfiguration *config;
2006 Drawable root;
2007
2008 AWT_LOCK();
2009
2010 root = RootWindow(awt_display, screen);
2011 config = awt_XRRGetScreenInfo(awt_display, root);
2012 if (config != NULL) {
2013 jboolean foundConfig = JNI_FALSE;
2014 int chosenSizeIndex = -1;
2015 short chosenRate = -1;
2016 int nsizes;
2017 XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
2018
2019 if (sizes != NULL) {
2020 int i, j;
2021
2022 /* find the size index that matches the requested dimensions */
2023 for (i = 0; i < nsizes; i++) {
2024 XRRScreenSize size = sizes[i];
2025
2026 if ((size.width == width) && (size.height == height)) {
2027 /* we've found our size index... */
2028 int nrates;
2029 short *rates = awt_XRRConfigRates(config, i, &nrates);
2030
2031 /* now find rate that matches requested refresh rate */
2032 for (j = 0; j < nrates; j++) {
2033 if (rates[j] == refreshRate) {
2034 /* we've found our rate; break out of the loop */
2035 chosenSizeIndex = i;
2036 chosenRate = rates[j];
2037 foundConfig = JNI_TRUE;
2038 break;
2039 }
2040 }
2041
2042 break;
2043 }
2044 }
2045 }
2046
2047 if (foundConfig) {
2048 Status status =
2049 awt_XRRSetScreenConfigAndRate(awt_display, config, root,
2050 chosenSizeIndex,
2051 RR_Rotate_0,
2052 chosenRate,
2053 CurrentTime);
2054
2055 /* issue XSync to ensure immediate mode change */
2056 XSync(awt_display, False);
2057
2058 if (status == RRSetConfigSuccess) {
2059 success = JNI_TRUE;
2060 }
2061 }
2062
2063 awt_XRRFreeScreenConfigInfo(config);
2064 }
2065
2066 AWT_FLUSH_UNLOCK();
2067
2068 if (!success) {
2069 JNU_ThrowInternalError(env, "Could not set display mode");
2070 }
2071 #endif /* !HEADLESS */
2072 }
2073
2074 /*
2075 * Class: sun_awt_X11GraphicsDevice
2076 * Method: enterFullScreenExclusive
2077 * Signature: (J)V
2078 */
2079 JNIEXPORT void JNICALL
2080 Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive
2081 (JNIEnv* env, jclass x11gd,
2082 jlong window)
2083 {
2084 #ifndef HEADLESS
2085 Window win = (Window)window;
2086
2087 AWT_LOCK();
2088 XSync(awt_display, False); /* ensures window is visible first */
2089 X11GD_SetFullscreenMode(win, JNI_TRUE);
2090 AWT_UNLOCK();
2091 #endif /* !HEADLESS */
2092 }
2093
2094 /*
2095 * Class: sun_awt_X11GraphicsDevice
2096 * Method: exitFullScreenExclusive
2097 * Signature: (J)V
2098 */
2099 JNIEXPORT void JNICALL
2100 Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive
2101 (JNIEnv* env, jclass x11gd,
2102 jlong window)
2103 {
2104 #ifndef HEADLESS
2105 Window win = (Window)window;
2106
2107 AWT_LOCK();
2108 X11GD_SetFullscreenMode(win, JNI_FALSE);
2109 AWT_UNLOCK();
2110 #endif /* !HEADLESS */
2111 }
2112
2113 /**
2114 * End DisplayMode/FullScreen support
2115 */