8176530: JDK support for JavaFX modal print dialogs
Reviewed-by: serb, psadhukhan, kcr
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/print/DialogOnTop.java Wed Mar 15 11:14:23 2017 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.print;
+
+import javax.print.attribute.Attribute;
+import javax.print.attribute.PrintRequestAttribute;
+
+/*
+ * An implementation class used to request the dialog be set always-on-top.
+ * It needs to be read and honoured by the dialog code which will use
+ * java.awt.Window.setAlwaysOnTop(true) in cases where it is supported.
+ */
+public class DialogOnTop implements PrintRequestAttribute {
+
+ private static final long serialVersionUID = -1901909867156076547L;
+
+ long id;
+
+ public DialogOnTop() {
+ }
+
+ public DialogOnTop(long id) {
+ this.id = id;
+ }
+
+ public final Class<? extends Attribute> getCategory() {
+ return DialogOnTop.class;
+ }
+
+ public long getID() {
+ return id;
+ }
+
+ public final String getName() {
+ return "dialog-on-top";
+ }
+
+ public String toString() {
+ return "dialog-on-top";
+ }
+}
--- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Wed Mar 15 20:42:55 2017 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Wed Mar 15 11:14:23 2017 -0700
@@ -785,7 +785,9 @@
PrintService pservice = getPrintService();
PageFormat pageFrmAttrib = attributeToPageFormat(pservice,
attributes);
+ setParentWindowID(attributes);
PageFormat page = pageDialog(pageFrmAttrib);
+ clearParentWindowID();
// If user cancels the dialog, pageDialog() will return the original
// page object and as per spec, we should return null in that case.
@@ -828,6 +830,9 @@
int x = gcBounds.x+50;
int y = gcBounds.y+50;
ServiceDialog pageDialog;
+ if (onTop != null) {
+ attributes.add(onTop);
+ }
if (w instanceof Frame) {
pageDialog = new ServiceDialog(gc, x, y, service,
DocFlavor.SERVICE_FORMATTED.PAGEABLE,
@@ -837,6 +842,7 @@
DocFlavor.SERVICE_FORMATTED.PAGEABLE,
attributes, (Dialog)w);
}
+
Rectangle dlgBounds = pageDialog.getBounds();
// if portion of dialog is not within the gc boundary
@@ -923,7 +929,9 @@
}
+ setParentWindowID(attributes);
boolean ret = printDialog();
+ clearParentWindowID();
this.attributes = attributes;
return ret;
@@ -2539,4 +2547,26 @@
return new String(out_chars, 0, pos);
}
}
+
+ private DialogOnTop onTop = null;
+
+ private long parentWindowID = 0L;
+
+ /* Called from native code */
+ private long getParentWindowID() {
+ return parentWindowID;
+ }
+
+ private void clearParentWindowID() {
+ parentWindowID = 0L;
+ onTop = null;
+ }
+
+ private void setParentWindowID(PrintRequestAttributeSet attrs) {
+ parentWindowID = 0L;
+ onTop = (DialogOnTop)attrs.get(DialogOnTop.class);
+ if (onTop != null) {
+ parentWindowID = onTop.getID();
+ }
+ }
}
--- a/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java Wed Mar 15 20:42:55 2017 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java Wed Mar 15 11:14:23 2017 -0700
@@ -184,6 +184,9 @@
isAWT = true;
}
+ if (attributes.get(DialogOnTop.class) != null) {
+ setAlwaysOnTop(true);
+ }
Container c = getContentPane();
c.setLayout(new BorderLayout());
@@ -275,6 +278,10 @@
this.asOriginal = attributes;
this.asCurrent = new HashPrintRequestAttributeSet(attributes);
+ if (attributes.get(DialogOnTop.class) != null) {
+ setAlwaysOnTop(true);
+ }
+
Container c = getContentPane();
c.setLayout(new BorderLayout());
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.cpp Wed Mar 15 20:42:55 2017 +0300
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.cpp Wed Mar 15 11:14:23 2017 -0700
@@ -54,6 +54,7 @@
jmethodID AwtPrintControl::setDevmodeID;
jmethodID AwtPrintControl::getDevnamesID;
jmethodID AwtPrintControl::setDevnamesID;
+jmethodID AwtPrintControl::getParentWindowID;
jfieldID AwtPrintControl::driverDoesMultipleCopiesID;
jfieldID AwtPrintControl::driverDoesCollationID;
jmethodID AwtPrintControl::getWin32MediaID;
@@ -240,6 +241,11 @@
DASSERT(AwtPrintControl::dialogOwnerPeerID != NULL);
CHECK_NULL(AwtPrintControl::dialogOwnerPeerID);
+ AwtPrintControl::getParentWindowID = env->GetMethodID(cls,
+ "getParentWindowID", "()J");
+ DASSERT(AwtPrintControl::getParentWindowID != NULL);
+ CHECK_NULL(AwtPrintControl::getParentWindowID);
+
AwtPrintControl::getPrintDCID = env->GetMethodID(cls, "getPrintDC", "()J");
DASSERT(AwtPrintControl::getPrintDCID != NULL);
CHECK_NULL(AwtPrintControl::getPrintDCID);
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.h Wed Mar 15 20:42:55 2017 +0300
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintControl.h Wed Mar 15 11:14:23 2017 -0700
@@ -47,6 +47,7 @@
static jmethodID setDevmodeID;
static jmethodID getDevnamesID;
static jmethodID setDevnamesID;
+ static jmethodID getParentWindowID;
static jmethodID getWin32MediaID;
static jmethodID setWin32MediaID;
static jmethodID getWin32MediaTrayID;
@@ -97,6 +98,10 @@
LPTSTR pPrinterName,
LPDEVMODE *pDevMode);
+ inline static HWND getParentID(JNIEnv *env, jobject self) {
+ return (HWND)env->CallLongMethod(self, getParentWindowID);
+ }
+
inline static HDC getPrintDC(JNIEnv *env, jobject self) {
return (HDC)env->CallLongMethod(self, getPrintDCID);
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintDialog.cpp Wed Mar 15 20:42:55 2017 +0300
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintDialog.cpp Wed Mar 15 11:14:23 2017 -0700
@@ -248,6 +248,11 @@
pd.lpfnPrintHook = (LPPRINTHOOKPROC)PrintDialogHookProc;
pd.lpfnSetupHook = (LPSETUPHOOKPROC)PrintDialogHookProc;
pd.Flags |= PD_ENABLESETUPHOOK | PD_ENABLEPRINTHOOK;
+ HWND parent = AwtPrintControl::getParentID(env, control);
+ if (parent != NULL && ::IsWindow(parent)) {
+ // Windows native modality is requested (used by JavaFX).
+ pd.hwndOwner = parent;
+ }
/*
Fix for 6488834.
To disable Win32 native parent modality we have to set
@@ -255,7 +260,7 @@
parentless dialogs we use NULL to show them in the taskbar,
and for all other dialogs AwtToolkit's HWND is used.
*/
- if (awtParent != NULL)
+ else if (awtParent != NULL)
{
pd.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp Wed Mar 15 20:42:55 2017 +0300
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp Wed Mar 15 11:14:23 2017 -0700
@@ -521,12 +521,18 @@
AwtComponent *awtParent = (parent != NULL) ? (AwtComponent *)JNI_GET_PDATA(parent) : NULL;
HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL;
+
jboolean doIt = JNI_FALSE; // Assume the user will cancel the dialog.
PAGESETUPDLG setup;
memset(&setup, 0, sizeof(setup));
setup.lStructSize = sizeof(setup);
+ HWND parentID = AwtPrintControl::getParentID(env, self);
+ if (parentID != NULL && ::IsWindow(parentID)) {
+ // windows native modality is requested (used by JavaFX).
+ setup.hwndOwner = parentID;
+ }
/*
Fix for 6488834.
To disable Win32 native parent modality we have to set
@@ -534,7 +540,7 @@
parentless dialogs we use NULL to show them in the taskbar,
and for all other dialogs AwtToolkit's HWND is used.
*/
- if (awtParent != NULL)
+ else if (awtParent != NULL)
{
setup.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
}