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 #if defined(__linux__) || defined(MACOSX)
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 #endif
141
142 Bool usingXinerama = False;
143 XRectangle fbrects[MAXFRAMEBUFFERS];
144
145 JNIEXPORT void JNICALL
146 Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls)
147 {
148 x11GraphicsConfigIDs.aData = NULL;
149 x11GraphicsConfigIDs.bitsPerPixel = NULL;
150
151 x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J");
152 CHECK_NULL(x11GraphicsConfigIDs.aData);
153 x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I");
154 CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel);
155
156 if (x11GraphicsConfigIDs.aData == NULL ||
157 x11GraphicsConfigIDs.bitsPerPixel == NULL) {
158
159 JNU_ThrowNoSuchFieldError(env, "Can't find a field");
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 #ifdef MACOSX
431 #define XRENDER_LIB "/usr/X11/lib/libXrender.dylib"
432 #else
433 #define XRENDER_LIB "libXrender.so"
434 #endif
435
436 if (xrenderLibHandle == NULL) {
437 xrenderLibHandle = dlopen(XRENDER_LIB,
438 RTLD_LAZY | RTLD_GLOBAL);
439 }
440
441 #ifndef __linux__ /* SOLARIS */
442 if (xrenderLibHandle == NULL) {
443 xrenderLibHandle = dlopen("/usr/lib/libXrender.so.1",
444 RTLD_LAZY | RTLD_GLOBAL);
445 }
446 #endif
447
448 if (xrenderLibHandle != NULL) {
449 xrenderFindVisualFormat =
450 (XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle,
451 "XRenderFindVisualFormat");
452 }
453 }
454
455 for (i = 0; i < nTrue; i++) {
456 if (XVisualIDFromVisual(pVITrue[i].visual) ==
457 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) ||
458 pVITrue[i].depth == 12) {
459 /* Skip the non-supported 12-bit TrueColor visual */
460 continue;
461 } else {
462 ind = nConfig++;
463 }
464 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
465 graphicsConfigs [ind]->awt_depth = pVITrue [i].depth;
466 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],
467 sizeof (XVisualInfo));
468 if (xrenderFindVisualFormat != NULL) {
469 XRenderPictFormat *format = xrenderFindVisualFormat (awt_display,
470 pVITrue [i].visual);
471 if (format &&
472 format->type == PictTypeDirect &&
473 format->direct.alphaMask)
474 {
475 graphicsConfigs [ind]->isTranslucencySupported = 1;
476 memcpy(&graphicsConfigs [ind]->renderPictFormat, format,
477 sizeof(*format));
478 }
479 }
480 }
481
482 if (xrenderLibHandle != NULL) {
483 dlclose(xrenderLibHandle);
484 xrenderLibHandle = NULL;
485 }
486
487 for (i = 0; i < n8p; i++) {
488 if (XVisualIDFromVisual(pVI8p[i].visual) ==
489 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
490 continue;
491 } else {
492 ind = nConfig++;
493 }
494 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
495 graphicsConfigs [ind]->awt_depth = pVI8p [i].depth;
496 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i],
497 sizeof (XVisualInfo));
498 }
565 if (n8p != 0)
566 XFree (pVI8p);
567 if (n12p != 0)
568 XFree (pVI12p);
569 if (n8s != 0)
570 XFree (pVI8s);
571 if (n8gs != 0)
572 XFree (pVI8gs);
573 if (n8sg != 0)
574 XFree (pVI8sg);
575 if (n1sg != 0)
576 XFree (pVI1sg);
577
578 screenDataPtr->numConfigs = nConfig;
579 screenDataPtr->configs = graphicsConfigs;
580
581 AWT_UNLOCK ();
582 }
583
584 #ifndef HEADLESS
585 #if defined(__linux__) || defined(MACOSX)
586 static void xinerama_init_linux()
587 {
588 void* libHandle = NULL;
589 int32_t locNumScr = 0;
590 XineramaScreenInfo *xinInfo;
591 char* XineramaQueryScreensName = "XineramaQueryScreens";
592 XineramaQueryScreensFunc* XineramaQueryScreens = NULL;
593
594 /* load library */
595 libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"),
596 RTLD_LAZY | RTLD_GLOBAL);
597 if (libHandle == NULL) {
598 libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL);
599 }
600 if (libHandle != NULL) {
601 XineramaQueryScreens = (XineramaQueryScreensFunc*)
602 dlsym(libHandle, XineramaQueryScreensName);
603
604 if (XineramaQueryScreens != NULL) {
605 DTRACE_PRINTLN("calling XineramaQueryScreens func on Linux");
606 xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
607 if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
608 int32_t idx;
609 DTRACE_PRINTLN("Enabling Xinerama support");
610 usingXinerama = True;
611 /* set global number of screens */
612 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
613 awt_numScreens = locNumScr;
614
615 /* stuff values into fbrects */
616 for (idx = 0; idx < awt_numScreens; idx++) {
617 DASSERT(xinInfo[idx].screen_number == idx);
618
619 fbrects[idx].width = xinInfo[idx].width;
620 fbrects[idx].height = xinInfo[idx].height;
621 fbrects[idx].x = xinInfo[idx].x_org;
622 fbrects[idx].y = xinInfo[idx].y_org;
623 }
624 } else {
625 DTRACE_PRINTLN("calling XineramaQueryScreens didn't work");
626 }
627 } else {
628 DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");
629 }
630 dlclose(libHandle);
631 } else {
632 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
633 }
634 }
635 #endif
636 #if !defined(__linux__) && !defined(MACOSX) /* Solaris */
637 static void xinerama_init_solaris()
638 {
639 void* libHandle = NULL;
640 unsigned char fbhints[MAXFRAMEBUFFERS];
641 int32_t locNumScr = 0;
642 /* load and run XineramaGetInfo */
643 char* XineramaGetInfoName = "XineramaGetInfo";
644 XineramaGetInfoFunc* XineramaSolarisFunc = NULL;
645
646 /* load library */
647 libHandle = dlopen(JNI_LIB_NAME("Xext"), RTLD_LAZY | RTLD_GLOBAL);
648 if (libHandle != NULL) {
649 XineramaSolarisFunc = (XineramaGetInfoFunc*)dlsym(libHandle, XineramaGetInfoName);
650 if (XineramaSolarisFunc != NULL) {
651 DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris");
652 if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0],
653 &fbhints[0], &locNumScr) != 0 &&
654 locNumScr > XScreenCount(awt_display))
655 {
656 DTRACE_PRINTLN("Enabling Xinerama support");
672 #endif
673
674 /*
675 * Checks if Xinerama is running and perform Xinerama-related
676 * platform dependent initialization.
677 */
678 static void xineramaInit(void) {
679 char* XinExtName = "XINERAMA";
680 int32_t major_opcode, first_event, first_error;
681 Bool gotXinExt = False;
682
683 gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,
684 &first_event, &first_error);
685
686 if (!gotXinExt) {
687 DTRACE_PRINTLN("Xinerama extension is not available");
688 return;
689 }
690
691 DTRACE_PRINTLN("Xinerama extension is available");
692 #if defined(__linux__) || defined(MACOSX)
693 xinerama_init_linux();
694 #else /* Solaris */
695 xinerama_init_solaris();
696 #endif /* __linux__ || MACOSX */
697 }
698 #endif /* HEADLESS */
699
700 Display *
701 awt_init_Display(JNIEnv *env, jobject this)
702 {
703 jclass klass;
704 Display *dpy;
705 char errmsg[128];
706 int i;
707 #ifdef NETSCAPE
708 sigset_t alarm_set, oldset;
709 #endif
710
711 if (awt_display) {
712 return awt_display;
713 }
714
715 #ifdef NETSCAPE
716 /* Disable interrupts during XtOpenDisplay to avoid bugs in unix os select
|
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 #if defined(__solaris__)
126 typedef Status XineramaGetInfoFunc(Display* display, int screen_number,
127 XRectangle* framebuffer_rects, unsigned char* framebuffer_hints,
128 int* num_framebuffers);
129 #else /* Linux, Mac, AIX */
130 typedef struct {
131 int screen_number;
132 short x_org;
133 short y_org;
134 short width;
135 short height;
136 } XineramaScreenInfo;
137
138 typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*);
139 #endif
140
141 Bool usingXinerama = False;
142 XRectangle fbrects[MAXFRAMEBUFFERS];
143
144 JNIEXPORT void JNICALL
145 Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls)
146 {
147 x11GraphicsConfigIDs.aData = NULL;
148 x11GraphicsConfigIDs.bitsPerPixel = NULL;
149
150 x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J");
151 CHECK_NULL(x11GraphicsConfigIDs.aData);
152 x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I");
153 CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel);
154
155 if (x11GraphicsConfigIDs.aData == NULL ||
156 x11GraphicsConfigIDs.bitsPerPixel == NULL) {
157
158 JNU_ThrowNoSuchFieldError(env, "Can't find a field");
407 AWT_UNLOCK();
408 return;
409 }
410
411 if (screenDataPtr->defaultConfig == NULL) {
412 /*
413 * After a display change event, the default config field will have
414 * been reset, so we need to recreate the default config here.
415 */
416 screenDataPtr->defaultConfig = makeDefaultConfig(env, screen);
417 }
418
419 defaultConfig = screenDataPtr->defaultConfig;
420 graphicsConfigs[0] = defaultConfig;
421 nConfig = 1; /* reserve index 0 for default config */
422
423 // Only use the RENDER extension if it is available on the X server
424 if (XQueryExtension(awt_display, "RENDER",
425 &major_opcode, &first_event, &first_error))
426 {
427 DTRACE_PRINTLN("RENDER extension available");
428 xrenderLibHandle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);
429
430 #ifdef MACOSX
431 #define XRENDER_LIB "/usr/X11/lib/libXrender.dylib"
432 #else
433 #define XRENDER_LIB "libXrender.so"
434 #endif
435
436 if (xrenderLibHandle == NULL) {
437 xrenderLibHandle = dlopen(XRENDER_LIB,
438 RTLD_LAZY | RTLD_GLOBAL);
439 }
440
441 #ifdef __solaris__
442 if (xrenderLibHandle == NULL) {
443 xrenderLibHandle = dlopen("/usr/lib/libXrender.so.1",
444 RTLD_LAZY | RTLD_GLOBAL);
445 }
446 #endif
447 #ifdef _AIX
448 if (xrenderLibHandle == NULL) {
449 xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",
450 RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
451 }
452 #endif
453 if (xrenderLibHandle != NULL) {
454 DTRACE_PRINTLN("Loaded libXrender");
455 xrenderFindVisualFormat =
456 (XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle,
457 "XRenderFindVisualFormat");
458 } else {
459 DTRACE_PRINTLN1("Can't load libXrender (%s)", dlerror());
460 }
461 } else {
462 DTRACE_PRINTLN("RENDER extension NOT available");
463 }
464
465 for (i = 0; i < nTrue; i++) {
466 if (XVisualIDFromVisual(pVITrue[i].visual) ==
467 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) ||
468 pVITrue[i].depth == 12) {
469 /* Skip the non-supported 12-bit TrueColor visual */
470 continue;
471 } else {
472 ind = nConfig++;
473 }
474 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
475 graphicsConfigs [ind]->awt_depth = pVITrue [i].depth;
476 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],
477 sizeof (XVisualInfo));
478 if (xrenderFindVisualFormat != NULL) {
479 XRenderPictFormat *format = xrenderFindVisualFormat (awt_display,
480 pVITrue [i].visual);
481 if (format &&
482 format->type == PictTypeDirect &&
483 format->direct.alphaMask)
484 {
485 DTRACE_PRINTLN1("GraphicsConfig[%d] supports Translucency", ind);
486 graphicsConfigs [ind]->isTranslucencySupported = 1;
487 memcpy(&graphicsConfigs [ind]->renderPictFormat, format,
488 sizeof(*format));
489 } else {
490 DTRACE_PRINTLN1(format ?
491 "GraphicsConfig[%d] has no Translucency support" :
492 "Error calling 'XRenderFindVisualFormat'", ind);
493 }
494 } else {
495 DTRACE_PRINTLN1("Can't find 'XRenderFindVisualFormat' in libXrender (%s)", dlerror());
496 }
497 }
498
499 if (xrenderLibHandle != NULL) {
500 dlclose(xrenderLibHandle);
501 xrenderLibHandle = NULL;
502 }
503
504 for (i = 0; i < n8p; i++) {
505 if (XVisualIDFromVisual(pVI8p[i].visual) ==
506 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
507 continue;
508 } else {
509 ind = nConfig++;
510 }
511 graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData);
512 graphicsConfigs [ind]->awt_depth = pVI8p [i].depth;
513 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i],
514 sizeof (XVisualInfo));
515 }
582 if (n8p != 0)
583 XFree (pVI8p);
584 if (n12p != 0)
585 XFree (pVI12p);
586 if (n8s != 0)
587 XFree (pVI8s);
588 if (n8gs != 0)
589 XFree (pVI8gs);
590 if (n8sg != 0)
591 XFree (pVI8sg);
592 if (n1sg != 0)
593 XFree (pVI1sg);
594
595 screenDataPtr->numConfigs = nConfig;
596 screenDataPtr->configs = graphicsConfigs;
597
598 AWT_UNLOCK ();
599 }
600
601 #ifndef HEADLESS
602 #if defined(__linux__) || defined(MACOSX) || defined(_AIX)
603 static void xinerama_init_linux()
604 {
605 void* libHandle = NULL;
606 int32_t locNumScr = 0;
607 XineramaScreenInfo *xinInfo;
608 char* XineramaQueryScreensName = "XineramaQueryScreens";
609 XineramaQueryScreensFunc* XineramaQueryScreens = NULL;
610
611 /* load library */
612 libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"),
613 RTLD_LAZY | RTLD_GLOBAL);
614 if (libHandle == NULL) {
615 #if defined(_AIX)
616 libHandle = dlopen("libXext.a(shr_64.o)", RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
617 #else
618 libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL);
619 #endif
620 }
621 if (libHandle != NULL) {
622 XineramaQueryScreens = (XineramaQueryScreensFunc*)
623 dlsym(libHandle, XineramaQueryScreensName);
624
625 if (XineramaQueryScreens != NULL) {
626 DTRACE_PRINTLN("calling XineramaQueryScreens func");
627 xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
628 if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
629 int32_t idx;
630 DTRACE_PRINTLN("Enabling Xinerama support");
631 usingXinerama = True;
632 /* set global number of screens */
633 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
634 awt_numScreens = locNumScr;
635
636 /* stuff values into fbrects */
637 for (idx = 0; idx < awt_numScreens; idx++) {
638 DASSERT(xinInfo[idx].screen_number == idx);
639
640 fbrects[idx].width = xinInfo[idx].width;
641 fbrects[idx].height = xinInfo[idx].height;
642 fbrects[idx].x = xinInfo[idx].x_org;
643 fbrects[idx].y = xinInfo[idx].y_org;
644 }
645 } else {
646 DTRACE_PRINTLN((xinInfo == NULL) ?
647 "calling XineramaQueryScreens didn't work" :
648 "XineramaQueryScreens <= XScreenCount"
649 );
650 }
651 } else {
652 DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");
653 }
654 dlclose(libHandle);
655 } else {
656 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
657 }
658 }
659 #endif
660 #if defined(__solaris__)
661 static void xinerama_init_solaris()
662 {
663 void* libHandle = NULL;
664 unsigned char fbhints[MAXFRAMEBUFFERS];
665 int32_t locNumScr = 0;
666 /* load and run XineramaGetInfo */
667 char* XineramaGetInfoName = "XineramaGetInfo";
668 XineramaGetInfoFunc* XineramaSolarisFunc = NULL;
669
670 /* load library */
671 libHandle = dlopen(JNI_LIB_NAME("Xext"), RTLD_LAZY | RTLD_GLOBAL);
672 if (libHandle != NULL) {
673 XineramaSolarisFunc = (XineramaGetInfoFunc*)dlsym(libHandle, XineramaGetInfoName);
674 if (XineramaSolarisFunc != NULL) {
675 DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris");
676 if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0],
677 &fbhints[0], &locNumScr) != 0 &&
678 locNumScr > XScreenCount(awt_display))
679 {
680 DTRACE_PRINTLN("Enabling Xinerama support");
696 #endif
697
698 /*
699 * Checks if Xinerama is running and perform Xinerama-related
700 * platform dependent initialization.
701 */
702 static void xineramaInit(void) {
703 char* XinExtName = "XINERAMA";
704 int32_t major_opcode, first_event, first_error;
705 Bool gotXinExt = False;
706
707 gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,
708 &first_event, &first_error);
709
710 if (!gotXinExt) {
711 DTRACE_PRINTLN("Xinerama extension is not available");
712 return;
713 }
714
715 DTRACE_PRINTLN("Xinerama extension is available");
716 #if defined(__solaris__)
717 xinerama_init_solaris();
718 #else /* Linux, Mac, AIX */
719 xinerama_init_linux();
720 #endif
721 }
722 #endif /* HEADLESS */
723
724 Display *
725 awt_init_Display(JNIEnv *env, jobject this)
726 {
727 jclass klass;
728 Display *dpy;
729 char errmsg[128];
730 int i;
731 #ifdef NETSCAPE
732 sigset_t alarm_set, oldset;
733 #endif
734
735 if (awt_display) {
736 return awt_display;
737 }
738
739 #ifdef NETSCAPE
740 /* Disable interrupts during XtOpenDisplay to avoid bugs in unix os select
|