[svn] Load openjdk/jdk7/b22 into jdk/trunk.
2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
29 #include <java_awt_DisplayMode.h>
30 #include <sun_awt_X11GraphicsEnvironment.h>
31 #include <sun_awt_X11GraphicsDevice.h>
32 #include <sun_awt_X11GraphicsConfig.h>
34 #include <X11/extensions/Xdbe.h>
35 #include <X11/XKBlib.h>
37 #include "GLXGraphicsConfig.h"
38 #endif /* !HEADLESS */
47 #include "awt_GraphicsEnv.h"
48 #include "awt_Window.h"
56 extern int awt_init_xt;
61 int awt_numScreens; /* Xinerama-aware number of screens */
63 AwtScreenDataPtr x11Screens;
66 * Set in initDisplay() to indicate whether we should attempt to initialize
67 * GLX for the default configuration.
69 static jboolean glxRequested = JNI_FALSE;
71 #endif /* !HEADLESS */
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;
87 /** Convenience macro for loading the lock-related method IDs. */
88 #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \
90 method_id = (*env)->GetStaticMethodID(env, klass, \
91 method_name, method_sig); \
92 if (method_id == NULL) return NULL; \
95 struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
96 struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs;
97 extern struct WindowIDs mWindowIDs;
98 extern struct MWindowPeerIDs mWindowPeerIDs;
101 int awtCreateX11Colormap(AwtGraphicsConfigDataPtr adata);
102 #endif /* HEADLESS */
104 static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig";
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
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
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
124 #define MAXFRAMEBUFFERS 16
132 } XineramaScreenInfo;
134 typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*);
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,
143 XineramaGetCenterHintFunc* XineramaSolarisCenterFunc = NULL;
146 Bool usingXinerama = False;
147 XRectangle fbrects[MAXFRAMEBUFFERS];
149 JNIEXPORT void JNICALL
150 Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls)
152 x11GraphicsConfigIDs.aData = NULL;
153 x11GraphicsConfigIDs.bitsPerPixel = NULL;
154 x11GraphicsConfigIDs.screen = NULL;
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;");
160 if (x11GraphicsConfigIDs.aData == NULL ||
161 x11GraphicsConfigIDs.bitsPerPixel == NULL ||
162 x11GraphicsConfigIDs.screen == NULL) {
164 JNU_ThrowNoSuchFieldError(env, "Can't find a field");
169 JNIEXPORT void JNICALL
170 Java_sun_awt_X11GraphicsDevice_initIDs (JNIEnv *env, jclass cls)
172 x11GraphicsDeviceIDs.screen = NULL;
173 x11GraphicsDeviceIDs.screen = (*env)->GetFieldID (env, cls, "screen", "I");
174 DASSERT(x11GraphicsDeviceIDs.screen);
183 xerror_handler(Display * disp, XErrorEvent * err)
188 char *ev = getenv("NOISY_AWT");
192 XGetErrorText(disp, err->error_code, msg, sizeof(msg));
193 jio_fprintf(stderr, "Xerror %s, XID %x, ser# %d\n", msg, err->resourceid, err->serial);
194 jio_snprintf(buf, sizeof(buf), "%d", err->request_code);
195 XGetErrorDatabaseText(disp, "XRequest", buf, "Unknown", msg, sizeof(msg));
196 jio_fprintf(stderr, "Major opcode %d (%s)\n", err->request_code, msg);
197 if (err->request_code > 128) {
198 jio_fprintf(stderr, "Minor opcode %d\n", err->minor_code);
201 /*SignalError(lockedee->lastpc, lockedee, "fp/ade/gui/GUIException", msg); */
203 if (strcasecmp(ev, "abort") == 0) {
204 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
206 (*env)->FatalError(env, "xerror_handler abort");
213 xioerror_handler(Display * disp)
216 if (errno == EPIPE) {
217 jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL));
219 /*SignalError(lockedee->lastpc, lockedee, "fp/ade/gui/GUIException", "I/O error"); */
224 static AwtGraphicsConfigDataPtr
225 findWithTemplate(XVisualInfo *vinfo,
229 XVisualInfo *visualList;
231 AwtGraphicsConfigDataPtr defaultConfig;
232 int visualsMatched, i;
234 visualList = XGetVisualInfo(awt_display,
235 mask, vinfo, &visualsMatched);
237 defaultConfig = ZALLOC(_AwtGraphicsConfigData);
238 for (i = 0; i < visualsMatched; i++) {
239 memcpy(&defaultConfig->awt_visInfo, &visualList[i], sizeof(XVisualInfo));
240 defaultConfig->awt_depth = visualList[i].depth;
242 /* we can't use awtJNI_CreateColorData here, because it'll pull,
243 SystemColor, which in turn will cause toolkit to be reinitialized */
244 if (awtCreateX11Colormap(defaultConfig)) {
245 /* Allocate white and black pixels for this visual */
246 color.flags = DoRed | DoGreen | DoBlue;
247 color.red = color.green = color.blue = 0x0000;
248 XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
249 x11Screens[visualList[i].screen].blackpixel = color.pixel;
250 color.flags = DoRed | DoGreen | DoBlue;
251 color.red = color.green = color.blue = 0xffff;
252 XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
253 x11Screens[visualList[i].screen].whitepixel = color.pixel;
256 return defaultConfig;
260 free((void *)defaultConfig);
265 /* default config is based on X11 screen. All Xinerama screens of that X11
266 screen will have the same default config */
267 /* Need more notes about which fields of the structure are based on the X
268 screen, and which are based on the Xinerama screen */
269 static AwtGraphicsConfigDataPtr
270 makeDefaultConfig(JNIEnv *env, int screen) {
272 AwtGraphicsConfigDataPtr defaultConfig;
273 int xinawareScreen = 0;
274 VisualID forcedVisualID, defaultVisualID;
275 char *forcedVisualStr;
279 xinawareScreen = usingXinerama ? 0 : screen;
281 XVisualIDFromVisual(DefaultVisual(awt_display, xinawareScreen));
283 memset(&vinfo, 0, sizeof(XVisualInfo));
284 vinfo.screen = xinawareScreen;
286 if ((forcedVisualStr = getenv("FORCEDEFVIS"))) {
287 mask = VisualIDMask | VisualScreenMask;
288 if (sscanf(forcedVisualStr, "%x", &forcedVisualID) > 0 &&
291 vinfo.visualid = forcedVisualID;
293 vinfo.visualid = defaultVisualID;
296 VisualID bestGLXVisualID;
298 (bestGLXVisualID = GLXGC_FindBestVisual(env, xinawareScreen)) > 0)
300 /* we've found the best visual for use with GLX, so use it */
301 vinfo.visualid = bestGLXVisualID;
302 mask = VisualIDMask | VisualScreenMask;
304 /* otherwise, continue looking for the best X11 visual */
306 vinfo.class = TrueColor;
307 mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
311 /* try the best, or forced visual */
312 defaultConfig = findWithTemplate(&vinfo, mask);
314 return defaultConfig;
317 /* try the default visual */
318 vinfo.visualid = defaultVisualID;
319 mask = VisualIDMask | VisualScreenMask;
320 defaultConfig = findWithTemplate(&vinfo, mask);
322 return defaultConfig;
325 /* try any TrueColor */
326 vinfo.class = TrueColor;
327 mask = VisualScreenMask | VisualClassMask;
328 defaultConfig = findWithTemplate(&vinfo, mask);
330 return defaultConfig;
333 /* try 8-bit PseudoColor */
335 vinfo.class = PseudoColor;
336 mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
337 defaultConfig = findWithTemplate(&vinfo, mask);
339 return defaultConfig;
344 mask = VisualDepthMask | VisualScreenMask;
345 defaultConfig = findWithTemplate(&vinfo, mask);
347 return defaultConfig;
350 /* we tried everything, give up */
351 JNU_ThrowInternalError(env, "Can't find supported visual");
352 XCloseDisplay(awt_display);
358 getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) {
361 int n8p=0, n12p=0, n8s=0, n8gs=0, n8sg=0, n1sg=0, nTrue=0;
363 XVisualInfo *pVI8p, *pVI12p, *pVI8s, *pVITrue, *pVI8gs,
364 *pVI8sg, *pVI1sg = NULL, viTmp;
365 AwtGraphicsConfigDataPtr *graphicsConfigs;
366 AwtGraphicsConfigDataPtr defaultConfig;
375 xinawareScreen = screen;
380 viTmp.screen = xinawareScreen;
383 viTmp.class = PseudoColor;
384 viTmp.colormap_size = 256;
385 pVI8p = XGetVisualInfo (awt_display,
386 VisualDepthMask | VisualClassMask |
387 VisualColormapSizeMask | VisualScreenMask,
391 viTmp.class = PseudoColor;
392 viTmp.colormap_size = 4096;
393 pVI12p = XGetVisualInfo (awt_display,
394 VisualDepthMask | VisualClassMask |
395 VisualColormapSizeMask | VisualScreenMask,
398 viTmp.class = TrueColor;
399 pVITrue = XGetVisualInfo (awt_display,
405 viTmp.class = StaticColor;
406 pVI8s = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask |
407 VisualScreenMask, &viTmp, &n8s);
410 viTmp.class = GrayScale;
411 viTmp.colormap_size = 256;
412 pVI8gs = XGetVisualInfo (awt_display,
413 VisualDepthMask | VisualClassMask |
414 VisualColormapSizeMask | VisualScreenMask,
417 viTmp.class = StaticGray;
418 viTmp.colormap_size = 256;
419 pVI8sg = XGetVisualInfo (awt_display,
420 VisualDepthMask | VisualClassMask |
421 VisualColormapSizeMask | VisualScreenMask,
424 /* REMIND.. remove when we have support for the color classes below */
425 /* viTmp.depth = 1; */
426 /* viTmp.class = StaticGray; */
427 /* pVI1sg = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask, */
430 nConfig = n8p + n12p + n8s + n8gs + n8sg + n1sg + nTrue + 1;
431 graphicsConfigs = (AwtGraphicsConfigDataPtr *)
432 calloc(nConfig, sizeof(AwtGraphicsConfigDataPtr));
433 if (graphicsConfigs == NULL) {
434 JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
440 if (screenDataPtr->defaultConfig == NULL) {
442 * After a display change event, the default config field will have
443 * been reset, so we need to recreate the default config here.
445 screenDataPtr->defaultConfig = makeDefaultConfig(env, screen);
448 defaultConfig = screenDataPtr->defaultConfig;
449 graphicsConfigs[0] = defaultConfig;
450 nConfig = 1; /* reserve index 0 for default config */
452 for (i = 0; i < nTrue; i++) {
453 if (XVisualIDFromVisual(pVITrue[i].visual) ==
454 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) ||
455 pVITrue[i].depth == 12) {
456 /* Skip the non-supported 12-bit TrueColor visual */
461 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
462 graphicsConfigs [ind]->awt_depth = pVITrue [i].depth;
463 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],
464 sizeof (XVisualInfo));
467 for (i = 0; i < n8p; i++) {
468 if (XVisualIDFromVisual(pVI8p[i].visual) ==
469 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
474 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
475 graphicsConfigs [ind]->awt_depth = pVI8p [i].depth;
476 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i],
477 sizeof (XVisualInfo));
480 for (i = 0; i < n12p; i++) {
481 if (XVisualIDFromVisual(pVI12p[i].visual) ==
482 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
487 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
488 graphicsConfigs [ind]->awt_depth = pVI12p [i].depth;
489 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI12p [i],
490 sizeof (XVisualInfo));
493 for (i = 0; i < n8s; i++) {
494 if (XVisualIDFromVisual(pVI8s[i].visual) ==
495 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
500 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
501 graphicsConfigs [ind]->awt_depth = pVI8s [i].depth;
502 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8s [i],
503 sizeof (XVisualInfo));
506 for (i = 0; i < n8gs; i++) {
507 if (XVisualIDFromVisual(pVI8gs[i].visual) ==
508 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
513 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
514 graphicsConfigs [ind]->awt_depth = pVI8gs [i].depth;
515 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8gs [i],
516 sizeof (XVisualInfo));
519 for (i = 0; i < n8sg; i++) {
520 if (XVisualIDFromVisual(pVI8sg[i].visual) ==
521 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
526 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
527 graphicsConfigs [ind]->awt_depth = pVI8sg [i].depth;
528 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8sg [i],
529 sizeof (XVisualInfo));
532 for (i = 0; i < n1sg; i++) {
533 if (XVisualIDFromVisual(pVI1sg[i].visual) ==
534 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
539 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
540 graphicsConfigs [ind]->awt_depth = pVI1sg [i].depth;
541 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI1sg [i],
542 sizeof (XVisualInfo));
558 screenDataPtr->numConfigs = nConfig;
559 screenDataPtr->configs = graphicsConfigs;
565 * Determing if this top-level has been moved onto another Xinerama screen.
566 * Called from awt_TopLevel.c
568 * ASSUME: wdata != null
571 void checkNewXineramaScreen(JNIEnv* env, jobject peer, struct FrameData* wdata,
572 int32_t newX, int32_t newY,
573 int32_t newWidth, int32_t newHeight) {
578 int largestAmtScr = 0;
583 if (!usingXinerama) { return; }
585 totAmt = newWidth * newHeight;
587 /* assert that peer implements WindowPeer */
588 DASSERT(JNU_IsInstanceOfByName(env, peer, "java/awt/peer/WindowPeer"));
590 DTRACE_PRINTLN4("checkNewXineramaScreen() x=%i y=%i w=%i h=%i\n",newX, newY, newWidth, newHeight);
592 /* decide which screen we're on
593 * if we're spanning, figure out which screen we're most on
595 for (i = 0; i < awt_numScreens; i++) {
596 if (INTERSECTS(newX, newX + newWidth, newY, newY + newHeight,
597 fbrects[i].x, fbrects[i].x + fbrects[i].width,
598 fbrects[i].y, fbrects[i].y + fbrects[i].height)) {
600 /* calc how much of window is on this screen */
601 horiz = MIN(newX + newWidth, fbrects[i].x + fbrects[i].width) -
602 MAX(newX, fbrects[i].x);
603 vert = MIN(newY + newHeight, fbrects[i].y + fbrects[i].height) -
604 MAX(newY, fbrects[i].y);
610 /* completely on this screen - done! */
614 if (amt > largestAmt) {
622 /* check if we're on a new screen */
623 if (largestAmtScr != wdata->screenNum) {
624 wdata->screenNum = largestAmtScr;
625 /* update peer, target Comp */
626 (*env)->CallVoidMethod(env, peer,
627 mWindowPeerIDs.draggedToScreenMID, largestAmtScr);
631 #endif /* HEADLESS */
635 static void xinerama_init_linux()
638 char* XineramaLibName= "libXinerama.so.1";
639 int32_t locNumScr = 0;
640 XineramaScreenInfo *xinInfo;
641 char* XineramaQueryScreensName = "XineramaQueryScreens";
642 XineramaQueryScreensFunc* XineramaQueryScreens = NULL;
645 libHandle = dlopen(XineramaLibName, RTLD_LAZY | RTLD_GLOBAL);
646 if (libHandle != 0) {
647 XineramaQueryScreens = (XineramaQueryScreensFunc*)
648 dlsym(libHandle, XineramaQueryScreensName);
650 if (XineramaQueryScreens != NULL) {
651 DTRACE_PRINTLN("calling XineramaQueryScreens func on Linux");
652 xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
653 if (xinInfo != NULL) {
655 DTRACE_PRINTLN("Enabling Xinerama support");
656 usingXinerama = True;
657 /* set global number of screens */
658 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
659 awt_numScreens = locNumScr;
661 /* stuff values into fbrects */
662 for (idx = 0; idx < awt_numScreens; idx++) {
663 DASSERT(xinInfo[idx].screen_number == idx);
665 fbrects[idx].width = xinInfo[idx].width;
666 fbrects[idx].height = xinInfo[idx].height;
667 fbrects[idx].x = xinInfo[idx].x_org;
668 fbrects[idx].y = xinInfo[idx].y_org;
671 DTRACE_PRINTLN("calling XineramaQueryScreens didn't work");
674 DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");
678 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
682 #ifndef __linux__ /* Solaris */
683 static void xinerama_init_solaris()
686 char* XineramaLibName= "libXext.so";
687 unsigned char fbhints[MAXFRAMEBUFFERS];
688 int32_t locNumScr = 0;
689 /* load and run XineramaGetInfo */
690 char* XineramaGetInfoName = "XineramaGetInfo";
691 char* XineramaGetCenterHintName = "XineramaGetCenterHint";
692 XineramaGetInfoFunc* XineramaSolarisFunc = NULL;
695 libHandle = dlopen(XineramaLibName, RTLD_LAZY | RTLD_GLOBAL);
696 if (libHandle != 0) {
697 XineramaSolarisFunc = (XineramaGetInfoFunc*)dlsym(libHandle, XineramaGetInfoName);
698 XineramaSolarisCenterFunc =
699 (XineramaGetCenterHintFunc*)dlsym(libHandle, XineramaGetCenterHintName);
701 if (XineramaSolarisFunc != NULL) {
702 DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris");
703 if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0],
704 &fbhints[0], &locNumScr) != 0)
706 DTRACE_PRINTLN("Enabling Xinerama support");
707 usingXinerama = True;
708 /* set global number of screens */
709 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
710 awt_numScreens = locNumScr;
712 DTRACE_PRINTLN("calling XineramaGetInfo didn't work");
715 DTRACE_PRINTLN("couldn't load XineramaGetInfo symbol");
719 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
725 * Checks if Xinerama is running and perform Xinerama-related
726 * platform dependent initialization.
728 static void xineramaInit(void) {
729 char* XinExtName = "XINERAMA";
730 int32_t major_opcode, first_event, first_error;
731 Bool gotXinExt = False;
733 gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,
734 &first_event, &first_error);