1 /*
2 * Copyright (c) 1996, 2018, 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 "jni_util.h"
27 #include "awt_Toolkit.h"
28 #include "awt_Dialog.h"
29 #include "awt_Window.h"
30
31 #include <windowsx.h>
32
33 #include "java_awt_Dialog.h"
34
35 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
36 */
37
38 /************************************************************************/
39 // Struct for _SetIMMOption() method
40 struct SetIMMOptionStruct {
41 jobject dialog;
42 jstring option;
43 };
44 /************************************************************************
45 * AwtDialog fields
46 */
47
48 jfieldID AwtDialog::titleID;
49 jfieldID AwtDialog::undecoratedID;
50
51 #if defined(DEBUG)
52 // counts how many nested modal dialogs are open, a sanity
53 // check to ensure the somewhat complicated disable/enable
54 // code is working properly
55 int AwtModalityNestCounter = 0;
56 #endif
57
58 HHOOK AWTModalHook;
59 HHOOK AWTMouseHook;
60
61 int VisibleModalDialogsCount = 0;
62
63 /************************************************************************
64 * AwtDialog class methods
65 */
66
AwtDialog()67 AwtDialog::AwtDialog() {
68 m_modalWnd = NULL;
69 }
70
~AwtDialog()71 AwtDialog::~AwtDialog()
72 {
73 }
74
Dispose()75 void AwtDialog::Dispose()
76 {
77 if (m_modalWnd != NULL) {
78 WmEndModal();
79 }
80 AwtFrame::Dispose();
81 }
82
GetClassName()83 LPCTSTR AwtDialog::GetClassName() {
84 return AWT_DIALOG_WINDOW_CLASS_NAME;
85 }
86
FillClassInfo(WNDCLASSEX * lpwc)87 void AwtDialog::FillClassInfo(WNDCLASSEX *lpwc)
88 {
89 AwtWindow::FillClassInfo(lpwc);
90 //Fixed 6280303: REGRESSION: Java cup icon appears in title bar of dialogs
91 // Dialog inherits icon from its owner dinamically
92 lpwc->hIcon = NULL;
93 lpwc->hIconSm = NULL;
94 }
95
96 /*
97 * Create a new AwtDialog object and window.
98 */
Create(jobject peer,jobject parent)99 AwtDialog* AwtDialog::Create(jobject peer, jobject parent)
100 {
101 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
102
103 jobject background = NULL;
104 jobject target = NULL;
105 AwtDialog* dialog = NULL;
106
107 try {
108 if (env->EnsureLocalCapacity(2) < 0) {
109 return NULL;
110 }
111
112 PDATA pData;
113 AwtWindow* awtParent = NULL;
114 HWND hwndParent = NULL;
115
116 target = env->GetObjectField(peer, AwtObject::targetID);
117 JNI_CHECK_NULL_GOTO(target, "null target", done);
118
119 if (parent != NULL) {
120 JNI_CHECK_PEER_GOTO(parent, done);
121 awtParent = (AwtWindow *)pData;
122 HWND oHWnd = awtParent->GetOverriddenHWnd();
123 hwndParent = oHWnd ? oHWnd : awtParent->GetHWnd();
124 } else {
125 // There is no way to prevent a parentless dialog from showing on
126 // the taskbar other than to specify an invisible parent and set
127 // WS_POPUP style for the dialog. Using toolkit window here. That
128 // will also excludes the dialog from appearing in window list while
129 // ALT+TAB'ing
130 // From the other point, it may be confusing when the dialog without
131 // an owner is missing on the toolbar. So, do not set any fake
132 // parent window here.
133 // hwndParent = AwtToolkit::GetInstance().GetHWnd();
134 }
135 dialog = new AwtDialog();
136
137 {
138 int colorId = COLOR_3DFACE;
139 DWORD style = WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN;
140 if (hwndParent != NULL) {
141 style |= WS_POPUP;
142 }
143 style &= ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
144 DWORD exStyle = WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME;
145
146 if (GetRTL()) {
147 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
148 if (GetRTLReadingOrder())
149 exStyle |= WS_EX_RTLREADING;
150 }
151
152
153 if (env->GetBooleanField(target, AwtDialog::undecoratedID) == JNI_TRUE) {
154 style = WS_POPUP | WS_CLIPCHILDREN;
155 exStyle = 0;
156 dialog->m_isUndecorated = TRUE;
157 }
158
159 jint x = env->GetIntField(target, AwtComponent::xID);
160 jint y = env->GetIntField(target, AwtComponent::yID);
161 jint width = env->GetIntField(target, AwtComponent::widthID);
162 jint height = env->GetIntField(target, AwtComponent::heightID);
163
164 dialog->CreateHWnd(env, L"",
165 style, exStyle,
166 x, y, width, height,
167 hwndParent,
168 NULL,
169 ::GetSysColor(COLOR_WINDOWTEXT),
170 ::GetSysColor(colorId),
171 peer);
172
173 dialog->RecalcNonClient();
174 dialog->UpdateSystemMenu();
175
176 /*
177 * Initialize icon as inherited from parent if it exists
178 */
179 if (parent != NULL) {
180 dialog->m_hIcon = awtParent->GetHIcon();
181 dialog->m_hIconSm = awtParent->GetHIconSm();
182 dialog->m_iconInherited = TRUE;
183 }
184 dialog->DoUpdateIcon();
185
186
187 background = env->GetObjectField(target,
188 AwtComponent::backgroundID);
189 if (background == NULL) {
190 JNU_CallMethodByName(env, NULL,
191 peer, "setDefaultColor", "()V");
192 }
193 }
194 } catch (...) {
195 env->DeleteLocalRef(background);
196 env->DeleteLocalRef(target);
197 throw;
198 }
199
200 done:
201 env->DeleteLocalRef(background);
202 env->DeleteLocalRef(target);
203
204 return dialog;
205 }
206
WmNcMouseDown(WPARAM hitTest,int x,int y,int button)207 MsgRouting AwtDialog::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
208 // By the request from Swing team, click on the Dialog's title should generate Ungrab
209 if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
210 m_grabbedWindow->Ungrab();
211 }
212
213 if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
214 // Dialog is non-maximizable
215 if ((button & DBL_CLICK) && hitTest == HTCAPTION) {
216 return mrConsume;
217 }
218 }
219 return AwtFrame::WmNcMouseDown(hitTest, x, y, button);
220 }
221
ModalFilterProc(int code,WPARAM wParam,LPARAM lParam)222 LRESULT CALLBACK AwtDialog::ModalFilterProc(int code,
223 WPARAM wParam, LPARAM lParam)
224 {
225 HWND hWnd = (HWND)wParam;
226 HWND blocker = AwtWindow::GetModalBlocker(hWnd);
227 if (::IsWindow(blocker) &&
228 ((code == HCBT_ACTIVATE) ||
229 (code == HCBT_SETFOCUS)))
230 {
231 // fix for 6270632: this window and all its blockers can be minimized by
232 // "show desktop" button, so we should restore them first
233 if (::IsIconic(hWnd)) {
234 ::ShowWindow(hWnd, SW_RESTORE);
235 }
236 PopupBlockers(blocker, TRUE, ::GetForegroundWindow(), FALSE);
237 // return 1 to prevent the system from allowing the operation
238 return 1;
239 }
240 return CallNextHookEx(0, code, wParam, lParam);
241 }
242
MouseHookProc(int nCode,WPARAM wParam,LPARAM lParam)243 LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode,
244 WPARAM wParam, LPARAM lParam)
245 {
246 if (nCode >= 0)
247 {
248 MOUSEHOOKSTRUCT *mhs = (MOUSEHOOKSTRUCT *)lParam;
249 HWND hWnd = mhs->hwnd;
250 if ((wParam == WM_LBUTTONDOWN) ||
251 (wParam == WM_MBUTTONDOWN) ||
252 (wParam == WM_RBUTTONDOWN) ||
253 (wParam == WM_MOUSEACTIVATE) ||
254 (wParam == WM_MOUSEWHEEL) ||
255 (wParam == WM_NCLBUTTONDOWN) ||
256 (wParam == WM_NCMBUTTONDOWN) ||
257 (wParam == WM_NCRBUTTONDOWN))
258 {
259 HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd));
260 if (::IsWindow(blocker)) {
261 BOOL onTaskbar = !(::WindowFromPoint(mhs->pt) == hWnd);
262 PopupBlockers(blocker, FALSE, ::GetForegroundWindow(), onTaskbar);
263 // return a nonzero value to prevent the system from passing
264 // the message to the target window procedure
265 return 1;
266 }
267 }
268 }
269
270 return CallNextHookEx(0, nCode, wParam, lParam);
271 }
272
273 /*
274 * The function goes through the hierarchy of the blockers and
275 * popups all the blockers. Note that the function starts from the top
276 * blocker and goes down to the blocker which is the bottom one.
277 * Using another traversal algorithm (bottom->top) may cause to flickering
278 * as the bottom blocker will cover the top blocker for a while.
279 */
PopupBlockers(HWND blocker,BOOL isModalHook,HWND prevFGWindow,BOOL onTaskbar)280 void AwtDialog::PopupBlockers(HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar)
281 {
282 HWND nextBlocker = AwtWindow::GetModalBlocker(blocker);
283 BOOL nextBlockerExists = ::IsWindow(nextBlocker);
284 if (nextBlockerExists) {
285 PopupBlockers(nextBlocker, isModalHook, prevFGWindow, onTaskbar);
286 }
287 PopupBlocker(blocker, nextBlocker, isModalHook, prevFGWindow, onTaskbar);
288 }
289
290 /*
291 * The function popups the blocker, for a non-blocked blocker we need
292 * to activate the blocker but if a blocker is blocked, then we need
293 * to change z-order of the blocker placing the blocker under the next blocker.
294 */
PopupBlocker(HWND blocker,HWND nextBlocker,BOOL isModalHook,HWND prevFGWindow,BOOL onTaskbar)295 void AwtDialog::PopupBlocker(HWND blocker, HWND nextBlocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar)
296 {
297 if (blocker == AwtToolkit::GetInstance().GetHWnd()) {
298 return;
299 }
300
301 // fix for 6494032
302 if (isModalHook && !::IsWindowVisible(blocker)) {
303 ::ShowWindow(blocker, SW_SHOWNA);
304 }
305
306 BOOL nextBlockerExists = ::IsWindow(nextBlocker);
307 UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
308
309 if (nextBlockerExists) {
310 // Fix for 6829546: if blocker is a top-most window, but window isn't, then
311 // calling ::SetWindowPos(dialog, blocker, ...) makes window top-most as well
312 BOOL topmostNextBlocker = (::GetWindowLong(nextBlocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
313 BOOL topmostBlocker = (::GetWindowLong(blocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
314 if (!topmostNextBlocker || topmostBlocker) {
315 ::SetWindowPos(blocker, nextBlocker, 0, 0, 0, 0, flags);
316 } else {
317 ::SetWindowPos(blocker, HWND_TOP, 0, 0, 0, 0, flags);
318 }
319 } else {
320 ::SetWindowPos(blocker, HWND_TOP, 0, 0, 0, 0, flags);
321 // no beep/flash if the mouse was clicked in the taskbar menu
322 // or the dialog is currently inactive
323 if (!isModalHook && !onTaskbar && (blocker == prevFGWindow)) {
324 AnimateModalBlocker(blocker);
325 }
326 ::BringWindowToTop(blocker);
327 ::SetForegroundWindow(blocker);
328 }
329 }
330
AnimateModalBlocker(HWND window)331 void AwtDialog::AnimateModalBlocker(HWND window)
332 {
333 ::MessageBeep(MB_OK);
334 // some heuristics: 3 times x 64 milliseconds
335 AwtWindow::FlashWindowEx(window, 3, 64, FLASHW_CAPTION);
336 }
337
MouseHookProc_NonTT(int nCode,WPARAM wParam,LPARAM lParam)338 LRESULT CALLBACK AwtDialog::MouseHookProc_NonTT(int nCode,
339 WPARAM wParam, LPARAM lParam)
340 {
341 static HWND lastHWnd = NULL;
342 if (nCode >= 0)
343 {
344 MOUSEHOOKSTRUCT *mhs = (MOUSEHOOKSTRUCT *)lParam;
345 HWND hWnd = mhs->hwnd;
346 HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd));
347 if (::IsWindow(blocker)) {
348 if ((wParam == WM_MOUSEMOVE) ||
349 (wParam == WM_NCMOUSEMOVE))
350 {
351 if (lastHWnd != hWnd) {
352 static HCURSOR hArrowCur = ::LoadCursor(NULL, IDC_ARROW);
353 ::SetCursor(hArrowCur);
354 lastHWnd = hWnd;
355 }
356 ::PostMessage(hWnd, WM_SETCURSOR, (WPARAM)hWnd, 0);
357 } else if (wParam == WM_MOUSELEAVE) {
358 lastHWnd = NULL;
359 }
360
361 AwtDialog::MouseHookProc(nCode, wParam, lParam);
362 return 1;
363 }
364 }
365
366 return CallNextHookEx(0, nCode, wParam, lParam);
367 }
368
Show()369 void AwtDialog::Show()
370 {
371 m_visible = true;
372 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
373
374 BOOL locationByPlatform = env->GetBooleanField(GetTarget(env), AwtWindow::locationByPlatformID);
375 if (locationByPlatform) {
376 moveToDefaultLocation();
377 }
378 EnableTranslucency(TRUE);
379 if (IsFocusableWindow() && (IsAutoRequestFocus() || IsFocusedWindowModalBlocker())) {
380 ::ShowWindow(GetHWnd(), SW_SHOW);
381 } else {
382 ::ShowWindow(GetHWnd(), SW_SHOWNA);
383 }
384 }
385
DoUpdateIcon()386 void AwtDialog::DoUpdateIcon()
387 {
388 AwtFrame::DoUpdateIcon();
389 //Workaround windows bug:
390 //Decorations are not updated correctly for owned dialogs
391 //when changing dlg with icon <--> dlg without icon
392 RECT winRect;
393 RECT clientRect;
394 ::GetWindowRect(GetHWnd(), &winRect);
395 ::GetClientRect(GetHWnd(), &clientRect);
396 ::MapWindowPoints(HWND_DESKTOP, GetHWnd(), (LPPOINT)&winRect, 2);
397 HRGN winRgn = CreateRectRgnIndirect(&winRect);
398 HRGN clientRgn = CreateRectRgnIndirect(&clientRect);
399 ::CombineRgn(winRgn, winRgn, clientRgn, RGN_DIFF);
400 ::RedrawWindow(GetHWnd(), NULL, winRgn, RDW_FRAME | RDW_INVALIDATE);
401 ::DeleteObject(winRgn);
402 ::DeleteObject(clientRgn);
403 }
404
GetEffectiveIcon(int iconType)405 HICON AwtDialog::GetEffectiveIcon(int iconType)
406 {
407 HWND hOwner = ::GetWindow(GetHWnd(), GW_OWNER);
408 BOOL isResizable = ((GetStyle() & WS_THICKFRAME) != 0);
409 BOOL smallIcon = ((iconType == ICON_SMALL) || (iconType == 2/*ICON_SMALL2*/));
410 HICON hIcon = (smallIcon) ? GetHIconSm() : GetHIcon();
411 if ((hIcon == NULL) && (isResizable || (hOwner == NULL))) {
412 //Java cup icon is not loaded in window class for dialogs
413 //It needs to be set explicitly for resizable dialogs
414 //and ownerless dialogs
415 hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm() :
416 AwtToolkit::GetInstance().GetAwtIcon();
417 } else if ((hIcon != NULL) && IsIconInherited() && !isResizable) {
418 //Non-resizable dialogs without explicitely set icon
419 //Should have no icon
420 hIcon = NULL;
421 }
422 return hIcon;
423 }
424
CheckInstallModalHook()425 void AwtDialog::CheckInstallModalHook() {
426 VisibleModalDialogsCount++;
427 if (VisibleModalDialogsCount == 1) {
428 AWTModalHook = ::SetWindowsHookEx(WH_CBT, (HOOKPROC)ModalFilterProc,
429 0, AwtToolkit::MainThread());
430 AWTMouseHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)MouseHookProc,
431 0, AwtToolkit::MainThread());
432 }
433 }
434
CheckUninstallModalHook()435 void AwtDialog::CheckUninstallModalHook() {
436 if (VisibleModalDialogsCount == 1) {
437 UnhookWindowsHookEx(AWTModalHook);
438 UnhookWindowsHookEx(AWTMouseHook);
439 }
440 VisibleModalDialogsCount--;
441 }
442
ModalPerformActivation(HWND hWnd)443 void AwtDialog::ModalPerformActivation(HWND hWnd)
444 {
445 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
446
447 AwtWindow *w = (AwtWindow *)AwtComponent::GetComponent(hWnd);
448 if ((w != NULL) && w->IsEmbeddedFrame()) {
449 jobject target = w->GetTarget(env);
450 env->CallVoidMethod(target, AwtFrame::activateEmbeddingTopLevelMID);
451 env->DeleteLocalRef(target);
452 } else {
453 ::BringWindowToTop(hWnd);
454 ::SetForegroundWindow(hWnd);
455 }
456 }
457
ModalActivateNextWindow(HWND dialogHWnd,jobject dialogTarget,jobject dialogPeer)458 void AwtDialog::ModalActivateNextWindow(HWND dialogHWnd,
459 jobject dialogTarget, jobject dialogPeer)
460 {
461 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
462
463 jboolean exc;
464 jlongArray windows = (jlongArray) JNU_CallStaticMethodByName
465 (env,
466 &exc,
467 "sun/awt/windows/WWindowPeer",
468 "getActiveWindowHandles",
469 "(Ljava/awt/Component;)[J",
470 dialogTarget).l;
471 if (exc == JNI_TRUE) {
472 throw std::bad_alloc();
473 }
474 if (windows == NULL) {
475 return;
476 }
477
478 jboolean isCopy;
479 jlong *ws = env->GetLongArrayElements(windows, &isCopy);
480 if (ws == NULL) {
481 throw std::bad_alloc();
482 }
483 int windowsCount = env->GetArrayLength(windows);
484 for (int i = windowsCount - 1; i >= 0; i--) {
485 HWND w = (HWND)ws[i];
486 if ((w != dialogHWnd) && ModalCanBeActivated(w)) {
487 AwtDialog::ModalPerformActivation(w);
488 break;
489 }
490 }
491 env->ReleaseLongArrayElements(windows, ws, 0);
492
493 env->DeleteLocalRef(windows);
494 }
495
WmShowModal()496 MsgRouting AwtDialog::WmShowModal()
497 {
498 DASSERT(::GetCurrentThreadId() == AwtToolkit::MainThread());
499
500 // fix for 6213128: release capture (got by popups, choices, etc) when
501 // modal dialog is shown
502 HWND capturer = ::GetCapture();
503 if (capturer != NULL) {
504 ::ReleaseCapture();
505 }
506
507 SendMessage(WM_AWT_COMPONENT_SHOW);
508
509 CheckInstallModalHook();
510
511 m_modalWnd = GetHWnd();
512
513 return mrConsume;
514 }
515
WmEndModal()516 MsgRouting AwtDialog::WmEndModal()
517 {
518 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
519
520 DASSERT( ::GetCurrentThreadId() == AwtToolkit::MainThread() );
521 DASSERT( ::IsWindow(m_modalWnd) );
522
523 m_modalWnd = NULL;
524
525 CheckUninstallModalHook();
526
527 HWND parentHWnd = ::GetParent(GetHWnd());
528 jobject peer = GetPeer(env);
529 jobject target = GetTarget(env);
530 if (::GetForegroundWindow() == GetHWnd()) {
531 ModalActivateNextWindow(GetHWnd(), target, peer);
532 }
533 // hide the dialog
534 SendMessage(WM_AWT_COMPONENT_HIDE);
535
536 env->DeleteLocalRef(target);
537
538 return mrConsume;
539 }
540
SetResizable(BOOL isResizable)541 void AwtDialog::SetResizable(BOOL isResizable)
542 {
543 // call superclass
544 AwtFrame::SetResizable(isResizable);
545
546 LONG style = GetStyle();
547 LONG xstyle = GetStyleEx();
548 if (isResizable || IsUndecorated()) {
549 // remove modal frame
550 xstyle &= ~WS_EX_DLGMODALFRAME;
551 } else {
552 // add modal frame
553 xstyle |= WS_EX_DLGMODALFRAME;
554 }
555 // dialogs are never minimizable/maximizable, so remove those bits
556 style &= ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
557 SetStyle(style);
558 SetStyleEx(xstyle);
559 RedrawNonClient();
560 }
561
562 // Adjust system menu so that:
563 // Non-resizable dialogs only have Move and Close items
564 // Resizable dialogs have the full system menu with
565 // Maximize, Minimize items disabled (the items
566 // get disabled by the native system).
567 // This perfectly mimics the native MS Windows behavior.
568 // Normally, Win32 dialog system menu handling is done via
569 // CreateDialog/DefDlgProc, but our dialogs are using DefWindowProc
570 // so we handle the system menu ourselves
UpdateSystemMenu()571 void AwtDialog::UpdateSystemMenu()
572 {
573 HWND hWndSelf = GetHWnd();
574 BOOL isResizable = IsResizable();
575
576 // before restoring the default menu, check if there is an
577 // InputMethodManager menu item already. Note that it assumes
578 // that the length of the InputMethodManager menu item string
579 // should not be longer than 256 bytes.
580 MENUITEMINFO mii;
581 memset(&mii, 0, sizeof(MENUITEMINFO));
582 TCHAR immItem[256];
583 BOOL hasImm;
584 mii.cbSize = sizeof(MENUITEMINFO);
585 mii.fMask = MIIM_TYPE;
586 mii.cch = sizeof(immItem);
587 mii.dwTypeData = immItem;
588 hasImm = ::GetMenuItemInfo(GetSystemMenu(hWndSelf, FALSE),
589 SYSCOMMAND_IMM, FALSE, &mii);
590
591 // restore the default menu
592 ::GetSystemMenu(hWndSelf, TRUE);
593 // now get a working copy of the menu
594 HMENU hMenuSys = GetSystemMenu(hWndSelf, FALSE);
595
596 if (!isResizable) {
597 // remove inapplicable sizing commands
598 ::DeleteMenu(hMenuSys, SC_MINIMIZE, MF_BYCOMMAND);
599 ::DeleteMenu(hMenuSys, SC_RESTORE, MF_BYCOMMAND);
600 ::DeleteMenu(hMenuSys, SC_MAXIMIZE, MF_BYCOMMAND);
601 ::DeleteMenu(hMenuSys, SC_SIZE, MF_BYCOMMAND);
602 // remove separator if only 3 items left (Move, Separator, and Close)
603 if (::GetMenuItemCount(hMenuSys) == 3) {
604 MENUITEMINFO mi;
605 memset(&mi, 0, sizeof(MENUITEMINFO));
606 mi.cbSize = sizeof(MENUITEMINFO);
607 mi.fMask = MIIM_TYPE;
608 ::GetMenuItemInfo(hMenuSys, 1, TRUE, &mi);
609 if (mi.fType & MFT_SEPARATOR) {
610 ::DeleteMenu(hMenuSys, 1, MF_BYPOSITION);
611 }
612 }
613 }
614
615 // if there was the InputMethodManager menu item, restore it.
616 if (hasImm) {
617 ::AppendMenu(hMenuSys, MF_STRING, SYSCOMMAND_IMM, immItem);
618 }
619 }
620
621 // Override WmStyleChanged to adjust system menu for sizable/non-resizable dialogs
WmStyleChanged(int wStyleType,LPSTYLESTRUCT lpss)622 MsgRouting AwtDialog::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
623 {
624 UpdateSystemMenu();
625 DoUpdateIcon();
626 return mrConsume;
627 }
628
WmSize(UINT type,int w,int h)629 MsgRouting AwtDialog::WmSize(UINT type, int w, int h)
630 {
631 if (type == SIZE_MAXIMIZED || type == SIZE_MINIMIZED
632 || (type == SIZE_RESTORED && !IsResizing()))
633 {
634 UpdateSystemMenu(); // adjust to reflect restored vs. maximized state
635 }
636
637 return AwtFrame::WmSize(type, w, h);
638 }
639
WindowProc(UINT message,WPARAM wParam,LPARAM lParam)640 LRESULT AwtDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
641 {
642 MsgRouting mr = mrDoDefault;
643 LRESULT retValue = 0L;
644
645 switch(message) {
646 case WM_AWT_DLG_SHOWMODAL:
647 mr = WmShowModal();
648 break;
649 case WM_AWT_DLG_ENDMODAL:
650 mr = WmEndModal();
651 break;
652 }
653
654 if (mr != mrConsume) {
655 retValue = AwtFrame::WindowProc(message, wParam, lParam);
656 }
657 return retValue;
658 }
659
_ShowModal(void * param)660 void AwtDialog::_ShowModal(void *param)
661 {
662 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
663
664 jobject self = (jobject)param;
665
666 AwtDialog *d = NULL;
667
668 PDATA pData;
669 JNI_CHECK_PEER_GOTO(self, ret);
670 d = (AwtDialog *)pData;
671 if (::IsWindow(d->GetHWnd())) {
672 d->SendMessage(WM_AWT_DLG_SHOWMODAL);
673 }
674 ret:
675 env->DeleteGlobalRef(self);
676 }
677
_EndModal(void * param)678 void AwtDialog::_EndModal(void *param)
679 {
680 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
681
682 jobject self = (jobject)param;
683
684 AwtDialog *d = NULL;
685
686 PDATA pData;
687 JNI_CHECK_PEER_GOTO(self, ret);
688 d = (AwtDialog *)pData;
689 if (::IsWindow(d->GetHWnd())) {
690 d->SendMessage(WM_AWT_DLG_ENDMODAL);
691 }
692 ret:
693 env->DeleteGlobalRef(self);
694 }
695
_SetIMMOption(void * param)696 void AwtDialog::_SetIMMOption(void *param)
697 {
698 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
699
700 SetIMMOptionStruct *sios = (SetIMMOptionStruct *)param;
701 jobject self = sios->dialog;
702 jstring option = sios->option;
703
704 int badAlloc = 0;
705 LPCTSTR coption;
706 LPCTSTR empty = TEXT("InputMethod");
707 AwtDialog *d = NULL;
708
709 PDATA pData;
710 JNI_CHECK_PEER_GOTO(self, ret);
711 JNI_CHECK_NULL_GOTO(option, "null IMMOption", ret);
712
713 d = (AwtDialog *)pData;
714 if (::IsWindow(d->GetHWnd()))
715 {
716 coption = JNU_GetStringPlatformChars(env, option, NULL);
717 if (coption == NULL)
718 {
719 badAlloc = 1;
720 }
721 if (!badAlloc)
722 {
723 HMENU hSysMenu = ::GetSystemMenu(d->GetHWnd(), FALSE);
724 ::AppendMenu(hSysMenu, MF_STRING, SYSCOMMAND_IMM, coption);
725
726 if (coption != empty)
727 {
728 JNU_ReleaseStringPlatformChars(env, option, coption);
729 }
730 }
731 }
732 ret:
733 env->DeleteGlobalRef(self);
734 env->DeleteGlobalRef(option);
735
736 delete sios;
737
738 if (badAlloc)
739 {
740 throw std::bad_alloc();
741 }
742 }
743
744 /************************************************************************
745 * Dialog native methods
746 */
747
748 extern "C" {
749
750 JNIEXPORT void JNICALL
Java_java_awt_Dialog_initIDs(JNIEnv * env,jclass cls)751 Java_java_awt_Dialog_initIDs(JNIEnv *env, jclass cls)
752 {
753 TRY;
754
755 /* java.awt.Dialog fields and methods */
756 AwtDialog::titleID
757 = env->GetFieldID(cls, "title", "Ljava/lang/String;");
758 DASSERT(AwtDialog::titleID != NULL);
759 CHECK_NULL(AwtDialog::titleID);
760
761 AwtDialog::undecoratedID
762 = env->GetFieldID(cls,"undecorated","Z");
763 DASSERT(AwtDialog::undecoratedID != NULL);
764 CHECK_NULL(AwtDialog::undecoratedID);
765
766 CATCH_BAD_ALLOC;
767 }
768
769 } /* extern "C" */
770
771
772 /************************************************************************
773 * DialogPeer native methods
774 */
775
776 extern "C" {
777
778 /*
779 * Class: sun_awt_windows_WDialogPeer
780 * Method: create
781 * Signature: (Lsun/awt/windows/WComponentPeer;)V
782 */
783 JNIEXPORT void JNICALL
Java_sun_awt_windows_WDialogPeer_createAwtDialog(JNIEnv * env,jobject self,jobject parent)784 Java_sun_awt_windows_WDialogPeer_createAwtDialog(JNIEnv *env, jobject self,
785 jobject parent)
786 {
787 TRY;
788
789 AwtToolkit::CreateComponent(self, parent,
790 (AwtToolkit::ComponentFactory)
791 AwtDialog::Create);
792
793 CATCH_BAD_ALLOC;
794 }
795
796 /*
797 * Class: sun_awt_windows_WDialogPeer
798 * Method: _show
799 * Signature: ()V
800 */
801 JNIEXPORT void JNICALL
Java_sun_awt_windows_WDialogPeer_showModal(JNIEnv * env,jobject self)802 Java_sun_awt_windows_WDialogPeer_showModal(JNIEnv *env, jobject self)
803 {
804 TRY;
805
806 jobject selfGlobalRef = env->NewGlobalRef(self);
807
808 AwtToolkit::GetInstance().SyncCall(AwtDialog::_ShowModal,
809 (void *)selfGlobalRef);
810 // selfGlobalRef is deleted in _ShowModal
811
812 CATCH_BAD_ALLOC;
813 }
814
815 /*
816 * Class: sun_awt_windows_WDialogPeer
817 * Method: _hide
818 * Signature: ()V
819 */
820 JNIEXPORT void JNICALL
Java_sun_awt_windows_WDialogPeer_endModal(JNIEnv * env,jobject self)821 Java_sun_awt_windows_WDialogPeer_endModal(JNIEnv *env, jobject self)
822 {
823 TRY;
824
825 jobject selfGlobalRef = env->NewGlobalRef(self);
826
827 AwtToolkit::GetInstance().SyncCall(AwtDialog::_EndModal,
828 (void *)selfGlobalRef);
829 // selfGlobalRef is deleted in _EndModal
830
831 CATCH_BAD_ALLOC;
832 }
833
834 /*
835 * Class: sun_awt_windows_WFramePeer
836 * Method: pSetIMMOption
837 * Signature: (Ljava/lang/String;)V
838 */
839 JNIEXPORT void JNICALL
Java_sun_awt_windows_WDialogPeer_pSetIMMOption(JNIEnv * env,jobject self,jstring option)840 Java_sun_awt_windows_WDialogPeer_pSetIMMOption(JNIEnv *env, jobject self,
841 jstring option)
842 {
843 TRY;
844
845 SetIMMOptionStruct *sios = new SetIMMOptionStruct;
846 sios->dialog = env->NewGlobalRef(self);
847 sios->option = (jstring)env->NewGlobalRef(option);
848
849 AwtToolkit::GetInstance().SyncCall(AwtDialog::_SetIMMOption, sios);
850 // global refs and sios are deleted in _SetIMMOption
851
852 CATCH_BAD_ALLOC;
853 }
854 } /* extern "C" */
855