diff --git a/widget/src/os2/Makefile.in b/widget/src/os2/Makefile.in index a8bd2abf92b1..939360a7f3bc 100644 --- a/widget/src/os2/Makefile.in +++ b/widget/src/os2/Makefile.in @@ -61,7 +61,7 @@ CPPSRCS = \ nsBidiKeyboard.cpp \ nsClipboard.cpp \ nsFilePicker.cpp \ - nsFrameWindow.cpp \ + os2FrameWindow.cpp \ nsLookAndFeel.cpp \ nsOS2Uni.cpp \ nsPrintOS2.cpp \ diff --git a/widget/src/os2/nsFrameWindow.cpp b/widget/src/os2/nsFrameWindow.cpp deleted file mode 100644 index f6912fa7874b..000000000000 --- a/widget/src/os2/nsFrameWindow.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* vim: set sw=2 sts=2 et cin: */ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Mozilla OS/2 libraries. - * - * The Initial Developer of the Original Code is - * John Fairhurst, . - * Portions created by the Initial Developer are Copyright (C) 1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Rich Walsh - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** - * - * This Original Code has been modified by IBM Corporation. - * Modifications made by IBM are - * Copyright (c) International Business Machines Corporation, 2000 - * - */ -//============================================================================= - -#include "nsFrameWindow.h" -#include "nsIRollupListener.h" - -//----------------------------------------------------------------------------- - -extern nsIRollupListener* gRollupListener; -extern nsIWidget* gRollupWidget; -extern PRBool gRollupConsumeRollupEvent; -extern PRUint32 gOS2Flags; - -#ifdef DEBUG_FOCUS - extern int currentWindowIdentifier; -#endif - -//============================================================================= -// nsFrameWindow Setup -//============================================================================= - -nsFrameWindow::nsFrameWindow() : nsWindow() -{ - mPrevFrameProc = 0; - mWindowType = eWindowType_toplevel; - mNeedActivation = PR_FALSE; -} - -nsFrameWindow::~nsFrameWindow() -{ -} - -//----------------------------------------------------------------------------- -// Create frame & client windows for an nsFrameWindow object - -nsresult nsFrameWindow::CreateWindow(nsWindow* aParent, - HWND aParentWnd, - const nsIntRect& aRect, - PRUint32 aStyle) -{ - // top-level widget windows (i.e nsFrameWindow) are created for - // windows of types eWindowType_toplevel, *_dialog, & *_invisible - mIsTopWidgetWindow = PR_TRUE; - - // Create a frame window with a MozillaWindowClass window as its client. - PRUint32 fcfFlags = GetFCFlags(); - mFrameWnd = WinCreateStdWindow(HWND_DESKTOP, - 0, - (ULONG*)&fcfFlags, - kWindowClassName, - "Title", - aStyle, - NULLHANDLE, - 0, - &mWnd); - NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_FAILURE); - - // Hide from the Window List until shown. - SetWindowListVisibility(PR_FALSE); - - // This prevents a modal dialog from being covered by its disabled parent. - if (aParentWnd != HWND_DESKTOP) { - WinSetOwner(mFrameWnd, aParentWnd); - } - - // Set the frame control HWNDs as properties for use by fullscreen mode. - HWND hTemp = WinWindowFromID(mFrameWnd, FID_TITLEBAR); - WinSetProperty(mFrameWnd, "hwndTitleBar", (PVOID)hTemp, 0); - hTemp = WinWindowFromID(mFrameWnd, FID_SYSMENU); - WinSetProperty(mFrameWnd, "hwndSysMenu", (PVOID)hTemp, 0); - hTemp = WinWindowFromID(mFrameWnd, FID_MINMAX); - WinSetProperty(mFrameWnd, "hwndMinMax", (PVOID)hTemp, 0); - - // Establish a minimum height or else some dialogs will be truncated. - PRInt32 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); - } - - // Store the frame's adjusted dimensions, move & resize accordingly, - // then calculate the client's dimensions. - mBounds = aRect; - if (mBounds.height < minHeight) { - mBounds.height = minHeight; - } - PRInt32 pmY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - - mBounds.y - mBounds.height; - WinSetWindowPos(mFrameWnd, 0, mBounds.x, pmY, - mBounds.width, mBounds.height, SWP_SIZE | SWP_MOVE); - UpdateClientSize(); - - // Subclass the frame; the client will be subclassed by Create(). - mPrevFrameProc = WinSubclassWindow(mFrameWnd, fnwpFrame); - WinSetWindowPtr(mFrameWnd, QWL_USER, this); - - DEBUGFOCUS(Create nsFrameWindow); - return NS_OK; -} - -//----------------------------------------------------------------------------- - -PRUint32 nsFrameWindow::GetFCFlags() -{ - PRUint32 style = FCF_TITLEBAR | FCF_SYSMENU | FCF_TASKLIST | - FCF_CLOSEBUTTON | FCF_NOBYTEALIGN | FCF_AUTOICON; - - if (mWindowType == eWindowType_dialog) { - if (mBorderStyle == eBorderStyle_default) { - style |= FCF_DLGBORDER; - } else { - style |= FCF_SIZEBORDER | FCF_MINMAX; - } - } - else { - style |= FCF_SIZEBORDER | FCF_MINMAX; - } - - if (gOS2Flags & kIsDBCS) { - style |= FCF_DBE_APPSTAT; - } - if (mWindowType == eWindowType_invisible) { - style &= ~FCF_TASKLIST; - } - - if (mBorderStyle != eBorderStyle_default && - mBorderStyle != eBorderStyle_all) { - if (mBorderStyle == eBorderStyle_none || - !(mBorderStyle & eBorderStyle_resizeh)) { - style &= ~FCF_SIZEBORDER; - style |= FCF_DLGBORDER; - } - if (mBorderStyle == eBorderStyle_none || - !(mBorderStyle & eBorderStyle_border)) { - style &= ~(FCF_DLGBORDER | FCF_SIZEBORDER); - } - if (mBorderStyle == eBorderStyle_none || - !(mBorderStyle & eBorderStyle_title)) { - style &= ~(FCF_TITLEBAR | FCF_TASKLIST); - } - if (mBorderStyle == eBorderStyle_none || - !(mBorderStyle & eBorderStyle_close)) { - style &= ~FCF_CLOSEBUTTON; - } - if (mBorderStyle == eBorderStyle_none || - !(mBorderStyle & (eBorderStyle_menu | eBorderStyle_close))) { - style &= ~FCF_SYSMENU; - } - - // Looks like getting rid of the system menu also does away - // with the close box. So, we only get rid of the system menu - // if you want neither it nor the close box. - - if (mBorderStyle == eBorderStyle_none || - !(mBorderStyle & eBorderStyle_minimize)) { - style &= ~FCF_MINBUTTON; - } - if (mBorderStyle == eBorderStyle_none || - !(mBorderStyle & eBorderStyle_maximize)) { - style &= ~FCF_MAXBUTTON; - } - } - - return style; -} - -//============================================================================= -// Window Operations -//============================================================================= - -// For frame windows, 'Show' is equivalent to 'Show & Activate' - -NS_METHOD nsFrameWindow::Show(PRBool aState) -{ - if (!mWnd) { - return NS_OK; - } - - PRUint32 ulFlags; - if (!aState) { - ulFlags = SWP_HIDE | SWP_DEACTIVATE; - } else { - ulFlags = SWP_SHOW; - - // Don't activate the window unless the parent is visible - if (WinIsWindowVisible(WinQueryWindow(mFrameWnd, QW_PARENT))) { - ulFlags |= SWP_ACTIVATE; - } - - PRUint32 ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE); - if (!(ulStyle & WS_VISIBLE)) { - PRInt32 sizeMode; - GetSizeMode(&sizeMode); - if (sizeMode == nsSizeMode_Maximized) { - ulFlags |= SWP_MAXIMIZE; - } else if (sizeMode == nsSizeMode_Minimized) { - ulFlags |= SWP_MINIMIZE; - } else { - ulFlags |= SWP_RESTORE; - } - } - if (ulStyle & WS_MINIMIZED) { - ulFlags |= (SWP_RESTORE | SWP_MAXIMIZE); - } - } - - WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, ulFlags); - SetWindowListVisibility(aState); - - return NS_OK; -} - -//----------------------------------------------------------------------------- - -NS_METHOD nsFrameWindow::GetClientBounds(nsIntRect& aRect) -{ - RECTL rcl = { 0, 0, mBounds.width, mBounds.height }; - WinCalcFrameRect(mFrameWnd, &rcl, TRUE); // provided == frame rect - aRect.x = rcl.xLeft; - aRect.y = mBounds.height - rcl.yTop; - aRect.width = mSizeClient.width; - aRect.height = mSizeClient.height; - return NS_OK; -} - -//----------------------------------------------------------------------------- - -void nsFrameWindow::UpdateClientSize() -{ - RECTL rcl = { 0, 0, mBounds.width, mBounds.height }; - WinCalcFrameRect(mFrameWnd, &rcl, TRUE); // provided == frame rect - mSizeClient.width = rcl.xRight - rcl.xLeft; - mSizeClient.height = rcl.yTop - rcl.yBottom; -} - -//----------------------------------------------------------------------------- -// When WM_ACTIVATE is received with the "gaining activation" flag set, -// the frame's wndproc sets mNeedActivation. Later, when an nsWindow -// gets a WM_FOCUSCHANGED msg with the "gaining focus" flag set, it -// invokes this method on nsFrameWindow to fire an NS_ACTIVATE event. - -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); - DispatchActivationEvent(NS_ACTIVATE); - } - } - return; -} - -//----------------------------------------------------------------------------- -// Just ignore this callback; the correct stuff is done in the frame wp. - -PRBool nsFrameWindow::OnReposition(PSWP pSwp) -{ - return PR_TRUE; -} - -//----------------------------------------------------------------------------- - -void nsFrameWindow::SetWindowListVisibility(PRBool aState) -{ - HSWITCH hswitch = WinQuerySwitchHandle(mFrameWnd, 0); - if (hswitch) { - SWCNTRL swctl; - WinQuerySwitchEntry(hswitch, &swctl); - swctl.uchVisibility = aState ? SWL_VISIBLE : SWL_INVISIBLE; - swctl.fbJump = aState ? SWL_JUMPABLE : SWL_NOTJUMPABLE; - WinChangeSwitchEntry(hswitch, &swctl); - } -} - -//============================================================================= -// nsFrameWindow's Window Procedure -//============================================================================= - -// Subclass for frame window - -MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - // check to see if we have a rollup listener registered - if (gRollupListener && gRollupWidget) { - if (msg == WM_TRACKFRAME || msg == WM_MINMAXFRAME || - msg == WM_BUTTON1DOWN || msg == WM_BUTTON2DOWN || - msg == WM_BUTTON3DOWN) { - // Rollup if the event is outside the popup - if (!nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget)) { - gRollupListener->Rollup(PR_UINT32_MAX, nsnull); - } - } - } - - nsFrameWindow* pFrame = (nsFrameWindow*)WinQueryWindowPtr(hwnd, QWL_USER); - return pFrame->FrameMessage(msg, mp1, mp2); -} - -//----------------------------------------------------------------------------- -// Process messages from the frame - -MRESULT nsFrameWindow::FrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2) -{ - MRESULT mresult = 0; - PRBool bDone = PR_FALSE; - - switch (msg) { - case WM_WINDOWPOSCHANGED: { - PSWP pSwp = (PSWP)mp1; - - // Note that client windows never get 'move' messages - 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; - mBounds.x = ptl.x; - mBounds.y = ptl.y; - DispatchMoveEvent(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 = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2); - bDone = PR_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 hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax"); - if (hTemp) { - WinSetParent(hTemp, mFrameWnd, TRUE); - } - hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar"); - if (hTemp) { - WinSetParent(hTemp, mFrameWnd, TRUE); - } - hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu"); - if (hTemp) { - WinSetParent(hTemp, mFrameWnd, TRUE); - } - } - break; - } - - case WM_ADJUSTFRAMEPOS: { - if (mChromeHidden && ((PSWP)mp1)->fl & SWP_RESTORE) { - HWND hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu"); - if (hTemp) { - WinSetParent(hTemp, HWND_OBJECT, TRUE); - } - hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar"); - if (hTemp) { - WinSetParent(hTemp, HWND_OBJECT, TRUE); - } - hTemp = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax"); - if (hTemp) { - WinSetParent(hTemp, HWND_OBJECT, TRUE); - } - } - break; - } - - case WM_DESTROY: - DEBUGFOCUS(frame WM_DESTROY); - WinSubclassWindow(mFrameWnd, mPrevFrameProc); - 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 && - 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); - bDone = PR_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) { - bDone = PR_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); - DispatchActivationEvent(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 = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2); - } - - return mresult; -} - -//============================================================================= - diff --git a/widget/src/os2/nsFrameWindow.h b/widget/src/os2/nsFrameWindow.h deleted file mode 100644 index 1f41ec5b6874..000000000000 --- a/widget/src/os2/nsFrameWindow.h +++ /dev/null @@ -1,109 +0,0 @@ -/* vim: set sw=2 sts=2 et cin: */ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Mozilla OS/2 libraries. - * - * The Initial Developer of the Original Code is - * John Fairhurst, . - * Portions created by the Initial Developer are Copyright (C) 1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Rich Walsh - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//============================================================================= -/* - * nsFrameWindow is a subclass of nsWindow and is created when NS_WINDOW_CID - * is specified. It represents a top-level widget and is implemented as two - * native windows, a frame (WC_FRAME) and a client (MozillaWindowClass). - * - * Most methods inherited from nsIWidget are handled by nsWindow. For those - * which require slightly different implementations for top-level and child - * widgets, nsWindow relies on a flag or on virtual helper methods to handle - * the differences properly. - * - * There are two items where these differences are particularly important: - * - mWnd identifies the frame's client which is seldom acted upon directly; - * instead, most operations involve mFrameWnd. - * - mBounds contains the dimensions of mFrameWnd, not mWnd whose width and - * height are stored in mSizeClient. - * - */ -//============================================================================= - -#ifndef _nsframewindow_h -#define _nsframewindow_h - -#include "nsWindow.h" -#include "nssize.h" - -//============================================================================= -// nsFrameWindow -//============================================================================= - -class nsFrameWindow : public nsWindow -{ -public: - nsFrameWindow(); - virtual ~nsFrameWindow(); - - // from nsIWidget - virtual nsresult CreateWindow(nsWindow* aParent, - HWND aParentWnd, - const nsIntRect& aRect, - PRUint32 aStyle); - NS_IMETHOD Show(PRBool aState); - NS_IMETHOD GetClientBounds(nsIntRect& aRect); - -protected: - // from nsWindow - virtual HWND GetMainWindow() const {return mFrameWnd;} - virtual void ActivateTopLevelWidget(); - virtual PRBool OnReposition(PSWP pSwp); - virtual PRInt32 GetClientHeight() {return mSizeClient.height;} - - // nsFrameWindow - PRUint32 GetFCFlags(); - void UpdateClientSize(); - void SetWindowListVisibility(PRBool aState); - MRESULT FrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2); - - friend MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg, - MPARAM mp1, MPARAM mp2); - - PFNWP mPrevFrameProc; - nsSize mSizeClient; - PRBool mNeedActivation; -}; - -#endif //_nsframewindow_h - -//============================================================================= - diff --git a/widget/src/os2/nsWidgetFactory.cpp b/widget/src/os2/nsWidgetFactory.cpp index 494571e2f5e3..d94b48e14b54 100644 --- a/widget/src/os2/nsWidgetFactory.cpp +++ b/widget/src/os2/nsWidgetFactory.cpp @@ -84,9 +84,6 @@ #include "nsDeviceContextSpecOS2.h" #include "nsPrintOptionsOS2.h" #include "nsPrintSession.h" - -#include "nsFrameWindow.h" // OS/2 only - #include "nsIdleServiceOS2.h" // objects that just require generic constructors @@ -95,7 +92,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsFrameWindow) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) @@ -124,7 +121,7 @@ static const nsModuleComponentInfo components[] = { "OS/2 Child Window", NS_CHILD_CID, "@mozilla.org/widget/child_window/os2;1", - nsWindowConstructor }, + nsChildWindowConstructor }, { "OS/2 Clipboard", NS_CLIPBOARD_CID, "@mozilla.org/widget/clipboard;1", @@ -153,10 +150,10 @@ static const nsModuleComponentInfo components[] = NS_TOOLKIT_CID, "@mozilla.org/widget/toolkit/os2;1", nsToolkitConstructor }, - { "OS/2 Frame Window", + { "OS/2 Window", NS_WINDOW_CID, "@mozilla.org/widget/window/os2;1", - nsFrameWindowConstructor }, + nsWindowConstructor }, { "OS/2 Transferable", NS_TRANSFERABLE_CID, "@mozilla.org/widget/transferable;1", diff --git a/widget/src/os2/nsWindow.cpp b/widget/src/os2/nsWindow.cpp index 17d8c30999fe..55b0652db1cd 100644 --- a/widget/src/os2/nsWindow.cpp +++ b/widget/src/os2/nsWindow.cpp @@ -66,6 +66,7 @@ //============================================================================= #include "nsWindow.h" +#include "os2FrameWindow.h" #include "gfxContext.h" #include "gfxOS2Surface.h" #include "imgIContainer.h" @@ -166,11 +167,21 @@ // name of the window class used to clip plugins #define kClipWndClass "nsClipWnd" +//----------------------------------------------------------------------------- +// Debug + +#ifdef DEBUG_FOCUS + #define DEBUGFOCUS(what) fprintf(stderr, "[%8x] %8lx (%02d) "#what"\n", \ + (int)this, mWnd, mWindowIdentifier) +#else + #define DEBUGFOCUS(what) +#endif + //============================================================================= // Variables & Forward declarations //============================================================================= -// Rollup Listener - used by nsWindow & nsFrameWindow +// Rollup Listener - used by nsWindow & os2FrameWindow nsIRollupListener* gRollupListener = 0; nsIMenuRollup* gMenuRollup = 0; nsIWidget* gRollupWidget = 0; @@ -204,8 +215,8 @@ nsWindow::nsWindow() : nsBaseWidget() { mWnd = 0; mParent = 0; - mIsTopWidgetWindow = PR_FALSE; - mWindowType = eWindowType_child; + mFrame = 0; + mWindowType = eWindowType_toplevel; mBorderStyle = eBorderStyle_default; mWindowState = nsWindowState_ePrecreate; mOnDestroyCalled = PR_FALSE; @@ -217,10 +228,6 @@ nsWindow::nsWindow() : nsBaseWidget() mCssCursorHPtr = 0; mThebesSurface = 0; - mFrameWnd = 0; - mFrameIcon = 0; - mChromeHidden = PR_FALSE; - if (!gOS2Flags) { InitGlobals(); } @@ -239,10 +246,6 @@ nsWindow::~nsWindow() // may even be illegal to call them from here. mIsDestroying = PR_TRUE; - if (mFrameIcon) { - WinFreeFileIcon(mFrameIcon); - mFrameIcon = 0; - } if (mCssCursorHPtr) { WinDestroyPointer(mCssCursorHPtr); @@ -257,6 +260,12 @@ nsWindow::~nsWindow() nsWindowState_eInCreate); Destroy(); } + + // If it exists, destroy our os2FrameWindow helper object. + if (mFrame) { + delete mFrame; + mFrame = 0; + } } //----------------------------------------------------------------------------- @@ -316,7 +325,7 @@ void nsWindow::ReleaseGlobals() } //----------------------------------------------------------------------------- -// Init an nsWindow or nsFrameWindow & create the appropriate native window. +// Init an nsWindow & create the appropriate native window. NS_METHOD nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent, @@ -327,12 +336,11 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent, nsIToolkit* aToolkit, nsWidgetInitData* aInitData) { - nsresult rv; mWindowState = nsWindowState_eInCreate; // Identify the parent's nsWindow & native window. Only one of these // should be supplied. Note: only nsWindow saves pParent as mParent; - // nsFrameWindow discards it since toplevel widgets have no parent. + // os2FrameWindow discards it since toplevel widgets have no parent. HWND hParent; nsWindow* pParent; if (aParent) { @@ -357,7 +365,7 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent, NS_ADDREF(mContext); } else { static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID); - rv = CallCreateInstance(kDeviceContextCID, &mContext); + nsresult rv = CallCreateInstance(kDeviceContextCID, &mContext); NS_ENSURE_SUCCESS(rv, rv); mContext->Init(nsnull); } @@ -375,30 +383,34 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent, NS_ADDREF(mToolkit); } - // Some basic initialization. - PRUint32 style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; - if (aInitData) { - // While we comply with the clipSiblings flag, we always set - // clipChildren regardless of the flag for performance reasons. - if (!aInitData->clipSiblings) { - style &= ~WS_CLIPSIBLINGS; - } - mWindowType = aInitData->mWindowType; - mBorderStyle = aInitData->mBorderStyle; - } - #ifdef DEBUG_FOCUS mWindowIdentifier = currentWindowIdentifier; currentWindowIdentifier++; #endif - // This is virtual and creates the appropriate type of window for - // the class. It also does a few other class-specific chores. - rv = CreateWindow(pParent, hParent, aRect, style); - NS_ENSURE_SUCCESS(rv, rv); + // Some basic initialization. + if (aInitData) { + mWindowType = aInitData->mWindowType; + mBorderStyle = aInitData->mBorderStyle; + } - // Both versions of CreateWindow() create a MozillaWindow - // class window that needs to store this object's pointer. + // For toplevel windows, create an instance of our helper class, + // then have it create a frame & client window; otherwise, + // call our own CreateWindow() method to create a child window. + if (mWindowType == eWindowType_toplevel || + mWindowType == eWindowType_dialog || + mWindowType == eWindowType_invisible) { + mFrame = new os2FrameWindow(this); + NS_ENSURE_TRUE(mFrame, NS_ERROR_FAILURE); + mWnd = mFrame->CreateFrameWindow(pParent, hParent, aRect, + mWindowType, mBorderStyle); + NS_ENSURE_TRUE(mWnd, NS_ERROR_FAILURE); + } else { + nsresult rv = CreateWindow(pParent, hParent, aRect, aInitData); + NS_ENSURE_SUCCESS(rv, rv); + } + + // Store a pointer to this object in the window's extra bytes. SetNSWindowPtr(mWnd, this); // Finalize the widget creation process. @@ -407,7 +419,7 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent, DispatchWindowEvent(&event); mWindowState = nsWindowState_eLive; - return rv; + return NS_OK; } //----------------------------------------------------------------------------- @@ -416,7 +428,7 @@ NS_METHOD nsWindow::Create(nsIWidget* aParent, nsresult nsWindow::CreateWindow(nsWindow* aParent, HWND aParentWnd, const nsIntRect& aRect, - PRUint32 aStyle) + nsWidgetInitData* aInitData) { // For pop-ups, the Desktop is the parent and aParentWnd is the owner. HWND hOwner = 0; @@ -425,11 +437,18 @@ nsresult nsWindow::CreateWindow(nsWindow* aParent, aParentWnd = HWND_DESKTOP; } + // While we comply with the clipSiblings flag, we always set + // clipChildren regardless of the flag for performance reasons. + PRUint32 style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + if (aInitData && !aInitData->clipSiblings) { + style &= ~WS_CLIPSIBLINGS; + } + // Create the window hidden; it will be resized below. mWnd = WinCreateWindow(aParentWnd, kWindowClassName, 0, - aStyle, + style, 0, 0, 0, 0, hOwner, HWND_TOP, @@ -488,9 +507,7 @@ NS_METHOD nsWindow::Destroy() CaptureRollupEvents(nsnull, nsnull, PR_FALSE, PR_TRUE); } - // Since this may be called by the destructor, don't use - // GetMainWindow() which is virtual (and will cause a crash). - HWND hMain = mFrameWnd ? mFrameWnd : mWnd; + HWND hMain = GetMainWindow(); if (hMain) { DEBUGFOCUS(Destroy); if (hMain == WinQueryFocus(HWND_DESKTOP)) { @@ -505,8 +522,19 @@ NS_METHOD nsWindow::Destroy() // Standard Window Operations //============================================================================= +// This can't be inlined in nsWindow.h because it doesn't know about +// GetFrameWnd(). + +inline HWND nsWindow::GetMainWindow() +{ + return mFrame ? mFrame->GetFrameWnd() : mWnd; +} + +//----------------------------------------------------------------------------- +// Inline this here for consistency (and a cleaner looking .h). + // static -nsWindow* nsWindow::GetNSWindowPtr(HWND aWnd) +inline nsWindow* nsWindow::GetNSWindowPtr(HWND aWnd) { return (nsWindow*)WinQueryWindowPtr(aWnd, QWL_NSWINDOWPTR); } @@ -514,7 +542,7 @@ nsWindow* nsWindow::GetNSWindowPtr(HWND aWnd) //----------------------------------------------------------------------------- // static -PRBool nsWindow::SetNSWindowPtr(HWND aWnd, nsWindow* aPtr) +inline PRBool nsWindow::SetNSWindowPtr(HWND aWnd, nsWindow* aPtr) { return WinSetWindowPtr(aWnd, QWL_NSWINDOWPTR, aPtr); } @@ -525,7 +553,7 @@ nsIWidget* nsWindow::GetParent() { // if this window isn't supposed to have a parent or it doesn't have // a parent, or if it or its parent is being destroyed, return null - if (mIsTopWidgetWindow || mIsDestroying || mOnDestroyCalled || + if (mFrame || mIsDestroying || mOnDestroyCalled || !mParent || mParent->mIsDestroying) { return 0; } @@ -555,10 +583,12 @@ NS_METHOD nsWindow::IsEnabled(PRBool* aState) } //----------------------------------------------------------------------------- -// nsFrameWindow overrides this NS_METHOD nsWindow::Show(PRBool aState) { + if (mFrame) { + return mFrame->Show(aState); + } if (mWnd) { if (aState) { // don't try to show new windows (e.g. the Bookmark menu) @@ -828,15 +858,21 @@ void nsWindow::Scroll(const nsIntPoint& aDelta, // Window Positioning //============================================================================= +// For toplevel windows, mBounds contains the dimensions of the client +// window. os2FrameWindow's "override" returns the size of the frame. + NS_METHOD nsWindow::GetBounds(nsIntRect& aRect) { + if (mFrame) { + return mFrame->GetBounds(aRect); + } aRect = mBounds; return NS_OK; } //----------------------------------------------------------------------------- -// nsFrameWindow overrides this method. Since it is only invoked on toplevel -// windows, this implementation for child windows should never get called. +// Since mBounds contains the dimensions of the client, os2FrameWindow +// doesn't have to provide any special handling for this method. NS_METHOD nsWindow::GetClientBounds(nsIntRect& aRect) { @@ -865,14 +901,14 @@ nsIntPoint nsWindow::WidgetToScreenOffset() // ptl is in this window's space void nsWindow::NS2PM(POINTL& ptl) { - ptl.y = GetClientHeight() - ptl.y - 1; + ptl.y = mBounds.height - ptl.y - 1; } // rcl is in this window's space void nsWindow::NS2PM(RECTL& rcl) { LONG height = rcl.yTop - rcl.yBottom; - rcl.yTop = GetClientHeight() - rcl.yBottom; + rcl.yTop = mBounds.height - rcl.yBottom; rcl.yBottom = rcl.yTop - height; } @@ -882,7 +918,7 @@ void nsWindow::NS2PM_PARENT(POINTL& ptl) if (mParent) { mParent->NS2PM(ptl); } else { - HWND hParent = WinQueryWindow(GetMainWindow(), QW_PARENT); + HWND hParent = WinQueryWindow(mWnd, QW_PARENT); SWP swp; WinQueryWindowPos(hParent, &swp); ptl.y = swp.cy - ptl.y - 1; @@ -893,9 +929,8 @@ void nsWindow::NS2PM_PARENT(POINTL& ptl) NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY) { - if (mWindowType == eWindowType_toplevel || - mWindowType == eWindowType_dialog) { - SetSizeMode(nsSizeMode_Normal); + if (mFrame) { + return mFrame->Move(aX, aY); } Resize(aX, aY, mBounds.width, mBounds.height, PR_FALSE); return NS_OK; @@ -905,6 +940,9 @@ NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY) NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) { + if (mFrame) { + return mFrame->Resize(aWidth, aHeight, aRepaint); + } Resize(mBounds.x, mBounds.y, aWidth, aHeight, aRepaint); return NS_OK; } @@ -914,6 +952,10 @@ NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) { + if (mFrame) { + return mFrame->Resize(aX, aY, aWidth, aHeight, aRepaint); + } + // For mWnd & eWindowType_child set the cached values upfront, see bug 286555. // For other mWnd types we defer transfer of values to mBounds to // WinSetWindowPos(), see bug 391421. @@ -943,7 +985,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, &ptl, 1); } - if (!WinSetWindowPos(GetMainWindow(), 0, ptl.x, ptl.y, aWidth, aHeight, + if (!WinSetWindowPos(mWnd, 0, ptl.x, ptl.y, aWidth, aHeight, SWP_MOVE | SWP_SIZE) && aRepaint) { WinInvalidateRect(mWnd, 0, FALSE); } @@ -1183,277 +1225,57 @@ HWND nsWindow::GetPluginClipWindow(HWND aParentWnd) // Top-level (frame window) Operations //============================================================================= -// When a window gets the focus, call nsFrameWindow's version of this +// When a window gets the focus, call os2FrameWindow's version of this // method. It will fire an NS_ACTIVATE event on the top-level widget // if appropriate. void nsWindow::ActivateTopLevelWidget() { - nsWindow* top = static_cast(GetTopLevelWidget()); - if (top) { - top->ActivateTopLevelWidget(); + if (mFrame) { + mFrame->ActivateTopLevelWidget(); + } else { + nsWindow* top = static_cast(GetTopLevelWidget()); + if (top && top->mFrame) { + top->mFrame->ActivateTopLevelWidget(); + } } return; } //----------------------------------------------------------------------------- -// Maximize, minimize or restore the window. When the frame has its -// controls, this method is advisory because the min/max/restore has -// already occurred. Only when the frame is in kiosk/fullscreen mode -// does it perform the minimize or restore +// All of these methods are inherently toplevel-only, and are in fact +// only invoked on toplevel widgets. If they're invoked on a child +// window, there's an error upstream. NS_IMETHODIMP nsWindow::SetSizeMode(PRInt32 aMode) { - NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED); - - PRInt32 previousMode; - GetSizeMode(&previousMode); - - // save the new state - nsresult rv = 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; + NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED); + return mFrame->SetSizeMode(aMode); } -//----------------------------------------------------------------------------- -// Hide or show the frame & its controls (titlebar, minmax, etc.). - NS_IMETHODIMP nsWindow::HideWindowChrome(PRBool aShouldHide) { - NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED); - - // Putting a maximized window into fullscreen mode causes multiple - // problems if it's later minimized & then restored. To avoid them, - // restore maximized windows before putting them in fullscreen mode. - if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MAXIMIZED) { - WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE | SWP_NOREDRAW); - } - - HWND hParent; - if (aShouldHide) { - hParent = HWND_OBJECT; - mChromeHidden = PR_TRUE; - } else { - hParent = mFrameWnd; - mChromeHidden = PR_FALSE; - } - - // Hide or show the frame controls. - HWND hControl = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar"); - if (hControl) { - WinSetParent(hControl, hParent, FALSE); - } - hControl = (HWND)WinQueryProperty(mFrameWnd, "hwndSysMenu"); - if (hControl) { - WinSetParent(hControl, hParent, FALSE); - } - hControl = (HWND)WinQueryProperty(mFrameWnd, "hwndMinMax"); - if (hControl) { - WinSetParent(hControl, hParent, FALSE); - } - - // Modify the frame style, then advise it of the changes. - if (aShouldHide) { - ULONG ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE); - WinSetProperty(mFrameWnd, "ulStyle", (PVOID)ulStyle, 0); - WinSetWindowULong(mFrameWnd, QWL_STYLE, ulStyle & ~FS_SIZEBORDER); - WinSendMsg(mFrameWnd, WM_UPDATEFRAME, 0, 0); - } else { - ULONG ulStyle = (ULONG)WinQueryProperty(mFrameWnd, "ulStyle"); - WinSetWindowULong(mFrameWnd, QWL_STYLE, ulStyle); - WinSendMsg(mFrameWnd, WM_UPDATEFRAME, - MPFROMLONG(FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX), 0); - } - - return NS_OK; + NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED); + return mFrame->HideWindowChrome(aShouldHide); } -//----------------------------------------------------------------------------- -// On OS/2, if you pass a titlebar > 512 characters, it doesn't display at all. -// We are going to limit our titlebars to 256 just to be on the safe side. - -#define MAX_TITLEBAR_LENGTH 256 - NS_METHOD nsWindow::SetTitle(const nsAString& aTitle) { - NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED); - - PRUnichar* uchtemp = ToNewUnicode(aTitle); - for (PRUint32 i = 0; i < aTitle.Length(); i++) { - switch (uchtemp[i]) { - case 0x2018: - case 0x2019: - uchtemp[i] = 0x0027; - break; - case 0x201C: - case 0x201D: - uchtemp[i] = 0x0022; - break; - case 0x2014: - uchtemp[i] = 0x002D; - break; - } - } - - nsAutoCharBuffer title; - PRInt32 titleLength; - WideCharToMultiByte(0, uchtemp, aTitle.Length(), title, titleLength); - if (titleLength > MAX_TITLEBAR_LENGTH) { - title[MAX_TITLEBAR_LENGTH] = '\0'; - } - WinSetWindowText(mFrameWnd, title.Elements()); - - // If the chrome is hidden, set the text of the titlebar directly - if (mChromeHidden) { - HWND hTitleBar = (HWND)WinQueryProperty(mFrameWnd, "hwndTitleBar"); - WinSetWindowText(hTitleBar, title.Elements()); - } - - nsMemory::Free(uchtemp); - return NS_OK; + NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED); + return mFrame->SetTitle(aTitle); } -//----------------------------------------------------------------------------- -// This implementation guarantees that sysmenus & minimized windows -// will always have some icon other than the sysmenu default. - NS_METHOD nsWindow::SetIcon(const nsAString& aIconSpec) { - NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED); - - static HPOINTER hDefaultIcon = 0; - HPOINTER hWorkingIcon = 0; - - // Assume the given string is a local identifier for an icon file. - nsCOMPtr iconFile; - ResolveIconName(aIconSpec, NS_LITERAL_STRING(".ico"), - getter_AddRefs(iconFile)); - - // if the file was found, try to use it - if (iconFile) { - nsCAutoString path; - iconFile->GetNativePath(path); - - if (mFrameIcon) { - WinFreeFileIcon(mFrameIcon); - } - mFrameIcon = WinLoadFileIcon(path.get(), FALSE); - hWorkingIcon = mFrameIcon; - } - - // if that doesn't work, use the app's icon (let's hope it can be - // loaded because nobody should have to look at SPTR_APPICON - ugggh!) - if (!hWorkingIcon) { - if (!hDefaultIcon) { - hDefaultIcon = WinLoadPointer(HWND_DESKTOP, 0, 1); - if (!hDefaultIcon) { - hDefaultIcon = WinQuerySysPointer(HWND_DESKTOP, SPTR_APPICON, FALSE); - } - } - hWorkingIcon = hDefaultIcon; - } - - WinSendMsg(mFrameWnd, WM_SETICON, (MPARAM)hWorkingIcon, (MPARAM)0); - return NS_OK; + NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED); + return mFrame->SetIcon(aIconSpec); } -//----------------------------------------------------------------------------- -// Constrain a potential move to fit onscreen. - NS_METHOD nsWindow::ConstrainPosition(PRBool aAllowSlop, PRInt32* aX, PRInt32* aY) { - NS_ENSURE_TRUE(mFrameWnd, NS_ERROR_UNEXPECTED); - - // do we have enough info to do anything - PRBool doConstrain = PR_FALSE; - - // get our playing field. use the current screen, or failing - // that for any reason, use device caps for the default screen. - RECTL screenRect; - - nsCOMPtr screenmgr = - do_GetService("@mozilla.org/gfx/screenmanager;1"); - if (screenmgr) { - nsCOMPtr screen; - PRInt32 left, top, width, height; - - // zero size rects confuse the screen manager - width = mBounds.width > 0 ? mBounds.width : 1; - height = mBounds.height > 0 ? mBounds.height : 1; - screenmgr->ScreenForRect(*aX, *aY, width, height, - getter_AddRefs(screen)); - if (screen) { - screen->GetAvailRect(&left, &top, &width, &height); - screenRect.xLeft = left; - screenRect.xRight = left+width; - screenRect.yTop = top; - screenRect.yBottom = top+height; - doConstrain = PR_TRUE; - } - } - -#define kWindowPositionSlop 100 - - if (doConstrain) { - if (aAllowSlop) { - if (*aX < screenRect.xLeft - mBounds.width + kWindowPositionSlop) { - *aX = screenRect.xLeft - mBounds.width + kWindowPositionSlop; - } else - if (*aX >= screenRect.xRight - kWindowPositionSlop) { - *aX = screenRect.xRight - kWindowPositionSlop; - } - - if (*aY < screenRect.yTop) { - *aY = screenRect.yTop; - } else - if (*aY >= screenRect.yBottom - kWindowPositionSlop) { - *aY = screenRect.yBottom - kWindowPositionSlop; - } - } else { - if (*aX < screenRect.xLeft) { - *aX = screenRect.xLeft; - } else - if (*aX >= screenRect.xRight - mBounds.width) { - *aX = screenRect.xRight - mBounds.width; - } - - if (*aY < screenRect.yTop) { - *aY = screenRect.yTop; - } else - if (*aY >= screenRect.yBottom - mBounds.height) { - *aY = screenRect.yBottom - mBounds.height; - } - } - } - - return NS_OK; + NS_ENSURE_TRUE(mFrame, NS_ERROR_UNEXPECTED); + return mFrame->ConstrainPosition(aAllowSlop, aX, aY); } //============================================================================= @@ -2143,7 +1965,7 @@ MRESULT nsWindow::ProcessMessage(ULONG msg, MPARAM mp1, MPARAM mp2) isDone = DispatchScrollEvent(msg, mp1, mp2); break; - // Do not act on WM_ACTIVATE - it is handled by nsFrameWindow. + // Do not act on WM_ACTIVATE - it is handled by os2FrameWindow. // case WM_ACTIVATE: // break; @@ -2220,7 +2042,6 @@ void nsWindow::OnDestroy() } //----------------------------------------------------------------------------- -// nsFrameWindow overrides this. PRBool nsWindow::OnReposition(PSWP pSwp) { @@ -2297,7 +2118,7 @@ PRBool nsWindow::OnPaint() // build XP rect from in-ex window rect nsIntRect rect; rect.x = rcl.xLeft; - rect.y = GetClientHeight() - rcl.yTop; + rect.y = mBounds.height - rcl.yTop; rect.width = rcl.xRight - rcl.xLeft; rect.height = rcl.yTop - rcl.yBottom; event.rect = ▭ diff --git a/widget/src/os2/nsWindow.h b/widget/src/os2/nsWindow.h index 888e2e8172d6..e89705e90e1a 100644 --- a/widget/src/os2/nsWindow.h +++ b/widget/src/os2/nsWindow.h @@ -46,16 +46,33 @@ //============================================================================= /* - * nsWindow derives from nsIWidget via nsBaseWindow, and is created when - * NS_CHILD_CID is specified. It is used for widgets that are either - * children of other widgets or are popups (standalone windows such as - * menus that float above other widgets). - * + * nsWindow derives from nsIWidget via nsBaseWindow. With the aid + * of a helper class (os2FrameWindow) and a subclass (nsChildWindow), + * it implements the functionality of both toplevel and child widgets. + * * Top-level widgets (windows surrounded by a frame with a titlebar, etc.) - * are implemented by nsFrameWindow which is a subclass of nsWindow. Many - * nsWindow methods operate on both child & top-level windows. Where the - * two categories require differing implementations, these methods rely on - * a flag or on virtual helper methods to produce the correct result. + * are created when NS_WINDOW_CID is used to identify the type of object + * needed. Child widgets (windows that either are children of other windows + * or are popups such as menus) are created when NS_CHILD_CID is specified. + * Since Mozilla expects these to be different classes, NS_CHILD_CID is + * mapped to a subclass (nsChildWindow) which acts solely as a wrapper for + * nsWindow and adds no functionality. + * + * While most of the methods inherited from nsIWidget are generic, some + * apply only to toplevel widgets (e.g. setting a title or icon). The + * nature of toplevel windows on OS/2 with their separate frame & client + * windows introduces the need for additional toplevel-specific methods, + * as well as for special handling in otherwise generic methods. + * + * Rather than incorporating these toplevel functions into the body of + * the class, nsWindow delegates them to a helper class, os2FrameWindow. + * An instance of this class is created when nsWindow is told to create + * a toplevel native window and is destroyed in nsWindow's destructor. + * The class's methods operate exclusively on the frame window and never + * deal with the frame's client other than to create it. Similarly, + * nsWindow never operates on frame windows except for a few trivial + * methods (e.g. Enable()). Neither class accesses the other's data + * though, of necessity, both call the other's methods. * */ //============================================================================= @@ -123,18 +140,12 @@ extern "C" { //#define DEBUG_FOCUS -#ifdef DEBUG_FOCUS - #define DEBUGFOCUS(what) fprintf(stderr, "[%8x] %8lx (%02d) "#what"\n", \ - (int)this, mWnd, mWindowIdentifier) -#else - #define DEBUGFOCUS(what) -#endif - //----------------------------------------------------------------------------- // Forward declarations class imgIContainer; class gfxOS2Surface; +class os2FrameWindow; MRESULT EXPENTRY fnwpNSWindow(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2); MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2); @@ -215,11 +226,11 @@ protected: // nsWindow static void InitGlobals(); - virtual nsresult CreateWindow(nsWindow* aParent, + nsresult CreateWindow(nsWindow* aParent, HWND aParentWnd, const nsIntRect& aRect, - PRUint32 aStyle); - virtual HWND GetMainWindow() const {return mWnd;} + nsWidgetInitData* aInitData); + HWND GetMainWindow(); static nsWindow* GetNSWindowPtr(HWND aWnd); static PRBool SetNSWindowPtr(HWND aWnd, nsWindow* aPtr); void NS2PM(POINTL& ptl); @@ -228,7 +239,7 @@ protected: void ActivatePlugin(HWND aWnd); void SetPluginClipRegion(const Configuration& aConfiguration); HWND GetPluginClipWindow(HWND aParentWnd); - virtual void ActivateTopLevelWidget(); + void ActivateTopLevelWidget(); HBITMAP DataToBitmap(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth); HBITMAP CreateBitmapRGB(PRUint8* aImageData, @@ -240,7 +251,7 @@ protected: static PRBool RollupOnButtonDown(ULONG aMsg); static void RollupOnFocusLost(HWND aFocus); MRESULT ProcessMessage(ULONG msg, MPARAM mp1, MPARAM mp2); - virtual PRBool OnReposition(PSWP pNewSwp); + PRBool OnReposition(PSWP pNewSwp); PRBool OnPaint(); PRBool OnMouseChord(MPARAM mp1, MPARAM mp2); PRBool OnDragDropMsg(ULONG msg, MPARAM mp1, MPARAM mp2, @@ -264,16 +275,16 @@ protected: PRInt16 aButton = nsMouseEvent::eLeftButton); PRBool DispatchActivationEvent(PRUint32 aEventType); PRBool DispatchScrollEvent(ULONG msg, MPARAM mp1, MPARAM mp2); - virtual PRInt32 GetClientHeight() {return mBounds.height;} friend MRESULT EXPENTRY fnwpNSWindow(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2); friend MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2); + friend class os2FrameWindow; HWND mWnd; // window handle nsWindow* mParent; // parent widget - PRBool mIsTopWidgetWindow; // is nsFrameWindow class? + os2FrameWindow* mFrame; // ptr to os2FrameWindow helper object PRInt32 mWindowState; // current nsWindowState_* value PRBool mIsDestroying; // in destructor PRBool mInSetFocus; // prevent recursive calls @@ -283,14 +294,24 @@ protected: HPOINTER mCssCursorHPtr; // created by SetCursor(imgIContainer*) nsCOMPtr mCssCursorImg;// saved by SetCursor(imgIContainer*) nsRefPtr mThebesSurface; - HWND mFrameWnd; // frame window handle - HPOINTER mFrameIcon; // current frame icon - PRBool mChromeHidden; // are frame controls hidden? #ifdef DEBUG_FOCUS int mWindowIdentifier; // a serial number for each new window #endif }; +//============================================================================= +// nsChildWindow +//============================================================================= + +// This only purpose of this subclass is to map NS_CHILD_CID to +// some class other than nsWindow which is mapped to NS_WINDOW_CID. + +class nsChildWindow : public nsWindow { +public: + nsChildWindow() {} + ~nsChildWindow() {} +}; + #endif // _nswindow_h //============================================================================= diff --git a/widget/src/os2/os2FrameWindow.cpp b/widget/src/os2/os2FrameWindow.cpp new file mode 100644 index 000000000000..5f67abc88bcd --- /dev/null +++ b/widget/src/os2/os2FrameWindow.cpp @@ -0,0 +1,745 @@ +/* vim: set sw=2 sts=2 et cin: */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla OS/2 libraries. + * + * The Initial Developer of the Original Code is + * John Fairhurst, . + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Rich Walsh + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** + * + * This Original Code has been modified by IBM Corporation. + * Modifications made by IBM are + * Copyright (c) International Business Machines Corporation, 2000 + * + */ +//============================================================================= + +#include "nsWindow.h" +#include "os2FrameWindow.h" +#include "nsIRollupListener.h" +#include "nsIScreenManager.h" +#include "nsOS2Uni.h" + +//----------------------------------------------------------------------------- +// External Variables (in nsWindow.cpp) + +extern nsIRollupListener* gRollupListener; +extern nsIWidget* gRollupWidget; +extern PRBool gRollupConsumeRollupEvent; +extern PRUint32 gOS2Flags; + +#ifdef DEBUG_FOCUS + extern int currentWindowIdentifier; +#endif + +//----------------------------------------------------------------------------- +// Debug + +#ifdef DEBUG_FOCUS + #define DEBUGFOCUS(what) fprintf(stderr, "[%8x] %8lx (%02d) "#what"\n", \ + (int)this, mFrameWnd, mWindowIdentifier) +#else + #define DEBUGFOCUS(what) +#endif + +//============================================================================= +// os2FrameWindow Setup +//============================================================================= + +os2FrameWindow::os2FrameWindow(nsWindow* aOwner) +{ + mOwner = aOwner; + mFrameWnd = 0; + mTitleBar = 0; + mSysMenu = 0; + mMinMax = 0; + mSavedStyle = 0; + mFrameIcon = 0; + mChromeHidden = PR_FALSE; + mNeedActivation = PR_FALSE; + mPrevFrameProc = 0; + mFrameBounds = nsIntRect(0, 0, 0, 0); +} + +//----------------------------------------------------------------------------- + +os2FrameWindow::~os2FrameWindow() +{ + if (mFrameIcon) { + WinFreeFileIcon(mFrameIcon); + mFrameIcon = 0; + } +} + +//----------------------------------------------------------------------------- +// Create frame & client windows for an os2FrameWindow object; return the +// handle of the client window. This is the only method that manipulates +// the client window - all other operations on it are handled by nsWindow. + +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; + PRUint32 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(PR_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. + PRInt32 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; +} + +//----------------------------------------------------------------------------- + +PRUint32 os2FrameWindow::GetFCFlags(nsWindowType aWindowType, + nsBorderStyle aBorderStyle) +{ + PRUint32 style = FCF_TITLEBAR | FCF_SYSMENU | FCF_TASKLIST | + FCF_CLOSEBUTTON | FCF_NOBYTEALIGN | FCF_AUTOICON; + + if (aWindowType == eWindowType_dialog) { + if (aBorderStyle == eBorderStyle_default) { + style |= FCF_DLGBORDER; + } else { + style |= FCF_SIZEBORDER | FCF_MINMAX; + } + } + else { + style |= FCF_SIZEBORDER | FCF_MINMAX; + } + + if (gOS2Flags & kIsDBCS) { + style |= FCF_DBE_APPSTAT; + } + if (aWindowType == eWindowType_invisible) { + style &= ~FCF_TASKLIST; + } + + if (aBorderStyle != eBorderStyle_default && + aBorderStyle != eBorderStyle_all) { + if (aBorderStyle == eBorderStyle_none || + !(aBorderStyle & eBorderStyle_resizeh)) { + style &= ~FCF_SIZEBORDER; + style |= FCF_DLGBORDER; + } + if (aBorderStyle == eBorderStyle_none || + !(aBorderStyle & eBorderStyle_border)) { + style &= ~(FCF_DLGBORDER | FCF_SIZEBORDER); + } + if (aBorderStyle == eBorderStyle_none || + !(aBorderStyle & eBorderStyle_title)) { + style &= ~(FCF_TITLEBAR | FCF_TASKLIST); + } + if (aBorderStyle == eBorderStyle_none || + !(aBorderStyle & eBorderStyle_close)) { + style &= ~FCF_CLOSEBUTTON; + } + if (aBorderStyle == eBorderStyle_none || + !(aBorderStyle & (eBorderStyle_menu | eBorderStyle_close))) { + style &= ~FCF_SYSMENU; + } + + // Looks like getting rid of the system menu also does away + // with the close box. So, we only get rid of the system menu + // if you want neither it nor the close box. + + if (aBorderStyle == eBorderStyle_none || + !(aBorderStyle & eBorderStyle_minimize)) { + style &= ~FCF_MINBUTTON; + } + if (aBorderStyle == eBorderStyle_none || + !(aBorderStyle & eBorderStyle_maximize)) { + style &= ~FCF_MAXBUTTON; + } + } + + return style; +} + +//============================================================================= +// Window Operations +//============================================================================= + +// For frame windows, 'Show' is equivalent to 'Show & Activate'. + +nsresult os2FrameWindow::Show(PRBool aState) +{ + PRUint32 ulFlags; + if (!aState) { + ulFlags = SWP_HIDE | SWP_DEACTIVATE; + } else { + ulFlags = SWP_SHOW | SWP_ACTIVATE; + + PRUint32 ulStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE); + PRInt32 sizeMode; + mOwner->GetSizeMode(&sizeMode); + if (!(ulStyle & WS_VISIBLE)) { + if (sizeMode == nsSizeMode_Maximized) { + ulFlags |= SWP_MAXIMIZE; + } else if (sizeMode == nsSizeMode_Minimized) { + ulFlags |= SWP_MINIMIZE; + } else { + ulFlags |= SWP_RESTORE; + } + } else if (ulStyle & WS_MINIMIZED) { + if (sizeMode == nsSizeMode_Maximized) { + ulFlags |= SWP_MAXIMIZE; + } else { + ulFlags |= SWP_RESTORE; + } + } + } + + WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, ulFlags); + SetWindowListVisibility(aState); + + return NS_OK; +} + +//----------------------------------------------------------------------------- + +void os2FrameWindow::SetWindowListVisibility(PRBool aState) +{ + HSWITCH hswitch = WinQuerySwitchHandle(mFrameWnd, 0); + if (hswitch) { + SWCNTRL swctl; + WinQuerySwitchEntry(hswitch, &swctl); + swctl.uchVisibility = aState ? SWL_VISIBLE : SWL_INVISIBLE; + swctl.fbJump = aState ? SWL_JUMPABLE : SWL_NOTJUMPABLE; + WinChangeSwitchEntry(hswitch, &swctl); + } +} + +//============================================================================= +// Window Positioning +//============================================================================= + +nsresult os2FrameWindow::GetBounds(nsIntRect& aRect) +{ + aRect = mFrameBounds; + return NS_OK; +} + +//----------------------------------------------------------------------------- + +nsresult os2FrameWindow::Move(PRInt32 aX, PRInt32 aY) +{ + aY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - mFrameBounds.height - aY; + WinSetWindowPos(mFrameWnd, 0, aX, aY, 0, 0, SWP_MOVE); + return NS_OK; +} + +//----------------------------------------------------------------------------- + +nsresult os2FrameWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, + PRBool aRepaint) +{ + WinSetWindowPos(mFrameWnd, 0, 0, 0, aWidth, aHeight, SWP_SIZE); + return NS_OK; +} + +//----------------------------------------------------------------------------- + +nsresult os2FrameWindow::Resize(PRInt32 aX, PRInt32 aY, + PRInt32 aWidth, PRInt32 aHeight, + PRBool aRepaint) +{ + aY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - aY - aHeight; + WinSetWindowPos(mFrameWnd, 0, aX, aY, aWidth, aHeight, SWP_MOVE | SWP_SIZE); + return NS_OK; +} + +//============================================================================= +// Top-level (frame window) Operations +//============================================================================= + +// When WM_ACTIVATE is received with the "gaining activation" flag set, +// the frame's wndproc sets mNeedActivation. Later, when an nsWindow +// gets a WM_FOCUSCHANGED msg with the "gaining focus" flag set, it +// invokes this method on os2FrameWindow to fire an NS_ACTIVATE event. + +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) { + PRInt32 sizeMode; + mOwner->GetSizeMode(&sizeMode); + if (sizeMode != nsSizeMode_Minimized) { + mNeedActivation = PR_FALSE; + DEBUGFOCUS(NS_ACTIVATE); + mOwner->DispatchActivationEvent(NS_ACTIVATE); + } + } + return; +} + +//----------------------------------------------------------------------------- +// Maximize, minimize or restore the window. When the frame has its +// controls, this method is advisory because the min/max/restore has +// already occurred. Only when the frame is in kiosk/fullscreen mode +// does it perform the minimize or restore + +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; +} + +//----------------------------------------------------------------------------- +// Hide or show the frame & its controls (titlebar, minmax, etc.). + +nsresult os2FrameWindow::HideWindowChrome(PRBool aShouldHide) +{ + // Putting a maximized window into fullscreen mode causes multiple + // problems if it's later minimized & then restored. To avoid them, + // restore maximized windows before putting them in fullscreen mode. + if (WinQueryWindowULong(mFrameWnd, QWL_STYLE) & WS_MAXIMIZED) { + WinSetWindowPos(mFrameWnd, 0, 0, 0, 0, 0, SWP_RESTORE | SWP_NOREDRAW); + } + + HWND hParent; + if (aShouldHide) { + hParent = HWND_OBJECT; + mChromeHidden = PR_TRUE; + } else { + hParent = mFrameWnd; + mChromeHidden = PR_FALSE; + } + + // Hide or show the frame controls. + WinSetParent(mTitleBar, hParent, FALSE); + WinSetParent(mSysMenu, hParent, FALSE); + WinSetParent(mMinMax, hParent, FALSE); + + // Modify the frame style, then advise it of the changes. + if (aShouldHide) { + mSavedStyle = WinQueryWindowULong(mFrameWnd, QWL_STYLE); + WinSetWindowULong(mFrameWnd, QWL_STYLE, mSavedStyle & ~FS_SIZEBORDER); + WinSendMsg(mFrameWnd, WM_UPDATEFRAME, 0, 0); + } else { + WinSetWindowULong(mFrameWnd, QWL_STYLE, mSavedStyle); + WinSendMsg(mFrameWnd, WM_UPDATEFRAME, + MPFROMLONG(FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX), 0); + } + + return NS_OK; +} + +//----------------------------------------------------------------------------- +// On OS/2, if you pass a titlebar > 512 characters, it doesn't display at all. +// We are going to limit our titlebars to 256 just to be on the safe side. + +#define MAX_TITLEBAR_LENGTH 256 + +nsresult os2FrameWindow::SetTitle(const nsAString& aTitle) +{ + PRUnichar* uchtemp = ToNewUnicode(aTitle); + for (PRUint32 i = 0; i < aTitle.Length(); i++) { + switch (uchtemp[i]) { + case 0x2018: + case 0x2019: + uchtemp[i] = 0x0027; + break; + case 0x201C: + case 0x201D: + uchtemp[i] = 0x0022; + break; + case 0x2014: + uchtemp[i] = 0x002D; + break; + } + } + + nsAutoCharBuffer title; + PRInt32 titleLength; + WideCharToMultiByte(0, uchtemp, aTitle.Length(), title, titleLength); + if (titleLength > MAX_TITLEBAR_LENGTH) { + title[MAX_TITLEBAR_LENGTH] = '\0'; + } + WinSetWindowText(mFrameWnd, title.Elements()); + + // If the chrome is hidden, set the text of the titlebar directly + if (mChromeHidden) { + WinSetWindowText(mTitleBar, title.Elements()); + } + + nsMemory::Free(uchtemp); + return NS_OK; +} + +//----------------------------------------------------------------------------- +// This implementation guarantees that sysmenus & minimized windows +// will always have some icon other than the sysmenu default. + +nsresult os2FrameWindow::SetIcon(const nsAString& aIconSpec) +{ + static HPOINTER hDefaultIcon = 0; + HPOINTER hWorkingIcon = 0; + + // Assume the given string is a local identifier for an icon file. + nsCOMPtr iconFile; + mOwner->ResolveIconName(aIconSpec, NS_LITERAL_STRING(".ico"), + getter_AddRefs(iconFile)); + + // if the file was found, try to use it + if (iconFile) { + nsCAutoString path; + iconFile->GetNativePath(path); + + if (mFrameIcon) { + WinFreeFileIcon(mFrameIcon); + } + mFrameIcon = WinLoadFileIcon(path.get(), FALSE); + hWorkingIcon = mFrameIcon; + } + + // if that doesn't work, use the app's icon (let's hope it can be + // loaded because nobody should have to look at SPTR_APPICON) + if (!hWorkingIcon) { + if (!hDefaultIcon) { + hDefaultIcon = WinLoadPointer(HWND_DESKTOP, 0, 1); + if (!hDefaultIcon) { + hDefaultIcon = WinQuerySysPointer(HWND_DESKTOP, SPTR_APPICON, FALSE); + } + } + hWorkingIcon = hDefaultIcon; + } + + WinSendMsg(mFrameWnd, WM_SETICON, (MPARAM)hWorkingIcon, (MPARAM)0); + return NS_OK; +} + +//----------------------------------------------------------------------------- +// Constrain a potential move to fit onscreen. + +nsresult os2FrameWindow::ConstrainPosition(PRBool aAllowSlop, + PRInt32* aX, PRInt32* aY) +{ + // do we have enough info to do anything + PRBool doConstrain = PR_FALSE; + + // get our playing field. use the current screen, or failing + // that for any reason, use device caps for the default screen. + RECTL screenRect; + + nsCOMPtr screenmgr = + do_GetService("@mozilla.org/gfx/screenmanager;1"); + if (screenmgr) { + nsCOMPtr screen; + PRInt32 left, top, width, height; + + // zero size rects confuse the screen manager + width = mFrameBounds.width > 0 ? mFrameBounds.width : 1; + height = mFrameBounds.height > 0 ? mFrameBounds.height : 1; + screenmgr->ScreenForRect(*aX, *aY, width, height, + getter_AddRefs(screen)); + if (screen) { + screen->GetAvailRect(&left, &top, &width, &height); + screenRect.xLeft = left; + screenRect.xRight = left+width; + screenRect.yTop = top; + screenRect.yBottom = top+height; + doConstrain = PR_TRUE; + } + } + +#define kWindowPositionSlop 100 + + if (doConstrain) { + if (aAllowSlop) { + if (*aX < screenRect.xLeft - mFrameBounds.width + kWindowPositionSlop) { + *aX = screenRect.xLeft - mFrameBounds.width + kWindowPositionSlop; + } else + if (*aX >= screenRect.xRight - kWindowPositionSlop) { + *aX = screenRect.xRight - kWindowPositionSlop; + } + + if (*aY < screenRect.yTop) { + *aY = screenRect.yTop; + } else + if (*aY >= screenRect.yBottom - kWindowPositionSlop) { + *aY = screenRect.yBottom - kWindowPositionSlop; + } + } else { + if (*aX < screenRect.xLeft) { + *aX = screenRect.xLeft; + } else + if (*aX >= screenRect.xRight - mFrameBounds.width) { + *aX = screenRect.xRight - mFrameBounds.width; + } + + if (*aY < screenRect.yTop) { + *aY = screenRect.yTop; + } else + if (*aY >= screenRect.yBottom - mFrameBounds.height) { + *aY = screenRect.yBottom - mFrameBounds.height; + } + } + } + + return NS_OK; +} + +//============================================================================= +// os2FrameWindow's Window Procedure +//============================================================================= + +// Subclass for frame window + +MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + // check to see if we have a rollup listener registered + if (gRollupListener && gRollupWidget) { + if (msg == WM_TRACKFRAME || msg == WM_MINMAXFRAME || + msg == WM_BUTTON1DOWN || msg == WM_BUTTON2DOWN || + msg == WM_BUTTON3DOWN) { + // Rollup if the event is outside the popup + if (!nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget)) { + gRollupListener->Rollup(PR_UINT32_MAX, nsnull); + } + } + } + + os2FrameWindow* pFrame = (os2FrameWindow*)WinQueryWindowPtr(hwnd, QWL_USER); + return pFrame->ProcessFrameMessage(msg, mp1, mp2); +} + +//----------------------------------------------------------------------------- +// Process messages from the frame + +MRESULT os2FrameWindow::ProcessFrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2) +{ + MRESULT mresult = 0; + PRBool isDone = PR_FALSE; + + switch (msg) { + case WM_WINDOWPOSCHANGED: { + PSWP pSwp = (PSWP)mp1; + + 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 = PR_TRUE; + } + + if (pSwp->fl & (SWP_MAXIMIZE | SWP_MINIMIZE | SWP_RESTORE)) { + nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, mOwner); + if (pSwp->fl & SWP_MAXIMIZE) { + event.mSizeMode = nsSizeMode_Maximized; + } else if (pSwp->fl & SWP_MINIMIZE) { + event.mSizeMode = nsSizeMode_Minimized; + } else { + event.mSizeMode = nsSizeMode_Normal; + } + mOwner->InitEvent(event); + mOwner->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) { + 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 = PR_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 = PR_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); + mOwner->DispatchActivationEvent(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 (!isDone) { + mresult = (*mPrevFrameProc)(mFrameWnd, msg, mp1, mp2); + } + + return mresult; +} + +//============================================================================= + diff --git a/widget/src/os2/os2FrameWindow.h b/widget/src/os2/os2FrameWindow.h new file mode 100644 index 000000000000..b96553f4d1e4 --- /dev/null +++ b/widget/src/os2/os2FrameWindow.h @@ -0,0 +1,109 @@ +/* vim: set sw=2 sts=2 et cin: */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla OS/2 libraries. + * + * The Initial Developer of the Original Code is + * John Fairhurst, . + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Rich Walsh + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//============================================================================= +/* + * os2FrameWindow is a helper class instantiated by nsWindow to handle + * operations that are specific to OS/2 frame windows. It never references + * the frame's client window except to create it. See nsWindow.h for details. + * Note: nsWindow.h must be #included in *.cpp before #including this file. + * + */ +//============================================================================= + +#ifndef _os2framewindow_h +#define _os2framewindow_h + +//============================================================================= +// os2FrameWindow +//============================================================================= + +class os2FrameWindow +{ +public: + os2FrameWindow(nsWindow* aOwner); + ~os2FrameWindow(); + + HWND CreateFrameWindow(nsWindow* aParent, + HWND aParentWnd, + const nsIntRect& aRect, + nsWindowType aWindowType, + nsBorderStyle aBorderStyle); + PRUint32 GetFCFlags(nsWindowType aWindowType, + nsBorderStyle aBorderStyle); + nsresult Show(PRBool aState); + void SetWindowListVisibility(PRBool aState); + nsresult GetBounds(nsIntRect& aRect); + nsresult Move(PRInt32 aX, PRInt32 aY); + nsresult Resize(PRInt32 aWidth, PRInt32 aHeight, + PRBool aRepaint); + nsresult Resize(PRInt32 aX, PRInt32 aY, PRInt32 w, PRInt32 h, + PRBool aRepaint); + void ActivateTopLevelWidget(); + nsresult SetSizeMode(PRInt32 aMode); + nsresult HideWindowChrome(PRBool aShouldHide); + nsresult SetTitle(const nsAString& aTitle); + nsresult SetIcon(const nsAString& aIconSpec); + nsresult ConstrainPosition(PRBool aAllowSlop, + PRInt32* aX, PRInt32* aY); + MRESULT ProcessFrameMessage(ULONG msg, MPARAM mp1, MPARAM mp2); + HWND GetFrameWnd() {return mFrameWnd;} + + friend MRESULT EXPENTRY fnwpFrame(HWND hwnd, ULONG msg, + MPARAM mp1, MPARAM mp2); + +protected: + nsWindow * mOwner; // the nsWindow that created this instance + HWND mFrameWnd; // the frame's window handle + HWND mTitleBar; // the frame controls that have + HWND mSysMenu; // to be hidden or shown when + HWND mMinMax; // HideWindowChrome() is called + PRUint32 mSavedStyle; // frame style saved by HideWindowChrome() + HPOINTER mFrameIcon; // current frame icon + PRBool mChromeHidden; // are frame controls hidden? + PRBool mNeedActivation; // triggers activation when focus changes + PFNWP mPrevFrameProc; // the frame's original wndproc + nsIntRect mFrameBounds; // the frame's location & dimensions +}; + +#endif //_os2framewindow_h + +//============================================================================= +