1 /* 2 * Copyright (c) 1996, 2016, 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 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 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 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 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 /* 263 * There's a situation (see bug 4906972) when InvokeFunction (by which this method is called) 264 * returnes earlier than this method returnes. Probably it's caused due to ReplyMessage system call. 265 * So for the avoidance of this mistiming we need to make new global reference here 266 * (not local as it's used by the hook) and then manage it independently of the calling thread. 267 */ 268 peer = env->NewGlobalRef((jobject)p); 269 270 try { 271 DASSERT(peer); 272 target = env->GetObjectField(peer, AwtObject::targetID); 273 parent = env->GetObjectField(peer, AwtFileDialog::parentID); 274 if (parent != NULL) { 275 awtParent = (AwtComponent *)JNI_GET_PDATA(parent); 276 } 277 // DASSERT(awtParent); 278 title = (jstring)(env)->GetObjectField(target, AwtDialog::titleID); 279 HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL; 280 281 if (title == NULL || env->GetStringLength(title)==0) { 282 title = JNU_NewStringPlatform(env, L" "); 283 if (title == NULL) { 284 throw std::bad_alloc(); 285 } 286 } 287 288 JavaStringBuffer titleBuffer(env, title); 289 directory = 290 (jstring)env->GetObjectField(target, AwtFileDialog::dirID); 291 JavaStringBuffer directoryBuffer(env, directory); 292 293 multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID); 294 295 UINT bufferLimit; 296 if (multipleMode == JNI_TRUE) { 297 bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT; 298 } else { 299 bufferLimit = SINGLE_MODE_BUFFER_LIMIT; 300 } 301 LPTSTR fileBuffer = new TCHAR[bufferLimit]; 302 memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR)); 303 304 file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID); 305 if (file != NULL) { 306 LPCTSTR tmp = JNU_GetStringPlatformChars(env, file, NULL); 307 _tcsncpy(fileBuffer, tmp, bufferLimit - 2); // the fileBuffer is double null terminated string 308 JNU_ReleaseStringPlatformChars(env, file, tmp); 309 } else { 310 fileBuffer[0] = _T('\0'); 311 } 312 313 ofn.lStructSize = sizeof(ofn); 314 ofn.lpstrFilter = s_fileFilterString; 315 ofn.nFilterIndex = 1; 316 /* 317 Fix for 6488834. 318 To disable Win32 native parent modality we have to set 319 hwndOwner field to either NULL or some hidden window. For 320 parentless dialogs we use NULL to show them in the taskbar, 321 and for all other dialogs AwtToolkit's HWND is used. 322 */ 323 if (awtParent != NULL) 324 { 325 ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd(); 326 } 327 else 328 { 329 ofn.hwndOwner = NULL; 330 } 331 ofn.lpstrFile = fileBuffer; 332 ofn.nMaxFile = bufferLimit; 333 ofn.lpstrTitle = titleBuffer; 334 ofn.lpstrInitialDir = directoryBuffer; 335 ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | 336 OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING; 337 fileFilter = env->GetObjectField(peer, 338 AwtFileDialog::fileFilterID); 339 if (!JNU_IsNull(env,fileFilter)) { 340 ofn.Flags |= OFN_ENABLEINCLUDENOTIFY; 341 } 342 ofn.lCustData = (LPARAM)peer; 343 ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc; 344 345 if (multipleMode == JNI_TRUE) { 346 ofn.Flags |= OFN_ALLOWMULTISELECT; 347 } 348 349 // Save current directory, so we can reset if it changes. 350 currentDirectory = new TCHAR[MAX_PATH+1]; 351 352 VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0); 353 354 mode = env->GetIntField(target, AwtFileDialog::modeID); 355 356 AwtDialog::CheckInstallModalHook(); 357 358 // show the Win32 file dialog 359 if (mode == java_awt_FileDialog_LOAD) { 360 result = ::GetOpenFileName(&ofn); 361 } else { 362 result = ::GetSaveFileName(&ofn); 363 } 364 // Fix for 4181310: FileDialog does not show up. 365 // If the dialog is not shown because of invalid file name 366 // replace the file name by empty string. 367 if (!result) { 368 dlgerr = ::CommDlgExtendedError(); 369 if (dlgerr == FNERR_INVALIDFILENAME) { 370 _tcscpy_s(fileBuffer, bufferLimit, TEXT("")); 371 if (mode == java_awt_FileDialog_LOAD) { 372 result = ::GetOpenFileName(&ofn); 373 } else { 374 result = ::GetSaveFileName(&ofn); 375 } 376 } 377 } 378 379 AwtDialog::CheckUninstallModalHook(); 380 381 DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L); 382 383 AwtDialog::ModalActivateNextWindow(NULL, target, peer); 384 385 VERIFY(::SetCurrentDirectory(currentDirectory)); 386 387 // Report result to peer. 388 if (result) { 389 jint length = multipleMode 390 ? (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile) 391 : (jint)_tcslen(ofn.lpstrFile); 392 jcharArray jnames = env->NewCharArray(length); 393 if (jnames == NULL) { 394 throw std::bad_alloc(); 395 } 396 env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile); 397 398 env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames); 399 env->DeleteLocalRef(jnames); 400 } else { 401 env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID); 402 } 403 DASSERT(!safe_ExceptionOccurred(env)); 404 } catch (...) { 405 406 env->DeleteLocalRef(target); 407 env->DeleteLocalRef(parent); 408 env->DeleteLocalRef(title); 409 env->DeleteLocalRef(directory); 410 env->DeleteLocalRef(file); 411 env->DeleteLocalRef(fileFilter); 412 env->DeleteGlobalRef(peer); 413 414 delete[] currentDirectory; 415 if (ofn.lpstrFile) 416 delete[] ofn.lpstrFile; 417 throw; 418 } 419 420 env->DeleteLocalRef(target); 421 env->DeleteLocalRef(parent); 422 env->DeleteLocalRef(title); 423 env->DeleteLocalRef(directory); 424 env->DeleteLocalRef(file); 425 env->DeleteLocalRef(fileFilter); 426 env->DeleteGlobalRef(peer); 427 428 delete[] currentDirectory; 429 if (ofn.lpstrFile) 430 delete[] ofn.lpstrFile; 431 } 432 433 BOOL AwtFileDialog::InheritsNativeMouseWheelBehavior() {return true;} 434 435 void AwtFileDialog::_DisposeOrHide(void *param) 436 { 437 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 438 439 jobject self = (jobject)param; 440 441 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); 442 if (::IsWindow(hdlg)) 443 { 444 ::SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), 445 (LPARAM)hdlg); 446 } 447 448 env->DeleteGlobalRef(self); 449 } 450 451 void AwtFileDialog::_ToFront(void *param) 452 { 453 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 454 455 jobject self = (jobject)param; 456 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); 457 if (::IsWindow(hdlg)) 458 { 459 ::SetWindowPos(hdlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 460 } 461 462 env->DeleteGlobalRef(self); 463 } 464 465 void AwtFileDialog::_ToBack(void *param) 466 { 467 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 468 469 jobject self = (jobject)param; 470 HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); 471 if (::IsWindow(hdlg)) 472 { 473 ::SetWindowPos(hdlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 474 } 475 476 env->DeleteGlobalRef(self); 477 } 478 479 // Returns the length of the double null terminated output buffer 480 UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit) 481 { 482 UINT index = 0; 483 while ((index < limit) && 484 (buffer[index] != NULL || buffer[index+1] != NULL)) 485 { 486 index++; 487 } 488 return index; 489 } 490 491 /************************************************************************ 492 * WFileDialogPeer native methods 493 */ 494 495 extern "C" { 496 497 JNIEXPORT void JNICALL 498 Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv *env, jclass cls) 499 { 500 TRY; 501 502 AwtFileDialog::parentID = 503 env->GetFieldID(cls, "parent", "Lsun/awt/windows/WComponentPeer;"); 504 DASSERT(AwtFileDialog::parentID != NULL); 505 CHECK_NULL(AwtFileDialog::parentID); 506 507 AwtFileDialog::fileFilterID = 508 env->GetFieldID(cls, "fileFilter", "Ljava/io/FilenameFilter;"); 509 DASSERT(AwtFileDialog::fileFilterID != NULL); 510 CHECK_NULL(AwtFileDialog::fileFilterID); 511 512 AwtFileDialog::setHWndMID = env->GetMethodID(cls, "setHWnd", "(J)V"); 513 DASSERT(AwtFileDialog::setHWndMID != NULL); 514 CHECK_NULL(AwtFileDialog::setHWndMID); 515 516 AwtFileDialog::handleSelectedMID = 517 env->GetMethodID(cls, "handleSelected", "([C)V"); 518 DASSERT(AwtFileDialog::handleSelectedMID != NULL); 519 CHECK_NULL(AwtFileDialog::handleSelectedMID); 520 521 AwtFileDialog::handleCancelMID = 522 env->GetMethodID(cls, "handleCancel", "()V"); 523 DASSERT(AwtFileDialog::handleCancelMID != NULL); 524 CHECK_NULL(AwtFileDialog::handleCancelMID); 525 526 AwtFileDialog::checkFilenameFilterMID = 527 env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z"); 528 DASSERT(AwtFileDialog::checkFilenameFilterMID != NULL); 529 CHECK_NULL(AwtFileDialog::checkFilenameFilterMID); 530 531 AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z"); 532 DASSERT(AwtFileDialog::isMultipleModeMID != NULL); 533 CHECK_NULL(AwtFileDialog::isMultipleModeMID); 534 535 /* java.awt.FileDialog fields */ 536 cls = env->FindClass("java/awt/FileDialog"); 537 CHECK_NULL(cls); 538 539 AwtFileDialog::modeID = env->GetFieldID(cls, "mode", "I"); 540 DASSERT(AwtFileDialog::modeID != NULL); 541 CHECK_NULL(AwtFileDialog::modeID); 542 543 AwtFileDialog::dirID = env->GetFieldID(cls, "dir", "Ljava/lang/String;"); 544 DASSERT(AwtFileDialog::dirID != NULL); 545 CHECK_NULL(AwtFileDialog::dirID); 546 547 AwtFileDialog::fileID = env->GetFieldID(cls, "file", "Ljava/lang/String;"); 548 DASSERT(AwtFileDialog::fileID != NULL); 549 CHECK_NULL(AwtFileDialog::fileID); 550 551 AwtFileDialog::filterID = 552 env->GetFieldID(cls, "filter", "Ljava/io/FilenameFilter;"); 553 DASSERT(AwtFileDialog::filterID != NULL); 554 555 CATCH_BAD_ALLOC; 556 } 557 558 JNIEXPORT void JNICALL 559 Java_sun_awt_windows_WFileDialogPeer_setFilterString(JNIEnv *env, jclass cls, 560 jstring filterDescription) 561 { 562 TRY; 563 564 AwtFileDialog::Initialize(env, filterDescription); 565 566 CATCH_BAD_ALLOC; 567 } 568 569 JNIEXPORT void JNICALL 570 Java_sun_awt_windows_WFileDialogPeer__1show(JNIEnv *env, jobject peer) 571 { 572 TRY; 573 574 /* 575 * Fix for 4906972. 576 * 'peer' reference has to be global as it's used further in another thread. 577 */ 578 jobject peerGlobal = env->NewGlobalRef(peer); 579 580 if (!AwtToolkit::GetInstance().PostMessage(WM_AWT_INVOKE_METHOD, 581 (WPARAM)AwtFileDialog::Show, (LPARAM)peerGlobal)) { 582 env->DeleteGlobalRef(peerGlobal); 583 } 584 585 CATCH_BAD_ALLOC; 586 } 587 588 JNIEXPORT void JNICALL 589 Java_sun_awt_windows_WFileDialogPeer__1dispose(JNIEnv *env, jobject peer) 590 { 591 TRY_NO_VERIFY; 592 593 jobject peerGlobal = env->NewGlobalRef(peer); 594 595 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide, 596 (void *)peerGlobal); 597 // peerGlobal ref is deleted in _DisposeOrHide 598 599 CATCH_BAD_ALLOC; 600 } 601 602 JNIEXPORT void JNICALL 603 Java_sun_awt_windows_WFileDialogPeer__1hide(JNIEnv *env, jobject peer) 604 { 605 TRY; 606 607 jobject peerGlobal = env->NewGlobalRef(peer); 608 609 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide, 610 (void *)peerGlobal); 611 // peerGlobal ref is deleted in _DisposeOrHide 612 613 CATCH_BAD_ALLOC; 614 } 615 616 JNIEXPORT void JNICALL 617 Java_sun_awt_windows_WFileDialogPeer_toFront(JNIEnv *env, jobject peer) 618 { 619 TRY; 620 621 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToFront, 622 (void *)(env->NewGlobalRef(peer))); 623 // global ref is deleted in _ToFront 624 625 CATCH_BAD_ALLOC; 626 } 627 628 JNIEXPORT void JNICALL 629 Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv *env, jobject peer) 630 { 631 TRY; 632 633 AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToBack, 634 (void *)(env->NewGlobalRef(peer))); 635 // global ref is deleted in _ToBack 636 637 CATCH_BAD_ALLOC; 638 } 639 640 int ScaleDownX(int x, HWND hwnd) { 641 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd); 642 Devices::InstanceAccess devices; 643 AwtWin32GraphicsDevice* device = devices->GetDevice(screen); 644 return device == NULL ? x : device->ScaleDownX(x); 645 } 646 647 int ScaleDownY(int y, HWND hwnd) { 648 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd); 649 Devices::InstanceAccess devices; 650 AwtWin32GraphicsDevice* device = devices->GetDevice(screen); 651 return device == NULL ? y : device->ScaleDownY(y); 652 } 653 654 jobject AwtFileDialog::_GetLocationOnScreen(void *param) 655 { 656 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 657 658 jobject result = NULL; 659 HWND hwnd = (HWND)env->GetLongField((jobject)param, AwtComponent::hwndID); 660 661 if (::IsWindow(hwnd)) 662 { 663 RECT rect; 664 VERIFY(::GetWindowRect(hwnd, &rect)); 665 result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V", 666 ScaleDownX(rect.left, hwnd), ScaleDownY(rect.top, hwnd)); 667 } 668 669 if (result != NULL) 670 { 671 jobject resultRef = env->NewGlobalRef(result); 672 env->DeleteLocalRef(result); 673 return resultRef; 674 } 675 else 676 { 677 return NULL; 678 } 679 } 680 681 /* 682 * Class: sun_awt_windows_WFileDialogPeer 683 * Method: getLocationOnScreen 684 * Signature: ()Ljava/awt/Point; 685 */ 686 JNIEXPORT jobject JNICALL 687 Java_sun_awt_windows_WFileDialogPeer_getLocationOnScreen(JNIEnv *env, 688 jobject peer) { 689 TRY; 690 691 jobject peerRef = env->NewGlobalRef(peer); 692 jobject resultRef = (jobject)AwtToolkit::GetInstance().SyncCall( 693 (void*(*)(void*))AwtFileDialog::_GetLocationOnScreen, (void *)peerRef); 694 env->DeleteGlobalRef(peerRef); 695 696 if (resultRef != NULL) 697 { 698 jobject result = env->NewLocalRef(resultRef); 699 env->DeleteGlobalRef(resultRef); 700 return result; 701 } 702 703 return NULL; 704 705 CATCH_BAD_ALLOC_RET(NULL); 706 } 707 708 } /* extern "C" */