1 /* 2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "awt.h" 27 #include "awt_PrintDialog.h" 28 #include "awt_Dialog.h" 29 #include "awt_PrintControl.h" 30 #include "awt_Window.h" 31 #include "ComCtl32Util.h" 32 #include <sun_awt_windows_WPrintDialog.h> 33 #include <sun_awt_windows_WPrintDialogPeer.h> 34 35 jfieldID AwtPrintDialog::controlID; 36 jfieldID AwtPrintDialog::parentID; 37 38 jmethodID AwtPrintDialog::setHWndMID; 39 40 BOOL 41 AwtPrintDialog::PrintDlg(LPPRINTDLG data) { 42 return static_cast<BOOL>(reinterpret_cast<INT_PTR>( 43 AwtToolkit::GetInstance().InvokeFunction( 44 reinterpret_cast<void *(*)(void *)>(::PrintDlg), data))); 45 } 46 47 LRESULT CALLBACK PrintDialogWndProc(HWND hWnd, UINT message, 48 WPARAM wParam, LPARAM lParam) 49 { 50 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 51 52 switch (message) { 53 case WM_COMMAND: { 54 if ((LOWORD(wParam) == IDOK) || 55 (LOWORD(wParam) == IDCANCEL)) 56 { 57 // If we recieve on of these two notifications, the dialog 58 // is about to be closed. It's time to unblock all the 59 // windows blocked by this dialog, as doing so from the 60 // WM_DESTROY handler is too late 61 jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp)); 62 env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, (jlong)0); 63 } 64 break; 65 } 66 } 67 68 WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp)); 69 return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam); 70 } 71 72 static UINT_PTR CALLBACK 73 PrintDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) 74 { 75 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 76 77 TRY; 78 79 switch(uiMsg) { 80 case WM_INITDIALOG: { 81 PRINTDLG *pd = (PRINTDLG *)lParam; 82 jobject peer = (jobject)(pd->lCustData); 83 env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, 84 (jlong)hdlg); 85 ::SetProp(hdlg, ModalDialogPeerProp, reinterpret_cast<HANDLE>(peer)); 86 87 // fix for 4632159 - disable CS_SAVEBITS 88 DWORD style = ::GetClassLong(hdlg, GCL_STYLE); 89 ::SetClassLong(hdlg,GCL_STYLE, style & ~CS_SAVEBITS); 90 91 ::SetFocus(hdlg); // will not break synthetic focus as hdlg is a native toplevel 92 93 // set appropriate icon for parentless dialogs 94 jobject awtParent = env->GetObjectField(peer, AwtPrintDialog::parentID); 95 if (awtParent == NULL) { 96 ::SendMessage(hdlg, WM_SETICON, (WPARAM)ICON_BIG, 97 (LPARAM)AwtToolkit::GetInstance().GetAwtIcon()); 98 } else { 99 env->DeleteLocalRef(awtParent); 100 } 101 102 // subclass dialog's parent to receive additional messages 103 WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(hdlg, 104 PrintDialogWndProc); 105 ::SetProp(hdlg, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc)); 106 107 break; 108 } 109 case WM_DESTROY: { 110 WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hdlg, NativeDialogWndProcProp)); 111 ComCtl32Util::GetInstance().UnsubclassHWND(hdlg, 112 PrintDialogWndProc, 113 lpfnWndProc); 114 ::RemoveProp(hdlg, ModalDialogPeerProp); 115 ::RemoveProp(hdlg, NativeDialogWndProcProp); 116 break; 117 } 118 } 119 return FALSE; 120 121 CATCH_BAD_ALLOC_RET(TRUE); 122 } 123 124 void AwtPrintDialog::_ToFront(void *param) 125 { 126 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 127 128 jobject self = (jobject)param; 129 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); 130 if (::IsWindow(hdlg)) 131 { 132 ::SetWindowPos(hdlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 133 } 134 135 env->DeleteGlobalRef(self); 136 } 137 138 void AwtPrintDialog::_ToBack(void *param) 139 { 140 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 141 142 jobject self = (jobject)param; 143 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); 144 if (::IsWindow(hdlg)) 145 { 146 ::SetWindowPos(hdlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 147 } 148 149 env->DeleteGlobalRef(self); 150 } 151 152 153 extern "C" { 154 JNIEXPORT void JNICALL 155 Java_sun_awt_windows_WPrintDialog_initIDs(JNIEnv *env, jclass cls) 156 { 157 TRY; 158 159 AwtPrintDialog::controlID = 160 env->GetFieldID(cls, "pjob", "Ljava/awt/print/PrinterJob;"); 161 DASSERT(AwtPrintDialog::controlID != NULL); 162 163 AwtPrintControl::initIDs(env, cls); 164 165 CATCH_BAD_ALLOC; 166 } 167 168 JNIEXPORT void JNICALL 169 Java_sun_awt_windows_WPrintDialogPeer_initIDs(JNIEnv *env, jclass cls) 170 { 171 TRY; 172 173 AwtPrintDialog::parentID = 174 env->GetFieldID(cls, "parent", "Lsun/awt/windows/WComponentPeer;"); 175 DASSERT(AwtPrintDialog::parentID != NULL); 176 CHECK_NULL(AwtPrintDialog::parentID); 177 178 AwtPrintDialog::setHWndMID = 179 env->GetMethodID(cls, "setHWnd", "(J)V"); 180 DASSERT(AwtPrintDialog::setHWndMID != NULL); 181 CHECK_NULL(AwtPrintDialog::setHWndMID); 182 183 CATCH_BAD_ALLOC; 184 } 185 186 JNIEXPORT jboolean JNICALL 187 Java_sun_awt_windows_WPrintDialogPeer__1show(JNIEnv *env, jobject peer) 188 { 189 TRY; 190 191 jboolean result = JNI_FALSE; 192 193 // as peer object is used later on another thread, create a global ref 194 jobject peerGlobalRef = env->NewGlobalRef(peer); 195 DASSERT(peerGlobalRef != NULL); 196 CHECK_NULL_RETURN(peerGlobalRef, 0); 197 jobject target = env->GetObjectField(peerGlobalRef, AwtObject::targetID); 198 DASSERT(target != NULL); 199 if (target == NULL) { 200 env->DeleteGlobalRef(peerGlobalRef); 201 return 0; 202 } 203 jobject parent = env->GetObjectField(peerGlobalRef, AwtPrintDialog::parentID); 204 jobject control = env->GetObjectField(target, AwtPrintDialog::controlID); 205 DASSERT(control != NULL); 206 if (control == NULL) { 207 env->DeleteGlobalRef(peerGlobalRef); 208 env->DeleteLocalRef(target); 209 if (parent != NULL) { 210 env->DeleteLocalRef(parent); 211 } 212 return 0; 213 } 214 215 AwtComponent *awtParent = (parent != NULL) ? (AwtComponent *)JNI_GET_PDATA(parent) : NULL; 216 HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL; 217 218 PRINTDLG pd; 219 memset(&pd, 0, sizeof(PRINTDLG)); 220 pd.lStructSize = sizeof(PRINTDLG); 221 pd.lCustData = (LPARAM)peerGlobalRef; 222 BOOL ret; 223 try { 224 ret = AwtPrintControl::InitPrintDialog(env, control, pd); 225 } catch (std::bad_alloc&) { 226 env->DeleteGlobalRef(peerGlobalRef); 227 env->DeleteLocalRef(target); 228 if (parent != NULL) { 229 env->DeleteLocalRef(parent); 230 } 231 env->DeleteLocalRef(control); 232 throw; 233 } 234 if (!ret) { 235 /* Couldn't use the printer, or spooler isn't running 236 * Call Page dialog with ' PD_RETURNDEFAULT' so it doesn't try 237 * to show the dialog, but does prompt the user to install a printer. 238 * If this returns false, then they declined and we just return. 239 */ 240 pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC; 241 ret = AwtPrintDialog::PrintDlg(&pd); 242 } 243 if (!ret) { 244 result = JNI_FALSE; 245 } 246 else 247 { 248 pd.lpfnPrintHook = (LPPRINTHOOKPROC)PrintDialogHookProc; 249 pd.lpfnSetupHook = (LPSETUPHOOKPROC)PrintDialogHookProc; 250 pd.Flags |= PD_ENABLESETUPHOOK | PD_ENABLEPRINTHOOK; 251 HWND parent = AwtPrintControl::getParentID(env, control); 252 if (parent != NULL) { 253 // Windows native modality is requested (used by JavaFX). 254 pd.hwndOwner = parent; 255 } 256 /* 257 Fix for 6488834. 258 To disable Win32 native parent modality we have to set 259 hwndOwner field to either NULL or some hidden window. For 260 parentless dialogs we use NULL to show them in the taskbar, 261 and for all other dialogs AwtToolkit's HWND is used. 262 */ 263 else if (awtParent != NULL) 264 { 265 pd.hwndOwner = AwtToolkit::GetInstance().GetHWnd(); 266 } 267 else 268 { 269 pd.hwndOwner = NULL; 270 } 271 272 AwtDialog::CheckInstallModalHook(); 273 274 BOOL ret = AwtPrintDialog::PrintDlg(&pd); 275 if (ret) 276 { 277 AwtPrintControl::UpdateAttributes(env, control, pd); 278 result = JNI_TRUE; 279 } 280 else 281 { 282 result = JNI_FALSE; 283 } 284 285 DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L); 286 287 AwtDialog::CheckUninstallModalHook(); 288 289 AwtDialog::ModalActivateNextWindow(NULL, target, peer); 290 } 291 292 env->DeleteGlobalRef(peerGlobalRef); 293 env->DeleteLocalRef(target); 294 if (parent != NULL) { 295 env->DeleteLocalRef(parent); 296 } 297 env->DeleteLocalRef(control); 298 299 return result; 300 301 CATCH_BAD_ALLOC_RET(0); 302 } 303 304 JNIEXPORT void JNICALL 305 Java_sun_awt_windows_WPrintDialogPeer_toFront(JNIEnv *env, jobject peer) 306 { 307 TRY; 308 309 AwtToolkit::GetInstance().SyncCall(AwtPrintDialog::_ToFront, 310 (void *)(env->NewGlobalRef(peer))); 311 // global ref is deleted in _ToFront 312 313 CATCH_BAD_ALLOC; 314 } 315 316 JNIEXPORT void JNICALL 317 Java_sun_awt_windows_WPrintDialogPeer_toBack(JNIEnv *env, jobject peer) 318 { 319 TRY; 320 321 AwtToolkit::GetInstance().SyncCall(AwtPrintDialog::_ToBack, 322 (void *)(env->NewGlobalRef(peer))); 323 // global ref is deleted in _ToBack 324 325 CATCH_BAD_ALLOC; 326 } 327 328 } /* extern "C" */ --- EOF ---