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 /*
252 Fix for 6488834.
253 To disable Win32 native parent modality we have to set
254 hwndOwner field to either NULL or some hidden window. For
255 parentless dialogs we use NULL to show them in the taskbar,
256 and for all other dialogs AwtToolkit's HWND is used.
257 */
258 if (awtParent != NULL)
259 {
260 pd.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
261 }
262 else
263 {
264 pd.hwndOwner = NULL;
265 }
266
267 AwtDialog::CheckInstallModalHook();
268
269 BOOL ret = AwtPrintDialog::PrintDlg(&pd);
270 if (ret)
271 {
272 AwtPrintControl::UpdateAttributes(env, control, pd);
273 result = JNI_TRUE;
274 }
275 else
276 {
277 result = JNI_FALSE;
278 }
279
280 DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L);
281
282 AwtDialog::CheckUninstallModalHook();
283
284 AwtDialog::ModalActivateNextWindow(NULL, target, peer);
285 }
286
287 env->DeleteGlobalRef(peerGlobalRef);
288 env->DeleteLocalRef(target);
289 if (parent != NULL) {
290 env->DeleteLocalRef(parent);
291 }
292 env->DeleteLocalRef(control);
293
294 return result;
295
296 CATCH_BAD_ALLOC_RET(0);
297 }
298
299 JNIEXPORT void JNICALL
300 Java_sun_awt_windows_WPrintDialogPeer_toFront(JNIEnv *env, jobject peer)
301 {
302 TRY;
303
304 AwtToolkit::GetInstance().SyncCall(AwtPrintDialog::_ToFront,
305 (void *)(env->NewGlobalRef(peer)));
306 // global ref is deleted in _ToFront
307
308 CATCH_BAD_ALLOC;
309 }
310
311 JNIEXPORT void JNICALL
312 Java_sun_awt_windows_WPrintDialogPeer_toBack(JNIEnv *env, jobject peer)
313 {
314 TRY;
315
316 AwtToolkit::GetInstance().SyncCall(AwtPrintDialog::_ToBack,
317 (void *)(env->NewGlobalRef(peer)));
318 // global ref is deleted in _ToBack
319
320 CATCH_BAD_ALLOC;
321 }
322
323 } /* extern "C" */
--- EOF ---