1 /*
2 * Copyright (c) 1996, 2017, 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_FileDialog.h"
28 #include "awt_Dialog.h"
29 #include "awt_Toolkit.h"
30 #include "ComCtl32Util.h"
31 #include <commdlg.h>
32 #include <cderr.h>
33 #include <shlobj.h>
34
35
36 /************************************************************************
37 * AwtFileDialog fields
38 */
39
40 /* WFileDialogPeer ids */
41 jfieldID AwtFileDialog::parentID;
42 jfieldID AwtFileDialog::fileFilterID;
43 jmethodID AwtFileDialog::setHWndMID;
44 jmethodID AwtFileDialog::handleSelectedMID;
45 jmethodID AwtFileDialog::handleCancelMID;
46 jmethodID AwtFileDialog::checkFilenameFilterMID;
47 jmethodID AwtFileDialog::isMultipleModeMID;
48
49 /* FileDialog ids */
50 jfieldID AwtFileDialog::modeID;
51 jfieldID AwtFileDialog::dirID;
52 jfieldID AwtFileDialog::fileID;
53 jfieldID AwtFileDialog::filterID;
54
55 /* Localized filter string */
56 #define MAX_FILTER_STRING 128
57 static TCHAR s_fileFilterString[MAX_FILTER_STRING];
58 /* Non-localized suffix of the filter string */
59 static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0");
60
61 // Default limit of the output buffer.
62 #define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1
63 #define MULTIPLE_MODE_BUFFER_LIMIT 32768
64
65 // The name of the property holding the pointer to the OPENFILENAME structure.
66 static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN");
67
68 /***********************************************************************/
69
70 void
Initialize(JNIEnv * env,jstring filterDescription)71 AwtFileDialog::Initialize(JNIEnv *env, jstring filterDescription)
72 {
73 int length = env->GetStringLength(filterDescription);
74 DASSERT(length + 1 < MAX_FILTER_STRING);
75 LPCTSTR tmp = JNU_GetStringPlatformChars(env, filterDescription, NULL);
76 _tcscpy_s(s_fileFilterString, MAX_FILTER_STRING, tmp);
77 JNU_ReleaseStringPlatformChars(env, filterDescription, tmp);
78
79 //AdditionalString should be terminated by two NULL characters (Windows
80 //requirement), so we have to organize the following cycle and use memcpy
81 //unstead of, for example, strcat.
82 LPTSTR s = s_fileFilterString;
83 while (*s) {
84 ++s;
85 DASSERT(s < s_fileFilterString + MAX_FILTER_STRING);
86 }
87 DASSERT(s + sizeof(s_additionalString) < s_fileFilterString + MAX_FILTER_STRING);
88 memcpy(s, s_additionalString, sizeof(s_additionalString));
89 }
90
FileDialogWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)91 LRESULT CALLBACK FileDialogWndProc(HWND hWnd, UINT message,
92 WPARAM wParam, LPARAM lParam)
93 {
94 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
95
96 switch (message) {
97 case WM_COMMAND: {
98 if (LOWORD(wParam) == IDCANCEL)
99 {
100 // Unlike Print/Page dialogs, we only handle IDCANCEL here and
101 // don't handle IDOK. This is because user can press OK button
102 // when no file is selected, and the dialog is not closed. So
103 // OK button is handled in the CDN_FILEOK notification handler
104 // (see FileDialogHookProc below)
105 jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp));
106 env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0);
107 }
108 break;
109 }
110 case WM_SETICON: {
111 return 0;
112 }
113 }
114
115 WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp));
116 return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam);
117 }
118
119 static UINT_PTR CALLBACK
FileDialogHookProc(HWND hdlg,UINT uiMsg,WPARAM wParam,LPARAM lParam)120 FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
121 {
122 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
123
124 TRY;
125
126 HWND parent = ::GetParent(hdlg);
127
128 switch(uiMsg) {
129 case WM_INITDIALOG: {
130 OPENFILENAME *ofn = (OPENFILENAME *)lParam;
131 jobject peer = (jobject)(ofn->lCustData);
132 env->CallVoidMethod(peer, AwtFileDialog::setHWndMID,
133 (jlong)parent);
134 ::SetProp(parent, ModalDialogPeerProp, reinterpret_cast<HANDLE>(peer));
135
136 // fix for 4508670 - disable CS_SAVEBITS
137 DWORD style = ::GetClassLong(hdlg,GCL_STYLE);
138 ::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS);
139
140 // set appropriate icon for parentless dialogs
141 jobject awtParent = env->GetObjectField(peer, AwtFileDialog::parentID);
142 if (awtParent == NULL) {
143 ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG,
144 (LPARAM)AwtToolkit::GetInstance().GetAwtIcon());
145 } else {
146 AwtWindow *awtWindow = (AwtWindow *)JNI_GET_PDATA(awtParent);
147 ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG,
148 (LPARAM)(awtWindow->GetHIcon()));
149 ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_SMALL,
150 (LPARAM)(awtWindow->GetHIconSm()));
151 env->DeleteLocalRef(awtParent);
152 }
153
154 // subclass dialog's parent to receive additional messages
155 WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(parent,
156 FileDialogWndProc);
157 ::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc));
158
159 ::SetProp(parent, OpenFileNameProp, (void *)lParam);
160
161 break;
162 }
163 case WM_DESTROY: {
164 HIMC hIMC = ::ImmGetContext(hdlg);
165 if (hIMC != NULL) {
166 ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
167 ::ImmReleaseContext(hdlg, hIMC);
168 }
169
170 WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(parent, NativeDialogWndProcProp));
171 ComCtl32Util::GetInstance().UnsubclassHWND(parent,
172 FileDialogWndProc,
173 lpfnWndProc);
174 ::RemoveProp(parent, ModalDialogPeerProp);
175 ::RemoveProp(parent, NativeDialogWndProcProp);
176 ::RemoveProp(parent, OpenFileNameProp);
177 break;
178 }
179 case WM_NOTIFY: {
180 OFNOTIFYEX *notifyEx = (OFNOTIFYEX *)lParam;
181 if (notifyEx) {
182 jobject peer = (jobject)(::GetProp(parent, ModalDialogPeerProp));
183 if (notifyEx->hdr.code == CDN_INCLUDEITEM) {
184 LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl;
185 // Get the filename and directory
186 TCHAR szPath[MAX_PATH];
187 if (!::SHGetPathFromIDList(pidl, szPath)) {
188 return TRUE;
189 }
190 jstring strPath = JNU_NewStringPlatform(env, szPath);
191 if (strPath == NULL) {
192 throw std::bad_alloc();
193 }
194 // Call FilenameFilter.accept with path and filename
195 UINT uRes = (env->CallBooleanMethod(peer,
196 AwtFileDialog::checkFilenameFilterMID, strPath) == JNI_TRUE);
197 env->DeleteLocalRef(strPath);
198 return uRes;
199 } else if (notifyEx->hdr.code == CDN_FILEOK) {
200 // This notification is sent when user selects some file and presses
201 // OK button; it is not sent when no file is selected. So it's time
202 // to unblock all the windows blocked by this dialog as it will
203 // be closed soon
204 env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0);
205 } else if (notifyEx->hdr.code == CDN_SELCHANGE) {
206 // reallocate the buffer if the buffer is too small
207 LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp);
208
209 UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) +
210 CommDlg_OpenSave_GetFolderPath(parent, NULL, 0);
211
212 if (lpofn->nMaxFile < nLength)
213 {
214 // allocate new buffer
215 LPTSTR newBuffer = new TCHAR[nLength];
216
217 if (newBuffer) {
218 memset(newBuffer, 0, nLength * sizeof(TCHAR));
219 LPTSTR oldBuffer = lpofn->lpstrFile;
220 lpofn->lpstrFile = newBuffer;
221 lpofn->nMaxFile = nLength;
222 // free the previously allocated buffer
223 if (oldBuffer) {
224 delete[] oldBuffer;
225 }
226
227 }
228 }
229 }
230 }
231 break;
232 }
233 }
234
235 return FALSE;
236
237 CATCH_BAD_ALLOC_RET(TRUE);
238 }
239
240 void
Show(void * p)241 AwtFileDialog::Show(void *p)
242 {
243 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
244 jobject peer;
245 LPTSTR fileBuffer = NULL;
246 LPTSTR currentDirectory = NULL;
247 jint mode = 0;
248 BOOL result = FALSE;
249 DWORD dlgerr;
250 jstring directory = NULL;
251 jstring title = NULL;
252 jstring file = NULL;
253 jobject fileFilter = NULL;
254 jobject target = NULL;
255 jobject parent = NULL;
256 AwtComponent* awtParent = NULL;
257 jboolean multipleMode = JNI_FALSE;
258
259 OPENFILENAME ofn;
260 memset(&ofn, 0, sizeof(ofn));
261
262 peer = (jobject)p;
263
264 try {
265 DASSERT(peer);
266 target = env->GetObjectField(peer, AwtObject::targetID);
267 parent = env->GetObjectField(peer, AwtFileDialog::parentID);
268 if (parent != NULL) {
269 awtParent = (AwtComponent *)JNI_GET_PDATA(parent);
270 }
271 // DASSERT(awtParent);
272 title = (jstring)(env)->GetObjectField(target, AwtDialog::titleID);
273 HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL;
274
275 if (title == NULL || env->GetStringLength(title)==0) {
276 title = JNU_NewStringPlatform(env, L" ");
277 if (title == NULL) {
278 throw std::bad_alloc();
279 }
280 }
281
282 JavaStringBuffer titleBuffer(env, title);
283 directory =
284 (jstring)env->GetObjectField(target, AwtFileDialog::dirID);
285 JavaStringBuffer directoryBuffer(env, directory);
286
287 multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID);
288
289 UINT bufferLimit;
290 if (multipleMode == JNI_TRUE) {
291 bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT;
292 } else {
293 bufferLimit = SINGLE_MODE_BUFFER_LIMIT;
294 }
295 LPTSTR fileBuffer = new TCHAR[bufferLimit];
296 memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR));
297
298 file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID);
299 if (file != NULL) {
300 LPCTSTR tmp = JNU_GetStringPlatformChars(env, file, NULL);
301 _tcsncpy(fileBuffer, tmp, bufferLimit - 2); // the fileBuffer is double null terminated string
302 JNU_ReleaseStringPlatformChars(env, file, tmp);
303 } else {
304 fileBuffer[0] = _T('\0');
305 }
306
307 ofn.lStructSize = sizeof(ofn);
308 ofn.lpstrFilter = s_fileFilterString;
309 ofn.nFilterIndex = 1;
310 /*
311 Fix for 6488834.
312 To disable Win32 native parent modality we have to set
313 hwndOwner field to either NULL or some hidden window. For
314 parentless dialogs we use NULL to show them in the taskbar,
315 and for all other dialogs AwtToolkit's HWND is used.
316 */
317 if (awtParent != NULL)
318 {
319 ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd();
320 }
321 else
322 {
323 ofn.hwndOwner = NULL;
324 }
325 ofn.lpstrFile = fileBuffer;
326 ofn.nMaxFile = bufferLimit;
327 ofn.lpstrTitle = titleBuffer;
328 ofn.lpstrInitialDir = directoryBuffer;
329 ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
330 OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING;
331 fileFilter = env->GetObjectField(peer,
332 AwtFileDialog::fileFilterID);
333 if (!JNU_IsNull(env,fileFilter)) {
334 ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
335 }
336 ofn.lCustData = (LPARAM)peer;
337 ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc;
338
339 if (multipleMode == JNI_TRUE) {
340 ofn.Flags |= OFN_ALLOWMULTISELECT;
341 }
342
343 // Save current directory, so we can reset if it changes.
344 currentDirectory = new TCHAR[MAX_PATH+1];
345
346 VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0);
347
348 mode = env->GetIntField(target, AwtFileDialog::modeID);
349
350 AwtDialog::CheckInstallModalHook();
351
352 // show the Win32 file dialog
353 if (mode == java_awt_FileDialog_LOAD) {
354 result = ::GetOpenFileName(&ofn);
355 } else {
356 result = ::GetSaveFileName(&ofn);
357 }
358 // Fix for 4181310: FileDialog does not show up.
359 // If the dialog is not shown because of invalid file name
360 // replace the file name by empty string.
361 if (!result) {
362 dlgerr = ::CommDlgExtendedError();
363 if (dlgerr == FNERR_INVALIDFILENAME) {
364 _tcscpy_s(fileBuffer, bufferLimit, TEXT(""));
365 if (mode == java_awt_FileDialog_LOAD) {
366 result = ::GetOpenFileName(&ofn);
367 } else {
368 result = ::GetSaveFileName(&ofn);
369 }
370 }
371 }
372
373 AwtDialog::CheckUninstallModalHook();
374
375 DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L);
376
377 AwtDialog::ModalActivateNextWindow(NULL, target, peer);
378
379 VERIFY(::SetCurrentDirectory(currentDirectory));
380
381 // Report result to peer.
382 if (result) {
383 jint length = multipleMode
384 ? (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile)
385 : (jint)_tcslen(ofn.lpstrFile);
386 jcharArray jnames = env->NewCharArray(length);
387 if (jnames == NULL) {
388 throw std::bad_alloc();
389 }
390 env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile);
391
392 env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames);
393 env->DeleteLocalRef(jnames);
394 } else {
395 env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID);
396 }
397 DASSERT(!safe_ExceptionOccurred(env));
398 } catch (...) {
399
400 env->DeleteLocalRef(target);
401 env->DeleteLocalRef(parent);
402 env->DeleteLocalRef(title);
403 env->DeleteLocalRef(directory);
404 env->DeleteLocalRef(file);
405 env->DeleteLocalRef(fileFilter);
406 env->DeleteGlobalRef(peer);
407
408 delete[] currentDirectory;
409 if (ofn.lpstrFile)
410 delete[] ofn.lpstrFile;
411 throw;
412 }
413
414 env->DeleteLocalRef(target);
415 env->DeleteLocalRef(parent);
416 env->DeleteLocalRef(title);
417 env->DeleteLocalRef(directory);
418 env->DeleteLocalRef(file);
419 env->DeleteLocalRef(fileFilter);
420 env->DeleteGlobalRef(peer);
421
422 delete[] currentDirectory;
423 if (ofn.lpstrFile)
424 delete[] ofn.lpstrFile;
425 }
426
InheritsNativeMouseWheelBehavior()427 BOOL AwtFileDialog::InheritsNativeMouseWheelBehavior() {return true;}
428
_DisposeOrHide(void * param)429 void AwtFileDialog::_DisposeOrHide(void *param)
430 {
431 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
432
433 jobject self = (jobject)param;
434
435 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
436 if (::IsWindow(hdlg))
437 {
438 ::SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0),
439 (LPARAM)hdlg);
440 }
441
442 env->DeleteGlobalRef(self);
443 }
444
_ToFront(void * param)445 void AwtFileDialog::_ToFront(void *param)
446 {
447 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
448
449 jobject self = (jobject)param;
450 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
451 if (::IsWindow(hdlg))
452 {
453 ::SetWindowPos(hdlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
454 }
455
456 env->DeleteGlobalRef(self);
457 }
458
_ToBack(void * param)459 void AwtFileDialog::_ToBack(void *param)
460 {
461 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
462
463 jobject self = (jobject)param;
464 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID));
465 if (::IsWindow(hdlg))
466 {
467 ::SetWindowPos(hdlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
468 }
469
470 env->DeleteGlobalRef(self);
471 }
472
473 // Returns the length of the double null terminated output buffer
GetBufferLength(LPTSTR buffer,UINT limit)474 UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit)
475 {
476 UINT index = 0;
477 while ((index < limit) &&
478 (buffer[index] != NULL || buffer[index+1] != NULL))
479 {
480 index++;
481 }
482 return index;
483 }
484
485 /************************************************************************
486 * WFileDialogPeer native methods
487 */
488
489 extern "C" {
490
491 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv * env,jclass cls)492 Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv *env, jclass cls)
493 {
494 TRY;
495
496 AwtFileDialog::parentID =
497 env->GetFieldID(cls, "parent", "Lsun/awt/windows/WComponentPeer;");
498 DASSERT(AwtFileDialog::parentID != NULL);
499 CHECK_NULL(AwtFileDialog::parentID);
500
501 AwtFileDialog::fileFilterID =
502 env->GetFieldID(cls, "fileFilter", "Ljava/io/FilenameFilter;");
503 DASSERT(AwtFileDialog::fileFilterID != NULL);
504 CHECK_NULL(AwtFileDialog::fileFilterID);
505
506 AwtFileDialog::setHWndMID = env->GetMethodID(cls, "setHWnd", "(J)V");
507 DASSERT(AwtFileDialog::setHWndMID != NULL);
508 CHECK_NULL(AwtFileDialog::setHWndMID);
509
510 AwtFileDialog::handleSelectedMID =
511 env->GetMethodID(cls, "handleSelected", "([C)V");
512 DASSERT(AwtFileDialog::handleSelectedMID != NULL);
513 CHECK_NULL(AwtFileDialog::handleSelectedMID);
514
515 AwtFileDialog::handleCancelMID =
516 env->GetMethodID(cls, "handleCancel", "()V");
517 DASSERT(AwtFileDialog::handleCancelMID != NULL);
518 CHECK_NULL(AwtFileDialog::handleCancelMID);
519
520 AwtFileDialog::checkFilenameFilterMID =
521 env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z");
522 DASSERT(AwtFileDialog::checkFilenameFilterMID != NULL);
523 CHECK_NULL(AwtFileDialog::checkFilenameFilterMID);
524
525 AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z");
526 DASSERT(AwtFileDialog::isMultipleModeMID != NULL);
527 CHECK_NULL(AwtFileDialog::isMultipleModeMID);
528
529 /* java.awt.FileDialog fields */
530 cls = env->FindClass("java/awt/FileDialog");
531 CHECK_NULL(cls);
532
533 AwtFileDialog::modeID = env->GetFieldID(cls, "mode", "I");
534 DASSERT(AwtFileDialog::modeID != NULL);
535 CHECK_NULL(AwtFileDialog::modeID);
536
537 AwtFileDialog::dirID = env->GetFieldID(cls, "dir", "Ljava/lang/String;");
538 DASSERT(AwtFileDialog::dirID != NULL);
539 CHECK_NULL(AwtFileDialog::dirID);
540
541 AwtFileDialog::fileID = env->GetFieldID(cls, "file", "Ljava/lang/String;");
542 DASSERT(AwtFileDialog::fileID != NULL);
543 CHECK_NULL(AwtFileDialog::fileID);
544
545 AwtFileDialog::filterID =
546 env->GetFieldID(cls, "filter", "Ljava/io/FilenameFilter;");
547 DASSERT(AwtFileDialog::filterID != NULL);
548
549 CATCH_BAD_ALLOC;
550 }
551
552 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_setFilterString(JNIEnv * env,jclass cls,jstring filterDescription)553 Java_sun_awt_windows_WFileDialogPeer_setFilterString(JNIEnv *env, jclass cls,
554 jstring filterDescription)
555 {
556 TRY;
557
558 AwtFileDialog::Initialize(env, filterDescription);
559
560 CATCH_BAD_ALLOC;
561 }
562
563 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer__1show(JNIEnv * env,jobject peer)564 Java_sun_awt_windows_WFileDialogPeer__1show(JNIEnv *env, jobject peer)
565 {
566 TRY;
567
568 /*
569 * Fix for 4906972.
570 * 'peer' reference has to be global as it's used further in another thread.
571 */
572 jobject peerGlobal = env->NewGlobalRef(peer);
573
574 if (!AwtToolkit::GetInstance().PostMessage(WM_AWT_INVOKE_METHOD,
575 (WPARAM)AwtFileDialog::Show, (LPARAM)peerGlobal)) {
576 env->DeleteGlobalRef(peerGlobal);
577 }
578
579 CATCH_BAD_ALLOC;
580 }
581
582 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer__1dispose(JNIEnv * env,jobject peer)583 Java_sun_awt_windows_WFileDialogPeer__1dispose(JNIEnv *env, jobject peer)
584 {
585 TRY_NO_VERIFY;
586
587 jobject peerGlobal = env->NewGlobalRef(peer);
588
589 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide,
590 (void *)peerGlobal);
591 // peerGlobal ref is deleted in _DisposeOrHide
592
593 CATCH_BAD_ALLOC;
594 }
595
596 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer__1hide(JNIEnv * env,jobject peer)597 Java_sun_awt_windows_WFileDialogPeer__1hide(JNIEnv *env, jobject peer)
598 {
599 TRY;
600
601 jobject peerGlobal = env->NewGlobalRef(peer);
602
603 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide,
604 (void *)peerGlobal);
605 // peerGlobal ref is deleted in _DisposeOrHide
606
607 CATCH_BAD_ALLOC;
608 }
609
610 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_toFront(JNIEnv * env,jobject peer)611 Java_sun_awt_windows_WFileDialogPeer_toFront(JNIEnv *env, jobject peer)
612 {
613 TRY;
614
615 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToFront,
616 (void *)(env->NewGlobalRef(peer)));
617 // global ref is deleted in _ToFront
618
619 CATCH_BAD_ALLOC;
620 }
621
622 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv * env,jobject peer)623 Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv *env, jobject peer)
624 {
625 TRY;
626
627 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToBack,
628 (void *)(env->NewGlobalRef(peer)));
629 // global ref is deleted in _ToBack
630
631 CATCH_BAD_ALLOC;
632 }
633
ScaleDownX(int x,HWND hwnd)634 int ScaleDownX(int x, HWND hwnd) {
635 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd);
636 Devices::InstanceAccess devices;
637 AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
638 return device == NULL ? x : device->ScaleDownX(x);
639 }
640
ScaleDownY(int y,HWND hwnd)641 int ScaleDownY(int y, HWND hwnd) {
642 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd);
643 Devices::InstanceAccess devices;
644 AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
645 return device == NULL ? y : device->ScaleDownY(y);
646 }
647
_GetLocationOnScreen(void * param)648 jobject AwtFileDialog::_GetLocationOnScreen(void *param)
649 {
650 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
651
652 jobject result = NULL;
653 HWND hwnd = (HWND)env->GetLongField((jobject)param, AwtComponent::hwndID);
654
655 if (::IsWindow(hwnd))
656 {
657 RECT rect;
658 VERIFY(::GetWindowRect(hwnd, &rect));
659 result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
660 ScaleDownX(rect.left, hwnd), ScaleDownY(rect.top, hwnd));
661 }
662
663 if (result != NULL)
664 {
665 jobject resultRef = env->NewGlobalRef(result);
666 env->DeleteLocalRef(result);
667 return resultRef;
668 }
669 else
670 {
671 return NULL;
672 }
673 }
674
675 /*
676 * Class: sun_awt_windows_WFileDialogPeer
677 * Method: getLocationOnScreen
678 * Signature: ()Ljava/awt/Point;
679 */
680 JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WFileDialogPeer_getLocationOnScreen(JNIEnv * env,jobject peer)681 Java_sun_awt_windows_WFileDialogPeer_getLocationOnScreen(JNIEnv *env,
682 jobject peer) {
683 TRY;
684
685 jobject peerRef = env->NewGlobalRef(peer);
686 jobject resultRef = (jobject)AwtToolkit::GetInstance().SyncCall(
687 (void*(*)(void*))AwtFileDialog::_GetLocationOnScreen, (void *)peerRef);
688 env->DeleteGlobalRef(peerRef);
689
690 if (resultRef != NULL)
691 {
692 jobject result = env->NewLocalRef(resultRef);
693 env->DeleteGlobalRef(resultRef);
694 return result;
695 }
696
697 return NULL;
698
699 CATCH_BAD_ALLOC_RET(NULL);
700 }
701
702 } /* extern "C" */
703