nsresult os2FrameWindow::SetSizeMode(int32_t aMode) { int32_t previousMode; mOwner->GetSizeMode(&previousMode); // save the new state nsresult rv = mOwner->nsBaseWidget::SetSizeMode(aMode); if (!NS_SUCCEEDED(rv)) { return rv; } // Minimized windows would get restored involuntarily if we fired an // NS_ACTIVATE when the user clicks on them. Instead, we defer the // activation event until the window has explicitly been restored. if (previousMode == nsSizeMode_Minimized && previousMode != aMode) { DEBUGFOCUS(deferred NS_ACTIVATE); ActivateTopLevelWidget(); } ULONG ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE); switch (aMode) { case nsSizeMode_Normal: if (ulStyle & (WS_MAXIMIZED | WS_MINIMIZED)) { WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE); } break; case nsSizeMode_Minimized: if (!(ulStyle & WS_MINIMIZED)) { WinSetWindowPos(mFrameWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_MINIMIZE | SWP_ZORDER | SWP_DEACTIVATE); } break; case nsSizeMode_Maximized: // Don't permit the window to be maximized when in // fullscreen mode because it won't be restored correctly. if (!(ulStyle & WS_MAXIMIZED) && !mChromeHidden) { WinSetWindowPos(mFrameWnd, HWND_TOP, 0, 0, 0, 0, SWP_MAXIMIZE | SWP_ZORDER); } break; // 'nsSizeMode_Fullscreen' is defined but isn't used (as of v1.9.3) case nsSizeMode_Fullscreen: default: break; } return NS_OK; }
void os2FrameWindow::ActivateTopLevelWidget() { // Don't fire event if we're minimized or else the window will // be restored as soon as the user clicks on it. When the user // explicitly restores it, SetSizeMode() will call this method. if (mNeedActivation) { if (mOwner->SizeMode() != nsSizeMode_Minimized) { mNeedActivation = false; DEBUGFOCUS(NS_ACTIVATE); mOwner->DispatchActivationEvent(NS_ACTIVATE); } } return; }
void nsFrameWindow::ActivateTopLevelWidget() { // Don't fire event if we're minimized or else the window will // be restored as soon as the user clicks on it. When the user // explicitly restores it, SetSizeMode() will call this method. if (mNeedActivation) { PRInt32 sizeMode; GetSizeMode(&sizeMode); if (sizeMode != nsSizeMode_Minimized) { mNeedActivation = PR_FALSE; DEBUGFOCUS(NS_ACTIVATE); DispatchFocus(NS_ACTIVATE); } } return; }
nsresult os2FrameWindow::SetSizeMode(PRInt32 aMode) { PRInt32 previousMode; mOwner->GetSizeMode(&previousMode); // save the new state nsresult rv = mOwner->nsBaseWidget::SetSizeMode(aMode); // Minimized windows would get restored involuntarily if we fired an // NS_ACTIVATE when the user clicks on them. Instead, we defer the // activation event until the window has explicitly been restored. if (previousMode == nsSizeMode_Minimized && previousMode != aMode) { DEBUGFOCUS(deferred NS_ACTIVATE); ActivateTopLevelWidget(); } // nothing to do in these cases if (!NS_SUCCEEDED(rv) || !mChromeHidden || aMode == nsSizeMode_Maximized) { return rv; } ULONG ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE); // act on the request if the frame isn't already in the requested state if (aMode == nsSizeMode_Minimized) { if (!(ulStyle & WS_MINIMIZED)) { WinSetWindowPos(mFrameWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_MINIMIZE | SWP_ZORDER | SWP_DEACTIVATE); } } else if (ulStyle & (WS_MAXIMIZED | WS_MINIMIZED)) { WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE); } return NS_OK; }
HWND os2FrameWindow::CreateFrameWindow(nsWindow* aParent, HWND aParentWnd, const nsIntRect& aRect, nsWindowType aWindowType, nsBorderStyle aBorderStyle) { // Create a frame window with a MozillaWindowClass window as its client. HWND hClient; uint32_t fcfFlags = GetFCFlags(aWindowType, aBorderStyle); mFrameWnd = WinCreateStdWindow(HWND_DESKTOP, 0, (ULONG*)&fcfFlags, kWindowClassName, "Title", WS_CLIPCHILDREN, NULLHANDLE, 0, &hClient); if (!mFrameWnd) { return 0; } // Hide from the Window List until shown. SetWindowListVisibility(false); // This prevents a modal dialog from being covered by its disabled parent. if (aParentWnd != HWND_DESKTOP) { WinSetOwner(mFrameWnd, aParentWnd); } // Get the frame control HWNDs for use by fullscreen mode. mTitleBar = WinWindowFromID(mFrameWnd, FID_TITLEBAR); mSysMenu = WinWindowFromID(mFrameWnd, FID_SYSMENU); mMinMax = WinWindowFromID(mFrameWnd, FID_MINMAX); // Calc the size of a frame needed to contain a client area of the // specified width & height. Without this, eWindowType_dialog windows // will be truncated (toplevel windows will still display correctly). RECTL rcl = {0, 0, aRect.width, aRect.height}; WinCalcFrameRect(mFrameWnd, &rcl, FALSE); mFrameBounds = nsIntRect(aRect.x, aRect.y, rcl.xRight-rcl.xLeft, rcl.yTop-rcl.yBottom); // Move & resize the frame. int32_t pmY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - mFrameBounds.y - mFrameBounds.height; WinSetWindowPos(mFrameWnd, 0, mFrameBounds.x, pmY, mFrameBounds.width, mFrameBounds.height, SWP_SIZE | SWP_MOVE); // Store the client's bounds. For windows with resizable borders, // the width includes the width of the frame controls (minmax, etc.). SWP swp; WinQueryWindowPos(hClient, &swp); mOwner->SetBounds(nsIntRect(swp.x, mFrameBounds.height - swp.y - swp.cy, swp.cx, swp.cy)); // Subclass the frame. mPrevFrameProc = WinSubclassWindow(mFrameWnd, fnwpFrame); WinSetWindowPtr(mFrameWnd, QWL_USER, this); DEBUGFOCUS(Create os2FrameWindow); return hClient; }
MRESULT os2FrameWindow::ProcessFrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2) { MRESULT mresult = 0; bool isDone = false; switch (msg) { case WM_WINDOWPOSCHANGED: { PSWP pSwp = (PSWP)mp1; // Don't save the new position or size of a minimized // window, or else it won't be restored correctly. if (pSwp->fl & SWP_MOVE && !(pSwp->fl & SWP_MINIMIZE)) { POINTL ptl = { pSwp->x, pSwp->y + pSwp->cy }; ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - ptl.y; mFrameBounds.x = ptl.x; mFrameBounds.y = ptl.y; mOwner->DispatchMoveEvent(ptl.x, ptl.y); } // Save the frame's bounds, then call the default wndproc // so the client can handle its WM_WINDOWPOSCHANGED msg now. if (pSwp->fl & SWP_SIZE && !(pSwp->fl & SWP_MINIMIZE)) { mFrameBounds.width = pSwp->cx; mFrameBounds.height = pSwp->cy; mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2); isDone = true; } if (pSwp->fl & (SWP_MAXIMIZE | SWP_MINIMIZE | SWP_RESTORE)) { if (mOwner->mWidgetListener) { nsSizeMode mode; if (pSwp->fl & SWP_MAXIMIZE) { mode = nsSizeMode_Maximized; } else if (pSwp->fl & SWP_MINIMIZE) { mode = nsSizeMode_Minimized; } else { mode = nsSizeMode_Normal; } mOwner->mWidgetListener->SizeModeChanged(mode); } } break; } // A frame window in kiosk/fullscreen mode must have its frame // controls reattached before it's minimized & detached after it's // restored. If this doesn't happen at the correct times, clicking // on the icon won't restore it, the sysmenu will have the wrong // items, and/or the minmax button will have the wrong buttons. case WM_ADJUSTWINDOWPOS: if (mChromeHidden && ((PSWP)mp1)->fl & SWP_MINIMIZE) { WinSetParent(mTitleBar, mFrameWnd, TRUE); WinSetParent(mSysMenu, mFrameWnd, TRUE); WinSetParent(mMinMax, mFrameWnd, TRUE); } break; case WM_ADJUSTFRAMEPOS: if (mChromeHidden && ((PSWP)mp1)->fl & SWP_RESTORE) { WinSetParent(mTitleBar, HWND_OBJECT, TRUE); WinSetParent(mSysMenu, HWND_OBJECT, TRUE); WinSetParent(mMinMax, HWND_OBJECT, TRUE); } break; case WM_DESTROY: DEBUGFOCUS(frame WM_DESTROY); WinSubclassWindow(mFrameWnd, mPrevFrameProc); WinSetWindowPtr(mFrameWnd, QWL_USER, 0); break; case WM_INITMENU: // If we are in fullscreen/kiosk mode, disable maximize menu item. if (mChromeHidden && SHORT1FROMMP(mp1) == SC_SYSMENU && WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) { MENUITEM menuitem; WinSendMsg(WinWindowFromID(mFrameWnd, FID_SYSMENU), MM_QUERYITEM, MPFROM2SHORT(SC_SYSMENU, FALSE), MPARAM(&menuitem)); mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2); WinEnableMenuItem(menuitem.hwndSubMenu, SC_MAXIMIZE, FALSE); isDone = true; } break; case WM_SYSCOMMAND: // If we are in fullscreen/kiosk mode, don't honor maximize requests. if (mChromeHidden && SHORT1FROMMP(mp1) == SC_MAXIMIZE && WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) { isDone = true; } break; // When the frame is activated, set a flag to be acted on after // PM has finished changing focus. When deactivated, dispatch // the event immediately because it doesn't affect the focus. case WM_ACTIVATE: DEBUGFOCUS(WM_ACTIVATE); if (mp1) { mNeedActivation = true; } else { mNeedActivation = false; DEBUGFOCUS(NS_DEACTIVATE); mOwner->DispatchActivationEvent(false); // Prevent the frame from automatically focusing any window // when it's reactivated. Let moz set the focus to avoid // having non-widget children of plugins focused in error. WinSetWindowULong(mFrameWnd, QWL_HWNDFOCUSSAVE, 0); } break; } if (!isDone) { mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2); } return mresult; }
// Called in the PM thread. void nsFrameWindow::RealDoCreate( HWND hwndP, nsWindow *aParent, const nsIntRect &aRect, EVENT_CALLBACK aHandleEventFunction, nsIDeviceContext *aContext, nsIAppShell *aAppShell, nsWidgetInitData *aInitData, HWND hwndO) { nsIntRect rect = aRect; if( aParent) // Offset rect by position of owner { nsIntRect clientRect; aParent->GetBounds(rect); aParent->GetClientBounds(clientRect); rect.x += aRect.x + clientRect.x; rect.y += aRect.y + clientRect.y; rect.width = aRect.width; rect.height = aRect.height; hwndP = aParent->GetMainWindow(); rect.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - (rect.y + rect.height); } else // Use original rect, no owner window { rect = aRect; rect.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - (aRect.y + aRect.height); } #if DEBUG_sobotka printf("\nIn nsFrameWindow::RealDoCreate:\n"); printf(" hwndP = %lu\n", hwndP); printf(" aParent = 0x%lx\n", &aParent); printf(" aRect = %ld, %ld, %ld, %ld\n", aRect.x, aRect.y, aRect.height, aRect.width); #endif ULONG fcfFlags = GetFCFlags(); ULONG style = WindowStyle(); if( aInitData) { if( aInitData->clipChildren) style |= WS_CLIPCHILDREN; #if 0 // // Windows has a slightly different idea of what the implications are // of a window having or not having the CLIPSIBLINGS style. // All 'canvas' components we create must have clipsiblings, or // strange things happen & performance actually degrades. // else style &= ~WS_CLIPCHILDREN; #endif if( aInitData->clipSiblings) style |= WS_CLIPSIBLINGS; else style &= ~WS_CLIPSIBLINGS; } #ifdef DEBUG_FOCUS mWindowIdentifier = currentWindowIdentifier; currentWindowIdentifier++; if (aInitData && (aInitData->mWindowType == eWindowType_toplevel)) DEBUGFOCUS(Create Frame Window); else DEBUGFOCUS(Create Window); #endif mFrameWnd = WinCreateStdWindow( HWND_DESKTOP, 0, &fcfFlags, WindowClass(), "Title", style, NULLHANDLE, 0, &mWnd); /* Because WinCreateStdWindow doesn't take an owner, we have to set it */ if (hwndP) WinSetOwner(mFrameWnd, hwndP); /* Set some HWNDs and style into properties for fullscreen mode */ HWND hwndTitleBar = WinWindowFromID(mFrameWnd, FID_TITLEBAR); WinSetProperty(mFrameWnd, "hwndTitleBar", (PVOID)hwndTitleBar, 0); HWND hwndSysMenu = WinWindowFromID(mFrameWnd, FID_SYSMENU); WinSetProperty(mFrameWnd, "hwndSysMenu", (PVOID)hwndSysMenu, 0); HWND hwndMinMax = WinWindowFromID(mFrameWnd, FID_MINMAX); WinSetProperty(mFrameWnd, "hwndMinMax", (PVOID)hwndMinMax, 0); SetWindowListVisibility( PR_FALSE); // Hide from Window List until shown NS_ASSERTION( mFrameWnd, "Couldn't create frame"); // Frames have a minimum height based on the pieces they are created with, // such as titlebar, menubar, frame borders, etc. We need this minimum // height so we can correctly set the frame position (coordinate flipping). nsIntRect frameRect = rect; long minheight; if ( fcfFlags & FCF_SIZEBORDER) { minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYSIZEBORDER); } else if ( fcfFlags & FCF_DLGBORDER) { minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME); } else { minheight = 2 * WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER); } if ( fcfFlags & FCF_TITLEBAR) { minheight += WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR); } if ( frameRect.height < minheight) { frameRect.height = minheight; } // Set up parent data - don't addref to avoid circularity mParent = nsnull; // Make sure we have a device context from somewhere if( aContext) { mContext = aContext; NS_ADDREF(mContext); } else { nsresult rc; static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID); rc = CallCreateInstance(kDeviceContextCID, &mContext); if( NS_SUCCEEDED(rc)) mContext->Init(this); #ifdef DEBUG else printf( "Couldn't find DC instance for nsWindow\n"); #endif } // Record bounds. This is XP, the rect of the entire main window in // parent space. Returned by GetBounds(). // NB: We haven't subclassed yet, so callbacks to change mBounds won't // have happened! mBounds = frameRect; mBounds.height = frameRect.height; // Record passed in things mEventCallback = aHandleEventFunction; if( mParent) mParent->AddChild( this); // call the event callback to notify about creation DispatchStandardEvent( NS_CREATE ); SubclassWindow(TRUE); PostCreateWidget(); // Subclass frame fnwpDefFrame = WinSubclassWindow( mFrameWnd, fnwpFrame); WinSetWindowPtr( mFrameWnd, QWL_USER, this); WinSetWindowPos(mFrameWnd, 0, frameRect.x, frameRect.y, frameRect.width, frameRect.height, SWP_SIZE | SWP_MOVE); }
// Process messages from the frame MRESULT nsFrameWindow::FrameMessage( ULONG msg, MPARAM mp1, MPARAM mp2) { MRESULT mresult = 0; BOOL bDone = FALSE; switch (msg) { case WM_WINDOWPOSCHANGED: { PSWP pSwp = (PSWP) mp1; // Note that client windows never get 'move' messages (well, they won't here anyway) if( pSwp->fl & SWP_MOVE && !(pSwp->fl & SWP_MINIMIZE)) { // These commented-out `-1's cancel each other out. POINTL ptl = { pSwp->x, pSwp->y + pSwp->cy /* - 1 */ }; ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - ptl.y /* - 1*/ ; mBounds.x = ptl.x; mBounds.y = ptl.y; OnMove( ptl.x, ptl.y); } // When the frame is sized, do stuff to recalculate client size. if( pSwp->fl & SWP_SIZE && !(pSwp->fl & SWP_MINIMIZE)) { mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2); bDone = TRUE; mBounds.width = pSwp->cx; mBounds.height = pSwp->cy; UpdateClientSize(); DispatchResizeEvent( mSizeClient.width, mSizeClient.height); } if (pSwp->fl & (SWP_MAXIMIZE | SWP_MINIMIZE | SWP_RESTORE)) { nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this); if (pSwp->fl & SWP_MAXIMIZE) event.mSizeMode = nsSizeMode_Maximized; else if (pSwp->fl & SWP_MINIMIZE) event.mSizeMode = nsSizeMode_Minimized; else event.mSizeMode = nsSizeMode_Normal; InitEvent(event); DispatchWindowEvent(&event); } break; } // a frame window in kiosk/fullscreen mode must have its frame // controls reattached before it's minimized & detached after it's // restored; if this doesn't happen at the correct times, clicking // on the icon won't restore it, the sysmenu will have the wrong // items, and/or the minmax button will have the wrong buttons case WM_ADJUSTWINDOWPOS: { if (mChromeHidden && ((PSWP)mp1)->fl & SWP_MINIMIZE) { HWND hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax"); if (hwndTemp) WinSetParent(hwndTemp, mFrameWnd, TRUE); hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar"); if (hwndTemp) WinSetParent(hwndTemp, mFrameWnd, TRUE); hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu"); if (hwndTemp) WinSetParent(hwndTemp, mFrameWnd, TRUE); } break; } case WM_ADJUSTFRAMEPOS: { if (mChromeHidden && ((PSWP)mp1)->fl & SWP_RESTORE) { HWND hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu"); if (hwndTemp) WinSetParent(hwndTemp, HWND_OBJECT, TRUE); hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar"); if (hwndTemp) WinSetParent(hwndTemp, HWND_OBJECT, TRUE); hwndTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax"); if (hwndTemp) WinSetParent(hwndTemp, HWND_OBJECT, TRUE); } break; } case WM_DESTROY: DEBUGFOCUS(frame WM_DESTROY); WinSubclassWindow( mFrameWnd, fnwpDefFrame); WinSetWindowPtr( mFrameWnd, QWL_USER, 0); WinRemoveProperty(mFrameWnd, "hwndTitleBar"); WinRemoveProperty(mFrameWnd, "hwndSysMenu"); WinRemoveProperty(mFrameWnd, "hwndMinMax"); WinRemoveProperty(mFrameWnd, "ulStyle"); break; case WM_INITMENU: /* If we are in fullscreen/kiosk mode, disable maximize menu item */ if (mChromeHidden) { if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) { if (SHORT1FROMMP(mp1) == SC_SYSMENU) { MENUITEM menuitem; WinSendMsg(WinWindowFromID(mFrameWnd, FID_SYSMENU), MM_QUERYITEM, MPFROM2SHORT(SC_SYSMENU, FALSE), MPARAM(&menuitem)); mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2); WinEnableMenuItem(menuitem.hwndSubMenu, SC_MAXIMIZE, FALSE); bDone = TRUE; } } } break; case WM_SYSCOMMAND: /* If we are in fullscreen/kiosk mode, don't honor maximize requests */ if (mChromeHidden) { if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MINIMIZED) { if ((SHORT1FROMMP(mp1) == SC_MAXIMIZE)) { bDone = TRUE; } } } break; // When the frame is activated, set a flag to be acted on after // PM has finished changing focus. When deactivated, dispatch // the event immediately because it doesn't affect the focus. case WM_ACTIVATE: DEBUGFOCUS(WM_ACTIVATE); if (mp1) { mNeedActivation = PR_TRUE; } else { mNeedActivation = PR_FALSE; DEBUGFOCUS(NS_DEACTIVATE); DispatchFocus(NS_DEACTIVATE); // Prevent the frame from automatically focusing any window // when it's reactivated. Let moz set the focus to avoid // having non-widget children of plugins focused in error. WinSetWindowULong(mFrameWnd, QWL_HWNDFOCUSSAVE, 0); } break; } if( !bDone) mresult = (*fnwpDefFrame)( mFrameWnd, msg, mp1, mp2); return mresult; }