1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sts=2 sw=2 et cin: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Dean Tessman <dean_tessman@hotmail.com>
25 * Ere Maijala <emaijala@kolumbus.fi>
26 * Mark Hammond <markh@activestate.com>
27 * Michael Lowe <michael.lowe@bigfoot.com>
28 * Peter Bajusz <hyp-x@inf.bme.hu>
29 * Pierre Phaneuf <pp@ludusdesign.com>
30 * Robert O'Callahan <roc+moz@cs.cmu.edu>
31 * Roy Yokoyama <yokoyama@netscape.com>
32 * Makoto Kato <m_kato@ga2.so-net.ne.jp>
33 * Masayuki Nakano <masayuki@d-toybox.com>
34 * Dainis Jonitis <Dainis_Jonitis@swh-t.lv>
35 * Christian Biesinger <cbiesinger@web.de>
36 * Mats Palmgren <matspal@gmail.com>
37 * Ningjie Chen <chenn@email.uc.edu>
38 * Jim Mathies <jmathies@mozilla.com>
39 * Kyle Huey <me@kylehuey.com>
41 * Alternatively, the contents of this file may be used under the terms of
42 * either the GNU General Public License Version 2 or later (the "GPL"), or
43 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
44 * in which case the provisions of the GPL or the LGPL are applicable instead
45 * of those above. If you wish to allow use of your version of this file only
46 * under the terms of either the GPL or the LGPL, and not to allow others to
47 * use your version of this file under the terms of the MPL, indicate your
48 * decision by deleting the provisions above and replace them with the notice
49 * and other provisions required by the GPL or the LGPL. If you do not delete
50 * the provisions above, a recipient may use your version of this file under
51 * the terms of any one of the MPL, the GPL or the LGPL.
53 * ***** END LICENSE BLOCK ***** */
56 * nsWindow - Native window management and event handling.
58 * nsWindow is organized into a set of major blocks and
59 * block subsections. The layout is as follows:
64 * nsIWidget methods and utilities
65 * nsSwitchToUIThread impl.
66 * nsSwitchToUIThread methods and utilities
68 * Event initialization
73 * OnEvent event handlers
74 * IME management and accessibility
80 * Search for "BLOCK:" to find major blocks.
81 * Search for "SECTION:" to find specific sections.
83 * Blocks should be split out into separate files if they
84 * become unmanageable.
88 * nsWindowDefs.h - Definitions, macros, structs, enums
90 * nsWindowDbg.h/.cpp - Debug related code and directives.
91 * nsWindowGfx.h/.cpp - Graphics and painting.
92 * nsWindowCE.h/.cpp - WINCE specific code that can be
93 * split out from nsWindow.
97 /**************************************************************
98 **************************************************************
104 **************************************************************
105 **************************************************************/
108 #include "mozilla/ipc/RPCChannel.h"
111 #include "nsWindow.h"
115 #include <commctrl.h>
123 #include "nsIAppShell.h"
124 #include "nsISupportsPrimitives.h"
125 #include "nsIDOMNSUIEvent.h"
126 #include "nsITheme.h"
127 #include "nsIPrefBranch.h"
128 #include "nsIPrefBranch2.h"
129 #include "nsIPrefService.h"
130 #include "nsIObserverService.h"
131 #include "nsIScreenManager.h"
132 #include "imgIContainer.h"
134 #include "nsIRollupListener.h"
135 #include "nsIMenuRollup.h"
136 #include "nsIRegion.h"
137 #include "nsIServiceManager.h"
138 #include "nsIClipboard.h"
139 #include "nsIMM32Handler.h"
140 #include "nsILocalFile.h"
141 #include "nsIFontMetrics.h"
142 #include "nsIFontEnumerator.h"
143 #include "nsIDeviceContext.h"
144 #include "nsILookAndFeel.h"
145 #include "nsGUIEvent.h"
148 #include "nsThreadUtils.h"
149 #include "nsNativeCharsetUtils.h"
150 #include "nsWidgetAtoms.h"
151 #include "nsUnicharUtils.h"
153 #include "nsAppDirectoryServiceDefs.h"
154 #include "nsXPIDLString.h"
155 #include "nsWidgetsCID.h"
156 #include "nsTHashtable.h"
157 #include "nsHashKeys.h"
158 #include "nsString.h"
159 #include "mozilla/Services.h"
160 #include "nsNativeThemeWin.h"
163 #include "nsWindowCE.h"
166 #if defined(WINCE_WINDOWS_MOBILE)
167 #define KILL_PRIORITY_ID 2444
170 #include "nsWindowGfx.h"
171 #include "gfxWindowsPlatform.h"
174 #ifdef MOZ_ENABLE_D3D9_LAYER
175 #include "LayerManagerD3D9.h"
177 #include "LayerManagerOGL.h"
179 #include "BasicLayers.h"
182 #include "nsUXThemeConstants.h"
183 #include "KeyboardLayout.h"
184 #include "nsNativeDragTarget.h"
185 #include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
188 #include <richedit.h>
189 #endif // !defined(WINCE)
191 #if defined(ACCESSIBILITY)
194 #include "nsIAccessibleDocument.h"
195 #if !defined(WINABLEAPI)
197 #endif // !defined(WINABLEAPI)
198 #endif // defined(ACCESSIBILITY)
200 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
201 #include "nsIWinTaskbar.h"
204 #if defined(NS_ENABLE_TSF)
205 #include "nsTextStore.h"
206 #endif // defined(NS_ENABLE_TSF)
208 #if defined(MOZ_SPLASHSCREEN)
209 #include "nsSplashScreen.h"
210 #endif // defined(MOZ_SPLASHSCREEN)
212 // Windowless plugin support
215 #include "nsWindowDefs.h"
217 #include "mozilla/FunctionTimer.h"
219 #ifdef WINCE_WINDOWS_MOBILE
220 #include "nsGfxCIID.h"
223 #include "mozilla/FunctionTimer.h"
225 #ifdef MOZ_CRASHREPORTER
226 #include "nsICrashReporter.h"
229 using namespace mozilla::widget
;
231 /**************************************************************
232 **************************************************************
236 ** nsWindow Class static initializations and global variables.
238 **************************************************************
239 **************************************************************/
241 /**************************************************************
243 * SECTION: nsWindow statics
245 **************************************************************/
247 PRUint32
nsWindow::sInstanceCount
= 0;
248 PRBool
nsWindow::sSwitchKeyboardLayout
= PR_FALSE
;
249 BOOL
nsWindow::sIsRegistered
= FALSE
;
250 BOOL
nsWindow::sIsPopupClassRegistered
= FALSE
;
251 BOOL
nsWindow::sIsOleInitialized
= FALSE
;
252 HCURSOR
nsWindow::sHCursor
= NULL
;
253 imgIContainer
* nsWindow::sCursorImgContainer
= nsnull
;
254 nsWindow
* nsWindow::sCurrentWindow
= nsnull
;
255 PRBool
nsWindow::sJustGotDeactivate
= PR_FALSE
;
256 PRBool
nsWindow::sJustGotActivate
= PR_FALSE
;
258 // imported in nsWidgetFactory.cpp
259 TriStateBool
nsWindow::sCanQuit
= TRI_UNKNOWN
;
261 // Hook Data Memebers for Dropdowns. sProcessHook Tells the
262 // hook methods whether they should be processing the hook
264 HHOOK
nsWindow::sMsgFilterHook
= NULL
;
265 HHOOK
nsWindow::sCallProcHook
= NULL
;
266 HHOOK
nsWindow::sCallMouseHook
= NULL
;
267 PRPackedBool
nsWindow::sProcessHook
= PR_FALSE
;
268 UINT
nsWindow::sRollupMsgId
= 0;
269 HWND
nsWindow::sRollupMsgWnd
= NULL
;
270 UINT
nsWindow::sHookTimerId
= 0;
273 nsIRollupListener
* nsWindow::sRollupListener
= nsnull
;
274 nsIMenuRollup
* nsWindow::sMenuRollup
= nsnull
;
275 nsIWidget
* nsWindow::sRollupWidget
= nsnull
;
276 PRBool
nsWindow::sRollupConsumeEvent
= PR_FALSE
;
278 // Mouse Clicks - static variable definitions for figuring
280 POINT
nsWindow::sLastMousePoint
= {0};
281 POINT
nsWindow::sLastMouseMovePoint
= {0};
282 LONG
nsWindow::sLastMouseDownTime
= 0L;
283 LONG
nsWindow::sLastClickCount
= 0L;
284 BYTE
nsWindow::sLastMouseButton
= 0;
286 // Trim heap on minimize. (initialized, but still true.)
287 int nsWindow::sTrimOnMinimize
= 2;
289 // Default Trackpoint Hack to off
290 PRBool
nsWindow::sTrackPointHack
= PR_FALSE
;
293 BOOL
nsWindow::sIsAccessibilityOn
= FALSE
;
294 // Accessibility wm_getobject handler
295 HINSTANCE
nsWindow::sAccLib
= 0;
296 LPFNLRESULTFROMOBJECT
297 nsWindow::sLresultFromObject
= 0;
298 #endif // ACCESSIBILITY
301 // Used in OOPP plugin focus processing.
302 const PRUnichar
* kOOPPPluginFocusEventId
= L
"OOPP Plugin Focus Widget Event";
303 PRUint32
nsWindow::sOOPPPluginFocusEvent
=
304 RegisterWindowMessageW(kOOPPPluginFocusEventId
);
307 /**************************************************************
309 * SECTION: globals variables
311 **************************************************************/
313 static const char *sScreenManagerContractID
= "@mozilla.org/gfx/screenmanager;1";
316 PRLogModuleInfo
* gWindowsLog
= nsnull
;
320 // Kbd layout. Used throughout character processing.
321 static KeyboardLayout gKbdLayout
;
324 #ifdef WINCE_WINDOWS_MOBILE
325 // HTC Navigation Wheel Event
326 // This is the defined value for Gesture Mode
327 const int WM_HTCNAV
= 0x0400 + 200;
329 typedef int (__stdcall
* HTCApiNavOpen
)(HANDLE
, int);
330 typedef int (__stdcall
* HTCApiNavSetMode
)(HANDLE
, unsigned int);
332 HTCApiNavOpen gHTCApiNavOpen
= nsnull
;
333 HTCApiNavSetMode gHTCApiNavSetMode
= nsnull
;
334 static PRBool gCheckForHTCApi
= PR_FALSE
;
337 // Global user preference for disabling native theme. Used
338 // in NativeWindowTheme.
339 PRBool gDisableNativeTheme
= PR_FALSE
;
341 // Global used in Show window enumerations.
342 static PRBool gWindowsVisible
= PR_FALSE
;
344 static NS_DEFINE_CID(kCClipboardCID
, NS_CLIPBOARD_CID
);
345 #ifdef WINCE_WINDOWS_MOBILE
346 static NS_DEFINE_CID(kRegionCID
, NS_REGION_CID
);
349 /**************************************************************
350 **************************************************************
352 ** BLOCK: nsIWidget impl.
354 ** nsIWidget interface implementation, broken down into
357 **************************************************************
358 **************************************************************/
360 /**************************************************************
362 * SECTION: nsWindow construction and destruction
364 **************************************************************/
366 nsWindow::nsWindow() : nsBaseWidget()
370 gWindowsLog
= PR_NewLogModule("nsWindowsWidgets");
375 mPrevWndProc
= nsnull
;
377 mNativeDragTarget
= nsnull
;
379 mIsVisible
= PR_FALSE
;
380 mIsInMouseCapture
= PR_FALSE
;
381 mIsTopWidgetWindow
= PR_FALSE
;
382 mUnicodeWidget
= PR_TRUE
;
383 mDisplayPanFeedback
= PR_FALSE
;
384 mTouchWindow
= PR_FALSE
;
385 mCustomNonClient
= PR_FALSE
;
386 mHideChrome
= PR_FALSE
;
387 mWindowType
= eWindowType_child
;
388 mBorderStyle
= eBorderStyle_default
;
389 mPopupType
= ePopupTypeAny
;
390 mOldSizeMode
= nsSizeMode_Normal
;
394 mLastSize
.height
= 0;
398 mExitToNonClientArea
= 0;
399 mLastKeyboardLayout
= 0;
400 mBlurSuppressLevel
= 0;
401 mIMEEnabled
= nsIWidget::IME_STATUS_ENABLED
;
403 mTransparentSurface
= nsnull
;
405 mTransparencyMode
= eTransparencyOpaque
;
406 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
407 memset(&mGlassMargins
, 0, sizeof mGlassMargins
);
408 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
410 mBackground
= ::GetSysColor(COLOR_BTNFACE
);
411 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
412 mForeground
= ::GetSysColor(COLOR_WINDOWTEXT
);
414 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
415 mTaskbarPreview
= nsnull
;
416 mHasTaskbarIconBeenCreated
= PR_FALSE
;
419 // Global initialization
420 if (!sInstanceCount
) {
422 gKbdLayout
.LoadLayout(::GetKeyboardLayout(0));
426 nsIMM32Handler::Initialize();
429 nsTextStore::Initialize();
433 if (SUCCEEDED(::OleInitialize(NULL
)))
434 sIsOleInitialized
= TRUE
;
435 NS_ASSERTION(sIsOleInitialized
, "***** OLE is not initialized!\n");
438 #if defined(HEAP_DUMP_EVENT)
443 InitTrackPointHack();
446 // Init titlebar button info for custom frames.
447 nsUXThemeData::InitTitlebarInfo();
450 mIdleService
= nsnull
;
455 nsWindow::~nsWindow()
459 // If the widget was released without calling Destroy() then the native window still
460 // exists, and we need to destroy it. This will also result in a call to OnDestroy.
462 // XXX How could this happen???
469 if (sInstanceCount
== 0) {
471 nsTextStore::Terminate();
475 NS_IF_RELEASE(sCursorImgContainer
);
476 if (sIsOleInitialized
) {
477 ::OleFlushClipboard();
479 sIsOleInitialized
= FALSE
;
481 // delete any of the IME structures that we allocated
482 nsIMM32Handler::Terminate();
483 #endif // !defined(WINCE)
487 NS_IF_RELEASE(mNativeDragTarget
);
488 #endif // !defined(WINCE)
491 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow
, nsBaseWidget
)
493 /**************************************************************
495 * SECTION: nsIWidget::Create, nsIWidget::Destroy
497 * Creating and destroying windows for this widget.
499 **************************************************************/
501 // Allow Derived classes to modify the height that is passed
502 // when the window is created or resized. Also add extra height
503 // if needed (on Windows CE)
504 PRInt32
nsWindow::GetHeight(PRInt32 aProposedHeight
)
508 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
509 DWORD style
= WindowStyle();
510 if ((style
& WS_SYSMENU
) && (style
& WS_POPUP
)) {
511 extra
= GetSystemMetrics(SM_CYCAPTION
);
515 return aProposedHeight
+ extra
;
518 // Create the proper widget
520 nsWindow::Create(nsIWidget
*aParent
,
521 nsNativeWidget aNativeParent
,
522 const nsIntRect
&aRect
,
523 EVENT_CALLBACK aHandleEventFunction
,
524 nsIDeviceContext
*aContext
,
525 nsIAppShell
*aAppShell
,
526 nsIToolkit
*aToolkit
,
527 nsWidgetInitData
*aInitData
)
529 nsWidgetInitData defaultInitData
;
531 aInitData
= &defaultInitData
;
533 mUnicodeWidget
= aInitData
->mUnicode
;
535 nsIWidget
*baseParent
= aInitData
->mWindowType
== eWindowType_dialog
||
536 aInitData
->mWindowType
== eWindowType_toplevel
||
537 aInitData
->mWindowType
== eWindowType_invisible
?
540 mIsTopWidgetWindow
= (nsnull
== baseParent
);
541 mBounds
.width
= aRect
.width
;
542 mBounds
.height
= aRect
.height
;
544 BaseCreate(baseParent
, aRect
, aHandleEventFunction
, aContext
,
545 aAppShell
, aToolkit
, aInitData
);
548 if (aParent
) { // has a nsIWidget parent
549 parent
= aParent
? (HWND
)aParent
->GetNativeData(NS_NATIVE_WINDOW
) : NULL
;
551 } else { // has a nsNative parent
552 parent
= (HWND
)aNativeParent
;
553 mParent
= aNativeParent
? GetNSWindowPtr((HWND
)aNativeParent
) : nsnull
;
556 mPopupType
= aInitData
->mPopupHint
;
557 mContentType
= aInitData
->mContentType
;
559 DWORD style
= WindowStyle();
560 DWORD extendedStyle
= WindowExStyle();
562 if (aInitData
->mRTL
) {
563 extendedStyle
|= WS_EX_LAYOUTRTL
| WS_EX_NOINHERITLAYOUT
;
566 if (mWindowType
== eWindowType_popup
) {
569 } else if (mWindowType
== eWindowType_invisible
) {
570 // Make sure CreateWindowEx succeeds at creating a toplevel window
571 style
&= ~0x40000000; // WS_CHILDWINDOW
573 // See if the caller wants to explictly set clip children and clip siblings
574 if (aInitData
->clipChildren
) {
575 style
|= WS_CLIPCHILDREN
;
577 style
&= ~WS_CLIPCHILDREN
;
579 if (aInitData
->clipSiblings
) {
580 style
|= WS_CLIPSIBLINGS
;
584 mWnd
= ::CreateWindowExW(extendedStyle
,
585 aInitData
->mDropShadow
?
586 WindowPopupClass() : WindowClass(),
592 GetHeight(aRect
.height
),
595 nsToolkit::mDllInstance
,
599 NS_WARNING("nsWindow CreateWindowEx failed.");
600 return NS_ERROR_FAILURE
;
603 if (nsWindow::sTrackPointHack
&&
604 mWindowType
!= eWindowType_plugin
&&
605 mWindowType
!= eWindowType_invisible
) {
606 // Ugly Thinkpad Driver Hack (Bug 507222)
607 // We create an invisible scrollbar to trick the
608 // Trackpoint driver into sending us scrolling messages
609 ::CreateWindowW(L
"SCROLLBAR", L
"FAKETRACKPOINTSCROLLBAR",
610 WS_CHILD
| WS_VISIBLE
, 0,0,0,0, mWnd
, NULL
,
611 nsToolkit::mDllInstance
, NULL
);
614 // call the event callback to notify about creation
616 DispatchStandardEvent(NS_CREATE
);
617 SubclassWindow(TRUE
);
619 if (sTrimOnMinimize
== 2 && mWindowType
== eWindowType_invisible
) {
620 /* The internal variable set by the config.trim_on_minimize pref
621 has not yet been initialized, and this is the hidden window
622 (conveniently created before any visible windows, and after
623 the profile has been initialized).
625 Default config.trim_on_minimize to false, to fix bug 76831
626 for good. If anyone complains about this new default, saying
627 that a Mozilla app hogs too much memory while minimized, they
628 will have that entire bug tattooed on their backside. */
631 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
633 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
634 prefs
->GetBranch(0, getter_AddRefs(prefBranch
));
638 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("config.trim_on_minimize",
643 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("intl.keyboard.per_window_layout",
645 sSwitchKeyboardLayout
= temp
;
647 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("mozilla.widget.disable-native-theme",
649 gDisableNativeTheme
= temp
;
653 #if defined(WINCE_HAVE_SOFTKB)
654 if (mWindowType
== eWindowType_dialog
|| mWindowType
== eWindowType_toplevel
)
655 nsWindowCE::CreateSoftKeyMenuBar(mWnd
);
661 // Close this nsWindow
662 NS_METHOD
nsWindow::Destroy()
664 // WM_DESTROY has already fired, we're done.
668 // During the destruction of all of our children, make sure we don't get deleted.
669 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
672 * On windows the LayerManagerOGL destructor wants the widget to be around for
673 * cleanup. It also would like to have the HWND intact, so we NULL it here.
676 mLayerManager
->Destroy();
678 mLayerManager
= nsnull
;
680 /* We should clear our cached resources now and not wait for the GC to
681 * delete the nsWindow. */
682 ClearCachedResources();
684 // The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
685 // and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
686 // from it. The function also destroys the window's menu, flushes the thread message queue,
687 // destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if
688 // the window is at the top of the viewer chain).
690 // If the specified window is a parent or owner window, DestroyWindow automatically destroys
691 // the associated child or owned windows when it destroys the parent or owner window. The
692 // function first destroys child or owned windows, and then it destroys the parent or owner
694 VERIFY(::DestroyWindow(mWnd
));
696 // Our windows can be subclassed which may prevent us receiving WM_DESTROY. If OnDestroy()
697 // didn't get called, call it now.
698 if (PR_FALSE
== mOnDestroyCalled
)
704 /**************************************************************
706 * SECTION: Window class utilities
708 * Utilities for calculating the proper window class name for
711 **************************************************************/
713 // Return the proper window class for everything except popups.
714 LPCWSTR
nsWindow::WindowClass()
716 if (!nsWindow::sIsRegistered
) {
719 // wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
720 wc
.style
= CS_DBLCLKS
;
721 wc
.lpfnWndProc
= ::DefWindowProcW
;
724 wc
.hInstance
= nsToolkit::mDllInstance
;
725 wc
.hIcon
= ::LoadIconW(::GetModuleHandleW(NULL
), (LPWSTR
)IDI_APPLICATION
);
727 wc
.hbrBackground
= mBrush
;
728 wc
.lpszMenuName
= NULL
;
729 wc
.lpszClassName
= kClassNameHidden
;
731 BOOL succeeded
= ::RegisterClassW(&wc
) != 0 &&
732 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError();
733 nsWindow::sIsRegistered
= succeeded
;
735 wc
.lpszClassName
= kClassNameContentFrame
;
736 if (!::RegisterClassW(&wc
) &&
737 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
738 nsWindow::sIsRegistered
= FALSE
;
741 wc
.lpszClassName
= kClassNameContent
;
742 if (!::RegisterClassW(&wc
) &&
743 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
744 nsWindow::sIsRegistered
= FALSE
;
747 wc
.lpszClassName
= kClassNameUI
;
748 if (!::RegisterClassW(&wc
) &&
749 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
750 nsWindow::sIsRegistered
= FALSE
;
753 wc
.lpszClassName
= kClassNameGeneral
;
754 ATOM generalClassAtom
= ::RegisterClassW(&wc
);
755 if (!generalClassAtom
&&
756 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
757 nsWindow::sIsRegistered
= FALSE
;
760 wc
.lpszClassName
= kClassNameDialog
;
762 if (!::RegisterClassW(&wc
) &&
763 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
764 nsWindow::sIsRegistered
= FALSE
;
768 if (mWindowType
== eWindowType_invisible
) {
769 return kClassNameHidden
;
771 if (mWindowType
== eWindowType_dialog
) {
772 return kClassNameDialog
;
774 if (mContentType
== eContentTypeContent
) {
775 return kClassNameContent
;
777 if (mContentType
== eContentTypeContentFrame
) {
778 return kClassNameContentFrame
;
780 if (mContentType
== eContentTypeUI
) {
783 return kClassNameGeneral
;
786 // Return the proper popup window class
787 LPCWSTR
nsWindow::WindowPopupClass()
789 if (!nsWindow::sIsPopupClassRegistered
) {
792 wc
.style
= CS_DBLCLKS
| CS_XP_DROPSHADOW
;
793 wc
.lpfnWndProc
= ::DefWindowProcW
;
796 wc
.hInstance
= nsToolkit::mDllInstance
;
797 wc
.hIcon
= ::LoadIconW(::GetModuleHandleW(NULL
), (LPWSTR
)IDI_APPLICATION
);
799 wc
.hbrBackground
= mBrush
;
800 wc
.lpszMenuName
= NULL
;
801 wc
.lpszClassName
= kClassNameDropShadow
;
803 nsWindow::sIsPopupClassRegistered
= ::RegisterClassW(&wc
);
804 if (!nsWindow::sIsPopupClassRegistered
) {
805 // For older versions of Win32 (i.e., not XP), the registration will
806 // fail, so we have to re-register without the CS_XP_DROPSHADOW flag.
807 wc
.style
= CS_DBLCLKS
;
808 nsWindow::sIsPopupClassRegistered
= ::RegisterClassW(&wc
);
812 return kClassNameDropShadow
;
815 /**************************************************************
817 * SECTION: Window styles utilities
819 * Return the proper windows styles and extended styles.
821 **************************************************************/
823 // Return nsWindow styles
824 #if !defined(WINCE) // implemented in nsWindowCE.cpp
825 DWORD
nsWindow::WindowStyle()
829 switch (mWindowType
) {
830 case eWindowType_plugin
:
831 case eWindowType_child
:
832 style
= WS_OVERLAPPED
;
835 case eWindowType_dialog
:
836 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
| DS_3DLOOK
|
837 DS_MODALFRAME
| WS_CLIPCHILDREN
;
838 if (mBorderStyle
!= eBorderStyle_default
)
839 style
|= WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
842 case eWindowType_popup
:
845 style
|= WS_OVERLAPPED
;
850 NS_ERROR("unknown border style");
853 case eWindowType_toplevel
:
854 case eWindowType_invisible
:
855 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
|
856 WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPCHILDREN
;
860 if (mBorderStyle
!= eBorderStyle_default
&& mBorderStyle
!= eBorderStyle_all
) {
861 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_border
))
864 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_title
)) {
865 style
&= ~WS_DLGFRAME
;
870 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_close
))
872 // XXX The close box can only be removed by changing the window class,
873 // as far as I know --- roc+moz@cs.cmu.edu
875 if (mBorderStyle
== eBorderStyle_none
||
876 !(mBorderStyle
& (eBorderStyle_menu
| eBorderStyle_close
)))
877 style
&= ~WS_SYSMENU
;
878 // Looks like getting rid of the system menu also does away with the
879 // close box. So, we only get rid of the system menu if you want neither it
880 // nor the close box. How does the Windows "Dialog" window class get just
881 // closebox and no sysmenu? Who knows.
883 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_resizeh
))
884 style
&= ~WS_THICKFRAME
;
886 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_minimize
))
887 style
&= ~WS_MINIMIZEBOX
;
889 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_maximize
))
890 style
&= ~WS_MAXIMIZEBOX
;
892 if (IsPopupWithTitleBar()) {
894 if (mBorderStyle
& eBorderStyle_close
) {
900 VERIFY_WINDOW_STYLE(style
);
903 #endif // !defined(WINCE)
905 // Return nsWindow extended styles
906 DWORD
nsWindow::WindowExStyle()
910 case eWindowType_plugin
:
911 case eWindowType_child
:
914 case eWindowType_dialog
:
915 return WS_EX_WINDOWEDGE
| WS_EX_DLGMODALFRAME
;
917 case eWindowType_popup
:
919 DWORD extendedStyle
=
920 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
924 if (mPopupLevel
== ePopupLevelTop
)
925 extendedStyle
|= WS_EX_TOPMOST
;
926 return extendedStyle
;
929 NS_ERROR("unknown border style");
932 case eWindowType_toplevel
:
933 case eWindowType_invisible
:
934 return WS_EX_WINDOWEDGE
;
938 /**************************************************************
940 * SECTION: Window subclassing utilities
942 * Set or clear window subclasses on native windows. Used in
943 * Create and Destroy.
945 **************************************************************/
947 // Subclass (or remove the subclass from) this component's nsWindow
948 void nsWindow::SubclassWindow(BOOL bState
)
951 //NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
952 if (!::IsWindow(mWnd
)) {
953 NS_ERROR("Invalid window handle");
957 // change the nsWindow proc
959 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
,
960 (LONG_PTR
)nsWindow::WindowProc
);
962 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
,
963 (LONG_PTR
)nsWindow::WindowProc
);
964 NS_ASSERTION(mPrevWndProc
, "Null standard window procedure");
965 // connect the this pointer to the nsWindow handle
966 SetNSWindowPtr(mWnd
, this);
970 ::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
972 ::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
973 SetNSWindowPtr(mWnd
, NULL
);
979 /**************************************************************
981 * SECTION: Window properties
983 * Set and clear native window properties.
985 **************************************************************/
987 static PRUnichar sPropName
[40] = L
"";
988 static PRUnichar
* GetNSWindowPropName()
992 _snwprintf(sPropName
, 39, L
"MozillansIWidgetPtr%p", GetCurrentProcessId());
993 sPropName
[39] = '\0';
998 nsWindow
* nsWindow::GetNSWindowPtr(HWND aWnd
)
1000 return (nsWindow
*) ::GetPropW(aWnd
, GetNSWindowPropName());
1003 BOOL
nsWindow::SetNSWindowPtr(HWND aWnd
, nsWindow
* ptr
)
1006 ::RemovePropW(aWnd
, GetNSWindowPropName());
1009 return ::SetPropW(aWnd
, GetNSWindowPropName(), (HANDLE
)ptr
);
1013 /**************************************************************
1015 * SECTION: nsIWidget::SetParent, nsIWidget::GetParent
1017 * Set or clear the parent widgets using window properties, and
1018 * handles calculating native parent handles.
1020 **************************************************************/
1022 // Get and set parent widgets
1023 NS_IMETHODIMP
nsWindow::SetParent(nsIWidget
*aNewParent
)
1025 mParent
= aNewParent
;
1028 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
1030 nsIWidget
* parent
= GetParent();
1032 parent
->RemoveChild(this);
1035 HWND newParent
= (HWND
)aNewParent
->GetNativeData(NS_NATIVE_WINDOW
);
1036 NS_ASSERTION(newParent
, "Parent widget has a null native window handle");
1037 if (newParent
&& mWnd
) {
1038 ::SetParent(mWnd
, newParent
);
1041 aNewParent
->AddChild(this);
1046 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
1048 nsIWidget
* parent
= GetParent();
1051 parent
->RemoveChild(this);
1055 // If we have no parent, SetParent should return the desktop.
1056 VERIFY(::SetParent(mWnd
, nsnull
));
1062 nsIWidget
* nsWindow::GetParent(void)
1064 return GetParentWindow(PR_FALSE
);
1067 float nsWindow::GetDPI()
1069 HDC dc
= ::GetDC(mWnd
);
1073 double heightInches
= ::GetDeviceCaps(dc
, VERTSIZE
)/MM_PER_INCH_FLOAT
;
1074 int heightPx
= ::GetDeviceCaps(dc
, VERTRES
);
1075 ::ReleaseDC(mWnd
, dc
);
1076 if (heightInches
< 0.25) {
1077 // Something's broken
1080 return float(heightPx
/heightInches
);
1083 nsWindow
* nsWindow::GetParentWindow(PRBool aIncludeOwner
)
1085 if (mIsTopWidgetWindow
) {
1086 // Must use a flag instead of mWindowType to tell if the window is the
1087 // owned by the topmost widget, because a child window can be embedded inside
1088 // a HWND which is not associated with a nsIWidget.
1092 // If this widget has already been destroyed, pretend we have no parent.
1093 // This corresponds to code in Destroy which removes the destroyed
1094 // widget from its parent's child list.
1095 if (mInDtor
|| mOnDestroyCalled
)
1099 // aIncludeOwner set to true implies walking the parent chain to retrieve the
1100 // root owner. aIncludeOwner set to false implies the search will stop at the
1101 // true parent (default).
1102 nsWindow
* widget
= nsnull
;
1105 HWND parent
= ::GetParent(mWnd
);
1107 HWND parent
= nsnull
;
1109 parent
= ::GetParent(mWnd
);
1111 parent
= ::GetAncestor(mWnd
, GA_PARENT
);
1114 widget
= GetNSWindowPtr(parent
);
1116 // If the widget is in the process of being destroyed then
1118 if (widget
->mInDtor
) {
1128 /**************************************************************
1130 * SECTION: nsIWidget::Show
1132 * Hide or show this component.
1134 **************************************************************/
1136 NS_METHOD
nsWindow::Show(PRBool bState
)
1138 #if defined(MOZ_SPLASHSCREEN)
1139 // we're about to show the first toplevel window,
1140 // so kill off any splash screen if we had one
1141 nsSplashScreen
*splash
= nsSplashScreen::Get();
1142 if (splash
&& splash
->IsOpen() && mWnd
&& bState
&&
1143 (mWindowType
== eWindowType_toplevel
||
1144 mWindowType
== eWindowType_dialog
||
1145 mWindowType
== eWindowType_popup
))
1151 #ifdef NS_FUNCTION_TIMER
1152 static bool firstShow
= true;
1154 (mWindowType
== eWindowType_toplevel
||
1155 mWindowType
== eWindowType_dialog
||
1156 mWindowType
== eWindowType_popup
))
1159 mozilla::FunctionTimer::LogMessage("@ First toplevel/dialog/popup showing");
1163 PRBool wasVisible
= mIsVisible
;
1164 // Set the status now so that anyone asking during ShowWindow or
1165 // SetWindowPos would get the correct answer.
1166 mIsVisible
= bState
;
1168 if (!mIsVisible
&& wasVisible
) {
1169 ClearCachedResources();
1174 if (!wasVisible
&& mWindowType
== eWindowType_toplevel
) {
1175 switch (mSizeMode
) {
1177 case nsSizeMode_Fullscreen
:
1178 ::SetForegroundWindow(mWnd
);
1179 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1180 MakeFullScreen(TRUE
);
1183 case nsSizeMode_Maximized
:
1184 ::SetForegroundWindow(mWnd
);
1185 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1187 // use default for nsSizeMode_Minimized on Windows CE
1189 case nsSizeMode_Maximized
:
1190 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1192 case nsSizeMode_Minimized
:
1193 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
1197 if (CanTakeFocus()) {
1199 ::SetForegroundWindow(mWnd
);
1201 ::ShowWindow(mWnd
, SW_SHOWNORMAL
);
1203 // Place the window behind the foreground window
1204 // (as long as it is not topmost)
1205 HWND wndAfter
= ::GetForegroundWindow();
1207 wndAfter
= HWND_BOTTOM
;
1208 else if (GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
)
1209 wndAfter
= HWND_TOP
;
1210 ::SetWindowPos(mWnd
, wndAfter
, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOSIZE
|
1211 SWP_NOMOVE
| SWP_NOACTIVATE
);
1217 DWORD flags
= SWP_NOSIZE
| SWP_NOMOVE
| SWP_SHOWWINDOW
;
1219 flags
|= SWP_NOZORDER
;
1221 if (mWindowType
== eWindowType_popup
) {
1223 // ensure popups are the topmost of the TOPMOST
1224 // layer. Remember not to set the SWP_NOZORDER
1225 // flag as that might allow the taskbar to overlap
1226 // the popup. However on windows ce, we need to
1227 // activate the popup or clicks will not be sent.
1228 flags
|= SWP_NOACTIVATE
;
1230 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
1231 ::SetWindowPos(mWnd
, owner
? 0 : HWND_TOPMOST
, 0, 0, 0, 0, flags
);
1234 if (mWindowType
== eWindowType_dialog
&& !CanTakeFocus())
1235 flags
|= SWP_NOACTIVATE
;
1237 ::SetWindowPos(mWnd
, HWND_TOP
, 0, 0, 0, 0, flags
);
1242 if (!wasVisible
&& (mWindowType
== eWindowType_toplevel
|| mWindowType
== eWindowType_dialog
)) {
1243 // when a toplevel window or dialog is shown, initialize the UI state
1244 ::SendMessageW(mWnd
, WM_CHANGEUISTATE
, MAKEWPARAM(UIS_INITIALIZE
, UISF_HIDEFOCUS
| UISF_HIDEACCEL
), 0);
1248 if (mWindowType
!= eWindowType_dialog
) {
1249 ::ShowWindow(mWnd
, SW_HIDE
);
1251 ::SetWindowPos(mWnd
, 0, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1252 SWP_NOZORDER
| SWP_NOACTIVATE
);
1258 if (!wasVisible
&& bState
)
1259 Invalidate(PR_FALSE
);
1265 /**************************************************************
1267 * SECTION: nsIWidget::IsVisible
1269 * Returns the visibility state.
1271 **************************************************************/
1273 // Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
1274 NS_METHOD
nsWindow::IsVisible(PRBool
& bState
)
1276 bState
= mIsVisible
;
1280 /**************************************************************
1282 * SECTION: Window clipping utilities
1284 * Used in Size and Move operations for setting the proper
1285 * window clipping regions for window transparency.
1287 **************************************************************/
1289 // XP and Vista visual styles sometimes require window clipping regions to be applied for proper
1290 // transparency. These routines are called on size and move operations.
1291 void nsWindow::ClearThemeRegion()
1294 if (nsUXThemeData::sIsVistaOrLater
&& !HasGlass() &&
1295 mWindowType
== eWindowType_popup
&& (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
)) {
1296 SetWindowRgn(mWnd
, NULL
, false);
1301 void nsWindow::SetThemeRegion()
1304 // Popup types that have a visual styles region applied (bug 376408). This can be expanded
1305 // for other window types as needed. The regions are applied generically to the base window
1306 // so default constants are used for part and state. At some point we might need part and
1307 // state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
1308 // change shape based on state haven't come up.
1309 if (nsUXThemeData::sIsVistaOrLater
&& !HasGlass() &&
1310 mWindowType
== eWindowType_popup
&& (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
)) {
1312 RECT rect
= {0,0,mBounds
.width
,mBounds
.height
};
1314 HDC dc
= ::GetDC(mWnd
);
1315 nsUXThemeData::getThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip
), dc
, TTP_STANDARD
, TS_NORMAL
, &rect
, &hRgn
);
1317 if (!SetWindowRgn(mWnd
, hRgn
, false)) // do not delete or alter hRgn if accepted.
1320 ::ReleaseDC(mWnd
, dc
);
1325 /**************************************************************
1327 * SECTION: nsIWidget::RegisterTouchWindow,
1328 * nsIWidget::UnregisterTouchWindow, and helper functions
1330 * Used to register the native window to receive touch events
1332 **************************************************************/
1334 NS_METHOD
nsWindow::RegisterTouchWindow() {
1335 mTouchWindow
= PR_TRUE
;
1337 mGesture
.RegisterTouchWindow(mWnd
);
1338 ::EnumChildWindows(mWnd
, nsWindow::RegisterTouchForDescendants
, 0);
1343 NS_METHOD
nsWindow::UnregisterTouchWindow() {
1344 mTouchWindow
= PR_FALSE
;
1346 mGesture
.UnregisterTouchWindow(mWnd
);
1347 ::EnumChildWindows(mWnd
, nsWindow::UnregisterTouchForDescendants
, 0);
1353 BOOL CALLBACK
nsWindow::RegisterTouchForDescendants(HWND aWnd
, LPARAM aMsg
) {
1354 nsWindow
* win
= GetNSWindowPtr(aWnd
);
1356 win
->mGesture
.RegisterTouchWindow(aWnd
);
1360 BOOL CALLBACK
nsWindow::UnregisterTouchForDescendants(HWND aWnd
, LPARAM aMsg
) {
1361 nsWindow
* win
= GetNSWindowPtr(aWnd
);
1363 win
->mGesture
.UnregisterTouchWindow(aWnd
);
1368 /**************************************************************
1370 * SECTION: nsIWidget::Move, nsIWidget::Resize,
1371 * nsIWidget::Size, nsIWidget::BeginResizeDrag
1373 * Repositioning and sizing a window.
1375 **************************************************************/
1377 // Move this component
1378 NS_METHOD
nsWindow::Move(PRInt32 aX
, PRInt32 aY
)
1380 if (mWindowType
== eWindowType_toplevel
||
1381 mWindowType
== eWindowType_dialog
) {
1382 SetSizeMode(nsSizeMode_Normal
);
1384 // Check to see if window needs to be moved first
1385 // to avoid a costly call to SetWindowPos. This check
1386 // can not be moved to the calling code in nsView, because
1387 // some platforms do not position child windows correctly
1389 // Only perform this check for non-popup windows, since the positioning can
1390 // in fact change even when the x/y do not. We always need to perform the
1391 // check. See bug #97805 for details.
1392 if (mWindowType
!= eWindowType_popup
&& (mBounds
.x
== aX
) && (mBounds
.y
== aY
))
1394 // Nothing to do, since it is already positioned correctly.
1403 // complain if a window is moved offscreen (legal, but potentially worrisome)
1404 if (mIsTopWidgetWindow
) { // only a problem for top-level windows
1405 // Make sure this window is actually on the screen before we move it
1406 // XXX: Needs multiple monitor support
1407 HDC dc
= ::GetDC(mWnd
);
1409 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1411 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &workArea
, 0);
1412 // no annoying assertions. just mention the issue.
1413 if (aX
< 0 || aX
>= workArea
.right
|| aY
< 0 || aY
>= workArea
.bottom
)
1414 printf("window moved to offscreen position\n");
1416 ::ReleaseDC(mWnd
, dc
);
1421 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, 0, 0,
1422 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOSIZE
));
1428 // Resize this component
1429 NS_METHOD
nsWindow::Resize(PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1431 NS_ASSERTION((aWidth
>=0 ) , "Negative width passed to nsWindow::Resize");
1432 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1434 // Avoid unnecessary resizing calls
1435 if (mBounds
.width
== aWidth
&& mBounds
.height
== aHeight
&& !aRepaint
)
1439 if (eTransparencyTransparent
== mTransparencyMode
)
1440 ResizeTranslucentWindow(aWidth
, aHeight
);
1443 // Set cached value for lightweight and printing
1444 mBounds
.width
= aWidth
;
1445 mBounds
.height
= aHeight
;
1448 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOMOVE
;
1452 flags
|= SWP_NOREDRAW
;
1457 VERIFY(::SetWindowPos(mWnd
, NULL
, 0, 0, aWidth
, GetHeight(aHeight
), flags
));
1462 Invalidate(PR_FALSE
);
1467 // Resize this component
1468 NS_METHOD
nsWindow::Resize(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1470 NS_ASSERTION((aWidth
>=0 ), "Negative width passed to nsWindow::Resize");
1471 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1473 // Avoid unnecessary resizing calls
1474 if (mBounds
.x
== aX
&& mBounds
.y
== aY
&&
1475 mBounds
.width
== aWidth
&& mBounds
.height
== aHeight
&& !aRepaint
)
1479 if (eTransparencyTransparent
== mTransparencyMode
)
1480 ResizeTranslucentWindow(aWidth
, aHeight
);
1483 // Set cached value for lightweight and printing
1486 mBounds
.width
= aWidth
;
1487 mBounds
.height
= aHeight
;
1490 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1493 flags
|= SWP_NOREDRAW
;
1498 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, aWidth
, GetHeight(aHeight
), flags
));
1503 Invalidate(PR_FALSE
);
1508 // Resize the client area and position the widget within it's parent
1509 NS_METHOD
nsWindow::ResizeClient(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1511 NS_ASSERTION((aWidth
>=0) , "Negative width passed to ResizeClient");
1512 NS_ASSERTION((aHeight
>=0), "Negative height passed to ResizeClient");
1514 // Adjust our existing window bounds, based on the new client dims.
1516 GetClientRect(mWnd
, &client
);
1517 nsIntPoint
dims(client
.right
- client
.left
, client
.bottom
- client
.top
);
1518 aWidth
= mBounds
.width
+ (aWidth
- dims
.x
);
1519 aHeight
= mBounds
.height
+ (aHeight
- dims
.y
);
1524 GetScreenBounds(bounds
);
1527 return Resize(aX
, aY
, aWidth
, aHeight
, aRepaint
);
1529 return Resize(aWidth
, aHeight
, aRepaint
);
1534 nsWindow::BeginResizeDrag(nsGUIEvent
* aEvent
, PRInt32 aHorizontal
, PRInt32 aVertical
)
1536 NS_ENSURE_ARG_POINTER(aEvent
);
1538 if (aEvent
->eventStructType
!= NS_MOUSE_EVENT
) {
1539 // you can only begin a resize drag with a mouse event
1540 return NS_ERROR_INVALID_ARG
;
1543 nsMouseEvent
* mouseEvent
= static_cast<nsMouseEvent
*>(aEvent
);
1544 if (mouseEvent
->button
!= nsMouseEvent::eLeftButton
) {
1545 // you can only begin a resize drag with the left mouse button
1546 return NS_ERROR_INVALID_ARG
;
1549 // work out what sizemode we're talking about
1551 if (aVertical
< 0) {
1552 if (aHorizontal
< 0) {
1553 syscommand
= SC_SIZE
| WMSZ_TOPLEFT
;
1554 } else if (aHorizontal
== 0) {
1555 syscommand
= SC_SIZE
| WMSZ_TOP
;
1557 syscommand
= SC_SIZE
| WMSZ_TOPRIGHT
;
1559 } else if (aVertical
== 0) {
1560 if (aHorizontal
< 0) {
1561 syscommand
= SC_SIZE
| WMSZ_LEFT
;
1562 } else if (aHorizontal
== 0) {
1563 return NS_ERROR_INVALID_ARG
;
1565 syscommand
= SC_SIZE
| WMSZ_RIGHT
;
1568 if (aHorizontal
< 0) {
1569 syscommand
= SC_SIZE
| WMSZ_BOTTOMLEFT
;
1570 } else if (aHorizontal
== 0) {
1571 syscommand
= SC_SIZE
| WMSZ_BOTTOM
;
1573 syscommand
= SC_SIZE
| WMSZ_BOTTOMRIGHT
;
1577 // resizing doesn't work if the mouse is already captured
1578 CaptureMouse(PR_FALSE
);
1580 // find the top-level window
1581 HWND toplevelWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
1583 // tell Windows to start the resize
1584 ::PostMessage(toplevelWnd
, WM_SYSCOMMAND
, syscommand
,
1585 POINTTOPOINTS(aEvent
->refPoint
));
1590 /**************************************************************
1592 * SECTION: Window Z-order and state.
1594 * nsIWidget::PlaceBehind, nsIWidget::SetSizeMode,
1595 * nsIWidget::ConstrainPosition
1597 * Z-order, positioning, restore, minimize, and maximize.
1599 **************************************************************/
1601 // Position the window behind the given window
1602 NS_METHOD
nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
1603 nsIWidget
*aWidget
, PRBool aActivate
)
1605 HWND behind
= HWND_TOP
;
1606 if (aPlacement
== eZPlacementBottom
)
1607 behind
= HWND_BOTTOM
;
1608 else if (aPlacement
== eZPlacementBelow
&& aWidget
)
1609 behind
= (HWND
)aWidget
->GetNativeData(NS_NATIVE_WINDOW
);
1610 UINT flags
= SWP_NOMOVE
| SWP_NOREPOSITION
| SWP_NOSIZE
;
1612 flags
|= SWP_NOACTIVATE
;
1614 if (!CanTakeFocus() && behind
== HWND_TOP
)
1616 // Can't place the window to top so place it behind the foreground window
1617 // (as long as it is not topmost)
1618 HWND wndAfter
= ::GetForegroundWindow();
1620 behind
= HWND_BOTTOM
;
1621 else if (!(GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
))
1623 flags
|= SWP_NOACTIVATE
;
1626 ::SetWindowPos(mWnd
, behind
, 0, 0, 0, 0, flags
);
1630 // Maximize, minimize or restore the window.
1631 #if !defined(WINCE) // implemented in nsWindowCE.cpp
1632 NS_IMETHODIMP
nsWindow::SetSizeMode(PRInt32 aMode
) {
1636 // Let's not try and do anything if we're already in that state.
1637 // (This is needed to prevent problems when calling window.minimize(), which
1638 // calls us directly, and then the OS triggers another call to us.)
1639 if (aMode
== mSizeMode
)
1642 // save the requested state
1643 rv
= nsBaseWidget::SetSizeMode(aMode
);
1644 if (NS_SUCCEEDED(rv
) && mIsVisible
) {
1648 case nsSizeMode_Fullscreen
:
1652 case nsSizeMode_Maximized
:
1656 case nsSizeMode_Minimized
:
1657 // Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
1658 // keeps the window active in the tray. So after the window is minimized,
1659 // windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
1660 // we will do some additional processing to get the active window set right.
1661 // If sTrimOnMinimize is set, we let windows handle minimization normally
1662 // using SW_MINIMIZE.
1663 mode
= sTrimOnMinimize
? SW_MINIMIZE
: SW_SHOWMINIMIZED
;
1669 ::ShowWindow(mWnd
, mode
);
1670 // we dispatch an activate event here to ensure that the right child window
1672 if (mode
== SW_RESTORE
|| mode
== SW_MAXIMIZE
)
1673 DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
1677 #endif // !defined(WINCE)
1679 // Constrain a potential move to fit onscreen
1680 NS_METHOD
nsWindow::ConstrainPosition(PRBool aAllowSlop
,
1681 PRInt32
*aX
, PRInt32
*aY
)
1683 if (!mIsTopWidgetWindow
) // only a problem for top-level windows
1686 PRBool doConstrain
= PR_FALSE
; // whether we have enough info to do anything
1688 /* get our playing field. use the current screen, or failing that
1689 for any reason, use device caps for the default screen. */
1692 nsCOMPtr
<nsIScreenManager
> screenmgr
= do_GetService(sScreenManagerContractID
);
1694 nsCOMPtr
<nsIScreen
> screen
;
1695 PRInt32 left
, top
, width
, height
;
1697 // zero size rects confuse the screen manager
1698 width
= mBounds
.width
> 0 ? mBounds
.width
: 1;
1699 height
= mBounds
.height
> 0 ? mBounds
.height
: 1;
1700 screenmgr
->ScreenForRect(*aX
, *aY
, width
, height
,
1701 getter_AddRefs(screen
));
1703 if (mSizeMode
!= nsSizeMode_Fullscreen
) {
1704 // For normalized windows, use the desktop work area.
1705 screen
->GetAvailRect(&left
, &top
, &width
, &height
);
1707 // For full screen windows, use the desktop.
1708 screen
->GetRect(&left
, &top
, &width
, &height
);
1710 screenRect
.left
= left
;
1711 screenRect
.right
= left
+width
;
1712 screenRect
.top
= top
;
1713 screenRect
.bottom
= top
+height
;
1714 doConstrain
= PR_TRUE
;
1718 HDC dc
= ::GetDC(mWnd
);
1720 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1721 if (mSizeMode
!= nsSizeMode_Fullscreen
) {
1722 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &screenRect
, 0);
1724 screenRect
.left
= screenRect
.top
= 0;
1725 screenRect
.right
= GetSystemMetrics(SM_CXFULLSCREEN
);
1726 screenRect
.bottom
= GetSystemMetrics(SM_CYFULLSCREEN
);
1728 doConstrain
= PR_TRUE
;
1730 ::ReleaseDC(mWnd
, dc
);
1736 if (*aX
< screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
)
1737 *aX
= screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
;
1738 else if (*aX
>= screenRect
.right
- kWindowPositionSlop
)
1739 *aX
= screenRect
.right
- kWindowPositionSlop
;
1741 if (*aY
< screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
)
1742 *aY
= screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
;
1743 else if (*aY
>= screenRect
.bottom
- kWindowPositionSlop
)
1744 *aY
= screenRect
.bottom
- kWindowPositionSlop
;
1748 if (*aX
< screenRect
.left
)
1749 *aX
= screenRect
.left
;
1750 else if (*aX
>= screenRect
.right
- mBounds
.width
)
1751 *aX
= screenRect
.right
- mBounds
.width
;
1753 if (*aY
< screenRect
.top
)
1754 *aY
= screenRect
.top
;
1755 else if (*aY
>= screenRect
.bottom
- mBounds
.height
)
1756 *aY
= screenRect
.bottom
- mBounds
.height
;
1762 /**************************************************************
1764 * SECTION: nsIWidget::Enable, nsIWidget::IsEnabled
1766 * Enabling and disabling the widget.
1768 **************************************************************/
1770 // Enable/disable this component
1771 NS_METHOD
nsWindow::Enable(PRBool bState
)
1774 ::EnableWindow(mWnd
, bState
);
1779 // Return the current enable state
1780 NS_METHOD
nsWindow::IsEnabled(PRBool
*aState
)
1782 NS_ENSURE_ARG_POINTER(aState
);
1785 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(::GetAncestor(mWnd
, GA_ROOT
)));
1787 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(mWnd
));
1794 /**************************************************************
1796 * SECTION: nsIWidget::SetFocus
1798 * Give the focus to this widget.
1800 **************************************************************/
1802 NS_METHOD
nsWindow::SetFocus(PRBool aRaise
)
1805 #ifdef WINSTATE_DEBUG_OUTPUT
1806 if (mWnd
== GetTopLevelHWND(mWnd
))
1807 printf("*** SetFocus: [ top] raise=%d\n", aRaise
);
1809 printf("*** SetFocus: [child] raise=%d\n", aRaise
);
1811 // Uniconify, if necessary
1812 HWND toplevelWnd
= GetTopLevelHWND(mWnd
);
1813 if (aRaise
&& ::IsIconic(toplevelWnd
)) {
1814 ::ShowWindow(toplevelWnd
, SW_RESTORE
);
1822 /**************************************************************
1826 * GetBounds, GetClientBounds, GetScreenBounds, GetClientOffset
1827 * SetDrawsInTitlebar, GetNonClientMargins, SetNonClientMargins
1829 * Bound calculations.
1831 **************************************************************/
1833 // Return the window's full dimensions in screen coordinates.
1834 // If the window has a parent, converts the origin to an offset
1835 // of the parent's screen origin.
1836 NS_METHOD
nsWindow::GetBounds(nsIntRect
&aRect
)
1840 VERIFY(::GetWindowRect(mWnd
, &r
));
1843 aRect
.width
= r
.right
- r
.left
;
1844 aRect
.height
= r
.bottom
- r
.top
;
1846 // chrome on parent:
1847 // ___ 5,5 (chrome start)
1848 // | ____ 10,10 (client start)
1849 // | | ____ 20,20 (child start)
1851 // 20,20 - 5,5 = 15,15 (??)
1852 // minus GetClientOffset:
1853 // 15,15 - 5,5 = 10,10
1855 // no chrome on parent:
1856 // ______ 10,10 (win start)
1857 // | ____ 20,20 (child start)
1859 // 20,20 - 10,10 = 10,10
1861 // walking the chain:
1862 // ___ 5,5 (chrome start)
1863 // | ___ 10,10 (client start)
1864 // | | ___ 20,20 (child start)
1865 // | | | __ 30,30 (child start)
1867 // 30,30 - 20,20 = 10,10 (offset from second child to first)
1868 // 20,20 - 5,5 = 15,15 + 10,10 = 25,25 (??)
1869 // minus GetClientOffset:
1870 // 25,25 - 5,5 = 20,20 (offset from second child to parent client)
1872 // convert coordinates if parent exists
1873 HWND parent
= ::GetParent(mWnd
);
1876 VERIFY(::GetWindowRect(parent
, &pr
));
1879 // adjust for chrome
1880 nsWindow
* pWidget
= static_cast<nsWindow
*>(GetParent());
1881 if (pWidget
&& pWidget
->IsTopLevelWidget()) {
1882 nsIntPoint clientOffset
= pWidget
->GetClientOffset();
1883 r
.left
-= clientOffset
.x
;
1884 r
.top
-= clientOffset
.y
;
1896 // Get this component dimension
1897 NS_METHOD
nsWindow::GetClientBounds(nsIntRect
&aRect
)
1901 VERIFY(::GetClientRect(mWnd
, &r
));
1906 aRect
.width
= r
.right
- r
.left
;
1907 aRect
.height
= r
.bottom
- r
.top
;
1910 aRect
.SetRect(0,0,0,0);
1915 // Like GetBounds, but don't offset by the parent
1916 NS_METHOD
nsWindow::GetScreenBounds(nsIntRect
&aRect
)
1920 VERIFY(::GetWindowRect(mWnd
, &r
));
1922 aRect
.width
= r
.right
- r
.left
;
1923 aRect
.height
= r
.bottom
- r
.top
;
1932 // return the x,y offset of the client area from the origin
1933 // of the window. If the window is borderless returns (0,0).
1934 nsIntPoint
nsWindow::GetClientOffset()
1937 return nsIntPoint(0, 0);
1941 GetWindowRect(mWnd
, &r1
);
1942 nsIntPoint pt
= WidgetToScreenOffset();
1943 return nsIntPoint(pt
.x
- r1
.left
, pt
.y
- r1
.top
);
1947 nsWindow::SetDrawsInTitlebar(PRBool aState
)
1949 nsWindow
* window
= GetTopLevelWindow(PR_TRUE
);
1950 if (window
&& window
!= this) {
1951 return window
->SetDrawsInTitlebar(aState
);
1955 // left, top, right, bottom for nsIntMargin
1956 nsIntMargin
margins(-1, 0, -1, -1);
1957 SetNonClientMargins(margins
);
1960 nsIntMargin
margins(-1, -1, -1, -1);
1961 SetNonClientMargins(margins
);
1966 nsWindow::GetNonClientMargins(nsIntMargin
&margins
)
1968 nsWindow
* window
= GetTopLevelWindow(PR_TRUE
);
1969 if (window
&& window
!= this) {
1970 return window
->GetNonClientMargins(margins
);
1973 if (mCustomNonClient
) {
1974 margins
= mNonClientMargins
;
1978 margins
.top
= GetSystemMetrics(SM_CYCAPTION
);
1979 margins
.bottom
= GetSystemMetrics(SM_CYFRAME
);
1980 margins
.top
+= margins
.bottom
;
1981 margins
.left
= margins
.right
= GetSystemMetrics(SM_CYFRAME
);
1987 nsWindow::ResetLayout()
1989 // This will trigger a frame changed event, triggering
1990 // nc calc size and a sizemode gecko event.
1991 SetWindowPos(mWnd
, 0, 0, 0, 0, 0,
1992 SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|
1993 SWP_NOOWNERZORDER
|SWP_NOSIZE
|SWP_NOZORDER
);
1995 // If hidden, just send the frame changed event for now.
1999 // Send a gecko size event to trigger reflow.
2000 RECT clientRc
= {0};
2001 GetClientRect(mWnd
, &clientRc
);
2002 nsIntRect
evRect(nsWindowGfx::ToIntRect(clientRc
));
2005 // Invalidate and update
2006 Invalidate(PR_FALSE
);
2009 // Called when the window layout changes: full screen mode transitions,
2010 // theme changes, and composition changes. Calculates the new non-client
2011 // margins and fires off a frame changed event, which triggers an nc calc
2012 // size windows event, kicking the changes in.
2014 nsWindow::UpdateNonClientMargins(PRInt32 aSizeMode
, PRBool aReflowWindow
)
2016 if (!mCustomNonClient
)
2019 mNonClientOffset
.top
= mNonClientOffset
.bottom
=
2020 mNonClientOffset
.left
= mNonClientOffset
.right
= 0;
2022 if (aSizeMode
== -1)
2023 aSizeMode
= mSizeMode
;
2025 if (aSizeMode
== nsSizeMode_Minimized
||
2026 aSizeMode
== nsSizeMode_Fullscreen
) {
2027 mCaptionHeight
= mVertResizeMargin
= mHorResizeMargin
= 0;
2031 // Note, for maximized windows, we need to continue to offset the client by
2032 // thick frame margins of a normal window, since windows expects this
2033 // in it's DwmDefWndProc hit testing.
2034 mCaptionHeight
= GetSystemMetrics(SM_CYCAPTION
);
2035 mHorResizeMargin
= GetSystemMetrics(SM_CXFRAME
);
2036 mVertResizeMargin
= GetSystemMetrics(SM_CYFRAME
);
2038 mCaptionHeight
+= mVertResizeMargin
;
2040 // If a margin value is 0, set the offset to the default size of the frame.
2041 // If a margin is -1, leave as default, and if a margin > 0, set the offset
2042 // so that the frame size is equal to the margin value.
2043 if (!mNonClientMargins
.top
)
2044 mNonClientOffset
.top
= mCaptionHeight
;
2045 else if (mNonClientMargins
.top
> 0)
2046 mNonClientOffset
.top
= mCaptionHeight
- mNonClientMargins
.top
;
2048 if (!mNonClientMargins
.left
)
2049 mNonClientOffset
.left
= mHorResizeMargin
;
2050 else if (mNonClientMargins
.left
> 0)
2051 mNonClientOffset
.left
= mHorResizeMargin
- mNonClientMargins
.left
;
2053 if (!mNonClientMargins
.right
)
2054 mNonClientOffset
.right
= mHorResizeMargin
;
2055 else if (mNonClientMargins
.right
> 0)
2056 mNonClientOffset
.right
= mHorResizeMargin
- mNonClientMargins
.right
;
2058 if (!mNonClientMargins
.bottom
)
2059 mNonClientOffset
.bottom
= mVertResizeMargin
;
2060 else if (mNonClientMargins
.bottom
> 0)
2061 mNonClientOffset
.bottom
= mVertResizeMargin
- mNonClientMargins
.bottom
;
2064 if (aSizeMode
== nsSizeMode_Maximized
) {
2065 // Address an issue with auto-hide taskbars which fall behind the window.
2066 // Ensure a 1 pixel margin at the bottom of the monitor so that unhiding
2067 // the taskbar works properly.
2068 MONITORINFO info
= {sizeof(MONITORINFO
)};
2069 if (::GetMonitorInfo(::MonitorFromWindow(mWnd
, MONITOR_DEFAULTTOPRIMARY
),
2072 if (::GetWindowRect(mWnd
, &r
)) {
2073 // Adjust window rect to account for non-client margins.
2074 r
.top
+= mVertResizeMargin
- mNonClientOffset
.top
;
2075 r
.left
+= mHorResizeMargin
- mNonClientOffset
.left
;
2076 r
.bottom
-= mVertResizeMargin
- mNonClientOffset
.bottom
;
2077 r
.right
-= mHorResizeMargin
- mNonClientOffset
.right
;
2078 // Leave the 1 pixel margin if the window covers the monitor.
2079 if (r
.top
<= info
.rcMonitor
.top
&&
2080 r
.left
<= info
.rcMonitor
.left
&&
2081 r
.right
>= info
.rcMonitor
.right
&&
2082 r
.bottom
>= info
.rcMonitor
.bottom
)
2083 mNonClientOffset
.bottom
-= r
.bottom
- info
.rcMonitor
.bottom
+ 1;
2089 if (aReflowWindow
) {
2090 // Force a reflow of content based on the new client
2099 nsWindow::SetNonClientMargins(nsIntMargin
&margins
)
2101 if (!mIsTopWidgetWindow
||
2102 mBorderStyle
& eBorderStyle_none
||
2104 return NS_ERROR_INVALID_ARG
;
2106 // Request for a reset
2107 if (margins
.top
== -1 && margins
.left
== -1 &&
2108 margins
.right
== -1 && margins
.bottom
== -1) {
2109 mCustomNonClient
= PR_FALSE
;
2110 mNonClientMargins
= margins
;
2111 // Force a reflow of content based on the new client
2117 if (margins
.top
< -1 || margins
.bottom
< -1 ||
2118 margins
.left
< -1 || margins
.right
< -1)
2119 return NS_ERROR_INVALID_ARG
;
2121 mNonClientMargins
= margins
;
2122 mCustomNonClient
= PR_TRUE
;
2123 if (!UpdateNonClientMargins()) {
2124 NS_WARNING("UpdateNonClientMargins failed!");
2132 nsWindow::InvalidateNonClientRegion()
2134 // +-+-----------------------+-+
2135 // | | app non-client chrome | |
2136 // | +-----------------------+ |
2137 // | | app client chrome | | }
2138 // | +-----------------------+ | }
2139 // | | app content | | } area we don't want to invalidate
2140 // | +-----------------------+ | }
2141 // | | app client chrome | | }
2142 // | +-----------------------+ |
2143 // +---------------------------+ <
2144 // ^ ^ windows non-client chrome
2145 // client area = app *
2147 GetWindowRect(mWnd
, &rect
);
2148 MapWindowPoints(NULL
, mWnd
, (LPPOINT
)&rect
, 2);
2149 HRGN winRgn
= CreateRectRgnIndirect(&rect
);
2151 // Subtract app client chrome and app content leaving
2152 // windows non-client chrome and app non-client chrome
2154 GetWindowRect(mWnd
, &rect
);
2155 rect
.top
+= mCaptionHeight
;
2156 rect
.right
-= mHorResizeMargin
;
2157 rect
.bottom
-= mHorResizeMargin
;
2158 rect
.left
+= mVertResizeMargin
;
2159 MapWindowPoints(NULL
, mWnd
, (LPPOINT
)&rect
, 2);
2160 HRGN clientRgn
= CreateRectRgnIndirect(&rect
);
2161 CombineRgn(winRgn
, winRgn
, clientRgn
, RGN_DIFF
);
2162 DeleteObject(clientRgn
);
2164 // triggers ncpaint and paint events for the two areas
2165 RedrawWindow(mWnd
, NULL
, winRgn
, RDW_FRAME
|RDW_INVALIDATE
);
2166 DeleteObject(winRgn
);
2170 nsWindow::ExcludeNonClientFromPaintRegion(HRGN aRegion
)
2174 if (aRegion
== (HRGN
)1) { // undocumented value indicating a full refresh
2175 GetWindowRect(mWnd
, &rect
);
2176 rgn
= CreateRectRgnIndirect(&rect
);
2180 GetClientRect(mWnd
, &rect
);
2181 MapWindowPoints(mWnd
, NULL
, (LPPOINT
)&rect
, 2);
2182 HRGN nonClientRgn
= CreateRectRgnIndirect(&rect
);
2183 CombineRgn(rgn
, rgn
, nonClientRgn
, RGN_DIFF
);
2184 DeleteObject(nonClientRgn
);
2188 /**************************************************************
2190 * SECTION: nsIWidget::SetBackgroundColor
2192 * Sets the window background paint color.
2194 **************************************************************/
2196 NS_METHOD
nsWindow::SetBackgroundColor(const nscolor
&aColor
)
2198 nsBaseWidget::SetBackgroundColor(aColor
);
2201 ::DeleteObject(mBrush
);
2203 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
2206 ::SetClassLongPtrW(mWnd
, GCLP_HBRBACKGROUND
, (LONG_PTR
)mBrush
);
2212 /**************************************************************
2214 * SECTION: nsIWidget::SetCursor
2216 * SetCursor and related utilities for manging cursor state.
2218 **************************************************************/
2220 // Set this component cursor
2221 NS_METHOD
nsWindow::SetCursor(nsCursor aCursor
)
2223 // Only change cursor if it's changing
2225 //XXX mCursor isn't always right. Scrollbars and others change it, too.
2226 //XXX If we want this optimization we need a better way to do it.
2227 //if (aCursor != mCursor) {
2228 HCURSOR newCursor
= NULL
;
2231 case eCursor_select
:
2232 newCursor
= ::LoadCursor(NULL
, IDC_IBEAM
);
2236 newCursor
= ::LoadCursor(NULL
, IDC_WAIT
);
2239 case eCursor_hyperlink
:
2241 newCursor
= ::LoadCursor(NULL
, IDC_HAND
);
2245 case eCursor_standard
:
2246 newCursor
= ::LoadCursor(NULL
, IDC_ARROW
);
2249 case eCursor_n_resize
:
2250 case eCursor_s_resize
:
2251 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
2254 case eCursor_w_resize
:
2255 case eCursor_e_resize
:
2256 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
2259 case eCursor_nw_resize
:
2260 case eCursor_se_resize
:
2261 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
2264 case eCursor_ne_resize
:
2265 case eCursor_sw_resize
:
2266 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
2269 case eCursor_crosshair
:
2270 newCursor
= ::LoadCursor(NULL
, IDC_CROSS
);
2274 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
2278 newCursor
= ::LoadCursor(NULL
, IDC_HELP
);
2281 case eCursor_copy
: // CSS3
2282 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COPY
));
2286 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ALIAS
));
2290 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_CELL
));
2294 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRAB
));
2297 case eCursor_grabbing
:
2298 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRABBING
));
2301 case eCursor_spinning
:
2302 newCursor
= ::LoadCursor(NULL
, IDC_APPSTARTING
);
2305 case eCursor_context_menu
:
2306 // XXX this CSS3 cursor needs to be implemented
2309 case eCursor_zoom_in
:
2310 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMIN
));
2313 case eCursor_zoom_out
:
2314 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMOUT
));
2317 case eCursor_not_allowed
:
2318 case eCursor_no_drop
:
2319 newCursor
= ::LoadCursor(NULL
, IDC_NO
);
2322 case eCursor_col_resize
:
2323 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COLRESIZE
));
2326 case eCursor_row_resize
:
2327 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ROWRESIZE
));
2330 case eCursor_vertical_text
:
2331 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_VERTICALTEXT
));
2334 case eCursor_all_scroll
:
2335 // XXX not 100% appropriate perhaps
2336 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
2339 case eCursor_nesw_resize
:
2340 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
2343 case eCursor_nwse_resize
:
2344 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
2347 case eCursor_ns_resize
:
2348 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
2351 case eCursor_ew_resize
:
2352 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
2356 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_NONE
));
2360 NS_ERROR("Invalid cursor type");
2364 if (NULL
!= newCursor
) {
2366 HCURSOR oldCursor
= ::SetCursor(newCursor
);
2368 if (sHCursor
== oldCursor
) {
2369 NS_IF_RELEASE(sCursorImgContainer
);
2370 if (sHCursor
!= NULL
)
2371 ::DestroyIcon(sHCursor
);
2379 // Setting the actual cursor
2380 NS_IMETHODIMP
nsWindow::SetCursor(imgIContainer
* aCursor
,
2381 PRUint32 aHotspotX
, PRUint32 aHotspotY
)
2383 if (sCursorImgContainer
== aCursor
&& sHCursor
) {
2384 ::SetCursor(sHCursor
);
2392 rv
= aCursor
->GetWidth(&width
);
2393 NS_ENSURE_SUCCESS(rv
, rv
);
2394 rv
= aCursor
->GetHeight(&height
);
2395 NS_ENSURE_SUCCESS(rv
, rv
);
2397 // Reject cursors greater than 128 pixels in either direction, to prevent
2399 // XXX ideally we should rescale. Also, we could modify the API to
2400 // allow trusted content to set larger cursors.
2401 if (width
> 128 || height
> 128)
2402 return NS_ERROR_NOT_AVAILABLE
;
2405 rv
= nsWindowGfx::CreateIcon(aCursor
, PR_TRUE
, aHotspotX
, aHotspotY
, &cursor
);
2406 NS_ENSURE_SUCCESS(rv
, rv
);
2408 mCursor
= nsCursor(-1);
2409 ::SetCursor(cursor
);
2411 NS_IF_RELEASE(sCursorImgContainer
);
2412 sCursorImgContainer
= aCursor
;
2413 NS_ADDREF(sCursorImgContainer
);
2415 if (sHCursor
!= NULL
)
2416 ::DestroyIcon(sHCursor
);
2422 /**************************************************************
2424 * SECTION: nsIWidget::Get/SetTransparencyMode
2426 * Manage the transparency mode of the top-level window
2427 * containing this widget.
2429 **************************************************************/
2432 nsTransparencyMode
nsWindow::GetTransparencyMode()
2434 return GetTopLevelWindow(PR_TRUE
)->GetWindowTranslucencyInner();
2437 void nsWindow::SetTransparencyMode(nsTransparencyMode aMode
)
2439 GetTopLevelWindow(PR_TRUE
)->SetWindowTranslucencyInner(aMode
);
2443 BOOL CALLBACK
AddClientAreaToRegion(HWND hWnd
, LPARAM lParam
) {
2444 nsIntRegion
*region
= reinterpret_cast<nsIntRegion
*>(lParam
);
2447 ::GetWindowRect(hWnd
, &clientRect
);
2448 nsIntRect
clientArea(clientRect
.left
, clientRect
.top
,
2449 clientRect
.right
- clientRect
.left
,
2450 clientRect
.bottom
- clientRect
.top
);
2451 region
->Or(*region
, clientArea
);
2456 void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion
&aDirtyRegion
,
2457 const nsIntRegion
&aPossiblyTransparentRegion
) {
2458 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2462 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2463 nsWindow
* topWindow
= GetNSWindowPtr(hWnd
);
2468 mPossiblyTransparentRegion
.Sub(mPossiblyTransparentRegion
, aDirtyRegion
);
2469 mPossiblyTransparentRegion
.Or(mPossiblyTransparentRegion
, aPossiblyTransparentRegion
);
2471 nsIntRegion childWindowRegion
;
2473 ::EnumChildWindows(mWnd
, AddClientAreaToRegion
, reinterpret_cast<LPARAM
>(&childWindowRegion
));
2475 nsIntPoint clientOffset
= GetClientOffset();
2476 childWindowRegion
.MoveBy(-clientOffset
);
2479 ::GetWindowRect(mWnd
, &r
);
2480 childWindowRegion
.MoveBy(-r
.left
, -r
.top
);
2482 nsIntRect clientBounds
;
2483 topWindow
->GetClientBounds(clientBounds
);
2484 nsIntRegion opaqueRegion
;
2485 opaqueRegion
.Sub(clientBounds
, mPossiblyTransparentRegion
);
2486 opaqueRegion
.Or(opaqueRegion
, childWindowRegion
);
2487 // Sometimes child windows overlap our bounds
2488 opaqueRegion
.And(opaqueRegion
, clientBounds
);
2490 MARGINS margins
= { 0, 0, 0, 0 };
2491 DWORD_PTR dwStyle
= ::GetWindowLongPtrW(hWnd
, GWL_STYLE
);
2493 // If there is no opaque region or hidechrome=true, set margins
2494 // to support a full sheet of glass.
2495 if (opaqueRegion
.IsEmpty() || mHideChrome
) {
2496 // Comments in MSDN indicate all values must be set to -1
2497 margins
.cxLeftWidth
= margins
.cxRightWidth
=
2498 margins
.cyTopHeight
= margins
.cyBottomHeight
= -1;
2500 // Find the largest rectangle and use that to calculate the inset
2501 nsIntRect largest
= opaqueRegion
.GetLargestRectangle();
2502 margins
.cxLeftWidth
= largest
.x
;
2503 margins
.cxRightWidth
= clientBounds
.width
- largest
.XMost();
2504 margins
.cyTopHeight
= largest
.y
;
2505 margins
.cyBottomHeight
= clientBounds
.height
- largest
.YMost();
2508 // Only update glass area if there are changes
2509 if (memcmp(&mGlassMargins
, &margins
, sizeof mGlassMargins
)) {
2510 mGlassMargins
= margins
;
2513 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2516 void nsWindow::UpdateGlass()
2518 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2519 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2520 MARGINS margins
= mGlassMargins
;
2522 // DWMNCRP_USEWINDOWSTYLE - The non-client rendering area is
2523 // rendered based on the window style.
2524 // DWMNCRP_ENABLED - The non-client area rendering is
2525 // enabled; the window style is ignored.
2526 DWMNCRENDERINGPOLICY policy
= DWMNCRP_USEWINDOWSTYLE
;
2527 switch (mTransparencyMode
) {
2528 case eTransparencyBorderlessGlass
:
2529 // Only adjust if there is some opaque rectangle
2530 if (margins
.cxLeftWidth
>= 0) {
2531 const PRInt32 kGlassMarginAdjustment
= 2;
2532 margins
.cxLeftWidth
+= kGlassMarginAdjustment
;
2533 margins
.cyTopHeight
+= kGlassMarginAdjustment
;
2534 margins
.cxRightWidth
+= kGlassMarginAdjustment
;
2535 margins
.cyBottomHeight
+= kGlassMarginAdjustment
;
2538 case eTransparencyGlass
:
2539 policy
= DWMNCRP_ENABLED
;
2543 // Extends the window frame behind the client area
2544 if(nsUXThemeData::CheckForCompositor()) {
2545 nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd
, &margins
);
2546 nsUXThemeData::dwmSetWindowAttributePtr(hWnd
, DWMWA_NCRENDERING_POLICY
, &policy
, sizeof policy
);
2548 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2552 /**************************************************************
2554 * SECTION: nsIWidget::HideWindowChrome
2556 * Show or hide window chrome.
2558 **************************************************************/
2560 NS_IMETHODIMP
nsWindow::HideWindowChrome(PRBool aShouldHide
)
2562 HWND hwnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2563 if (!GetNSWindowPtr(hwnd
))
2565 NS_WARNING("Trying to hide window decorations in an embedded context");
2566 return NS_ERROR_FAILURE
;
2569 if (mHideChrome
== aShouldHide
)
2572 DWORD_PTR style
, exStyle
;
2573 mHideChrome
= aShouldHide
;
2575 DWORD_PTR tempStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2576 DWORD_PTR tempExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2578 style
= tempStyle
& ~(WS_CAPTION
| WS_THICKFRAME
);
2579 exStyle
= tempExStyle
& ~(WS_EX_DLGMODALFRAME
| WS_EX_WINDOWEDGE
|
2580 WS_EX_CLIENTEDGE
| WS_EX_STATICEDGE
);
2582 mOldStyle
= tempStyle
;
2583 mOldExStyle
= tempExStyle
;
2586 if (!mOldStyle
|| !mOldExStyle
) {
2587 mOldStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2588 mOldExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2592 exStyle
= mOldExStyle
;
2595 VERIFY_WINDOW_STYLE(style
);
2596 ::SetWindowLongPtrW(hwnd
, GWL_STYLE
, style
);
2597 ::SetWindowLongPtrW(hwnd
, GWL_EXSTYLE
, exStyle
);
2602 /**************************************************************
2604 * SECTION: nsIWidget::Invalidate
2606 * Invalidate an area of the client for painting.
2608 **************************************************************/
2610 // Invalidate this component visible area
2611 NS_METHOD
nsWindow::Invalidate(PRBool aIsSynchronous
)
2615 #ifdef WIDGET_DEBUG_OUTPUT
2616 debug_DumpInvalidate(stdout
,
2620 nsCAutoString("noname"),
2622 #endif // WIDGET_DEBUG_OUTPUT
2624 VERIFY(::InvalidateRect(mWnd
, NULL
, FALSE
));
2626 if (aIsSynchronous
) {
2627 VERIFY(::UpdateWindow(mWnd
));
2633 // Invalidate this component visible area
2634 NS_METHOD
nsWindow::Invalidate(const nsIntRect
& aRect
, PRBool aIsSynchronous
)
2638 #ifdef WIDGET_DEBUG_OUTPUT
2639 debug_DumpInvalidate(stdout
,
2643 nsCAutoString("noname"),
2645 #endif // WIDGET_DEBUG_OUTPUT
2649 rect
.left
= aRect
.x
;
2651 rect
.right
= aRect
.x
+ aRect
.width
;
2652 rect
.bottom
= aRect
.y
+ aRect
.height
;
2654 VERIFY(::InvalidateRect(mWnd
, &rect
, FALSE
));
2656 if (aIsSynchronous
) {
2657 VERIFY(::UpdateWindow(mWnd
));
2664 nsWindow::MakeFullScreen(PRBool aFullScreen
)
2666 #if WINCE_WINDOWS_MOBILE
2669 SetForegroundWindow(mWnd
);
2670 if (nsWindowCE::sMenuBarShown
) {
2672 memset(&sipInfo
, 0, sizeof(SIPINFO
));
2673 sipInfo
.cbSize
= sizeof(SIPINFO
);
2674 if (SipGetInfo(&sipInfo
))
2675 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
),
2676 sipInfo
.rcVisibleDesktop
.bottom
);
2678 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
),
2679 GetSystemMetrics(SM_CYSCREEN
));
2681 if (GetWindowRect(nsWindowCE::sSoftKeyMenuBarHandle
, &menuBarRect
) &&
2682 menuBarRect
.top
< rc
.bottom
)
2683 rc
.bottom
= menuBarRect
.top
;
2684 SHFullScreen(mWnd
, SHFS_HIDETASKBAR
| SHFS_HIDESTARTICON
| SHFS_SHOWSIPBUTTON
);
2687 SHFullScreen(mWnd
, SHFS_HIDETASKBAR
| SHFS_HIDESTARTICON
| SHFS_HIDESIPBUTTON
);
2688 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2692 SHFullScreen(mWnd
, SHFS_SHOWTASKBAR
| SHFS_SHOWSTARTICON
);
2693 SystemParametersInfo(SPI_GETWORKAREA
, 0, &rc
, FALSE
);
2697 mSizeMode
= nsSizeMode_Fullscreen
;
2699 // nsBaseWidget hides the chrome and resizes the window, replicate that here
2700 HideWindowChrome(aFullScreen
);
2701 Resize(rc
.left
, rc
.top
, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, PR_TRUE
);
2708 if (mSizeMode
== nsSizeMode_Fullscreen
)
2710 mOldSizeMode
= mSizeMode
;
2711 SetSizeMode(nsSizeMode_Fullscreen
);
2713 SetSizeMode(mOldSizeMode
);
2716 UpdateNonClientMargins();
2718 // Will call hide chrome, reposition window. Note this will
2719 // also cache dimensions for restoration, so it should only
2720 // be called once per fullscreen request.
2721 nsresult rv
= nsBaseWidget::MakeFullScreen(aFullScreen
);
2723 // Let the dom know via web shell window
2724 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
2725 event
.mSizeMode
= mSizeMode
;
2727 DispatchWindowEvent(&event
);
2733 /**************************************************************
2735 * SECTION: nsIWidget::Update
2737 * Force a synchronous repaint of the window.
2739 **************************************************************/
2741 NS_IMETHODIMP
nsWindow::Update()
2743 nsresult rv
= NS_OK
;
2745 // updates can come through for windows no longer holding an mWnd during
2746 // deletes triggered by JavaScript in buttons with mouse feedback
2748 VERIFY(::UpdateWindow(mWnd
));
2753 /**************************************************************
2755 * SECTION: Native data storage
2757 * nsIWidget::GetNativeData
2758 * nsIWidget::FreeNativeData
2760 * Set or clear native data based on a constant.
2762 **************************************************************/
2764 // Return some native data according to aDataType
2765 void* nsWindow::GetNativeData(PRUint32 aDataType
)
2767 switch (aDataType
) {
2768 case NS_NATIVE_PLUGIN_PORT
:
2769 case NS_NATIVE_WIDGET
:
2770 case NS_NATIVE_WINDOW
:
2772 case NS_NATIVE_GRAPHIC
:
2773 // XXX: This is sleezy!! Remember to Release the DC after using it!
2775 return (void*)(eTransparencyTransparent
== mTransparencyMode
) ?
2776 mMemoryDC
: ::GetDC(mWnd
);
2778 return (void*)::GetDC(mWnd
);
2781 #ifdef NS_ENABLE_TSF
2782 case NS_NATIVE_TSF_THREAD_MGR
:
2783 return nsTextStore::GetThreadMgr();
2784 case NS_NATIVE_TSF_CATEGORY_MGR
:
2785 return nsTextStore::GetCategoryMgr();
2786 case NS_NATIVE_TSF_DISPLAY_ATTR_MGR
:
2787 return nsTextStore::GetDisplayAttrMgr();
2788 #endif //NS_ENABLE_TSF
2797 // Free some native data according to aDataType
2798 void nsWindow::FreeNativeData(void * data
, PRUint32 aDataType
)
2802 case NS_NATIVE_GRAPHIC
:
2804 if (eTransparencyTransparent
!= mTransparencyMode
)
2805 ::ReleaseDC(mWnd
, (HDC
)data
);
2807 ::ReleaseDC(mWnd
, (HDC
)data
);
2810 case NS_NATIVE_WIDGET
:
2811 case NS_NATIVE_WINDOW
:
2812 case NS_NATIVE_PLUGIN_PORT
:
2819 /**************************************************************
2821 * SECTION: nsIWidget::SetTitle
2823 * Set the main windows title text.
2825 **************************************************************/
2827 NS_METHOD
nsWindow::SetTitle(const nsAString
& aTitle
)
2829 const nsString
& strTitle
= PromiseFlatString(aTitle
);
2830 ::SendMessageW(mWnd
, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)(LPCWSTR
)strTitle
.get());
2834 /**************************************************************
2836 * SECTION: nsIWidget::SetIcon
2838 * Set the main windows icon.
2840 **************************************************************/
2842 NS_METHOD
nsWindow::SetIcon(const nsAString
& aIconSpec
)
2845 // Assume the given string is a local identifier for an icon file.
2847 nsCOMPtr
<nsILocalFile
> iconFile
;
2848 ResolveIconName(aIconSpec
, NS_LITERAL_STRING(".ico"),
2849 getter_AddRefs(iconFile
));
2851 return NS_OK
; // not an error if icon is not found
2853 nsAutoString iconPath
;
2854 iconFile
->GetPath(iconPath
);
2856 // XXX this should use MZLU (see bug 239279)
2860 HICON bigIcon
= (HICON
)::LoadImageW(NULL
,
2861 (LPCWSTR
)iconPath
.get(),
2863 ::GetSystemMetrics(SM_CXICON
),
2864 ::GetSystemMetrics(SM_CYICON
),
2866 HICON smallIcon
= (HICON
)::LoadImageW(NULL
,
2867 (LPCWSTR
)iconPath
.get(),
2869 ::GetSystemMetrics(SM_CXSMICON
),
2870 ::GetSystemMetrics(SM_CYSMICON
),
2874 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
)bigIcon
);
2876 ::DestroyIcon(icon
);
2878 #ifdef DEBUG_SetIcon
2880 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
2881 printf( "\nIcon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
2885 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
)smallIcon
);
2887 ::DestroyIcon(icon
);
2889 #ifdef DEBUG_SetIcon
2891 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
2892 printf( "\nSmall icon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
2899 /**************************************************************
2901 * SECTION: nsIWidget::WidgetToScreenOffset
2903 * Return this widget's origin in screen coordinates.
2905 **************************************************************/
2907 nsIntPoint
nsWindow::WidgetToScreenOffset()
2912 ::ClientToScreen(mWnd
, &point
);
2913 return nsIntPoint(point
.x
, point
.y
);
2916 nsIntSize
nsWindow::ClientToWindowSize(const nsIntSize
& aClientSize
)
2918 if (!IsPopupWithTitleBar())
2921 // just use (200, 200) as the position
2925 r
.right
= 200 + aClientSize
.width
;
2926 r
.bottom
= 200 + aClientSize
.height
;
2927 ::AdjustWindowRectEx(&r
, WindowStyle(), PR_FALSE
, WindowExStyle());
2929 return nsIntSize(r
.right
- r
.left
, r
.bottom
- r
.top
);
2932 /**************************************************************
2934 * SECTION: nsIWidget::EnableDragDrop
2936 * Enables/Disables drag and drop of files on this widget.
2938 **************************************************************/
2940 #if !defined(WINCE) // implemented in nsWindowCE.cpp
2941 NS_METHOD
nsWindow::EnableDragDrop(PRBool aEnable
)
2943 NS_ASSERTION(mWnd
, "nsWindow::EnableDragDrop() called after Destroy()");
2945 nsresult rv
= NS_ERROR_FAILURE
;
2947 if (nsnull
== mNativeDragTarget
) {
2948 mNativeDragTarget
= new nsNativeDragTarget(this);
2949 if (NULL
!= mNativeDragTarget
) {
2950 mNativeDragTarget
->AddRef();
2951 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
,TRUE
,FALSE
)) {
2952 if (S_OK
== ::RegisterDragDrop(mWnd
, (LPDROPTARGET
)mNativeDragTarget
)) {
2959 if (nsnull
!= mWnd
&& NULL
!= mNativeDragTarget
) {
2960 ::RevokeDragDrop(mWnd
);
2961 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
, FALSE
, TRUE
)) {
2964 mNativeDragTarget
->DragCancel();
2965 NS_RELEASE(mNativeDragTarget
);
2972 /**************************************************************
2974 * SECTION: nsIWidget::CaptureMouse
2976 * Enables/Disables system mouse capture.
2978 **************************************************************/
2980 NS_METHOD
nsWindow::CaptureMouse(PRBool aCapture
)
2982 if (!nsToolkit::gMouseTrailer
) {
2983 NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
2988 nsToolkit::gMouseTrailer
->SetCaptureWindow(mWnd
);
2991 nsToolkit::gMouseTrailer
->SetCaptureWindow(NULL
);
2994 mIsInMouseCapture
= aCapture
;
2998 /**************************************************************
3000 * SECTION: nsIWidget::CaptureRollupEvents
3002 * Dealing with event rollup on destroy for popups. Enables &
3003 * Disables system capture of any and all events that would
3004 * cause a dropdown to be rolled up.
3006 **************************************************************/
3008 NS_IMETHODIMP
nsWindow::CaptureRollupEvents(nsIRollupListener
* aListener
,
3009 nsIMenuRollup
* aMenuRollup
,
3011 PRBool aConsumeRollupEvent
)
3014 /* we haven't bothered carrying a weak reference to sRollupWidget because
3015 we believe lifespan is properly scoped. this next assertion helps
3016 assure that remains true. */
3017 NS_ASSERTION(!sRollupWidget
, "rollup widget reassigned before release");
3018 sRollupConsumeEvent
= aConsumeRollupEvent
;
3019 NS_IF_RELEASE(sRollupWidget
);
3020 NS_IF_RELEASE(sMenuRollup
);
3021 sRollupListener
= aListener
;
3022 sMenuRollup
= aMenuRollup
;
3023 NS_IF_ADDREF(aMenuRollup
);
3024 sRollupWidget
= this;
3028 if (!sMsgFilterHook
&& !sCallProcHook
&& !sCallMouseHook
) {
3029 RegisterSpecialDropdownHooks();
3031 sProcessHook
= PR_TRUE
;
3035 sRollupListener
= nsnull
;
3036 NS_IF_RELEASE(sMenuRollup
);
3037 NS_IF_RELEASE(sRollupWidget
);
3040 sProcessHook
= PR_FALSE
;
3041 UnregisterSpecialDropdownHooks();
3048 /**************************************************************
3050 * SECTION: nsIWidget::GetAttention
3052 * Bring this window to the user's attention.
3054 **************************************************************/
3056 // Draw user's attention to this window until it comes to foreground.
3058 nsWindow::GetAttention(PRInt32 aCycleCount
)
3063 return NS_ERROR_NOT_INITIALIZED
;
3065 // Don't flash if the flash count is 0 or if the
3066 // top level window is already active.
3067 HWND fgWnd
= ::GetForegroundWindow();
3068 if (aCycleCount
== 0 || fgWnd
== GetTopLevelHWND(mWnd
))
3071 HWND flashWnd
= mWnd
;
3072 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
3073 flashWnd
= ownerWnd
;
3076 // Don't flash if the owner window is active either.
3077 if (fgWnd
== flashWnd
)
3080 DWORD defaultCycleCount
= 0;
3081 ::SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT
, 0, &defaultCycleCount
, 0);
3083 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
3084 FLASHW_ALL
, aCycleCount
> 0 ? aCycleCount
: defaultCycleCount
, 0 };
3085 ::FlashWindowEx(&flashInfo
);
3090 void nsWindow::StopFlashing()
3093 HWND flashWnd
= mWnd
;
3094 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
3095 flashWnd
= ownerWnd
;
3098 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
3099 FLASHW_STOP
, 0, 0 };
3100 ::FlashWindowEx(&flashInfo
);
3104 /**************************************************************
3106 * SECTION: nsIWidget::HasPendingInputEvent
3108 * Ask whether there user input events pending. All input events are
3109 * included, including those not targeted at this nsIwidget instance.
3111 **************************************************************/
3114 nsWindow::HasPendingInputEvent()
3116 // If there is pending input or the user is currently
3117 // moving the window then return true.
3118 // Note: When the user is moving the window WIN32 spins
3119 // a separate event loop and input events are not
3120 // reported to the application.
3121 if (HIWORD(GetQueueStatus(QS_INPUT
)))
3126 GUITHREADINFO guiInfo
;
3127 guiInfo
.cbSize
= sizeof(GUITHREADINFO
);
3128 if (!GetGUIThreadInfo(GetCurrentThreadId(), &guiInfo
))
3130 return GUI_INMOVESIZE
== (guiInfo
.flags
& GUI_INMOVESIZE
);
3134 /**************************************************************
3136 * SECTION: nsIWidget::GetLayerManager
3138 * Get the layer manager associated with this widget.
3140 **************************************************************/
3142 mozilla::layers::LayerManager
*
3143 nsWindow::GetLayerManager()
3145 nsWindow
*topWindow
= GetNSWindowPtr(GetTopLevelHWND(mWnd
, PR_TRUE
));
3148 return nsBaseWidget::GetLayerManager();
3151 if (topWindow
->GetAcceleratedRendering() != mUseAcceleratedRendering
) {
3152 mLayerManager
= NULL
;
3153 mUseAcceleratedRendering
= topWindow
->GetAcceleratedRendering();
3157 if (!mLayerManager
) {
3158 if (mUseAcceleratedRendering
) {
3159 nsCOMPtr
<nsIPrefBranch2
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
3161 PRBool allowAcceleration
= PR_TRUE
;
3162 PRBool preferOpenGL
= PR_FALSE
;
3164 prefs
->GetBoolPref("mozilla.widget.accelerated-layers",
3165 &allowAcceleration
);
3166 prefs
->GetBoolPref("mozilla.layers.prefer-opengl",
3170 if (allowAcceleration
) {
3171 #ifdef MOZ_ENABLE_D3D9_LAYER
3172 if (!preferOpenGL
) {
3173 nsRefPtr
<mozilla::layers::LayerManagerD3D9
> layerManager
=
3174 new mozilla::layers::LayerManagerD3D9(this);
3175 if (layerManager
->Initialize()) {
3176 mLayerManager
= layerManager
;
3180 if (!mLayerManager
) {
3181 nsRefPtr
<mozilla::layers::LayerManagerOGL
> layerManager
=
3182 new mozilla::layers::LayerManagerOGL(this);
3183 if (layerManager
->Initialize()) {
3184 mLayerManager
= layerManager
;
3192 return nsBaseWidget::GetLayerManager();
3195 /**************************************************************
3197 * SECTION: nsIWidget::GetThebesSurface
3199 * Get the Thebes surface associated with this widget.
3201 **************************************************************/
3203 gfxASurface
*nsWindow::GetThebesSurface()
3205 #ifdef CAIRO_HAS_D2D_SURFACE
3206 if (mD2DWindowSurface
) {
3207 return mD2DWindowSurface
;
3211 return (new gfxWindowsSurface(mPaintDC
));
3213 #ifdef CAIRO_HAS_D2D_SURFACE
3214 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
3215 gfxWindowsPlatform::RENDER_DIRECT2D
) {
3216 gfxASurface::gfxContentType content
= gfxASurface::CONTENT_COLOR
;
3217 #if defined(MOZ_XUL)
3218 if (mTransparencyMode
!= eTransparencyOpaque
) {
3219 content
= gfxASurface::CONTENT_COLOR_ALPHA
;
3222 return (new gfxD2DSurface(mWnd
, content
));
3225 PRUint32 flags
= gfxWindowsSurface::FLAG_TAKE_DC
;
3226 if (mTransparencyMode
!= eTransparencyOpaque
) {
3227 flags
|= gfxWindowsSurface::FLAG_IS_TRANSPARENT
;
3229 return (new gfxWindowsSurface(mWnd
, flags
));
3230 #ifdef CAIRO_HAS_D2D_SURFACE
3235 /**************************************************************
3237 * SECTION: nsIWidget::OnDefaultButtonLoaded
3239 * Called after the dialog is loaded and it has a default button.
3241 **************************************************************/
3244 nsWindow::OnDefaultButtonLoaded(const nsIntRect
&aButtonRect
)
3247 return NS_ERROR_NOT_IMPLEMENTED
;
3249 if (aButtonRect
.IsEmpty())
3252 // Don't snap when we are not active.
3253 HWND activeWnd
= ::GetActiveWindow();
3254 if (activeWnd
!= ::GetForegroundWindow() ||
3255 GetTopLevelHWND(mWnd
, PR_TRUE
) != GetTopLevelHWND(activeWnd
, PR_TRUE
)) {
3259 PRBool isAlwaysSnapCursor
= PR_FALSE
;
3260 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
3262 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
3263 prefs
->GetBranch(nsnull
, getter_AddRefs(prefBranch
));
3265 prefBranch
->GetBoolPref("ui.cursor_snapping.always_enabled",
3266 &isAlwaysSnapCursor
);
3270 if (!isAlwaysSnapCursor
) {
3271 BOOL snapDefaultButton
;
3272 if (!::SystemParametersInfo(SPI_GETSNAPTODEFBUTTON
, 0,
3273 &snapDefaultButton
, 0) || !snapDefaultButton
)
3277 nsIntRect widgetRect
;
3278 nsresult rv
= GetScreenBounds(widgetRect
);
3279 NS_ENSURE_SUCCESS(rv
, rv
);
3280 nsIntRect
buttonRect(aButtonRect
+ widgetRect
.TopLeft());
3282 nsIntPoint
centerOfButton(buttonRect
.x
+ buttonRect
.width
/ 2,
3283 buttonRect
.y
+ buttonRect
.height
/ 2);
3284 // The center of the button can be outside of the widget.
3285 // E.g., it could be hidden by scrolling.
3286 if (!widgetRect
.Contains(centerOfButton
)) {
3290 if (!::SetCursorPos(centerOfButton
.x
, centerOfButton
.y
)) {
3291 NS_ERROR("SetCursorPos failed");
3292 return NS_ERROR_FAILURE
;
3299 nsWindow::OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta
,
3300 PRBool aIsHorizontal
,
3301 PRInt32
&aOverriddenDelta
)
3303 // The default vertical and horizontal scrolling speed is 3, this is defined
3304 // on the document of SystemParametersInfo in MSDN.
3305 const PRUint32 kSystemDefaultScrollingSpeed
= 3;
3307 PRInt32 absOriginDelta
= PR_ABS(aOriginalDelta
);
3309 // Compute the simple overridden speed.
3310 PRInt32 absComputedOverriddenDelta
;
3312 nsBaseWidget::OverrideSystemMouseScrollSpeed(absOriginDelta
, aIsHorizontal
,
3313 absComputedOverriddenDelta
);
3314 NS_ENSURE_SUCCESS(rv
, rv
);
3316 aOverriddenDelta
= aOriginalDelta
;
3318 if (absComputedOverriddenDelta
== absOriginDelta
) {
3319 // We don't override now.
3323 // Otherwise, we should check whether the user customized the system settings
3324 // or not. If the user did it, we should respect the will.
3326 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, &systemSpeed
, 0)) {
3327 return NS_ERROR_FAILURE
;
3329 // The default vertical scrolling speed is 3, this is defined on the document
3330 // of SystemParametersInfo in MSDN.
3331 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
3335 // Only Vista and later, Windows has the system setting of horizontal
3336 // scrolling by the mouse wheel.
3337 if (GetWindowsVersion() >= VISTA_VERSION
) {
3338 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0, &systemSpeed
, 0)) {
3339 return NS_ERROR_FAILURE
;
3341 // The default horizontal scrolling speed is 3, this is defined on the
3342 // document of SystemParametersInfo in MSDN.
3343 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
3348 // Limit the overridden delta value from the system settings. The mouse
3349 // driver might accelerate the scrolling speed already. If so, we shouldn't
3350 // override the scrolling speed for preventing the unexpected high speed
3352 PRInt32 absDeltaLimit
;
3354 nsBaseWidget::OverrideSystemMouseScrollSpeed(kSystemDefaultScrollingSpeed
,
3355 aIsHorizontal
, absDeltaLimit
);
3356 NS_ENSURE_SUCCESS(rv
, rv
);
3358 // If the given delta is larger than our computed limitation value, the delta
3359 // was accelerated by the mouse driver. So, we should do nothing here.
3360 if (absDeltaLimit
<= absOriginDelta
) {
3364 absComputedOverriddenDelta
=
3365 PR_MIN(absComputedOverriddenDelta
, absDeltaLimit
);
3367 aOverriddenDelta
= (aOriginalDelta
> 0) ? absComputedOverriddenDelta
:
3368 -absComputedOverriddenDelta
;
3372 /**************************************************************
3373 **************************************************************
3375 ** BLOCK: Moz Events
3377 ** Moz GUI event management.
3379 **************************************************************
3380 **************************************************************/
3382 /**************************************************************
3384 * SECTION: Mozilla event initialization
3386 * Helpers for initializing moz events.
3388 **************************************************************/
3390 // Event intialization
3391 MSG
nsWindow::InitMSG(UINT aMessage
, WPARAM wParam
, LPARAM lParam
)
3394 msg
.message
= aMessage
;
3395 msg
.wParam
= wParam
;
3396 msg
.lParam
= lParam
;
3400 void nsWindow::InitEvent(nsGUIEvent
& event
, nsIntPoint
* aPoint
)
3402 if (nsnull
== aPoint
) { // use the point from the event
3403 // get the message position in client coordinates
3406 DWORD pos
= ::GetMessagePos();
3409 cpos
.x
= GET_X_LPARAM(pos
);
3410 cpos
.y
= GET_Y_LPARAM(pos
);
3412 ::ScreenToClient(mWnd
, &cpos
);
3413 event
.refPoint
.x
= cpos
.x
;
3414 event
.refPoint
.y
= cpos
.y
;
3416 event
.refPoint
.x
= 0;
3417 event
.refPoint
.y
= 0;
3421 // use the point override if provided
3422 event
.refPoint
.x
= aPoint
->x
;
3423 event
.refPoint
.y
= aPoint
->y
;
3427 event
.time
= ::GetMessageTime();
3429 event
.time
= PR_Now() / 1000;
3432 mLastPoint
= event
.refPoint
;
3435 /**************************************************************
3437 * SECTION: Moz event dispatch helpers
3439 * Helpers for dispatching different types of moz events.
3441 **************************************************************/
3443 // Main event dispatch. Invokes callback and ProcessEvent method on
3444 // Event Listener object. Part of nsIWidget.
3445 NS_IMETHODIMP
nsWindow::DispatchEvent(nsGUIEvent
* event
, nsEventStatus
& aStatus
)
3447 #ifdef WIDGET_DEBUG_OUTPUT
3448 debug_DumpEvent(stdout
,
3451 nsCAutoString("something"),
3453 #endif // WIDGET_DEBUG_OUTPUT
3455 aStatus
= nsEventStatus_eIgnore
;
3457 // skip processing of suppressed blur events
3458 if (event
->message
== NS_DEACTIVATE
&& BlurEventsSuppressed())
3461 // Top level windows can have a view attached which requires events be sent
3462 // to the underlying base window and the view. Added when we combined the
3463 // base chrome window with the main content child for nc client area (title
3465 if (mViewCallback
) {
3466 // A subset of events are sent to the base xul window first
3467 switch(event
->message
) {
3468 // send to the base window (view mgr ignores these for the view)
3469 case NS_UISTATECHANGED
:
3474 (*mEventCallback
)(event
); // web shell / xul window
3477 // sent to the base window, then to the view
3482 (*mEventCallback
)(event
); // web shell / xul window
3485 // attached view events
3486 aStatus
= (*mViewCallback
)(event
);
3488 else if (mEventCallback
) {
3489 aStatus
= (*mEventCallback
)(event
);
3492 // the window can be destroyed during processing of seemingly innocuous events like, say,
3493 // mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
3494 // which causes problems with the deleted window. therefore:
3495 if (mOnDestroyCalled
)
3496 aStatus
= nsEventStatus_eConsumeNoDefault
;
3500 PRBool
nsWindow::DispatchStandardEvent(PRUint32 aMsg
)
3502 nsGUIEvent
event(PR_TRUE
, aMsg
, this);
3505 PRBool result
= DispatchWindowEvent(&event
);
3509 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
)
3511 nsEventStatus status
;
3512 DispatchEvent(event
, status
);
3513 return ConvertStatus(status
);
3516 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
, nsEventStatus
&aStatus
) {
3517 DispatchEvent(event
, aStatus
);
3518 return ConvertStatus(aStatus
);
3521 PRBool
nsWindow::DispatchKeyEvent(PRUint32 aEventType
, WORD aCharCode
,
3522 const nsTArray
<nsAlternativeCharCode
>* aAlternativeCharCodes
,
3523 UINT aVirtualCharCode
, const MSG
*aMsg
,
3524 const nsModifierKeyState
&aModKeyState
,
3529 nsKeyEvent
event(PR_TRUE
, aEventType
, this);
3530 nsIntPoint
point(0, 0);
3532 InitEvent(event
, &point
); // this add ref's event.widget
3534 event
.flags
|= aFlags
;
3535 event
.charCode
= aCharCode
;
3536 if (aAlternativeCharCodes
)
3537 event
.alternativeCharCodes
.AppendElements(*aAlternativeCharCodes
);
3538 event
.keyCode
= aVirtualCharCode
;
3542 printf("%d DispatchKE Type: %s charCode %d keyCode %d ", cnt
++,
3543 (NS_KEY_PRESS
== aEventType
) ? "PRESS" : (aEventType
== NS_KEY_UP
? "Up" : "Down"),
3544 event
.charCode
, event
.keyCode
);
3545 printf("Shift: %s Control %s Alt: %s \n",
3546 (mIsShiftDown
? "D" : "U"), (mIsControlDown
? "D" : "U"), (mIsAltDown
? "D" : "U"));
3547 printf("[%c][%c][%c] <== [%c][%c][%c][ space bar ][%c][%c][%c]\n",
3548 IS_VK_DOWN(NS_VK_SHIFT
) ? 'S' : ' ',
3549 IS_VK_DOWN(NS_VK_CONTROL
) ? 'C' : ' ',
3550 IS_VK_DOWN(NS_VK_ALT
) ? 'A' : ' ',
3551 IS_VK_DOWN(VK_LSHIFT
) ? 'S' : ' ',
3552 IS_VK_DOWN(VK_LCONTROL
) ? 'C' : ' ',
3553 IS_VK_DOWN(VK_LMENU
) ? 'A' : ' ',
3554 IS_VK_DOWN(VK_RMENU
) ? 'A' : ' ',
3555 IS_VK_DOWN(VK_RCONTROL
) ? 'C' : ' ',
3556 IS_VK_DOWN(VK_RSHIFT
) ? 'S' : ' ');
3559 event
.isShift
= aModKeyState
.mIsShiftDown
;
3560 event
.isControl
= aModKeyState
.mIsControlDown
;
3561 event
.isMeta
= PR_FALSE
;
3562 event
.isAlt
= aModKeyState
.mIsAltDown
;
3564 NPEvent pluginEvent
;
3565 if (aMsg
&& PluginHasFocus()) {
3566 pluginEvent
.event
= aMsg
->message
;
3567 pluginEvent
.wParam
= aMsg
->wParam
;
3568 pluginEvent
.lParam
= aMsg
->lParam
;
3569 event
.pluginEvent
= (void *)&pluginEvent
;
3572 PRBool result
= DispatchWindowEvent(&event
);
3577 PRBool
nsWindow::DispatchCommandEvent(PRUint32 aEventCommand
)
3579 nsCOMPtr
<nsIAtom
> command
;
3580 switch (aEventCommand
) {
3581 case APPCOMMAND_BROWSER_BACKWARD
:
3582 command
= nsWidgetAtoms::Back
;
3584 case APPCOMMAND_BROWSER_FORWARD
:
3585 command
= nsWidgetAtoms::Forward
;
3587 case APPCOMMAND_BROWSER_REFRESH
:
3588 command
= nsWidgetAtoms::Reload
;
3590 case APPCOMMAND_BROWSER_STOP
:
3591 command
= nsWidgetAtoms::Stop
;
3593 case APPCOMMAND_BROWSER_SEARCH
:
3594 command
= nsWidgetAtoms::Search
;
3596 case APPCOMMAND_BROWSER_FAVORITES
:
3597 command
= nsWidgetAtoms::Bookmarks
;
3599 case APPCOMMAND_BROWSER_HOME
:
3600 command
= nsWidgetAtoms::Home
;
3605 nsCommandEvent
event(PR_TRUE
, nsWidgetAtoms::onAppCommand
, command
, this);
3608 DispatchWindowEvent(&event
);
3613 // Recursively dispatch synchronous paints for nsIWidget
3614 // descendants with invalidated rectangles.
3615 BOOL CALLBACK
nsWindow::DispatchStarvedPaints(HWND aWnd
, LPARAM aMsg
)
3617 LONG_PTR proc
= ::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
3618 if (proc
== (LONG_PTR
)&nsWindow::WindowProc
) {
3619 // its one of our windows so check to see if it has a
3620 // invalidated rect. If it does. Dispatch a synchronous
3622 if (GetUpdateRect(aWnd
, NULL
, FALSE
))
3623 VERIFY(::UpdateWindow(aWnd
));
3628 // Check for pending paints and dispatch any pending paint
3629 // messages for any nsIWidget which is a descendant of the
3630 // top-level window that *this* window is embedded within.
3632 // Note: We do not dispatch pending paint messages for non
3633 // nsIWidget managed windows.
3634 void nsWindow::DispatchPendingEvents()
3637 NS_WARNING("We were asked to dispatch pending events during painting, "
3638 "denying since that's unsafe.");
3642 // We need to ensure that reflow events do not get starved.
3643 // At the same time, we don't want to recurse through here
3644 // as that would prevent us from dispatching starved paints.
3645 static int recursionBlocker
= 0;
3646 if (recursionBlocker
++ == 0) {
3647 NS_ProcessPendingEvents(nsnull
, PR_MillisecondsToInterval(100));
3651 // Quickly check to see if there are any
3652 // paint events pending.
3653 if (::GetQueueStatus(QS_PAINT
)) {
3654 // Find the top level window.
3655 HWND topWnd
= GetTopLevelHWND(mWnd
);
3657 // Dispatch pending paints for all topWnd's descendant windows.
3658 // Note: EnumChildWindows enumerates all descendant windows not just
3661 ::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, 0);
3663 nsWindowCE::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, NULL
);
3668 // Deal with plugin events
3669 PRBool
nsWindow::DispatchPluginEvent(const MSG
&aMsg
)
3671 if (!PluginHasFocus())
3674 nsGUIEvent
event(PR_TRUE
, NS_PLUGIN_EVENT
, this);
3675 nsIntPoint
point(0, 0);
3676 InitEvent(event
, &point
);
3677 NPEvent pluginEvent
;
3678 pluginEvent
.event
= aMsg
.message
;
3679 pluginEvent
.wParam
= aMsg
.wParam
;
3680 pluginEvent
.lParam
= aMsg
.lParam
;
3681 event
.pluginEvent
= (void *)&pluginEvent
;
3682 return DispatchWindowEvent(&event
);
3685 PRBool
nsWindow::DispatchPluginEvent(UINT aMessage
,
3688 PRBool aDispatchPendingEvents
)
3690 PRBool ret
= DispatchPluginEvent(InitMSG(aMessage
, aWParam
, aLParam
));
3691 if (aDispatchPendingEvents
) {
3692 DispatchPendingEvents();
3697 void nsWindow::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg
,
3701 ::GetMessageW(&msg
, mWnd
, aFirstMsg
, aLastMsg
);
3702 DispatchPluginEvent(msg
);
3705 // Deal with all sort of mouse event
3706 PRBool
nsWindow::DispatchMouseEvent(PRUint32 aEventType
, WPARAM wParam
,
3707 LPARAM lParam
, PRBool aIsContextMenuKey
,
3708 PRInt16 aButton
, PRUint16 aInputSource
)
3710 PRBool result
= PR_FALSE
;
3714 if (!mEventCallback
) {
3718 switch (aEventType
) {
3719 case NS_MOUSE_BUTTON_DOWN
:
3720 CaptureMouse(PR_TRUE
);
3723 // NS_MOUSE_MOVE and NS_MOUSE_EXIT are here because we need to make sure capture flag
3724 // isn't left on after a drag where we wouldn't see a button up message (see bug 324131).
3725 case NS_MOUSE_BUTTON_UP
:
3728 if (!(wParam
& (MK_LBUTTON
| MK_MBUTTON
| MK_RBUTTON
)) && mIsInMouseCapture
)
3729 CaptureMouse(PR_FALSE
);
3737 nsIntPoint eventPoint
;
3738 eventPoint
.x
= GET_X_LPARAM(lParam
);
3739 eventPoint
.y
= GET_Y_LPARAM(lParam
);
3741 nsMouseEvent
event(PR_TRUE
, aEventType
, this, nsMouseEvent::eReal
,
3743 ? nsMouseEvent::eContextMenuKey
3744 : nsMouseEvent::eNormal
);
3745 if (aEventType
== NS_CONTEXTMENU
&& aIsContextMenuKey
) {
3746 nsIntPoint
zero(0, 0);
3747 InitEvent(event
, &zero
);
3749 InitEvent(event
, &eventPoint
);
3752 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
3753 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
3754 event
.isMeta
= PR_FALSE
;
3755 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
3756 event
.button
= aButton
;
3757 event
.inputSource
= aInputSource
;
3759 nsIntPoint mpScreen
= eventPoint
+ WidgetToScreenOffset();
3761 // Suppress mouse moves caused by widget creation
3762 if (aEventType
== NS_MOUSE_MOVE
)
3764 if ((sLastMouseMovePoint
.x
== mpScreen
.x
) && (sLastMouseMovePoint
.y
== mpScreen
.y
))
3766 sLastMouseMovePoint
.x
= mpScreen
.x
;
3767 sLastMouseMovePoint
.y
= mpScreen
.y
;
3770 PRBool insideMovementThreshold
= (abs(sLastMousePoint
.x
- eventPoint
.x
) < (short)::GetSystemMetrics(SM_CXDOUBLECLK
)) &&
3771 (abs(sLastMousePoint
.y
- eventPoint
.y
) < (short)::GetSystemMetrics(SM_CYDOUBLECLK
));
3775 case nsMouseEvent::eLeftButton
:
3776 eventButton
= VK_LBUTTON
;
3778 case nsMouseEvent::eMiddleButton
:
3779 eventButton
= VK_MBUTTON
;
3781 case nsMouseEvent::eRightButton
:
3782 eventButton
= VK_RBUTTON
;
3789 // Doubleclicks are used to set the click count, then changed to mousedowns
3790 // We're going to time double-clicks from mouse *up* to next mouse *down*
3792 LONG curMsgTime
= ::GetMessageTime();
3794 LONG curMsgTime
= PR_Now() / 1000;
3797 if (aEventType
== NS_MOUSE_DOUBLECLICK
) {
3798 event
.message
= NS_MOUSE_BUTTON_DOWN
;
3799 event
.button
= aButton
;
3800 sLastClickCount
= 2;
3802 else if (aEventType
== NS_MOUSE_BUTTON_UP
) {
3803 // remember when this happened for the next mouse down
3804 sLastMousePoint
.x
= eventPoint
.x
;
3805 sLastMousePoint
.y
= eventPoint
.y
;
3806 sLastMouseButton
= eventButton
;
3808 else if (aEventType
== NS_MOUSE_BUTTON_DOWN
) {
3809 // now look to see if we want to convert this to a double- or triple-click
3810 if (((curMsgTime
- sLastMouseDownTime
) < (LONG
)::GetDoubleClickTime()) && insideMovementThreshold
&&
3811 eventButton
== sLastMouseButton
) {
3814 // reset the click count, to count *this* click
3815 sLastClickCount
= 1;
3817 // Set last Click time on MouseDown only
3818 sLastMouseDownTime
= curMsgTime
;
3820 else if (aEventType
== NS_MOUSE_MOVE
&& !insideMovementThreshold
) {
3821 sLastClickCount
= 0;
3823 else if (aEventType
== NS_MOUSE_EXIT
) {
3824 event
.exit
= IsTopLevelMouseExit(mWnd
) ? nsMouseEvent::eTopLevel
: nsMouseEvent::eChild
;
3826 else if (aEventType
== NS_MOUSE_MOZHITTEST
)
3828 event
.flags
|= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH
;
3830 event
.clickCount
= sLastClickCount
;
3833 printf("Msg Time: %d Click Count: %d\n", curMsgTime
, event
.clickCount
);
3836 NPEvent pluginEvent
;
3840 case NS_MOUSE_BUTTON_DOWN
:
3842 case nsMouseEvent::eLeftButton
:
3843 pluginEvent
.event
= WM_LBUTTONDOWN
;
3845 case nsMouseEvent::eMiddleButton
:
3846 pluginEvent
.event
= WM_MBUTTONDOWN
;
3848 case nsMouseEvent::eRightButton
:
3849 pluginEvent
.event
= WM_RBUTTONDOWN
;
3855 case NS_MOUSE_BUTTON_UP
:
3857 case nsMouseEvent::eLeftButton
:
3858 pluginEvent
.event
= WM_LBUTTONUP
;
3860 case nsMouseEvent::eMiddleButton
:
3861 pluginEvent
.event
= WM_MBUTTONUP
;
3863 case nsMouseEvent::eRightButton
:
3864 pluginEvent
.event
= WM_RBUTTONUP
;
3870 case NS_MOUSE_DOUBLECLICK
:
3872 case nsMouseEvent::eLeftButton
:
3873 pluginEvent
.event
= WM_LBUTTONDBLCLK
;
3875 case nsMouseEvent::eMiddleButton
:
3876 pluginEvent
.event
= WM_MBUTTONDBLCLK
;
3878 case nsMouseEvent::eRightButton
:
3879 pluginEvent
.event
= WM_RBUTTONDBLCLK
;
3886 pluginEvent
.event
= WM_MOUSEMOVE
;
3889 pluginEvent
.event
= WM_MOUSELEAVE
;
3892 pluginEvent
.event
= WM_NULL
;
3896 pluginEvent
.wParam
= wParam
; // plugins NEED raw OS event flags!
3897 pluginEvent
.lParam
= lParam
;
3899 event
.pluginEvent
= (void *)&pluginEvent
;
3901 // call the event callback
3902 if (nsnull
!= mEventCallback
) {
3903 if (nsToolkit::gMouseTrailer
)
3904 nsToolkit::gMouseTrailer
->Disable();
3905 if (aEventType
== NS_MOUSE_MOVE
) {
3906 if (nsToolkit::gMouseTrailer
&& !mIsInMouseCapture
) {
3907 nsToolkit::gMouseTrailer
->SetMouseTrailerWindow(mWnd
);
3914 if (rect
.Contains(event
.refPoint
)) {
3915 if (sCurrentWindow
== NULL
|| sCurrentWindow
!= this) {
3916 if ((nsnull
!= sCurrentWindow
) && (!sCurrentWindow
->mInDtor
)) {
3917 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
3918 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_EXIT
, wParam
, pos
, PR_FALSE
,
3919 nsMouseEvent::eLeftButton
, aInputSource
);
3921 sCurrentWindow
= this;
3923 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
3924 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_ENTER
, wParam
, pos
, PR_FALSE
,
3925 nsMouseEvent::eLeftButton
, aInputSource
);
3929 } else if (aEventType
== NS_MOUSE_EXIT
) {
3930 if (sCurrentWindow
== this) {
3931 sCurrentWindow
= nsnull
;
3935 result
= DispatchWindowEvent(&event
);
3937 if (nsToolkit::gMouseTrailer
)
3938 nsToolkit::gMouseTrailer
->Enable();
3940 // Release the widget with NS_IF_RELEASE() just in case
3941 // the context menu key code in nsEventListenerManager::HandleEvent()
3942 // released it already.
3949 // Deal with accessibile event
3950 #ifdef ACCESSIBILITY
3952 nsWindow::DispatchAccessibleEvent(PRUint32 aEventType
)
3954 if (nsnull
== mEventCallback
) {
3958 nsAccessibleEvent
event(PR_TRUE
, aEventType
, this);
3959 InitEvent(event
, nsnull
);
3961 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
3962 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
3963 event
.isMeta
= PR_FALSE
;
3964 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
3966 DispatchWindowEvent(&event
);
3968 return event
.mAccessible
;
3972 PRBool
nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType
)
3974 if (aEventType
== NS_ACTIVATE
)
3975 sJustGotActivate
= PR_FALSE
;
3976 sJustGotDeactivate
= PR_FALSE
;
3978 // retrive the toplevel window or dialog
3980 HWND toplevelWnd
= NULL
;
3982 toplevelWnd
= curWnd
;
3984 nsWindow
*win
= GetNSWindowPtr(curWnd
);
3986 nsWindowType wintype
;
3987 win
->GetWindowType(wintype
);
3988 if (wintype
== eWindowType_toplevel
|| wintype
== eWindowType_dialog
)
3992 curWnd
= ::GetParent(curWnd
); // Parent or owner (if has no parent)
3996 nsWindow
*win
= GetNSWindowPtr(toplevelWnd
);
3998 return win
->DispatchFocus(aEventType
);
4004 // Deal with focus messages
4005 PRBool
nsWindow::DispatchFocus(PRUint32 aEventType
)
4007 // call the event callback
4008 if (mEventCallback
) {
4009 nsGUIEvent
event(PR_TRUE
, aEventType
, this);
4012 //focus and blur event should go to their base widget loc, not current mouse pos
4013 event
.refPoint
.x
= 0;
4014 event
.refPoint
.y
= 0;
4016 NPEvent pluginEvent
;
4021 pluginEvent
.event
= WM_SETFOCUS
;
4024 pluginEvent
.event
= WM_KILLFOCUS
;
4026 case NS_PLUGIN_ACTIVATE
:
4027 pluginEvent
.event
= WM_KILLFOCUS
;
4033 event
.pluginEvent
= (void *)&pluginEvent
;
4035 return DispatchWindowEvent(&event
);
4040 PRBool
nsWindow::IsTopLevelMouseExit(HWND aWnd
)
4042 DWORD pos
= ::GetMessagePos();
4044 mp
.x
= GET_X_LPARAM(pos
);
4045 mp
.y
= GET_Y_LPARAM(pos
);
4046 HWND mouseWnd
= ::WindowFromPoint(mp
);
4048 // GetTopLevelHWND will return a HWND for the window frame (which includes
4049 // the non-client area). If the mouse has moved into the non-client area,
4050 // we should treat it as a top-level exit.
4051 HWND mouseTopLevel
= nsWindow::GetTopLevelHWND(mouseWnd
);
4052 if (mouseWnd
== mouseTopLevel
)
4055 return nsWindow::GetTopLevelHWND(aWnd
) != mouseTopLevel
;
4058 PRBool
nsWindow::BlurEventsSuppressed()
4060 // are they suppressed in this window?
4061 if (mBlurSuppressLevel
> 0)
4064 // are they suppressed by any container widget?
4065 HWND parentWnd
= ::GetParent(mWnd
);
4067 nsWindow
*parent
= GetNSWindowPtr(parentWnd
);
4069 return parent
->BlurEventsSuppressed();
4074 // In some circumstances (opening dependent windows) it makes more sense
4075 // (and fixes a crash bug) to not blur the parent window. Called from
4077 void nsWindow::SuppressBlurEvents(PRBool aSuppress
)
4080 ++mBlurSuppressLevel
; // for this widget
4082 NS_ASSERTION(mBlurSuppressLevel
> 0, "unbalanced blur event suppression");
4083 if (mBlurSuppressLevel
> 0)
4084 --mBlurSuppressLevel
;
4088 PRBool
nsWindow::ConvertStatus(nsEventStatus aStatus
)
4090 return aStatus
== nsEventStatus_eConsumeNoDefault
;
4093 /**************************************************************
4097 * IPC related helpers.
4099 **************************************************************/
4105 nsWindow::IsAsyncResponseEvent(UINT aMsg
, LRESULT
& aResult
)
4111 case WM_WINDOWPOSCHANGING
:
4112 case WM_WINDOWPOSCHANGED
:
4113 case WM_PARENTNOTIFY
:
4114 case WM_ACTIVATEAPP
:
4117 case WM_CHILDACTIVATE
:
4118 case WM_IME_SETCONTEXT
:
4122 case WM_MOUSEACTIVATE
:
4123 case WM_CONTEXTMENU
:
4127 case WM_SETTINGCHANGE
:
4135 "An unhandled ISMEX_SEND message was received during spin loop! (%X)", aMsg
);
4143 nsWindow::IPCWindowProcHandler(UINT
& msg
, WPARAM
& wParam
, LPARAM
& lParam
)
4145 NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
4146 "Failed to prevent a nonqueued message from running!");
4148 // Modal UI being displayed in windowless plugins.
4149 if (mozilla::ipc::RPCChannel::IsSpinLoopActive() &&
4150 (InSendMessageEx(NULL
)&(ISMEX_REPLIED
|ISMEX_SEND
)) == ISMEX_SEND
) {
4152 if (IsAsyncResponseEvent(msg
, res
)) {
4158 // Handle certain sync plugin events sent to the parent which
4159 // trigger ipc calls that result in deadlocks.
4162 PRBool handled
= PR_FALSE
;
4165 // Windowless flash sending WM_ACTIVATE events to the main window
4166 // via calls to ShowWindow.
4168 if (lParam
!= 0 && LOWORD(wParam
) == WA_ACTIVE
&&
4169 IsWindow((HWND
)lParam
))
4172 // Wheel events forwarded from the child.
4174 case WM_MOUSEHWHEEL
:
4177 // Plugins taking or losing focus triggering focus app messages.
4180 // Windowed plugins that pass sys key events to defwndproc generate
4181 // WM_SYSCOMMAND events to the main window.
4183 // Windowed plugins that fire context menu selection events to parent
4185 case WM_CONTEXTMENU
:
4186 // IME events fired as a result of synchronous focus changes
4187 case WM_IME_SETCONTEXT
:
4193 (InSendMessageEx(NULL
)&(ISMEX_REPLIED
|ISMEX_SEND
)) == ISMEX_SEND
) {
4194 ReplyMessage(dwResult
);
4200 /**************************************************************
4201 **************************************************************
4203 ** BLOCK: Native events
4205 ** Main Windows message handlers and OnXXX handlers for
4206 ** Windows event handling.
4208 **************************************************************
4209 **************************************************************/
4211 /**************************************************************
4213 * SECTION: Wind proc.
4215 * The main Windows event procedures and associated
4216 * message processing methods.
4218 **************************************************************/
4221 static int ReportException(EXCEPTION_POINTERS
*aExceptionInfo
)
4223 #ifdef MOZ_CRASHREPORTER
4224 nsCOMPtr
<nsICrashReporter
> cr
=
4225 do_GetService("@mozilla.org/toolkit/crash-reporter;1");
4227 cr
->WriteMinidumpForException(aExceptionInfo
);
4229 return EXCEPTION_EXECUTE_HANDLER
;
4233 // The WndProc procedure for all nsWindows in this toolkit. This merely catches
4234 // exceptions and passes the real work to WindowProcInternal. See bug 587406
4235 // and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx
4236 LRESULT CALLBACK
nsWindow::WindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
4240 return WindowProcInternal(hWnd
, msg
, wParam
, lParam
);
4242 __except(ReportException(GetExceptionInformation())) {
4243 ::TerminateProcess(::GetCurrentProcess(), 253);
4246 return WindowProcInternal(hWnd
, msg
, wParam
, lParam
);
4250 LRESULT CALLBACK
nsWindow::WindowProcInternal(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
4252 NS_TIME_FUNCTION_MIN_FMT(5.0, "%s (line %d) (hWnd: %p, msg: %p, wParam: %p, lParam: %p",
4253 MOZ_FUNCTION_NAME
, __LINE__
, hWnd
, msg
,
4256 // Get the window which caused the event and ask it to process the message
4257 nsWindow
*someWindow
= GetNSWindowPtr(hWnd
);
4261 someWindow
->IPCWindowProcHandler(msg
, wParam
, lParam
);
4264 // create this here so that we store the last rolled up popup until after
4265 // the event has been processed.
4266 nsAutoRollup autoRollup
;
4268 LRESULT popupHandlingResult
;
4269 if (DealWithPopups(hWnd
, msg
, wParam
, lParam
, &popupHandlingResult
))
4270 return popupHandlingResult
;
4272 // XXX This fixes 50208 and we are leaving 51174 open to further investigate
4273 // why we are hitting this assert
4274 if (nsnull
== someWindow
) {
4275 NS_ASSERTION(someWindow
, "someWindow is null, cannot call any CallWindowProc");
4276 return ::DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
4279 // hold on to the window for the life of this method, in case it gets
4280 // deleted during processing. yes, it's a double hack, since someWindow
4281 // is not really an interface.
4282 nsCOMPtr
<nsISupports
> kungFuDeathGrip
;
4283 if (!someWindow
->mInDtor
) // not if we're in the destructor!
4284 kungFuDeathGrip
= do_QueryInterface((nsBaseWidget
*)someWindow
);
4286 // Call ProcessMessage
4288 if (PR_TRUE
== someWindow
->ProcessMessage(msg
, wParam
, lParam
, &retValue
)) {
4292 LRESULT res
= ::CallWindowProcW(someWindow
->GetPrevWindowProc(),
4293 hWnd
, msg
, wParam
, lParam
);
4298 // The main windows message processing method for plugins.
4299 // The result means whether this method processed the native
4300 // event for plugin. If false, the native event should be
4301 // processed by the caller self.
4303 nsWindow::ProcessMessageForPlugin(const MSG
&aMsg
,
4305 PRBool
&aCallDefWndProc
)
4307 NS_PRECONDITION(aResult
, "aResult must be non-null.");
4310 aCallDefWndProc
= PR_FALSE
;
4311 PRBool eventDispatched
= PR_FALSE
;
4312 switch (aMsg
.message
) {
4315 *aResult
= ProcessCharMessage(aMsg
, &eventDispatched
);
4320 *aResult
= ProcessKeyUpMessage(aMsg
, &eventDispatched
);
4325 *aResult
= ProcessKeyDownMessage(aMsg
, &eventDispatched
);
4329 case WM_SYSDEADCHAR
:
4330 case WM_CONTEXTMENU
:
4343 if (!eventDispatched
)
4344 aCallDefWndProc
= !DispatchPluginEvent(aMsg
);
4345 DispatchPendingEvents();
4349 // The main windows message processing method.
4350 PRBool
nsWindow::ProcessMessage(UINT msg
, WPARAM
&wParam
, LPARAM
&lParam
,
4353 // (Large blocks of code should be broken out into OnEvent handlers.)
4354 if (mWindowHook
.Notify(mWnd
, msg
, wParam
, lParam
, aRetValue
))
4357 #if defined(EVENT_DEBUG_OUTPUT)
4358 // First param shows all events, second param indicates whether
4359 // to show mouse move events. See nsWindowDbg for details.
4360 PrintEvent(msg
, SHOW_REPEAT_EVENTS
, SHOW_MOUSEMOVE_EVENTS
);
4364 if (nsIMM32Handler::ProcessMessage(this, msg
, wParam
, lParam
, aRetValue
,
4366 return mWnd
? eatMessage
: PR_TRUE
;
4369 if (PluginHasFocus()) {
4370 PRBool callDefaultWndProc
;
4371 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4372 if (ProcessMessageForPlugin(nativeMsg
, aRetValue
, callDefaultWndProc
)) {
4373 return mWnd
? !callDefaultWndProc
: PR_TRUE
;
4377 PRBool result
= PR_FALSE
; // call the default nsWindow proc
4380 static PRBool getWheelInfo
= PR_TRUE
;
4382 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4383 // Glass hit testing w/custom transparent margins
4384 LRESULT dwmHitResult
;
4385 if (mCustomNonClient
&&
4386 nsUXThemeData::CheckForCompositor() &&
4387 nsUXThemeData::dwmDwmDefWindowProcPtr(mWnd
, msg
, wParam
, lParam
, &dwmHitResult
)) {
4388 *aRetValue
= dwmHitResult
;
4391 #endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4395 // WM_QUERYENDSESSION must be handled by all windows.
4396 // Otherwise Windows thinks the window can just be killed at will.
4397 case WM_QUERYENDSESSION
:
4398 if (sCanQuit
== TRI_UNKNOWN
)
4400 // Ask if it's ok to quit, and store the answer until we
4401 // get WM_ENDSESSION signaling the round is complete.
4402 nsCOMPtr
<nsIObserverService
> obsServ
=
4403 mozilla::services::GetObserverService();
4404 nsCOMPtr
<nsISupportsPRBool
> cancelQuit
=
4405 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID
);
4406 cancelQuit
->SetData(PR_FALSE
);
4407 obsServ
->NotifyObservers(cancelQuit
, "quit-application-requested", nsnull
);
4410 cancelQuit
->GetData(&abortQuit
);
4411 sCanQuit
= abortQuit
? TRI_FALSE
: TRI_TRUE
;
4413 *aRetValue
= sCanQuit
? TRUE
: FALSE
;
4421 case MOZ_WM_APP_QUIT
:
4422 if (msg
== MOZ_WM_APP_QUIT
|| (wParam
== TRUE
&& sCanQuit
== TRI_TRUE
))
4424 // Let's fake a shutdown sequence without actually closing windows etc.
4425 // to avoid Windows killing us in the middle. A proper shutdown would
4426 // require having a chance to pump some messages. Unfortunately
4427 // Windows won't let us do that. Bug 212316.
4428 nsCOMPtr
<nsIObserverService
> obsServ
=
4429 mozilla::services::GetObserverService();
4430 NS_NAMED_LITERAL_STRING(context
, "shutdown-persist");
4431 obsServ
->NotifyObservers(nsnull
, "quit-application-granted", nsnull
);
4432 obsServ
->NotifyObservers(nsnull
, "quit-application-forced", nsnull
);
4433 obsServ
->NotifyObservers(nsnull
, "quit-application", nsnull
);
4434 obsServ
->NotifyObservers(nsnull
, "profile-change-net-teardown", context
.get());
4435 obsServ
->NotifyObservers(nsnull
, "profile-change-teardown", context
.get());
4436 obsServ
->NotifyObservers(nsnull
, "profile-before-change", context
.get());
4437 // Then a controlled but very quick exit.
4440 sCanQuit
= TRI_UNKNOWN
;
4445 case WM_DISPLAYCHANGE
:
4446 DispatchStandardEvent(NS_DISPLAYCHANGED
);
4450 case WM_SYSCOLORCHANGE
:
4451 // Note: This is sent for child windows as well as top-level windows.
4452 // The Win32 toolkit normally only sends these events to top-level windows.
4453 // But we cycle through all of the childwindows and send it to them as well
4454 // so all presentations get notified properly.
4455 // See nsWindow::GlobalMsgWindowProc.
4456 DispatchStandardEvent(NS_SYSCOLORCHANGED
);
4462 LPNMHDR pnmh
= (LPNMHDR
) lParam
;
4464 switch (pnmh
->code
) {
4467 DispatchStandardEvent(NS_TABCHANGE
);
4475 case WM_XP_THEMECHANGED
:
4477 // Update non-client margin offsets
4478 UpdateNonClientMargins();
4480 DispatchStandardEvent(NS_THEMECHANGED
);
4482 // Invalidate the window so that the repaint will
4483 // pick up the new theme.
4484 Invalidate(PR_FALSE
);
4491 PRBool didChange
= PR_FALSE
;
4493 // update the global font list
4494 nsCOMPtr
<nsIFontEnumerator
> fontEnum
= do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv
);
4495 if (NS_SUCCEEDED(rv
)) {
4496 fontEnum
->UpdateFontList(&didChange
);
4497 //didChange is TRUE only if new font langGroup is added to the list.
4499 // update device context font cache
4500 // Dirty but easiest way:
4501 // Changing nsIPrefBranch entry which triggers callbacks
4502 // and flows into calling mDeviceContext->FlushFontCache()
4503 // to update the font cache in all the instance of Browsers
4504 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
4506 nsCOMPtr
<nsIPrefBranch
> fiPrefs
;
4507 prefs
->GetBranch("font.internaluseonly.", getter_AddRefs(fiPrefs
));
4509 PRBool fontInternalChange
= PR_FALSE
;
4510 fiPrefs
->GetBoolPref("changed", &fontInternalChange
);
4511 fiPrefs
->SetBoolPref("changed", !fontInternalChange
);
4515 } //if (NS_SUCCEEDED(rv))
4521 // If wParam is TRUE, it specifies that the application should indicate
4522 // which part of the client area contains valid information. The system
4523 // copies the valid information to the specified area within the new
4524 // client area. If the wParam parameter is FALSE, the application should
4526 if (mCustomNonClient
) {
4534 // rgrc[0]: the proposed window
4535 // rgrc[1]: the current window
4536 // rgrc[2]: the source client area
4537 // pncsp->lppos: move/size data
4539 // rgrc[0]: the new client area
4540 // rgrc[1]: the destination window
4541 // rgrc[2]: the source client area
4542 // (all values in screen coordiantes)
4543 NCCALCSIZE_PARAMS
*pncsp
= reinterpret_cast<NCCALCSIZE_PARAMS
*>(lParam
);
4544 LRESULT res
= CallWindowProcW(GetPrevWindowProc(), mWnd
, msg
, wParam
, lParam
);
4545 pncsp
->rgrc
[0].top
-= mNonClientOffset
.top
;
4546 pncsp
->rgrc
[0].left
-= mNonClientOffset
.left
;
4547 pncsp
->rgrc
[0].right
+= mNonClientOffset
.right
;
4548 pncsp
->rgrc
[0].bottom
+= mNonClientOffset
.bottom
;
4559 * If an nc client area margin has been moved, we are responsible
4560 * for calculating where the resize margins are and returning the
4561 * appropriate set of hit test constants. DwmDefWindowProc (above)
4562 * will handle hit testing on it's command buttons if we are on a
4563 * composited desktop.
4566 if (!mCustomNonClient
)
4570 ClientMarginHitTestPoint(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
4577 * WM_SETTEXT paints the titlebar area. Avoid this if we have a
4578 * custom titlebar we paint ourselves.
4581 if (!mCustomNonClient
|| mNonClientMargins
.top
== -1)
4585 // From msdn, the way around this is to disable the visible state
4586 // temporarily. We need the text to be set but we don't want the
4588 DWORD style
= GetWindowLong(mWnd
, GWL_STYLE
);
4589 SetWindowLong(mWnd
, GWL_STYLE
, style
& ~WS_VISIBLE
);
4590 *aRetValue
= CallWindowProcW(GetPrevWindowProc(), mWnd
,
4591 msg
, wParam
, lParam
);
4592 SetWindowLong(mWnd
, GWL_STYLE
, style
);
4599 * WM_NCACTIVATE paints nc areas. Avoid this and re-route painting
4600 * through WM_NCPAINT via InvalidateNonClientRegion.
4603 if (!mCustomNonClient
)
4606 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4607 // let the dwm handle nc painting on glass
4608 if(nsUXThemeData::CheckForCompositor())
4612 if (wParam
== TRUE
) {
4614 *aRetValue
= FALSE
; // ignored
4616 // invalidate to trigger a paint
4617 InvalidateNonClientRegion();
4621 *aRetValue
= TRUE
; // go ahead and deactive
4623 // invalidate to trigger a paint
4624 InvalidateNonClientRegion();
4632 * Reset the non-client paint region so that it excludes the
4633 * non-client areas we paint manually. Then call defwndproc
4634 * to do the actual painting.
4637 if (!mCustomNonClient
)
4640 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4641 // let the dwm handle nc painting on glass
4642 if(nsUXThemeData::CheckForCompositor())
4646 HRGN paintRgn
= ExcludeNonClientFromPaintRegion((HRGN
)wParam
);
4647 LRESULT res
= CallWindowProcW(GetPrevWindowProc(), mWnd
,
4648 msg
, (WPARAM
)paintRgn
, lParam
);
4649 if (paintRgn
!= (HRGN
)wParam
)
4650 DeleteObject(paintRgn
);
4657 case WM_POWERBROADCAST
:
4658 // only hidden window handle this
4659 // to prevent duplicate notification
4660 if (mWindowType
== eWindowType_invisible
) {
4663 case PBT_APMSUSPEND
:
4664 PostSleepWakeNotification("sleep_notification");
4666 case PBT_APMRESUMEAUTOMATIC
:
4667 case PBT_APMRESUMECRITICAL
:
4668 case PBT_APMRESUMESUSPEND
:
4669 PostSleepWakeNotification("wake_notification");
4676 case WM_MOVE
: // Window moved
4679 ::GetWindowRect(mWnd
, &rect
);
4680 result
= OnMove(rect
.left
, rect
.top
);
4684 case WM_CLOSE
: // close request
4685 DispatchStandardEvent(NS_XUL_CLOSE
);
4686 result
= PR_TRUE
; // abort window closure
4696 *aRetValue
= (int) OnPaint(NULL
, 0);
4701 case WM_PRINTCLIENT
:
4702 result
= OnPaint((HDC
) wParam
, 0);
4707 result
= OnHotKey(wParam
, lParam
);
4713 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4714 result
= ProcessCharMessage(nativeMsg
, nsnull
);
4715 DispatchPendingEvents();
4722 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4723 result
= ProcessKeyUpMessage(nativeMsg
, nsnull
);
4724 DispatchPendingEvents();
4731 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4732 result
= ProcessKeyDownMessage(nativeMsg
, nsnull
);
4733 DispatchPendingEvents();
4737 // say we've dealt with erase background if widget does
4738 // not need auto-erasing
4740 if (!AutoErase((HDC
)wParam
)) {
4748 #ifdef WINCE_WINDOWS_MOBILE
4749 // Reset the kill timer so that we can continue at this
4751 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2seconds */, NULL
);
4753 // Suppress dispatch of pending events
4754 // when mouse moves are generated by widget
4755 // creation instead of user input.
4756 LPARAM lParamScreen
= lParamToScreen(lParam
);
4758 mp
.x
= GET_X_LPARAM(lParamScreen
);
4759 mp
.y
= GET_Y_LPARAM(lParamScreen
);
4760 PRBool userMovedMouse
= PR_FALSE
;
4761 if ((sLastMouseMovePoint
.x
!= mp
.x
) || (sLastMouseMovePoint
.y
!= mp
.y
)) {
4762 userMovedMouse
= PR_TRUE
;
4764 mExitToNonClientArea
= PR_FALSE
;
4766 result
= DispatchMouseEvent(NS_MOUSE_MOVE
, wParam
, lParam
,
4767 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4768 if (userMovedMouse
) {
4769 DispatchPendingEvents();
4774 #ifdef WINCE_WINDOWS_MOBILE
4776 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
4777 KillTimer(mWnd
, KILL_PRIORITY_ID
);
4781 case WM_LBUTTONDOWN
:
4783 #ifdef WINCE_WINDOWS_MOBILE
4784 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
4785 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2 seconds */, NULL
);
4787 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
,
4788 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4789 DispatchPendingEvents();
4795 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
,
4796 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4797 DispatchPendingEvents();
4799 #ifdef WINCE_WINDOWS_MOBILE
4800 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
4801 KillTimer(mWnd
, KILL_PRIORITY_ID
);
4809 // We need to check mouse button states and put them in for
4811 WPARAM mouseState
= (GetKeyState(VK_LBUTTON
) ? MK_LBUTTON
: 0)
4812 | (GetKeyState(VK_MBUTTON
) ? MK_MBUTTON
: 0)
4813 | (GetKeyState(VK_RBUTTON
) ? MK_RBUTTON
: 0);
4814 // Synthesize an event position because we don't get one from
4816 LPARAM pos
= lParamToClient(::GetMessagePos());
4817 DispatchMouseEvent(NS_MOUSE_EXIT
, mouseState
, pos
, PR_FALSE
,
4818 nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4823 case WM_CONTEXTMENU
:
4825 // if the context menu is brought up from the keyboard, |lParam|
4828 PRBool contextMenukey
= PR_FALSE
;
4831 contextMenukey
= PR_TRUE
;
4832 pos
= lParamToClient(GetMessagePos());
4836 pos
= lParamToClient(lParam
);
4839 result
= DispatchMouseEvent(NS_CONTEXTMENU
, wParam
, pos
, contextMenukey
,
4841 nsMouseEvent::eLeftButton
:
4842 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4846 case WM_LBUTTONDBLCLK
:
4847 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
4848 nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4851 case WM_MBUTTONDOWN
:
4853 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4854 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
4855 DispatchPendingEvents();
4860 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
4861 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
4862 DispatchPendingEvents();
4865 case WM_MBUTTONDBLCLK
:
4866 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4867 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
4870 case WM_RBUTTONDOWN
:
4872 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4873 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4874 DispatchPendingEvents();
4879 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
4880 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4881 DispatchPendingEvents();
4884 case WM_RBUTTONDBLCLK
:
4885 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
4886 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4889 case WM_NCRBUTTONDOWN
:
4890 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, 0, lParamToClient(lParam
),
4891 PR_FALSE
, nsMouseEvent::eRightButton
,
4892 MOUSE_INPUT_SOURCE());
4893 DispatchPendingEvents();
4896 case WM_NCRBUTTONUP
:
4897 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, 0, lParamToClient(lParam
),
4898 PR_FALSE
, nsMouseEvent::eRightButton
,
4899 MOUSE_INPUT_SOURCE());
4900 DispatchPendingEvents();
4903 case WM_NCRBUTTONDBLCLK
:
4904 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, 0, lParamToClient(lParam
),
4905 PR_FALSE
, nsMouseEvent::eRightButton
,
4906 MOUSE_INPUT_SOURCE());
4910 PRUint32 appCommand
= GET_APPCOMMAND_LPARAM(lParam
);
4914 case APPCOMMAND_BROWSER_BACKWARD
:
4915 case APPCOMMAND_BROWSER_FORWARD
:
4916 case APPCOMMAND_BROWSER_REFRESH
:
4917 case APPCOMMAND_BROWSER_STOP
:
4918 case APPCOMMAND_BROWSER_SEARCH
:
4919 case APPCOMMAND_BROWSER_FAVORITES
:
4920 case APPCOMMAND_BROWSER_HOME
:
4921 DispatchCommandEvent(appCommand
);
4922 // tell the driver that we handled the event
4927 // default = PR_FALSE - tell the driver that the event was not handled
4934 result
= OnScroll(msg
, wParam
, lParam
);
4937 // The WM_ACTIVATE event is fired when a window is raised or lowered,
4938 // and the loword of wParam specifies which. But we don't want to tell
4939 // the focus system about this until the WM_SETFOCUS or WM_KILLFOCUS
4940 // events are fired. Instead, set either the sJustGotActivate or
4941 // gJustGotDeativate flags and fire the NS_ACTIVATE or NS_DEACTIVATE
4942 // events once the focus events arrive.
4944 if (mEventCallback
) {
4945 PRInt32 fActive
= LOWORD(wParam
);
4947 #if defined(WINCE_HAVE_SOFTKB)
4948 if (mIsTopWidgetWindow
&& sSoftKeyboardState
)
4949 nsWindowCE::ToggleSoftKB(mWnd
, fActive
);
4950 if (nsWindowCE::sShowSIPButton
== TRI_FALSE
&& WA_INACTIVE
!= fActive
) {
4951 HWND hWndSIPB
= FindWindowW(L
"MS_SIPBUTTON", NULL
);
4953 ShowWindow(hWndSIPB
, SW_HIDE
);
4958 if (WA_INACTIVE
== fActive
) {
4959 // when minimizing a window, the deactivation and focus events will
4960 // be fired in the reverse order. Instead, just dispatch
4961 // NS_DEACTIVATE right away.
4963 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
4965 sJustGotDeactivate
= PR_TRUE
;
4967 if (mIsTopWidgetWindow
)
4968 mLastKeyboardLayout
= gKbdLayout
.GetLayout();
4974 sJustGotActivate
= PR_TRUE
;
4975 nsMouseEvent
event(PR_TRUE
, NS_MOUSE_ACTIVATE
, this,
4976 nsMouseEvent::eReal
);
4979 event
.acceptActivation
= PR_TRUE
;
4981 DispatchWindowEvent(&event
);
4983 if (event
.acceptActivation
)
4984 *aRetValue
= MA_ACTIVATE
;
4986 *aRetValue
= MA_NOACTIVATE
;
4988 if (sSwitchKeyboardLayout
&& mLastKeyboardLayout
)
4989 ActivateKeyboardLayout(mLastKeyboardLayout
, 0);
4995 #ifdef WINCE_WINDOWS_MOBILE
4996 if (!gCheckForHTCApi
&& gHTCApiNavOpen
== nsnull
) {
4997 gCheckForHTCApi
= PR_TRUE
;
4999 HINSTANCE library
= LoadLibrary(L
"HTCAPI.dll");
5000 gHTCApiNavOpen
= (HTCApiNavOpen
) GetProcAddress(library
, "HTCNavOpen");
5001 gHTCApiNavSetMode
= (HTCApiNavSetMode
) GetProcAddress(library
,"HTCNavSetMode");
5004 if (gHTCApiNavOpen
!= nsnull
) {
5005 gHTCApiNavOpen(mWnd
, 1 /* undocumented value */);
5007 if (gHTCApiNavSetMode
!= nsnull
)
5008 gHTCApiNavSetMode ( mWnd
, 4);
5009 // 4 is Gesture Mode. This will generate WM_HTCNAV events to the window
5015 case WM_MOUSEACTIVATE
:
5016 if (mWindowType
== eWindowType_popup
) {
5017 // a popup with a parent owner should not be activated when clicked
5018 // but should still allow the mouse event to be fired, so the return
5019 // value is set to MA_NOACTIVATE. But if the owner isn't the frontmost
5020 // window, just use default processing so that the window is activated.
5021 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
5022 if (owner
&& owner
== ::GetForegroundWindow()) {
5023 *aRetValue
= MA_NOACTIVATE
;
5029 case WM_WINDOWPOSCHANGING
:
5031 LPWINDOWPOS info
= (LPWINDOWPOS
) lParam
;
5032 OnWindowPosChanging(info
);
5038 if (sJustGotActivate
) {
5039 result
= DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
5042 #ifdef ACCESSIBILITY
5043 if (nsWindow::sIsAccessibilityOn
) {
5044 // Create it for the first time so that it can start firing events
5045 nsAccessible
*rootAccessible
= GetRootAccessible();
5049 #if defined(WINCE_HAVE_SOFTKB)
5051 // On Windows CE, we have a window that overlaps
5052 // the ISP button. In this case, we should always
5053 // try to hide it when we are activated
5055 nsIMEContext
IMEContext(mWnd
);
5057 ImmSetOpenStatus(IMEContext
.get(), TRUE
);
5063 #if defined(WINCE_HAVE_SOFTKB)
5065 nsIMEContext
IMEContext(mWnd
);
5066 ImmSetOpenStatus(IMEContext
.get(), FALSE
);
5069 if (sJustGotDeactivate
) {
5070 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
5074 case WM_WINDOWPOSCHANGED
:
5076 WINDOWPOS
*wp
= (LPWINDOWPOS
)lParam
;
5077 OnWindowPosChanged(wp
, result
);
5081 case WM_SETTINGCHANGE
:
5082 #if !defined (WINCE_WINDOWS_MOBILE)
5083 getWheelInfo
= PR_TRUE
;
5086 case SPI_SETSIPINFO
:
5087 case SPI_SETCURRENTIM
:
5088 nsWindowCE::OnSoftKbSettingsChange(mWnd
);
5090 case SETTINGCHANGE_RESET
:
5091 if (mWindowType
== eWindowType_invisible
) {
5092 // The OS sees to get confused and think that the invisable window
5093 // is in the foreground after an orientation change. By actually
5094 // setting it to the foreground and hiding it, we set it strait.
5095 // See bug 514007 for details.
5096 SetForegroundWindow(mWnd
);
5097 ShowWindow(mWnd
, SW_HIDE
);
5102 OnSettingsChange(wParam
, lParam
);
5106 case WM_INPUTLANGCHANGEREQUEST
:
5111 case WM_INPUTLANGCHANGE
:
5112 result
= OnInputLangChange((HKL
)lParam
);
5116 case WM_DESTROYCLIPBOARD
:
5118 nsIClipboard
* clipboard
;
5119 nsresult rv
= CallGetService(kCClipboardCID
, &clipboard
);
5120 if(NS_SUCCEEDED(rv
)) {
5121 clipboard
->EmptyClipboard(nsIClipboard::kGlobalClipboard
);
5122 NS_RELEASE(clipboard
);
5127 #ifdef ACCESSIBILITY
5131 if (lParam
== OBJID_CLIENT
) { // oleacc.dll will be loaded dynamically
5132 nsAccessible
*rootAccessible
= GetRootAccessible(); // Held by a11y cache
5133 if (rootAccessible
) {
5134 IAccessible
*msaaAccessible
= NULL
;
5135 rootAccessible
->GetNativeInterface((void**)&msaaAccessible
); // does an addref
5136 if (msaaAccessible
) {
5137 *aRetValue
= LresultFromObject(IID_IAccessible
, wParam
, msaaAccessible
); // does an addref
5138 msaaAccessible
->Release(); // release extra addref
5139 result
= PR_TRUE
; // We handled the WM_GETOBJECT message
5148 // prevent Windows from trimming the working set. bug 76831
5149 if (!sTrimOnMinimize
&& wParam
== SC_MINIMIZE
) {
5150 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
5159 nsMemory::HeapMinimize(PR_TRUE
);
5164 case WM_MOUSEHWHEEL
:
5166 // If OnMouseWheel returns true, the event was forwarded directly to another
5167 // mozilla window message handler (ProcessMessage). In this case the return
5168 // value of the forwarded event is in 'result' which we should return immediately.
5169 // If OnMouseWheel returns false, OnMouseWheel processed the event internally.
5170 // 'result' and 'aRetValue' will be set based on what we did with the event, so
5171 // we should fall through.
5172 if (OnMouseWheel(msg
, wParam
, lParam
, getWheelInfo
, result
, aRetValue
))
5178 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
5179 case WM_DWMCOMPOSITIONCHANGED
:
5180 UpdateNonClientMargins();
5181 BroadcastMsg(mWnd
, WM_DWMCOMPOSITIONCHANGED
);
5182 DispatchStandardEvent(NS_THEMECHANGED
);
5184 Invalidate(PR_FALSE
);
5188 case WM_UPDATEUISTATE
:
5190 // If the UI state has changed, fire an event so the UI updates the
5191 // keyboard cues based on the system setting and how the window was
5192 // opened. For example, a dialog opened via a keyboard press on a button
5193 // should enable cues, whereas the same dialog opened via a mouse click of
5194 // the button should not.
5195 PRInt32 action
= LOWORD(wParam
);
5196 if (action
== UIS_SET
|| action
== UIS_CLEAR
) {
5197 nsUIStateChangeEvent
event(PR_TRUE
, NS_UISTATECHANGED
, this);
5198 PRInt32 flags
= HIWORD(wParam
);
5199 if (flags
& UISF_HIDEACCEL
)
5200 event
.showAccelerators
= (action
== UIS_SET
) ? UIStateChangeType_Clear
: UIStateChangeType_Set
;
5201 if (flags
& UISF_HIDEFOCUS
)
5202 event
.showFocusRings
= (action
== UIS_SET
) ? UIStateChangeType_Clear
: UIStateChangeType_Set
;
5203 DispatchWindowEvent(&event
);
5209 /* Gesture support events */
5210 case WM_TABLET_QUERYSYSTEMGESTURESTATUS
:
5211 // According to MS samples, this must be handled to enable
5212 // rotational support in multi-touch drivers.
5214 *aRetValue
= TABLET_ROTATE_GESTURE_ENABLE
;
5217 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
5219 result
= OnTouch(wParam
, lParam
);
5227 result
= OnGesture(wParam
, lParam
);
5230 case WM_GESTURENOTIFY
:
5232 if (mWindowType
!= eWindowType_invisible
&&
5233 mWindowType
!= eWindowType_plugin
&&
5234 mWindowType
!= eWindowType_toplevel
) {
5235 // eWindowType_toplevel is the top level main frame window. Gesture support
5236 // there prevents the user from interacting with the title bar or nc
5237 // areas using a single finger. Java and plugin windows can make their
5239 GESTURENOTIFYSTRUCT
* gestureinfo
= (GESTURENOTIFYSTRUCT
*)lParam
;
5240 nsPointWin touchPoint
;
5241 touchPoint
= gestureinfo
->ptsLocation
;
5242 touchPoint
.ScreenToClient(mWnd
);
5243 nsGestureNotifyEvent
gestureNotifyEvent(PR_TRUE
, NS_GESTURENOTIFY_EVENT_START
, this);
5244 gestureNotifyEvent
.refPoint
= touchPoint
;
5245 nsEventStatus status
;
5246 DispatchEvent(&gestureNotifyEvent
, status
);
5247 mDisplayPanFeedback
= gestureNotifyEvent
.displayPanFeedback
;
5249 mGesture
.SetWinGestureSupport(mWnd
, gestureNotifyEvent
.panDirection
);
5251 result
= PR_FALSE
; //should always bubble to DefWindowProc
5254 #endif // !defined(WINCE)
5258 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_DELETE
, this);
5259 DispatchWindowEvent(&command
);
5266 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_CUT
, this);
5267 DispatchWindowEvent(&command
);
5274 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_COPY
, this);
5275 DispatchWindowEvent(&command
);
5282 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
, this);
5283 DispatchWindowEvent(&command
);
5291 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
, this);
5292 DispatchWindowEvent(&command
);
5293 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5300 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
, this);
5301 DispatchWindowEvent(&command
);
5302 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5309 // Support EM_CANPASTE message only when wParam isn't specified or
5310 // is plain text format.
5311 if (wParam
== 0 || wParam
== CF_TEXT
|| wParam
== CF_UNICODETEXT
) {
5312 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
,
5314 DispatchWindowEvent(&command
);
5315 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5323 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
,
5325 DispatchWindowEvent(&command
);
5326 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5333 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
,
5335 DispatchWindowEvent(&command
);
5336 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5342 #ifdef WINCE_WINDOWS_MOBILE
5343 //HTC NAVIGATION WHEEL EVENT
5346 int distance
= wParam
& 0x000000FF;
5347 if ( (wParam
& 0x000000100) != 0) // Counter Clockwise
5349 if (OnMouseWheel(WM_MOUSEWHEEL
, MAKEWPARAM(0, distance
),
5350 MAKELPARAM(GetSystemMetrics(SM_CXSCREEN
) / 2,
5351 GetSystemMetrics(SM_CYSCREEN
) / 2),
5352 getWheelInfo
, result
, aRetValue
))
5360 #ifdef NS_ENABLE_TSF
5361 if (msg
== WM_USER_TSF_TEXTCHANGE
) {
5362 nsTextStore::OnTextChangeMsg();
5364 #endif //NS_ENABLE_TSF
5365 #if defined(HEAP_DUMP_EVENT)
5366 if (msg
== GetHeapMsg()) {
5367 HeapDump(msg
, wParam
, lParam
);
5371 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
5372 if (msg
== nsAppShell::GetTaskbarButtonCreatedMessage())
5373 SetHasTaskbarIconBeenCreated();
5376 if (msg
== sOOPPPluginFocusEvent
) {
5378 // With OOPP, the plugin window exists in another process and is a child of
5379 // this window. This window is a placeholder plugin window for the dom. We
5380 // receive this event when the child window receives focus. (sent from
5381 // PluginInstanceParent.cpp)
5382 ::SendMessage(mWnd
, WM_MOUSEACTIVATE
, 0, 0); // See nsPluginNativeWindowWin.cpp
5384 // WM_KILLFOCUS was received by the child process.
5385 if (sJustGotDeactivate
) {
5386 DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
5395 //*aRetValue = result;
5400 //Events which caused mWnd destruction and aren't consumed
5401 //will crash during the Windows default processing.
5406 /**************************************************************
5408 * SECTION: Broadcast messaging
5410 * Broadcast messages to all windows.
5412 **************************************************************/
5414 // Enumerate all child windows sending aMsg to each of them
5415 BOOL CALLBACK
nsWindow::BroadcastMsgToChildren(HWND aWnd
, LPARAM aMsg
)
5417 WNDPROC winProc
= (WNDPROC
)::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
5418 if (winProc
== &nsWindow::WindowProc
) {
5419 // it's one of our windows so go ahead and send a message to it
5420 ::CallWindowProcW(winProc
, aWnd
, aMsg
, 0, 0);
5425 // Enumerate all top level windows specifying that the children of each
5426 // top level window should be enumerated. Do *not* send the message to
5427 // each top level window since it is assumed that the toolkit will send
5428 // aMsg to them directly.
5429 BOOL CALLBACK
nsWindow::BroadcastMsg(HWND aTopWindow
, LPARAM aMsg
)
5431 // Iterate each of aTopWindows child windows sending the aMsg
5434 ::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
5436 nsWindowCE::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
5441 // This method is called from nsToolkit::WindowProc to forward global
5442 // messages which need to be dispatched to all child windows.
5443 void nsWindow::GlobalMsgWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
5446 case WM_SYSCOLORCHANGE
:
5447 // Code to dispatch WM_SYSCOLORCHANGE message to all child windows.
5448 // WM_SYSCOLORCHANGE is only sent to top-level windows, but the
5449 // cross platform API requires that NS_SYSCOLORCHANGE message be sent to
5450 // all child windows as well. When running in an embedded application
5451 // we may not receive a WM_SYSCOLORCHANGE message because the top
5452 // level window is owned by the embeddor.
5453 // System color changes are posted to top-level windows only.
5454 // The NS_SYSCOLORCHANGE must be dispatched to all child
5457 ::EnumThreadWindows(GetCurrentThreadId(), nsWindow::BroadcastMsg
, msg
);
5463 /**************************************************************
5465 * SECTION: Event processing helpers
5467 * Special processing for certain event types and
5468 * synthesized events.
5470 **************************************************************/
5473 nsWindow::ClientMarginHitTestPoint(PRInt32 mx
, PRInt32 my
)
5475 // Calculations are done in screen coords
5477 GetWindowRect(mWnd
, &winRect
);
5479 // hit return constants:
5480 // HTBORDER - non-resizable border
5481 // HTBOTTOM, HTLEFT, HTRIGHT, HTTOP - resizable border
5482 // HTBOTTOMLEFT, HTBOTTOMRIGHT - resizable corner
5483 // HTTOPLEFT, HTTOPRIGHT - resizable corner
5484 // HTCAPTION - general title bar area
5485 // HTCLIENT - area considered the client
5486 // HTCLOSE - hovering over the close button
5487 // HTMAXBUTTON - maximize button
5488 // HTMINBUTTON - minimize button
5490 PRInt32 testResult
= HTCLIENT
;
5492 PRBool top
= PR_FALSE
;
5493 PRBool bottom
= PR_FALSE
;
5494 PRBool left
= PR_FALSE
;
5495 PRBool right
= PR_FALSE
;
5497 if (my
>= winRect
.top
&& my
<=
5498 (winRect
.top
+ mVertResizeMargin
+ (mCaptionHeight
- mNonClientOffset
.top
)))
5500 else if (my
<= winRect
.bottom
&& my
>= (winRect
.bottom
- mVertResizeMargin
))
5503 if (mx
>= winRect
.left
&& mx
<= (winRect
.left
+ mHorResizeMargin
))
5505 else if (mx
<= winRect
.right
&& mx
>= (winRect
.right
- mHorResizeMargin
))
5511 testResult
= HTTOPLEFT
;
5513 testResult
= HTTOPRIGHT
;
5514 } else if (bottom
) {
5515 testResult
= HTBOTTOM
;
5517 testResult
= HTBOTTOMLEFT
;
5519 testResult
= HTBOTTOMRIGHT
;
5522 testResult
= HTLEFT
;
5524 testResult
= HTRIGHT
;
5527 PRBool contentOverlap
= PR_TRUE
;
5529 if (mSizeMode
== nsSizeMode_Maximized
) {
5530 // There's no HTTOP in maximized state (bug 575493)
5531 if (testResult
== HTTOP
) {
5532 testResult
= HTCAPTION
;
5535 PRInt32 leftMargin
= mNonClientMargins
.left
== -1 ? mHorResizeMargin
: mNonClientMargins
.left
;
5536 PRInt32 rightMargin
= mNonClientMargins
.right
== -1 ? mHorResizeMargin
: mNonClientMargins
.right
;
5537 PRInt32 topMargin
= mNonClientMargins
.top
== -1 ? mVertResizeMargin
: mNonClientMargins
.top
;
5538 PRInt32 bottomMargin
= mNonClientMargins
.bottom
== -1 ? mVertResizeMargin
: mNonClientMargins
.bottom
;
5540 contentOverlap
= mx
>= winRect
.left
+ leftMargin
&&
5541 mx
<= winRect
.right
- rightMargin
&&
5542 my
>= winRect
.top
+ topMargin
&&
5543 my
<= winRect
.bottom
- bottomMargin
;
5546 if (!mIsInMouseCapture
&&
5548 (testResult
== HTCLIENT
||
5549 testResult
== HTTOP
||
5550 testResult
== HTTOPLEFT
||
5551 testResult
== HTCAPTION
)) {
5552 LPARAM lParam
= MAKELPARAM(mx
, my
);
5553 LPARAM lParamClient
= lParamToClient(lParam
);
5554 PRBool result
= DispatchMouseEvent(NS_MOUSE_MOZHITTEST
, 0, lParamClient
,
5555 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5557 // The mouse is over a blank area
5558 testResult
= testResult
== HTCLIENT
? HTCAPTION
: testResult
;
5560 if (!mExitToNonClientArea
) {
5561 // The first time the mouse pointer goes from client area to non-client area,
5562 // we don't want to miss that movement so we can interpret mouseout input.
5563 ::SendMessage(mWnd
, WM_MOUSEMOVE
, 0, lParamClient
);
5564 mExitToNonClientArea
= PR_TRUE
;
5567 // There's content over the mouse pointer. Set HTCLIENT
5568 // to possibly override a resizer border.
5569 testResult
= HTCLIENT
;
5578 void nsWindow::PostSleepWakeNotification(const char* aNotification
)
5580 nsCOMPtr
<nsIObserverService
> observerService
=
5581 mozilla::services::GetObserverService();
5582 if (observerService
)
5583 observerService
->NotifyObservers(nsnull
, aNotification
, nsnull
);
5587 LRESULT
nsWindow::ProcessCharMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
5589 NS_PRECONDITION(aMsg
.message
== WM_CHAR
|| aMsg
.message
== WM_SYSCHAR
,
5590 "message is not keydown event");
5591 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5592 ("%s charCode=%d scanCode=%d\n",
5593 aMsg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
5594 aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF));
5596 // These must be checked here too as a lone WM_CHAR could be received
5597 // if a child window didn't handle it (for example Alt+Space in a content window)
5598 nsModifierKeyState modKeyState
;
5599 return OnChar(aMsg
, modKeyState
, aEventDispatched
);
5602 LRESULT
nsWindow::ProcessKeyUpMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
5604 NS_PRECONDITION(aMsg
.message
== WM_KEYUP
|| aMsg
.message
== WM_SYSKEYUP
,
5605 "message is not keydown event");
5606 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5607 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
5608 "WM_SYSKEYUP" : "WM_KEYUP", aMsg
.wParam
));
5610 nsModifierKeyState modKeyState
;
5612 // Note: the original code passed (HIWORD(lParam)) to OnKeyUp as
5613 // scan code. However, this breaks Alt+Num pad input.
5614 // MSDN states the following:
5615 // Typically, ToAscii performs the translation based on the
5616 // virtual-key code. In some cases, however, bit 15 of the
5617 // uScanCode parameter may be used to distinguish between a key
5618 // press and a key release. The scan code is used for
5619 // translating ALT+number key combinations.
5621 // ignore [shift+]alt+space so the OS can handle it
5622 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
5623 IS_VK_DOWN(NS_VK_SPACE
)) {
5627 if (!nsIMM32Handler::IsComposingOn(this) &&
5628 (aMsg
.message
!= WM_KEYUP
|| aMsg
.wParam
!= VK_MENU
)) {
5629 // Ignore VK_MENU if it's not a system key release, so that the menu bar does not trigger
5630 // This helps avoid triggering the menu bar for ALT key accelerators used in
5631 // assistive technologies such as Window-Eyes and ZoomText, and when using Alt+Tab
5632 // to switch back to Mozilla in Windows 95 and Windows 98
5633 return OnKeyUp(aMsg
, modKeyState
, aEventDispatched
);
5639 LRESULT
nsWindow::ProcessKeyDownMessage(const MSG
&aMsg
,
5640 PRBool
*aEventDispatched
)
5642 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5643 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
5644 "WM_SYSKEYDOWN" : "WM_KEYDOWN", aMsg
.wParam
));
5645 NS_PRECONDITION(aMsg
.message
== WM_KEYDOWN
|| aMsg
.message
== WM_SYSKEYDOWN
,
5646 "message is not keydown event");
5648 nsModifierKeyState modKeyState
;
5650 // Note: the original code passed (HIWORD(lParam)) to OnKeyDown as
5651 // scan code. However, this breaks Alt+Num pad input.
5652 // MSDN states the following:
5653 // Typically, ToAscii performs the translation based on the
5654 // virtual-key code. In some cases, however, bit 15 of the
5655 // uScanCode parameter may be used to distinguish between a key
5656 // press and a key release. The scan code is used for
5657 // translating ALT+number key combinations.
5659 // ignore [shift+]alt+space so the OS can handle it
5660 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
5661 IS_VK_DOWN(NS_VK_SPACE
))
5665 if (modKeyState
.mIsAltDown
&& nsIMM32Handler::IsStatusChanged()) {
5666 nsIMM32Handler::NotifyEndStatusChange();
5667 } else if (!nsIMM32Handler::IsComposingOn(this)) {
5668 result
= OnKeyDown(aMsg
, modKeyState
, aEventDispatched
, nsnull
);
5672 if (aMsg
.wParam
== VK_MENU
||
5673 (aMsg
.wParam
== VK_F10
&& !modKeyState
.mIsShiftDown
)) {
5674 // We need to let Windows handle this keypress,
5675 // by returning PR_FALSE, if there's a native menu
5676 // bar somewhere in our containing window hierarchy.
5677 // Otherwise we handle the keypress and don't pass
5678 // it on to Windows, by returning PR_TRUE.
5679 PRBool hasNativeMenu
= PR_FALSE
;
5682 if (::GetMenu(hWnd
)) {
5683 hasNativeMenu
= PR_TRUE
;
5686 hWnd
= ::GetParent(hWnd
);
5688 result
= !hasNativeMenu
;
5696 nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout
,
5697 PRInt32 aNativeKeyCode
,
5698 PRUint32 aModifierFlags
,
5699 const nsAString
& aCharacters
,
5700 const nsAString
& aUnmodifiedCharacters
)
5702 #ifndef WINCE //Win CE doesn't support many of the calls used in this method, perhaps theres another way
5703 nsPrintfCString
layoutName("%08x", aNativeKeyboardLayout
);
5704 HKL loadedLayout
= LoadKeyboardLayoutA(layoutName
.get(), KLF_NOTELLSHELL
);
5705 if (loadedLayout
== NULL
)
5706 return NS_ERROR_NOT_AVAILABLE
;
5708 // Setup clean key state and load desired layout
5709 BYTE originalKbdState
[256];
5710 ::GetKeyboardState(originalKbdState
);
5712 memset(kbdState
, 0, sizeof(kbdState
));
5713 // This changes the state of the keyboard for the current thread only,
5714 // and we'll restore it soon, so this should be OK.
5715 ::SetKeyboardState(kbdState
);
5716 HKL oldLayout
= gKbdLayout
.GetLayout();
5717 gKbdLayout
.LoadLayout(loadedLayout
);
5719 nsAutoTArray
<KeyPair
,10> keySequence
;
5720 SetupKeyModifiersSequence(&keySequence
, aModifierFlags
);
5721 NS_ASSERTION(aNativeKeyCode
>= 0 && aNativeKeyCode
< 256,
5722 "Native VK key code out of range");
5723 keySequence
.AppendElement(KeyPair(aNativeKeyCode
, 0));
5725 // Simulate the pressing of each modifier key and then the real key
5726 for (PRUint32 i
= 0; i
< keySequence
.Length(); ++i
) {
5727 PRUint8 key
= keySequence
[i
].mGeneral
;
5728 PRUint8 keySpecific
= keySequence
[i
].mSpecific
;
5729 kbdState
[key
] = 0x81; // key is down and toggled on if appropriate
5731 kbdState
[keySpecific
] = 0x81;
5733 ::SetKeyboardState(kbdState
);
5734 nsModifierKeyState modKeyState
;
5735 MSG msg
= InitMSG(WM_KEYDOWN
, key
, 0);
5736 if (i
== keySequence
.Length() - 1 && aCharacters
.Length() > 0) {
5737 UINT scanCode
= ::MapVirtualKeyEx(aNativeKeyCode
, MAPVK_VK_TO_VSC
,
5738 gKbdLayout
.GetLayout());
5739 nsFakeCharMessage fakeMsg
= { aCharacters
.CharAt(0), scanCode
};
5740 OnKeyDown(msg
, modKeyState
, nsnull
, &fakeMsg
);
5742 OnKeyDown(msg
, modKeyState
, nsnull
, nsnull
);
5745 for (PRUint32 i
= keySequence
.Length(); i
> 0; --i
) {
5746 PRUint8 key
= keySequence
[i
- 1].mGeneral
;
5747 PRUint8 keySpecific
= keySequence
[i
- 1].mSpecific
;
5748 kbdState
[key
] = 0; // key is up and toggled off if appropriate
5750 kbdState
[keySpecific
] = 0;
5752 ::SetKeyboardState(kbdState
);
5753 nsModifierKeyState modKeyState
;
5754 MSG msg
= InitMSG(WM_KEYUP
, key
, 0);
5755 OnKeyUp(msg
, modKeyState
, nsnull
);
5758 // Restore old key state and layout
5759 ::SetKeyboardState(originalKbdState
);
5760 gKbdLayout
.LoadLayout(oldLayout
);
5762 UnloadKeyboardLayout(loadedLayout
);
5764 #else //XXX: is there another way to do this?
5765 return NS_ERROR_NOT_IMPLEMENTED
;
5770 nsWindow::SynthesizeNativeMouseEvent(nsIntPoint aPoint
,
5771 PRUint32 aNativeMessage
,
5772 PRUint32 aModifierFlags
)
5774 #ifndef WINCE // I don't think WINCE supports SendInput
5776 ::GetWindowRect(mWnd
, &r
);
5777 ::SetCursorPos(r
.left
+ aPoint
.x
, r
.top
+ aPoint
.y
);
5780 memset(&input
, 0, sizeof(input
));
5782 input
.type
= INPUT_MOUSE
;
5783 input
.mi
.dwFlags
= aNativeMessage
;
5784 ::SendInput(1, &input
, sizeof(INPUT
));
5788 return NS_ERROR_NOT_IMPLEMENTED
;
5792 /**************************************************************
5794 * SECTION: OnXXX message handlers
5796 * For message handlers that need to be broken out or
5797 * implemented in specific platform code.
5799 **************************************************************/
5801 BOOL
nsWindow::OnInputLangChange(HKL aHKL
)
5804 printf("OnInputLanguageChange\n");
5808 gKbdLayout
.LoadLayout(aHKL
);
5811 return PR_FALSE
; // always pass to child window
5814 #if !defined(WINCE) // implemented in nsWindowCE.cpp
5815 void nsWindow::OnWindowPosChanged(WINDOWPOS
*wp
, PRBool
& result
)
5820 #ifdef WINSTATE_DEBUG_OUTPUT
5821 if (mWnd
== GetTopLevelHWND(mWnd
))
5822 printf("*** OnWindowPosChanged: [ top] ");
5824 printf("*** OnWindowPosChanged: [child] ");
5825 printf("WINDOWPOS flags:");
5826 if (wp
->flags
& SWP_FRAMECHANGED
)
5827 printf("SWP_FRAMECHANGED ");
5828 if (wp
->flags
& SWP_SHOWWINDOW
)
5829 printf("SWP_SHOWWINDOW ");
5830 if (wp
->flags
& SWP_NOSIZE
)
5831 printf("SWP_NOSIZE ");
5832 if (wp
->flags
& SWP_HIDEWINDOW
)
5833 printf("SWP_HIDEWINDOW ");
5837 // Handle window size mode changes
5838 if (wp
->flags
& SWP_FRAMECHANGED
&& mSizeMode
!= nsSizeMode_Fullscreen
) {
5839 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
5842 pl
.length
= sizeof(pl
);
5843 ::GetWindowPlacement(mWnd
, &pl
);
5845 if (pl
.showCmd
== SW_SHOWMAXIMIZED
)
5846 event
.mSizeMode
= nsSizeMode_Maximized
;
5847 else if (pl
.showCmd
== SW_SHOWMINIMIZED
)
5848 event
.mSizeMode
= nsSizeMode_Minimized
;
5850 event
.mSizeMode
= nsSizeMode_Normal
;
5852 // Windows has just changed the size mode of this window. The following
5853 // NS_SIZEMODE event will trigger a call into SetSizeMode where we will
5854 // set the min/max window state again or for nsSizeMode_Normal, call
5855 // SetWindow with a parameter of SW_RESTORE. There's no need however as
5856 // this window's mode has already changed. Updating mSizeMode here
5857 // insures the SetSizeMode call is a no-op. Addresses a bug on Win7 related
5858 // to window docking. (bug 489258)
5859 mSizeMode
= event
.mSizeMode
;
5861 // If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
5862 // SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
5863 // prevents the working set from being trimmed but keeps the window active.
5864 // After the window is minimized, we need to do some touch up work on the
5865 // active window. (bugs 76831 & 499816)
5866 if (!sTrimOnMinimize
&& nsSizeMode_Minimized
== event
.mSizeMode
)
5867 ActivateOtherWindowHelper(mWnd
);
5869 #ifdef WINSTATE_DEBUG_OUTPUT
5870 switch (mSizeMode
) {
5871 case nsSizeMode_Normal
:
5872 printf("*** mSizeMode: nsSizeMode_Normal\n");
5874 case nsSizeMode_Minimized
:
5875 printf("*** mSizeMode: nsSizeMode_Minimized\n");
5877 case nsSizeMode_Maximized
:
5878 printf("*** mSizeMode: nsSizeMode_Maximized\n");
5881 printf("*** mSizeMode: ??????\n");
5888 result
= DispatchWindowEvent(&event
);
5890 // Skip window size change events below on minimization.
5891 if (mSizeMode
== nsSizeMode_Minimized
)
5895 // Handle window size changes
5896 if (0 == (wp
->flags
& SWP_NOSIZE
)) {
5898 PRInt32 newWidth
, newHeight
;
5900 ::GetWindowRect(mWnd
, &r
);
5902 newWidth
= r
.right
- r
.left
;
5903 newHeight
= r
.bottom
- r
.top
;
5904 nsIntRect
rect(wp
->x
, wp
->y
, newWidth
, newHeight
);
5907 if (eTransparencyTransparent
== mTransparencyMode
)
5908 ResizeTranslucentWindow(newWidth
, newHeight
);
5911 if (newWidth
> mLastSize
.width
)
5916 drect
.left
= wp
->x
+ mLastSize
.width
;
5918 drect
.right
= drect
.left
+ (newWidth
- mLastSize
.width
);
5919 drect
.bottom
= drect
.top
+ newHeight
;
5921 ::RedrawWindow(mWnd
, &drect
, NULL
,
5924 RDW_NOINTERNALPAINT
|
5928 if (newHeight
> mLastSize
.height
)
5934 drect
.top
= wp
->y
+ mLastSize
.height
;
5935 drect
.right
= drect
.left
+ newWidth
;
5936 drect
.bottom
= drect
.top
+ (newHeight
- mLastSize
.height
);
5938 ::RedrawWindow(mWnd
, &drect
, NULL
,
5941 RDW_NOINTERNALPAINT
|
5946 mBounds
.width
= newWidth
;
5947 mBounds
.height
= newHeight
;
5948 mLastSize
.width
= newWidth
;
5949 mLastSize
.height
= newHeight
;
5951 #ifdef WINSTATE_DEBUG_OUTPUT
5952 printf("*** Resize window: %d x %d x %d x %d\n", wp
->x
, wp
->y
, newWidth
, newHeight
);
5955 // If a maximized window is resized, recalculate the non-client margins and
5956 // ensure a 1 pixel margin at screen bottom to allow taskbar unhiding to
5958 if (mSizeMode
== nsSizeMode_Maximized
) {
5959 if (UpdateNonClientMargins(nsSizeMode_Maximized
, PR_TRUE
)) {
5960 // gecko resize event already sent by UpdateNonClientMargins.
5966 // Recalculate the width and height based on the client area for gecko events.
5967 if (::GetClientRect(mWnd
, &r
)) {
5968 rect
.width
= r
.right
- r
.left
;
5969 rect
.height
= r
.bottom
- r
.top
;
5972 // Send a gecko resize event
5973 result
= OnResize(rect
);
5978 void nsWindow::ActivateOtherWindowHelper(HWND aWnd
)
5980 // Find the next window that is enabled, visible, and not minimized.
5981 HWND hwndBelow
= ::GetNextWindow(aWnd
, GW_HWNDNEXT
);
5982 while (hwndBelow
&& (!::IsWindowEnabled(hwndBelow
) || !::IsWindowVisible(hwndBelow
) ||
5983 ::IsIconic(hwndBelow
))) {
5984 hwndBelow
= ::GetNextWindow(hwndBelow
, GW_HWNDNEXT
);
5987 // Push ourselves to the bottom of the stack, then activate the
5989 ::SetWindowPos(aWnd
, HWND_BOTTOM
, 0, 0, 0, 0,
5990 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
5992 ::SetForegroundWindow(hwndBelow
);
5994 // Play the minimize sound while we're here, since that is also
5995 // forgotten when we use SW_SHOWMINIMIZED.
5996 ::PlaySoundW(L
"Minimize", nsnull
, SND_ALIAS
| SND_NODEFAULT
| SND_ASYNC
);
5998 #endif // !defined(WINCE)
6001 void nsWindow::OnWindowPosChanging(LPWINDOWPOS
& info
)
6003 // Update non-client margins if the frame size is changing, and let the
6004 // browser know we are changing size modes, so alternative css can kick in.
6005 // If we're going into fullscreen mode, ignore this, since it'll reset
6006 // margins to normal mode.
6007 if (info
->flags
& SWP_FRAMECHANGED
&& mSizeMode
!= nsSizeMode_Fullscreen
) {
6009 pl
.length
= sizeof(pl
);
6010 ::GetWindowPlacement(mWnd
, &pl
);
6012 if (pl
.showCmd
== SW_SHOWMAXIMIZED
)
6013 sizeMode
= nsSizeMode_Maximized
;
6014 else if (pl
.showCmd
== SW_SHOWMINIMIZED
)
6015 sizeMode
= nsSizeMode_Minimized
;
6017 sizeMode
= nsSizeMode_Normal
;
6019 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
6022 event
.mSizeMode
= static_cast<nsSizeMode
>(sizeMode
);
6023 DispatchWindowEvent(&event
);
6025 UpdateNonClientMargins(sizeMode
, PR_FALSE
);
6028 // enforce local z-order rules
6029 if (!(info
->flags
& SWP_NOZORDER
)) {
6030 HWND hwndAfter
= info
->hwndInsertAfter
;
6032 nsZLevelEvent
event(PR_TRUE
, NS_SETZLEVEL
, this);
6033 nsWindow
*aboveWindow
= 0;
6037 if (hwndAfter
== HWND_BOTTOM
)
6038 event
.mPlacement
= nsWindowZBottom
;
6039 else if (hwndAfter
== HWND_TOP
|| hwndAfter
== HWND_TOPMOST
|| hwndAfter
== HWND_NOTOPMOST
)
6040 event
.mPlacement
= nsWindowZTop
;
6042 event
.mPlacement
= nsWindowZRelative
;
6043 aboveWindow
= GetNSWindowPtr(hwndAfter
);
6045 event
.mReqBelow
= aboveWindow
;
6046 event
.mActualBelow
= nsnull
;
6048 event
.mImmediate
= PR_FALSE
;
6049 event
.mAdjusted
= PR_FALSE
;
6050 DispatchWindowEvent(&event
);
6052 if (event
.mAdjusted
) {
6053 if (event
.mPlacement
== nsWindowZBottom
)
6054 info
->hwndInsertAfter
= HWND_BOTTOM
;
6055 else if (event
.mPlacement
== nsWindowZTop
)
6056 info
->hwndInsertAfter
= HWND_TOP
;
6058 info
->hwndInsertAfter
= (HWND
)event
.mActualBelow
->GetNativeData(NS_NATIVE_WINDOW
);
6061 NS_IF_RELEASE(event
.mActualBelow
);
6063 // prevent rude external programs from making hidden window visible
6064 if (mWindowType
== eWindowType_invisible
)
6065 info
->flags
&= ~SWP_SHOWWINDOW
;
6069 void nsWindow::UserActivity()
6071 // Check if we have the idle service, if not we try to get it.
6072 if (!mIdleService
) {
6073 mIdleService
= do_GetService("@mozilla.org/widget/idleservice;1");
6076 // Check that we now have the idle service.
6078 mIdleService
->ResetIdleTimeOut();
6082 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
6083 PRBool
nsWindow::OnTouch(WPARAM wParam
, LPARAM lParam
)
6085 PRUint32 cInputs
= LOWORD(wParam
);
6086 PTOUCHINPUT pInputs
= new TOUCHINPUT
[cInputs
];
6088 if (mGesture
.GetTouchInputInfo((HTOUCHINPUT
)lParam
, cInputs
, pInputs
)) {
6089 for (PRUint32 i
= 0; i
< cInputs
; i
++) {
6091 if (pInputs
[i
].dwFlags
& TOUCHEVENTF_MOVE
) {
6092 msg
= NS_MOZTOUCH_MOVE
;
6093 } else if (pInputs
[i
].dwFlags
& TOUCHEVENTF_DOWN
) {
6094 msg
= NS_MOZTOUCH_DOWN
;
6095 } else if (pInputs
[i
].dwFlags
& TOUCHEVENTF_UP
) {
6096 msg
= NS_MOZTOUCH_UP
;
6101 nsPointWin touchPoint
;
6102 touchPoint
.x
= TOUCH_COORD_TO_PIXEL(pInputs
[i
].x
);
6103 touchPoint
.y
= TOUCH_COORD_TO_PIXEL(pInputs
[i
].y
);
6104 touchPoint
.ScreenToClient(mWnd
);
6106 nsMozTouchEvent
touchEvent(PR_TRUE
, msg
, this, pInputs
[i
].dwID
);
6107 touchEvent
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6108 touchEvent
.refPoint
= touchPoint
;
6110 nsEventStatus status
;
6111 DispatchEvent(&touchEvent
, status
);
6116 mGesture
.CloseTouchInputHandle((HTOUCHINPUT
)lParam
);
6121 // Gesture event processing. Handles WM_GESTURE events.
6123 PRBool
nsWindow::OnGesture(WPARAM wParam
, LPARAM lParam
)
6125 // Treatment for pan events which translate into scroll events:
6126 if (mGesture
.IsPanEvent(lParam
)) {
6127 nsMouseScrollEvent
event(PR_TRUE
, NS_MOUSE_PIXEL_SCROLL
, this);
6129 if ( !mGesture
.ProcessPanMessage(mWnd
, wParam
, lParam
) )
6130 return PR_FALSE
; // ignore
6132 nsEventStatus status
;
6134 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6135 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6136 event
.isMeta
= PR_FALSE
;
6137 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6139 event
.time
= ::GetMessageTime();
6140 event
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6142 PRBool endFeedback
= PR_TRUE
;
6144 PRInt32 scrollOverflowX
= 0;
6145 PRInt32 scrollOverflowY
= 0;
6147 if (mGesture
.PanDeltaToPixelScrollX(event
)) {
6148 DispatchEvent(&event
, status
);
6149 scrollOverflowX
= event
.scrollOverflow
;
6152 if (mGesture
.PanDeltaToPixelScrollY(event
)) {
6153 DispatchEvent(&event
, status
);
6154 scrollOverflowY
= event
.scrollOverflow
;
6157 if (mDisplayPanFeedback
) {
6158 mGesture
.UpdatePanFeedbackX(mWnd
, scrollOverflowX
, endFeedback
);
6159 mGesture
.UpdatePanFeedbackY(mWnd
, scrollOverflowY
, endFeedback
);
6160 mGesture
.PanFeedbackFinalize(mWnd
, endFeedback
);
6163 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
6168 // Other gestures translate into simple gesture events:
6169 nsSimpleGestureEvent
event(PR_TRUE
, 0, this, 0, 0.0);
6170 if ( !mGesture
.ProcessGestureMessage(mWnd
, wParam
, lParam
, event
) ) {
6171 return PR_FALSE
; // fall through to DefWndProc
6174 // Polish up and send off the new event
6175 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6176 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6177 event
.isMeta
= PR_FALSE
;
6178 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6180 event
.time
= ::GetMessageTime();
6181 event
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6183 nsEventStatus status
;
6184 DispatchEvent(&event
, status
);
6185 if (status
== nsEventStatus_eIgnore
) {
6186 return PR_FALSE
; // Ignored, fall through
6189 // Only close this if we process and return true.
6190 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
6192 return PR_TRUE
; // Handled
6194 #endif // !defined(WINCE)
6197 PRUint16
nsWindow::GetMouseInputSource()
6199 PRUint16 inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_MOUSE
;
6200 LPARAM lParamExtraInfo
= ::GetMessageExtraInfo();
6201 if ((lParamExtraInfo
& TABLET_INK_SIGNATURE
) == TABLET_INK_CHECK
) {
6202 inputSource
= (lParamExtraInfo
& TABLET_INK_TOUCH
) ?
6203 PRUint16(nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
) : nsIDOMNSMouseEvent::MOZ_SOURCE_PEN
;
6209 * OnMouseWheel - mouse wheele event processing. This was originally embedded
6210 * within the message case block. If returning true result should be returned
6211 * immediately (no more processing).
6213 PRBool
nsWindow::OnMouseWheel(UINT msg
, WPARAM wParam
, LPARAM lParam
, PRBool
& getWheelInfo
, PRBool
& result
, LRESULT
*aRetValue
)
6215 // Handle both flavors of mouse wheel events.
6216 static int iDeltaPerLine
, iDeltaPerChar
;
6217 static ULONG ulScrollLines
, ulScrollChars
= 1;
6218 static int currentVDelta
, currentHDelta
;
6219 static HWND currentWindow
= 0;
6221 PRBool isVertical
= msg
== WM_MOUSEWHEEL
;
6223 // Get mouse wheel metrics (but only once).
6225 getWheelInfo
= PR_FALSE
;
6227 SystemParametersInfo (SPI_GETWHEELSCROLLLINES
, 0, &ulScrollLines
, 0);
6229 // ulScrollLines usually equals 3 or 0 (for no scrolling)
6230 // WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
6232 // However, if ulScrollLines > WHEEL_DELTA, we assume that
6233 // the mouse driver wants a page scroll. The docs state that
6234 // ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
6235 // since some mouse drivers use an arbitrary large number instead,
6236 // we have to handle that as well.
6239 if (ulScrollLines
) {
6240 if (ulScrollLines
<= WHEEL_DELTA
) {
6241 iDeltaPerLine
= WHEEL_DELTA
/ ulScrollLines
;
6243 ulScrollLines
= WHEEL_PAGESCROLL
;
6247 if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0,
6248 &ulScrollChars
, 0)) {
6249 // Note that we may always fail to get the value before Win Vista.
6254 if (ulScrollChars
) {
6255 if (ulScrollChars
<= WHEEL_DELTA
) {
6256 iDeltaPerChar
= WHEEL_DELTA
/ ulScrollChars
;
6258 ulScrollChars
= WHEEL_PAGESCROLL
;
6263 if ((isVertical
&& ulScrollLines
!= WHEEL_PAGESCROLL
&& !iDeltaPerLine
) ||
6264 (!isVertical
&& ulScrollChars
!= WHEEL_PAGESCROLL
&& !iDeltaPerChar
))
6265 return PR_FALSE
; // break
6267 // The mousewheel event will be dispatched to the toplevel
6268 // window. We need to give it to the child window
6270 if (!HandleScrollingPlugins(msg
, wParam
, lParam
, result
, aRetValue
, quit
))
6271 return quit
; // return immediately if its not our window
6273 // We should cancel the surplus delta if the current window is not
6274 // same as previous.
6275 if (currentWindow
!= mWnd
) {
6278 currentWindow
= mWnd
;
6281 nsMouseScrollEvent
scrollEvent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
6282 scrollEvent
.delta
= 0;
6284 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsVertical
;
6285 if (ulScrollLines
== WHEEL_PAGESCROLL
) {
6286 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6287 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? -1 : 1;
6289 currentVDelta
-= (short) HIWORD (wParam
);
6290 if (PR_ABS(currentVDelta
) >= iDeltaPerLine
) {
6291 scrollEvent
.delta
= currentVDelta
/ iDeltaPerLine
;
6292 currentVDelta
%= iDeltaPerLine
;
6296 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsHorizontal
;
6297 if (ulScrollChars
== WHEEL_PAGESCROLL
) {
6298 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6299 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? 1 : -1;
6301 currentHDelta
+= (short) HIWORD (wParam
);
6302 if (PR_ABS(currentHDelta
) >= iDeltaPerChar
) {
6303 scrollEvent
.delta
= currentHDelta
/ iDeltaPerChar
;
6304 currentHDelta
%= iDeltaPerChar
;
6309 if (!scrollEvent
.delta
) {
6310 // We store the wheel delta, and it will be used next wheel message, so,
6311 // we consume this message actually. We shouldn't call next wndproc.
6313 return PR_FALSE
; // break
6317 // The event may go to a plug-in which already dispatched this message.
6318 // Then, the event can cause deadlock. We should unlock the sender here.
6319 ::ReplyMessage(isVertical
? 0 : TRUE
);
6322 scrollEvent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6323 scrollEvent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6324 scrollEvent
.isMeta
= PR_FALSE
;
6325 scrollEvent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6326 InitEvent(scrollEvent
);
6327 if (nsnull
!= mEventCallback
) {
6328 result
= DispatchWindowEvent(&scrollEvent
);
6330 // Note that we should return zero if we process WM_MOUSEWHEEL.
6331 // But if we process WM_MOUSEHWHEEL, we should return non-zero.
6334 *aRetValue
= isVertical
? 0 : TRUE
;
6336 return PR_FALSE
; // break;
6340 StringCaseInsensitiveEquals(const PRUnichar
* aChars1
, const PRUint32 aNumChars1
,
6341 const PRUnichar
* aChars2
, const PRUint32 aNumChars2
)
6343 if (aNumChars1
!= aNumChars2
)
6346 nsCaseInsensitiveStringComparator comp
;
6347 return comp(aChars1
, aChars2
, aNumChars1
) == 0;
6350 UINT
nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode
)
6353 switch (aNativeKeyCode
) {
6354 case VK_OEM_1
: return NS_VK_SEMICOLON
; // 0xBA, For the US standard keyboard, the ';:' key
6355 case VK_OEM_PLUS
: return NS_VK_ADD
; // 0xBB, For any country/region, the '+' key
6356 case VK_OEM_MINUS
: return NS_VK_SUBTRACT
; // 0xBD, For any country/region, the '-' key
6360 return aNativeKeyCode
;
6364 * nsWindow::OnKeyDown peeks into the message queue and pulls out
6365 * WM_CHAR messages for processing. During testing we don't want to
6366 * mess with the real message queue. Instead we pass a
6367 * pseudo-WM_CHAR-message using this structure, and OnKeyDown will use
6368 * that as if it was in the message queue, and refrain from actually
6369 * looking at or touching the message queue.
6371 LRESULT
nsWindow::OnKeyDown(const MSG
&aMsg
,
6372 nsModifierKeyState
&aModKeyState
,
6373 PRBool
*aEventDispatched
,
6374 nsFakeCharMessage
* aFakeCharMessage
)
6376 UINT virtualKeyCode
= aMsg
.wParam
;
6379 gKbdLayout
.OnKeyDown (virtualKeyCode
);
6382 // Use only DOMKeyCode for XP processing.
6383 // Use aVirtualKeyCode for gKbdLayout and native processing.
6384 UINT DOMKeyCode
= nsIMM32Handler::IsComposingOn(this) ?
6385 virtualKeyCode
: MapFromNativeToDOM(virtualKeyCode
);
6388 //printf("In OnKeyDown virt: %d\n", DOMKeyCode);
6392 DispatchKeyEvent(NS_KEY_DOWN
, 0, nsnull
, DOMKeyCode
, &aMsg
, aModKeyState
);
6393 if (aEventDispatched
)
6394 *aEventDispatched
= PR_TRUE
;
6396 // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
6397 // for almost all keys
6398 switch (DOMKeyCode
) {
6402 case NS_VK_CAPS_LOCK
:
6403 case NS_VK_NUM_LOCK
:
6404 case NS_VK_SCROLL_LOCK
: return noDefault
;
6407 PRUint32 extraFlags
= (noDefault
? NS_EVENT_FLAG_NO_DEFAULT
: 0);
6409 BOOL gotMsg
= aFakeCharMessage
||
6410 ::PeekMessageW(&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
6411 // Enter and backspace are always handled here to avoid for example the
6412 // confusion between ctrl-enter and ctrl-J.
6413 if (DOMKeyCode
== NS_VK_RETURN
|| DOMKeyCode
== NS_VK_BACK
||
6414 ((aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)
6418 && !gKbdLayout
.IsDeadKey() && KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)))
6421 // Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
6422 // They can be more than one because of:
6423 // * Dead-keys not pairing with base character
6424 // * Some keyboard layouts may map up to 4 characters to the single key
6425 PRBool anyCharMessagesRemoved
= PR_FALSE
;
6427 if (aFakeCharMessage
) {
6428 anyCharMessagesRemoved
= PR_TRUE
;
6430 while (gotMsg
&& (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
))
6432 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6433 ("%s charCode=%d scanCode=%d\n", msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
6434 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
6435 RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST
, WM_KEYLAST
);
6436 anyCharMessagesRemoved
= PR_TRUE
;
6438 gotMsg
= ::PeekMessageW (&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
6442 if (!anyCharMessagesRemoved
&& DOMKeyCode
== NS_VK_BACK
&&
6443 nsIMM32Handler::IsDoingKakuteiUndo(mWnd
)) {
6444 NS_ASSERTION(!aFakeCharMessage
,
6445 "We shouldn't be touching the real msg queue");
6446 RemoveMessageAndDispatchPluginEvent(WM_CHAR
, WM_CHAR
);
6450 (aFakeCharMessage
||
6451 msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
|| msg
.message
== WM_DEADCHAR
)) {
6452 if (aFakeCharMessage
)
6453 return OnCharRaw(aFakeCharMessage
->mCharCode
,
6454 aFakeCharMessage
->mScanCode
, aModKeyState
, extraFlags
);
6456 // If prevent default set for keydown, do same for keypress
6457 ::GetMessageW(&msg
, mWnd
, msg
.message
, msg
.message
);
6459 if (msg
.message
== WM_DEADCHAR
) {
6460 if (!PluginHasFocus())
6463 // We need to send the removed message to focused plug-in.
6464 DispatchPluginEvent(msg
);
6468 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6469 ("%s charCode=%d scanCode=%d\n",
6470 msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
6471 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
6473 BOOL result
= OnChar(msg
, aModKeyState
, nsnull
, extraFlags
);
6474 // If a syschar keypress wasn't processed, Windows may want to
6475 // handle it to activate a native menu.
6476 if (!result
&& msg
.message
== WM_SYSCHAR
)
6477 ::DefWindowProcW(mWnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
6481 else if (!aModKeyState
.mIsControlDown
&& !aModKeyState
.mIsAltDown
&&
6482 (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
) ||
6483 KeyboardLayout::IsNumpadKey(virtualKeyCode
)))
6485 // If this is simple KeyDown event but next message is not WM_CHAR,
6486 // this event may not input text, so we should ignore this event.
6488 return PluginHasFocus() && noDefault
;
6491 if (gKbdLayout
.IsDeadKey ())
6492 return PluginHasFocus() && noDefault
;
6494 PRUint8 shiftStates
[5];
6495 PRUnichar uniChars
[5];
6496 PRUnichar shiftedChars
[5] = {0, 0, 0, 0, 0};
6497 PRUnichar unshiftedChars
[5] = {0, 0, 0, 0, 0};
6498 PRUnichar shiftedLatinChar
= 0;
6499 PRUnichar unshiftedLatinChar
= 0;
6500 PRUint32 numOfUniChars
= 0;
6501 PRUint32 numOfShiftedChars
= 0;
6502 PRUint32 numOfUnshiftedChars
= 0;
6503 PRUint32 numOfShiftStates
= 0;
6505 switch (virtualKeyCode
) {
6506 // keys to be sent as characters
6507 case VK_ADD
: uniChars
[0] = '+'; numOfUniChars
= 1; break;
6508 case VK_SUBTRACT
: uniChars
[0] = '-'; numOfUniChars
= 1; break;
6509 case VK_DIVIDE
: uniChars
[0] = '/'; numOfUniChars
= 1; break;
6510 case VK_MULTIPLY
: uniChars
[0] = '*'; numOfUniChars
= 1; break;
6521 uniChars
[0] = virtualKeyCode
- VK_NUMPAD0
+ '0';
6525 if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)) {
6526 numOfUniChars
= numOfShiftStates
=
6527 gKbdLayout
.GetUniChars(uniChars
, shiftStates
,
6528 NS_ARRAY_LENGTH(uniChars
));
6531 if (aModKeyState
.mIsControlDown
^ aModKeyState
.mIsAltDown
) {
6532 PRUint8 capsLockState
= (::GetKeyState(VK_CAPITAL
) & 1) ? eCapsLock
: 0;
6533 numOfUnshiftedChars
=
6534 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
, capsLockState
,
6535 unshiftedChars
, NS_ARRAY_LENGTH(unshiftedChars
));
6537 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
,
6538 capsLockState
| eShift
,
6539 shiftedChars
, NS_ARRAY_LENGTH(shiftedChars
));
6541 // The current keyboard cannot input alphabets or numerics,
6542 // we should append them for Shortcut/Access keys.
6543 // E.g., for Cyrillic keyboard layout.
6544 if (NS_VK_A
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_Z
) {
6545 shiftedLatinChar
= unshiftedLatinChar
= DOMKeyCode
;
6547 shiftedLatinChar
+= 0x20;
6549 unshiftedLatinChar
+= 0x20;
6550 if (unshiftedLatinChar
== unshiftedChars
[0] &&
6551 shiftedLatinChar
== shiftedChars
[0]) {
6552 shiftedLatinChar
= unshiftedLatinChar
= 0;
6556 if (NS_VK_0
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_9
) {
6559 switch (virtualKeyCode
) {
6560 case VK_OEM_PLUS
: ch
= '+'; break;
6561 case VK_OEM_MINUS
: ch
= '-'; break;
6564 if (ch
&& unshiftedChars
[0] != ch
&& shiftedChars
[0] != ch
) {
6565 // Windows has assigned a virtual key code to the key even though
6566 // the character can't be produced with this key. That probably
6567 // means the character can't be produced with any key in the
6568 // current layout and so the assignment is based on a QWERTY
6569 // layout. Append this code so that users can access the shortcut.
6570 unshiftedLatinChar
= ch
;
6574 // If the charCode is not ASCII character, we should replace the
6575 // charCode with ASCII character only when Ctrl is pressed.
6576 // But don't replace the charCode when the charCode is not same as
6577 // unmodified characters. In such case, Ctrl is sometimes used for a
6578 // part of character inputting key combination like Shift.
6579 if (aModKeyState
.mIsControlDown
) {
6580 PRUint8 currentState
= eCtrl
;
6581 if (aModKeyState
.mIsShiftDown
)
6582 currentState
|= eShift
;
6585 aModKeyState
.mIsShiftDown
? shiftedLatinChar
: unshiftedLatinChar
;
6587 (numOfUniChars
== 0 ||
6588 StringCaseInsensitiveEquals(uniChars
, numOfUniChars
,
6589 aModKeyState
.mIsShiftDown
? shiftedChars
: unshiftedChars
,
6590 aModKeyState
.mIsShiftDown
? numOfShiftedChars
:
6591 numOfUnshiftedChars
))) {
6592 numOfUniChars
= numOfShiftStates
= 1;
6594 shiftStates
[0] = currentState
;
6600 if (numOfUniChars
> 0 || numOfShiftedChars
> 0 || numOfUnshiftedChars
> 0) {
6601 PRUint32 num
= PR_MAX(numOfUniChars
,
6602 PR_MAX(numOfShiftedChars
, numOfUnshiftedChars
));
6603 PRUint32 skipUniChars
= num
- numOfUniChars
;
6604 PRUint32 skipShiftedChars
= num
- numOfShiftedChars
;
6605 PRUint32 skipUnshiftedChars
= num
- numOfUnshiftedChars
;
6606 UINT keyCode
= numOfUniChars
== 0 ? DOMKeyCode
: 0;
6607 for (PRUint32 cnt
= 0; cnt
< num
; cnt
++) {
6608 PRUint16 uniChar
, shiftedChar
, unshiftedChar
;
6609 uniChar
= shiftedChar
= unshiftedChar
= 0;
6610 if (skipUniChars
<= cnt
) {
6611 if (cnt
- skipUniChars
< numOfShiftStates
) {
6612 // If key in combination with Alt and/or Ctrl produces a different
6613 // character than without them then do not report these flags
6614 // because it is separate keyboard layout shift state. If dead-key
6615 // and base character does not produce a valid composite character
6616 // then both produced dead-key character and following base
6617 // character may have different modifier flags, too.
6618 aModKeyState
.mIsShiftDown
=
6619 (shiftStates
[cnt
- skipUniChars
] & eShift
) != 0;
6620 aModKeyState
.mIsControlDown
=
6621 (shiftStates
[cnt
- skipUniChars
] & eCtrl
) != 0;
6622 aModKeyState
.mIsAltDown
=
6623 (shiftStates
[cnt
- skipUniChars
] & eAlt
) != 0;
6625 uniChar
= uniChars
[cnt
- skipUniChars
];
6627 if (skipShiftedChars
<= cnt
)
6628 shiftedChar
= shiftedChars
[cnt
- skipShiftedChars
];
6629 if (skipUnshiftedChars
<= cnt
)
6630 unshiftedChar
= unshiftedChars
[cnt
- skipUnshiftedChars
];
6631 nsAutoTArray
<nsAlternativeCharCode
, 5> altArray
;
6633 if (shiftedChar
|| unshiftedChar
) {
6634 nsAlternativeCharCode
chars(unshiftedChar
, shiftedChar
);
6635 altArray
.AppendElement(chars
);
6637 if (cnt
== num
- 1 && (unshiftedLatinChar
|| shiftedLatinChar
)) {
6638 nsAlternativeCharCode
chars(unshiftedLatinChar
, shiftedLatinChar
);
6639 altArray
.AppendElement(chars
);
6642 DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, &altArray
,
6643 keyCode
, nsnull
, aModKeyState
, extraFlags
);
6646 DispatchKeyEvent(NS_KEY_PRESS
, 0, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
6651 UINT unichar
= ::MapVirtualKey(virtualKeyCode
, MAPVK_VK_TO_CHAR
);
6652 // Check for dead characters or no mapping
6653 if (unichar
& 0x80) {
6656 DispatchKeyEvent(NS_KEY_PRESS
, unichar
, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
6665 LRESULT
nsWindow::OnKeyUp(const MSG
&aMsg
,
6666 nsModifierKeyState
&aModKeyState
,
6667 PRBool
*aEventDispatched
)
6669 UINT virtualKeyCode
= aMsg
.wParam
;
6671 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6672 ("nsWindow::OnKeyUp VK=%d\n", virtualKeyCode
));
6674 if (!nsIMM32Handler::IsComposingOn(this)) {
6675 virtualKeyCode
= MapFromNativeToDOM(virtualKeyCode
);
6678 if (aEventDispatched
)
6679 *aEventDispatched
= PR_TRUE
;
6680 return DispatchKeyEvent(NS_KEY_UP
, 0, nsnull
, virtualKeyCode
, &aMsg
,
6685 LRESULT
nsWindow::OnChar(const MSG
&aMsg
, nsModifierKeyState
&aModKeyState
,
6686 PRBool
*aEventDispatched
, PRUint32 aFlags
)
6688 return OnCharRaw(aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF, aModKeyState
,
6689 aFlags
, &aMsg
, aEventDispatched
);
6693 LRESULT
nsWindow::OnCharRaw(UINT charCode
, UINT aScanCode
,
6694 nsModifierKeyState
&aModKeyState
, PRUint32 aFlags
,
6695 const MSG
*aMsg
, PRBool
*aEventDispatched
)
6697 // ignore [shift+]alt+space so the OS can handle it
6698 if (aModKeyState
.mIsAltDown
&& !aModKeyState
.mIsControlDown
&&
6699 IS_VK_DOWN(NS_VK_SPACE
)) {
6703 // Ignore Ctrl+Enter (bug 318235)
6704 if (aModKeyState
.mIsControlDown
&& charCode
== 0xA) {
6708 // WM_CHAR with Control and Alt (== AltGr) down really means a normal character
6709 PRBool saveIsAltDown
= aModKeyState
.mIsAltDown
;
6710 PRBool saveIsControlDown
= aModKeyState
.mIsControlDown
;
6711 if (aModKeyState
.mIsAltDown
&& aModKeyState
.mIsControlDown
)
6712 aModKeyState
.mIsAltDown
= aModKeyState
.mIsControlDown
= PR_FALSE
;
6716 if (nsIMM32Handler::IsComposingOn(this)) {
6720 if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1A) { // Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
6721 // need to account for shift here. bug 16486
6722 if (aModKeyState
.mIsShiftDown
)
6723 uniChar
= charCode
- 1 + 'A';
6725 uniChar
= charCode
- 1 + 'a';
6728 else if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1F) {
6729 // Fix for 50255 - <ctrl><[> and <ctrl><]> are not being processed.
6730 // also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
6731 // for some reason the keypress handler need to have the uniChar code set
6732 // with the addition of a upper case A not the lower case.
6733 uniChar
= charCode
- 1 + 'A';
6735 } else { // 0x20 - SPACE, 0x3D - EQUALS
6736 if (charCode
< 0x20 || (charCode
== 0x3D && aModKeyState
.mIsControlDown
)) {
6744 // Keep the characters unshifted for shortcuts and accesskeys and make sure
6745 // that numbers are always passed as such (among others: bugs 50255 and 351310)
6746 if (uniChar
&& (aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)) {
6747 UINT virtualKeyCode
= ::MapVirtualKeyEx(aScanCode
, MAPVK_VSC_TO_VK
,
6748 gKbdLayout
.GetLayout());
6749 UINT unshiftedCharCode
=
6750 virtualKeyCode
>= '0' && virtualKeyCode
<= '9' ? virtualKeyCode
:
6751 aModKeyState
.mIsShiftDown
? ::MapVirtualKeyEx(virtualKeyCode
,
6753 gKbdLayout
.GetLayout()) : 0;
6754 // ignore diacritics (top bit set) and key mapping errors (char code 0)
6755 if ((INT
)unshiftedCharCode
> 0)
6756 uniChar
= unshiftedCharCode
;
6759 // Fix for bug 285161 (and 295095) which was caused by the initial fix for bug 178110.
6760 // When pressing (alt|ctrl)+char, the char must be lowercase unless shift is
6762 if (!aModKeyState
.mIsShiftDown
&& (saveIsAltDown
|| saveIsControlDown
)) {
6763 uniChar
= towlower(uniChar
);
6766 PRBool result
= DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, nsnull
,
6767 charCode
, aMsg
, aModKeyState
, aFlags
);
6768 if (aEventDispatched
)
6769 *aEventDispatched
= PR_TRUE
;
6770 aModKeyState
.mIsAltDown
= saveIsAltDown
;
6771 aModKeyState
.mIsControlDown
= saveIsControlDown
;
6776 nsWindow::SetupKeyModifiersSequence(nsTArray
<KeyPair
>* aArray
, PRUint32 aModifiers
)
6778 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(sModifierKeyMap
); ++i
) {
6779 const PRUint32
* map
= sModifierKeyMap
[i
];
6780 if (aModifiers
& map
[0]) {
6781 aArray
->AppendElement(KeyPair(map
[1], map
[2]));
6787 nsWindow::ConfigureChildren(const nsTArray
<Configuration
>& aConfigurations
)
6789 // XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos
6790 // here, if that helps in some situations. So far I haven't seen a
6792 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
6793 const Configuration
& configuration
= aConfigurations
[i
];
6794 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
6795 NS_ASSERTION(w
->GetParent() == this,
6796 "Configured widget is not a child");
6798 // MSDN says we should do on WinCE this before moving or resizing the window
6799 // See http://msdn.microsoft.com/en-us/library/aa930600.aspx
6800 // We put the region back just below, anyway.
6801 ::SetWindowRgn(w
->mWnd
, NULL
, TRUE
);
6804 w
->GetBounds(bounds
);
6805 if (bounds
.Size() != configuration
.mBounds
.Size()) {
6806 w
->Resize(configuration
.mBounds
.x
, configuration
.mBounds
.y
,
6807 configuration
.mBounds
.width
, configuration
.mBounds
.height
,
6809 } else if (bounds
.TopLeft() != configuration
.mBounds
.TopLeft()) {
6810 w
->Move(configuration
.mBounds
.x
, configuration
.mBounds
.y
);
6812 nsresult rv
= w
->SetWindowClipRegion(configuration
.mClipRegion
, PR_FALSE
);
6813 NS_ENSURE_SUCCESS(rv
, rv
);
6819 CreateHRGNFromArray(const nsTArray
<nsIntRect
>& aRects
)
6821 PRInt32 size
= sizeof(RGNDATAHEADER
) + sizeof(RECT
)*aRects
.Length();
6822 nsAutoTArray
<PRUint8
,100> buf
;
6823 if (!buf
.SetLength(size
))
6825 RGNDATA
* data
= reinterpret_cast<RGNDATA
*>(buf
.Elements());
6826 RECT
* rects
= reinterpret_cast<RECT
*>(data
->Buffer
);
6827 data
->rdh
.dwSize
= sizeof(data
->rdh
);
6828 data
->rdh
.iType
= RDH_RECTANGLES
;
6829 data
->rdh
.nCount
= aRects
.Length();
6831 for (PRUint32 i
= 0; i
< aRects
.Length(); ++i
) {
6832 const nsIntRect
& r
= aRects
[i
];
6833 bounds
.UnionRect(bounds
, r
);
6834 ::SetRect(&rects
[i
], r
.x
, r
.y
, r
.XMost(), r
.YMost());
6836 ::SetRect(&data
->rdh
.rcBound
, bounds
.x
, bounds
.y
, bounds
.XMost(), bounds
.YMost());
6837 return ::ExtCreateRegion(NULL
, buf
.Length(), data
);
6841 nsWindow::SetWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
,
6842 PRBool aIntersectWithExisting
)
6844 if (!aIntersectWithExisting
) {
6845 if (!StoreWindowClipRegion(aRects
))
6849 HRGN dest
= CreateHRGNFromArray(aRects
);
6851 return NS_ERROR_OUT_OF_MEMORY
;
6853 if (aIntersectWithExisting
) {
6854 HRGN current
= ::CreateRectRgn(0, 0, 0, 0);
6856 if (::GetWindowRgn(mWnd
, current
) != 0 /*ERROR*/) {
6857 ::CombineRgn(dest
, dest
, current
, RGN_AND
);
6859 ::DeleteObject(current
);
6863 if (!::SetWindowRgn(mWnd
, dest
, TRUE
)) {
6864 ::DeleteObject(dest
);
6865 return NS_ERROR_FAILURE
;
6870 // WM_DESTROY event handler
6871 void nsWindow::OnDestroy()
6873 mOnDestroyCalled
= PR_TRUE
;
6875 // Make sure we don't get destroyed in the process of tearing down.
6876 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
6878 // Dispatch the NS_DESTROY event. Must be called before mEventCallback is cleared.
6880 DispatchStandardEvent(NS_DESTROY
);
6882 // Prevent the widget from sending additional events.
6883 mEventCallback
= nsnull
;
6885 // Free our subclass and clear |this| stored in the window props. We will no longer
6886 // receive events from Windows after this point.
6887 SubclassWindow(FALSE
);
6889 // Once mEventCallback is cleared and the subclass is reset, sCurrentWindow can be
6890 // cleared. (It's used in tracking windows for mouse events.)
6891 if (sCurrentWindow
== this)
6892 sCurrentWindow
= nsnull
;
6894 // Disconnects us from our parent, will call our GetParent().
6895 nsBaseWidget::Destroy();
6897 // Release references to children, device context, toolkit, and app shell.
6898 nsBaseWidget::OnDestroy();
6900 // Clear our native parent handle.
6901 // XXX Windows will take care of this in the proper order, and SetParent(nsnull)'s
6902 // remove child on the parent already took place in nsBaseWidget's Destroy call above.
6903 //SetParent(nsnull);
6906 // We have to destroy the native drag target before we null out our window pointer.
6907 EnableDragDrop(PR_FALSE
);
6909 // If we're going away and for some reason we're still the rollup widget, rollup and
6910 // turn off capture.
6911 if ( this == sRollupWidget
) {
6912 if ( sRollupListener
)
6913 sRollupListener
->Rollup(nsnull
, nsnull
);
6914 CaptureRollupEvents(nsnull
, nsnull
, PR_FALSE
, PR_TRUE
);
6917 // If IME is disabled, restore it.
6919 mOldIMC
= ::ImmAssociateContext(mWnd
, mOldIMC
);
6920 NS_ASSERTION(!mOldIMC
, "Another IMC was associated");
6923 // Turn off mouse trails if enabled.
6924 MouseTrailer
* mtrailer
= nsToolkit::gMouseTrailer
;
6926 if (mtrailer
->GetMouseTrailerWindow() == mWnd
)
6927 mtrailer
->DestroyTimer();
6929 if (mtrailer
->GetCaptureWindow() == mWnd
)
6930 mtrailer
->SetCaptureWindow(nsnull
);
6933 // Free GDI window class objects
6935 VERIFY(::DeleteObject(mBrush
));
6939 // Free app icon resources.
6941 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
) 0);
6943 ::DestroyIcon(icon
);
6945 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
) 0);
6947 ::DestroyIcon(icon
);
6949 // Destroy any custom cursor resources.
6951 SetCursor(eCursor_standard
);
6954 // Reset transparency
6955 if (eTransparencyTransparent
== mTransparencyMode
)
6956 SetupTranslucentWindowMemoryBitmap(eTransparencyOpaque
);
6959 #if defined(WINCE_HAVE_SOFTKB)
6960 // Revert the changes made for the software keyboard settings
6961 nsWindowCE::ResetSoftKB(mWnd
);
6965 // Finalize panning feedback to possibly restore window displacement
6966 mGesture
.PanFeedbackFinalize(mWnd
, PR_TRUE
);
6969 // Clear the main HWND.
6974 PRBool
nsWindow::OnMove(PRInt32 aX
, PRInt32 aY
)
6979 nsGUIEvent
event(PR_TRUE
, NS_MOVE
, this);
6981 event
.refPoint
.x
= aX
;
6982 event
.refPoint
.y
= aY
;
6984 return DispatchWindowEvent(&event
);
6987 // Send a resize message to the listener
6988 PRBool
nsWindow::OnResize(nsIntRect
&aWindowRect
)
6990 #ifdef CAIRO_HAS_D2D_SURFACE
6991 if (mD2DWindowSurface
) {
6992 mD2DWindowSurface
= NULL
;
6993 Invalidate(PR_FALSE
);
6996 // call the event callback
6997 if (mEventCallback
) {
6998 nsSizeEvent
event(PR_TRUE
, NS_SIZE
, this);
7000 event
.windowSize
= &aWindowRect
;
7002 if (::GetWindowRect(mWnd
, &r
)) {
7003 event
.mWinWidth
= PRInt32(r
.right
- r
.left
);
7004 event
.mWinHeight
= PRInt32(r
.bottom
- r
.top
);
7006 event
.mWinWidth
= 0;
7007 event
.mWinHeight
= 0;
7011 printf("[%X] OnResize: client:(%d x %d x %d x %d) window:(%d x %d)\n", this,
7012 aWindowRect
.x
, aWindowRect
.y
, aWindowRect
.width
, aWindowRect
.height
,
7013 event
.mWinWidth
, event
.mWinHeight
);
7016 return DispatchWindowEvent(&event
);
7022 #if !defined(WINCE) // implemented in nsWindowCE.cpp
7023 PRBool
nsWindow::OnHotKey(WPARAM wParam
, LPARAM lParam
)
7027 #endif // !defined(WINCE)
7029 void nsWindow::OnSettingsChange(WPARAM wParam
, LPARAM lParam
)
7031 if (mWindowType
== eWindowType_dialog
||
7032 mWindowType
== eWindowType_toplevel
)
7033 nsWindowGfx::OnSettingsChangeGfx(wParam
);
7036 static PRBool
IsOurProcessWindow(HWND aHWND
)
7038 DWORD processId
= 0;
7039 ::GetWindowThreadProcessId(aHWND
, &processId
);
7040 return processId
== ::GetCurrentProcessId();
7043 static HWND
FindOurProcessWindow(HWND aHWND
)
7045 for (HWND wnd
= ::GetParent(aHWND
); wnd
; wnd
= ::GetParent(wnd
)) {
7046 if (IsOurProcessWindow(wnd
)) {
7053 // Scrolling helper function for handling plugins.
7054 // Return value indicates whether the calling function should handle this
7055 // aHandled indicates whether this was handled at all
7056 // aQuitProcessing tells whether or not to continue processing the message
7057 PRBool
nsWindow::HandleScrollingPlugins(UINT aMsg
, WPARAM aWParam
,
7058 LPARAM aLParam
, PRBool
& aHandled
,
7060 PRBool
& aQuitProcessing
)
7062 // The scroll event will be dispatched to the toplevel
7063 // window. We need to give it to the child window
7064 aQuitProcessing
= PR_FALSE
; // default is to not stop processing
7066 DWORD dwPoints
= ::GetMessagePos();
7067 point
.x
= GET_X_LPARAM(dwPoints
);
7068 point
.y
= GET_Y_LPARAM(dwPoints
);
7070 static PRBool sIsProcessing
= PR_FALSE
;
7071 if (sIsProcessing
) {
7072 return PR_TRUE
; // the caller should handle this.
7075 static PRBool sMayBeUsingLogitechMouse
= PR_FALSE
;
7076 if (aMsg
== WM_MOUSEHWHEEL
) {
7077 // Logitech (Logicool) mouse driver (confirmed with 4.82.11 and MX-1100)
7078 // always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs one
7079 // message at first time, this time, ::GetMessagePos works fine.
7080 // Then, we will return 0 (0 means we process it) to the message. Then, the
7081 // driver will POST the same messages continuously during the wheel tilted.
7082 // But ::GetMessagePos API always returns (0, 0), even if the actual mouse
7083 // cursor isn't 0,0. Therefore, we cannot trust the result of
7084 // ::GetMessagePos API if the sender is the driver.
7085 if (!sMayBeUsingLogitechMouse
&& aLParam
== 0 && (DWORD
)aLParam
!= dwPoints
&&
7086 ::InSendMessage()) {
7087 sMayBeUsingLogitechMouse
= PR_TRUE
;
7088 } else if (sMayBeUsingLogitechMouse
&& aLParam
!= 0 && ::InSendMessage()) {
7089 // The user has changed the mouse from Logitech's to another one (e.g.,
7090 // the user has changed to the touchpad of the notebook.
7091 sMayBeUsingLogitechMouse
= PR_FALSE
;
7093 // If the WM_MOUSEHWHEEL comes from Logitech's mouse driver, and the
7094 // ::GetMessagePos isn't correct, probably, we should use ::GetCursorPos
7096 if (sMayBeUsingLogitechMouse
&& aLParam
== 0 && dwPoints
== 0) {
7097 ::GetCursorPos(&point
);
7101 HWND destWnd
= ::WindowFromPoint(point
);
7102 // Since we receive scroll events for as long as
7103 // we are focused, it's entirely possible that there
7104 // is another app's window or no window under the
7108 // No window is under the pointer
7109 return PR_FALSE
; // break, but continue processing
7112 nsWindow
* destWindow
;
7114 // We don't handle the message if the found window belongs to another
7115 // process's top window. If it belongs window, that is a plug-in's window.
7116 // Then, we need to send the message to the plug-in window.
7117 if (!IsOurProcessWindow(destWnd
)) {
7118 HWND ourPluginWnd
= FindOurProcessWindow(destWnd
);
7119 if (!ourPluginWnd
) {
7120 // Somebody elses window
7121 return PR_FALSE
; // break, but continue processing
7123 destWindow
= GetNSWindowPtr(ourPluginWnd
);
7125 destWindow
= GetNSWindowPtr(destWnd
);
7128 if (destWindow
== this && mWindowType
== eWindowType_plugin
) {
7129 // If this is plug-in window, the message came from the plug-in window.
7130 // Then, the message should be processed on the parent window.
7131 destWindow
= static_cast<nsWindow
*>(GetParent());
7132 NS_ENSURE_TRUE(destWindow
, PR_FALSE
); // break, but continue processing
7133 destWnd
= destWindow
->mWnd
;
7134 NS_ENSURE_TRUE(destWnd
, PR_FALSE
); // break, but continue processing
7137 if (!destWindow
|| destWindow
->mWindowType
== eWindowType_plugin
) {
7138 // Some other app, or a plugin window.
7139 // Windows directs scrolling messages to the focused window.
7140 // However, Mozilla does not like plugins having focus, so a
7141 // Mozilla window (ie, the plugin's parent (us!) has focus.)
7142 // Therefore, plugins etc _should_ get first grab at the
7143 // message, but this focus vaguary means the plugin misses
7144 // out. If the window is a child of ours, forward it on.
7145 // Determine if a child by walking the parent list until
7146 // we find a parent matching our wndproc.
7147 HWND parentWnd
= ::GetParent(destWnd
);
7149 nsWindow
* parentWindow
= GetNSWindowPtr(parentWnd
);
7151 // We have a child window - quite possibly a plugin window.
7152 // However, not all plugins are created equal - some will handle this
7153 // message themselves, some will forward directly back to us, while
7154 // others will call DefWndProc, which itself still forwards back to us.
7155 // So if we have sent it once, we need to handle it ourself.
7158 // XXX The message shouldn't come from the plugin window at here.
7159 // But the message might come from it due to some bugs. If it happens,
7160 // SendMessage causes deadlock. For safety, we should unlock the
7162 ::ReplyMessage(aMsg
== WM_MOUSEHWHEEL
? TRUE
: 0);
7165 // First time we have seen this message.
7166 // Call the child - either it will consume it, or
7167 // it will wind it's way back to us,triggering the destWnd case above
7168 // either way,when the call returns,we are all done with the message,
7169 sIsProcessing
= PR_TRUE
;
7170 ::SendMessageW(destWnd
, aMsg
, aWParam
, aLParam
);
7171 sIsProcessing
= PR_FALSE
;
7173 aQuitProcessing
= PR_TRUE
;
7174 return PR_FALSE
; // break, and stop processing
7176 parentWnd
= ::GetParent(parentWnd
);
7177 } // while parentWnd
7179 if (destWnd
== nsnull
)
7181 if (destWnd
!= mWnd
) {
7183 sIsProcessing
= PR_TRUE
;
7184 aHandled
= destWindow
->ProcessMessage(aMsg
, aWParam
, aLParam
, aRetValue
);
7185 sIsProcessing
= PR_FALSE
;
7186 aQuitProcessing
= PR_TRUE
;
7187 return PR_FALSE
; // break, and stop processing
7191 printf("WARNING: couldn't get child window for SCROLL event\n");
7194 return PR_TRUE
; // caller should handle this
7197 PRBool
nsWindow::OnScroll(UINT aMsg
, WPARAM aWParam
, LPARAM aLParam
)
7199 static PRInt8 sMouseWheelEmulation
= -1;
7200 if (sMouseWheelEmulation
< 0) {
7201 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
7202 NS_ENSURE_TRUE(prefs
, PR_FALSE
);
7203 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
7204 prefs
->GetBranch(0, getter_AddRefs(prefBranch
));
7205 NS_ENSURE_TRUE(prefBranch
, PR_FALSE
);
7208 prefBranch
->GetBoolPref("mousewheel.emulate_at_wm_scroll", &emulate
);
7209 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
7210 sMouseWheelEmulation
= PRInt8(emulate
);
7213 if (aLParam
|| sMouseWheelEmulation
) {
7214 // Scroll message generated by Thinkpad Trackpoint Driver or similar
7215 // Treat as a mousewheel message and scroll appropriately
7216 PRBool quit
, result
;
7219 if (!HandleScrollingPlugins(aMsg
, aWParam
, aLParam
, result
, &retVal
, quit
))
7220 return quit
; // Return if it's not our message or has been dispatched
7222 nsMouseScrollEvent
scrollevent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
7223 scrollevent
.scrollFlags
= (aMsg
== WM_VSCROLL
)
7224 ? nsMouseScrollEvent::kIsVertical
7225 : nsMouseScrollEvent::kIsHorizontal
;
7226 switch (LOWORD(aWParam
))
7229 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
7231 scrollevent
.delta
= 1;
7234 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
7236 scrollevent
.delta
= -1;
7242 // The event may go to a plug-in which already dispatched this message.
7243 // Then, the event can cause deadlock. We should unlock the sender here.
7246 scrollevent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
7247 scrollevent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
7248 scrollevent
.isMeta
= PR_FALSE
;
7249 scrollevent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
7250 InitEvent(scrollevent
);
7251 if (nsnull
!= mEventCallback
)
7253 DispatchWindowEvent(&scrollevent
);
7258 // Scroll message generated by external application
7259 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_SCROLL
, this);
7261 command
.mScroll
.mIsHorizontal
= (aMsg
== WM_HSCROLL
);
7263 switch (LOWORD(aWParam
))
7265 case SB_LINEUP
: // SB_LINELEFT
7266 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Line
;
7267 command
.mScroll
.mAmount
= -1;
7269 case SB_LINEDOWN
: // SB_LINERIGHT
7270 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Line
;
7271 command
.mScroll
.mAmount
= 1;
7273 case SB_PAGEUP
: // SB_PAGELEFT
7274 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Page
;
7275 command
.mScroll
.mAmount
= -1;
7277 case SB_PAGEDOWN
: // SB_PAGERIGHT
7278 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Page
;
7279 command
.mScroll
.mAmount
= 1;
7281 case SB_TOP
: // SB_LEFT
7282 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Whole
;
7283 command
.mScroll
.mAmount
= -1;
7285 case SB_BOTTOM
: // SB_RIGHT
7286 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Whole
;
7287 command
.mScroll
.mAmount
= 1;
7292 DispatchWindowEvent(&command
);
7296 // Can be overriden. Controls auto-erase of background.
7297 PRBool
nsWindow::AutoErase(HDC dc
)
7302 /**************************************************************
7303 **************************************************************
7305 ** BLOCK: IME management and accessibility
7307 ** Handles managing IME input and accessibility.
7309 **************************************************************
7310 **************************************************************/
7312 NS_IMETHODIMP
nsWindow::ResetInputState()
7314 #ifdef DEBUG_KBSTATE
7315 printf("ResetInputState\n");
7318 #ifdef NS_ENABLE_TSF
7319 nsTextStore::CommitComposition(PR_FALSE
);
7320 #endif //NS_ENABLE_TSF
7322 nsIMM32Handler::CommitComposition(this);
7326 NS_IMETHODIMP
nsWindow::SetIMEOpenState(PRBool aState
)
7328 #ifdef DEBUG_KBSTATE
7329 printf("SetIMEOpenState %s\n", (aState
? "Open" : "Close"));
7332 #ifdef NS_ENABLE_TSF
7333 nsTextStore::SetIMEOpenState(aState
);
7334 #endif //NS_ENABLE_TSF
7336 nsIMEContext
IMEContext(mWnd
);
7337 if (IMEContext
.IsValid()) {
7338 ::ImmSetOpenStatus(IMEContext
.get(), aState
? TRUE
: FALSE
);
7343 NS_IMETHODIMP
nsWindow::GetIMEOpenState(PRBool
* aState
)
7345 nsIMEContext
IMEContext(mWnd
);
7346 if (IMEContext
.IsValid()) {
7347 BOOL isOpen
= ::ImmGetOpenStatus(IMEContext
.get());
7348 *aState
= isOpen
? PR_TRUE
: PR_FALSE
;
7352 #ifdef NS_ENABLE_TSF
7353 *aState
|= nsTextStore::GetIMEOpenState();
7354 #endif //NS_ENABLE_TSF
7359 NS_IMETHODIMP
nsWindow::SetIMEEnabled(PRUint32 aState
)
7361 #ifdef NS_ENABLE_TSF
7362 nsTextStore::SetIMEEnabled(aState
);
7363 #endif //NS_ENABLE_TSF
7364 #ifdef DEBUG_KBSTATE
7365 printf("SetIMEEnabled: %s\n", (aState
== nsIWidget::IME_STATUS_ENABLED
||
7366 aState
== nsIWidget::IME_STATUS_PLUGIN
)?
7367 "Enabled": "Disabled");
7369 if (nsIMM32Handler::IsComposing()) {
7372 mIMEEnabled
= aState
;
7373 PRBool enable
= (aState
== nsIWidget::IME_STATUS_ENABLED
||
7374 aState
== nsIWidget::IME_STATUS_PLUGIN
);
7376 #if defined(WINCE_HAVE_SOFTKB)
7377 sSoftKeyboardState
= (aState
!= nsIWidget::IME_STATUS_DISABLED
);
7378 nsWindowCE::ToggleSoftKB(mWnd
, sSoftKeyboardState
);
7381 if (!enable
!= !mOldIMC
)
7383 mOldIMC
= ::ImmAssociateContext(mWnd
, enable
? mOldIMC
: NULL
);
7384 NS_ASSERTION(!enable
|| !mOldIMC
, "Another IMC was associated");
7389 NS_IMETHODIMP
nsWindow::GetIMEEnabled(PRUint32
* aState
)
7391 #ifdef DEBUG_KBSTATE
7392 printf("GetIMEEnabled: %s\n", mIMEEnabled
? "Enabled": "Disabled");
7394 *aState
= mIMEEnabled
;
7398 NS_IMETHODIMP
nsWindow::CancelIMEComposition()
7400 #ifdef DEBUG_KBSTATE
7401 printf("CancelIMEComposition\n");
7404 #ifdef NS_ENABLE_TSF
7405 nsTextStore::CommitComposition(PR_TRUE
);
7406 #endif //NS_ENABLE_TSF
7408 nsIMM32Handler::CancelComposition(this);
7413 nsWindow::GetToggledKeyState(PRUint32 aKeyCode
, PRBool
* aLEDState
)
7415 #ifdef DEBUG_KBSTATE
7416 printf("GetToggledKeyState\n");
7418 NS_ENSURE_ARG_POINTER(aLEDState
);
7419 *aLEDState
= (::GetKeyState(aKeyCode
) & 1) != 0;
7423 #ifdef NS_ENABLE_TSF
7425 nsWindow::OnIMEFocusChange(PRBool aFocus
)
7427 nsresult rv
= nsTextStore::OnFocusChange(aFocus
, this, mIMEEnabled
);
7428 if (rv
== NS_ERROR_NOT_AVAILABLE
)
7429 rv
= NS_ERROR_NOT_IMPLEMENTED
; // TSF is not enabled, maybe.
7434 nsWindow::OnIMETextChange(PRUint32 aStart
,
7438 return nsTextStore::OnTextChange(aStart
, aOldEnd
, aNewEnd
);
7442 nsWindow::OnIMESelectionChange(void)
7444 return nsTextStore::OnSelectionChange();
7446 #endif //NS_ENABLE_TSF
7448 #ifdef ACCESSIBILITY
7450 #ifdef DEBUG_WMGETOBJECT
7451 #define NS_LOG_WMGETOBJECT_WNDACC(aWnd) \
7452 nsAccessible* acc = aWnd ? \
7453 aWnd->DispatchAccessibleEvent(NS_GETACCESSIBLE) : nsnull; \
7454 printf(" acc: %p", acc); \
7456 nsAutoString name; \
7457 acc->GetName(name); \
7458 printf(", accname: %s", NS_ConvertUTF16toUTF8(name).get()); \
7459 nsCOMPtr<nsIAccessibleDocument> doc = do_QueryObject(acc); \
7460 void *hwnd = nsnull; \
7461 doc->GetWindowHandle(&hwnd); \
7462 printf(", acc hwnd: %d", hwnd); \
7465 #define NS_LOG_WMGETOBJECT_THISWND \
7467 printf("\n*******Get Doc Accessible*******\nOrig Window: "); \
7468 printf("\n {\n HWND: %d, parent HWND: %d, wndobj: %p, content type: %d,\n",\
7469 mWnd, ::GetParent(mWnd), this, mContentType); \
7470 NS_LOG_WMGETOBJECT_WNDACC(this) \
7474 #define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd) \
7476 nsWindow* wnd = GetNSWindowPtr(aHwnd); \
7477 printf("Get " aMsg ":\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n", \
7478 aHwnd, ::GetParent(aHwnd), wnd); \
7479 NS_LOG_WMGETOBJECT_WNDACC(wnd); \
7483 #define NS_LOG_WMGETOBJECT_THISWND
7484 #define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd)
7485 #endif // DEBUG_WMGETOBJECT
7488 nsWindow::GetRootAccessible()
7490 // We want the ability to forcibly disable a11y on windows, because
7491 // some non-a11y-related components attempt to bring it up. See bug
7492 // 538530 for details; we have a pref here that allows it to be disabled
7493 // for performance and testing resons.
7495 // This pref is checked only once, and the browser needs a restart to
7496 // pick up any changes.
7497 static int accForceDisable
= -1;
7499 if (accForceDisable
== -1) {
7500 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
7501 PRBool b
= PR_FALSE
;
7502 nsresult rv
= prefs
->GetBoolPref("accessibility.win32.force_disabled", &b
);
7503 if (NS_SUCCEEDED(rv
) && b
) {
7504 accForceDisable
= 1;
7506 accForceDisable
= 0;
7510 // If the pref was true, return null here, disabling a11y.
7511 if (accForceDisable
)
7514 nsWindow::sIsAccessibilityOn
= TRUE
;
7516 if (mInDtor
|| mOnDestroyCalled
|| mWindowType
== eWindowType_invisible
) {
7520 NS_LOG_WMGETOBJECT_THISWND
7522 if (mContentType
!= eContentTypeInherit
) {
7523 // We're on a MozillaContentWindowClass or MozillaUIWindowClass window.
7524 // Search for the correct visible child window to get an accessible
7525 // document from. Make sure to use an active child window. If this window
7526 // doesn't have child windows then return an accessible for it.
7527 HWND accessibleWnd
= ::GetTopWindow(mWnd
);
7528 NS_LOG_WMGETOBJECT_WND("Top Window", accessibleWnd
);
7529 if (!accessibleWnd
) {
7530 NS_LOG_WMGETOBJECT_WND("This Window", mWnd
);
7531 return DispatchAccessibleEvent(NS_GETACCESSIBLE
);
7534 nsWindow
* accessibleWindow
= nsnull
;
7535 while (accessibleWnd
) {
7536 // Loop through windows and find the first one with accessibility info
7537 accessibleWindow
= GetNSWindowPtr(accessibleWnd
);
7538 if (accessibleWindow
) {
7539 nsAccessible
*rootAccessible
=
7540 accessibleWindow
->DispatchAccessibleEvent(NS_GETACCESSIBLE
);
7541 if (rootAccessible
) {
7542 // Success, one of the child windows was active.
7543 return rootAccessible
;
7546 accessibleWnd
= ::GetNextWindow(accessibleWnd
, GW_HWNDNEXT
);
7547 NS_LOG_WMGETOBJECT_WND("Next Window", accessibleWnd
);
7552 NS_LOG_WMGETOBJECT_WND("This Window", mWnd
);
7553 return DispatchAccessibleEvent(NS_GETACCESSIBLE
);
7556 STDMETHODIMP_(LRESULT
)
7557 nsWindow::LresultFromObject(REFIID riid
, WPARAM wParam
, LPUNKNOWN pAcc
)
7559 // open the dll dynamically
7561 sAccLib
=::LoadLibraryW(L
"OLEACC.DLL");
7564 if (!sLresultFromObject
)
7565 sLresultFromObject
= (LPFNLRESULTFROMOBJECT
)GetProcAddress(sAccLib
,"LresultFromObject");
7567 if (sLresultFromObject
)
7568 return sLresultFromObject(riid
,wParam
,pAcc
);
7575 /**************************************************************
7576 **************************************************************
7578 ** BLOCK: Transparency
7580 ** Window transparency helpers.
7582 **************************************************************
7583 **************************************************************/
7587 void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth
, PRInt32 aNewHeight
, PRBool force
)
7589 if (!force
&& aNewWidth
== mBounds
.width
&& aNewHeight
== mBounds
.height
)
7592 #ifdef CAIRO_HAS_D2D_SURFACE
7593 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
7594 gfxWindowsPlatform::RENDER_DIRECT2D
) {
7595 nsRefPtr
<gfxD2DSurface
> newSurface
=
7596 new gfxD2DSurface(gfxIntSize(aNewWidth
, aNewHeight
), gfxASurface::ImageFormatARGB32
);
7597 mTransparentSurface
= newSurface
;
7602 nsRefPtr
<gfxWindowsSurface
> newSurface
=
7603 new gfxWindowsSurface(gfxIntSize(aNewWidth
, aNewHeight
), gfxASurface::ImageFormatARGB32
);
7604 mTransparentSurface
= newSurface
;
7605 mMemoryDC
= newSurface
->GetDC();
7609 void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode
)
7613 if (aMode
== mTransparencyMode
)
7616 // stop on dialogs and popups!
7617 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
7618 nsWindow
* parent
= GetNSWindowPtr(hWnd
);
7622 NS_WARNING("Trying to use transparent chrome in an embedded context");
7626 if (parent
!= this) {
7627 NS_WARNING("Setting SetWindowTranslucencyInner on a parent this is not us!");
7630 if (aMode
== eTransparencyTransparent
) {
7631 // If we're switching to the use of a transparent window, hide the chrome
7633 HideWindowChrome(PR_TRUE
);
7634 } else if (mHideChrome
&& mTransparencyMode
== eTransparencyTransparent
) {
7635 // if we're switching out of transparent, re-enable our parent's chrome.
7636 HideWindowChrome(PR_FALSE
);
7639 LONG_PTR style
= ::GetWindowLongPtrW(hWnd
, GWL_STYLE
),
7640 exStyle
= ::GetWindowLongPtr(hWnd
, GWL_EXSTYLE
);
7642 if (parent
->mIsVisible
)
7643 style
|= WS_VISIBLE
;
7644 if (parent
->mSizeMode
== nsSizeMode_Maximized
)
7645 style
|= WS_MAXIMIZE
;
7646 else if (parent
->mSizeMode
== nsSizeMode_Minimized
)
7647 style
|= WS_MINIMIZE
;
7649 if (aMode
== eTransparencyTransparent
)
7650 exStyle
|= WS_EX_LAYERED
;
7652 exStyle
&= ~WS_EX_LAYERED
;
7654 VERIFY_WINDOW_STYLE(style
);
7655 ::SetWindowLongPtrW(hWnd
, GWL_STYLE
, style
);
7656 ::SetWindowLongPtrW(hWnd
, GWL_EXSTYLE
, exStyle
);
7658 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
7660 memset(&mGlassMargins
, 0, sizeof mGlassMargins
);
7661 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
7662 mTransparencyMode
= aMode
;
7664 SetupTranslucentWindowMemoryBitmap(aMode
);
7666 #endif // #ifndef WINCE
7669 void nsWindow::SetupTranslucentWindowMemoryBitmap(nsTransparencyMode aMode
)
7671 if (eTransparencyTransparent
== aMode
) {
7672 ResizeTranslucentWindow(mBounds
.width
, mBounds
.height
, PR_TRUE
);
7674 mTransparentSurface
= nsnull
;
7679 nsresult
nsWindow::UpdateTranslucentWindow()
7682 if (mBounds
.IsEmpty())
7687 BLENDFUNCTION bf
= { AC_SRC_OVER
, 0, 255, AC_SRC_ALPHA
};
7688 SIZE winSize
= { mBounds
.width
, mBounds
.height
};
7689 POINT srcPos
= { 0, 0 };
7690 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
7692 ::GetWindowRect(hWnd
, &winRect
);
7694 #ifdef CAIRO_HAS_D2D_SURFACE
7695 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
7696 gfxWindowsPlatform::RENDER_DIRECT2D
) {
7697 mMemoryDC
= static_cast<gfxD2DSurface
*>(mTransparentSurface
.get())->
7701 // perform the alpha blend
7702 PRBool updateSuccesful
=
7703 ::UpdateLayeredWindow(hWnd
, NULL
, (POINT
*)&winRect
, &winSize
, mMemoryDC
, &srcPos
, 0, &bf
, ULW_ALPHA
);
7705 #ifdef CAIRO_HAS_D2D_SURFACE
7706 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
7707 gfxWindowsPlatform::RENDER_DIRECT2D
) {
7708 nsIntRect
r(0, 0, 0, 0);
7709 static_cast<gfxD2DSurface
*>(mTransparentSurface
.get())->ReleaseDC(&r
);
7713 if (!updateSuccesful
) {
7714 return NS_ERROR_FAILURE
;
7723 /**************************************************************
7724 **************************************************************
7726 ** BLOCK: Popup rollup hooks
7728 ** Deals with CaptureRollup on popup windows.
7730 **************************************************************
7731 **************************************************************/
7734 // Schedules a timer for a window, so we can rollup after processing the hook event
7735 void nsWindow::ScheduleHookTimer(HWND aWnd
, UINT aMsgId
)
7737 // In some cases multiple hooks may be scheduled
7738 // so ignore any other requests once one timer is scheduled
7739 if (sHookTimerId
== 0) {
7740 // Remember the window handle and the message ID to be used later
7741 sRollupMsgId
= aMsgId
;
7742 sRollupMsgWnd
= aWnd
;
7743 // Schedule native timer for doing the rollup after
7744 // this event is done being processed
7745 sHookTimerId
= ::SetTimer(NULL
, 0, 0, (TIMERPROC
)HookTimerForPopups
);
7746 NS_ASSERTION(sHookTimerId
, "Timer couldn't be created.");
7750 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7751 int gLastMsgCode
= 0;
7752 extern MSGFEventMsgInfo gMSGFEvents
[];
7755 // Process Menu messages, rollup when popup is clicked.
7756 LRESULT CALLBACK
nsWindow::MozSpecialMsgFilter(int code
, WPARAM wParam
, LPARAM lParam
)
7758 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7760 MSG
* pMsg
= (MSG
*)lParam
;
7763 while (gMSGFEvents
[inx
].mId
!= code
&& gMSGFEvents
[inx
].mStr
!= NULL
) {
7766 if (code
!= gLastMsgCode
) {
7767 if (gMSGFEvents
[inx
].mId
== code
) {
7769 printf("MozSpecialMessageProc - code: 0x%X - %s hw: %p\n", code
, gMSGFEvents
[inx
].mStr
, pMsg
->hwnd
);
7773 printf("MozSpecialMessageProc - code: 0x%X - %d hw: %p\n", code
, gMSGFEvents
[inx
].mId
, pMsg
->hwnd
);
7776 gLastMsgCode
= code
;
7778 PrintEvent(pMsg
->message
, FALSE
, FALSE
);
7780 #endif // #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7782 if (sProcessHook
&& code
== MSGF_MENU
) {
7783 MSG
* pMsg
= (MSG
*)lParam
;
7784 ScheduleHookTimer( pMsg
->hwnd
, pMsg
->message
);
7787 return ::CallNextHookEx(sMsgFilterHook
, code
, wParam
, lParam
);
7790 // Process all mouse messages. Roll up when a click is in a native window
7791 // that doesn't have an nsIWidget.
7792 LRESULT CALLBACK
nsWindow::MozSpecialMouseProc(int code
, WPARAM wParam
, LPARAM lParam
)
7796 case WM_LBUTTONDOWN
:
7797 case WM_RBUTTONDOWN
:
7798 case WM_MBUTTONDOWN
:
7800 case WM_MOUSEHWHEEL
:
7802 MOUSEHOOKSTRUCT
* ms
= (MOUSEHOOKSTRUCT
*)lParam
;
7803 nsIWidget
* mozWin
= (nsIWidget
*)GetNSWindowPtr(ms
->hwnd
);
7805 // If this window is windowed plugin window, the mouse events are not
7807 if (static_cast<nsWindow
*>(mozWin
)->mWindowType
== eWindowType_plugin
)
7808 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
7810 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
7816 return ::CallNextHookEx(sCallMouseHook
, code
, wParam
, lParam
);
7819 // Process all messages. Roll up when the window is moving, or
7820 // is resizing or when maximized or mininized.
7821 LRESULT CALLBACK
nsWindow::MozSpecialWndProc(int code
, WPARAM wParam
, LPARAM lParam
)
7823 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7825 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
7826 PrintEvent(cwpt
->message
, FALSE
, FALSE
);
7831 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
7832 if (cwpt
->message
== WM_MOVING
||
7833 cwpt
->message
== WM_SIZING
||
7834 cwpt
->message
== WM_GETMINMAXINFO
) {
7835 ScheduleHookTimer(cwpt
->hwnd
, (UINT
)cwpt
->message
);
7839 return ::CallNextHookEx(sCallProcHook
, code
, wParam
, lParam
);
7842 // Register the special "hooks" for dropdown processing.
7843 void nsWindow::RegisterSpecialDropdownHooks()
7845 NS_ASSERTION(!sMsgFilterHook
, "sMsgFilterHook must be NULL!");
7846 NS_ASSERTION(!sCallProcHook
, "sCallProcHook must be NULL!");
7848 DISPLAY_NMM_PRT("***************** Installing Msg Hooks ***************\n");
7850 //HMODULE hMod = GetModuleHandle("gkwidget.dll");
7852 // Install msg hook for moving the window and resizing
7853 if (!sMsgFilterHook
) {
7854 DISPLAY_NMM_PRT("***** Hooking sMsgFilterHook!\n");
7855 sMsgFilterHook
= SetWindowsHookEx(WH_MSGFILTER
, MozSpecialMsgFilter
, NULL
, GetCurrentThreadId());
7856 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7857 if (!sMsgFilterHook
) {
7858 printf("***** SetWindowsHookEx is NOT installed for WH_MSGFILTER!\n");
7863 // Install msg hook for menus
7864 if (!sCallProcHook
) {
7865 DISPLAY_NMM_PRT("***** Hooking sCallProcHook!\n");
7866 sCallProcHook
= SetWindowsHookEx(WH_CALLWNDPROC
, MozSpecialWndProc
, NULL
, GetCurrentThreadId());
7867 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7868 if (!sCallProcHook
) {
7869 printf("***** SetWindowsHookEx is NOT installed for WH_CALLWNDPROC!\n");
7874 // Install msg hook for the mouse
7875 if (!sCallMouseHook
) {
7876 DISPLAY_NMM_PRT("***** Hooking sCallMouseHook!\n");
7877 sCallMouseHook
= SetWindowsHookEx(WH_MOUSE
, MozSpecialMouseProc
, NULL
, GetCurrentThreadId());
7878 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7879 if (!sCallMouseHook
) {
7880 printf("***** SetWindowsHookEx is NOT installed for WH_MOUSE!\n");
7886 // Unhook special message hooks for dropdowns.
7887 void nsWindow::UnregisterSpecialDropdownHooks()
7889 DISPLAY_NMM_PRT("***************** De-installing Msg Hooks ***************\n");
7891 if (sCallProcHook
) {
7892 DISPLAY_NMM_PRT("***** Unhooking sCallProcHook!\n");
7893 if (!::UnhookWindowsHookEx(sCallProcHook
)) {
7894 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallProcHook!\n");
7896 sCallProcHook
= NULL
;
7899 if (sMsgFilterHook
) {
7900 DISPLAY_NMM_PRT("***** Unhooking sMsgFilterHook!\n");
7901 if (!::UnhookWindowsHookEx(sMsgFilterHook
)) {
7902 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sMsgFilterHook!\n");
7904 sMsgFilterHook
= NULL
;
7907 if (sCallMouseHook
) {
7908 DISPLAY_NMM_PRT("***** Unhooking sCallMouseHook!\n");
7909 if (!::UnhookWindowsHookEx(sCallMouseHook
)) {
7910 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallMouseHook!\n");
7912 sCallMouseHook
= NULL
;
7916 // This timer is designed to only fire one time at most each time a "hook" function
7917 // is used to rollup the dropdown. In some cases, the timer may be scheduled from the
7918 // hook, but that hook event or a subsequent event may roll up the dropdown before
7919 // this timer function is executed.
7921 // For example, if an MFC control takes focus, the combobox will lose focus and rollup
7922 // before this function fires.
7923 VOID CALLBACK
nsWindow::HookTimerForPopups(HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
7925 if (sHookTimerId
!= 0) {
7926 // if the window is NULL then we need to use the ID to kill the timer
7927 BOOL status
= ::KillTimer(NULL
, sHookTimerId
);
7928 NS_ASSERTION(status
, "Hook Timer was not killed.");
7932 if (sRollupMsgId
!= 0) {
7933 // Note: DealWithPopups does the check to make sure that
7934 // sRollupListener and sRollupWidget are not NULL
7935 LRESULT popupHandlingResult
;
7936 nsAutoRollup autoRollup
;
7937 DealWithPopups(sRollupMsgWnd
, sRollupMsgId
, 0, 0, &popupHandlingResult
);
7939 sRollupMsgWnd
= NULL
;
7944 BOOL CALLBACK
nsWindow::ClearResourcesCallback(HWND aWnd
, LPARAM aMsg
)
7946 nsWindow
*window
= nsWindow::GetNSWindowPtr(aWnd
);
7948 window
->ClearCachedResources();
7954 nsWindow::ClearCachedResources()
7956 #ifdef CAIRO_HAS_D2D_SURFACE
7957 mD2DWindowSurface
= nsnull
;
7959 if (mLayerManager
&&
7960 mLayerManager
->GetBackendType() == LayerManager::LAYERS_BASIC
) {
7961 static_cast<BasicLayerManager
*>(mLayerManager
.get())->
7962 ClearCachedResources();
7964 ::EnumChildWindows(mWnd
, nsWindow::ClearResourcesCallback
, NULL
);
7967 static PRBool
IsDifferentThreadWindow(HWND aWnd
)
7969 return ::GetCurrentThreadId() != ::GetWindowThreadProcessId(aWnd
, NULL
);
7973 nsWindow::EventIsInsideWindow(UINT Msg
, nsWindow
* aWindow
)
7978 if (Msg
== WM_ACTIVATEAPP
)
7979 // don't care about activation/deactivation
7982 if (Msg
== WM_ACTIVATE
)
7983 // but on Windows CE we do care about
7984 // activation/deactivation because there doesn't exist
7985 // cancelable Mouse Activation events
7989 ::GetWindowRect(aWindow
->mWnd
, &r
);
7990 DWORD pos
= ::GetMessagePos();
7992 mp
.x
= GET_X_LPARAM(pos
);
7993 mp
.y
= GET_Y_LPARAM(pos
);
7995 // was the event inside this window?
7996 return (PRBool
) PtInRect(&r
, mp
);
7999 // Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
8001 nsWindow::DealWithPopups(HWND inWnd
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
, LRESULT
* outResult
)
8003 if (sRollupListener
&& sRollupWidget
&& ::IsWindowVisible(inWnd
)) {
8005 if (inMsg
== WM_LBUTTONDOWN
|| inMsg
== WM_RBUTTONDOWN
|| inMsg
== WM_MBUTTONDOWN
||
8006 inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
|| inMsg
== WM_ACTIVATE
||
8007 (inMsg
== WM_KILLFOCUS
&& IsDifferentThreadWindow((HWND
)inWParam
))
8010 inMsg
== WM_NCRBUTTONDOWN
||
8011 inMsg
== WM_MOVING
||
8012 inMsg
== WM_SIZING
||
8013 inMsg
== WM_NCLBUTTONDOWN
||
8014 inMsg
== WM_NCMBUTTONDOWN
||
8015 inMsg
== WM_MOUSEACTIVATE
||
8016 inMsg
== WM_ACTIVATEAPP
||
8017 inMsg
== WM_MENUSELECT
8021 // Rollup if the event is outside the popup.
8022 PRBool rollup
= !nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)sRollupWidget
);
8024 if (rollup
&& (inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
))
8026 sRollupListener
->ShouldRollupOnMouseWheelEvent(&rollup
);
8027 *outResult
= PR_TRUE
;
8030 // If we're dealing with menus, we probably have submenus and we don't
8031 // want to rollup if the click is in a parent menu of the current submenu.
8032 PRUint32 popupsToRollup
= PR_UINT32_MAX
;
8034 if ( sMenuRollup
) {
8035 nsAutoTArray
<nsIWidget
*, 5> widgetChain
;
8036 PRUint32 sameTypeCount
= sMenuRollup
->GetSubmenuWidgetChain(&widgetChain
);
8037 for ( PRUint32 i
= 0; i
< widgetChain
.Length(); ++i
) {
8038 nsIWidget
* widget
= widgetChain
[i
];
8039 if ( nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)widget
) ) {
8040 // don't roll up if the mouse event occurred within a menu of the
8041 // same type. If the mouse event occurred in a menu higher than
8042 // that, roll up, but pass the number of popups to Rollup so
8043 // that only those of the same type close up.
8044 if (i
< sameTypeCount
) {
8048 popupsToRollup
= sameTypeCount
;
8052 } // foreach parent menu widget
8053 } // if rollup listener knows about menus
8057 if (inMsg
== WM_MOUSEACTIVATE
&& popupsToRollup
== PR_UINT32_MAX
) {
8058 // Prevent the click inside the popup from causing a change in window
8059 // activation. Since the popup is shown non-activated, we need to eat
8060 // any requests to activate the window while it is displayed. Windows
8061 // will automatically activate the popup on the mousedown otherwise.
8063 *outResult
= MA_NOACTIVATE
;
8068 UINT uMsg
= HIWORD(inLParam
);
8069 if (uMsg
== WM_MOUSEMOVE
)
8071 // WM_MOUSEACTIVATE cause by moving the mouse - X-mouse (eg. TweakUI)
8072 // must be enabled in Windows.
8073 sRollupListener
->ShouldRollupOnMouseActivate(&rollup
);
8076 *outResult
= MA_NOACTIVATE
;
8082 // if we've still determined that we should still rollup everything, do it.
8086 // sRollupConsumeEvent may be modified by
8087 // nsIRollupListener::Rollup.
8088 PRBool consumeRollupEvent
= sRollupConsumeEvent
;
8089 // only need to deal with the last rollup for left mouse down events.
8090 sRollupListener
->Rollup(popupsToRollup
, inMsg
== WM_LBUTTONDOWN
? &mLastRollup
: nsnull
);
8092 // Tell hook to stop processing messages
8093 sProcessHook
= PR_FALSE
;
8095 sRollupMsgWnd
= NULL
;
8097 // return TRUE tells Windows that the event is consumed,
8098 // false allows the event to be dispatched
8100 // So if we are NOT supposed to be consuming events, let it go through
8101 if (consumeRollupEvent
&& inMsg
!= WM_RBUTTONDOWN
) {
8106 // if we are only rolling up some popups, don't activate and don't let
8107 // the event go through. This prevents clicks menus higher in the
8108 // chain from opening when a context menu is open
8109 if (popupsToRollup
!= PR_UINT32_MAX
&& inMsg
== WM_MOUSEACTIVATE
) {
8110 *outResult
= MA_NOACTIVATEANDEAT
;
8115 } // if event that might trigger a popup to rollup
8116 } // if rollup listeners registered
8121 /**************************************************************
8122 **************************************************************
8124 ** BLOCK: Misc. utility methods and functions.
8128 **************************************************************
8129 **************************************************************/
8131 // nsModifierKeyState used in various character processing.
8132 nsModifierKeyState::nsModifierKeyState()
8134 mIsShiftDown
= IS_VK_DOWN(NS_VK_SHIFT
);
8135 mIsControlDown
= IS_VK_DOWN(NS_VK_CONTROL
);
8136 mIsAltDown
= IS_VK_DOWN(NS_VK_ALT
);
8140 PRInt32
nsWindow::GetWindowsVersion()
8145 static PRInt32 version
= 0;
8146 static PRBool didCheck
= PR_FALSE
;
8151 OSVERSIONINFOEX osInfo
;
8152 osInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
8153 // This cast is safe and supposed to be here, don't worry
8154 ::GetVersionEx((OSVERSIONINFO
*)&osInfo
);
8155 version
= (osInfo
.dwMajorVersion
& 0xff) << 8 | (osInfo
.dwMinorVersion
& 0xff);
8161 // Note that the result of GetTopLevelWindow method can be different from the
8162 // result of GetTopLevelHWND method. The result can be non-floating window.
8163 // Because our top level window may be contained in another window which is
8164 // not managed by us.
8165 nsWindow
* nsWindow::GetTopLevelWindow(PRBool aStopOnDialogOrPopup
)
8167 nsWindow
* curWindow
= this;
8170 if (aStopOnDialogOrPopup
) {
8171 switch (curWindow
->mWindowType
) {
8172 case eWindowType_dialog
:
8173 case eWindowType_popup
:
8180 // Retrieve the top level parent or owner window
8181 nsWindow
* parentWindow
= curWindow
->GetParentWindow(PR_TRUE
);
8186 curWindow
= parentWindow
;
8190 // Note that the result of GetTopLevelHWND can be different from the result
8191 // of GetTopLevelWindow method. Because this is checking whether the window
8192 // is top level only in Win32 window system. Therefore, the result window
8193 // may not be managed by us.
8194 HWND
nsWindow::GetTopLevelHWND(HWND aWnd
, PRBool aStopOnDialogOrPopup
)
8203 if (aStopOnDialogOrPopup
) {
8204 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
8206 VERIFY_WINDOW_STYLE(style
);
8208 if (!(style
& WS_CHILD
)) // first top-level window
8212 upWnd
= ::GetParent(curWnd
); // Parent or owner (if has no parent)
8215 // For dialog windows, we want just the parent, not the owner.
8216 // For other/popup windows, we want to find the first owner/parent
8217 // that's a dialog and/or has an owner.
8218 if (upWnd
&& ::GetWindow(curWnd
, GW_OWNER
) == upWnd
) {
8219 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
8220 if ((style
& WS_DLGFRAME
) != 0)
8231 static BOOL CALLBACK
gEnumWindowsProc(HWND hwnd
, LPARAM lParam
)
8234 ::GetWindowThreadProcessId(hwnd
, &pid
);
8235 if (pid
== GetCurrentProcessId() && ::IsWindowVisible(hwnd
))
8237 gWindowsVisible
= PR_TRUE
;
8243 PRBool
nsWindow::CanTakeFocus()
8245 gWindowsVisible
= PR_FALSE
;
8246 EnumWindows(gEnumWindowsProc
, 0);
8247 if (!gWindowsVisible
) {
8250 HWND fgWnd
= ::GetForegroundWindow();
8255 GetWindowThreadProcessId(fgWnd
, &pid
);
8256 if (pid
== GetCurrentProcessId()) {
8264 void nsWindow::InitTrackPointHack()
8266 // Init Trackpoint Hack
8270 const WCHAR wstrKeys
[][40] = {L
"Software\\Lenovo\\TrackPoint",
8271 L
"Software\\Lenovo\\UltraNav",
8272 L
"Software\\Alps\\Apoint\\TrackPoint",
8273 L
"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
8274 L
"Software\\Synaptics\\SynTPEnh\\UltraNavPS2"};
8275 // If anything fails turn the hack off
8276 sTrackPointHack
= false;
8277 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
8278 if(NS_SUCCEEDED(rv
) && prefs
) {
8279 prefs
->GetIntPref("ui.trackpoint_hack.enabled", &lHackValue
);
8280 switch (lHackValue
) {
8281 // 0 means hack disabled
8284 // 1 means hack enabled
8286 sTrackPointHack
= true;
8288 // -1 means autodetect
8290 for(unsigned i
= 0; i
< NS_ARRAY_LENGTH(wstrKeys
); i
++) {
8292 lResult
= ::RegOpenKeyExW(HKEY_CURRENT_USER
, (LPCWSTR
)&wstrKeys
[i
],
8293 0, KEY_READ
, &hKey
);
8294 ::RegCloseKey(hKey
);
8295 if(lResult
== ERROR_SUCCESS
) {
8296 // If we detected a registry key belonging to a TrackPoint driver
8298 sTrackPointHack
= true;
8303 // Shouldn't be any other values, but treat them as disabled
8310 #endif // #if !defined(WINCE)
8312 LPARAM
nsWindow::lParamToScreen(LPARAM lParam
)
8315 pt
.x
= GET_X_LPARAM(lParam
);
8316 pt
.y
= GET_Y_LPARAM(lParam
);
8317 ::ClientToScreen(mWnd
, &pt
);
8318 return MAKELPARAM(pt
.x
, pt
.y
);
8321 LPARAM
nsWindow::lParamToClient(LPARAM lParam
)
8324 pt
.x
= GET_X_LPARAM(lParam
);
8325 pt
.y
= GET_Y_LPARAM(lParam
);
8326 ::ScreenToClient(mWnd
, &pt
);
8327 return MAKELPARAM(pt
.x
, pt
.y
);
8330 /**************************************************************
8331 **************************************************************
8333 ** BLOCK: ChildWindow impl.
8335 ** Child window overrides.
8337 **************************************************************
8338 **************************************************************/
8340 // return the style for a child nsWindow
8341 DWORD
ChildWindow::WindowStyle()
8343 DWORD style
= WS_CLIPCHILDREN
| nsWindow::WindowStyle();
8344 if (!(style
& WS_POPUP
))
8345 style
|= WS_CHILD
; // WS_POPUP and WS_CHILD are mutually exclusive.
8346 VERIFY_WINDOW_STYLE(style
);