diff --git a/make/sun/xawt/mapfile-vers b/make/sun/xawt/mapfile-vers index 3aa1ca49fc6f9ecf3883088df8a923aa3fa849bb..dec924278082726e81279cc10388c5ffba376439 100644 --- a/make/sun/xawt/mapfile-vers +++ b/make/sun/xawt/mapfile-vers @@ -158,6 +158,7 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl; Java_sun_awt_X11_XRobotPeer_mouseWheelImpl; Java_sun_awt_X11_XRobotPeer_setup; + Java_sun_awt_X11_XRobotPeer__1dispose; Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl; Java_java_awt_Component_initIDs; Java_java_awt_Container_initIDs; diff --git a/src/share/classes/java/awt/Toolkit.java b/src/share/classes/java/awt/Toolkit.java index 85ee6db4a4316db9bb18bd727ef873b523ea25b0..105bc1bf3254e8303c6fc91aa65650d705e46304 100644 --- a/src/share/classes/java/awt/Toolkit.java +++ b/src/share/classes/java/awt/Toolkit.java @@ -1157,12 +1157,9 @@ public abstract class Toolkit { * takes JobAttributes and PageAttributes objects. This object * may be updated to reflect the user's job choices on exit. May * be null. - * * @return a PrintJob object, or null if the * user cancelled the print job. - * @throws NullPointerException if frame is null. This exception is - * always thrown when GraphicsEnvironment.isHeadless() returns - * true. + * @throws NullPointerException if frame is null * @throws SecurityException if this thread is not allowed to initiate a * print job request * @see java.awt.GraphicsEnvironment#isHeadless @@ -1201,12 +1198,9 @@ public abstract class Toolkit { * job. The attributes will be updated to reflect the user's * choices as outlined in the PageAttributes documentation. May be * null. - * * @return a PrintJob object, or null if the * user cancelled the print job. - * @throws NullPointerException if frame is null and either jobAttributes - * is null or jobAttributes.getDialog() returns - * JobAttributes.DialogType.NATIVE. + * @throws NullPointerException if frame is null * @throws IllegalArgumentException if pageAttributes specifies differing * cross feed and feed resolutions. Also if this thread has * access to the file system and jobAttributes specifies @@ -1218,9 +1212,6 @@ public abstract class Toolkit { * opportunity to select a file and proceed with printing. * The dialog will ensure that the selected output file * is valid before returning from this method. - *

- * This exception is always thrown when GraphicsEnvironment.isHeadless() - * returns true. * @throws SecurityException if this thread is not allowed to initiate a * print job request, or if jobAttributes specifies print to file, * and this thread is not allowed to access the file system @@ -1236,10 +1227,6 @@ public abstract class Toolkit { PageAttributes pageAttributes) { // Override to add printing support with new job/page control classes - if (GraphicsEnvironment.isHeadless()) { - throw new IllegalArgumentException(); - } - if (this != Toolkit.getDefaultToolkit()) { return Toolkit.getDefaultToolkit().getPrintJob(frame, jobtitle, jobAttributes, diff --git a/src/share/classes/sun/awt/HeadlessToolkit.java b/src/share/classes/sun/awt/HeadlessToolkit.java index e1df71630346b70958ac96b50e38c1ffab3239dd..8dc8a19c7e267f1f2ba9dde9594e08e0c2e66a58 100644 --- a/src/share/classes/sun/awt/HeadlessToolkit.java +++ b/src/share/classes/sun/awt/HeadlessToolkit.java @@ -320,8 +320,7 @@ public class HeadlessToolkit extends Toolkit // Should never happen throw new HeadlessException(); } - throw new IllegalArgumentException( - "PrintJob not supported in a headless environment"); + throw new NullPointerException("frame must not be null"); } public PrintJob getPrintJob(Frame frame, String doctitle, Properties props) @@ -330,8 +329,7 @@ public class HeadlessToolkit extends Toolkit // Should never happen throw new HeadlessException(); } - throw new IllegalArgumentException( - "PrintJob not supported in a headless environment"); + throw new NullPointerException("frame must not be null"); } /* diff --git a/src/solaris/classes/sun/awt/X11/XRobotPeer.java b/src/solaris/classes/sun/awt/X11/XRobotPeer.java index a6acd8eb5f58241958e601b14a5fd3710838b222..1463f283f0bd33b06551bf3d0ae687bd51a96803 100644 --- a/src/solaris/classes/sun/awt/X11/XRobotPeer.java +++ b/src/solaris/classes/sun/awt/X11/XRobotPeer.java @@ -48,7 +48,7 @@ class XRobotPeer implements RobotPeer { } public void dispose() { - // does nothing + _dispose(); } public void mouseMove(int x, int y) { @@ -88,6 +88,7 @@ class XRobotPeer implements RobotPeer { } private static native synchronized void setup(int numberOfButtons, int[] buttonDownMasks); + private static native synchronized void _dispose(); private static native synchronized void mouseMoveImpl(X11GraphicsConfig xgc, int x, int y); private static native synchronized void mousePressImpl(int buttons); diff --git a/src/solaris/classes/sun/awt/X11/XToolkit.java b/src/solaris/classes/sun/awt/X11/XToolkit.java index ad92d2e9c0016df894965d0f72b2c7a2907a3b61..8bde71a79747d5dc76d2b40926d67a72ffd79a5d 100644 --- a/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -1222,8 +1222,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable { public PrintJob getPrintJob(final Frame frame, final String doctitle, final Properties props) { - if (GraphicsEnvironment.isHeadless()) { - throw new IllegalArgumentException(); + if (frame == null) { + throw new NullPointerException("frame must not be null"); } PrintJob2D printJob = new PrintJob2D(frame, doctitle, props); @@ -1236,11 +1236,10 @@ public final class XToolkit extends UNIXToolkit implements Runnable { public PrintJob getPrintJob(final Frame frame, final String doctitle, final JobAttributes jobAttributes, - final PageAttributes pageAttributes) { - - - if (GraphicsEnvironment.isHeadless()) { - throw new IllegalArgumentException(); + final PageAttributes pageAttributes) + { + if (frame == null) { + throw new NullPointerException("frame must not be null"); } PrintJob2D printJob = new PrintJob2D(frame, doctitle, diff --git a/src/solaris/native/sun/awt/awt_Robot.c b/src/solaris/native/sun/awt/awt_Robot.c index c3384b2eb1a3a5461bac73c2cebd1f84c3105e39..38ad27863667f4e7fe49f8f702470dc36500f4ff 100644 --- a/src/solaris/native/sun/awt/awt_Robot.c +++ b/src/solaris/native/sun/awt/awt_Robot.c @@ -48,12 +48,28 @@ #ifdef __linux__ #include #endif +#include extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; static jint * masks; static jint num_buttons; +static unsigned int s_robotInstanceCounter = 0; + +static void* xcompositeLibHandle = NULL; +static Bool xcompositeExtAvailable = False; +static Bool xcompositeExtTested = False; + +typedef Status (*T_XCompositeQueryVersion)(Display *dpy, int *major_versionp, int *minor_versionp); +typedef Window (*T_XCompositeGetOverlayWindow)(Display *dpy, Window window); +typedef void (*T_XCompositeReleaseOverlayWindow)(Display *dpy, Window window); + +static T_XCompositeQueryVersion XCompositeQueryVersion = NULL; +static T_XCompositeGetOverlayWindow XCompositeGetOverlayWindow = NULL; +static T_XCompositeReleaseOverlayWindow XCompositeReleaseOverlayWindow = NULL; + + static int32_t isXTestAvailable() { int32_t major_opcode, first_event, first_error; int32_t event_basep, error_basep, majorp, minorp; @@ -194,8 +210,80 @@ Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButton } AWT_UNLOCK(); + + s_robotInstanceCounter++; } +JNIEXPORT void JNICALL +Java_sun_awt_X11_XRobotPeer__1dispose (JNIEnv * env, jclass cls) +{ + if (--s_robotInstanceCounter) { + return; + } + + // This is the last instance of the XRobotPeer being released + + if (xcompositeExtTested && xcompositeExtAvailable && xcompositeLibHandle) { + // The lib is loaded in IsXCompositeAvailable(). Unload under AWT_LOCK + // so that the shutdown function of the lib behaves correctly. + AWT_LOCK(); + dlclose(xcompositeLibHandle); + AWT_UNLOCK(); + } + + xcompositeExtTested = False; + xcompositeExtAvailable = False; + xcompositeLibHandle = NULL; +} + +/* + * Returns True only if XCOMPOSITE is of version 0.3 or higher. + * The functions that we need are available since that version. + * + * Must be invoked under AWT_LOCK. + * + * Leaves the library loaded if the version is correct. + */ +static Bool IsXCompositeAvailable() +{ + if (!xcompositeExtTested) { + int opcode, eventb, errorb; + + if (XQueryExtension(awt_display, "Composite", &opcode, &eventb, &errorb)) { + xcompositeLibHandle = dlopen("libXcomposite.so.1", RTLD_LAZY | RTLD_GLOBAL); +#ifndef __linux__ /* SOLARIS */ + if (xcompositeLibHandle == NULL) { + xcompositeLibHandle = dlopen("/usr/sfw/lib/libXcomposite.so.1", + RTLD_LAZY | RTLD_GLOBAL); + } +#endif + + if (xcompositeLibHandle) { + int major, minor; + XCompositeQueryVersion = (T_XCompositeQueryVersion)dlsym(xcompositeLibHandle, "XCompositeQueryVersion"); + + if (XCompositeQueryVersion && XCompositeQueryVersion(awt_display, &major, &minor)) { + if (major >= 0 && minor >= 3) { + XCompositeGetOverlayWindow = (T_XCompositeGetOverlayWindow)dlsym(xcompositeLibHandle, "XCompositeGetOverlayWindow"); + XCompositeReleaseOverlayWindow = (T_XCompositeReleaseOverlayWindow)dlsym(xcompositeLibHandle, "XCompositeReleaseOverlayWindow"); + + if (XCompositeGetOverlayWindow && XCompositeReleaseOverlayWindow) { + xcompositeExtAvailable = True; + } + } + } + + if (!xcompositeExtAvailable) { + dlclose(xcompositeLibHandle); + } /* else the lib is unloaded in _dispose() */ + } + } + + xcompositeExtTested = True; + } + + return xcompositeExtAvailable; +} JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, @@ -211,7 +299,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, jint *ary; /* Array of jints for sending pixel values back * to parent process. */ - Window rootWindow; + Window window; AwtGraphicsConfigDataPtr adata; DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray); @@ -228,14 +316,24 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData); DASSERT(adata != NULL); - rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen); - image = getWindowImage(awt_display, rootWindow, x, y, width, height); + window = XRootWindow(awt_display, adata->awt_visInfo.screen); + + if (IsXCompositeAvailable()) { + // Use 'composite overlay window' instead of the root window. + // See 6903034 for details. + window = XCompositeGetOverlayWindow(awt_display, window); + } + + image = getWindowImage(awt_display, window, x, y, width, height); /* Array to use to crunch around the pixel values */ ary = (jint *) malloc(width * height * sizeof (jint)); if (ary == NULL) { JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); XDestroyImage(image); + if (IsXCompositeAvailable()) { + XCompositeReleaseOverlayWindow(awt_display, window); + } AWT_UNLOCK(); return; } @@ -256,6 +354,9 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, free(ary); XDestroyImage(image); + if (IsXCompositeAvailable()) { + XCompositeReleaseOverlayWindow(awt_display, window); + } AWT_UNLOCK(); } diff --git a/src/windows/classes/sun/awt/windows/WToolkit.java b/src/windows/classes/sun/awt/windows/WToolkit.java index b994c23a1e5a93b45411a0e34055025ff0be10f1..7a18683e659245347dfe687f9b2b6822435b855b 100644 --- a/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/src/windows/classes/sun/awt/windows/WToolkit.java @@ -630,10 +630,10 @@ public class WToolkit extends SunToolkit implements Runnable { public PrintJob getPrintJob(Frame frame, String doctitle, JobAttributes jobAttributes, - PageAttributes pageAttributes) { - - if (GraphicsEnvironment.isHeadless()) { - throw new IllegalArgumentException(); + PageAttributes pageAttributes) + { + if (frame == null) { + throw new NullPointerException("frame must not be null"); } PrintJob2D printJob = new PrintJob2D(frame, doctitle, diff --git a/src/windows/native/sun/windows/awt_Toolkit.cpp b/src/windows/native/sun/windows/awt_Toolkit.cpp index cab78049f238613890afc30984612524b39aeaf0..687dc8b5a7e8b72e95aacb406700b5134428b3e3 100644 --- a/src/windows/native/sun/windows/awt_Toolkit.cpp +++ b/src/windows/native/sun/windows/awt_Toolkit.cpp @@ -528,9 +528,6 @@ BOOL AwtToolkit::Dispose() { tk.m_isActive = FALSE; - awt_dnd_uninitialize(); - awt_clipboard_uninitialize((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)); - // dispose Direct3D-related resources. This should be done // before AwtObjectList::Cleanup() as the d3d will attempt to // shutdown when the last of its windows is disposed of @@ -539,6 +536,9 @@ BOOL AwtToolkit::Dispose() { AwtObjectList::Cleanup(); AwtFont::Cleanup(); + awt_dnd_uninitialize(); + awt_clipboard_uninitialize((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)); + if (tk.m_inputMethodHWnd != NULL) { ::SendMessage(tk.m_inputMethodHWnd, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0); } diff --git a/test/java/awt/Toolkit/Headless/GetPrintJob/GetPrintJob.java b/test/java/awt/Toolkit/Headless/GetPrintJob/GetPrintJob.java new file mode 100644 index 0000000000000000000000000000000000000000..29a0950bf3bdfea4f92c4ac03eff73d9c07ea0fb --- /dev/null +++ b/test/java/awt/Toolkit/Headless/GetPrintJob/GetPrintJob.java @@ -0,0 +1,48 @@ +/* +@test +@bug 7023011 +@library ../../../regtesthelpers +@build Sysout +@summary Toolkit.getPrintJob() throws wrong exceptions +@author andrei dmitriev: area=awt.headless +@run main GetPrintJob + */ + +import java.awt.*; +import java.util.Properties; +import test.java.awt.regtesthelpers.Sysout; +/* + * In headfull mode we should always getting NPE on the getPrintJob() call if frame == null. + */ + +public class GetPrintJob { + + public static void main(String[] s) { + boolean stage1Passed = false; + boolean stage2Passed = false; + + try { + Toolkit.getDefaultToolkit().getPrintJob( + (Frame) null, "title", new Properties()); + } catch (NullPointerException e) { + stage1Passed = true; + Sysout.println("Stage 1 passed. getPrintJob(null, String, property) has thrown NPE."); + } + if (!stage1Passed) { + throw new RuntimeException("getPrintJob() should have thrown NPE but didn't."); + } + + try { + Toolkit.getDefaultToolkit().getPrintJob( + (Frame) null, "title", new JobAttributes(), new PageAttributes()); + } catch (NullPointerException e) { + stage2Passed = true; + Sysout.println("Stage 2 passed. getPrintJob(null, String, jobAttrs, pageAttr) has thrown NPE."); + } + if (!stage2Passed) { + throw new RuntimeException("getPrintJob() should have thrown NPE but didn't."); + } + + Sysout.println("Test PASSED"); + } +} diff --git a/test/java/awt/Toolkit/Headless/GetPrintJob/GetPrintJobHeadless.java b/test/java/awt/Toolkit/Headless/GetPrintJob/GetPrintJobHeadless.java new file mode 100644 index 0000000000000000000000000000000000000000..c5edf26095fa76683e17668f5d0270c10f1c9823 --- /dev/null +++ b/test/java/awt/Toolkit/Headless/GetPrintJob/GetPrintJobHeadless.java @@ -0,0 +1,50 @@ +/* +@test +@bug 7023011 +@library ../../../regtesthelpers +@build Sysout +@summary Toolkit.getPrintJob() throws wrong exceptions +@author andrei dmitriev: area=awt.headless +@run main/othervm -Djava.awt.headless=true GetPrintJobHeadless + */ + +/* + * In headless mode we should always getting NPE on the getPrintJob() call + */ +import java.awt.*; +import java.util.Properties; +import test.java.awt.regtesthelpers.Sysout; + +public class GetPrintJobHeadless { + + public static void main(String[] s) { + boolean stage1Passed = false; + boolean stage2Passed = false; + + try { + Toolkit.getDefaultToolkit().getPrintJob( + (Frame) null, "title", new Properties()); + } catch (NullPointerException e) { + stage1Passed = true; + e.printStackTrace(); + Sysout.println("Stage 1 passed. getPrintJob(null, String, property) has thrown NPE."); + } + if (!stage1Passed) { + throw new RuntimeException("getPrintJob() should have thrown NPE but didn't."); + } + + try { + Toolkit.getDefaultToolkit().getPrintJob( + (Frame) null, "title", new JobAttributes(), new PageAttributes()); + } catch (NullPointerException e) { + stage2Passed = true; + e.printStackTrace(); + Sysout.println("Stage 2 passed. getPrintJob(null, String, jobAttrs, pageAttr) has thrown NPE."); + } + if (!stage2Passed) { + throw new RuntimeException("getPrintJob() should have thrown NPE but didn't."); + } + + Sysout.println("Test PASSED"); + } +}