| /* |
| * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| |
| #include <windowsx.h> |
| |
| #include "awt_Component.h" |
| #include "awt_Container.h" |
| #include "awt_Frame.h" |
| #include "awt_Insets.h" |
| #include "awt_Panel.h" |
| #include "awt_Toolkit.h" |
| #include "awt_Window.h" |
| #include "awt_dlls.h" |
| #include "ddrawUtils.h" |
| #include "awt_Win32GraphicsDevice.h" |
| #include "awt_BitmapUtil.h" |
| #include "awt_IconCursor.h" |
| |
| #include "java_awt_Insets.h" |
| #include <java_awt_Container.h> |
| #include <java_awt_event_ComponentEvent.h> |
| #include "sun_awt_windows_WCanvasPeer.h" |
| |
| #if !defined(__int3264) |
| typedef __int32 LONG_PTR; |
| #endif // __int3264 |
| |
| // Used for Swing's Menu/Tooltip animation Support |
| const int UNSPECIFIED = 0; |
| const int TOOLTIP = 1; |
| const int MENU = 2; |
| const int SUBMENU = 3; |
| const int POPUPMENU = 4; |
| const int COMBOBOX_POPUP = 5; |
| const int TYPES_COUNT = 6; |
| jint windowTYPES[TYPES_COUNT]; |
| |
| |
| /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. |
| */ |
| |
| /***********************************************************************/ |
| // struct for _SetAlwaysOnTop() method |
| struct SetAlwaysOnTopStruct { |
| jobject window; |
| jboolean value; |
| }; |
| // struct for _SetTitle() method |
| struct SetTitleStruct { |
| jobject window; |
| jstring title; |
| }; |
| // struct for _SetResizable() method |
| struct SetResizableStruct { |
| jobject window; |
| jboolean resizable; |
| }; |
| // struct for _UpdateInsets() method |
| struct UpdateInsetsStruct { |
| jobject window; |
| jobject insets; |
| }; |
| // struct for _ReshapeFrame() method |
| struct ReshapeFrameStruct { |
| jobject frame; |
| jint x, y; |
| jint w, h; |
| }; |
| |
| // struct for _SetIconImagesData |
| struct SetIconImagesDataStruct { |
| jobject window; |
| jintArray iconRaster; |
| jint w, h; |
| jintArray smallIconRaster; |
| jint smw, smh; |
| }; |
| |
| // struct for _SetMinSize() method |
| // and other methods setting sizes |
| struct SizeStruct { |
| jobject window; |
| jint w, h; |
| }; |
| // struct for _SetFocusableWindow() method |
| struct SetFocusableWindowStruct { |
| jobject window; |
| jboolean isFocusableWindow; |
| }; |
| // struct for _ModalDisable() method |
| struct ModalDisableStruct { |
| jobject window; |
| jlong blockerHWnd; |
| }; |
| /************************************************************************ |
| * AwtWindow fields |
| */ |
| |
| jfieldID AwtWindow::warningStringID; |
| jfieldID AwtWindow::locationByPlatformID; |
| jfieldID AwtWindow::autoRequestFocusID; |
| |
| jclass AwtWindow::wwindowPeerCls; |
| jmethodID AwtWindow::getActiveWindowsMID; |
| |
| int AwtWindow::ms_instanceCounter = 0; |
| HHOOK AwtWindow::ms_hCBTFilter; |
| AwtWindow * AwtWindow::m_grabbedWindow = NULL; |
| HWND AwtWindow::sm_retainingHierarchyZOrderInShow = NULL; |
| BOOL AwtWindow::sm_resizing = FALSE; |
| |
| /************************************************************************ |
| * AwtWindow class methods |
| */ |
| |
| AwtWindow::AwtWindow() { |
| m_sizePt.x = m_sizePt.y = 0; |
| m_owningFrameDialog = NULL; |
| m_isResizable = FALSE;//Default value is replaced after construction |
| m_minSize.x = m_minSize.y = 0; |
| m_hIcon = NULL; |
| m_hIconSm = NULL; |
| m_iconInherited = FALSE; |
| VERIFY(::SetRectEmpty(&m_insets)); |
| VERIFY(::SetRectEmpty(&m_old_insets)); |
| VERIFY(::SetRectEmpty(&m_warningRect)); |
| |
| // what's the best initial value? |
| m_screenNum = -1; |
| ms_instanceCounter++; |
| m_grabbed = FALSE; |
| m_isFocusableWindow = TRUE; |
| m_isRetainingHierarchyZOrder = FALSE; |
| m_filterFocusAndActivation = FALSE; |
| |
| if (AwtWindow::ms_instanceCounter == 1) { |
| AwtWindow::ms_hCBTFilter = |
| ::SetWindowsHookEx(WH_CBT, (HOOKPROC)AwtWindow::CBTFilter, |
| 0, AwtToolkit::MainThread()); |
| } |
| } |
| |
| AwtWindow::~AwtWindow() |
| { |
| } |
| |
| void AwtWindow::Dispose() |
| { |
| // Fix 4745575 GDI Resource Leak |
| // MSDN |
| // Before a window is destroyed (that is, before it returns from processing |
| // the WM_NCDESTROY message), an application must remove all entries it has |
| // added to the property list. The application must use the RemoveProp function |
| // to remove the entries. |
| |
| if (--AwtWindow::ms_instanceCounter == 0) { |
| ::UnhookWindowsHookEx(AwtWindow::ms_hCBTFilter); |
| } |
| |
| ::RemoveProp(GetHWnd(), ModalBlockerProp); |
| |
| if (m_grabbedWindow == this) { |
| Ungrab(); |
| } |
| if ((m_hIcon != NULL) && !m_iconInherited) { |
| ::DestroyIcon(m_hIcon); |
| } |
| if ((m_hIconSm != NULL) && !m_iconInherited) { |
| ::DestroyIcon(m_hIconSm); |
| } |
| |
| AwtCanvas::Dispose(); |
| } |
| |
| void |
| AwtWindow::Grab() { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| if (m_grabbedWindow != NULL) { |
| m_grabbedWindow->Ungrab(); |
| } |
| m_grabbed = TRUE; |
| m_grabbedWindow = this; |
| if (sm_focusedWindow == NULL && IsFocusableWindow()) { |
| // we shouldn't perform grab in this case (see 4841881 & 6539458) |
| Ungrab(); |
| } else if (GetHWnd() != sm_focusedWindow) { |
| _ToFront(env->NewGlobalRef(GetPeer(env))); |
| // Global ref was deleted in _ToFront |
| } |
| } |
| |
| void |
| AwtWindow::Ungrab(BOOL doPost) { |
| if (m_grabbed && m_grabbedWindow == this) { |
| if (doPost) { |
| PostUngrabEvent(); |
| } |
| m_grabbedWindow = NULL; |
| m_grabbed = FALSE; |
| } |
| } |
| |
| void |
| AwtWindow::Ungrab() { |
| Ungrab(TRUE); |
| } |
| |
| void AwtWindow::_Grab(void * param) { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject self = (jobject)param; |
| |
| if (env->EnsureLocalCapacity(1) < 0) |
| { |
| env->DeleteGlobalRef(self); |
| return; |
| } |
| |
| AwtWindow *p = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| p = (AwtWindow *)pData; |
| p->Grab(); |
| |
| ret: |
| env->DeleteGlobalRef(self); |
| } |
| |
| void AwtWindow::_Ungrab(void * param) { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject self = (jobject)param; |
| |
| if (env->EnsureLocalCapacity(1) < 0) |
| { |
| env->DeleteGlobalRef(self); |
| return; |
| } |
| |
| AwtWindow *p = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| p = (AwtWindow *)pData; |
| p->Ungrab(FALSE); |
| |
| ret: |
| env->DeleteGlobalRef(self); |
| } |
| |
| MsgRouting AwtWindow::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) { |
| if (m_grabbedWindow != NULL && !m_grabbedWindow->IsOneOfOwnersOf(this)) { |
| m_grabbedWindow->Ungrab(); |
| } |
| return AwtCanvas::WmNcMouseDown(hitTest, x, y, button); |
| } |
| |
| MsgRouting AwtWindow::WmWindowPosChanging(LPARAM windowPos) { |
| /* |
| * See 6178004. |
| * Some windows shouldn't trigger a change in z-order of |
| * any window from the hierarchy. |
| */ |
| if (IsRetainingHierarchyZOrder()) { |
| if (((WINDOWPOS *)windowPos)->flags & SWP_SHOWWINDOW) { |
| sm_retainingHierarchyZOrderInShow = GetHWnd(); |
| } |
| } else if (sm_retainingHierarchyZOrderInShow != NULL) { |
| HWND ancestor = ::GetAncestor(sm_retainingHierarchyZOrderInShow, GA_ROOTOWNER); |
| HWND windowAncestor = ::GetAncestor(GetHWnd(), GA_ROOTOWNER); |
| |
| if (windowAncestor == ancestor) { |
| ((WINDOWPOS *)windowPos)->flags |= SWP_NOZORDER; |
| } |
| } |
| return mrDoDefault; |
| } |
| |
| MsgRouting AwtWindow::WmWindowPosChanged(LPARAM windowPos) { |
| if (IsRetainingHierarchyZOrder() && ((WINDOWPOS *)windowPos)->flags & SWP_SHOWWINDOW) { |
| // By this time all the windows from the hierarchy are already notified about z-order change. |
| // Thus we may and we should reset the trigger in order not to affect other changes. |
| sm_retainingHierarchyZOrderInShow = NULL; |
| } |
| return mrDoDefault; |
| } |
| |
| LPCTSTR AwtWindow::GetClassName() { |
| return TEXT("SunAwtWindow"); |
| } |
| |
| void AwtWindow::FillClassInfo(WNDCLASSEX *lpwc) |
| { |
| AwtComponent::FillClassInfo(lpwc); |
| /* |
| * This line causes bug #4189244 (Swing Popup menu is not being refreshed (cleared) under a Dialog) |
| * so it's comment out (son@sparc.spb.su) |
| * |
| * lpwc->style |= CS_SAVEBITS; // improve pull-down menu performance |
| */ |
| lpwc->cbWndExtra = DLGWINDOWEXTRA; |
| } |
| |
| LRESULT CALLBACK AwtWindow::CBTFilter(int nCode, WPARAM wParam, LPARAM lParam) |
| { |
| if (nCode == HCBT_ACTIVATE || nCode == HCBT_SETFOCUS) { |
| AwtComponent *comp = AwtComponent::GetComponent((HWND)wParam); |
| |
| if (comp != NULL && comp->IsTopLevel() && !((AwtWindow*)comp)->IsFocusableWindow()) { |
| return 1; // Don't change focus/activation. |
| } |
| } |
| return ::CallNextHookEx(AwtWindow::ms_hCBTFilter, nCode, wParam, lParam); |
| } |
| |
| /* Create a new AwtWindow object and window. */ |
| AwtWindow* AwtWindow::Create(jobject self, jobject parent) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject target = NULL; |
| AwtWindow* window = NULL; |
| |
| try { |
| if (env->EnsureLocalCapacity(1) < 0) { |
| return NULL; |
| } |
| |
| AwtWindow* awtParent = NULL; |
| |
| PDATA pData; |
| if (parent != NULL) { |
| JNI_CHECK_PEER_GOTO(parent, done); |
| awtParent = (AwtWindow *)pData; |
| } |
| |
| target = env->GetObjectField(self, AwtObject::targetID); |
| JNI_CHECK_NULL_GOTO(target, "null target", done); |
| |
| window = new AwtWindow(); |
| |
| { |
| if (JNU_IsInstanceOfByName(env, target, "javax/swing/Popup$HeavyWeightWindow") > 0) { |
| window->m_isRetainingHierarchyZOrder = TRUE; |
| } |
| DWORD style = WS_CLIPCHILDREN | WS_POPUP; |
| DWORD exStyle = 0; |
| if (GetRTL()) { |
| exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; |
| if (GetRTLReadingOrder()) |
| exStyle |= WS_EX_RTLREADING; |
| } |
| if (awtParent != NULL) { |
| window->InitOwner(awtParent); |
| } else { |
| // specify WS_EX_TOOLWINDOW to remove parentless windows from taskbar |
| exStyle |= WS_EX_TOOLWINDOW; |
| } |
| window->CreateHWnd(env, L"", |
| style, exStyle, |
| 0, 0, 0, 0, |
| (awtParent != NULL) ? awtParent->GetHWnd() : NULL, |
| NULL, |
| ::GetSysColor(COLOR_WINDOWTEXT), |
| ::GetSysColor(COLOR_WINDOW), |
| self); |
| |
| jint x = env->GetIntField(target, AwtComponent::xID); |
| jint y = env->GetIntField(target, AwtComponent::yID); |
| jint width = env->GetIntField(target, AwtComponent::widthID); |
| jint height = env->GetIntField(target, AwtComponent::heightID); |
| |
| /* |
| * Initialize icon as inherited from parent if it exists |
| */ |
| if (parent != NULL) { |
| window->m_hIcon = awtParent->GetHIcon(); |
| window->m_hIconSm = awtParent->GetHIconSm(); |
| window->m_iconInherited = TRUE; |
| } |
| window->DoUpdateIcon(); |
| |
| |
| /* |
| * Reshape here instead of during create, so that a WM_NCCALCSIZE |
| * is sent. |
| */ |
| window->Reshape(x, y, width, height); |
| } |
| } catch (...) { |
| env->DeleteLocalRef(target); |
| throw; |
| } |
| |
| done: |
| env->DeleteLocalRef(target); |
| return window; |
| } |
| |
| BOOL AwtWindow::IsOneOfOwnersOf(AwtWindow * wnd) { |
| while (wnd != NULL) { |
| if (wnd == this || wnd->GetOwningFrameOrDialog() == this) return TRUE; |
| wnd = (AwtWindow*)GetComponent(::GetWindow(wnd->GetHWnd(), GW_OWNER)); |
| } |
| return FALSE; |
| } |
| |
| void AwtWindow::InitOwner(AwtWindow *owner) |
| { |
| DASSERT(owner != NULL); |
| while (owner != NULL && owner->IsSimpleWindow()) { |
| |
| HWND ownerOwnerHWND = ::GetWindow(owner->GetHWnd(), GW_OWNER); |
| if (ownerOwnerHWND == NULL) { |
| owner = NULL; |
| break; |
| } |
| owner = (AwtWindow *)AwtComponent::GetComponent(ownerOwnerHWND); |
| } |
| m_owningFrameDialog = (AwtFrame *)owner; |
| } |
| |
| void AwtWindow::moveToDefaultLocation() { |
| HWND boggy = ::CreateWindow(GetClassName(), L"BOGGY", WS_OVERLAPPED, CW_USEDEFAULT, 0 ,0, 0, |
| NULL, NULL, NULL, NULL); |
| RECT defLoc; |
| |
| // Fixed 6477497: Windows drawn off-screen on Win98, even when java.awt.Window.locationByPlatform is set |
| // Win9x does not position a window until the window is shown. |
| // The behavior is slightly opposite to the WinNT (and up), where |
| // Windows will position the window upon creation of the window. |
| // That's why we have to manually set the left & top values of |
| // the defLoc to 0 if the GetWindowRect function returns FALSE. |
| BOOL result = ::GetWindowRect(boggy, &defLoc); |
| if (!result) { |
| defLoc.left = defLoc.top = 0; |
| } |
| VERIFY(::DestroyWindow(boggy)); |
| VERIFY(::SetWindowPos(GetHWnd(), NULL, defLoc.left, defLoc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER)); |
| } |
| |
| void AwtWindow::Show() |
| { |
| m_visible = true; |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| BOOL done = false; |
| HWND hWnd = GetHWnd(); |
| |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return; |
| } |
| jobject target = GetTarget(env); |
| INT nCmdShow; |
| |
| AwtFrame* owningFrame = GetOwningFrameOrDialog(); |
| if (IsFocusableWindow() && IsAutoRequestFocus() && owningFrame != NULL && |
| ::GetForegroundWindow() == owningFrame->GetHWnd()) |
| { |
| nCmdShow = SW_SHOW; |
| } else { |
| nCmdShow = SW_SHOWNA; |
| } |
| |
| BOOL locationByPlatform = env->GetBooleanField(GetTarget(env), AwtWindow::locationByPlatformID); |
| |
| if (locationByPlatform) { |
| moveToDefaultLocation(); |
| } |
| |
| // The following block exists to support Menu/Tooltip animation for |
| // Swing programs in a way which avoids introducing any new public api into |
| // AWT or Swing. |
| // This code should eventually be replaced by a better longterm solution |
| // which might involve tagging java.awt.Window instances with a semantic |
| // property so platforms can animate/decorate/etc accordingly. |
| // |
| if ((IS_WIN98 || IS_WIN2000) && |
| JNU_IsInstanceOfByName(env, target, "com/sun/java/swing/plaf/windows/WindowsPopupWindow") > 0) |
| { |
| // need this global ref to make the class unloadable (see 6500204) |
| static jclass windowsPopupWindowCls; |
| static jfieldID windowTypeFID = NULL; |
| jint windowType = 0; |
| BOOL animateflag = FALSE; |
| BOOL fadeflag = FALSE; |
| DWORD animateStyle = 0; |
| |
| if (windowTypeFID == NULL) { |
| // Initialize Window type constants ONCE... |
| |
| jfieldID windowTYPESFID[TYPES_COUNT]; |
| jclass cls = env->GetObjectClass(target); |
| windowTypeFID = env->GetFieldID(cls, "windowType", "I"); |
| |
| windowTYPESFID[UNSPECIFIED] = env->GetStaticFieldID(cls, "UNDEFINED_WINDOW_TYPE", "I"); |
| windowTYPESFID[TOOLTIP] = env->GetStaticFieldID(cls, "TOOLTIP_WINDOW_TYPE", "I"); |
| windowTYPESFID[MENU] = env->GetStaticFieldID(cls, "MENU_WINDOW_TYPE", "I"); |
| windowTYPESFID[SUBMENU] = env->GetStaticFieldID(cls, "SUBMENU_WINDOW_TYPE", "I"); |
| windowTYPESFID[POPUPMENU] = env->GetStaticFieldID(cls, "POPUPMENU_WINDOW_TYPE", "I"); |
| windowTYPESFID[COMBOBOX_POPUP] = env->GetStaticFieldID(cls, "COMBOBOX_POPUP_WINDOW_TYPE", "I"); |
| |
| for (int i=0; i < 6; i++) { |
| windowTYPES[i] = env->GetStaticIntField(cls, windowTYPESFID[i]); |
| } |
| windowsPopupWindowCls = (jclass) env->NewGlobalRef(cls); |
| env->DeleteLocalRef(cls); |
| } |
| windowType = env->GetIntField(target, windowTypeFID); |
| |
| if (windowType == windowTYPES[TOOLTIP]) { |
| if (IS_WIN2000) { |
| SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &animateflag, 0); |
| SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &fadeflag, 0); |
| } else { |
| // use same setting as menus |
| SystemParametersInfo(SPI_GETMENUANIMATION, 0, &animateflag, 0); |
| } |
| if (animateflag) { |
| // AW_BLEND currently produces runtime parameter error |
| // animateStyle = fadeflag? AW_BLEND : AW_SLIDE | AW_VER_POSITIVE; |
| animateStyle = fadeflag? 0 : AW_SLIDE | AW_VER_POSITIVE; |
| } |
| } else if (windowType == windowTYPES[MENU] || windowType == windowTYPES[SUBMENU] || |
| windowType == windowTYPES[POPUPMENU]) { |
| SystemParametersInfo(SPI_GETMENUANIMATION, 0, &animateflag, 0); |
| if (animateflag) { |
| |
| if (IS_WIN2000) { |
| SystemParametersInfo(SPI_GETMENUFADE, 0, &fadeflag, 0); |
| if (fadeflag) { |
| // AW_BLEND currently produces runtime parameter error |
| //animateStyle = AW_BLEND; |
| } |
| } |
| if (animateStyle == 0 && !fadeflag) { |
| animateStyle = AW_SLIDE; |
| if (windowType == windowTYPES[MENU]) { |
| animateStyle |= AW_VER_POSITIVE; |
| } else if (windowType == windowTYPES[SUBMENU]) { |
| animateStyle |= AW_HOR_POSITIVE; |
| } else { /* POPUPMENU */ |
| animateStyle |= (AW_VER_POSITIVE | AW_HOR_POSITIVE); |
| } |
| } |
| } |
| } else if (windowType == windowTYPES[COMBOBOX_POPUP]) { |
| SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &animateflag, 0); |
| if (animateflag) { |
| animateStyle = AW_SLIDE | AW_VER_POSITIVE; |
| } |
| } |
| |
| if (animateStyle != 0) { |
| load_user_procs(); |
| |
| if (fn_animate_window != NULL) { |
| BOOL result = (*fn_animate_window)(hWnd, (DWORD)200, animateStyle); |
| if (result == 0) { |
| LPTSTR msgBuffer = NULL; |
| FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| FORMAT_MESSAGE_FROM_SYSTEM | |
| FORMAT_MESSAGE_IGNORE_INSERTS, |
| NULL, |
| GetLastError(), |
| MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
| (LPTSTR)&msgBuffer, // it's an output parameter when allocate buffer is used |
| 0, |
| NULL); |
| |
| if (msgBuffer == NULL) { |
| msgBuffer = TEXT("<Could not get GetLastError() message text>"); |
| } |
| _ftprintf(stderr,TEXT("AwtWindow::Show: AnimateWindow: ")); |
| _ftprintf(stderr,msgBuffer); |
| LocalFree(msgBuffer); |
| } else { |
| // WM_PAINT is not automatically sent when invoking AnimateWindow, |
| // so force an expose event |
| RECT rect; |
| ::GetWindowRect(hWnd,&rect); |
| ::ScreenToClient(hWnd, (LPPOINT)&rect); |
| ::InvalidateRect(hWnd,&rect,TRUE); |
| ::UpdateWindow(hWnd); |
| done = TRUE; |
| } |
| } |
| } |
| } |
| if (!done) { |
| ::ShowWindow(GetHWnd(), nCmdShow); |
| } |
| env->DeleteLocalRef(target); |
| } |
| |
| /* |
| * Get and return the insets for this window (container, really). |
| * Calculate & cache them while we're at it, for use by AwtGraphics |
| */ |
| BOOL AwtWindow::UpdateInsets(jobject insets) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| DASSERT(GetPeer(env) != NULL); |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return FALSE; |
| } |
| |
| // fix 4167248 : don't update insets when frame is iconified |
| // to avoid bizarre window/client rectangles |
| if (::IsIconic(GetHWnd())) { |
| return FALSE; |
| } |
| |
| /* |
| * Code to calculate insets. Stores results in frame's data |
| * members, and in the peer's Inset object. |
| */ |
| RECT outside; |
| RECT inside; |
| int extraBottomInsets = 0; |
| |
| ::GetClientRect(GetHWnd(), &inside); |
| ::GetWindowRect(GetHWnd(), &outside); |
| |
| jobject target = GetTarget(env); |
| jstring warningString = |
| (jstring)(env)->GetObjectField(target, AwtWindow::warningStringID); |
| if (warningString != NULL) { |
| ::CopyRect(&inside, &outside); |
| DefWindowProc(WM_NCCALCSIZE, FALSE, (LPARAM)&inside); |
| /* |
| * Fix for BugTraq ID 4304024. |
| * Calculate client rectangle in client coordinates. |
| */ |
| VERIFY(::OffsetRect(&inside, -inside.left, -inside.top)); |
| extraBottomInsets = ::GetSystemMetrics(SM_CYCAPTION) + |
| ((GetStyle() & WS_THICKFRAME) ? 2 : -2); |
| } |
| env->DeleteLocalRef(target); |
| env->DeleteLocalRef(warningString); |
| |
| /* Update our inset member */ |
| if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) { |
| ::MapWindowPoints(GetHWnd(), 0, (LPPOINT)&inside, 2); |
| m_insets.top = inside.top - outside.top; |
| m_insets.bottom = outside.bottom - inside.bottom + extraBottomInsets; |
| m_insets.left = inside.left - outside.left; |
| m_insets.right = outside.right - inside.right; |
| } else { |
| m_insets.top = -1; |
| } |
| if (m_insets.left < 0 || m_insets.top < 0 || |
| m_insets.right < 0 || m_insets.bottom < 0) |
| { |
| /* This window hasn't been sized yet -- use system metrics. */ |
| jobject target = GetTarget(env); |
| if (IsUndecorated() == FALSE) { |
| /* Get outer frame sizes. */ |
| LONG style = GetStyle(); |
| if (style & WS_THICKFRAME) { |
| m_insets.left = m_insets.right = |
| ::GetSystemMetrics(SM_CXSIZEFRAME); |
| m_insets.top = m_insets.bottom = |
| ::GetSystemMetrics(SM_CYSIZEFRAME); |
| } else { |
| m_insets.left = m_insets.right = |
| ::GetSystemMetrics(SM_CXDLGFRAME); |
| m_insets.top = m_insets.bottom = |
| ::GetSystemMetrics(SM_CYDLGFRAME); |
| } |
| |
| |
| /* Add in title. */ |
| m_insets.top += ::GetSystemMetrics(SM_CYCAPTION); |
| } |
| else { |
| /* fix for 4418125: Undecorated frames are off by one */ |
| /* undo the -1 set above */ |
| /* Additional fix for 5059656 */ |
| /* Also, 5089312: Window insets should be 0. */ |
| ::memset(&m_insets, 0, sizeof(m_insets)); |
| } |
| |
| /* Add in menuBar, if any. */ |
| if (JNU_IsInstanceOfByName(env, target, "java/awt/Frame") > 0 && |
| ((AwtFrame*)this)->GetMenuBar()) { |
| m_insets.top += ::GetSystemMetrics(SM_CYMENU); |
| } |
| m_insets.bottom += extraBottomInsets; |
| env->DeleteLocalRef(target); |
| } |
| |
| BOOL insetsChanged = FALSE; |
| |
| jobject peer = GetPeer(env); |
| /* Get insets into our peer directly */ |
| jobject peerInsets = (env)->GetObjectField(peer, AwtPanel::insets_ID); |
| DASSERT(!safe_ExceptionOccurred(env)); |
| if (peerInsets != NULL) { // may have been called during creation |
| (env)->SetIntField(peerInsets, AwtInsets::topID, m_insets.top); |
| (env)->SetIntField(peerInsets, AwtInsets::bottomID, |
| m_insets.bottom); |
| (env)->SetIntField(peerInsets, AwtInsets::leftID, m_insets.left); |
| (env)->SetIntField(peerInsets, AwtInsets::rightID, m_insets.right); |
| } |
| /* Get insets into the Inset object (if any) that was passed */ |
| if (insets != NULL) { |
| (env)->SetIntField(insets, AwtInsets::topID, m_insets.top); |
| (env)->SetIntField(insets, AwtInsets::bottomID, m_insets.bottom); |
| (env)->SetIntField(insets, AwtInsets::leftID, m_insets.left); |
| (env)->SetIntField(insets, AwtInsets::rightID, m_insets.right); |
| } |
| env->DeleteLocalRef(peerInsets); |
| |
| insetsChanged = !::EqualRect( &m_old_insets, &m_insets ); |
| ::CopyRect( &m_old_insets, &m_insets ); |
| |
| if (insetsChanged && DDCanReplaceSurfaces(GetHWnd())) { |
| // Since insets are changed we need to update the surfaceData object |
| // to reflect that change |
| env->CallVoidMethod(peer, AwtComponent::replaceSurfaceDataLaterMID); |
| } |
| |
| return insetsChanged; |
| } |
| |
| /** |
| * Sometimes we need the hWnd that actually owns this Window's hWnd (if |
| * there is an owner). |
| */ |
| HWND AwtWindow::GetTopLevelHWnd() |
| { |
| return m_owningFrameDialog ? m_owningFrameDialog->GetHWnd() : |
| GetHWnd(); |
| } |
| |
| /* |
| * Although this function sends ComponentEvents, it needs to be defined |
| * here because only top-level windows need to have move and resize |
| * events fired from native code. All contained windows have these events |
| * fired from common Java code. |
| */ |
| void AwtWindow::SendComponentEvent(jint eventId) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| static jclass classEvent = NULL; |
| if (classEvent == NULL) { |
| if (env->PushLocalFrame(1) < 0) |
| return; |
| classEvent = env->FindClass("java/awt/event/ComponentEvent"); |
| if (classEvent != NULL) { |
| classEvent = (jclass)env->NewGlobalRef(classEvent); |
| } |
| env->PopLocalFrame(0); |
| } |
| static jmethodID eventInitMID = NULL; |
| if (eventInitMID == NULL) { |
| eventInitMID = env->GetMethodID(classEvent, "<init>", |
| "(Ljava/awt/Component;I)V"); |
| if (eventInitMID == NULL) { |
| return; |
| } |
| } |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return; |
| } |
| jobject target = GetTarget(env); |
| jobject event = env->NewObject(classEvent, eventInitMID, |
| target, eventId); |
| DASSERT(!safe_ExceptionOccurred(env)); |
| DASSERT(event != NULL); |
| SendEvent(event); |
| |
| env->DeleteLocalRef(target); |
| env->DeleteLocalRef(event); |
| } |
| |
| void AwtWindow::SendWindowEvent(jint id, HWND opposite, |
| jint oldState, jint newState) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| static jclass wClassEvent; |
| if (wClassEvent == NULL) { |
| if (env->PushLocalFrame(1) < 0) |
| return; |
| wClassEvent = env->FindClass("java/awt/event/WindowEvent"); |
| if (wClassEvent != NULL) { |
| wClassEvent = (jclass)env->NewGlobalRef(wClassEvent); |
| } |
| env->PopLocalFrame(0); |
| if (wClassEvent == NULL) { |
| return; |
| } |
| } |
| |
| static jmethodID wEventInitMID; |
| if (wEventInitMID == NULL) { |
| wEventInitMID = |
| env->GetMethodID(wClassEvent, "<init>", |
| "(Ljava/awt/Window;ILjava/awt/Window;II)V"); |
| DASSERT(wEventInitMID); |
| if (wEventInitMID == NULL) { |
| return; |
| } |
| } |
| |
| static jclass sequencedEventCls; |
| if (sequencedEventCls == NULL) { |
| jclass sequencedEventClsLocal |
| = env->FindClass("java/awt/SequencedEvent"); |
| DASSERT(sequencedEventClsLocal); |
| if (sequencedEventClsLocal == NULL) { |
| /* exception already thrown */ |
| return; |
| } |
| sequencedEventCls = |
| (jclass)env->NewGlobalRef(sequencedEventClsLocal); |
| env->DeleteLocalRef(sequencedEventClsLocal); |
| } |
| |
| static jmethodID sequencedEventConst; |
| if (sequencedEventConst == NULL) { |
| sequencedEventConst = |
| env->GetMethodID(sequencedEventCls, "<init>", |
| "(Ljava/awt/AWTEvent;)V"); |
| } |
| |
| if (env->EnsureLocalCapacity(3) < 0) { |
| return; |
| } |
| |
| jobject target = GetTarget(env); |
| jobject jOpposite = NULL; |
| if (opposite != NULL) { |
| AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite); |
| if (awtOpposite != NULL) { |
| jOpposite = awtOpposite->GetTarget(env); |
| } |
| } |
| jobject event = env->NewObject(wClassEvent, wEventInitMID, target, id, |
| jOpposite, oldState, newState); |
| DASSERT(!safe_ExceptionOccurred(env)); |
| DASSERT(event != NULL); |
| if (jOpposite != NULL) { |
| env->DeleteLocalRef(jOpposite); jOpposite = NULL; |
| } |
| env->DeleteLocalRef(target); target = NULL; |
| |
| if (id == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS || |
| id == java_awt_event_WindowEvent_WINDOW_LOST_FOCUS) |
| { |
| jobject sequencedEvent = env->NewObject(sequencedEventCls, |
| sequencedEventConst, |
| event); |
| DASSERT(!safe_ExceptionOccurred(env)); |
| DASSERT(sequencedEvent != NULL); |
| env->DeleteLocalRef(event); |
| event = sequencedEvent; |
| } |
| |
| SendEvent(event); |
| |
| env->DeleteLocalRef(event); |
| } |
| |
| MsgRouting AwtWindow::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) |
| { |
| jint type; |
| |
| if (nState != WA_INACTIVE) { |
| ::SetFocus((sm_focusOwner == NULL || |
| AwtComponent::GetTopLevelParentForWindow(sm_focusOwner) != |
| GetHWnd()) ? NULL : sm_focusOwner); |
| type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; |
| AwtToolkit::GetInstance(). |
| InvokeFunctionLater(BounceActivation, this); |
| sm_focusedWindow = GetHWnd(); |
| } else { |
| if (m_grabbedWindow != NULL && !m_grabbedWindow->IsOneOfOwnersOf(this)) { |
| m_grabbedWindow->Ungrab(); |
| } |
| type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; |
| sm_focusedWindow = NULL; |
| } |
| |
| SendWindowEvent(type, opposite); |
| return mrConsume; |
| } |
| |
| void AwtWindow::BounceActivation(void *self) { |
| AwtWindow *wSelf = (AwtWindow *)self; |
| |
| if (::GetActiveWindow() == wSelf->GetHWnd()) { |
| AwtFrame *owner = wSelf->GetOwningFrameOrDialog(); |
| |
| if (owner != NULL) { |
| sm_suppressFocusAndActivation = TRUE; |
| ::SetActiveWindow(owner->GetHWnd()); |
| ::SetFocus(owner->GetProxyFocusOwner()); |
| sm_suppressFocusAndActivation = FALSE; |
| } |
| } |
| } |
| |
| MsgRouting AwtWindow::WmDDEnterFullScreen(HMONITOR monitor) { |
| /** |
| * DirectDraw expects to receive a top-level window. This object may |
| * be an AwtWindow instance, which has an owning AwtFrame window, or |
| * an AwtFrame object which does not have an owner. |
| * What we want is the top-level Frame hWnd, whether we were handed a |
| * top-level AwtFrame, or some owned AwtWindow. We get this by calling |
| * GetTopLevelHWnd(), which returns the hwnd of a top-level AwtFrame |
| * object (if this window has an owner) which we then pass |
| * into DirectDraw. |
| */ |
| HWND hWnd = GetTopLevelHWnd(); |
| if (!::IsWindowVisible(hWnd)) { |
| // Sometimes there are problems going into fullscreen on an owner frame |
| // that is not yet visible; make sure the FS window is visible first |
| ::ShowWindow(hWnd, SW_SHOWNA); |
| } |
| /* |
| * Fix for 6225472. |
| * Non-focusable window should be set alwaysOnTop to overlap the taskbar. |
| */ |
| AwtWindow* window = (AwtWindow *)AwtComponent::GetComponent(GetHWnd()); |
| if (window != NULL && !window->IsFocusableWindow()) { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(env, GetPeer(env), (jboolean)TRUE); |
| } |
| |
| DDEnterFullScreen(monitor, GetHWnd(), hWnd); |
| return mrDoDefault; |
| } |
| |
| MsgRouting AwtWindow::WmDDExitFullScreen(HMONITOR monitor) { |
| HWND hWnd = GetTopLevelHWnd(); |
| DDExitFullScreen(monitor, hWnd); |
| |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jboolean alwaysOnTop = JNU_CallMethodByName(env, NULL, GetTarget(env), |
| "isAlwaysOnTop", "()Z").z; |
| |
| // We should restore alwaysOnTop state as it's anyway dropped here. |
| Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(env, GetPeer(env), alwaysOnTop); |
| return mrDoDefault; |
| } |
| |
| MsgRouting AwtWindow::WmCreate() |
| { |
| return mrDoDefault; |
| } |
| |
| MsgRouting AwtWindow::WmClose() |
| { |
| SendWindowEvent(java_awt_event_WindowEvent_WINDOW_CLOSING); |
| |
| /* Rely on above notification to handle quitting as needed */ |
| return mrConsume; |
| } |
| |
| MsgRouting AwtWindow::WmDestroy() |
| { |
| SendWindowEvent(java_awt_event_WindowEvent_WINDOW_CLOSED); |
| return AwtComponent::WmDestroy(); |
| } |
| |
| MsgRouting AwtWindow::WmShowWindow(BOOL show, UINT status) |
| { |
| /* |
| * Original fix for 4810575. Modified for 6386592. |
| * If an owned window (not frame/dialog) gets disposed we should synthesize |
| * WM_ACTIVATE for its nearest owner. This is not performed by default because |
| * the owner frame/dialog is natively active. |
| */ |
| HWND hwndSelf = GetHWnd(); |
| HWND hwndParent = ::GetParent(hwndSelf); |
| |
| if (!show && IsSimpleWindow() && hwndSelf == sm_focusedWindow && |
| hwndParent != NULL && ::IsWindowVisible(hwndParent)) |
| { |
| ::PostMessage(hwndParent, WM_ACTIVATE, (WPARAM)WA_ACTIVE, (LPARAM)hwndSelf); |
| } |
| |
| //Fixed 4842599: REGRESSION: JPopupMenu not Hidden Properly After Iconified and Deiconified |
| if (show && (status == SW_PARENTOPENING)) { |
| if (!IsVisible()) { |
| return mrConsume; |
| } |
| } |
| return AwtCanvas::WmShowWindow(show, status); |
| } |
| |
| /* |
| * Override AwtComponent's move handling to first update the |
| * java AWT target's position fields directly, since Windows |
| * and below can be resized from outside of java (by user) |
| */ |
| MsgRouting AwtWindow::WmMove(int x, int y) |
| { |
| if ( ::IsIconic(GetHWnd()) ) { |
| // fixes 4065534 (robi.khan@eng) |
| // if a window is iconified we don't want to update |
| // it's target's position since minimized Win32 windows |
| // move to -32000, -32000 for whatever reason |
| // NOTE: See also AwtWindow::Reshape |
| return mrDoDefault; |
| } |
| |
| if (m_screenNum == -1) { |
| // Set initial value |
| m_screenNum = GetScreenImOn(); |
| } |
| else { |
| CheckIfOnNewScreen(); |
| } |
| |
| /* Update the java AWT target component's fields directly */ |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| if (env->EnsureLocalCapacity(1) < 0) { |
| return mrConsume; |
| } |
| jobject peer = GetPeer(env); |
| jobject target = env->GetObjectField(peer, AwtObject::targetID); |
| |
| RECT rect; |
| ::GetWindowRect(GetHWnd(), &rect); |
| |
| (env)->SetIntField(target, AwtComponent::xID, rect.left); |
| (env)->SetIntField(target, AwtComponent::yID, rect.top); |
| SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_MOVED); |
| |
| env->DeleteLocalRef(target); |
| return AwtComponent::WmMove(x, y); |
| } |
| |
| MsgRouting AwtWindow::WmGetMinMaxInfo(LPMINMAXINFO lpmmi) |
| { |
| MsgRouting r = AwtCanvas::WmGetMinMaxInfo(lpmmi); |
| if ((m_minSize.x == 0) && (m_minSize.y == 0)) { |
| return r; |
| } |
| lpmmi->ptMinTrackSize.x = m_minSize.x; |
| lpmmi->ptMinTrackSize.y = m_minSize.y; |
| return mrConsume; |
| } |
| |
| MsgRouting AwtWindow::WmSizing() |
| { |
| if (!AwtToolkit::GetInstance().IsDynamicLayoutActive()) { |
| return mrDoDefault; |
| } |
| |
| DTRACE_PRINTLN("AwtWindow::WmSizing fullWindowDragEnabled"); |
| |
| SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_RESIZED); |
| |
| HWND thisHwnd = GetHWnd(); |
| if (thisHwnd == NULL) { |
| return mrDoDefault; |
| } |
| |
| // Call WComponentPeer::dynamicallyLayoutContainer() |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jobject peer = GetPeer(env); |
| JNU_CallMethodByName(env, NULL, peer, "dynamicallyLayoutContainer", "()V"); |
| DASSERT(!safe_ExceptionOccurred(env)); |
| |
| return mrDoDefault; |
| } |
| |
| /* |
| * Override AwtComponent's size handling to first update the |
| * java AWT target's dimension fields directly, since Windows |
| * and below can be resized from outside of java (by user) |
| */ |
| MsgRouting AwtWindow::WmSize(UINT type, int w, int h) |
| { |
| if (type == SIZE_MINIMIZED) { |
| return mrDoDefault; |
| } |
| |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| if (env->EnsureLocalCapacity(1) < 0) |
| return mrDoDefault; |
| jobject target = GetTarget(env); |
| // fix 4167248 : ensure the insets are up-to-date before using |
| BOOL insetsChanged = UpdateInsets(NULL); |
| int newWidth = w + m_insets.left + m_insets.right; |
| int newHeight = h + m_insets.top + m_insets.bottom; |
| |
| (env)->SetIntField(target, AwtComponent::widthID, newWidth); |
| (env)->SetIntField(target, AwtComponent::heightID, newHeight); |
| if (!AwtWindow::IsResizing()) { |
| WindowResized(); |
| } |
| |
| env->DeleteLocalRef(target); |
| return AwtComponent::WmSize(type, w, h); |
| } |
| |
| MsgRouting AwtWindow::WmPaint(HDC) |
| { |
| PaintUpdateRgn(&m_insets); |
| return mrConsume; |
| } |
| |
| MsgRouting AwtWindow::WmSettingChange(UINT wFlag, LPCTSTR pszSection) |
| { |
| if (wFlag == SPI_SETNONCLIENTMETRICS) { |
| // user changed window metrics in |
| // Control Panel->Display->Appearance |
| // which may cause window insets to change |
| UpdateInsets(NULL); |
| |
| // [rray] fix for 4407329 - Changing Active Window Border width in display |
| // settings causes problems |
| WindowResized(); |
| Invalidate(NULL); |
| |
| return mrConsume; |
| } |
| return mrDoDefault; |
| } |
| |
| MsgRouting AwtWindow::WmNcCalcSize(BOOL fCalcValidRects, |
| LPNCCALCSIZE_PARAMS lpncsp, LRESULT& retVal) |
| { |
| MsgRouting mrRetVal = mrDoDefault; |
| |
| if (fCalcValidRects == FALSE) { |
| return mrDoDefault; |
| } |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return mrConsume; |
| } |
| jobject target = GetTarget(env); |
| jstring warningString = |
| (jstring)(env)->GetObjectField(target, AwtWindow::warningStringID); |
| if (warningString != NULL) { |
| RECT r; |
| ::CopyRect(&r, &lpncsp->rgrc[0]); |
| retVal = static_cast<UINT>(DefWindowProc(WM_NCCALCSIZE, fCalcValidRects, |
| reinterpret_cast<LPARAM>(lpncsp))); |
| |
| /* Adjust non-client area for warning banner space. */ |
| m_warningRect.left = lpncsp->rgrc[0].left; |
| m_warningRect.right = lpncsp->rgrc[0].right; |
| m_warningRect.bottom = lpncsp->rgrc[0].bottom; |
| m_warningRect.top = |
| m_warningRect.bottom - ::GetSystemMetrics(SM_CYCAPTION); |
| if (GetStyle() & WS_THICKFRAME) { |
| m_warningRect.top -= 2; |
| } else { |
| m_warningRect.top += 2; |
| } |
| |
| lpncsp->rgrc[0].bottom = (m_warningRect.top >= lpncsp->rgrc[0].top) |
| ? m_warningRect.top |
| : lpncsp->rgrc[0].top; |
| |
| /* Convert to window-relative coordinates. */ |
| ::OffsetRect(&m_warningRect, -r.left, -r.top); |
| |
| /* Notify target of Insets change. */ |
| if (HasValidRect()) { |
| UpdateInsets(NULL); |
| } |
| |
| mrRetVal = mrConsume; |
| } else { |
| // WM_NCCALCSIZE is usually in response to a resize, but |
| // also can be triggered by SetWindowPos(SWP_FRAMECHANGED), |
| // which means the insets will have changed - rnk 4/7/1998 |
| retVal = static_cast<UINT>(DefWindowProc( |
| WM_NCCALCSIZE, fCalcValidRects, reinterpret_cast<LPARAM>(lpncsp))); |
| if (HasValidRect()) { |
| UpdateInsets(NULL); |
| } |
| mrRetVal = mrConsume; |
| } |
| env->DeleteLocalRef(target); |
| env->DeleteLocalRef(warningString); |
| return mrRetVal; |
| } |
| |
| MsgRouting AwtWindow::WmNcPaint(HRGN hrgn) |
| { |
| DefWindowProc(WM_NCPAINT, (WPARAM)hrgn, 0); |
| |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return mrConsume; |
| } |
| jobject target = GetTarget(env); |
| jstring warningString = |
| (jstring)(env)->GetObjectField(target, AwtWindow::warningStringID); |
| if (warningString != NULL) { |
| RECT r; |
| ::CopyRect(&r, &m_warningRect); |
| HDC hDC = ::GetWindowDC(GetHWnd()); |
| DASSERT(hDC); |
| int iSaveDC = ::SaveDC(hDC); |
| VERIFY(::SelectClipRgn(hDC, NULL) != NULL); |
| VERIFY(::FillRect(hDC, &m_warningRect, (HBRUSH)::GetStockObject(BLACK_BRUSH))); |
| |
| if (GetStyle() & WS_THICKFRAME) { |
| /* draw edge */ |
| VERIFY(::DrawEdge(hDC, &r, EDGE_RAISED, BF_TOP)); |
| r.top += 2; |
| VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT)); |
| ::InflateRect(&r, -2, -2); |
| } |
| |
| /* draw warning text */ |
| LPWSTR text = TO_WSTRING(warningString); |
| VERIFY(::SetBkColor(hDC, ::GetSysColor(COLOR_BTNFACE)) != CLR_INVALID); |
| VERIFY(::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT)) != CLR_INVALID); |
| VERIFY(::SelectObject(hDC, ::GetStockObject(DEFAULT_GUI_FONT)) != NULL); |
| VERIFY(::SetTextAlign(hDC, TA_LEFT | TA_BOTTOM) != GDI_ERROR); |
| VERIFY(::ExtTextOutW(hDC, r.left+2, r.bottom-1, |
| ETO_CLIPPED | ETO_OPAQUE, |
| &r, text, static_cast<UINT>(wcslen(text)), NULL)); |
| VERIFY(::RestoreDC(hDC, iSaveDC)); |
| ::ReleaseDC(GetHWnd(), hDC); |
| } |
| |
| env->DeleteLocalRef(target); |
| env->DeleteLocalRef(warningString); |
| return mrConsume; |
| } |
| |
| MsgRouting AwtWindow::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) |
| { |
| // If this window is blocked by modal dialog, return HTCLIENT for any point of it. |
| // That prevents it to be moved or resized using the mouse. Disabling these |
| // actions to be launched from sysmenu is implemented by ignoring WM_SYSCOMMAND |
| if (::IsWindow(GetModalBlocker(GetHWnd()))) { |
| retVal = HTCLIENT; |
| } else { |
| retVal = DefWindowProc(WM_NCHITTEST, 0, MAKELPARAM(x, y)); |
| } |
| return mrConsume; |
| } |
| |
| MsgRouting AwtWindow::WmGetIcon(WPARAM iconType, LRESULT& retValue) |
| { |
| return mrDoDefault; |
| } |
| |
| LRESULT AwtWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) |
| { |
| MsgRouting mr = mrDoDefault; |
| LRESULT retValue = 0L; |
| |
| switch(message) { |
| case WM_GETICON: |
| mr = WmGetIcon(wParam, retValue); |
| break; |
| case WM_SYSCOMMAND: |
| //Fixed 6355340: Contents of frame are not layed out properly on maximize |
| if ((wParam & 0xFFF0) == SC_SIZE) { |
| AwtWindow::sm_resizing = TRUE; |
| mr = WmSysCommand(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); |
| if (mr != mrConsume) { |
| AwtWindow::DefWindowProc(message, wParam, lParam); |
| } |
| AwtWindow::sm_resizing = FALSE; |
| if (!AwtToolkit::GetInstance().IsDynamicLayoutActive()) { |
| WindowResized(); |
| } |
| mr = mrConsume; |
| } |
| break; |
| } |
| |
| if (mr != mrConsume) { |
| retValue = AwtCanvas::WindowProc(message, wParam, lParam); |
| } |
| return retValue; |
| } |
| |
| /* |
| * Fix for BugTraq ID 4041703: keyDown not being invoked. |
| * This method overrides AwtCanvas::HandleEvent() since |
| * an empty Window always receives the focus on the activation |
| * so we don't have to modify the behavior. |
| */ |
| MsgRouting AwtWindow::HandleEvent(MSG *msg, BOOL synthetic) |
| { |
| return AwtComponent::HandleEvent(msg, synthetic); |
| } |
| |
| void AwtWindow::WindowResized() |
| { |
| SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_RESIZED); |
| // Need to replace surfaceData on resize to catch changes to |
| // various component-related values, such as insets |
| if (DDCanReplaceSurfaces(GetHWnd())) { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| env->CallVoidMethod(m_peerObject, AwtComponent::replaceSurfaceDataLaterMID); |
| } |
| } |
| |
| BOOL CALLBACK InvalidateChildRect(HWND hWnd, LPARAM) |
| { |
| TRY; |
| |
| ::InvalidateRect(hWnd, NULL, TRUE); |
| return TRUE; |
| |
| CATCH_BAD_ALLOC_RET(FALSE); |
| } |
| |
| void AwtWindow::Invalidate(RECT* r) |
| { |
| ::InvalidateRect(GetHWnd(), NULL, TRUE); |
| ::EnumChildWindows(GetHWnd(), (WNDENUMPROC)InvalidateChildRect, 0); |
| } |
| |
| BOOL AwtWindow::IsResizable() { |
| return m_isResizable; |
| } |
| |
| void AwtWindow::SetResizable(BOOL isResizable) |
| { |
| m_isResizable = isResizable; |
| if (IsEmbeddedFrame()) { |
| return; |
| } |
| LONG style = GetStyle(); |
| LONG resizeStyle = WS_MAXIMIZEBOX; |
| |
| if (IsUndecorated() == FALSE) { |
| resizeStyle |= WS_THICKFRAME; |
| } |
| |
| if (isResizable) { |
| style |= resizeStyle; |
| } else { |
| style &= ~resizeStyle; |
| } |
| SetStyle(style); |
| RedrawNonClient(); |
| } |
| |
| // SetWindowPos flags to cause frame edge to be recalculated |
| static const UINT SwpFrameChangeFlags = |
| SWP_FRAMECHANGED | /* causes WM_NCCALCSIZE to be called */ |
| SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | |
| SWP_NOACTIVATE | SWP_NOCOPYBITS | |
| SWP_NOREPOSITION | SWP_NOSENDCHANGING; |
| |
| // |
| // Forces WM_NCCALCSIZE to be called to recalculate |
| // window border (updates insets) without redrawing it |
| // |
| void AwtWindow::RecalcNonClient() |
| { |
| ::SetWindowPos(GetHWnd(), (HWND) NULL, 0, 0, 0, 0, SwpFrameChangeFlags|SWP_NOREDRAW); |
| } |
| |
| // |
| // Forces WM_NCCALCSIZE to be called to recalculate |
| // window border (updates insets) and redraws border to match |
| // |
| void AwtWindow::RedrawNonClient() |
| { |
| ::SetWindowPos(GetHWnd(), (HWND) NULL, 0, 0, 0, 0, SwpFrameChangeFlags|SWP_ASYNCWINDOWPOS); |
| } |
| |
| int AwtWindow::GetScreenImOn() { |
| MHND hmon; |
| int scrnNum; |
| |
| hmon = ::MonitorFromWindow(GetHWnd(), MONITOR_DEFAULT_TO_PRIMARY); |
| DASSERT(hmon != NULL); |
| |
| scrnNum = AwtWin32GraphicsDevice::GetScreenFromMHND(hmon); |
| DASSERT(scrnNum > -1); |
| |
| return scrnNum; |
| } |
| |
| /* Check to see if we've been moved onto another screen. |
| * If so, update internal data, surfaces, etc. |
| */ |
| |
| void AwtWindow::CheckIfOnNewScreen() { |
| int curScrn = GetScreenImOn(); |
| |
| if (curScrn != m_screenNum) { // we've been moved |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jclass peerCls = env->GetObjectClass(m_peerObject); |
| DASSERT(peerCls); |
| |
| jmethodID draggedID = env->GetMethodID(peerCls, "draggedToNewScreen", |
| "()V"); |
| DASSERT(draggedID); |
| |
| env->CallVoidMethod(m_peerObject, draggedID); |
| m_screenNum = curScrn; |
| |
| env->DeleteLocalRef(peerCls); |
| } |
| } |
| |
| BOOL AwtWindow::IsFocusableWindow() { |
| /* |
| * For Window/Frame/Dialog to accept focus it should: |
| * - be focusable; |
| * - be not blocked by any modal blocker. |
| */ |
| BOOL focusable = m_isFocusableWindow && !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())); |
| AwtFrame *owner = GetOwningFrameOrDialog(); // NULL for Frame and Dialog |
| |
| if (owner != NULL) { |
| /* |
| * Also for Window (not Frame/Dialog) to accept focus: |
| * - its decorated parent should accept focus; |
| */ |
| focusable = focusable && owner->IsFocusableWindow(); |
| } |
| return focusable; |
| } |
| |
| void AwtWindow::SetModalBlocker(HWND window, HWND blocker) { |
| if (!::IsWindow(window)) { |
| return; |
| } |
| |
| if (::IsWindow(blocker)) { |
| ::SetProp(window, ModalBlockerProp, reinterpret_cast<HANDLE>(blocker)); |
| ::EnableWindow(window, FALSE); |
| } else { |
| ::RemoveProp(window, ModalBlockerProp); |
| AwtComponent *comp = AwtComponent::GetComponent(window); |
| // we don't expect to be called with non-java HWNDs |
| DASSERT(comp && comp->IsTopLevel()); |
| // we should not unblock disabled toplevels |
| ::EnableWindow(window, comp->isEnabled()); |
| } |
| } |
| |
| void AwtWindow::SetAndActivateModalBlocker(HWND window, HWND blocker) { |
| if (!::IsWindow(window)) { |
| return; |
| } |
| AwtWindow::SetModalBlocker(window, blocker); |
| if (::IsWindow(blocker)) { |
| // We must check for visibility. Otherwise invisible dialog will receive WM_ACTIVATE. |
| if (::IsWindowVisible(blocker)) { |
| ::BringWindowToTop(blocker); |
| ::SetForegroundWindow(blocker); |
| } |
| } |
| } |
| |
| void AwtWindow::FlashWindowEx(HWND hWnd, UINT count, DWORD timeout, DWORD flags) { |
| FLASHWINFO fi; |
| fi.cbSize = sizeof(fi); |
| fi.hwnd = hWnd; |
| fi.dwFlags = flags; |
| fi.uCount = count; |
| fi.dwTimeout = timeout; |
| ::FlashWindowEx(&fi); |
| } |
| |
| void AwtWindow::_ToFront(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject self = (jobject)param; |
| |
| AwtWindow *w = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| w = (AwtWindow *)pData; |
| if (::IsWindow(w->GetHWnd())) |
| { |
| UINT flags = SWP_NOMOVE|SWP_NOSIZE; |
| BOOL focusable = w->IsFocusableWindow(); |
| BOOL autoRequestFocus = w->IsAutoRequestFocus(); |
| |
| if (!focusable || !autoRequestFocus) |
| { |
| flags = flags|SWP_NOACTIVATE; |
| } |
| ::SetWindowPos(w->GetHWnd(), HWND_TOP, 0, 0, 0, 0, flags); |
| if (focusable && autoRequestFocus) |
| { |
| ::SetForegroundWindow(w->GetHWnd()); |
| } |
| } |
| ret: |
| env->DeleteGlobalRef(self); |
| } |
| |
| void AwtWindow::_ToBack(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject self = (jobject)param; |
| |
| AwtWindow *w = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| w = (AwtWindow *)pData; |
| if (::IsWindow(w->GetHWnd())) |
| { |
| HWND hwnd = w->GetHWnd(); |
| // if (AwtComponent::GetComponent(hwnd) == NULL) { |
| // // Window was disposed. Don't bother. |
| // return; |
| // } |
| |
| ::SetWindowPos(hwnd, HWND_BOTTOM, 0, 0 ,0, 0, |
| SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); |
| |
| // If hwnd is the foreground window or if *any* of its owners are, then |
| // we have to reset the foreground window. The reason is that when we send |
| // hwnd to back, all of its owners are sent to back as well. If any one of |
| // them is the foreground window, then it's possible that we could end up |
| // with a foreground window behind a window of another application. |
| HWND foregroundWindow = ::GetForegroundWindow(); |
| BOOL adjustForegroundWindow; |
| HWND toTest = hwnd; |
| do |
| { |
| adjustForegroundWindow = (toTest == foregroundWindow); |
| if (adjustForegroundWindow) |
| { |
| break; |
| } |
| toTest = ::GetWindow(toTest, GW_OWNER); |
| } |
| while (toTest != NULL); |
| |
| if (adjustForegroundWindow) |
| { |
| HWND foregroundSearch = hwnd, newForegroundWindow = NULL; |
| while (1) |
| { |
| foregroundSearch = ::GetNextWindow(foregroundSearch, GW_HWNDPREV); |
| if (foregroundSearch == NULL) |
| { |
| break; |
| } |
| LONG style = static_cast<LONG>(::GetWindowLongPtr(foregroundSearch, GWL_STYLE)); |
| if ((style & WS_CHILD) || !(style & WS_VISIBLE)) |
| { |
| continue; |
| } |
| |
| AwtComponent *c = AwtComponent::GetComponent(foregroundSearch); |
| if ((c != NULL) && !::IsWindow(AwtWindow::GetModalBlocker(c->GetHWnd()))) |
| { |
| newForegroundWindow = foregroundSearch; |
| } |
| } |
| if (newForegroundWindow != NULL) |
| { |
| ::SetWindowPos(newForegroundWindow, HWND_TOP, 0, 0, 0, 0, |
| SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); |
| if (((AwtWindow*)AwtComponent::GetComponent(newForegroundWindow))->IsFocusableWindow()) |
| { |
| ::SetForegroundWindow(newForegroundWindow); |
| } |
| } |
| else |
| { |
| // We *have* to set the active HWND to something new. We simply |
| // cannot risk having an active Java HWND which is behind an HWND |
| // of a native application. This really violates the Windows user |
| // experience. |
| // |
| // Windows won't allow us to set the foreground window to NULL, |
| // so we use the desktop window instead. To the user, it appears |
| // that there is no foreground window system-wide. |
| ::SetForegroundWindow(::GetDesktopWindow()); |
| } |
| } |
| } |
| ret: |
| env->DeleteGlobalRef(self); |
| } |
| |
| void AwtWindow::_SetAlwaysOnTop(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SetAlwaysOnTopStruct *sas = (SetAlwaysOnTopStruct *)param; |
| jobject self = sas->window; |
| jboolean value = sas->value; |
| |
| AwtWindow *w = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| w = (AwtWindow *)pData; |
| if (::IsWindow(w->GetHWnd())) |
| { |
| w->SendMessage(WM_AWT_SETALWAYSONTOP, (WPARAM)value, (LPARAM)w); |
| } |
| ret: |
| env->DeleteGlobalRef(self); |
| |
| delete sas; |
| } |
| |
| void AwtWindow::_SetTitle(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SetTitleStruct *sts = (SetTitleStruct *)param; |
| jobject self = sts->window; |
| jstring title = sts->title; |
| |
| AwtWindow *w = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| JNI_CHECK_NULL_GOTO(title, "null title", ret); |
| |
| w = (AwtWindow *)pData; |
| if (::IsWindow(w->GetHWnd())) |
| { |
| int length = env->GetStringLength(title); |
| WCHAR *buffer = new WCHAR[length + 1]; |
| env->GetStringRegion(title, 0, length, buffer); |
| buffer[length] = L'\0'; |
| VERIFY(::SetWindowTextW(w->GetHWnd(), buffer)); |
| delete[] buffer; |
| } |
| ret: |
| env->DeleteGlobalRef(self); |
| if (title != NULL) { |
| env->DeleteGlobalRef(title); |
| } |
| |
| delete sts; |
| } |
| |
| void AwtWindow::_SetResizable(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SetResizableStruct *srs = (SetResizableStruct *)param; |
| jobject self = srs->window; |
| jboolean resizable = srs->resizable; |
| |
| AwtWindow *w = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| w = (AwtWindow *)pData; |
| if (::IsWindow(w->GetHWnd())) |
| { |
| DASSERT(!IsBadReadPtr(w, sizeof(AwtWindow))); |
| w->SetResizable(resizable != 0); |
| } |
| ret: |
| env->DeleteGlobalRef(self); |
| |
| delete srs; |
| } |
| |
| void AwtWindow::_UpdateInsets(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| UpdateInsetsStruct *uis = (UpdateInsetsStruct *)param; |
| jobject self = uis->window; |
| jobject insets = uis->insets; |
| |
| AwtWindow *w = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| JNI_CHECK_NULL_GOTO(insets, "null insets", ret); |
| w = (AwtWindow *)pData; |
| if (::IsWindow(w->GetHWnd())) |
| { |
| w->UpdateInsets(insets); |
| } |
| ret: |
| env->DeleteGlobalRef(self); |
| env->DeleteGlobalRef(insets); |
| |
| delete uis; |
| } |
| |
| void AwtWindow::_ReshapeFrame(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| ReshapeFrameStruct *rfs = (ReshapeFrameStruct *)param; |
| jobject self = rfs->frame; |
| jint x = rfs->x; |
| jint y = rfs->y; |
| jint w = rfs->w; |
| jint h = rfs->h; |
| |
| if (env->EnsureLocalCapacity(1) < 0) |
| { |
| env->DeleteGlobalRef(self); |
| delete rfs; |
| return; |
| } |
| |
| AwtFrame *p = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| p = (AwtFrame *)pData; |
| if (::IsWindow(p->GetHWnd())) |
| { |
| jobject target = env->GetObjectField(self, AwtObject::targetID); |
| if (target != NULL) |
| { |
| // enforce tresholds before sending the event |
| // Fix for 4459064 : do not enforce thresholds for embedded frames |
| if (!p->IsEmbeddedFrame()) |
| { |
| int minWidth = ::GetSystemMetrics(SM_CXMIN); |
| int minHeight = ::GetSystemMetrics(SM_CYMIN); |
| if (w < minWidth) |
| { |
| env->SetIntField(target, AwtComponent::widthID, |
| w = minWidth); |
| } |
| if (h < minHeight) |
| { |
| env->SetIntField(target, AwtComponent::heightID, |
| h = minHeight); |
| } |
| } |
| env->DeleteLocalRef(target); |
| |
| RECT *r = new RECT; |
| ::SetRect(r, x, y, x + w, y + h); |
| p->SendMessage(WM_AWT_RESHAPE_COMPONENT, 0, (LPARAM)r); |
| // r is deleted in message handler |
| |
| // After the input method window shown, the dimension & position may not |
| // be valid until this method is called. So we need to adjust the |
| // IME candidate window position for the same reason as commented on |
| // awt_Frame.cpp Show() method. |
| if (p->isInputMethodWindow() && ::IsWindowVisible(p->GetHWnd())) { |
| p->AdjustCandidateWindowPos(); |
| } |
| } |
| else |
| { |
| JNU_ThrowNullPointerException(env, "null target"); |
| } |
| } |
| ret: |
| env->DeleteGlobalRef(self); |
| |
| delete rfs; |
| } |
| |
| /* |
| * This is AwtWindow-specific function that is not intended for reusing |
| */ |
| HICON CreateIconFromRaster(JNIEnv* env, jintArray iconRaster, jint w, jint h) |
| { |
| HBITMAP mask = NULL; |
| HBITMAP image = NULL; |
| HICON icon = NULL; |
| if (iconRaster != NULL) { |
| int* iconRasterBuffer = NULL; |
| try { |
| iconRasterBuffer = (int *)env->GetPrimitiveArrayCritical(iconRaster, 0); |
| |
| JNI_CHECK_NULL_GOTO(iconRasterBuffer, "iconRaster data", done); |
| |
| mask = BitmapUtil::CreateTransparencyMaskFromARGB(w, h, iconRasterBuffer); |
| image = BitmapUtil::CreateV4BitmapFromARGB(w, h, iconRasterBuffer); |
| } catch (...) { |
| if (iconRasterBuffer != NULL) { |
| env->ReleasePrimitiveArrayCritical(iconRaster, iconRasterBuffer, 0); |
| } |
| throw; |
| } |
| if (iconRasterBuffer != NULL) { |
| env->ReleasePrimitiveArrayCritical(iconRaster, iconRasterBuffer, 0); |
| } |
| } |
| if (mask && image) { |
| ICONINFO icnInfo; |
| memset(&icnInfo, 0, sizeof(ICONINFO)); |
| icnInfo.hbmMask = mask; |
| icnInfo.hbmColor = image; |
| icnInfo.fIcon = TRUE; |
| icon = ::CreateIconIndirect(&icnInfo); |
| } |
| if (image) { |
| destroy_BMP(image); |
| } |
| if (mask) { |
| destroy_BMP(mask); |
| } |
| done: |
| return icon; |
| } |
| |
| void AwtWindow::SetIconData(JNIEnv* env, jintArray iconRaster, jint w, jint h, |
| jintArray smallIconRaster, jint smw, jint smh) |
| { |
| HICON hOldIcon = NULL; |
| HICON hOldIconSm = NULL; |
| //Destroy previous icon if it isn't inherited |
| if ((m_hIcon != NULL) && !m_iconInherited) { |
| hOldIcon = m_hIcon; |
| } |
| m_hIcon = NULL; |
| if ((m_hIconSm != NULL) && !m_iconInherited) { |
| hOldIconSm = m_hIconSm; |
| } |
| m_hIconSm = NULL; |
| m_hIcon = CreateIconFromRaster(env, iconRaster, w, h); |
| m_hIconSm = CreateIconFromRaster(env, smallIconRaster, smw, smh); |
| |
| m_iconInherited = (m_hIcon == NULL); |
| if (m_iconInherited) { |
| HWND hOwner = ::GetWindow(GetHWnd(), GW_OWNER); |
| AwtWindow* owner = (AwtWindow *)AwtComponent::GetComponent(hOwner); |
| if (owner != NULL) { |
| m_hIcon = owner->GetHIcon(); |
| m_hIconSm = owner->GetHIconSm(); |
| } else { |
| m_iconInherited = FALSE; |
| } |
| } |
| DoUpdateIcon(); |
| EnumThreadWindows(AwtToolkit::MainThread(), UpdateOwnedIconCallback, (LPARAM)this); |
| if (hOldIcon != NULL) { |
| DestroyIcon(hOldIcon); |
| } |
| if (hOldIconSm != NULL) { |
| DestroyIcon(hOldIconSm); |
| } |
| } |
| |
| BOOL AwtWindow::UpdateOwnedIconCallback(HWND hWndOwned, LPARAM lParam) |
| { |
| HWND hWndOwner = ::GetWindow(hWndOwned, GW_OWNER); |
| AwtWindow* owner = (AwtWindow*)lParam; |
| if (hWndOwner == owner->GetHWnd()) { |
| AwtComponent* comp = AwtComponent::GetComponent(hWndOwned); |
| if (comp != NULL && comp->IsTopLevel()) { |
| AwtWindow* owned = (AwtWindow *)comp; |
| if (owned->m_iconInherited) { |
| owned->m_hIcon = owner->m_hIcon; |
| owned->m_hIconSm = owner->m_hIconSm; |
| owned->DoUpdateIcon(); |
| EnumThreadWindows(AwtToolkit::MainThread(), UpdateOwnedIconCallback, (LPARAM)owned); |
| } |
| } |
| } |
| return TRUE; |
| } |
| |
| void AwtWindow::DoUpdateIcon() |
| { |
| //Does nothing for windows, is overriden for frames and dialogs |
| } |
| |
| void AwtWindow::_SetIconImagesData(void * param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SetIconImagesDataStruct* s = (SetIconImagesDataStruct*)param; |
| jobject self = s->window; |
| |
| jintArray iconRaster = s->iconRaster; |
| jintArray smallIconRaster = s->smallIconRaster; |
| |
| AwtWindow *window = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| // ok to pass null raster: default AWT icon |
| |
| window = (AwtWindow*)pData; |
| if (::IsWindow(window->GetHWnd())) |
| { |
| window->SetIconData(env, iconRaster, s->w, s->h, smallIconRaster, s->smw, s->smh); |
| |
| } |
| |
| ret: |
| env->DeleteGlobalRef(self); |
| env->DeleteGlobalRef(iconRaster); |
| env->DeleteGlobalRef(smallIconRaster); |
| delete s; |
| } |
| |
| void AwtWindow::_SetMinSize(void* param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SizeStruct *ss = (SizeStruct *)param; |
| jobject self = ss->window; |
| jint w = ss->w; |
| jint h = ss->h; |
| //Perform size setting |
| AwtWindow *window = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| window = (AwtWindow *)pData; |
| window->m_minSize.x = w; |
| window->m_minSize.y = h; |
| ret: |
| env->DeleteGlobalRef(self); |
| delete ss; |
| } |
| |
| jint AwtWindow::_GetScreenImOn(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject self = (jobject)param; |
| |
| // It's entirely possible that our native resources have been destroyed |
| // before our java peer - if we're dispose()d, for instance. |
| // Alert caller w/ IllegalComponentStateException. |
| if (self == NULL) { |
| JNU_ThrowByName(env, "java/awt/IllegalComponentStateException", |
| "Peer null in JNI"); |
| return 0; |
| } |
| PDATA pData = JNI_GET_PDATA(self); |
| if (pData == NULL) { |
| JNU_ThrowByName(env, "java/awt/IllegalComponentStateException", |
| "Native resources unavailable"); |
| env->DeleteGlobalRef(self); |
| return 0; |
| } |
| |
| jint result = 0; |
| AwtWindow *w = (AwtWindow *)pData; |
| if (::IsWindow(w->GetHWnd())) |
| { |
| result = (jint)w->GetScreenImOn(); |
| } |
| |
| env->DeleteGlobalRef(self); |
| |
| return result; |
| } |
| |
| void AwtWindow::_SetFocusableWindow(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| SetFocusableWindowStruct *sfws = (SetFocusableWindowStruct *)param; |
| jobject self = sfws->window; |
| jboolean isFocusableWindow = sfws->isFocusableWindow; |
| |
| AwtWindow *window = NULL; |
| |
| PDATA pData; |
| JNI_CHECK_PEER_GOTO(self, ret); |
| window = (AwtWindow *)pData; |
| |
| window->m_isFocusableWindow = isFocusableWindow; |
| |
| if (IS_WIN2000) { |
| if (!window->m_isFocusableWindow) { |
| LONG isPopup = window->GetStyle() & WS_POPUP; |
| window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | AWT_WS_EX_NOACTIVATE); |
| } else { |
| window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~AWT_WS_EX_NOACTIVATE); |
| } |
| } |
| |
| ret: |
| env->DeleteGlobalRef(self); |
| delete sfws; |
| } |
| |
| void AwtWindow::_ModalDisable(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| ModalDisableStruct *mds = (ModalDisableStruct *)param; |
| jobject self = mds->window; |
| HWND blockerHWnd = (HWND)mds->blockerHWnd; |
| |
| AwtWindow *window = NULL; |
| HWND windowHWnd = 0; |
| |
| JNI_CHECK_NULL_GOTO(self, "peer", ret); |
| PDATA pData = JNI_GET_PDATA(self); |
| if (pData == NULL) { |
| env->DeleteGlobalRef(self); |
| delete mds; |
| return; |
| } |
| |
| window = (AwtWindow *)pData; |
| windowHWnd = window->GetHWnd(); |
| if (::IsWindow(windowHWnd)) { |
| AwtWindow::SetAndActivateModalBlocker(windowHWnd, blockerHWnd); |
| } |
| |
| ret: |
| env->DeleteGlobalRef(self); |
| |
| delete mds; |
| } |
| |
| void AwtWindow::_ModalEnable(void *param) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| jobject self = (jobject)param; |
| |
| AwtWindow *window = NULL; |
| HWND windowHWnd = 0; |
| |
| JNI_CHECK_NULL_GOTO(self, "peer", ret); |
| PDATA pData = JNI_GET_PDATA(self); |
| if (pData == NULL) { |
| env->DeleteGlobalRef(self); |
| return; |
| } |
| |
| window = (AwtWindow *)pData; |
| windowHWnd = window->GetHWnd(); |
| if (::IsWindow(windowHWnd)) { |
| AwtWindow::SetModalBlocker(windowHWnd, NULL); |
| } |
| |
| ret: |
| env->DeleteGlobalRef(self); |
| } |
| |
| /* |
| * Fixed 6353381: it's improved fix for 4792958 |
| * which was backed-out to avoid 5059656 |
| */ |
| BOOL AwtWindow::HasValidRect() |
| { |
| RECT inside; |
| RECT outside; |
| |
| if (::IsIconic(GetHWnd())) { |
| return FALSE; |
| } |
| |
| ::GetClientRect(GetHWnd(), &inside); |
| ::GetWindowRect(GetHWnd(), &outside); |
| |
| BOOL isZeroClientArea = (inside.right == 0 && inside.bottom == 0); |
| BOOL isInvalidLocation = ((outside.left == -32000 && outside.top == -32000) || // Win2k && WinXP |
| (outside.left == 32000 && outside.top == 32000) || // Win95 && Win98 |
| (outside.left == 3000 && outside.top == 3000)); // Win95 && Win98 |
| |
| // the bounds correspond to iconic state |
| if (isZeroClientArea && isInvalidLocation) |
| { |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| extern "C" { |
| |
| /* |
| * Class: java_awt_Window |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_java_awt_Window_initIDs(JNIEnv *env, jclass cls) |
| { |
| TRY; |
| |
| AwtWindow::warningStringID = |
| env->GetFieldID(cls, "warningString", "Ljava/lang/String;"); |
| AwtWindow::locationByPlatformID = |
| env->GetFieldID(cls, "locationByPlatform", "Z"); |
| AwtWindow::autoRequestFocusID = |
| env->GetFieldID(cls, "autoRequestFocus", "Z"); |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| } /* extern "C" */ |
| |
| |
| /************************************************************************ |
| * WindowPeer native methods |
| */ |
| |
| extern "C" { |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_initIDs(JNIEnv *env, jclass cls) |
| { |
| TRY; |
| |
| AwtWindow::wwindowPeerCls = cls; |
| AwtWindow::getActiveWindowsMID = |
| env->GetStaticMethodID(cls, "getActiveWindowHandles", "()[J"); |
| DASSERT(AwtWindow::getActiveWindowsMID != NULL); |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: toFront |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer__1toFront(JNIEnv *env, jobject self) |
| { |
| TRY; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_ToFront, |
| env->NewGlobalRef(self)); |
| // global ref is deleted in _ToFront() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: toBack |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_toBack(JNIEnv *env, jobject self) |
| { |
| TRY; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_ToBack, |
| env->NewGlobalRef(self)); |
| // global ref is deleted in _ToBack() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: setAlwaysOnTop |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(JNIEnv *env, jobject self, |
| jboolean value) |
| { |
| TRY; |
| |
| SetAlwaysOnTopStruct *sas = new SetAlwaysOnTopStruct; |
| sas->window = env->NewGlobalRef(self); |
| sas->value = value; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetAlwaysOnTop, sas); |
| // global ref and sas are deleted in _SetAlwaysOnTop |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: _setTitle |
| * Signature: (Ljava/lang/String;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer__1setTitle(JNIEnv *env, jobject self, |
| jstring title) |
| { |
| TRY; |
| |
| SetTitleStruct *sts = new SetTitleStruct; |
| sts->window = env->NewGlobalRef(self); |
| sts->title = (jstring)env->NewGlobalRef(title); |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetTitle, sts); |
| /// global refs and sts are deleted in _SetTitle() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: _setResizable |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer__1setResizable(JNIEnv *env, jobject self, |
| jboolean resizable) |
| { |
| TRY; |
| |
| SetResizableStruct *srs = new SetResizableStruct; |
| srs->window = env->NewGlobalRef(self); |
| srs->resizable = resizable; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetResizable, srs); |
| // global ref and srs are deleted in _SetResizable |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: create |
| * Signature: (Lsun/awt/windows/WComponentPeer;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_createAwtWindow(JNIEnv *env, jobject self, |
| jobject parent) |
| { |
| TRY; |
| |
| PDATA pData; |
| // JNI_CHECK_PEER_RETURN(parent); |
| AwtToolkit::CreateComponent(self, parent, |
| (AwtToolkit::ComponentFactory) |
| AwtWindow::Create); |
| JNI_CHECK_PEER_CREATION_RETURN(self); |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: updateInsets |
| * Signature: (Ljava/awt/Insets;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_updateInsets(JNIEnv *env, jobject self, |
| jobject insets) |
| { |
| TRY; |
| |
| UpdateInsetsStruct *uis = new UpdateInsetsStruct; |
| uis->window = env->NewGlobalRef(self); |
| uis->insets = env->NewGlobalRef(insets); |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_UpdateInsets, uis); |
| // global refs and uis are deleted in _UpdateInsets() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: reshapeFrame |
| * Signature: (IIII)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_reshapeFrame(JNIEnv *env, jobject self, |
| jint x, jint y, jint w, jint h) |
| { |
| TRY; |
| |
| ReshapeFrameStruct *rfs = new ReshapeFrameStruct; |
| rfs->frame = env->NewGlobalRef(self); |
| rfs->x = x; |
| rfs->y = y; |
| rfs->w = w; |
| rfs->h = h; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_ReshapeFrame, rfs); |
| // global ref and rfs are deleted in _ReshapeFrame() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: getSysMinWidth |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WWindowPeer_getSysMinWidth(JNIEnv *env, jclass self) |
| { |
| TRY; |
| |
| return ::GetSystemMetrics(SM_CXMIN); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: getSysMinHeight |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WWindowPeer_getSysMinHeight(JNIEnv *env, jclass self) |
| { |
| TRY; |
| |
| return ::GetSystemMetrics(SM_CYMIN); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: getSysIconHeight |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WWindowPeer_getSysIconHeight(JNIEnv *env, jclass self) |
| { |
| TRY; |
| |
| return ::GetSystemMetrics(SM_CYICON); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: getSysIconWidth |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WWindowPeer_getSysIconWidth(JNIEnv *env, jclass self) |
| { |
| TRY; |
| |
| return ::GetSystemMetrics(SM_CXICON); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: getSysSmIconHeight |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WWindowPeer_getSysSmIconHeight(JNIEnv *env, jclass self) |
| { |
| TRY; |
| |
| return ::GetSystemMetrics(SM_CYSMICON); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: getSysSmIconWidth |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WWindowPeer_getSysSmIconWidth(JNIEnv *env, jclass self) |
| { |
| TRY; |
| |
| return ::GetSystemMetrics(SM_CXSMICON); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: setIconImagesData |
| * Signature: ([I)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_setIconImagesData(JNIEnv *env, jobject self, |
| jintArray iconRaster, jint w, jint h, |
| jintArray smallIconRaster, jint smw, jint smh) |
| { |
| TRY; |
| |
| SetIconImagesDataStruct *sims = new SetIconImagesDataStruct; |
| |
| sims->window = env->NewGlobalRef(self); |
| sims->iconRaster = (jintArray)env->NewGlobalRef(iconRaster); |
| sims->w = w; |
| sims->h = h; |
| sims->smallIconRaster = (jintArray)env->NewGlobalRef(smallIconRaster); |
| sims->smw = smw; |
| sims->smh = smh; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetIconImagesData, sims); |
| // global refs and sims are deleted in _SetIconImagesData() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: setMinSize |
| * Signature: (Lsun/awt/windows/WWindowPeer;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_setMinSize(JNIEnv *env, jobject self, |
| jint w, jint h) |
| { |
| TRY; |
| |
| SizeStruct *ss = new SizeStruct; |
| ss->window = env->NewGlobalRef(self); |
| ss->w = w; |
| ss->h = h; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetMinSize, ss); |
| // global refs and mds are deleted in _SetMinSize |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: getScreenImOn |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WWindowPeer_getScreenImOn(JNIEnv *env, jobject self) |
| { |
| TRY; |
| |
| return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall( |
| (void *(*)(void *))AwtWindow::_GetScreenImOn, |
| env->NewGlobalRef(self)))); |
| // global ref is deleted in _GetScreenImOn() |
| |
| CATCH_BAD_ALLOC_RET(-1); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: modalDisable |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_modalDisable(JNIEnv *env, jobject self, |
| jobject blocker, jlong blockerHWnd) |
| { |
| TRY; |
| |
| ModalDisableStruct *mds = new ModalDisableStruct; |
| mds->window = env->NewGlobalRef(self); |
| mds->blockerHWnd = blockerHWnd; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_ModalDisable, mds); |
| // global ref and mds are deleted in _ModalDisable |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: modalEnable |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_modalEnable(JNIEnv *env, jobject self, jobject blocker) |
| { |
| TRY; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_ModalEnable, |
| env->NewGlobalRef(self)); |
| // global ref is deleted in _ModalEnable |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WWindowPeer |
| * Method: setFocusableWindow |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_setFocusableWindow(JNIEnv *env, jobject self, jboolean isFocusableWindow) |
| { |
| TRY; |
| |
| SetFocusableWindowStruct *sfws = new SetFocusableWindowStruct; |
| sfws->window = env->NewGlobalRef(self); |
| sfws->isFocusableWindow = isFocusableWindow; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetFocusableWindow, sfws); |
| // global ref and sfws are deleted in _SetFocusableWindow() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_nativeGrab(JNIEnv *env, jobject self) |
| { |
| TRY; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_Grab, env->NewGlobalRef(self)); |
| // global ref is deleted in _Grab() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WWindowPeer_nativeUngrab(JNIEnv *env, jobject self) |
| { |
| TRY; |
| |
| AwtToolkit::GetInstance().SyncCall(AwtWindow::_Ungrab, env->NewGlobalRef(self)); |
| // global ref is deleted in _Ungrab() |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| } /* extern "C" */ |