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"
162 #include "nsWindowCE.h"
165 #if defined(WINCE_WINDOWS_MOBILE)
166 #define KILL_PRIORITY_ID 2444
169 #include "nsWindowGfx.h"
170 #include "gfxWindowsPlatform.h"
173 #ifdef MOZ_ENABLE_D3D9_LAYER
174 #include "LayerManagerD3D9.h"
176 #include "LayerManagerOGL.h"
180 #include "nsUXThemeConstants.h"
181 #include "nsKeyboardLayout.h"
182 #include "nsNativeDragTarget.h"
183 #include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
186 #include <richedit.h>
187 #endif // !defined(WINCE)
189 #if defined(ACCESSIBILITY)
192 #include "nsIAccessibleDocument.h"
193 #if !defined(WINABLEAPI)
195 #endif // !defined(WINABLEAPI)
196 #endif // defined(ACCESSIBILITY)
198 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
199 #include "nsIWinTaskbar.h"
202 #if defined(NS_ENABLE_TSF)
203 #include "nsTextStore.h"
204 #endif // defined(NS_ENABLE_TSF)
206 #if defined(MOZ_SPLASHSCREEN)
207 #include "nsSplashScreen.h"
208 #endif // defined(MOZ_SPLASHSCREEN)
210 // Windowless plugin support
213 #include "nsWindowDefs.h"
215 #include "mozilla/FunctionTimer.h"
217 #ifdef WINCE_WINDOWS_MOBILE
218 #include "nsGfxCIID.h"
221 #include "mozilla/FunctionTimer.h"
223 /**************************************************************
224 **************************************************************
228 ** nsWindow Class static initializations and global variables.
230 **************************************************************
231 **************************************************************/
233 /**************************************************************
235 * SECTION: nsWindow statics
237 **************************************************************/
239 PRUint32
nsWindow::sInstanceCount
= 0;
240 PRBool
nsWindow::sSwitchKeyboardLayout
= PR_FALSE
;
241 BOOL
nsWindow::sIsRegistered
= FALSE
;
242 BOOL
nsWindow::sIsPopupClassRegistered
= FALSE
;
243 BOOL
nsWindow::sIsOleInitialized
= FALSE
;
244 HCURSOR
nsWindow::sHCursor
= NULL
;
245 imgIContainer
* nsWindow::sCursorImgContainer
= nsnull
;
246 nsWindow
* nsWindow::sCurrentWindow
= nsnull
;
247 PRBool
nsWindow::sJustGotDeactivate
= PR_FALSE
;
248 PRBool
nsWindow::sJustGotActivate
= PR_FALSE
;
250 // imported in nsWidgetFactory.cpp
251 TriStateBool
nsWindow::sCanQuit
= TRI_UNKNOWN
;
253 // Hook Data Memebers for Dropdowns. sProcessHook Tells the
254 // hook methods whether they should be processing the hook
256 HHOOK
nsWindow::sMsgFilterHook
= NULL
;
257 HHOOK
nsWindow::sCallProcHook
= NULL
;
258 HHOOK
nsWindow::sCallMouseHook
= NULL
;
259 PRPackedBool
nsWindow::sProcessHook
= PR_FALSE
;
260 UINT
nsWindow::sRollupMsgId
= 0;
261 HWND
nsWindow::sRollupMsgWnd
= NULL
;
262 UINT
nsWindow::sHookTimerId
= 0;
265 nsIRollupListener
* nsWindow::sRollupListener
= nsnull
;
266 nsIMenuRollup
* nsWindow::sMenuRollup
= nsnull
;
267 nsIWidget
* nsWindow::sRollupWidget
= nsnull
;
268 PRBool
nsWindow::sRollupConsumeEvent
= PR_FALSE
;
270 // Mouse Clicks - static variable definitions for figuring
272 POINT
nsWindow::sLastMousePoint
= {0};
273 POINT
nsWindow::sLastMouseMovePoint
= {0};
274 LONG
nsWindow::sLastMouseDownTime
= 0L;
275 LONG
nsWindow::sLastClickCount
= 0L;
276 BYTE
nsWindow::sLastMouseButton
= 0;
278 // Trim heap on minimize. (initialized, but still true.)
279 int nsWindow::sTrimOnMinimize
= 2;
281 // Default Trackpoint Hack to off
282 PRBool
nsWindow::sTrackPointHack
= PR_FALSE
;
285 BOOL
nsWindow::sIsAccessibilityOn
= FALSE
;
286 // Accessibility wm_getobject handler
287 HINSTANCE
nsWindow::sAccLib
= 0;
288 LPFNLRESULTFROMOBJECT
289 nsWindow::sLresultFromObject
= 0;
290 #endif // ACCESSIBILITY
293 // Used in OOPP plugin focus processing.
294 const PRUnichar
* kOOPPPluginFocusEventId
= L
"OOPP Plugin Focus Widget Event";
295 PRUint32
nsWindow::sOOPPPluginFocusEvent
=
296 RegisterWindowMessageW(kOOPPPluginFocusEventId
);
299 /**************************************************************
301 * SECTION: globals variables
303 **************************************************************/
305 static const char *sScreenManagerContractID
= "@mozilla.org/gfx/screenmanager;1";
308 PRLogModuleInfo
* gWindowsLog
= nsnull
;
312 // Kbd layout. Used throughout character processing.
313 static KeyboardLayout gKbdLayout
;
316 #ifdef WINCE_WINDOWS_MOBILE
317 // HTC Navigation Wheel Event
318 // This is the defined value for Gesture Mode
319 const int WM_HTCNAV
= 0x0400 + 200;
321 typedef int (__stdcall
* HTCApiNavOpen
)(HANDLE
, int);
322 typedef int (__stdcall
* HTCApiNavSetMode
)(HANDLE
, unsigned int);
324 HTCApiNavOpen gHTCApiNavOpen
= nsnull
;
325 HTCApiNavSetMode gHTCApiNavSetMode
= nsnull
;
326 static PRBool gCheckForHTCApi
= PR_FALSE
;
329 // Global user preference for disabling native theme. Used
330 // in NativeWindowTheme.
331 PRBool gDisableNativeTheme
= PR_FALSE
;
333 // Global used in Show window enumerations.
334 static PRBool gWindowsVisible
= PR_FALSE
;
336 static NS_DEFINE_CID(kCClipboardCID
, NS_CLIPBOARD_CID
);
337 #ifdef WINCE_WINDOWS_MOBILE
338 static NS_DEFINE_CID(kRegionCID
, NS_REGION_CID
);
341 /**************************************************************
342 **************************************************************
344 ** BLOCK: nsIWidget impl.
346 ** nsIWidget interface implementation, broken down into
349 **************************************************************
350 **************************************************************/
352 /**************************************************************
354 * SECTION: nsWindow construction and destruction
356 **************************************************************/
358 nsWindow::nsWindow() : nsBaseWidget()
362 gWindowsLog
= PR_NewLogModule("nsWindowsWidgets");
367 mPrevWndProc
= nsnull
;
369 mNativeDragTarget
= nsnull
;
371 mIsVisible
= PR_FALSE
;
372 mIsInMouseCapture
= PR_FALSE
;
373 mIsTopWidgetWindow
= PR_FALSE
;
374 mUnicodeWidget
= PR_TRUE
;
375 mDisplayPanFeedback
= PR_FALSE
;
376 mCustomNonClient
= PR_FALSE
;
377 mCompositorFlag
= PR_FALSE
;
378 mHideChrome
= PR_FALSE
;
379 mWindowType
= eWindowType_child
;
380 mBorderStyle
= eBorderStyle_default
;
381 mPopupType
= ePopupTypeAny
;
382 mOldSizeMode
= nsSizeMode_Normal
;
386 mLastSize
.height
= 0;
390 mExitToNonClientArea
= 0;
391 mLastKeyboardLayout
= 0;
392 mBlurSuppressLevel
= 0;
393 mIMEEnabled
= nsIWidget::IME_STATUS_ENABLED
;
395 mTransparentSurface
= nsnull
;
397 mTransparencyMode
= eTransparencyOpaque
;
398 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
399 memset(&mGlassMargins
, 0, sizeof mGlassMargins
);
400 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
402 mBackground
= ::GetSysColor(COLOR_BTNFACE
);
403 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
404 mForeground
= ::GetSysColor(COLOR_WINDOWTEXT
);
406 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
407 mTaskbarPreview
= nsnull
;
408 mHasTaskbarIconBeenCreated
= PR_FALSE
;
411 // Global initialization
412 if (!sInstanceCount
) {
414 gKbdLayout
.LoadLayout(::GetKeyboardLayout(0));
418 nsIMM32Handler::Initialize();
421 nsTextStore::Initialize();
425 if (SUCCEEDED(::OleInitialize(NULL
)))
426 sIsOleInitialized
= TRUE
;
427 NS_ASSERTION(sIsOleInitialized
, "***** OLE is not initialized!\n");
430 #if defined(HEAP_DUMP_EVENT)
435 InitTrackPointHack();
439 mIdleService
= nsnull
;
444 nsWindow::~nsWindow()
448 // If the widget was released without calling Destroy() then the native window still
449 // exists, and we need to destroy it. This will also result in a call to OnDestroy.
451 // XXX How could this happen???
458 if (sInstanceCount
== 0) {
460 nsTextStore::Terminate();
464 NS_IF_RELEASE(sCursorImgContainer
);
465 if (sIsOleInitialized
) {
466 ::OleFlushClipboard();
468 sIsOleInitialized
= FALSE
;
470 // delete any of the IME structures that we allocated
471 nsIMM32Handler::Terminate();
472 #endif // !defined(WINCE)
476 NS_IF_RELEASE(mNativeDragTarget
);
477 #endif // !defined(WINCE)
480 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow
, nsBaseWidget
)
482 /**************************************************************
484 * SECTION: nsIWidget::Create, nsIWidget::Destroy
486 * Creating and destroying windows for this widget.
488 **************************************************************/
490 // Allow Derived classes to modify the height that is passed
491 // when the window is created or resized. Also add extra height
492 // if needed (on Windows CE)
493 PRInt32
nsWindow::GetHeight(PRInt32 aProposedHeight
)
497 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
498 DWORD style
= WindowStyle();
499 if ((style
& WS_SYSMENU
) && (style
& WS_POPUP
)) {
500 extra
= GetSystemMetrics(SM_CYCAPTION
);
504 return aProposedHeight
+ extra
;
507 // Create the proper widget
509 nsWindow::Create(nsIWidget
*aParent
,
510 nsNativeWidget aNativeParent
,
511 const nsIntRect
&aRect
,
512 EVENT_CALLBACK aHandleEventFunction
,
513 nsIDeviceContext
*aContext
,
514 nsIAppShell
*aAppShell
,
515 nsIToolkit
*aToolkit
,
516 nsWidgetInitData
*aInitData
)
519 mUnicodeWidget
= aInitData
->mUnicode
;
521 nsIWidget
*baseParent
= aInitData
&&
522 (aInitData
->mWindowType
== eWindowType_dialog
||
523 aInitData
->mWindowType
== eWindowType_toplevel
||
524 aInitData
->mWindowType
== eWindowType_invisible
) ?
527 mIsTopWidgetWindow
= (nsnull
== baseParent
);
528 mBounds
.width
= aRect
.width
;
529 mBounds
.height
= aRect
.height
;
531 BaseCreate(baseParent
, aRect
, aHandleEventFunction
, aContext
,
532 aAppShell
, aToolkit
, aInitData
);
535 if (aParent
) { // has a nsIWidget parent
536 parent
= aParent
? (HWND
)aParent
->GetNativeData(NS_NATIVE_WINDOW
) : NULL
;
538 } else { // has a nsNative parent
539 parent
= (HWND
)aNativeParent
;
540 mParent
= aNativeParent
? GetNSWindowPtr((HWND
)aNativeParent
) : nsnull
;
543 if (nsnull
!= aInitData
) {
544 mPopupType
= aInitData
->mPopupHint
;
547 mContentType
= aInitData
? aInitData
->mContentType
: eContentTypeInherit
;
549 DWORD style
= WindowStyle();
550 DWORD extendedStyle
= WindowExStyle();
552 if (aInitData
->mRTL
) {
553 extendedStyle
|= WS_EX_LAYOUTRTL
| WS_EX_NOINHERITLAYOUT
;
556 if (mWindowType
== eWindowType_popup
) {
557 // if a parent was specified, don't use WS_EX_TOPMOST so that the popup
558 // only appears above the parent, instead of all windows
560 extendedStyle
= WS_EX_TOOLWINDOW
;
563 } else if (mWindowType
== eWindowType_invisible
) {
564 // Make sure CreateWindowEx succeeds at creating a toplevel window
565 style
&= ~0x40000000; // WS_CHILDWINDOW
566 } else if (nsnull
!= aInitData
) {
567 // See if the caller wants to explictly set clip children and clip siblings
568 if (aInitData
->clipChildren
) {
569 style
|= WS_CLIPCHILDREN
;
571 style
&= ~WS_CLIPCHILDREN
;
573 if (aInitData
->clipSiblings
) {
574 style
|= WS_CLIPSIBLINGS
;
578 mWnd
= ::CreateWindowExW(extendedStyle
,
579 aInitData
&& aInitData
->mDropShadow
?
580 WindowPopupClass() : WindowClass(),
586 GetHeight(aRect
.height
),
589 nsToolkit::mDllInstance
,
593 NS_WARNING("nsWindow CreateWindowEx failed.");
594 return NS_ERROR_FAILURE
;
597 if (nsWindow::sTrackPointHack
&&
598 mWindowType
!= eWindowType_plugin
&&
599 mWindowType
!= eWindowType_invisible
) {
600 // Ugly Thinkpad Driver Hack (Bug 507222)
601 // We create an invisible scrollbar to trick the
602 // Trackpoint driver into sending us scrolling messages
603 ::CreateWindowW(L
"SCROLLBAR", L
"FAKETRACKPOINTSCROLLBAR",
604 WS_CHILD
| WS_VISIBLE
, 0,0,0,0, mWnd
, NULL
,
605 nsToolkit::mDllInstance
, NULL
);
608 // call the event callback to notify about creation
610 DispatchStandardEvent(NS_CREATE
);
611 SubclassWindow(TRUE
);
613 if (sTrimOnMinimize
== 2 && mWindowType
== eWindowType_invisible
) {
614 /* The internal variable set by the config.trim_on_minimize pref
615 has not yet been initialized, and this is the hidden window
616 (conveniently created before any visible windows, and after
617 the profile has been initialized).
619 Default config.trim_on_minimize to false, to fix bug 76831
620 for good. If anyone complains about this new default, saying
621 that a Mozilla app hogs too much memory while minimized, they
622 will have that entire bug tattooed on their backside. */
625 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
627 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
628 prefs
->GetBranch(0, getter_AddRefs(prefBranch
));
632 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("config.trim_on_minimize",
637 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("intl.keyboard.per_window_layout",
639 sSwitchKeyboardLayout
= temp
;
641 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("mozilla.widget.disable-native-theme",
643 gDisableNativeTheme
= temp
;
647 #if defined(WINCE_HAVE_SOFTKB)
648 if (mWindowType
== eWindowType_dialog
|| mWindowType
== eWindowType_toplevel
)
649 nsWindowCE::CreateSoftKeyMenuBar(mWnd
);
655 // Close this nsWindow
656 NS_METHOD
nsWindow::Destroy()
658 // WM_DESTROY has already fired, we're done.
662 // During the destruction of all of our children, make sure we don't get deleted.
663 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
666 * On windows the LayerManagerOGL destructor wants the widget to be around for
667 * cleanup. It also would like to have the HWND intact, so we NULL it here.
669 mLayerManager
= NULL
;
671 // The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
672 // and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
673 // from it. The function also destroys the window's menu, flushes the thread message queue,
674 // destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if
675 // the window is at the top of the viewer chain).
677 // If the specified window is a parent or owner window, DestroyWindow automatically destroys
678 // the associated child or owned windows when it destroys the parent or owner window. The
679 // function first destroys child or owned windows, and then it destroys the parent or owner
681 VERIFY(::DestroyWindow(mWnd
));
683 // Our windows can be subclassed which may prevent us receiving WM_DESTROY. If OnDestroy()
684 // didn't get called, call it now.
685 if (PR_FALSE
== mOnDestroyCalled
)
691 /**************************************************************
693 * SECTION: Window class utilities
695 * Utilities for calculating the proper window class name for
698 **************************************************************/
700 // Return the proper window class for everything except popups.
701 LPCWSTR
nsWindow::WindowClass()
703 if (!nsWindow::sIsRegistered
) {
706 // wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
707 wc
.style
= CS_DBLCLKS
;
708 wc
.lpfnWndProc
= ::DefWindowProcW
;
711 wc
.hInstance
= nsToolkit::mDllInstance
;
712 wc
.hIcon
= ::LoadIconW(::GetModuleHandleW(NULL
), (LPWSTR
)IDI_APPLICATION
);
714 wc
.hbrBackground
= mBrush
;
715 wc
.lpszMenuName
= NULL
;
716 wc
.lpszClassName
= kClassNameHidden
;
718 BOOL succeeded
= ::RegisterClassW(&wc
) != 0 &&
719 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError();
720 nsWindow::sIsRegistered
= succeeded
;
722 wc
.lpszClassName
= kClassNameContentFrame
;
723 if (!::RegisterClassW(&wc
) &&
724 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
725 nsWindow::sIsRegistered
= FALSE
;
728 wc
.lpszClassName
= kClassNameContent
;
729 if (!::RegisterClassW(&wc
) &&
730 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
731 nsWindow::sIsRegistered
= FALSE
;
734 wc
.lpszClassName
= kClassNameUI
;
735 if (!::RegisterClassW(&wc
) &&
736 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
737 nsWindow::sIsRegistered
= FALSE
;
740 wc
.lpszClassName
= kClassNameGeneral
;
741 ATOM generalClassAtom
= ::RegisterClassW(&wc
);
742 if (!generalClassAtom
&&
743 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
744 nsWindow::sIsRegistered
= FALSE
;
747 wc
.lpszClassName
= kClassNameDialog
;
749 if (!::RegisterClassW(&wc
) &&
750 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
751 nsWindow::sIsRegistered
= FALSE
;
755 if (mWindowType
== eWindowType_invisible
) {
756 return kClassNameHidden
;
758 if (mWindowType
== eWindowType_dialog
) {
759 return kClassNameDialog
;
761 if (mContentType
== eContentTypeContent
) {
762 return kClassNameContent
;
764 if (mContentType
== eContentTypeContentFrame
) {
765 return kClassNameContentFrame
;
767 if (mContentType
== eContentTypeUI
) {
770 return kClassNameGeneral
;
773 // Return the proper popup window class
774 LPCWSTR
nsWindow::WindowPopupClass()
776 if (!nsWindow::sIsPopupClassRegistered
) {
779 wc
.style
= CS_DBLCLKS
| CS_XP_DROPSHADOW
;
780 wc
.lpfnWndProc
= ::DefWindowProcW
;
783 wc
.hInstance
= nsToolkit::mDllInstance
;
784 wc
.hIcon
= ::LoadIconW(::GetModuleHandleW(NULL
), (LPWSTR
)IDI_APPLICATION
);
786 wc
.hbrBackground
= mBrush
;
787 wc
.lpszMenuName
= NULL
;
788 wc
.lpszClassName
= kClassNameDropShadow
;
790 nsWindow::sIsPopupClassRegistered
= ::RegisterClassW(&wc
);
791 if (!nsWindow::sIsPopupClassRegistered
) {
792 // For older versions of Win32 (i.e., not XP), the registration will
793 // fail, so we have to re-register without the CS_XP_DROPSHADOW flag.
794 wc
.style
= CS_DBLCLKS
;
795 nsWindow::sIsPopupClassRegistered
= ::RegisterClassW(&wc
);
799 return kClassNameDropShadow
;
802 /**************************************************************
804 * SECTION: Window styles utilities
806 * Return the proper windows styles and extended styles.
808 **************************************************************/
810 // Return nsWindow styles
811 #if !defined(WINCE) // implemented in nsWindowCE.cpp
812 DWORD
nsWindow::WindowStyle()
816 switch (mWindowType
) {
817 case eWindowType_plugin
:
818 case eWindowType_child
:
819 style
= WS_OVERLAPPED
;
822 case eWindowType_dialog
:
823 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
| DS_3DLOOK
|
824 DS_MODALFRAME
| WS_CLIPCHILDREN
;
825 if (mBorderStyle
!= eBorderStyle_default
)
826 style
|= WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
829 case eWindowType_popup
:
831 if (mTransparencyMode
!= eTransparencyGlass
) {
832 style
|= WS_OVERLAPPED
;
837 NS_ERROR("unknown border style");
840 case eWindowType_toplevel
:
841 case eWindowType_invisible
:
842 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
|
843 WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPCHILDREN
;
847 if (mBorderStyle
!= eBorderStyle_default
&& mBorderStyle
!= eBorderStyle_all
) {
848 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_border
))
851 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_title
)) {
852 style
&= ~WS_DLGFRAME
;
857 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_close
))
859 // XXX The close box can only be removed by changing the window class,
860 // as far as I know --- roc+moz@cs.cmu.edu
862 if (mBorderStyle
== eBorderStyle_none
||
863 !(mBorderStyle
& (eBorderStyle_menu
| eBorderStyle_close
)))
864 style
&= ~WS_SYSMENU
;
865 // Looks like getting rid of the system menu also does away with the
866 // close box. So, we only get rid of the system menu if you want neither it
867 // nor the close box. How does the Windows "Dialog" window class get just
868 // closebox and no sysmenu? Who knows.
870 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_resizeh
))
871 style
&= ~WS_THICKFRAME
;
873 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_minimize
))
874 style
&= ~WS_MINIMIZEBOX
;
876 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_maximize
))
877 style
&= ~WS_MAXIMIZEBOX
;
879 VERIFY_WINDOW_STYLE(style
);
882 #endif // !defined(WINCE)
884 // Return nsWindow extended styles
885 DWORD
nsWindow::WindowExStyle()
889 case eWindowType_plugin
:
890 case eWindowType_child
:
893 case eWindowType_dialog
:
894 return WS_EX_WINDOWEDGE
| WS_EX_DLGMODALFRAME
;
896 case eWindowType_popup
:
898 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
901 WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
904 NS_ERROR("unknown border style");
907 case eWindowType_toplevel
:
908 case eWindowType_invisible
:
909 return WS_EX_WINDOWEDGE
;
913 /**************************************************************
915 * SECTION: Window subclassing utilities
917 * Set or clear window subclasses on native windows. Used in
918 * Create and Destroy.
920 **************************************************************/
922 // Subclass (or remove the subclass from) this component's nsWindow
923 void nsWindow::SubclassWindow(BOOL bState
)
926 //NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
927 if (!::IsWindow(mWnd
)) {
928 NS_ERROR("Invalid window handle");
932 // change the nsWindow proc
934 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
,
935 (LONG_PTR
)nsWindow::WindowProc
);
937 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
,
938 (LONG_PTR
)nsWindow::WindowProc
);
939 NS_ASSERTION(mPrevWndProc
, "Null standard window procedure");
940 // connect the this pointer to the nsWindow handle
941 SetNSWindowPtr(mWnd
, this);
945 ::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
947 ::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
948 SetNSWindowPtr(mWnd
, NULL
);
954 /**************************************************************
956 * SECTION: Window properties
958 * Set and clear native window properties.
960 **************************************************************/
962 static PRUnichar sPropName
[40] = L
"";
963 static PRUnichar
* GetNSWindowPropName()
967 _snwprintf(sPropName
, 39, L
"MozillansIWidgetPtr%p", GetCurrentProcessId());
968 sPropName
[39] = '\0';
973 nsWindow
* nsWindow::GetNSWindowPtr(HWND aWnd
)
975 return (nsWindow
*) ::GetPropW(aWnd
, GetNSWindowPropName());
978 BOOL
nsWindow::SetNSWindowPtr(HWND aWnd
, nsWindow
* ptr
)
981 ::RemovePropW(aWnd
, GetNSWindowPropName());
984 return ::SetPropW(aWnd
, GetNSWindowPropName(), (HANDLE
)ptr
);
988 /**************************************************************
990 * SECTION: nsIWidget::SetParent, nsIWidget::GetParent
992 * Set or clear the parent widgets using window properties, and
993 * handles calculating native parent handles.
995 **************************************************************/
997 // Get and set parent widgets
998 NS_IMETHODIMP
nsWindow::SetParent(nsIWidget
*aNewParent
)
1000 mParent
= aNewParent
;
1003 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
1005 nsIWidget
* parent
= GetParent();
1007 parent
->RemoveChild(this);
1010 HWND newParent
= (HWND
)aNewParent
->GetNativeData(NS_NATIVE_WINDOW
);
1011 NS_ASSERTION(newParent
, "Parent widget has a null native window handle");
1012 if (newParent
&& mWnd
) {
1013 ::SetParent(mWnd
, newParent
);
1016 aNewParent
->AddChild(this);
1021 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
1023 nsIWidget
* parent
= GetParent();
1026 parent
->RemoveChild(this);
1030 // If we have no parent, SetParent should return the desktop.
1031 VERIFY(::SetParent(mWnd
, nsnull
));
1037 nsIWidget
* nsWindow::GetParent(void)
1039 return GetParentWindow(PR_FALSE
);
1042 nsWindow
* nsWindow::GetParentWindow(PRBool aIncludeOwner
)
1044 if (mIsTopWidgetWindow
) {
1045 // Must use a flag instead of mWindowType to tell if the window is the
1046 // owned by the topmost widget, because a child window can be embedded inside
1047 // a HWND which is not associated with a nsIWidget.
1051 // If this widget has already been destroyed, pretend we have no parent.
1052 // This corresponds to code in Destroy which removes the destroyed
1053 // widget from its parent's child list.
1054 if (mInDtor
|| mOnDestroyCalled
)
1058 // aIncludeOwner set to true implies walking the parent chain to retrieve the
1059 // root owner. aIncludeOwner set to false implies the search will stop at the
1060 // true parent (default).
1061 nsWindow
* widget
= nsnull
;
1064 HWND parent
= ::GetParent(mWnd
);
1066 HWND parent
= nsnull
;
1068 parent
= ::GetParent(mWnd
);
1070 parent
= ::GetAncestor(mWnd
, GA_PARENT
);
1073 widget
= GetNSWindowPtr(parent
);
1075 // If the widget is in the process of being destroyed then
1077 if (widget
->mInDtor
) {
1087 /**************************************************************
1089 * SECTION: nsIWidget::Show
1091 * Hide or show this component.
1093 **************************************************************/
1095 NS_METHOD
nsWindow::Show(PRBool bState
)
1097 #if defined(MOZ_SPLASHSCREEN)
1098 // we're about to show the first toplevel window,
1099 // so kill off any splash screen if we had one
1100 nsSplashScreen
*splash
= nsSplashScreen::Get();
1101 if (splash
&& splash
->IsOpen() && mWnd
&& bState
&&
1102 (mWindowType
== eWindowType_toplevel
||
1103 mWindowType
== eWindowType_dialog
||
1104 mWindowType
== eWindowType_popup
))
1110 #ifdef NS_FUNCTION_TIMER
1111 static bool firstShow
= true;
1113 (mWindowType
== eWindowType_toplevel
||
1114 mWindowType
== eWindowType_dialog
||
1115 mWindowType
== eWindowType_popup
))
1118 mozilla::FunctionTimer::LogMessage("@ First toplevel/dialog/popup showing");
1122 PRBool wasVisible
= mIsVisible
;
1123 // Set the status now so that anyone asking during ShowWindow or
1124 // SetWindowPos would get the correct answer.
1125 mIsVisible
= bState
;
1129 if (!wasVisible
&& mWindowType
== eWindowType_toplevel
) {
1130 switch (mSizeMode
) {
1132 case nsSizeMode_Fullscreen
:
1133 ::SetForegroundWindow(mWnd
);
1134 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1135 MakeFullScreen(TRUE
);
1138 case nsSizeMode_Maximized
:
1139 ::SetForegroundWindow(mWnd
);
1140 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1142 // use default for nsSizeMode_Minimized on Windows CE
1144 case nsSizeMode_Maximized
:
1145 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1147 case nsSizeMode_Minimized
:
1148 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
1152 if (CanTakeFocus()) {
1154 ::SetForegroundWindow(mWnd
);
1156 ::ShowWindow(mWnd
, SW_SHOWNORMAL
);
1158 // Place the window behind the foreground window
1159 // (as long as it is not topmost)
1160 HWND wndAfter
= ::GetForegroundWindow();
1162 wndAfter
= HWND_BOTTOM
;
1163 else if (GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
)
1164 wndAfter
= HWND_TOP
;
1165 ::SetWindowPos(mWnd
, wndAfter
, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOSIZE
|
1166 SWP_NOMOVE
| SWP_NOACTIVATE
);
1172 DWORD flags
= SWP_NOSIZE
| SWP_NOMOVE
| SWP_SHOWWINDOW
;
1174 flags
|= SWP_NOZORDER
;
1176 if (mWindowType
== eWindowType_popup
) {
1178 // ensure popups are the topmost of the TOPMOST
1179 // layer. Remember not to set the SWP_NOZORDER
1180 // flag as that might allow the taskbar to overlap
1181 // the popup. However on windows ce, we need to
1182 // activate the popup or clicks will not be sent.
1183 flags
|= SWP_NOACTIVATE
;
1185 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
1186 ::SetWindowPos(mWnd
, owner
? 0 : HWND_TOPMOST
, 0, 0, 0, 0, flags
);
1189 if (mWindowType
== eWindowType_dialog
&& !CanTakeFocus())
1190 flags
|= SWP_NOACTIVATE
;
1192 ::SetWindowPos(mWnd
, HWND_TOP
, 0, 0, 0, 0, flags
);
1197 if (!wasVisible
&& (mWindowType
== eWindowType_toplevel
|| mWindowType
== eWindowType_dialog
)) {
1198 // when a toplevel window or dialog is shown, initialize the UI state
1199 ::SendMessageW(mWnd
, WM_CHANGEUISTATE
, MAKEWPARAM(UIS_INITIALIZE
, UISF_HIDEFOCUS
| UISF_HIDEACCEL
), 0);
1203 if (mWindowType
!= eWindowType_dialog
) {
1204 ::ShowWindow(mWnd
, SW_HIDE
);
1206 ::SetWindowPos(mWnd
, 0, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1207 SWP_NOZORDER
| SWP_NOACTIVATE
);
1213 if (!wasVisible
&& bState
)
1214 Invalidate(PR_FALSE
);
1220 /**************************************************************
1222 * SECTION: nsIWidget::IsVisible
1224 * Returns the visibility state.
1226 **************************************************************/
1228 // Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
1229 NS_METHOD
nsWindow::IsVisible(PRBool
& bState
)
1231 bState
= mIsVisible
;
1235 /**************************************************************
1237 * SECTION: Window clipping utilities
1239 * Used in Size and Move operations for setting the proper
1240 * window clipping regions for window transparency.
1242 **************************************************************/
1244 // XP and Vista visual styles sometimes require window clipping regions to be applied for proper
1245 // transparency. These routines are called on size and move operations.
1246 void nsWindow::ClearThemeRegion()
1249 if (nsUXThemeData::sIsVistaOrLater
&& mTransparencyMode
!= eTransparencyGlass
&&
1250 mWindowType
== eWindowType_popup
&& (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
)) {
1251 SetWindowRgn(mWnd
, NULL
, false);
1256 void nsWindow::SetThemeRegion()
1259 // Popup types that have a visual styles region applied (bug 376408). This can be expanded
1260 // for other window types as needed. The regions are applied generically to the base window
1261 // so default constants are used for part and state. At some point we might need part and
1262 // state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
1263 // change shape based on state haven't come up.
1264 if (nsUXThemeData::sIsVistaOrLater
&& mTransparencyMode
!= eTransparencyGlass
&&
1265 mWindowType
== eWindowType_popup
&& (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
)) {
1267 RECT rect
= {0,0,mBounds
.width
,mBounds
.height
};
1269 HDC dc
= ::GetDC(mWnd
);
1270 nsUXThemeData::getThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip
), dc
, TTP_STANDARD
, TS_NORMAL
, &rect
, &hRgn
);
1272 if (!SetWindowRgn(mWnd
, hRgn
, false)) // do not delete or alter hRgn if accepted.
1275 ::ReleaseDC(mWnd
, dc
);
1280 /**************************************************************
1282 * SECTION: nsIWidget::Move, nsIWidget::Resize,
1283 * nsIWidget::Size, nsIWidget::BeginResizeDrag
1285 * Repositioning and sizing a window.
1287 **************************************************************/
1289 // Move this component
1290 NS_METHOD
nsWindow::Move(PRInt32 aX
, PRInt32 aY
)
1292 if (mWindowType
== eWindowType_toplevel
||
1293 mWindowType
== eWindowType_dialog
) {
1294 SetSizeMode(nsSizeMode_Normal
);
1296 // Check to see if window needs to be moved first
1297 // to avoid a costly call to SetWindowPos. This check
1298 // can not be moved to the calling code in nsView, because
1299 // some platforms do not position child windows correctly
1301 // Only perform this check for non-popup windows, since the positioning can
1302 // in fact change even when the x/y do not. We always need to perform the
1303 // check. See bug #97805 for details.
1304 if (mWindowType
!= eWindowType_popup
&& (mBounds
.x
== aX
) && (mBounds
.y
== aY
))
1306 // Nothing to do, since it is already positioned correctly.
1315 // complain if a window is moved offscreen (legal, but potentially worrisome)
1316 if (mIsTopWidgetWindow
) { // only a problem for top-level windows
1317 // Make sure this window is actually on the screen before we move it
1318 // XXX: Needs multiple monitor support
1319 HDC dc
= ::GetDC(mWnd
);
1321 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1323 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &workArea
, 0);
1324 // no annoying assertions. just mention the issue.
1325 if (aX
< 0 || aX
>= workArea
.right
|| aY
< 0 || aY
>= workArea
.bottom
)
1326 printf("window moved to offscreen position\n");
1328 ::ReleaseDC(mWnd
, dc
);
1333 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, 0, 0,
1334 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOSIZE
));
1340 // Resize this component
1341 NS_METHOD
nsWindow::Resize(PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1343 NS_ASSERTION((aWidth
>=0 ) , "Negative width passed to nsWindow::Resize");
1344 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1346 // Avoid unnecessary resizing calls
1347 if (mBounds
.width
== aWidth
&& mBounds
.height
== aHeight
&& !aRepaint
)
1351 if (eTransparencyTransparent
== mTransparencyMode
)
1352 ResizeTranslucentWindow(aWidth
, aHeight
);
1355 // Set cached value for lightweight and printing
1356 mBounds
.width
= aWidth
;
1357 mBounds
.height
= aHeight
;
1360 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOMOVE
;
1364 flags
|= SWP_NOREDRAW
;
1369 VERIFY(::SetWindowPos(mWnd
, NULL
, 0, 0, aWidth
, GetHeight(aHeight
), flags
));
1374 Invalidate(PR_FALSE
);
1379 // Resize this component
1380 NS_METHOD
nsWindow::Resize(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1382 NS_ASSERTION((aWidth
>=0 ), "Negative width passed to nsWindow::Resize");
1383 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1385 // Avoid unnecessary resizing calls
1386 if (mBounds
.x
== aX
&& mBounds
.y
== aY
&&
1387 mBounds
.width
== aWidth
&& mBounds
.height
== aHeight
&& !aRepaint
)
1391 if (eTransparencyTransparent
== mTransparencyMode
)
1392 ResizeTranslucentWindow(aWidth
, aHeight
);
1395 // Set cached value for lightweight and printing
1398 mBounds
.width
= aWidth
;
1399 mBounds
.height
= aHeight
;
1402 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1405 flags
|= SWP_NOREDRAW
;
1410 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, aWidth
, GetHeight(aHeight
), flags
));
1415 Invalidate(PR_FALSE
);
1420 // Resize the client area and position the widget within it's parent
1421 NS_METHOD
nsWindow::ResizeClient(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1423 NS_ASSERTION((aWidth
>=0) , "Negative width passed to ResizeClient");
1424 NS_ASSERTION((aHeight
>=0), "Negative height passed to ResizeClient");
1426 // Adjust our existing window bounds, based on the new client dims.
1428 GetClientRect(mWnd
, &client
);
1429 nsIntPoint
dims(client
.right
- client
.left
, client
.bottom
- client
.top
);
1430 aWidth
= mBounds
.width
+ (aWidth
- dims
.x
);
1431 aHeight
= mBounds
.height
+ (aHeight
- dims
.y
);
1436 GetScreenBounds(bounds
);
1439 return Resize(aX
, aY
, aWidth
, aHeight
, aRepaint
);
1441 return Resize(aWidth
, aHeight
, aRepaint
);
1446 nsWindow::BeginResizeDrag(nsGUIEvent
* aEvent
, PRInt32 aHorizontal
, PRInt32 aVertical
)
1448 NS_ENSURE_ARG_POINTER(aEvent
);
1450 if (aEvent
->eventStructType
!= NS_MOUSE_EVENT
) {
1451 // you can only begin a resize drag with a mouse event
1452 return NS_ERROR_INVALID_ARG
;
1455 nsMouseEvent
* mouseEvent
= static_cast<nsMouseEvent
*>(aEvent
);
1456 if (mouseEvent
->button
!= nsMouseEvent::eLeftButton
) {
1457 // you can only begin a resize drag with the left mouse button
1458 return NS_ERROR_INVALID_ARG
;
1461 // work out what sizemode we're talking about
1463 if (aVertical
< 0) {
1464 if (aHorizontal
< 0) {
1465 syscommand
= SC_SIZE
| WMSZ_TOPLEFT
;
1466 } else if (aHorizontal
== 0) {
1467 syscommand
= SC_SIZE
| WMSZ_TOP
;
1469 syscommand
= SC_SIZE
| WMSZ_TOPRIGHT
;
1471 } else if (aVertical
== 0) {
1472 if (aHorizontal
< 0) {
1473 syscommand
= SC_SIZE
| WMSZ_LEFT
;
1474 } else if (aHorizontal
== 0) {
1475 return NS_ERROR_INVALID_ARG
;
1477 syscommand
= SC_SIZE
| WMSZ_RIGHT
;
1480 if (aHorizontal
< 0) {
1481 syscommand
= SC_SIZE
| WMSZ_BOTTOMLEFT
;
1482 } else if (aHorizontal
== 0) {
1483 syscommand
= SC_SIZE
| WMSZ_BOTTOM
;
1485 syscommand
= SC_SIZE
| WMSZ_BOTTOMRIGHT
;
1489 // resizing doesn't work if the mouse is already captured
1490 CaptureMouse(PR_FALSE
);
1492 // find the top-level window
1493 HWND toplevelWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
1495 // tell Windows to start the resize
1496 ::PostMessage(toplevelWnd
, WM_SYSCOMMAND
, syscommand
,
1497 POINTTOPOINTS(aEvent
->refPoint
));
1502 /**************************************************************
1504 * SECTION: Window Z-order and state.
1506 * nsIWidget::PlaceBehind, nsIWidget::SetSizeMode,
1507 * nsIWidget::ConstrainPosition
1509 * Z-order, positioning, restore, minimize, and maximize.
1511 **************************************************************/
1513 // Position the window behind the given window
1514 NS_METHOD
nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
1515 nsIWidget
*aWidget
, PRBool aActivate
)
1517 HWND behind
= HWND_TOP
;
1518 if (aPlacement
== eZPlacementBottom
)
1519 behind
= HWND_BOTTOM
;
1520 else if (aPlacement
== eZPlacementBelow
&& aWidget
)
1521 behind
= (HWND
)aWidget
->GetNativeData(NS_NATIVE_WINDOW
);
1522 UINT flags
= SWP_NOMOVE
| SWP_NOREPOSITION
| SWP_NOSIZE
;
1524 flags
|= SWP_NOACTIVATE
;
1526 if (!CanTakeFocus() && behind
== HWND_TOP
)
1528 // Can't place the window to top so place it behind the foreground window
1529 // (as long as it is not topmost)
1530 HWND wndAfter
= ::GetForegroundWindow();
1532 behind
= HWND_BOTTOM
;
1533 else if (!(GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
))
1535 flags
|= SWP_NOACTIVATE
;
1538 ::SetWindowPos(mWnd
, behind
, 0, 0, 0, 0, flags
);
1542 // Maximize, minimize or restore the window.
1543 #if !defined(WINCE) // implemented in nsWindowCE.cpp
1544 NS_IMETHODIMP
nsWindow::SetSizeMode(PRInt32 aMode
) {
1548 // Let's not try and do anything if we're already in that state.
1549 // (This is needed to prevent problems when calling window.minimize(), which
1550 // calls us directly, and then the OS triggers another call to us.)
1551 if (aMode
== mSizeMode
)
1554 // save the requested state
1555 rv
= nsBaseWidget::SetSizeMode(aMode
);
1556 if (NS_SUCCEEDED(rv
) && mIsVisible
) {
1560 case nsSizeMode_Fullscreen
:
1564 case nsSizeMode_Maximized
:
1568 case nsSizeMode_Minimized
:
1569 // Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
1570 // keeps the window active in the tray. So after the window is minimized,
1571 // windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
1572 // we will do some additional processing to get the active window set right.
1573 // If sTrimOnMinimize is set, we let windows handle minimization normally
1574 // using SW_MINIMIZE.
1575 mode
= sTrimOnMinimize
? SW_MINIMIZE
: SW_SHOWMINIMIZED
;
1581 ::ShowWindow(mWnd
, mode
);
1582 // we dispatch an activate event here to ensure that the right child window
1584 if (mode
== SW_RESTORE
|| mode
== SW_MAXIMIZE
)
1585 DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
1589 #endif // !defined(WINCE)
1591 // Constrain a potential move to fit onscreen
1592 NS_METHOD
nsWindow::ConstrainPosition(PRBool aAllowSlop
,
1593 PRInt32
*aX
, PRInt32
*aY
)
1595 if (!mIsTopWidgetWindow
) // only a problem for top-level windows
1598 PRBool doConstrain
= PR_FALSE
; // whether we have enough info to do anything
1600 /* get our playing field. use the current screen, or failing that
1601 for any reason, use device caps for the default screen. */
1604 nsCOMPtr
<nsIScreenManager
> screenmgr
= do_GetService(sScreenManagerContractID
);
1606 nsCOMPtr
<nsIScreen
> screen
;
1607 PRInt32 left
, top
, width
, height
;
1609 // zero size rects confuse the screen manager
1610 width
= mBounds
.width
> 0 ? mBounds
.width
: 1;
1611 height
= mBounds
.height
> 0 ? mBounds
.height
: 1;
1612 screenmgr
->ScreenForRect(*aX
, *aY
, width
, height
,
1613 getter_AddRefs(screen
));
1615 if (mSizeMode
!= nsSizeMode_Fullscreen
) {
1616 // For normalized windows, use the desktop work area.
1617 screen
->GetAvailRect(&left
, &top
, &width
, &height
);
1619 // For full screen windows, use the desktop.
1620 screen
->GetRect(&left
, &top
, &width
, &height
);
1622 screenRect
.left
= left
;
1623 screenRect
.right
= left
+width
;
1624 screenRect
.top
= top
;
1625 screenRect
.bottom
= top
+height
;
1626 doConstrain
= PR_TRUE
;
1630 HDC dc
= ::GetDC(mWnd
);
1632 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1633 if (mSizeMode
!= nsSizeMode_Fullscreen
) {
1634 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &screenRect
, 0);
1636 screenRect
.left
= screenRect
.top
= 0;
1637 screenRect
.right
= GetSystemMetrics(SM_CXFULLSCREEN
);
1638 screenRect
.bottom
= GetSystemMetrics(SM_CYFULLSCREEN
);
1640 doConstrain
= PR_TRUE
;
1642 ::ReleaseDC(mWnd
, dc
);
1648 if (*aX
< screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
)
1649 *aX
= screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
;
1650 else if (*aX
>= screenRect
.right
- kWindowPositionSlop
)
1651 *aX
= screenRect
.right
- kWindowPositionSlop
;
1653 if (*aY
< screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
)
1654 *aY
= screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
;
1655 else if (*aY
>= screenRect
.bottom
- kWindowPositionSlop
)
1656 *aY
= screenRect
.bottom
- kWindowPositionSlop
;
1660 if (*aX
< screenRect
.left
)
1661 *aX
= screenRect
.left
;
1662 else if (*aX
>= screenRect
.right
- mBounds
.width
)
1663 *aX
= screenRect
.right
- mBounds
.width
;
1665 if (*aY
< screenRect
.top
)
1666 *aY
= screenRect
.top
;
1667 else if (*aY
>= screenRect
.bottom
- mBounds
.height
)
1668 *aY
= screenRect
.bottom
- mBounds
.height
;
1674 /**************************************************************
1676 * SECTION: nsIWidget::Enable, nsIWidget::IsEnabled
1678 * Enabling and disabling the widget.
1680 **************************************************************/
1682 // Enable/disable this component
1683 NS_METHOD
nsWindow::Enable(PRBool bState
)
1686 ::EnableWindow(mWnd
, bState
);
1691 // Return the current enable state
1692 NS_METHOD
nsWindow::IsEnabled(PRBool
*aState
)
1694 NS_ENSURE_ARG_POINTER(aState
);
1697 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(::GetAncestor(mWnd
, GA_ROOT
)));
1699 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(mWnd
));
1706 /**************************************************************
1708 * SECTION: nsIWidget::SetFocus
1710 * Give the focus to this widget.
1712 **************************************************************/
1714 NS_METHOD
nsWindow::SetFocus(PRBool aRaise
)
1717 #ifdef WINSTATE_DEBUG_OUTPUT
1718 if (mWnd
== GetTopLevelHWND(mWnd
))
1719 printf("*** SetFocus: [ top] raise=%d\n", aRaise
);
1721 printf("*** SetFocus: [child] raise=%d\n", aRaise
);
1723 // Uniconify, if necessary
1724 HWND toplevelWnd
= GetTopLevelHWND(mWnd
);
1725 if (aRaise
&& ::IsIconic(toplevelWnd
)) {
1726 ::ShowWindow(toplevelWnd
, SW_RESTORE
);
1734 /**************************************************************
1738 * GetBounds, GetClientBounds, GetScreenBounds, GetClientOffset
1739 * SetDrawsInTitlebar, GetNonClientMargins, SetNonClientMargins
1741 * Bound calculations.
1743 **************************************************************/
1745 // Return the window's full dimensions in screen coordinates.
1746 // If the window has a parent, converts the origin to an offset
1747 // of the parent's screen origin.
1748 NS_METHOD
nsWindow::GetBounds(nsIntRect
&aRect
)
1752 VERIFY(::GetWindowRect(mWnd
, &r
));
1755 aRect
.width
= r
.right
- r
.left
;
1756 aRect
.height
= r
.bottom
- r
.top
;
1758 // chrome on parent:
1759 // ___ 5,5 (chrome start)
1760 // | ____ 10,10 (client start)
1761 // | | ____ 20,20 (child start)
1763 // 20,20 - 5,5 = 15,15 (??)
1764 // minus GetClientOffset:
1765 // 15,15 - 5,5 = 10,10
1767 // no chrome on parent:
1768 // ______ 10,10 (win start)
1769 // | ____ 20,20 (child start)
1771 // 20,20 - 10,10 = 10,10
1773 // walking the chain:
1774 // ___ 5,5 (chrome start)
1775 // | ___ 10,10 (client start)
1776 // | | ___ 20,20 (child start)
1777 // | | | __ 30,30 (child start)
1779 // 30,30 - 20,20 = 10,10 (offset from second child to first)
1780 // 20,20 - 5,5 = 15,15 + 10,10 = 25,25 (??)
1781 // minus GetClientOffset:
1782 // 25,25 - 5,5 = 20,20 (offset from second child to parent client)
1784 // convert coordinates if parent exists
1785 HWND parent
= ::GetParent(mWnd
);
1788 VERIFY(::GetWindowRect(parent
, &pr
));
1791 // adjust for chrome
1792 nsWindow
* pWidget
= static_cast<nsWindow
*>(GetParent());
1793 if (pWidget
&& pWidget
->IsTopLevelWidget()) {
1794 nsIntPoint clientOffset
;
1795 pWidget
->GetClientOffset(clientOffset
);
1796 r
.left
-= clientOffset
.x
;
1797 r
.top
-= clientOffset
.y
;
1809 // Get this component dimension
1810 NS_METHOD
nsWindow::GetClientBounds(nsIntRect
&aRect
)
1814 VERIFY(::GetClientRect(mWnd
, &r
));
1819 aRect
.width
= r
.right
- r
.left
;
1820 aRect
.height
= r
.bottom
- r
.top
;
1823 aRect
.SetRect(0,0,0,0);
1828 // Like GetBounds, but don't offset by the parent
1829 NS_METHOD
nsWindow::GetScreenBounds(nsIntRect
&aRect
)
1833 VERIFY(::GetWindowRect(mWnd
, &r
));
1835 aRect
.width
= r
.right
- r
.left
;
1836 aRect
.height
= r
.bottom
- r
.top
;
1845 // return the x,y offset of the client area from the origin
1846 // of the window. If the window is borderless returns (0,0).
1847 NS_METHOD
nsWindow::GetClientOffset(nsIntPoint
&aPt
)
1855 GetWindowRect(mWnd
, &r1
);
1856 nsIntPoint pt
= WidgetToScreenOffset();
1857 aPt
.x
= pt
.x
- r1
.left
;
1858 aPt
.y
= pt
.y
- r1
.top
;
1863 nsWindow::SetDrawsInTitlebar(PRBool aState
)
1865 nsWindow
* window
= GetTopLevelWindow(PR_TRUE
);
1866 if (window
&& window
!= this) {
1867 return window
->SetDrawsInTitlebar(aState
);
1871 // left, top, right, bottom for nsIntMargin
1872 nsIntMargin
margins(-1, 0, -1, -1);
1873 SetNonClientMargins(margins
);
1876 nsIntMargin
margins(-1, -1, -1, -1);
1877 SetNonClientMargins(margins
);
1882 nsWindow::GetNonClientMargins(nsIntMargin
&margins
)
1884 nsWindow
* window
= GetTopLevelWindow(PR_TRUE
);
1885 if (window
&& window
!= this) {
1886 return window
->GetNonClientMargins(margins
);
1889 if (mCustomNonClient
) {
1890 margins
= mNonClientMargins
;
1894 margins
.top
= GetSystemMetrics(SM_CYCAPTION
);
1895 margins
.bottom
= GetSystemMetrics(SM_CYFRAME
);
1896 margins
.top
+= margins
.bottom
;
1897 margins
.left
= margins
.right
= GetSystemMetrics(SM_CYFRAME
);
1903 nsWindow::ResetLayout()
1905 // This will trigger a frame changed event, triggering
1906 // nc calc size and a sizemode gecko event.
1907 SetWindowPos(mWnd
, 0, 0, 0, 0, 0,
1908 SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|
1909 SWP_NOOWNERZORDER
|SWP_NOSIZE
|SWP_NOZORDER
);
1911 // If hidden, just send the frame changed event for now.
1915 // Send a gecko size event to trigger reflow.
1916 RECT clientRc
= {0};
1917 GetClientRect(mWnd
, &clientRc
);
1918 nsIntRect
evRect(nsWindowGfx::ToIntRect(clientRc
));
1921 // Invalidate and update
1922 Invalidate(PR_FALSE
);
1925 // Called when the window layout changes: full screen mode transitions,
1926 // theme changes, and composition changes. Calculates the new non-client
1927 // margins and fires off a frame changed event, which triggers an nc calc
1928 // size windows event, kicking the changes in.
1930 nsWindow::UpdateNonClientMargins(PRInt32 aSizeMode
, PRBool aReflowWindow
)
1932 if (!mCustomNonClient
)
1935 // XXX Temp disable margins until frame rendering is supported
1936 mCompositorFlag
= PR_TRUE
;
1937 if(!nsUXThemeData::CheckForCompositor()) {
1938 mCompositorFlag
= PR_FALSE
;
1942 mNonClientOffset
.top
= mNonClientOffset
.bottom
=
1943 mNonClientOffset
.left
= mNonClientOffset
.right
= 0;
1945 if (aSizeMode
== -1)
1946 aSizeMode
= mSizeMode
;
1948 if (aSizeMode
== nsSizeMode_Minimized
||
1949 aSizeMode
== nsSizeMode_Fullscreen
) {
1950 mCaptionHeight
= mVertResizeMargin
= mHorResizeMargin
= 0;
1954 // Note, for maximized windows, we need to continue to offset the client by
1955 // thick frame margins of a normal window, since windows expects this
1956 // in it's DwmDefWndProc hit testing.
1957 mCaptionHeight
= GetSystemMetrics(SM_CYCAPTION
);
1958 mHorResizeMargin
= GetSystemMetrics(SM_CXFRAME
);
1959 mVertResizeMargin
= GetSystemMetrics(SM_CYFRAME
);
1961 mCaptionHeight
+= mVertResizeMargin
;
1963 // If a margin value is 0, set the offset to the default size of the frame.
1964 // If a margin is -1, leave as default, and if a margin > 0, set the offset
1965 // so that the frame size is equal to the margin value.
1966 if (!mNonClientMargins
.top
)
1967 mNonClientOffset
.top
= mCaptionHeight
;
1968 else if (mNonClientMargins
.top
> 0)
1969 mNonClientOffset
.top
= mCaptionHeight
- mNonClientMargins
.top
;
1971 if (!mNonClientMargins
.left
)
1972 mNonClientOffset
.left
= mHorResizeMargin
;
1973 else if (mNonClientMargins
.left
> 0)
1974 mNonClientOffset
.left
= mHorResizeMargin
- mNonClientMargins
.left
;
1976 if (!mNonClientMargins
.right
)
1977 mNonClientOffset
.right
= mHorResizeMargin
;
1978 else if (mNonClientMargins
.right
> 0)
1979 mNonClientOffset
.right
= mHorResizeMargin
- mNonClientMargins
.right
;
1981 if (!mNonClientMargins
.bottom
)
1982 mNonClientOffset
.bottom
= mVertResizeMargin
;
1983 else if (mNonClientMargins
.bottom
> 0)
1984 mNonClientOffset
.bottom
= mVertResizeMargin
- mNonClientMargins
.bottom
;
1986 NS_ASSERTION(mNonClientOffset
.top
>= 0, "non-client top margin is negative!");
1987 NS_ASSERTION(mNonClientOffset
.left
>= 0, "non-client left margin is negative!");
1988 NS_ASSERTION(mNonClientOffset
.right
>= 0, "non-client right margin is negative!");
1989 NS_ASSERTION(mNonClientOffset
.bottom
>= 0, "non-client bottom margin is negative!");
1991 if (mNonClientOffset
.top
< 0)
1992 mNonClientOffset
.top
= 0;
1993 if (mNonClientOffset
.left
< 0)
1994 mNonClientOffset
.left
= 0;
1995 if (mNonClientOffset
.right
< 0)
1996 mNonClientOffset
.right
= 0;
1997 if (mNonClientOffset
.bottom
< 0)
1998 mNonClientOffset
.bottom
= 0;
2000 if (aReflowWindow
) {
2001 // Force a reflow of content based on the new client
2010 nsWindow::SetNonClientMargins(nsIntMargin
&margins
)
2012 if (!mIsTopWidgetWindow
||
2013 mBorderStyle
& eBorderStyle_none
||
2015 return NS_ERROR_INVALID_ARG
;
2017 // Request for a reset
2018 if (margins
.top
== -1 && margins
.left
== -1 &&
2019 margins
.right
== -1 && margins
.bottom
== -1) {
2020 mCustomNonClient
= PR_FALSE
;
2021 mNonClientMargins
= margins
;
2022 // Force a reflow of content based on the new client
2028 if (margins
.top
< -1 || margins
.bottom
< -1 ||
2029 margins
.left
< -1 || margins
.right
< -1)
2030 return NS_ERROR_INVALID_ARG
;
2032 mNonClientMargins
= margins
;
2033 mCustomNonClient
= PR_TRUE
;
2034 if (!UpdateNonClientMargins()) {
2035 NS_WARNING("UpdateNonClientMargins failed!");
2042 /**************************************************************
2044 * SECTION: nsIWidget::SetBackgroundColor
2046 * Sets the window background paint color.
2048 **************************************************************/
2050 NS_METHOD
nsWindow::SetBackgroundColor(const nscolor
&aColor
)
2052 nsBaseWidget::SetBackgroundColor(aColor
);
2055 ::DeleteObject(mBrush
);
2057 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
2060 ::SetClassLongPtrW(mWnd
, GCLP_HBRBACKGROUND
, (LONG_PTR
)mBrush
);
2066 /**************************************************************
2068 * SECTION: nsIWidget::SetCursor
2070 * SetCursor and related utilities for manging cursor state.
2072 **************************************************************/
2074 // Set this component cursor
2075 NS_METHOD
nsWindow::SetCursor(nsCursor aCursor
)
2077 // Only change cursor if it's changing
2079 //XXX mCursor isn't always right. Scrollbars and others change it, too.
2080 //XXX If we want this optimization we need a better way to do it.
2081 //if (aCursor != mCursor) {
2082 HCURSOR newCursor
= NULL
;
2085 case eCursor_select
:
2086 newCursor
= ::LoadCursor(NULL
, IDC_IBEAM
);
2090 newCursor
= ::LoadCursor(NULL
, IDC_WAIT
);
2093 case eCursor_hyperlink
:
2095 newCursor
= ::LoadCursor(NULL
, IDC_HAND
);
2099 case eCursor_standard
:
2100 newCursor
= ::LoadCursor(NULL
, IDC_ARROW
);
2103 case eCursor_n_resize
:
2104 case eCursor_s_resize
:
2105 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
2108 case eCursor_w_resize
:
2109 case eCursor_e_resize
:
2110 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
2113 case eCursor_nw_resize
:
2114 case eCursor_se_resize
:
2115 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
2118 case eCursor_ne_resize
:
2119 case eCursor_sw_resize
:
2120 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
2123 case eCursor_crosshair
:
2124 newCursor
= ::LoadCursor(NULL
, IDC_CROSS
);
2128 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
2132 newCursor
= ::LoadCursor(NULL
, IDC_HELP
);
2135 case eCursor_copy
: // CSS3
2136 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COPY
));
2140 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ALIAS
));
2144 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_CELL
));
2148 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRAB
));
2151 case eCursor_grabbing
:
2152 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRABBING
));
2155 case eCursor_spinning
:
2156 newCursor
= ::LoadCursor(NULL
, IDC_APPSTARTING
);
2159 case eCursor_context_menu
:
2160 // XXX this CSS3 cursor needs to be implemented
2163 case eCursor_zoom_in
:
2164 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMIN
));
2167 case eCursor_zoom_out
:
2168 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMOUT
));
2171 case eCursor_not_allowed
:
2172 case eCursor_no_drop
:
2173 newCursor
= ::LoadCursor(NULL
, IDC_NO
);
2176 case eCursor_col_resize
:
2177 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COLRESIZE
));
2180 case eCursor_row_resize
:
2181 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ROWRESIZE
));
2184 case eCursor_vertical_text
:
2185 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_VERTICALTEXT
));
2188 case eCursor_all_scroll
:
2189 // XXX not 100% appropriate perhaps
2190 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
2193 case eCursor_nesw_resize
:
2194 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
2197 case eCursor_nwse_resize
:
2198 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
2201 case eCursor_ns_resize
:
2202 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
2205 case eCursor_ew_resize
:
2206 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
2210 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_NONE
));
2214 NS_ERROR("Invalid cursor type");
2218 if (NULL
!= newCursor
) {
2220 HCURSOR oldCursor
= ::SetCursor(newCursor
);
2222 if (sHCursor
== oldCursor
) {
2223 NS_IF_RELEASE(sCursorImgContainer
);
2224 if (sHCursor
!= NULL
)
2225 ::DestroyIcon(sHCursor
);
2233 // Setting the actual cursor
2234 NS_IMETHODIMP
nsWindow::SetCursor(imgIContainer
* aCursor
,
2235 PRUint32 aHotspotX
, PRUint32 aHotspotY
)
2237 if (sCursorImgContainer
== aCursor
&& sHCursor
) {
2238 ::SetCursor(sHCursor
);
2246 rv
= aCursor
->GetWidth(&width
);
2247 NS_ENSURE_SUCCESS(rv
, rv
);
2248 rv
= aCursor
->GetHeight(&height
);
2249 NS_ENSURE_SUCCESS(rv
, rv
);
2251 // Reject cursors greater than 128 pixels in either direction, to prevent
2253 // XXX ideally we should rescale. Also, we could modify the API to
2254 // allow trusted content to set larger cursors.
2255 if (width
> 128 || height
> 128)
2256 return NS_ERROR_NOT_AVAILABLE
;
2259 rv
= nsWindowGfx::CreateIcon(aCursor
, PR_TRUE
, aHotspotX
, aHotspotY
, &cursor
);
2260 NS_ENSURE_SUCCESS(rv
, rv
);
2262 mCursor
= nsCursor(-1);
2263 ::SetCursor(cursor
);
2265 NS_IF_RELEASE(sCursorImgContainer
);
2266 sCursorImgContainer
= aCursor
;
2267 NS_ADDREF(sCursorImgContainer
);
2269 if (sHCursor
!= NULL
)
2270 ::DestroyIcon(sHCursor
);
2276 /**************************************************************
2278 * SECTION: nsIWidget::Get/SetTransparencyMode
2280 * Manage the transparency mode of the top-level window
2281 * containing this widget.
2283 **************************************************************/
2286 nsTransparencyMode
nsWindow::GetTransparencyMode()
2288 return GetTopLevelWindow(PR_TRUE
)->GetWindowTranslucencyInner();
2291 void nsWindow::SetTransparencyMode(nsTransparencyMode aMode
)
2293 GetTopLevelWindow(PR_TRUE
)->SetWindowTranslucencyInner(aMode
);
2297 BOOL CALLBACK
AddClientAreaToRegion(HWND hWnd
, LPARAM lParam
) {
2298 nsIntRegion
*region
= reinterpret_cast<nsIntRegion
*>(lParam
);
2301 ::GetWindowRect(hWnd
, &clientRect
);
2302 nsIntRect
clientArea(clientRect
.left
, clientRect
.top
,
2303 clientRect
.right
- clientRect
.left
,
2304 clientRect
.bottom
- clientRect
.top
);
2305 region
->Or(*region
, clientArea
);
2310 void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion
&aDirtyRegion
,
2311 const nsIntRegion
&aPossiblyTransparentRegion
) {
2312 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2313 if (mTransparencyMode
!= eTransparencyGlass
)
2316 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2317 nsWindow
* topWindow
= GetNSWindowPtr(hWnd
);
2322 mPossiblyTransparentRegion
.Sub(mPossiblyTransparentRegion
, aDirtyRegion
);
2323 mPossiblyTransparentRegion
.Or(mPossiblyTransparentRegion
, aPossiblyTransparentRegion
);
2325 nsIntRegion childWindowRegion
;
2327 ::EnumChildWindows(mWnd
, AddClientAreaToRegion
, reinterpret_cast<LPARAM
>(&childWindowRegion
));
2329 nsIntPoint clientOffset
;
2330 GetClientOffset(clientOffset
);
2331 childWindowRegion
.MoveBy(-clientOffset
);
2334 ::GetWindowRect(mWnd
, &r
);
2335 childWindowRegion
.MoveBy(-r
.left
, -r
.top
);
2337 nsIntRect clientBounds
;
2338 topWindow
->GetClientBounds(clientBounds
);
2339 nsIntRegion opaqueRegion
;
2340 opaqueRegion
.Sub(clientBounds
, mPossiblyTransparentRegion
);
2341 opaqueRegion
.Or(opaqueRegion
, childWindowRegion
);
2342 // Sometimes child windows overlap our bounds
2343 opaqueRegion
.And(opaqueRegion
, clientBounds
);
2345 MARGINS margins
= { 0, 0, 0, 0 };
2346 DWORD_PTR dwStyle
= ::GetWindowLongPtrW(hWnd
, GWL_STYLE
);
2348 // If there is no opaque region or hidechrome=true, set margins
2349 // to support a full sheet of glass.
2350 if (opaqueRegion
.IsEmpty() || mHideChrome
) {
2351 // Comments in MSDN indicate all values must be set to -1
2352 margins
.cxLeftWidth
= margins
.cxRightWidth
=
2353 margins
.cyTopHeight
= margins
.cyBottomHeight
= -1;
2355 // Find the largest rectangle and use that to calculate the inset
2356 nsIntRect largest
= opaqueRegion
.GetLargestRectangle();
2357 margins
.cxLeftWidth
= largest
.x
;
2358 margins
.cxRightWidth
= clientBounds
.width
- largest
.XMost();
2359 margins
.cyTopHeight
= largest
.y
;
2360 margins
.cyBottomHeight
= clientBounds
.height
- largest
.YMost();
2363 // Only update glass area if there are changes
2364 if (memcmp(&mGlassMargins
, &margins
, sizeof mGlassMargins
)) {
2365 mGlassMargins
= margins
;
2368 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2371 void nsWindow::UpdateGlass()
2373 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2374 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2376 // DWMNCRP_USEWINDOWSTYLE - The non-client rendering area is
2377 // rendered based on the window style.
2378 // DWMNCRP_ENABLED - The non-client area rendering is
2379 // enabled; the window style is ignored.
2380 DWMNCRENDERINGPOLICY policy
= DWMNCRP_USEWINDOWSTYLE
;
2381 if (mTransparencyMode
== eTransparencyGlass
) {
2382 policy
= DWMNCRP_ENABLED
;
2385 // Extends the window frame behind the client area
2386 if(nsUXThemeData::CheckForCompositor()) {
2387 nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd
, &mGlassMargins
);
2388 nsUXThemeData::dwmSetWindowAttributePtr(hWnd
, DWMWA_NCRENDERING_POLICY
, &policy
, sizeof policy
);
2390 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2394 /**************************************************************
2396 * SECTION: nsIWidget::HideWindowChrome
2398 * Show or hide window chrome.
2400 **************************************************************/
2402 NS_IMETHODIMP
nsWindow::HideWindowChrome(PRBool aShouldHide
)
2404 HWND hwnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2405 if (!GetNSWindowPtr(hwnd
))
2407 NS_WARNING("Trying to hide window decorations in an embedded context");
2408 return NS_ERROR_FAILURE
;
2411 if (mHideChrome
== aShouldHide
)
2414 DWORD_PTR style
, exStyle
;
2415 mHideChrome
= aShouldHide
;
2417 DWORD_PTR tempStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2418 DWORD_PTR tempExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2420 style
= tempStyle
& ~(WS_CAPTION
| WS_THICKFRAME
);
2421 exStyle
= tempExStyle
& ~(WS_EX_DLGMODALFRAME
| WS_EX_WINDOWEDGE
|
2422 WS_EX_CLIENTEDGE
| WS_EX_STATICEDGE
);
2424 mOldStyle
= tempStyle
;
2425 mOldExStyle
= tempExStyle
;
2428 if (!mOldStyle
|| !mOldExStyle
) {
2429 mOldStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2430 mOldExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2434 exStyle
= mOldExStyle
;
2437 VERIFY_WINDOW_STYLE(style
);
2438 ::SetWindowLongPtrW(hwnd
, GWL_STYLE
, style
);
2439 ::SetWindowLongPtrW(hwnd
, GWL_EXSTYLE
, exStyle
);
2444 /**************************************************************
2446 * SECTION: nsIWidget::Invalidate
2448 * Invalidate an area of the client for painting.
2450 **************************************************************/
2452 // Invalidate this component visible area
2453 NS_METHOD
nsWindow::Invalidate(PRBool aIsSynchronous
)
2457 #ifdef WIDGET_DEBUG_OUTPUT
2458 debug_DumpInvalidate(stdout
,
2462 nsCAutoString("noname"),
2464 #endif // WIDGET_DEBUG_OUTPUT
2466 VERIFY(::InvalidateRect(mWnd
, NULL
, FALSE
));
2468 if (aIsSynchronous
) {
2469 VERIFY(::UpdateWindow(mWnd
));
2475 // Invalidate this component visible area
2476 NS_METHOD
nsWindow::Invalidate(const nsIntRect
& aRect
, PRBool aIsSynchronous
)
2480 #ifdef WIDGET_DEBUG_OUTPUT
2481 debug_DumpInvalidate(stdout
,
2485 nsCAutoString("noname"),
2487 #endif // WIDGET_DEBUG_OUTPUT
2491 rect
.left
= aRect
.x
;
2493 rect
.right
= aRect
.x
+ aRect
.width
;
2494 rect
.bottom
= aRect
.y
+ aRect
.height
;
2496 VERIFY(::InvalidateRect(mWnd
, &rect
, FALSE
));
2498 if (aIsSynchronous
) {
2499 VERIFY(::UpdateWindow(mWnd
));
2506 nsWindow::MakeFullScreen(PRBool aFullScreen
)
2508 #if WINCE_WINDOWS_MOBILE
2511 SetForegroundWindow(mWnd
);
2512 if (nsWindowCE::sMenuBarShown
) {
2514 memset(&sipInfo
, 0, sizeof(SIPINFO
));
2515 sipInfo
.cbSize
= sizeof(SIPINFO
);
2516 if (SipGetInfo(&sipInfo
))
2517 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
),
2518 sipInfo
.rcVisibleDesktop
.bottom
);
2520 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
),
2521 GetSystemMetrics(SM_CYSCREEN
));
2523 if (GetWindowRect(nsWindowCE::sSoftKeyMenuBarHandle
, &menuBarRect
) &&
2524 menuBarRect
.top
< rc
.bottom
)
2525 rc
.bottom
= menuBarRect
.top
;
2526 SHFullScreen(mWnd
, SHFS_HIDETASKBAR
| SHFS_HIDESTARTICON
| SHFS_SHOWSIPBUTTON
);
2529 SHFullScreen(mWnd
, SHFS_HIDETASKBAR
| SHFS_HIDESTARTICON
| SHFS_HIDESIPBUTTON
);
2530 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2534 SHFullScreen(mWnd
, SHFS_SHOWTASKBAR
| SHFS_SHOWSTARTICON
);
2535 SystemParametersInfo(SPI_GETWORKAREA
, 0, &rc
, FALSE
);
2539 mSizeMode
= nsSizeMode_Fullscreen
;
2541 // nsBaseWidget hides the chrome and resizes the window, replicate that here
2542 HideWindowChrome(aFullScreen
);
2543 Resize(rc
.left
, rc
.top
, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, PR_TRUE
);
2550 if (mSizeMode
!= nsSizeMode_Fullscreen
)
2551 mOldSizeMode
= mSizeMode
;
2552 SetSizeMode(nsSizeMode_Fullscreen
);
2554 SetSizeMode(mOldSizeMode
);
2557 UpdateNonClientMargins();
2559 // Will call hide chrome, reposition window. Note this will
2560 // also cache dimensions for restoration, so it should only
2561 // be called once per fullscreen request.
2562 return nsBaseWidget::MakeFullScreen(aFullScreen
);
2566 /**************************************************************
2568 * SECTION: nsIWidget::Update
2570 * Force a synchronous repaint of the window.
2572 **************************************************************/
2574 NS_IMETHODIMP
nsWindow::Update()
2576 nsresult rv
= NS_OK
;
2578 // updates can come through for windows no longer holding an mWnd during
2579 // deletes triggered by JavaScript in buttons with mouse feedback
2581 VERIFY(::UpdateWindow(mWnd
));
2586 /**************************************************************
2588 * SECTION: nsIWidget::Scroll
2590 * Scroll this widget.
2592 **************************************************************/
2595 ClipRegionContainedInRect(const nsTArray
<nsIntRect
>& aClipRects
,
2596 const nsIntRect
& aRect
)
2598 for (PRUint32 i
= 0; i
< aClipRects
.Length(); ++i
) {
2599 if (!aRect
.Contains(aClipRects
[i
]))
2605 // This function determines whether the given window has a descendant that
2606 // does not intersect the given aScreenRect. If we encounter a window owned
2607 // by another thread (which includes another process, since thread IDs
2608 // are unique system-wide), then we give up and conservatively return true.
2610 HasDescendantWindowOutsideRect(DWORD aThisThreadID
, HWND aWnd
,
2611 const RECT
& aScreenRect
)
2613 // If the window is owned by another thread, give up now, don't try to
2614 // look at its children since they could change asynchronously.
2615 // XXX should we try harder here for out-of-process plugins?
2616 if (GetWindowThreadProcessId(aWnd
, NULL
) != aThisThreadID
) {
2619 for (HWND child
= ::GetWindow(aWnd
, GW_CHILD
); child
;
2620 child
= ::GetWindow(child
, GW_HWNDNEXT
)) {
2621 RECT childScreenRect
;
2622 ::GetWindowRect(child
, &childScreenRect
);
2624 if (!::IntersectRect(&result
, &childScreenRect
, &aScreenRect
)) {
2628 if (HasDescendantWindowOutsideRect(aThisThreadID
, child
, aScreenRect
)) {
2637 InvalidateRgnInWindowSubtree(HWND aWnd
, HRGN aRgn
, HRGN aTmpRgn
)
2640 ::GetClientRect(aWnd
, &clientRect
);
2641 ::SetRectRgn(aTmpRgn
, clientRect
.left
, clientRect
.top
,
2642 clientRect
.right
, clientRect
.bottom
);
2643 if (::CombineRgn(aTmpRgn
, aTmpRgn
, aRgn
, RGN_AND
) == NULLREGION
) {
2647 ::InvalidateRgn(aWnd
, aTmpRgn
, FALSE
);
2649 for (HWND child
= ::GetWindow(aWnd
, GW_CHILD
); child
;
2650 child
= ::GetWindow(child
, GW_HWNDNEXT
)) {
2651 POINT pt
= { 0, 0 };
2652 ::MapWindowPoints(child
, aWnd
, &pt
, 1);
2653 ::OffsetRgn(aRgn
, -pt
.x
, -pt
.y
);
2654 InvalidateRgnInWindowSubtree(child
, aRgn
, aTmpRgn
);
2655 ::OffsetRgn(aRgn
, pt
.x
, pt
.y
);
2660 nsWindow::Scroll(const nsIntPoint
& aDelta
,
2661 const nsTArray
<nsIntRect
>& aDestRects
,
2662 const nsTArray
<Configuration
>& aConfigurations
)
2664 // We use SW_SCROLLCHILDREN if all the windows that intersect the
2665 // affected area are moving by the scroll amount.
2666 // First, build the set of widgets that are to be moved by the scroll
2668 // At the same time, set the clip region of all changed windows to the
2669 // intersection of the current and new regions.
2670 nsTHashtable
<nsPtrHashKey
<nsWindow
> > scrolledWidgets
;
2671 scrolledWidgets
.Init();
2672 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
2673 const Configuration
& configuration
= aConfigurations
[i
];
2674 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
2675 NS_ASSERTION(w
->GetParent() == this,
2676 "Configured widget is not a child");
2677 if (configuration
.mBounds
== w
->mBounds
+ aDelta
) {
2678 scrolledWidgets
.PutEntry(w
);
2680 w
->SetWindowClipRegion(configuration
.mClipRegion
, PR_TRUE
);
2683 // Create temporary regions
2684 HRGN updateRgn
= ::CreateRectRgn(0, 0, 0, 0);
2689 HRGN destRgn
= ::CreateRectRgn(0, 0, 0, 0);
2692 ::DeleteObject((HGDIOBJ
)updateRgn
);
2696 DWORD ourThreadID
= GetWindowThreadProcessId(mWnd
, NULL
);
2698 for (BlitRectIter
iter(aDelta
, aDestRects
); !iter
.IsDone(); ++iter
) {
2699 const nsIntRect
& destRect
= iter
.Rect();
2700 nsIntRect affectedRect
;
2701 affectedRect
.UnionRect(destRect
, destRect
- aDelta
);
2702 UINT flags
= SW_SCROLLCHILDREN
;
2703 // Now check if any of our children would be affected by
2704 // SW_SCROLLCHILDREN but not supposed to scroll.
2705 for (nsWindow
* w
= static_cast<nsWindow
*>(GetFirstChild()); w
;
2706 w
= static_cast<nsWindow
*>(w
->GetNextSibling())) {
2707 if (w
->mBounds
.Intersects(affectedRect
)) {
2708 // This child will be affected
2709 nsPtrHashKey
<nsWindow
>* entry
= scrolledWidgets
.GetEntry(w
);
2711 // It's supposed to be scrolled, so we can still use
2712 // SW_SCROLLCHILDREN. But don't allow SW_SCROLLCHILDREN to be
2713 // used on it again by a later rectangle; we don't want it to
2715 scrolledWidgets
.RawRemoveEntry(entry
);
2717 nsIntPoint screenOffset
= WidgetToScreenOffset();
2718 RECT screenAffectedRect
= {
2719 screenOffset
.x
+ affectedRect
.x
,
2720 screenOffset
.y
+ affectedRect
.y
,
2721 screenOffset
.x
+ affectedRect
.XMost(),
2722 screenOffset
.y
+ affectedRect
.YMost()
2724 if (HasDescendantWindowOutsideRect(ourThreadID
, w
->mWnd
,
2725 screenAffectedRect
)) {
2726 // SW_SCROLLCHILDREN seems to not move descendant windows
2727 // that don't intersect the scrolled rectangle, *even if* the
2728 // immediate child window of the scrolled window *does* intersect
2729 // the scrolled window. So if w has a descendant window
2730 // that would not be moved, SW_SCROLLCHILDREN will hopelessly mess
2731 // things up and we must not use it.
2732 flags
&= ~SW_SCROLLCHILDREN
;
2735 flags
&= ~SW_SCROLLCHILDREN
;
2736 // We may have removed some children from scrolledWidgets even
2737 // though we decide here to not use SW_SCROLLCHILDREN. That's OK,
2738 // it just means that we might not use SW_SCROLLCHILDREN
2739 // for a later rectangle when we could have.
2745 if (flags
& SW_SCROLLCHILDREN
2746 #ifdef CAIRO_HAS_D2D_SURFACE
2747 && !mD2DWindowSurface
2750 // ScrollWindowEx will send WM_MOVE to each moved window to tell it
2751 // its new position. Unfortunately those messages don't reach our
2752 // WM_MOVE handler for some plugins, so we have to update their
2753 // mBounds here. For windows that do receive WM_MOVE, this is OK,
2754 // they'll just overwrite mBounds again with the correct value.
2755 for (nsWindow
* w
= static_cast<nsWindow
*>(GetFirstChild()); w
;
2756 w
= static_cast<nsWindow
*>(w
->GetNextSibling())) {
2757 if (w
->mBounds
.Intersects(affectedRect
)) {
2758 w
->mBounds
+= aDelta
;
2763 RECT clip
= { affectedRect
.x
, affectedRect
.y
, affectedRect
.XMost(), affectedRect
.YMost() };
2764 #ifdef CAIRO_HAS_D2D_SURFACE
2765 if (mD2DWindowSurface
) {
2766 mD2DWindowSurface
->Scroll(aDelta
, affectedRect
);
2768 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
2769 const Configuration
& configuration
= aConfigurations
[i
];
2770 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
2771 w
->Invalidate(PR_FALSE
);
2774 // Get the system clip twice, offset one by the delta. This will make
2775 // systemClip contain the area of the systemClip, and movedSystemClip
2776 // contain the area after scrolling that was covered by the systemClip.
2777 HRGN systemClip
= ::CreateRectRgn(0, 0, 0, 0);
2778 HRGN movedSystemClip
= ::CreateRectRgn(0, 0, 0, 0);
2779 HDC dc
= ::GetDC(mWnd
);
2780 ::GetRandomRgn(dc
, systemClip
, SYSRGN
);
2781 ::GetRandomRgn(dc
, movedSystemClip
, SYSRGN
);
2782 ::OffsetRgn(movedSystemClip
, aDelta
.x
, aDelta
.y
);
2784 // RGN_DIFF will return the parts inside 'systemClip' but -not- inside
2785 // movedSystemClip. This is the area that was clipped (and possibly not
2786 // properly updated) before.
2787 ::CombineRgn(systemClip
, systemClip
, movedSystemClip
, RGN_DIFF
);
2789 // The systemClip is in screen coordinates, we need client coordinates.
2791 ::ClientToScreen(mWnd
, &p
);
2792 ::OffsetRgn(systemClip
, -p
.x
, -p
.y
);
2794 ::GetUpdateRgn(mWnd
, updateRgn
, FALSE
);
2795 ::OffsetRgn(updateRgn
, aDelta
.x
, aDelta
.y
);
2796 ::CombineRgn(updateRgn
, updateRgn
, systemClip
, RGN_OR
);
2798 ::DeleteObject((HGDIOBJ
)systemClip
);
2799 ::DeleteObject((HGDIOBJ
)movedSystemClip
);
2800 ::ReleaseDC(mWnd
, dc
);
2803 ::ScrollWindowEx(mWnd
, aDelta
.x
, aDelta
.y
, &clip
, &clip
, updateRgn
, NULL
, flags
);
2804 #ifdef CAIRO_HAS_D2D_SURFACE
2807 ::SetRectRgn(destRgn
, destRect
.x
, destRect
.y
, destRect
.XMost(), destRect
.YMost());
2808 ::CombineRgn(updateRgn
, updateRgn
, destRgn
, RGN_AND
);
2809 if (flags
& SW_SCROLLCHILDREN
) {
2810 for (nsWindow
* w
= static_cast<nsWindow
*>(GetFirstChild()); w
;
2811 w
= static_cast<nsWindow
*>(w
->GetNextSibling())) {
2812 if ((w
->mBounds
- aDelta
).Intersects(affectedRect
)) {
2813 // Widgets that have been scrolled by SW_SCROLLCHILDREN but which
2814 // were, or are, partly outside the scroll area must be invalidated
2815 // because SW_SCROLLCHILDREN doesn't update parts of widgets outside
2816 // the area it scrolled, even if it moved them.
2817 nsAutoTArray
<nsIntRect
,1> clipRegion
;
2818 w
->GetWindowClipRegion(&clipRegion
);
2819 if (!ClipRegionContainedInRect(clipRegion
,
2820 destRect
- w
->mBounds
.TopLeft()) ||
2821 !ClipRegionContainedInRect(clipRegion
,
2822 destRect
- (w
->mBounds
.TopLeft() - aDelta
))) {
2823 ::SetRectRgn(destRgn
, w
->mBounds
.x
, w
->mBounds
.y
, w
->mBounds
.XMost(), w
->mBounds
.YMost());
2824 ::CombineRgn(updateRgn
, updateRgn
, destRgn
, RGN_OR
);
2829 InvalidateRgnInWindowSubtree(mWnd
, updateRgn
, destRgn
);
2831 ::InvalidateRgn(mWnd
, updateRgn
, FALSE
);
2835 ::DeleteObject((HGDIOBJ
)updateRgn
);
2836 ::DeleteObject((HGDIOBJ
)destRgn
);
2838 // Now make sure all children actually get positioned, sized and clipped
2839 // correctly. If SW_SCROLLCHILDREN already moved widgets to their correct
2840 // locations, then the SetWindowPos calls this triggers will just be
2842 ConfigureChildren(aConfigurations
);
2845 /**************************************************************
2847 * SECTION: Native data storage
2849 * nsIWidget::GetNativeData
2850 * nsIWidget::FreeNativeData
2852 * Set or clear native data based on a constant.
2854 **************************************************************/
2856 // Return some native data according to aDataType
2857 void* nsWindow::GetNativeData(PRUint32 aDataType
)
2859 switch (aDataType
) {
2860 case NS_NATIVE_PLUGIN_PORT
:
2861 case NS_NATIVE_WIDGET
:
2862 case NS_NATIVE_WINDOW
:
2864 case NS_NATIVE_GRAPHIC
:
2865 // XXX: This is sleezy!! Remember to Release the DC after using it!
2867 return (void*)(eTransparencyTransparent
== mTransparencyMode
) ?
2868 mMemoryDC
: ::GetDC(mWnd
);
2870 return (void*)::GetDC(mWnd
);
2873 #ifdef NS_ENABLE_TSF
2874 case NS_NATIVE_TSF_THREAD_MGR
:
2875 return nsTextStore::GetThreadMgr();
2876 case NS_NATIVE_TSF_CATEGORY_MGR
:
2877 return nsTextStore::GetCategoryMgr();
2878 case NS_NATIVE_TSF_DISPLAY_ATTR_MGR
:
2879 return nsTextStore::GetDisplayAttrMgr();
2880 #endif //NS_ENABLE_TSF
2889 // Free some native data according to aDataType
2890 void nsWindow::FreeNativeData(void * data
, PRUint32 aDataType
)
2894 case NS_NATIVE_GRAPHIC
:
2896 if (eTransparencyTransparent
!= mTransparencyMode
)
2897 ::ReleaseDC(mWnd
, (HDC
)data
);
2899 ::ReleaseDC(mWnd
, (HDC
)data
);
2902 case NS_NATIVE_WIDGET
:
2903 case NS_NATIVE_WINDOW
:
2904 case NS_NATIVE_PLUGIN_PORT
:
2911 /**************************************************************
2913 * SECTION: nsIWidget::SetTitle
2915 * Set the main windows title text.
2917 **************************************************************/
2919 NS_METHOD
nsWindow::SetTitle(const nsAString
& aTitle
)
2921 const nsString
& strTitle
= PromiseFlatString(aTitle
);
2922 ::SendMessageW(mWnd
, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)(LPCWSTR
)strTitle
.get());
2926 /**************************************************************
2928 * SECTION: nsIWidget::SetIcon
2930 * Set the main windows icon.
2932 **************************************************************/
2934 NS_METHOD
nsWindow::SetIcon(const nsAString
& aIconSpec
)
2937 // Assume the given string is a local identifier for an icon file.
2939 nsCOMPtr
<nsILocalFile
> iconFile
;
2940 ResolveIconName(aIconSpec
, NS_LITERAL_STRING(".ico"),
2941 getter_AddRefs(iconFile
));
2943 return NS_OK
; // not an error if icon is not found
2945 nsAutoString iconPath
;
2946 iconFile
->GetPath(iconPath
);
2948 // XXX this should use MZLU (see bug 239279)
2952 HICON bigIcon
= (HICON
)::LoadImageW(NULL
,
2953 (LPCWSTR
)iconPath
.get(),
2955 ::GetSystemMetrics(SM_CXICON
),
2956 ::GetSystemMetrics(SM_CYICON
),
2958 HICON smallIcon
= (HICON
)::LoadImageW(NULL
,
2959 (LPCWSTR
)iconPath
.get(),
2961 ::GetSystemMetrics(SM_CXSMICON
),
2962 ::GetSystemMetrics(SM_CYSMICON
),
2966 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
)bigIcon
);
2968 ::DestroyIcon(icon
);
2970 #ifdef DEBUG_SetIcon
2972 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
2973 printf( "\nIcon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
2977 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
)smallIcon
);
2979 ::DestroyIcon(icon
);
2981 #ifdef DEBUG_SetIcon
2983 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
2984 printf( "\nSmall icon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
2991 /**************************************************************
2993 * SECTION: nsIWidget::WidgetToScreenOffset
2995 * Return this widget's origin in screen coordinates.
2997 **************************************************************/
2999 nsIntPoint
nsWindow::WidgetToScreenOffset()
3004 ::ClientToScreen(mWnd
, &point
);
3005 return nsIntPoint(point
.x
, point
.y
);
3008 /**************************************************************
3010 * SECTION: nsIWidget::EnableDragDrop
3012 * Enables/Disables drag and drop of files on this widget.
3014 **************************************************************/
3016 #if !defined(WINCE) // implemented in nsWindowCE.cpp
3017 NS_METHOD
nsWindow::EnableDragDrop(PRBool aEnable
)
3019 NS_ASSERTION(mWnd
, "nsWindow::EnableDragDrop() called after Destroy()");
3021 nsresult rv
= NS_ERROR_FAILURE
;
3023 if (nsnull
== mNativeDragTarget
) {
3024 mNativeDragTarget
= new nsNativeDragTarget(this);
3025 if (NULL
!= mNativeDragTarget
) {
3026 mNativeDragTarget
->AddRef();
3027 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
,TRUE
,FALSE
)) {
3028 if (S_OK
== ::RegisterDragDrop(mWnd
, (LPDROPTARGET
)mNativeDragTarget
)) {
3035 if (nsnull
!= mWnd
&& NULL
!= mNativeDragTarget
) {
3036 ::RevokeDragDrop(mWnd
);
3037 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
, FALSE
, TRUE
)) {
3040 mNativeDragTarget
->DragCancel();
3041 NS_RELEASE(mNativeDragTarget
);
3048 /**************************************************************
3050 * SECTION: nsIWidget::CaptureMouse
3052 * Enables/Disables system mouse capture.
3054 **************************************************************/
3056 NS_METHOD
nsWindow::CaptureMouse(PRBool aCapture
)
3058 if (!nsToolkit::gMouseTrailer
) {
3059 NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
3064 nsToolkit::gMouseTrailer
->SetCaptureWindow(mWnd
);
3067 nsToolkit::gMouseTrailer
->SetCaptureWindow(NULL
);
3070 mIsInMouseCapture
= aCapture
;
3074 /**************************************************************
3076 * SECTION: nsIWidget::CaptureRollupEvents
3078 * Dealing with event rollup on destroy for popups. Enables &
3079 * Disables system capture of any and all events that would
3080 * cause a dropdown to be rolled up.
3082 **************************************************************/
3084 NS_IMETHODIMP
nsWindow::CaptureRollupEvents(nsIRollupListener
* aListener
,
3085 nsIMenuRollup
* aMenuRollup
,
3087 PRBool aConsumeRollupEvent
)
3090 /* we haven't bothered carrying a weak reference to sRollupWidget because
3091 we believe lifespan is properly scoped. this next assertion helps
3092 assure that remains true. */
3093 NS_ASSERTION(!sRollupWidget
, "rollup widget reassigned before release");
3094 sRollupConsumeEvent
= aConsumeRollupEvent
;
3095 NS_IF_RELEASE(sRollupWidget
);
3096 NS_IF_RELEASE(sMenuRollup
);
3097 sRollupListener
= aListener
;
3098 sMenuRollup
= aMenuRollup
;
3099 NS_IF_ADDREF(aMenuRollup
);
3100 sRollupWidget
= this;
3104 if (!sMsgFilterHook
&& !sCallProcHook
&& !sCallMouseHook
) {
3105 RegisterSpecialDropdownHooks();
3107 sProcessHook
= PR_TRUE
;
3111 sRollupListener
= nsnull
;
3112 NS_IF_RELEASE(sMenuRollup
);
3113 NS_IF_RELEASE(sRollupWidget
);
3116 sProcessHook
= PR_FALSE
;
3117 UnregisterSpecialDropdownHooks();
3124 /**************************************************************
3126 * SECTION: nsIWidget::GetAttention
3128 * Bring this window to the user's attention.
3130 **************************************************************/
3132 // Draw user's attention to this window until it comes to foreground.
3134 nsWindow::GetAttention(PRInt32 aCycleCount
)
3139 return NS_ERROR_NOT_INITIALIZED
;
3141 // Don't flash if the flash count is 0 or if the
3142 // top level window is already active.
3143 HWND fgWnd
= ::GetForegroundWindow();
3144 if (aCycleCount
== 0 || fgWnd
== GetTopLevelHWND(mWnd
))
3147 HWND flashWnd
= mWnd
;
3148 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
3149 flashWnd
= ownerWnd
;
3152 // Don't flash if the owner window is active either.
3153 if (fgWnd
== flashWnd
)
3156 DWORD defaultCycleCount
= 0;
3157 ::SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT
, 0, &defaultCycleCount
, 0);
3159 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
3160 FLASHW_ALL
, aCycleCount
> 0 ? aCycleCount
: defaultCycleCount
, 0 };
3161 ::FlashWindowEx(&flashInfo
);
3166 void nsWindow::StopFlashing()
3169 HWND flashWnd
= mWnd
;
3170 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
3171 flashWnd
= ownerWnd
;
3174 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
3175 FLASHW_STOP
, 0, 0 };
3176 ::FlashWindowEx(&flashInfo
);
3180 /**************************************************************
3182 * SECTION: nsIWidget::HasPendingInputEvent
3184 * Ask whether there user input events pending. All input events are
3185 * included, including those not targeted at this nsIwidget instance.
3187 **************************************************************/
3190 nsWindow::HasPendingInputEvent()
3192 // If there is pending input or the user is currently
3193 // moving the window then return true.
3194 // Note: When the user is moving the window WIN32 spins
3195 // a separate event loop and input events are not
3196 // reported to the application.
3197 if (HIWORD(GetQueueStatus(QS_INPUT
)))
3202 GUITHREADINFO guiInfo
;
3203 guiInfo
.cbSize
= sizeof(GUITHREADINFO
);
3204 if (!GetGUIThreadInfo(GetCurrentThreadId(), &guiInfo
))
3206 return GUI_INMOVESIZE
== (guiInfo
.flags
& GUI_INMOVESIZE
);
3210 /**************************************************************
3212 * SECTION: nsIWidget::GetLayerManager
3214 * Get the layer manager associated with this widget.
3216 **************************************************************/
3218 mozilla::layers::LayerManager
*
3219 nsWindow::GetLayerManager()
3221 nsWindow
*topWindow
= GetNSWindowPtr(GetTopLevelHWND(mWnd
, PR_TRUE
));
3224 return nsBaseWidget::GetLayerManager();
3227 if (topWindow
->GetAcceleratedRendering() != mUseAcceleratedRendering
) {
3228 mLayerManager
= NULL
;
3229 mUseAcceleratedRendering
= topWindow
->GetAcceleratedRendering();
3233 if (!mLayerManager
) {
3234 if (mUseAcceleratedRendering
) {
3235 nsCOMPtr
<nsIPrefBranch2
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
3237 PRBool allowAcceleration
= PR_TRUE
;
3238 PRBool preferOpenGL
= PR_FALSE
;
3240 prefs
->GetBoolPref("mozilla.widget.accelerated-layers",
3241 &allowAcceleration
);
3242 prefs
->GetBoolPref("mozilla.layers.prefer-opengl",
3246 if (allowAcceleration
) {
3247 #ifdef MOZ_ENABLE_D3D9_LAYER
3248 if (!preferOpenGL
) {
3249 nsRefPtr
<mozilla::layers::LayerManagerD3D9
> layerManager
=
3250 new mozilla::layers::LayerManagerD3D9(this);
3251 if (layerManager
->Initialize()) {
3252 mLayerManager
= layerManager
;
3256 if (!mLayerManager
) {
3257 nsRefPtr
<mozilla::layers::LayerManagerOGL
> layerManager
=
3258 new mozilla::layers::LayerManagerOGL(this);
3259 if (layerManager
->Initialize()) {
3260 mLayerManager
= layerManager
;
3268 return nsBaseWidget::GetLayerManager();
3271 /**************************************************************
3273 * SECTION: nsIWidget::GetThebesSurface
3275 * Get the Thebes surface associated with this widget.
3277 **************************************************************/
3279 gfxASurface
*nsWindow::GetThebesSurface()
3281 #ifdef CAIRO_HAS_D2D_SURFACE
3282 if (mD2DWindowSurface
) {
3283 return mD2DWindowSurface
;
3287 return (new gfxWindowsSurface(mPaintDC
));
3289 #ifdef CAIRO_HAS_D2D_SURFACE
3290 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
3291 gfxWindowsPlatform::RENDER_DIRECT2D
) {
3292 gfxASurface::gfxContentType content
= gfxASurface::CONTENT_COLOR
;
3293 #if defined(MOZ_XUL)
3294 if (mTransparencyMode
!= eTransparencyOpaque
) {
3295 content
= gfxASurface::CONTENT_COLOR_ALPHA
;
3298 return (new gfxD2DSurface(mWnd
, content
));
3301 PRUint32 flags
= gfxWindowsSurface::FLAG_TAKE_DC
;
3302 if (mTransparencyMode
!= eTransparencyOpaque
) {
3303 flags
|= gfxWindowsSurface::FLAG_IS_TRANSPARENT
;
3305 return (new gfxWindowsSurface(mWnd
, flags
));
3306 #ifdef CAIRO_HAS_D2D_SURFACE
3311 /**************************************************************
3313 * SECTION: nsIWidget::OnDefaultButtonLoaded
3315 * Called after the dialog is loaded and it has a default button.
3317 **************************************************************/
3320 nsWindow::OnDefaultButtonLoaded(const nsIntRect
&aButtonRect
)
3323 return NS_ERROR_NOT_IMPLEMENTED
;
3325 if (aButtonRect
.IsEmpty())
3328 // Don't snap when we are not active.
3329 HWND activeWnd
= ::GetActiveWindow();
3330 if (activeWnd
!= ::GetForegroundWindow() ||
3331 GetTopLevelHWND(mWnd
, PR_TRUE
) != GetTopLevelHWND(activeWnd
, PR_TRUE
)) {
3335 PRBool isAlwaysSnapCursor
= PR_FALSE
;
3336 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
3338 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
3339 prefs
->GetBranch(nsnull
, getter_AddRefs(prefBranch
));
3341 prefBranch
->GetBoolPref("ui.cursor_snapping.always_enabled",
3342 &isAlwaysSnapCursor
);
3346 if (!isAlwaysSnapCursor
) {
3347 BOOL snapDefaultButton
;
3348 if (!::SystemParametersInfo(SPI_GETSNAPTODEFBUTTON
, 0,
3349 &snapDefaultButton
, 0) || !snapDefaultButton
)
3353 nsIntRect widgetRect
;
3354 nsresult rv
= GetScreenBounds(widgetRect
);
3355 NS_ENSURE_SUCCESS(rv
, rv
);
3356 nsIntRect
buttonRect(aButtonRect
+ widgetRect
.TopLeft());
3358 nsIntPoint
centerOfButton(buttonRect
.x
+ buttonRect
.width
/ 2,
3359 buttonRect
.y
+ buttonRect
.height
/ 2);
3360 // The center of the button can be outside of the widget.
3361 // E.g., it could be hidden by scrolling.
3362 if (!widgetRect
.Contains(centerOfButton
)) {
3366 if (!::SetCursorPos(centerOfButton
.x
, centerOfButton
.y
)) {
3367 NS_ERROR("SetCursorPos failed");
3368 return NS_ERROR_FAILURE
;
3375 nsWindow::OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta
,
3376 PRBool aIsHorizontal
,
3377 PRInt32
&aOverriddenDelta
)
3379 // The default vertical and horizontal scrolling speed is 3, this is defined
3380 // on the document of SystemParametersInfo in MSDN.
3381 const PRInt32 kSystemDefaultScrollingSpeed
= 3;
3383 PRInt32 absOriginDelta
= PR_ABS(aOriginalDelta
);
3385 // Compute the simple overridden speed.
3386 PRInt32 absComputedOverriddenDelta
;
3388 nsBaseWidget::OverrideSystemMouseScrollSpeed(absOriginDelta
, aIsHorizontal
,
3389 absComputedOverriddenDelta
);
3390 NS_ENSURE_SUCCESS(rv
, rv
);
3392 aOverriddenDelta
= aOriginalDelta
;
3394 if (absComputedOverriddenDelta
== absOriginDelta
) {
3395 // We don't override now.
3399 // Otherwise, we should check whether the user customized the system settings
3400 // or not. If the user did it, we should respect the will.
3402 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, &systemSpeed
, 0)) {
3403 return NS_ERROR_FAILURE
;
3405 // The default vertical scrolling speed is 3, this is defined on the document
3406 // of SystemParametersInfo in MSDN.
3407 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
3411 // Only Vista and later, Windows has the system setting of horizontal
3412 // scrolling by the mouse wheel.
3413 if (GetWindowsVersion() >= VISTA_VERSION
) {
3414 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0, &systemSpeed
, 0)) {
3415 return NS_ERROR_FAILURE
;
3417 // The default horizontal scrolling speed is 3, this is defined on the
3418 // document of SystemParametersInfo in MSDN.
3419 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
3424 // Limit the overridden delta value from the system settings. The mouse
3425 // driver might accelerate the scrolling speed already. If so, we shouldn't
3426 // override the scrolling speed for preventing the unexpected high speed
3428 PRInt32 absDeltaLimit
;
3430 nsBaseWidget::OverrideSystemMouseScrollSpeed(kSystemDefaultScrollingSpeed
,
3431 aIsHorizontal
, absDeltaLimit
);
3432 NS_ENSURE_SUCCESS(rv
, rv
);
3434 // If the given delta is larger than our computed limitation value, the delta
3435 // was accelerated by the mouse driver. So, we should do nothing here.
3436 if (absDeltaLimit
<= absOriginDelta
) {
3440 absComputedOverriddenDelta
=
3441 PR_MIN(absComputedOverriddenDelta
, absDeltaLimit
);
3443 aOverriddenDelta
= (aOriginalDelta
> 0) ? absComputedOverriddenDelta
:
3444 -absComputedOverriddenDelta
;
3448 /**************************************************************
3449 **************************************************************
3451 ** BLOCK: Moz Events
3453 ** Moz GUI event management.
3455 **************************************************************
3456 **************************************************************/
3458 /**************************************************************
3460 * SECTION: Mozilla event initialization
3462 * Helpers for initializing moz events.
3464 **************************************************************/
3466 // Event intialization
3467 MSG
nsWindow::InitMSG(UINT aMessage
, WPARAM wParam
, LPARAM lParam
)
3470 msg
.message
= aMessage
;
3471 msg
.wParam
= wParam
;
3472 msg
.lParam
= lParam
;
3476 void nsWindow::InitEvent(nsGUIEvent
& event
, nsIntPoint
* aPoint
)
3478 if (nsnull
== aPoint
) { // use the point from the event
3479 // get the message position in client coordinates
3482 DWORD pos
= ::GetMessagePos();
3485 cpos
.x
= GET_X_LPARAM(pos
);
3486 cpos
.y
= GET_Y_LPARAM(pos
);
3488 ::ScreenToClient(mWnd
, &cpos
);
3489 event
.refPoint
.x
= cpos
.x
;
3490 event
.refPoint
.y
= cpos
.y
;
3492 event
.refPoint
.x
= 0;
3493 event
.refPoint
.y
= 0;
3497 // use the point override if provided
3498 event
.refPoint
.x
= aPoint
->x
;
3499 event
.refPoint
.y
= aPoint
->y
;
3503 event
.time
= ::GetMessageTime();
3505 event
.time
= PR_Now() / 1000;
3508 mLastPoint
= event
.refPoint
;
3511 /**************************************************************
3513 * SECTION: Moz event dispatch helpers
3515 * Helpers for dispatching different types of moz events.
3517 **************************************************************/
3519 // Main event dispatch. Invokes callback and ProcessEvent method on
3520 // Event Listener object. Part of nsIWidget.
3521 NS_IMETHODIMP
nsWindow::DispatchEvent(nsGUIEvent
* event
, nsEventStatus
& aStatus
)
3523 #ifdef WIDGET_DEBUG_OUTPUT
3524 debug_DumpEvent(stdout
,
3527 nsCAutoString("something"),
3529 #endif // WIDGET_DEBUG_OUTPUT
3531 aStatus
= nsEventStatus_eIgnore
;
3533 // skip processing of suppressed blur events
3534 if (event
->message
== NS_DEACTIVATE
&& BlurEventsSuppressed())
3537 // Top level windows can have a view attached which requires events be sent
3538 // to the underlying base window and the view. Added when we combined the
3539 // base chrome window with the main content child for nc client area (title
3541 if (mViewCallback
) {
3542 // A subset of events are sent to the base xul window first
3543 switch(event
->message
) {
3544 // send to the base window (view mgr ignores these for the view)
3545 case NS_UISTATECHANGED
:
3550 (*mEventCallback
)(event
); // web shell / xul window
3553 // sent to the base window, then to the view
3558 (*mEventCallback
)(event
); // web shell / xul window
3561 // attached view events
3562 aStatus
= (*mViewCallback
)(event
);
3564 else if (mEventCallback
) {
3565 aStatus
= (*mEventCallback
)(event
);
3568 // the window can be destroyed during processing of seemingly innocuous events like, say,
3569 // mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
3570 // which causes problems with the deleted window. therefore:
3571 if (mOnDestroyCalled
)
3572 aStatus
= nsEventStatus_eConsumeNoDefault
;
3576 PRBool
nsWindow::DispatchStandardEvent(PRUint32 aMsg
)
3578 nsGUIEvent
event(PR_TRUE
, aMsg
, this);
3581 PRBool result
= DispatchWindowEvent(&event
);
3585 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
)
3587 nsEventStatus status
;
3588 DispatchEvent(event
, status
);
3589 return ConvertStatus(status
);
3592 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
, nsEventStatus
&aStatus
) {
3593 DispatchEvent(event
, aStatus
);
3594 return ConvertStatus(aStatus
);
3597 PRBool
nsWindow::DispatchKeyEvent(PRUint32 aEventType
, WORD aCharCode
,
3598 const nsTArray
<nsAlternativeCharCode
>* aAlternativeCharCodes
,
3599 UINT aVirtualCharCode
, const MSG
*aMsg
,
3600 const nsModifierKeyState
&aModKeyState
,
3605 nsKeyEvent
event(PR_TRUE
, aEventType
, this);
3606 nsIntPoint
point(0, 0);
3608 InitEvent(event
, &point
); // this add ref's event.widget
3610 event
.flags
|= aFlags
;
3611 event
.charCode
= aCharCode
;
3612 if (aAlternativeCharCodes
)
3613 event
.alternativeCharCodes
.AppendElements(*aAlternativeCharCodes
);
3614 event
.keyCode
= aVirtualCharCode
;
3618 printf("%d DispatchKE Type: %s charCode %d keyCode %d ", cnt
++,
3619 (NS_KEY_PRESS
== aEventType
) ? "PRESS" : (aEventType
== NS_KEY_UP
? "Up" : "Down"),
3620 event
.charCode
, event
.keyCode
);
3621 printf("Shift: %s Control %s Alt: %s \n",
3622 (mIsShiftDown
? "D" : "U"), (mIsControlDown
? "D" : "U"), (mIsAltDown
? "D" : "U"));
3623 printf("[%c][%c][%c] <== [%c][%c][%c][ space bar ][%c][%c][%c]\n",
3624 IS_VK_DOWN(NS_VK_SHIFT
) ? 'S' : ' ',
3625 IS_VK_DOWN(NS_VK_CONTROL
) ? 'C' : ' ',
3626 IS_VK_DOWN(NS_VK_ALT
) ? 'A' : ' ',
3627 IS_VK_DOWN(VK_LSHIFT
) ? 'S' : ' ',
3628 IS_VK_DOWN(VK_LCONTROL
) ? 'C' : ' ',
3629 IS_VK_DOWN(VK_LMENU
) ? 'A' : ' ',
3630 IS_VK_DOWN(VK_RMENU
) ? 'A' : ' ',
3631 IS_VK_DOWN(VK_RCONTROL
) ? 'C' : ' ',
3632 IS_VK_DOWN(VK_RSHIFT
) ? 'S' : ' ');
3635 event
.isShift
= aModKeyState
.mIsShiftDown
;
3636 event
.isControl
= aModKeyState
.mIsControlDown
;
3637 event
.isMeta
= PR_FALSE
;
3638 event
.isAlt
= aModKeyState
.mIsAltDown
;
3640 NPEvent pluginEvent
;
3641 if (aMsg
&& PluginHasFocus()) {
3642 pluginEvent
.event
= aMsg
->message
;
3643 pluginEvent
.wParam
= aMsg
->wParam
;
3644 pluginEvent
.lParam
= aMsg
->lParam
;
3645 event
.pluginEvent
= (void *)&pluginEvent
;
3648 PRBool result
= DispatchWindowEvent(&event
);
3653 PRBool
nsWindow::DispatchCommandEvent(PRUint32 aEventCommand
)
3655 nsCOMPtr
<nsIAtom
> command
;
3656 switch (aEventCommand
) {
3657 case APPCOMMAND_BROWSER_BACKWARD
:
3658 command
= nsWidgetAtoms::Back
;
3660 case APPCOMMAND_BROWSER_FORWARD
:
3661 command
= nsWidgetAtoms::Forward
;
3663 case APPCOMMAND_BROWSER_REFRESH
:
3664 command
= nsWidgetAtoms::Reload
;
3666 case APPCOMMAND_BROWSER_STOP
:
3667 command
= nsWidgetAtoms::Stop
;
3669 case APPCOMMAND_BROWSER_SEARCH
:
3670 command
= nsWidgetAtoms::Search
;
3672 case APPCOMMAND_BROWSER_FAVORITES
:
3673 command
= nsWidgetAtoms::Bookmarks
;
3675 case APPCOMMAND_BROWSER_HOME
:
3676 command
= nsWidgetAtoms::Home
;
3681 nsCommandEvent
event(PR_TRUE
, nsWidgetAtoms::onAppCommand
, command
, this);
3684 DispatchWindowEvent(&event
);
3689 // Recursively dispatch synchronous paints for nsIWidget
3690 // descendants with invalidated rectangles.
3691 BOOL CALLBACK
nsWindow::DispatchStarvedPaints(HWND aWnd
, LPARAM aMsg
)
3693 LONG_PTR proc
= ::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
3694 if (proc
== (LONG_PTR
)&nsWindow::WindowProc
) {
3695 // its one of our windows so check to see if it has a
3696 // invalidated rect. If it does. Dispatch a synchronous
3698 if (GetUpdateRect(aWnd
, NULL
, FALSE
))
3699 VERIFY(::UpdateWindow(aWnd
));
3704 // Check for pending paints and dispatch any pending paint
3705 // messages for any nsIWidget which is a descendant of the
3706 // top-level window that *this* window is embedded within.
3708 // Note: We do not dispatch pending paint messages for non
3709 // nsIWidget managed windows.
3710 void nsWindow::DispatchPendingEvents()
3713 NS_WARNING("We were asked to dispatch pending events during painting, "
3714 "denying since that's unsafe.");
3718 // We need to ensure that reflow events do not get starved.
3719 // At the same time, we don't want to recurse through here
3720 // as that would prevent us from dispatching starved paints.
3721 static int recursionBlocker
= 0;
3722 if (recursionBlocker
++ == 0) {
3723 NS_ProcessPendingEvents(nsnull
, PR_MillisecondsToInterval(100));
3727 // Quickly check to see if there are any
3728 // paint events pending.
3729 if (::GetQueueStatus(QS_PAINT
)) {
3730 // Find the top level window.
3731 HWND topWnd
= GetTopLevelHWND(mWnd
);
3733 // Dispatch pending paints for all topWnd's descendant windows.
3734 // Note: EnumChildWindows enumerates all descendant windows not just
3737 ::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, NULL
);
3739 nsWindowCE::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, NULL
);
3744 // Deal with plugin events
3745 PRBool
nsWindow::DispatchPluginEvent(const MSG
&aMsg
)
3747 if (!PluginHasFocus())
3750 nsGUIEvent
event(PR_TRUE
, NS_PLUGIN_EVENT
, this);
3751 nsIntPoint
point(0, 0);
3752 InitEvent(event
, &point
);
3753 NPEvent pluginEvent
;
3754 pluginEvent
.event
= aMsg
.message
;
3755 pluginEvent
.wParam
= aMsg
.wParam
;
3756 pluginEvent
.lParam
= aMsg
.lParam
;
3757 event
.pluginEvent
= (void *)&pluginEvent
;
3758 return DispatchWindowEvent(&event
);
3761 void nsWindow::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg
,
3765 ::GetMessageW(&msg
, mWnd
, aFirstMsg
, aLastMsg
);
3766 DispatchPluginEvent(msg
);
3769 // Deal with all sort of mouse event
3770 PRBool
nsWindow::DispatchMouseEvent(PRUint32 aEventType
, WPARAM wParam
,
3771 LPARAM lParam
, PRBool aIsContextMenuKey
,
3772 PRInt16 aButton
, PRUint16 aInputSource
)
3774 PRBool result
= PR_FALSE
;
3778 if (!mEventCallback
) {
3782 switch (aEventType
) {
3783 case NS_MOUSE_BUTTON_DOWN
:
3784 CaptureMouse(PR_TRUE
);
3787 // NS_MOUSE_MOVE and NS_MOUSE_EXIT are here because we need to make sure capture flag
3788 // isn't left on after a drag where we wouldn't see a button up message (see bug 324131).
3789 case NS_MOUSE_BUTTON_UP
:
3792 if (!(wParam
& (MK_LBUTTON
| MK_MBUTTON
| MK_RBUTTON
)) && mIsInMouseCapture
)
3793 CaptureMouse(PR_FALSE
);
3801 nsIntPoint eventPoint
;
3802 eventPoint
.x
= GET_X_LPARAM(lParam
);
3803 eventPoint
.y
= GET_Y_LPARAM(lParam
);
3805 nsMouseEvent
event(PR_TRUE
, aEventType
, this, nsMouseEvent::eReal
,
3807 ? nsMouseEvent::eContextMenuKey
3808 : nsMouseEvent::eNormal
);
3809 if (aEventType
== NS_CONTEXTMENU
&& aIsContextMenuKey
) {
3810 nsIntPoint
zero(0, 0);
3811 InitEvent(event
, &zero
);
3813 InitEvent(event
, &eventPoint
);
3816 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
3817 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
3818 event
.isMeta
= PR_FALSE
;
3819 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
3820 event
.button
= aButton
;
3821 event
.inputSource
= aInputSource
;
3823 nsIntPoint mpScreen
= eventPoint
+ WidgetToScreenOffset();
3825 // Suppress mouse moves caused by widget creation
3826 if (aEventType
== NS_MOUSE_MOVE
)
3828 if ((sLastMouseMovePoint
.x
== mpScreen
.x
) && (sLastMouseMovePoint
.y
== mpScreen
.y
))
3830 sLastMouseMovePoint
.x
= mpScreen
.x
;
3831 sLastMouseMovePoint
.y
= mpScreen
.y
;
3834 PRBool insideMovementThreshold
= (abs(sLastMousePoint
.x
- eventPoint
.x
) < (short)::GetSystemMetrics(SM_CXDOUBLECLK
)) &&
3835 (abs(sLastMousePoint
.y
- eventPoint
.y
) < (short)::GetSystemMetrics(SM_CYDOUBLECLK
));
3839 case nsMouseEvent::eLeftButton
:
3840 eventButton
= VK_LBUTTON
;
3842 case nsMouseEvent::eMiddleButton
:
3843 eventButton
= VK_MBUTTON
;
3845 case nsMouseEvent::eRightButton
:
3846 eventButton
= VK_RBUTTON
;
3853 // Doubleclicks are used to set the click count, then changed to mousedowns
3854 // We're going to time double-clicks from mouse *up* to next mouse *down*
3856 LONG curMsgTime
= ::GetMessageTime();
3858 LONG curMsgTime
= PR_Now() / 1000;
3861 if (aEventType
== NS_MOUSE_DOUBLECLICK
) {
3862 event
.message
= NS_MOUSE_BUTTON_DOWN
;
3863 event
.button
= aButton
;
3864 sLastClickCount
= 2;
3866 else if (aEventType
== NS_MOUSE_BUTTON_UP
) {
3867 // remember when this happened for the next mouse down
3868 sLastMousePoint
.x
= eventPoint
.x
;
3869 sLastMousePoint
.y
= eventPoint
.y
;
3870 sLastMouseButton
= eventButton
;
3872 else if (aEventType
== NS_MOUSE_BUTTON_DOWN
) {
3873 // now look to see if we want to convert this to a double- or triple-click
3874 if (((curMsgTime
- sLastMouseDownTime
) < (LONG
)::GetDoubleClickTime()) && insideMovementThreshold
&&
3875 eventButton
== sLastMouseButton
) {
3878 // reset the click count, to count *this* click
3879 sLastClickCount
= 1;
3881 // Set last Click time on MouseDown only
3882 sLastMouseDownTime
= curMsgTime
;
3884 else if (aEventType
== NS_MOUSE_MOVE
&& !insideMovementThreshold
) {
3885 sLastClickCount
= 0;
3887 else if (aEventType
== NS_MOUSE_EXIT
) {
3888 event
.exit
= IsTopLevelMouseExit(mWnd
) ? nsMouseEvent::eTopLevel
: nsMouseEvent::eChild
;
3890 else if (aEventType
== NS_MOUSE_MOZHITTEST
)
3892 event
.flags
|= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH
;
3894 event
.clickCount
= sLastClickCount
;
3897 printf("Msg Time: %d Click Count: %d\n", curMsgTime
, event
.clickCount
);
3900 NPEvent pluginEvent
;
3904 case NS_MOUSE_BUTTON_DOWN
:
3906 case nsMouseEvent::eLeftButton
:
3907 pluginEvent
.event
= WM_LBUTTONDOWN
;
3909 case nsMouseEvent::eMiddleButton
:
3910 pluginEvent
.event
= WM_MBUTTONDOWN
;
3912 case nsMouseEvent::eRightButton
:
3913 pluginEvent
.event
= WM_RBUTTONDOWN
;
3919 case NS_MOUSE_BUTTON_UP
:
3921 case nsMouseEvent::eLeftButton
:
3922 pluginEvent
.event
= WM_LBUTTONUP
;
3924 case nsMouseEvent::eMiddleButton
:
3925 pluginEvent
.event
= WM_MBUTTONUP
;
3927 case nsMouseEvent::eRightButton
:
3928 pluginEvent
.event
= WM_RBUTTONUP
;
3934 case NS_MOUSE_DOUBLECLICK
:
3936 case nsMouseEvent::eLeftButton
:
3937 pluginEvent
.event
= WM_LBUTTONDBLCLK
;
3939 case nsMouseEvent::eMiddleButton
:
3940 pluginEvent
.event
= WM_MBUTTONDBLCLK
;
3942 case nsMouseEvent::eRightButton
:
3943 pluginEvent
.event
= WM_RBUTTONDBLCLK
;
3950 pluginEvent
.event
= WM_MOUSEMOVE
;
3953 pluginEvent
.event
= WM_MOUSELEAVE
;
3956 pluginEvent
.event
= WM_NULL
;
3960 pluginEvent
.wParam
= wParam
; // plugins NEED raw OS event flags!
3961 pluginEvent
.lParam
= lParam
;
3963 event
.pluginEvent
= (void *)&pluginEvent
;
3965 // call the event callback
3966 if (nsnull
!= mEventCallback
) {
3967 if (nsToolkit::gMouseTrailer
)
3968 nsToolkit::gMouseTrailer
->Disable();
3969 if (aEventType
== NS_MOUSE_MOVE
) {
3970 if (nsToolkit::gMouseTrailer
&& !mIsInMouseCapture
) {
3971 nsToolkit::gMouseTrailer
->SetMouseTrailerWindow(mWnd
);
3978 if (rect
.Contains(event
.refPoint
)) {
3979 if (sCurrentWindow
== NULL
|| sCurrentWindow
!= this) {
3980 if ((nsnull
!= sCurrentWindow
) && (!sCurrentWindow
->mInDtor
)) {
3981 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
3982 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_EXIT
, wParam
, pos
, PR_FALSE
,
3983 nsMouseEvent::eLeftButton
, aInputSource
);
3985 sCurrentWindow
= this;
3987 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
3988 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_ENTER
, wParam
, pos
, PR_FALSE
,
3989 nsMouseEvent::eLeftButton
, aInputSource
);
3993 } else if (aEventType
== NS_MOUSE_EXIT
) {
3994 if (sCurrentWindow
== this) {
3995 sCurrentWindow
= nsnull
;
3999 result
= DispatchWindowEvent(&event
);
4001 if (nsToolkit::gMouseTrailer
)
4002 nsToolkit::gMouseTrailer
->Enable();
4004 // Release the widget with NS_IF_RELEASE() just in case
4005 // the context menu key code in nsEventListenerManager::HandleEvent()
4006 // released it already.
4013 // Deal with accessibile event
4014 #ifdef ACCESSIBILITY
4016 nsWindow::DispatchAccessibleEvent(PRUint32 aEventType
)
4018 if (nsnull
== mEventCallback
) {
4022 nsAccessibleEvent
event(PR_TRUE
, aEventType
, this);
4023 InitEvent(event
, nsnull
);
4025 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
4026 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
4027 event
.isMeta
= PR_FALSE
;
4028 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
4030 DispatchWindowEvent(&event
);
4032 return event
.mAccessible
;
4036 PRBool
nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType
)
4038 if (aEventType
== NS_ACTIVATE
)
4039 sJustGotActivate
= PR_FALSE
;
4040 sJustGotDeactivate
= PR_FALSE
;
4042 // retrive the toplevel window or dialog
4044 HWND toplevelWnd
= NULL
;
4046 toplevelWnd
= curWnd
;
4048 nsWindow
*win
= GetNSWindowPtr(curWnd
);
4050 nsWindowType wintype
;
4051 win
->GetWindowType(wintype
);
4052 if (wintype
== eWindowType_toplevel
|| wintype
== eWindowType_dialog
)
4056 curWnd
= ::GetParent(curWnd
); // Parent or owner (if has no parent)
4060 nsWindow
*win
= GetNSWindowPtr(toplevelWnd
);
4062 return win
->DispatchFocus(aEventType
);
4068 // Deal with focus messages
4069 PRBool
nsWindow::DispatchFocus(PRUint32 aEventType
)
4071 // call the event callback
4072 if (mEventCallback
) {
4073 nsGUIEvent
event(PR_TRUE
, aEventType
, this);
4076 //focus and blur event should go to their base widget loc, not current mouse pos
4077 event
.refPoint
.x
= 0;
4078 event
.refPoint
.y
= 0;
4080 NPEvent pluginEvent
;
4085 pluginEvent
.event
= WM_SETFOCUS
;
4088 pluginEvent
.event
= WM_KILLFOCUS
;
4090 case NS_PLUGIN_ACTIVATE
:
4091 pluginEvent
.event
= WM_KILLFOCUS
;
4097 event
.pluginEvent
= (void *)&pluginEvent
;
4099 return DispatchWindowEvent(&event
);
4104 PRBool
nsWindow::IsTopLevelMouseExit(HWND aWnd
)
4106 DWORD pos
= ::GetMessagePos();
4108 mp
.x
= GET_X_LPARAM(pos
);
4109 mp
.y
= GET_Y_LPARAM(pos
);
4110 HWND mouseWnd
= ::WindowFromPoint(mp
);
4112 // GetTopLevelHWND will return a HWND for the window frame (which includes
4113 // the non-client area). If the mouse has moved into the non-client area,
4114 // we should treat it as a top-level exit.
4115 HWND mouseTopLevel
= nsWindow::GetTopLevelHWND(mouseWnd
);
4116 if (mouseWnd
== mouseTopLevel
)
4119 return nsWindow::GetTopLevelHWND(aWnd
) != mouseTopLevel
;
4122 PRBool
nsWindow::BlurEventsSuppressed()
4124 // are they suppressed in this window?
4125 if (mBlurSuppressLevel
> 0)
4128 // are they suppressed by any container widget?
4129 HWND parentWnd
= ::GetParent(mWnd
);
4131 nsWindow
*parent
= GetNSWindowPtr(parentWnd
);
4133 return parent
->BlurEventsSuppressed();
4138 // In some circumstances (opening dependent windows) it makes more sense
4139 // (and fixes a crash bug) to not blur the parent window. Called from
4141 void nsWindow::SuppressBlurEvents(PRBool aSuppress
)
4144 ++mBlurSuppressLevel
; // for this widget
4146 NS_ASSERTION(mBlurSuppressLevel
> 0, "unbalanced blur event suppression");
4147 if (mBlurSuppressLevel
> 0)
4148 --mBlurSuppressLevel
;
4152 PRBool
nsWindow::ConvertStatus(nsEventStatus aStatus
)
4154 return aStatus
== nsEventStatus_eConsumeNoDefault
;
4157 /**************************************************************
4161 * IPC related helpers.
4163 **************************************************************/
4169 nsWindow::IsAsyncResponseEvent(UINT aMsg
, LRESULT
& aResult
)
4175 case WM_WINDOWPOSCHANGING
:
4176 case WM_WINDOWPOSCHANGED
:
4177 case WM_PARENTNOTIFY
:
4178 case WM_ACTIVATEAPP
:
4181 case WM_CHILDACTIVATE
:
4182 case WM_IME_SETCONTEXT
:
4186 case WM_MOUSEACTIVATE
:
4187 case WM_CONTEXTMENU
:
4191 case WM_SETTINGCHANGE
:
4199 "An unhandled ISMEX_SEND message was received during spin loop! (%X)", aMsg
);
4207 nsWindow::IPCWindowProcHandler(UINT
& msg
, WPARAM
& wParam
, LPARAM
& lParam
)
4209 NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
4210 "Failed to prevent a nonqueued message from running!");
4212 // Modal UI being displayed in windowless plugins.
4213 if (mozilla::ipc::RPCChannel::IsSpinLoopActive() &&
4214 (InSendMessageEx(NULL
)&(ISMEX_REPLIED
|ISMEX_SEND
)) == ISMEX_SEND
) {
4216 if (IsAsyncResponseEvent(msg
, res
)) {
4222 // Handle certain sync plugin events sent to the parent which
4223 // trigger ipc calls that result in deadlocks.
4226 PRBool handled
= PR_FALSE
;
4229 // Windowless flash sending WM_ACTIVATE events to the main window
4230 // via calls to ShowWindow.
4232 if (lParam
!= 0 && LOWORD(wParam
) == WA_ACTIVE
&&
4233 IsWindow((HWND
)lParam
))
4236 // Wheel events forwarded from the child.
4238 case WM_MOUSEHWHEEL
:
4241 // Plugins taking or losing focus triggering focus app messages.
4244 // Windowed plugins that pass sys key events to defwndproc generate
4245 // WM_SYSCOMMAND events to the main window.
4247 // Windowed plugins that fire context menu selection events to parent
4249 case WM_CONTEXTMENU
:
4250 // IME events fired as a result of synchronous focus changes
4251 case WM_IME_SETCONTEXT
:
4257 (InSendMessageEx(NULL
)&(ISMEX_REPLIED
|ISMEX_SEND
)) == ISMEX_SEND
) {
4258 ReplyMessage(dwResult
);
4264 /**************************************************************
4265 **************************************************************
4267 ** BLOCK: Native events
4269 ** Main Windows message handlers and OnXXX handlers for
4270 ** Windows event handling.
4272 **************************************************************
4273 **************************************************************/
4275 /**************************************************************
4277 * SECTION: Wind proc.
4279 * The main Windows event procedures and associated
4280 * message processing methods.
4282 **************************************************************/
4284 // The WndProc procedure for all nsWindows in this toolkit
4285 LRESULT CALLBACK
nsWindow::WindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
4287 NS_TIME_FUNCTION_MIN_FMT(5.0, "%s (line %d) (hWnd: %p, msg: %p, wParam: %p, lParam: %p",
4288 MOZ_FUNCTION_NAME
, __LINE__
, hWnd
, msg
,
4291 // Get the window which caused the event and ask it to process the message
4292 nsWindow
*someWindow
= GetNSWindowPtr(hWnd
);
4296 someWindow
->IPCWindowProcHandler(msg
, wParam
, lParam
);
4299 // create this here so that we store the last rolled up popup until after
4300 // the event has been processed.
4301 nsAutoRollup autoRollup
;
4303 LRESULT popupHandlingResult
;
4304 if (DealWithPopups(hWnd
, msg
, wParam
, lParam
, &popupHandlingResult
))
4305 return popupHandlingResult
;
4307 // XXX This fixes 50208 and we are leaving 51174 open to further investigate
4308 // why we are hitting this assert
4309 if (nsnull
== someWindow
) {
4310 NS_ASSERTION(someWindow
, "someWindow is null, cannot call any CallWindowProc");
4311 return ::DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
4314 // hold on to the window for the life of this method, in case it gets
4315 // deleted during processing. yes, it's a double hack, since someWindow
4316 // is not really an interface.
4317 nsCOMPtr
<nsISupports
> kungFuDeathGrip
;
4318 if (!someWindow
->mInDtor
) // not if we're in the destructor!
4319 kungFuDeathGrip
= do_QueryInterface((nsBaseWidget
*)someWindow
);
4321 // Call ProcessMessage
4323 if (PR_TRUE
== someWindow
->ProcessMessage(msg
, wParam
, lParam
, &retValue
)) {
4327 LRESULT res
= ::CallWindowProcW(someWindow
->GetPrevWindowProc(),
4328 hWnd
, msg
, wParam
, lParam
);
4333 // The main windows message processing method for plugins.
4334 // The result means whether this method processed the native
4335 // event for plugin. If false, the native event should be
4336 // processed by the caller self.
4338 nsWindow::ProcessMessageForPlugin(const MSG
&aMsg
,
4340 PRBool
&aCallDefWndProc
)
4342 NS_PRECONDITION(aResult
, "aResult must be non-null.");
4345 aCallDefWndProc
= PR_FALSE
;
4346 PRBool fallBackToNonPluginProcess
= PR_FALSE
;
4347 PRBool eventDispatched
= PR_FALSE
;
4348 PRBool dispatchPendingEvents
= PR_TRUE
;
4349 switch (aMsg
.message
) {
4350 case WM_INPUTLANGCHANGEREQUEST
:
4351 case WM_INPUTLANGCHANGE
:
4352 DispatchPluginEvent(aMsg
);
4353 return PR_FALSE
; // go to non-plug-ins processing
4357 *aResult
= ProcessCharMessage(aMsg
, &eventDispatched
);
4362 *aResult
= ProcessKeyUpMessage(aMsg
, &eventDispatched
);
4367 *aResult
= ProcessKeyDownMessage(aMsg
, &eventDispatched
);
4371 case WM_SYSDEADCHAR
:
4372 case WM_CONTEXTMENU
:
4380 case WM_IME_STARTCOMPOSITION
:
4381 case WM_IME_COMPOSITION
:
4382 case WM_IME_ENDCOMPOSITION
:
4384 case WM_IME_COMPOSITIONFULL
:
4385 case WM_IME_CONTROL
:
4386 case WM_IME_KEYDOWN
:
4389 case WM_IME_REQUEST
:
4393 case WM_IME_SETCONTEXT
:
4394 // Don't synchronously dispatch when we receive WM_IME_SETCONTEXT
4395 // because we get it during plugin destruction. (bug 491848)
4396 dispatchPendingEvents
= PR_FALSE
;
4403 if (!eventDispatched
)
4404 aCallDefWndProc
= !DispatchPluginEvent(aMsg
);
4405 if (dispatchPendingEvents
)
4406 DispatchPendingEvents();
4410 // The main windows message processing method.
4411 PRBool
nsWindow::ProcessMessage(UINT msg
, WPARAM
&wParam
, LPARAM
&lParam
,
4414 // (Large blocks of code should be broken out into OnEvent handlers.)
4415 if (mWindowHook
.Notify(mWnd
, msg
, wParam
, lParam
, aRetValue
))
4418 #if defined(EVENT_DEBUG_OUTPUT)
4419 // First param shows all events, second param indicates whether
4420 // to show mouse move events. See nsWindowDbg for details.
4421 PrintEvent(msg
, SHOW_REPEAT_EVENTS
, SHOW_MOUSEMOVE_EVENTS
);
4425 if (nsIMM32Handler::ProcessMessage(this, msg
, wParam
, lParam
, aRetValue
,
4427 return mWnd
? eatMessage
: PR_TRUE
;
4430 if (PluginHasFocus()) {
4431 PRBool callDefaultWndProc
;
4432 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4433 if (ProcessMessageForPlugin(nativeMsg
, aRetValue
, callDefaultWndProc
)) {
4434 return mWnd
? !callDefaultWndProc
: PR_TRUE
;
4438 static UINT vkKeyCached
= 0; // caches VK code fon WM_KEYDOWN
4439 PRBool result
= PR_FALSE
; // call the default nsWindow proc
4442 static PRBool getWheelInfo
= PR_TRUE
;
4444 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4445 // Glass hit testing w/custom transparent margins
4446 LRESULT dwmHitResult
;
4447 if (mCustomNonClient
&&
4449 nsUXThemeData::CheckForCompositor() &&
4450 nsUXThemeData::dwmDwmDefWindowProcPtr(mWnd
, msg
, wParam
, lParam
, &dwmHitResult
)) {
4451 *aRetValue
= dwmHitResult
;
4454 #endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4458 // WM_QUERYENDSESSION must be handled by all windows.
4459 // Otherwise Windows thinks the window can just be killed at will.
4460 case WM_QUERYENDSESSION
:
4461 if (sCanQuit
== TRI_UNKNOWN
)
4463 // Ask if it's ok to quit, and store the answer until we
4464 // get WM_ENDSESSION signaling the round is complete.
4465 nsCOMPtr
<nsIObserverService
> obsServ
=
4466 mozilla::services::GetObserverService();
4467 nsCOMPtr
<nsISupportsPRBool
> cancelQuit
=
4468 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID
);
4469 cancelQuit
->SetData(PR_FALSE
);
4470 obsServ
->NotifyObservers(cancelQuit
, "quit-application-requested", nsnull
);
4473 cancelQuit
->GetData(&abortQuit
);
4474 sCanQuit
= abortQuit
? TRI_FALSE
: TRI_TRUE
;
4476 *aRetValue
= sCanQuit
? TRUE
: FALSE
;
4484 case MOZ_WM_APP_QUIT
:
4485 if (msg
== MOZ_WM_APP_QUIT
|| (wParam
== TRUE
&& sCanQuit
== TRI_TRUE
))
4487 // Let's fake a shutdown sequence without actually closing windows etc.
4488 // to avoid Windows killing us in the middle. A proper shutdown would
4489 // require having a chance to pump some messages. Unfortunately
4490 // Windows won't let us do that. Bug 212316.
4491 nsCOMPtr
<nsIObserverService
> obsServ
=
4492 mozilla::services::GetObserverService();
4493 NS_NAMED_LITERAL_STRING(context
, "shutdown-persist");
4494 obsServ
->NotifyObservers(nsnull
, "quit-application-granted", nsnull
);
4495 obsServ
->NotifyObservers(nsnull
, "quit-application-forced", nsnull
);
4496 obsServ
->NotifyObservers(nsnull
, "quit-application", nsnull
);
4497 obsServ
->NotifyObservers(nsnull
, "profile-change-net-teardown", context
.get());
4498 obsServ
->NotifyObservers(nsnull
, "profile-change-teardown", context
.get());
4499 obsServ
->NotifyObservers(nsnull
, "profile-before-change", context
.get());
4500 // Then a controlled but very quick exit.
4503 sCanQuit
= TRI_UNKNOWN
;
4508 case WM_DISPLAYCHANGE
:
4509 DispatchStandardEvent(NS_DISPLAYCHANGED
);
4513 case WM_SYSCOLORCHANGE
:
4514 // Note: This is sent for child windows as well as top-level windows.
4515 // The Win32 toolkit normally only sends these events to top-level windows.
4516 // But we cycle through all of the childwindows and send it to them as well
4517 // so all presentations get notified properly.
4518 // See nsWindow::GlobalMsgWindowProc.
4519 DispatchStandardEvent(NS_SYSCOLORCHANGED
);
4525 LPNMHDR pnmh
= (LPNMHDR
) lParam
;
4527 switch (pnmh
->code
) {
4530 DispatchStandardEvent(NS_TABCHANGE
);
4538 case WM_XP_THEMECHANGED
:
4540 // Update non-client margin offsets
4541 UpdateNonClientMargins();
4543 DispatchStandardEvent(NS_THEMECHANGED
);
4545 // Invalidate the window so that the repaint will
4546 // pick up the new theme.
4547 Invalidate(PR_FALSE
);
4554 PRBool didChange
= PR_FALSE
;
4556 // update the global font list
4557 nsCOMPtr
<nsIFontEnumerator
> fontEnum
= do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv
);
4558 if (NS_SUCCEEDED(rv
)) {
4559 fontEnum
->UpdateFontList(&didChange
);
4560 //didChange is TRUE only if new font langGroup is added to the list.
4562 // update device context font cache
4563 // Dirty but easiest way:
4564 // Changing nsIPrefBranch entry which triggers callbacks
4565 // and flows into calling mDeviceContext->FlushFontCache()
4566 // to update the font cache in all the instance of Browsers
4567 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
4569 nsCOMPtr
<nsIPrefBranch
> fiPrefs
;
4570 prefs
->GetBranch("font.internaluseonly.", getter_AddRefs(fiPrefs
));
4572 PRBool fontInternalChange
= PR_FALSE
;
4573 fiPrefs
->GetBoolPref("changed", &fontInternalChange
);
4574 fiPrefs
->SetBoolPref("changed", !fontInternalChange
);
4578 } //if (NS_SUCCEEDED(rv))
4584 // If wParam is TRUE, it specifies that the application should indicate
4585 // which part of the client area contains valid information. The system
4586 // copies the valid information to the specified area within the new
4587 // client area. If the wParam parameter is FALSE, the application should
4589 if (mCustomNonClient
&& mCompositorFlag
) {
4597 // rgrc[0]: the proposed window
4598 // rgrc[1]: the current window
4599 // rgrc[2]: the source client area
4600 // pncsp->lppos: move/size data
4602 // rgrc[0]: the new client area
4603 // rgrc[1]: the destination window
4604 // rgrc[2]: the source client area
4605 // (all values in screen coordiantes)
4606 NCCALCSIZE_PARAMS
*pncsp
= reinterpret_cast<NCCALCSIZE_PARAMS
*>(lParam
);
4607 LRESULT res
= CallWindowProcW(GetPrevWindowProc(), mWnd
, msg
, wParam
, lParam
);
4608 pncsp
->rgrc
[0].top
-= mNonClientOffset
.top
;
4609 pncsp
->rgrc
[0].left
-= mNonClientOffset
.left
;
4610 pncsp
->rgrc
[0].right
+= mNonClientOffset
.right
;
4611 pncsp
->rgrc
[0].bottom
+= mNonClientOffset
.bottom
;
4622 * If an nc client area margin has been moved, we are responsible
4623 * for calculating where the resize margins are and returning the
4624 * appropriate set of hit test constants. DwmDefWindowProc (above)
4625 * will handle hit testing on it's command buttons if we are on a
4626 * composited desktop.
4629 if (!mCustomNonClient
|| !mCompositorFlag
)
4633 ClientMarginHitTestPoint(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
4639 case WM_POWERBROADCAST
:
4640 // only hidden window handle this
4641 // to prevent duplicate notification
4642 if (mWindowType
== eWindowType_invisible
) {
4645 case PBT_APMSUSPEND
:
4646 PostSleepWakeNotification("sleep_notification");
4648 case PBT_APMRESUMEAUTOMATIC
:
4649 case PBT_APMRESUMECRITICAL
:
4650 case PBT_APMRESUMESUSPEND
:
4651 PostSleepWakeNotification("wake_notification");
4658 case WM_MOVE
: // Window moved
4660 PRInt32 x
= GET_X_LPARAM(lParam
); // horizontal position in screen coordinates
4661 PRInt32 y
= GET_Y_LPARAM(lParam
); // vertical position in screen coordinates
4662 result
= OnMove(x
, y
);
4666 case WM_CLOSE
: // close request
4667 DispatchStandardEvent(NS_XUL_CLOSE
);
4668 result
= PR_TRUE
; // abort window closure
4678 *aRetValue
= (int) OnPaint(NULL
, 0);
4683 case WM_PRINTCLIENT
:
4684 result
= OnPaint((HDC
) wParam
, 0);
4689 result
= OnHotKey(wParam
, lParam
);
4695 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4696 result
= ProcessCharMessage(nativeMsg
, nsnull
);
4697 DispatchPendingEvents();
4704 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4705 result
= ProcessKeyUpMessage(nativeMsg
, nsnull
);
4706 DispatchPendingEvents();
4713 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4714 result
= ProcessKeyDownMessage(nativeMsg
, nsnull
);
4715 DispatchPendingEvents();
4719 // say we've dealt with erase background if widget does
4720 // not need auto-erasing
4722 if (!AutoErase((HDC
)wParam
)) {
4730 #ifdef WINCE_WINDOWS_MOBILE
4731 // Reset the kill timer so that we can continue at this
4733 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2seconds */, NULL
);
4735 // Suppress dispatch of pending events
4736 // when mouse moves are generated by widget
4737 // creation instead of user input.
4738 LPARAM lParamScreen
= lParamToScreen(lParam
);
4740 mp
.x
= GET_X_LPARAM(lParamScreen
);
4741 mp
.y
= GET_Y_LPARAM(lParamScreen
);
4742 PRBool userMovedMouse
= PR_FALSE
;
4743 if ((sLastMouseMovePoint
.x
!= mp
.x
) || (sLastMouseMovePoint
.y
!= mp
.y
)) {
4744 userMovedMouse
= PR_TRUE
;
4746 mExitToNonClientArea
= PR_FALSE
;
4748 result
= DispatchMouseEvent(NS_MOUSE_MOVE
, wParam
, lParam
,
4749 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4750 if (userMovedMouse
) {
4751 DispatchPendingEvents();
4756 #ifdef WINCE_WINDOWS_MOBILE
4758 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
4759 KillTimer(mWnd
, KILL_PRIORITY_ID
);
4763 case WM_LBUTTONDOWN
:
4765 #ifdef WINCE_WINDOWS_MOBILE
4766 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
4767 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2 seconds */, NULL
);
4769 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
,
4770 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4771 DispatchPendingEvents();
4777 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
,
4778 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4779 DispatchPendingEvents();
4781 #ifdef WINCE_WINDOWS_MOBILE
4782 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
4783 KillTimer(mWnd
, KILL_PRIORITY_ID
);
4791 // We need to check mouse button states and put them in for
4793 WPARAM mouseState
= (GetKeyState(VK_LBUTTON
) ? MK_LBUTTON
: 0)
4794 | (GetKeyState(VK_MBUTTON
) ? MK_MBUTTON
: 0)
4795 | (GetKeyState(VK_RBUTTON
) ? MK_RBUTTON
: 0);
4796 // Synthesize an event position because we don't get one from
4798 LPARAM pos
= lParamToClient(::GetMessagePos());
4799 DispatchMouseEvent(NS_MOUSE_EXIT
, mouseState
, pos
, PR_FALSE
,
4800 nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4805 case WM_CONTEXTMENU
:
4807 // if the context menu is brought up from the keyboard, |lParam|
4810 PRBool contextMenukey
= PR_FALSE
;
4811 if (lParam
== 0xFFFFFFFF)
4813 contextMenukey
= PR_TRUE
;
4814 pos
= lParamToClient(GetMessagePos());
4818 pos
= lParamToClient(lParam
);
4821 result
= DispatchMouseEvent(NS_CONTEXTMENU
, wParam
, pos
, contextMenukey
,
4823 nsMouseEvent::eLeftButton
:
4824 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4828 case WM_LBUTTONDBLCLK
:
4829 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
4830 nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
4833 case WM_MBUTTONDOWN
:
4835 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4836 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
4837 DispatchPendingEvents();
4842 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
4843 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
4844 DispatchPendingEvents();
4847 case WM_MBUTTONDBLCLK
:
4848 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4849 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
4852 case WM_RBUTTONDOWN
:
4854 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4855 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4856 DispatchPendingEvents();
4861 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
4862 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4863 DispatchPendingEvents();
4866 case WM_RBUTTONDBLCLK
:
4867 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
4868 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
4871 case WM_NCRBUTTONDOWN
:
4872 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, 0, lParamToClient(lParam
),
4873 PR_FALSE
, nsMouseEvent::eRightButton
,
4874 MOUSE_INPUT_SOURCE());
4875 DispatchPendingEvents();
4878 case WM_NCRBUTTONUP
:
4879 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, 0, lParamToClient(lParam
),
4880 PR_FALSE
, nsMouseEvent::eRightButton
,
4881 MOUSE_INPUT_SOURCE());
4882 DispatchPendingEvents();
4885 case WM_NCRBUTTONDBLCLK
:
4886 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, 0, lParamToClient(lParam
),
4887 PR_FALSE
, nsMouseEvent::eRightButton
,
4888 MOUSE_INPUT_SOURCE());
4892 PRUint32 appCommand
= GET_APPCOMMAND_LPARAM(lParam
);
4896 case APPCOMMAND_BROWSER_BACKWARD
:
4897 case APPCOMMAND_BROWSER_FORWARD
:
4898 case APPCOMMAND_BROWSER_REFRESH
:
4899 case APPCOMMAND_BROWSER_STOP
:
4900 case APPCOMMAND_BROWSER_SEARCH
:
4901 case APPCOMMAND_BROWSER_FAVORITES
:
4902 case APPCOMMAND_BROWSER_HOME
:
4903 DispatchCommandEvent(appCommand
);
4904 // tell the driver that we handled the event
4909 // default = PR_FALSE - tell the driver that the event was not handled
4916 result
= OnScroll(msg
, wParam
, lParam
);
4919 // The WM_ACTIVATE event is fired when a window is raised or lowered,
4920 // and the loword of wParam specifies which. But we don't want to tell
4921 // the focus system about this until the WM_SETFOCUS or WM_KILLFOCUS
4922 // events are fired. Instead, set either the sJustGotActivate or
4923 // gJustGotDeativate flags and fire the NS_ACTIVATE or NS_DEACTIVATE
4924 // events once the focus events arrive.
4926 if (mEventCallback
) {
4927 PRInt32 fActive
= LOWORD(wParam
);
4929 #if defined(WINCE_HAVE_SOFTKB)
4930 if (mIsTopWidgetWindow
&& sSoftKeyboardState
)
4931 nsWindowCE::ToggleSoftKB(mWnd
, fActive
);
4932 if (nsWindowCE::sShowSIPButton
== TRI_FALSE
&& WA_INACTIVE
!= fActive
) {
4933 HWND hWndSIPB
= FindWindowW(L
"MS_SIPBUTTON", NULL
);
4935 ShowWindow(hWndSIPB
, SW_HIDE
);
4940 if (WA_INACTIVE
== fActive
) {
4941 // when minimizing a window, the deactivation and focus events will
4942 // be fired in the reverse order. Instead, just dispatch
4943 // NS_DEACTIVATE right away.
4945 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
4947 sJustGotDeactivate
= PR_TRUE
;
4949 if (mIsTopWidgetWindow
)
4950 mLastKeyboardLayout
= gKbdLayout
.GetLayout();
4956 sJustGotActivate
= PR_TRUE
;
4957 nsMouseEvent
event(PR_TRUE
, NS_MOUSE_ACTIVATE
, this,
4958 nsMouseEvent::eReal
);
4961 event
.acceptActivation
= PR_TRUE
;
4963 PRBool result
= DispatchWindowEvent(&event
);
4965 if (event
.acceptActivation
)
4966 *aRetValue
= MA_ACTIVATE
;
4968 *aRetValue
= MA_NOACTIVATE
;
4970 if (sSwitchKeyboardLayout
&& mLastKeyboardLayout
)
4971 ActivateKeyboardLayout(mLastKeyboardLayout
, 0);
4977 #ifdef WINCE_WINDOWS_MOBILE
4978 if (!gCheckForHTCApi
&& gHTCApiNavOpen
== nsnull
) {
4979 gCheckForHTCApi
= PR_TRUE
;
4981 HINSTANCE library
= LoadLibrary(L
"HTCAPI.dll");
4982 gHTCApiNavOpen
= (HTCApiNavOpen
) GetProcAddress(library
, "HTCNavOpen");
4983 gHTCApiNavSetMode
= (HTCApiNavSetMode
) GetProcAddress(library
,"HTCNavSetMode");
4986 if (gHTCApiNavOpen
!= nsnull
) {
4987 gHTCApiNavOpen(mWnd
, 1 /* undocumented value */);
4989 if (gHTCApiNavSetMode
!= nsnull
)
4990 gHTCApiNavSetMode ( mWnd
, 4);
4991 // 4 is Gesture Mode. This will generate WM_HTCNAV events to the window
4997 case WM_MOUSEACTIVATE
:
4998 if (mWindowType
== eWindowType_popup
) {
4999 // a popup with a parent owner should not be activated when clicked
5000 // but should still allow the mouse event to be fired, so the return
5001 // value is set to MA_NOACTIVATE. But if the owner isn't the frontmost
5002 // window, just use default processing so that the window is activated.
5003 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
5004 if (owner
&& owner
== ::GetForegroundWindow()) {
5005 *aRetValue
= MA_NOACTIVATE
;
5011 case WM_WINDOWPOSCHANGING
:
5013 LPWINDOWPOS info
= (LPWINDOWPOS
) lParam
;
5014 OnWindowPosChanging(info
);
5020 if (sJustGotActivate
) {
5021 result
= DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
5024 #ifdef ACCESSIBILITY
5025 if (nsWindow::sIsAccessibilityOn
) {
5026 // Create it for the first time so that it can start firing events
5027 nsAccessible
*rootAccessible
= GetRootAccessible();
5031 #if defined(WINCE_HAVE_SOFTKB)
5033 // On Windows CE, we have a window that overlaps
5034 // the ISP button. In this case, we should always
5035 // try to hide it when we are activated
5037 nsIMEContext
IMEContext(mWnd
);
5039 ImmSetOpenStatus(IMEContext
.get(), TRUE
);
5045 #if defined(WINCE_HAVE_SOFTKB)
5047 nsIMEContext
IMEContext(mWnd
);
5048 ImmSetOpenStatus(IMEContext
.get(), FALSE
);
5051 if (sJustGotDeactivate
) {
5052 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
5056 case WM_WINDOWPOSCHANGED
:
5058 WINDOWPOS
*wp
= (LPWINDOWPOS
)lParam
;
5059 OnWindowPosChanged(wp
, result
);
5063 case WM_SETTINGCHANGE
:
5064 #if !defined (WINCE_WINDOWS_MOBILE)
5065 getWheelInfo
= PR_TRUE
;
5068 case SPI_SETSIPINFO
:
5069 case SPI_SETCURRENTIM
:
5070 nsWindowCE::OnSoftKbSettingsChange(mWnd
);
5072 case SETTINGCHANGE_RESET
:
5073 if (mWindowType
== eWindowType_invisible
) {
5074 // The OS sees to get confused and think that the invisable window
5075 // is in the foreground after an orientation change. By actually
5076 // setting it to the foreground and hiding it, we set it strait.
5077 // See bug 514007 for details.
5078 SetForegroundWindow(mWnd
);
5079 ShowWindow(mWnd
, SW_HIDE
);
5084 OnSettingsChange(wParam
, lParam
);
5088 case WM_INPUTLANGCHANGEREQUEST
:
5093 case WM_INPUTLANGCHANGE
:
5094 result
= OnInputLangChange((HKL
)lParam
);
5098 case WM_DESTROYCLIPBOARD
:
5100 nsIClipboard
* clipboard
;
5101 nsresult rv
= CallGetService(kCClipboardCID
, &clipboard
);
5102 clipboard
->EmptyClipboard(nsIClipboard::kGlobalClipboard
);
5103 NS_RELEASE(clipboard
);
5107 #ifdef ACCESSIBILITY
5111 if (lParam
== OBJID_CLIENT
) { // oleacc.dll will be loaded dynamically
5112 nsAccessible
*rootAccessible
= GetRootAccessible(); // Held by a11y cache
5113 if (rootAccessible
) {
5114 IAccessible
*msaaAccessible
= NULL
;
5115 rootAccessible
->GetNativeInterface((void**)&msaaAccessible
); // does an addref
5116 if (msaaAccessible
) {
5117 *aRetValue
= LresultFromObject(IID_IAccessible
, wParam
, msaaAccessible
); // does an addref
5118 msaaAccessible
->Release(); // release extra addref
5119 result
= PR_TRUE
; // We handled the WM_GETOBJECT message
5128 // prevent Windows from trimming the working set. bug 76831
5129 if (!sTrimOnMinimize
&& wParam
== SC_MINIMIZE
) {
5130 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
5139 nsMemory::HeapMinimize(PR_TRUE
);
5144 case WM_MOUSEHWHEEL
:
5146 // If OnMouseWheel returns true, the event was forwarded directly to another
5147 // mozilla window message handler (ProcessMessage). In this case the return
5148 // value of the forwarded event is in 'result' which we should return immediately.
5149 // If OnMouseWheel returns false, OnMouseWheel processed the event internally.
5150 // 'result' and 'aRetValue' will be set based on what we did with the event, so
5151 // we should fall through.
5152 if (OnMouseWheel(msg
, wParam
, lParam
, getWheelInfo
, result
, aRetValue
))
5158 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
5159 case WM_DWMCOMPOSITIONCHANGED
:
5160 UpdateNonClientMargins();
5161 BroadcastMsg(mWnd
, WM_DWMCOMPOSITIONCHANGED
);
5162 DispatchStandardEvent(NS_THEMECHANGED
);
5164 Invalidate(PR_FALSE
);
5168 case WM_UPDATEUISTATE
:
5170 // If the UI state has changed, fire an event so the UI updates the
5171 // keyboard cues based on the system setting and how the window was
5172 // opened. For example, a dialog opened via a keyboard press on a button
5173 // should enable cues, whereas the same dialog opened via a mouse click of
5174 // the button should not.
5175 PRInt32 action
= LOWORD(wParam
);
5176 if (action
== UIS_SET
|| action
== UIS_CLEAR
) {
5177 nsUIStateChangeEvent
event(PR_TRUE
, NS_UISTATECHANGED
, this);
5178 PRInt32 flags
= HIWORD(wParam
);
5179 if (flags
& UISF_HIDEACCEL
)
5180 event
.showAccelerators
= (action
== UIS_SET
) ? UIStateChangeType_Clear
: UIStateChangeType_Set
;
5181 if (flags
& UISF_HIDEFOCUS
)
5182 event
.showFocusRings
= (action
== UIS_SET
) ? UIStateChangeType_Clear
: UIStateChangeType_Set
;
5183 DispatchWindowEvent(&event
);
5189 /* Gesture support events */
5190 case WM_TABLET_QUERYSYSTEMGESTURESTATUS
:
5191 // According to MS samples, this must be handled to enable
5192 // rotational support in multi-touch drivers.
5194 *aRetValue
= TABLET_ROTATE_GESTURE_ENABLE
;
5198 result
= OnGesture(wParam
, lParam
);
5201 case WM_GESTURENOTIFY
:
5203 if (mWindowType
!= eWindowType_invisible
&&
5204 mWindowType
!= eWindowType_plugin
&&
5205 mWindowType
!= eWindowType_toplevel
) {
5206 // eWindowType_toplevel is the top level main frame window. Gesture support
5207 // there prevents the user from interacting with the title bar or nc
5208 // areas using a single finger. Java and plugin windows can make their
5210 GESTURENOTIFYSTRUCT
* gestureinfo
= (GESTURENOTIFYSTRUCT
*)lParam
;
5211 nsPointWin touchPoint
;
5212 touchPoint
= gestureinfo
->ptsLocation
;
5213 touchPoint
.ScreenToClient(mWnd
);
5214 nsGestureNotifyEvent
gestureNotifyEvent(PR_TRUE
, NS_GESTURENOTIFY_EVENT_START
, this);
5215 gestureNotifyEvent
.refPoint
= touchPoint
;
5216 nsEventStatus status
;
5217 DispatchEvent(&gestureNotifyEvent
, status
);
5218 mDisplayPanFeedback
= gestureNotifyEvent
.displayPanFeedback
;
5219 mGesture
.SetWinGestureSupport(mWnd
, gestureNotifyEvent
.panDirection
);
5221 result
= PR_FALSE
; //should always bubble to DefWindowProc
5224 #endif // !defined(WINCE)
5228 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_DELETE
, this);
5229 DispatchWindowEvent(&command
);
5236 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_CUT
, this);
5237 DispatchWindowEvent(&command
);
5244 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_COPY
, this);
5245 DispatchWindowEvent(&command
);
5252 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
, this);
5253 DispatchWindowEvent(&command
);
5261 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
, this);
5262 DispatchWindowEvent(&command
);
5263 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5270 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
, this);
5271 DispatchWindowEvent(&command
);
5272 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5279 // Support EM_CANPASTE message only when wParam isn't specified or
5280 // is plain text format.
5281 if (wParam
== 0 || wParam
== CF_TEXT
|| wParam
== CF_UNICODETEXT
) {
5282 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
,
5284 DispatchWindowEvent(&command
);
5285 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5293 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
,
5295 DispatchWindowEvent(&command
);
5296 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5303 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
,
5305 DispatchWindowEvent(&command
);
5306 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5312 #ifdef WINCE_WINDOWS_MOBILE
5313 //HTC NAVIGATION WHEEL EVENT
5316 int distance
= wParam
& 0x000000FF;
5317 if ( (wParam
& 0x000000100) != 0) // Counter Clockwise
5319 if (OnMouseWheel(WM_MOUSEWHEEL
, MAKEWPARAM(0, distance
),
5320 MAKELPARAM(GetSystemMetrics(SM_CXSCREEN
) / 2,
5321 GetSystemMetrics(SM_CYSCREEN
) / 2),
5322 getWheelInfo
, result
, aRetValue
))
5330 #ifdef NS_ENABLE_TSF
5331 if (msg
== WM_USER_TSF_TEXTCHANGE
) {
5332 nsTextStore::OnTextChangeMsg();
5334 #endif //NS_ENABLE_TSF
5335 #if defined(HEAP_DUMP_EVENT)
5336 if (msg
== GetHeapMsg()) {
5337 HeapDump(msg
, wParam
, lParam
);
5341 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
5342 if (msg
== nsAppShell::GetTaskbarButtonCreatedMessage())
5343 SetHasTaskbarIconBeenCreated();
5346 if (msg
== sOOPPPluginFocusEvent
) {
5348 // With OOPP, the plugin window exists in another process and is a child of
5349 // this window. This window is a placeholder plugin window for the dom. We
5350 // receive this event when the child window receives focus. (sent from
5351 // PluginInstanceParent.cpp)
5352 ::SendMessage(mWnd
, WM_MOUSEACTIVATE
, 0, 0); // See nsPluginNativeWindowWin.cpp
5354 // WM_KILLFOCUS was received by the child process.
5355 if (sJustGotDeactivate
) {
5356 DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
5365 //*aRetValue = result;
5370 //Events which caused mWnd destruction and aren't consumed
5371 //will crash during the Windows default processing.
5376 /**************************************************************
5378 * SECTION: Broadcast messaging
5380 * Broadcast messages to all windows.
5382 **************************************************************/
5384 // Enumerate all child windows sending aMsg to each of them
5385 BOOL CALLBACK
nsWindow::BroadcastMsgToChildren(HWND aWnd
, LPARAM aMsg
)
5387 WNDPROC winProc
= (WNDPROC
)::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
5388 if (winProc
== &nsWindow::WindowProc
) {
5389 // it's one of our windows so go ahead and send a message to it
5390 ::CallWindowProcW(winProc
, aWnd
, aMsg
, 0, 0);
5395 // Enumerate all top level windows specifying that the children of each
5396 // top level window should be enumerated. Do *not* send the message to
5397 // each top level window since it is assumed that the toolkit will send
5398 // aMsg to them directly.
5399 BOOL CALLBACK
nsWindow::BroadcastMsg(HWND aTopWindow
, LPARAM aMsg
)
5401 // Iterate each of aTopWindows child windows sending the aMsg
5404 ::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
5406 nsWindowCE::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
5411 // This method is called from nsToolkit::WindowProc to forward global
5412 // messages which need to be dispatched to all child windows.
5413 void nsWindow::GlobalMsgWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
5416 case WM_SYSCOLORCHANGE
:
5417 // Code to dispatch WM_SYSCOLORCHANGE message to all child windows.
5418 // WM_SYSCOLORCHANGE is only sent to top-level windows, but the
5419 // cross platform API requires that NS_SYSCOLORCHANGE message be sent to
5420 // all child windows as well. When running in an embedded application
5421 // we may not receive a WM_SYSCOLORCHANGE message because the top
5422 // level window is owned by the embeddor.
5423 // System color changes are posted to top-level windows only.
5424 // The NS_SYSCOLORCHANGE must be dispatched to all child
5427 ::EnumThreadWindows(GetCurrentThreadId(), nsWindow::BroadcastMsg
, msg
);
5433 /**************************************************************
5435 * SECTION: Event processing helpers
5437 * Special processing for certain event types and
5438 * synthesized events.
5440 **************************************************************/
5443 nsWindow::ClientMarginHitTestPoint(PRInt32 mx
, PRInt32 my
)
5445 // Calculations are done in screen coords
5447 GetWindowRect(mWnd
, &winRect
);
5449 // hit return constants:
5450 // HTBORDER - non-resizable border
5451 // HTBOTTOM, HTLEFT, HTRIGHT, HTTOP - resizable border
5452 // HTBOTTOMLEFT, HTBOTTOMRIGHT - resizable corner
5453 // HTTOPLEFT, HTTOPRIGHT - resizable corner
5454 // HTCAPTION - general title bar area
5455 // HTCLIENT - area considered the client
5456 // HTCLOSE - hovering over the close button
5457 // HTMAXBUTTON - maximize button
5458 // HTMINBUTTON - minimize button
5460 PRInt32 testResult
= HTCLIENT
;
5462 PRBool top
= PR_FALSE
;
5463 PRBool bottom
= PR_FALSE
;
5464 PRBool left
= PR_FALSE
;
5465 PRBool right
= PR_FALSE
;
5467 if (my
>= winRect
.top
&& my
<=
5468 (winRect
.top
+ mVertResizeMargin
+ (mCaptionHeight
- mNonClientOffset
.top
)))
5470 else if (my
<= winRect
.bottom
&& my
>= (winRect
.bottom
- mVertResizeMargin
))
5473 if (mx
>= winRect
.left
&& mx
<= (winRect
.left
+ mHorResizeMargin
))
5475 else if (mx
<= winRect
.right
&& mx
>= (winRect
.right
- mHorResizeMargin
))
5481 testResult
= HTTOPLEFT
;
5483 testResult
= HTTOPRIGHT
;
5484 } else if (bottom
) {
5485 testResult
= HTBOTTOM
;
5487 testResult
= HTBOTTOMLEFT
;
5489 testResult
= HTBOTTOMRIGHT
;
5492 testResult
= HTLEFT
;
5494 testResult
= HTRIGHT
;
5497 // There's no HTTOP in maximized state (bug 575493)
5498 if (mSizeMode
== nsSizeMode_Maximized
&& testResult
== HTTOP
)
5499 testResult
= HTCAPTION
;
5501 if (!mIsInMouseCapture
&&
5502 (testResult
== HTCLIENT
||
5503 testResult
== HTTOP
||
5504 testResult
== HTTOPLEFT
||
5505 testResult
== HTCAPTION
)) {
5506 LPARAM lParam
= MAKELPARAM(mx
, my
);
5507 LPARAM lParamClient
= lParamToClient(lParam
);
5508 PRBool result
= DispatchMouseEvent(NS_MOUSE_MOZHITTEST
, 0, lParamClient
,
5509 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5511 // The mouse is over a blank area
5512 testResult
= testResult
== HTCLIENT
? HTCAPTION
: testResult
;
5514 if (!mExitToNonClientArea
) {
5515 // The first time the mouse pointer goes from client area to non-client area,
5516 // we don't want to miss that movement so we can interpret mouseout input.
5517 ::SendMessage(mWnd
, WM_MOUSEMOVE
, 0, lParamClient
);
5518 mExitToNonClientArea
= PR_TRUE
;
5521 // There's content over the mouse pointer. Set HTCLIENT
5522 // to possibly override a resizer border.
5523 testResult
= HTCLIENT
;
5532 void nsWindow::PostSleepWakeNotification(const char* aNotification
)
5534 nsCOMPtr
<nsIObserverService
> observerService
=
5535 mozilla::services::GetObserverService();
5536 if (observerService
)
5537 observerService
->NotifyObservers(nsnull
, aNotification
, nsnull
);
5541 LRESULT
nsWindow::ProcessCharMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
5543 NS_PRECONDITION(aMsg
.message
== WM_CHAR
|| aMsg
.message
== WM_SYSCHAR
,
5544 "message is not keydown event");
5545 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5546 ("%s charCode=%d scanCode=%d\n",
5547 aMsg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
5548 aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF));
5550 // These must be checked here too as a lone WM_CHAR could be received
5551 // if a child window didn't handle it (for example Alt+Space in a content window)
5552 nsModifierKeyState modKeyState
;
5553 return OnChar(aMsg
, modKeyState
, aEventDispatched
);
5556 LRESULT
nsWindow::ProcessKeyUpMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
5558 NS_PRECONDITION(aMsg
.message
== WM_KEYUP
|| aMsg
.message
== WM_SYSKEYUP
,
5559 "message is not keydown event");
5560 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5561 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
5562 "WM_SYSKEYUP" : "WM_KEYUP", aMsg
.wParam
));
5564 nsModifierKeyState modKeyState
;
5566 // Note: the original code passed (HIWORD(lParam)) to OnKeyUp as
5567 // scan code. However, this breaks Alt+Num pad input.
5568 // MSDN states the following:
5569 // Typically, ToAscii performs the translation based on the
5570 // virtual-key code. In some cases, however, bit 15 of the
5571 // uScanCode parameter may be used to distinguish between a key
5572 // press and a key release. The scan code is used for
5573 // translating ALT+number key combinations.
5575 // ignore [shift+]alt+space so the OS can handle it
5576 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
5577 IS_VK_DOWN(NS_VK_SPACE
)) {
5581 if (!nsIMM32Handler::IsComposing(this) &&
5582 (aMsg
.message
!= WM_KEYUP
|| aMsg
.wParam
!= VK_MENU
)) {
5583 // Ignore VK_MENU if it's not a system key release, so that the menu bar does not trigger
5584 // This helps avoid triggering the menu bar for ALT key accelerators used in
5585 // assistive technologies such as Window-Eyes and ZoomText, and when using Alt+Tab
5586 // to switch back to Mozilla in Windows 95 and Windows 98
5587 return OnKeyUp(aMsg
, modKeyState
, aEventDispatched
);
5593 LRESULT
nsWindow::ProcessKeyDownMessage(const MSG
&aMsg
,
5594 PRBool
*aEventDispatched
)
5596 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5597 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
5598 "WM_SYSKEYDOWN" : "WM_KEYDOWN", aMsg
.wParam
));
5599 NS_PRECONDITION(aMsg
.message
== WM_KEYDOWN
|| aMsg
.message
== WM_SYSKEYDOWN
,
5600 "message is not keydown event");
5602 nsModifierKeyState modKeyState
;
5604 // Note: the original code passed (HIWORD(lParam)) to OnKeyDown as
5605 // scan code. However, this breaks Alt+Num pad input.
5606 // MSDN states the following:
5607 // Typically, ToAscii performs the translation based on the
5608 // virtual-key code. In some cases, however, bit 15 of the
5609 // uScanCode parameter may be used to distinguish between a key
5610 // press and a key release. The scan code is used for
5611 // translating ALT+number key combinations.
5613 // ignore [shift+]alt+space so the OS can handle it
5614 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
5615 IS_VK_DOWN(NS_VK_SPACE
))
5619 if (modKeyState
.mIsAltDown
&& nsIMM32Handler::IsStatusChanged()) {
5620 nsIMM32Handler::NotifyEndStatusChange();
5621 } else if (!nsIMM32Handler::IsComposing(this)) {
5622 result
= OnKeyDown(aMsg
, modKeyState
, aEventDispatched
, nsnull
);
5626 if (aMsg
.wParam
== VK_MENU
||
5627 (aMsg
.wParam
== VK_F10
&& !modKeyState
.mIsShiftDown
)) {
5628 // We need to let Windows handle this keypress,
5629 // by returning PR_FALSE, if there's a native menu
5630 // bar somewhere in our containing window hierarchy.
5631 // Otherwise we handle the keypress and don't pass
5632 // it on to Windows, by returning PR_TRUE.
5633 PRBool hasNativeMenu
= PR_FALSE
;
5636 if (::GetMenu(hWnd
)) {
5637 hasNativeMenu
= PR_TRUE
;
5640 hWnd
= ::GetParent(hWnd
);
5642 result
= !hasNativeMenu
;
5650 nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout
,
5651 PRInt32 aNativeKeyCode
,
5652 PRUint32 aModifierFlags
,
5653 const nsAString
& aCharacters
,
5654 const nsAString
& aUnmodifiedCharacters
)
5656 #ifndef WINCE //Win CE doesn't support many of the calls used in this method, perhaps theres another way
5657 nsPrintfCString
layoutName("%08x", aNativeKeyboardLayout
);
5658 HKL loadedLayout
= LoadKeyboardLayoutA(layoutName
.get(), KLF_NOTELLSHELL
);
5659 if (loadedLayout
== NULL
)
5660 return NS_ERROR_NOT_AVAILABLE
;
5662 // Setup clean key state and load desired layout
5663 BYTE originalKbdState
[256];
5664 ::GetKeyboardState(originalKbdState
);
5666 memset(kbdState
, 0, sizeof(kbdState
));
5667 // This changes the state of the keyboard for the current thread only,
5668 // and we'll restore it soon, so this should be OK.
5669 ::SetKeyboardState(kbdState
);
5670 HKL oldLayout
= gKbdLayout
.GetLayout();
5671 gKbdLayout
.LoadLayout(loadedLayout
);
5673 nsAutoTArray
<KeyPair
,10> keySequence
;
5674 SetupKeyModifiersSequence(&keySequence
, aModifierFlags
);
5675 NS_ASSERTION(aNativeKeyCode
>= 0 && aNativeKeyCode
< 256,
5676 "Native VK key code out of range");
5677 keySequence
.AppendElement(KeyPair(aNativeKeyCode
, 0));
5679 // Simulate the pressing of each modifier key and then the real key
5680 for (PRUint32 i
= 0; i
< keySequence
.Length(); ++i
) {
5681 PRUint8 key
= keySequence
[i
].mGeneral
;
5682 PRUint8 keySpecific
= keySequence
[i
].mSpecific
;
5683 kbdState
[key
] = 0x81; // key is down and toggled on if appropriate
5685 kbdState
[keySpecific
] = 0x81;
5687 ::SetKeyboardState(kbdState
);
5688 nsModifierKeyState modKeyState
;
5689 MSG msg
= InitMSG(WM_KEYDOWN
, key
, 0);
5690 if (i
== keySequence
.Length() - 1 && aCharacters
.Length() > 0) {
5691 UINT scanCode
= ::MapVirtualKeyEx(aNativeKeyCode
, MAPVK_VK_TO_VSC
,
5692 gKbdLayout
.GetLayout());
5693 nsFakeCharMessage fakeMsg
= { aCharacters
.CharAt(0), scanCode
};
5694 OnKeyDown(msg
, modKeyState
, nsnull
, &fakeMsg
);
5696 OnKeyDown(msg
, modKeyState
, nsnull
, nsnull
);
5699 for (PRUint32 i
= keySequence
.Length(); i
> 0; --i
) {
5700 PRUint8 key
= keySequence
[i
- 1].mGeneral
;
5701 PRUint8 keySpecific
= keySequence
[i
- 1].mSpecific
;
5702 kbdState
[key
] = 0; // key is up and toggled off if appropriate
5704 kbdState
[keySpecific
] = 0;
5706 ::SetKeyboardState(kbdState
);
5707 nsModifierKeyState modKeyState
;
5708 MSG msg
= InitMSG(WM_KEYUP
, key
, 0);
5709 OnKeyUp(msg
, modKeyState
, nsnull
);
5712 // Restore old key state and layout
5713 ::SetKeyboardState(originalKbdState
);
5714 gKbdLayout
.LoadLayout(oldLayout
);
5716 UnloadKeyboardLayout(loadedLayout
);
5718 #else //XXX: is there another way to do this?
5719 return NS_ERROR_NOT_IMPLEMENTED
;
5724 nsWindow::SynthesizeNativeMouseEvent(nsIntPoint aPoint
,
5725 PRUint32 aNativeMessage
,
5726 PRUint32 aModifierFlags
)
5728 #ifndef WINCE // I don't think WINCE supports SendInput
5730 ::GetWindowRect(mWnd
, &r
);
5731 ::SetCursorPos(r
.left
+ aPoint
.x
, r
.top
+ aPoint
.y
);
5734 memset(&input
, 0, sizeof(input
));
5736 input
.type
= INPUT_MOUSE
;
5737 input
.mi
.dwFlags
= aNativeMessage
;
5738 ::SendInput(1, &input
, sizeof(INPUT
));
5742 return NS_ERROR_NOT_IMPLEMENTED
;
5746 /**************************************************************
5748 * SECTION: OnXXX message handlers
5750 * For message handlers that need to be broken out or
5751 * implemented in specific platform code.
5753 **************************************************************/
5755 BOOL
nsWindow::OnInputLangChange(HKL aHKL
)
5758 printf("OnInputLanguageChange\n");
5762 gKbdLayout
.LoadLayout(aHKL
);
5765 return PR_FALSE
; // always pass to child window
5768 #if !defined(WINCE) // implemented in nsWindowCE.cpp
5769 void nsWindow::OnWindowPosChanged(WINDOWPOS
*wp
, PRBool
& result
)
5774 #ifdef WINSTATE_DEBUG_OUTPUT
5775 if (mWnd
== GetTopLevelHWND(mWnd
))
5776 printf("*** OnWindowPosChanged: [ top] ");
5778 printf("*** OnWindowPosChanged: [child] ");
5779 printf("WINDOWPOS flags:");
5780 if (wp
->flags
& SWP_FRAMECHANGED
)
5781 printf("SWP_FRAMECHANGED ");
5782 if (wp
->flags
& SWP_SHOWWINDOW
)
5783 printf("SWP_SHOWWINDOW ");
5784 if (wp
->flags
& SWP_NOSIZE
)
5785 printf("SWP_NOSIZE ");
5786 if (wp
->flags
& SWP_HIDEWINDOW
)
5787 printf("SWP_HIDEWINDOW ");
5791 // Handle window size mode changes
5792 if (wp
->flags
& SWP_FRAMECHANGED
&& mSizeMode
!= nsSizeMode_Fullscreen
) {
5793 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
5796 pl
.length
= sizeof(pl
);
5797 ::GetWindowPlacement(mWnd
, &pl
);
5799 if (pl
.showCmd
== SW_SHOWMAXIMIZED
)
5800 event
.mSizeMode
= nsSizeMode_Maximized
;
5801 else if (pl
.showCmd
== SW_SHOWMINIMIZED
)
5802 event
.mSizeMode
= nsSizeMode_Minimized
;
5804 event
.mSizeMode
= nsSizeMode_Normal
;
5806 // Windows has just changed the size mode of this window. The following
5807 // NS_SIZEMODE event will trigger a call into SetSizeMode where we will
5808 // set the min/max window state again or for nsSizeMode_Normal, call
5809 // SetWindow with a parameter of SW_RESTORE. There's no need however as
5810 // this window's mode has already changed. Updating mSizeMode here
5811 // insures the SetSizeMode call is a no-op. Addresses a bug on Win7 related
5812 // to window docking. (bug 489258)
5813 mSizeMode
= event
.mSizeMode
;
5815 // If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
5816 // SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
5817 // prevents the working set from being trimmed but keeps the window active.
5818 // After the window is minimized, we need to do some touch up work on the
5819 // active window. (bugs 76831 & 499816)
5820 if (!sTrimOnMinimize
&& nsSizeMode_Minimized
== event
.mSizeMode
)
5821 ActivateOtherWindowHelper(mWnd
);
5823 #ifdef WINSTATE_DEBUG_OUTPUT
5824 switch (mSizeMode
) {
5825 case nsSizeMode_Normal
:
5826 printf("*** mSizeMode: nsSizeMode_Normal\n");
5828 case nsSizeMode_Minimized
:
5829 printf("*** mSizeMode: nsSizeMode_Minimized\n");
5831 case nsSizeMode_Maximized
:
5832 printf("*** mSizeMode: nsSizeMode_Maximized\n");
5835 printf("*** mSizeMode: ??????\n");
5842 result
= DispatchWindowEvent(&event
);
5844 // Skip window size change events below on minimization.
5845 if (mSizeMode
== nsSizeMode_Minimized
)
5849 // Handle window size changes
5850 if (0 == (wp
->flags
& SWP_NOSIZE
)) {
5852 PRInt32 newWidth
, newHeight
;
5854 ::GetWindowRect(mWnd
, &r
);
5856 newWidth
= r
.right
- r
.left
;
5857 newHeight
= r
.bottom
- r
.top
;
5858 nsIntRect
rect(wp
->x
, wp
->y
, newWidth
, newHeight
);
5861 if (eTransparencyTransparent
== mTransparencyMode
)
5862 ResizeTranslucentWindow(newWidth
, newHeight
);
5865 if (newWidth
> mLastSize
.width
)
5870 drect
.left
= wp
->x
+ mLastSize
.width
;
5872 drect
.right
= drect
.left
+ (newWidth
- mLastSize
.width
);
5873 drect
.bottom
= drect
.top
+ newHeight
;
5875 ::RedrawWindow(mWnd
, &drect
, NULL
,
5878 RDW_NOINTERNALPAINT
|
5882 if (newHeight
> mLastSize
.height
)
5888 drect
.top
= wp
->y
+ mLastSize
.height
;
5889 drect
.right
= drect
.left
+ newWidth
;
5890 drect
.bottom
= drect
.top
+ (newHeight
- mLastSize
.height
);
5892 ::RedrawWindow(mWnd
, &drect
, NULL
,
5895 RDW_NOINTERNALPAINT
|
5900 mBounds
.width
= newWidth
;
5901 mBounds
.height
= newHeight
;
5902 mLastSize
.width
= newWidth
;
5903 mLastSize
.height
= newHeight
;
5905 #ifdef WINSTATE_DEBUG_OUTPUT
5906 printf("*** Resize window: %d x %d x %d x %d\n", wp
->x
, wp
->y
, newWidth
, newHeight
);
5909 // Recalculate the width and height based on the client area for gecko events.
5910 if (::GetClientRect(mWnd
, &r
)) {
5911 rect
.width
= r
.right
- r
.left
;
5912 rect
.height
= r
.bottom
- r
.top
;
5915 // Send a gecko resize event
5916 result
= OnResize(rect
);
5921 void nsWindow::ActivateOtherWindowHelper(HWND aWnd
)
5923 // Find the next window that is enabled, visible, and not minimized.
5924 HWND hwndBelow
= ::GetNextWindow(aWnd
, GW_HWNDNEXT
);
5925 while (hwndBelow
&& (!::IsWindowEnabled(hwndBelow
) || !::IsWindowVisible(hwndBelow
) ||
5926 ::IsIconic(hwndBelow
))) {
5927 hwndBelow
= ::GetNextWindow(hwndBelow
, GW_HWNDNEXT
);
5930 // Push ourselves to the bottom of the stack, then activate the
5932 ::SetWindowPos(aWnd
, HWND_BOTTOM
, 0, 0, 0, 0,
5933 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
5935 ::SetForegroundWindow(hwndBelow
);
5937 // Play the minimize sound while we're here, since that is also
5938 // forgotten when we use SW_SHOWMINIMIZED.
5939 ::PlaySoundW(L
"Minimize", nsnull
, SND_ALIAS
| SND_NODEFAULT
| SND_ASYNC
);
5941 #endif // !defined(WINCE)
5944 void nsWindow::OnWindowPosChanging(LPWINDOWPOS
& info
)
5946 // Update non-client margins if the frame size is changing, and let the
5947 // browser know we are changing size modes, so alternative css can kick in.
5948 // If we're going into fullscreen mode, ignore this, since it'll reset
5949 // margins to normal mode.
5950 if (info
->flags
& SWP_FRAMECHANGED
&& mSizeMode
!= nsSizeMode_Fullscreen
) {
5952 pl
.length
= sizeof(pl
);
5953 ::GetWindowPlacement(mWnd
, &pl
);
5955 if (pl
.showCmd
== SW_SHOWMAXIMIZED
)
5956 sizeMode
= nsSizeMode_Maximized
;
5957 else if (pl
.showCmd
== SW_SHOWMINIMIZED
)
5958 sizeMode
= nsSizeMode_Minimized
;
5960 sizeMode
= nsSizeMode_Normal
;
5962 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
5965 event
.mSizeMode
= static_cast<nsSizeMode
>(sizeMode
);
5966 DispatchWindowEvent(&event
);
5968 UpdateNonClientMargins(sizeMode
, PR_FALSE
);
5971 // enforce local z-order rules
5972 if (!(info
->flags
& SWP_NOZORDER
)) {
5973 HWND hwndAfter
= info
->hwndInsertAfter
;
5975 nsZLevelEvent
event(PR_TRUE
, NS_SETZLEVEL
, this);
5976 nsWindow
*aboveWindow
= 0;
5980 if (hwndAfter
== HWND_BOTTOM
)
5981 event
.mPlacement
= nsWindowZBottom
;
5982 else if (hwndAfter
== HWND_TOP
|| hwndAfter
== HWND_TOPMOST
|| hwndAfter
== HWND_NOTOPMOST
)
5983 event
.mPlacement
= nsWindowZTop
;
5985 event
.mPlacement
= nsWindowZRelative
;
5986 aboveWindow
= GetNSWindowPtr(hwndAfter
);
5988 event
.mReqBelow
= aboveWindow
;
5989 event
.mActualBelow
= nsnull
;
5991 event
.mImmediate
= PR_FALSE
;
5992 event
.mAdjusted
= PR_FALSE
;
5993 DispatchWindowEvent(&event
);
5995 if (event
.mAdjusted
) {
5996 if (event
.mPlacement
== nsWindowZBottom
)
5997 info
->hwndInsertAfter
= HWND_BOTTOM
;
5998 else if (event
.mPlacement
== nsWindowZTop
)
5999 info
->hwndInsertAfter
= HWND_TOP
;
6001 info
->hwndInsertAfter
= (HWND
)event
.mActualBelow
->GetNativeData(NS_NATIVE_WINDOW
);
6004 NS_IF_RELEASE(event
.mActualBelow
);
6006 // prevent rude external programs from making hidden window visible
6007 if (mWindowType
== eWindowType_invisible
)
6008 info
->flags
&= ~SWP_SHOWWINDOW
;
6012 void nsWindow::UserActivity()
6014 // Check if we have the idle service, if not we try to get it.
6015 if (!mIdleService
) {
6016 mIdleService
= do_GetService("@mozilla.org/widget/idleservice;1");
6019 // Check that we now have the idle service.
6021 mIdleService
->ResetIdleTimeOut();
6025 // Gesture event processing. Handles WM_GESTURE events.
6027 PRBool
nsWindow::OnGesture(WPARAM wParam
, LPARAM lParam
)
6029 // Treatment for pan events which translate into scroll events:
6030 if (mGesture
.IsPanEvent(lParam
)) {
6031 nsMouseScrollEvent
event(PR_TRUE
, NS_MOUSE_PIXEL_SCROLL
, this);
6033 if ( !mGesture
.ProcessPanMessage(mWnd
, wParam
, lParam
) )
6034 return PR_FALSE
; // ignore
6036 nsEventStatus status
;
6038 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6039 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6040 event
.isMeta
= PR_FALSE
;
6041 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6043 event
.time
= ::GetMessageTime();
6044 event
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6046 PRBool endFeedback
= PR_TRUE
;
6048 PRInt32 scrollOverflowX
= 0;
6049 PRInt32 scrollOverflowY
= 0;
6051 if (mGesture
.PanDeltaToPixelScrollX(event
)) {
6052 DispatchEvent(&event
, status
);
6053 scrollOverflowX
= event
.scrollOverflow
;
6056 if (mGesture
.PanDeltaToPixelScrollY(event
)) {
6057 DispatchEvent(&event
, status
);
6058 scrollOverflowY
= event
.scrollOverflow
;
6061 if (mDisplayPanFeedback
) {
6062 mGesture
.UpdatePanFeedbackX(mWnd
, scrollOverflowX
, endFeedback
);
6063 mGesture
.UpdatePanFeedbackY(mWnd
, scrollOverflowY
, endFeedback
);
6064 mGesture
.PanFeedbackFinalize(mWnd
, endFeedback
);
6067 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
6072 // Other gestures translate into simple gesture events:
6073 nsSimpleGestureEvent
event(PR_TRUE
, 0, this, 0, 0.0);
6074 if ( !mGesture
.ProcessGestureMessage(mWnd
, wParam
, lParam
, event
) ) {
6075 return PR_FALSE
; // fall through to DefWndProc
6078 // Polish up and send off the new event
6079 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6080 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6081 event
.isMeta
= PR_FALSE
;
6082 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6084 event
.time
= ::GetMessageTime();
6085 event
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6087 nsEventStatus status
;
6088 DispatchEvent(&event
, status
);
6089 if (status
== nsEventStatus_eIgnore
) {
6090 return PR_FALSE
; // Ignored, fall through
6093 // Only close this if we process and return true.
6094 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
6096 return PR_TRUE
; // Handled
6098 #endif // !defined(WINCE)
6101 PRUint16
nsWindow::GetMouseInputSource()
6103 PRUint16 inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_MOUSE
;
6104 LPARAM lParamExtraInfo
= ::GetMessageExtraInfo();
6105 if ((lParamExtraInfo
& TABLET_INK_SIGNATURE
) == TABLET_INK_CHECK
) {
6106 inputSource
= (lParamExtraInfo
& TABLET_INK_TOUCH
) ?
6107 nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
: nsIDOMNSMouseEvent::MOZ_SOURCE_PEN
;
6113 * OnMouseWheel - mouse wheele event processing. This was originally embedded
6114 * within the message case block. If returning true result should be returned
6115 * immediately (no more processing).
6117 PRBool
nsWindow::OnMouseWheel(UINT msg
, WPARAM wParam
, LPARAM lParam
, PRBool
& getWheelInfo
, PRBool
& result
, LRESULT
*aRetValue
)
6119 // Handle both flavors of mouse wheel events.
6120 static int iDeltaPerLine
, iDeltaPerChar
;
6121 static ULONG ulScrollLines
, ulScrollChars
= 1;
6122 static int currentVDelta
, currentHDelta
;
6123 static HWND currentWindow
= 0;
6125 PRBool isVertical
= msg
== WM_MOUSEWHEEL
;
6127 // Get mouse wheel metrics (but only once).
6129 getWheelInfo
= PR_FALSE
;
6131 SystemParametersInfo (SPI_GETWHEELSCROLLLINES
, 0, &ulScrollLines
, 0);
6133 // ulScrollLines usually equals 3 or 0 (for no scrolling)
6134 // WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
6136 // However, if ulScrollLines > WHEEL_DELTA, we assume that
6137 // the mouse driver wants a page scroll. The docs state that
6138 // ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
6139 // since some mouse drivers use an arbitrary large number instead,
6140 // we have to handle that as well.
6143 if (ulScrollLines
) {
6144 if (ulScrollLines
<= WHEEL_DELTA
) {
6145 iDeltaPerLine
= WHEEL_DELTA
/ ulScrollLines
;
6147 ulScrollLines
= WHEEL_PAGESCROLL
;
6151 if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0,
6152 &ulScrollChars
, 0)) {
6153 // Note that we may always fail to get the value before Win Vista.
6158 if (ulScrollChars
) {
6159 if (ulScrollChars
<= WHEEL_DELTA
) {
6160 iDeltaPerChar
= WHEEL_DELTA
/ ulScrollChars
;
6162 ulScrollChars
= WHEEL_PAGESCROLL
;
6167 if ((isVertical
&& ulScrollLines
!= WHEEL_PAGESCROLL
&& !iDeltaPerLine
) ||
6168 (!isVertical
&& ulScrollChars
!= WHEEL_PAGESCROLL
&& !iDeltaPerChar
))
6169 return PR_FALSE
; // break
6171 // The mousewheel event will be dispatched to the toplevel
6172 // window. We need to give it to the child window
6174 if (!HandleScrollingPlugins(msg
, wParam
, lParam
, result
, aRetValue
, quit
))
6175 return quit
; // return immediately if its not our window
6177 // We should cancel the surplus delta if the current window is not
6178 // same as previous.
6179 if (currentWindow
!= mWnd
) {
6182 currentWindow
= mWnd
;
6185 nsMouseScrollEvent
scrollEvent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
6186 scrollEvent
.delta
= 0;
6188 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsVertical
;
6189 if (ulScrollLines
== WHEEL_PAGESCROLL
) {
6190 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6191 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? -1 : 1;
6193 currentVDelta
-= (short) HIWORD (wParam
);
6194 if (PR_ABS(currentVDelta
) >= iDeltaPerLine
) {
6195 scrollEvent
.delta
= currentVDelta
/ iDeltaPerLine
;
6196 currentVDelta
%= iDeltaPerLine
;
6200 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsHorizontal
;
6201 if (ulScrollChars
== WHEEL_PAGESCROLL
) {
6202 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6203 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? 1 : -1;
6205 currentHDelta
+= (short) HIWORD (wParam
);
6206 if (PR_ABS(currentHDelta
) >= iDeltaPerChar
) {
6207 scrollEvent
.delta
= currentHDelta
/ iDeltaPerChar
;
6208 currentHDelta
%= iDeltaPerChar
;
6213 if (!scrollEvent
.delta
) {
6214 // We store the wheel delta, and it will be used next wheel message, so,
6215 // we consume this message actually. We shouldn't call next wndproc.
6217 return PR_FALSE
; // break
6221 // The event may go to a plug-in which already dispatched this message.
6222 // Then, the event can cause deadlock. We should unlock the sender here.
6223 ::ReplyMessage(isVertical
? 0 : TRUE
);
6226 scrollEvent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6227 scrollEvent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6228 scrollEvent
.isMeta
= PR_FALSE
;
6229 scrollEvent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6230 InitEvent(scrollEvent
);
6231 if (nsnull
!= mEventCallback
) {
6232 result
= DispatchWindowEvent(&scrollEvent
);
6234 // Note that we should return zero if we process WM_MOUSEWHEEL.
6235 // But if we process WM_MOUSEHWHEEL, we should return non-zero.
6238 *aRetValue
= isVertical
? 0 : TRUE
;
6240 return PR_FALSE
; // break;
6244 StringCaseInsensitiveEquals(const PRUnichar
* aChars1
, const PRUint32 aNumChars1
,
6245 const PRUnichar
* aChars2
, const PRUint32 aNumChars2
)
6247 if (aNumChars1
!= aNumChars2
)
6250 nsCaseInsensitiveStringComparator comp
;
6251 return comp(aChars1
, aChars2
, aNumChars1
) == 0;
6254 UINT
nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode
)
6257 switch (aNativeKeyCode
) {
6258 case VK_OEM_1
: return NS_VK_SEMICOLON
; // 0xBA, For the US standard keyboard, the ';:' key
6259 case VK_OEM_PLUS
: return NS_VK_ADD
; // 0xBB, For any country/region, the '+' key
6260 case VK_OEM_MINUS
: return NS_VK_SUBTRACT
; // 0xBD, For any country/region, the '-' key
6264 return aNativeKeyCode
;
6268 * nsWindow::OnKeyDown peeks into the message queue and pulls out
6269 * WM_CHAR messages for processing. During testing we don't want to
6270 * mess with the real message queue. Instead we pass a
6271 * pseudo-WM_CHAR-message using this structure, and OnKeyDown will use
6272 * that as if it was in the message queue, and refrain from actually
6273 * looking at or touching the message queue.
6275 LRESULT
nsWindow::OnKeyDown(const MSG
&aMsg
,
6276 nsModifierKeyState
&aModKeyState
,
6277 PRBool
*aEventDispatched
,
6278 nsFakeCharMessage
* aFakeCharMessage
)
6280 UINT virtualKeyCode
= aMsg
.wParam
;
6283 gKbdLayout
.OnKeyDown (virtualKeyCode
);
6286 // Use only DOMKeyCode for XP processing.
6287 // Use aVirtualKeyCode for gKbdLayout and native processing.
6288 UINT DOMKeyCode
= nsIMM32Handler::IsComposing(this) ?
6289 virtualKeyCode
: MapFromNativeToDOM(virtualKeyCode
);
6292 //printf("In OnKeyDown virt: %d\n", DOMKeyCode);
6296 DispatchKeyEvent(NS_KEY_DOWN
, 0, nsnull
, DOMKeyCode
, &aMsg
, aModKeyState
);
6297 if (aEventDispatched
)
6298 *aEventDispatched
= PR_TRUE
;
6300 // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
6301 // for almost all keys
6302 switch (DOMKeyCode
) {
6306 case NS_VK_CAPS_LOCK
:
6307 case NS_VK_NUM_LOCK
:
6308 case NS_VK_SCROLL_LOCK
: return noDefault
;
6311 PRUint32 extraFlags
= (noDefault
? NS_EVENT_FLAG_NO_DEFAULT
: 0);
6313 BOOL gotMsg
= aFakeCharMessage
||
6314 ::PeekMessageW(&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
6315 // Enter and backspace are always handled here to avoid for example the
6316 // confusion between ctrl-enter and ctrl-J.
6317 if (DOMKeyCode
== NS_VK_RETURN
|| DOMKeyCode
== NS_VK_BACK
||
6318 ((aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)
6322 && !gKbdLayout
.IsDeadKey() && KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)))
6325 // Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
6326 // They can be more than one because of:
6327 // * Dead-keys not pairing with base character
6328 // * Some keyboard layouts may map up to 4 characters to the single key
6329 PRBool anyCharMessagesRemoved
= PR_FALSE
;
6331 if (aFakeCharMessage
) {
6332 anyCharMessagesRemoved
= PR_TRUE
;
6334 while (gotMsg
&& (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
))
6336 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6337 ("%s charCode=%d scanCode=%d\n", msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
6338 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
6339 RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST
, WM_KEYLAST
);
6340 anyCharMessagesRemoved
= PR_TRUE
;
6342 gotMsg
= ::PeekMessageW (&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
6346 if (!anyCharMessagesRemoved
&& DOMKeyCode
== NS_VK_BACK
&&
6347 nsIMM32Handler::IsDoingKakuteiUndo(mWnd
)) {
6348 NS_ASSERTION(!aFakeCharMessage
,
6349 "We shouldn't be touching the real msg queue");
6350 RemoveMessageAndDispatchPluginEvent(WM_CHAR
, WM_CHAR
);
6354 (aFakeCharMessage
||
6355 msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
|| msg
.message
== WM_DEADCHAR
)) {
6356 if (aFakeCharMessage
)
6357 return OnCharRaw(aFakeCharMessage
->mCharCode
,
6358 aFakeCharMessage
->mScanCode
, aModKeyState
, extraFlags
);
6360 // If prevent default set for keydown, do same for keypress
6361 ::GetMessageW(&msg
, mWnd
, msg
.message
, msg
.message
);
6363 if (msg
.message
== WM_DEADCHAR
) {
6364 if (!PluginHasFocus())
6367 // We need to send the removed message to focused plug-in.
6368 DispatchPluginEvent(msg
);
6372 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6373 ("%s charCode=%d scanCode=%d\n",
6374 msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
6375 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
6377 BOOL result
= OnChar(msg
, aModKeyState
, nsnull
, extraFlags
);
6378 // If a syschar keypress wasn't processed, Windows may want to
6379 // handle it to activate a native menu.
6380 if (!result
&& msg
.message
== WM_SYSCHAR
)
6381 ::DefWindowProcW(mWnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
6385 else if (!aModKeyState
.mIsControlDown
&& !aModKeyState
.mIsAltDown
&&
6386 (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
) ||
6387 KeyboardLayout::IsNumpadKey(virtualKeyCode
)))
6389 // If this is simple KeyDown event but next message is not WM_CHAR,
6390 // this event may not input text, so we should ignore this event.
6392 return PluginHasFocus() && noDefault
;
6395 if (gKbdLayout
.IsDeadKey ())
6396 return PluginHasFocus() && noDefault
;
6398 PRUint8 shiftStates
[5];
6399 PRUnichar uniChars
[5];
6400 PRUnichar shiftedChars
[5] = {0, 0, 0, 0, 0};
6401 PRUnichar unshiftedChars
[5] = {0, 0, 0, 0, 0};
6402 PRUnichar shiftedLatinChar
= 0;
6403 PRUnichar unshiftedLatinChar
= 0;
6404 PRUint32 numOfUniChars
= 0;
6405 PRUint32 numOfShiftedChars
= 0;
6406 PRUint32 numOfUnshiftedChars
= 0;
6407 PRUint32 numOfShiftStates
= 0;
6409 switch (virtualKeyCode
) {
6410 // keys to be sent as characters
6411 case VK_ADD
: uniChars
[0] = '+'; numOfUniChars
= 1; break;
6412 case VK_SUBTRACT
: uniChars
[0] = '-'; numOfUniChars
= 1; break;
6413 case VK_DIVIDE
: uniChars
[0] = '/'; numOfUniChars
= 1; break;
6414 case VK_MULTIPLY
: uniChars
[0] = '*'; numOfUniChars
= 1; break;
6425 uniChars
[0] = virtualKeyCode
- VK_NUMPAD0
+ '0';
6429 if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)) {
6430 numOfUniChars
= numOfShiftStates
=
6431 gKbdLayout
.GetUniChars(uniChars
, shiftStates
,
6432 NS_ARRAY_LENGTH(uniChars
));
6435 if (aModKeyState
.mIsControlDown
^ aModKeyState
.mIsAltDown
) {
6436 PRUint8 capsLockState
= (::GetKeyState(VK_CAPITAL
) & 1) ? eCapsLock
: 0;
6437 numOfUnshiftedChars
=
6438 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
, capsLockState
,
6439 unshiftedChars
, NS_ARRAY_LENGTH(unshiftedChars
));
6441 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
,
6442 capsLockState
| eShift
,
6443 shiftedChars
, NS_ARRAY_LENGTH(shiftedChars
));
6445 // The current keyboard cannot input alphabets or numerics,
6446 // we should append them for Shortcut/Access keys.
6447 // E.g., for Cyrillic keyboard layout.
6448 if (NS_VK_A
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_Z
) {
6449 shiftedLatinChar
= unshiftedLatinChar
= DOMKeyCode
;
6451 shiftedLatinChar
+= 0x20;
6453 unshiftedLatinChar
+= 0x20;
6454 if (unshiftedLatinChar
== unshiftedChars
[0] &&
6455 shiftedLatinChar
== shiftedChars
[0]) {
6456 shiftedLatinChar
= unshiftedLatinChar
= 0;
6460 if (NS_VK_0
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_9
) {
6463 switch (virtualKeyCode
) {
6464 case VK_OEM_PLUS
: ch
= '+'; break;
6465 case VK_OEM_MINUS
: ch
= '-'; break;
6468 if (ch
&& unshiftedChars
[0] != ch
&& shiftedChars
[0] != ch
) {
6469 // Windows has assigned a virtual key code to the key even though
6470 // the character can't be produced with this key. That probably
6471 // means the character can't be produced with any key in the
6472 // current layout and so the assignment is based on a QWERTY
6473 // layout. Append this code so that users can access the shortcut.
6474 unshiftedLatinChar
= ch
;
6478 // If the charCode is not ASCII character, we should replace the
6479 // charCode with ASCII character only when Ctrl is pressed.
6480 // But don't replace the charCode when the charCode is not same as
6481 // unmodified characters. In such case, Ctrl is sometimes used for a
6482 // part of character inputting key combination like Shift.
6483 if (aModKeyState
.mIsControlDown
) {
6484 PRUint8 currentState
= eCtrl
;
6485 if (aModKeyState
.mIsShiftDown
)
6486 currentState
|= eShift
;
6489 aModKeyState
.mIsShiftDown
? shiftedLatinChar
: unshiftedLatinChar
;
6491 (numOfUniChars
== 0 ||
6492 StringCaseInsensitiveEquals(uniChars
, numOfUniChars
,
6493 aModKeyState
.mIsShiftDown
? shiftedChars
: unshiftedChars
,
6494 aModKeyState
.mIsShiftDown
? numOfShiftedChars
:
6495 numOfUnshiftedChars
))) {
6496 numOfUniChars
= numOfShiftStates
= 1;
6498 shiftStates
[0] = currentState
;
6504 if (numOfUniChars
> 0 || numOfShiftedChars
> 0 || numOfUnshiftedChars
> 0) {
6505 PRUint32 num
= PR_MAX(numOfUniChars
,
6506 PR_MAX(numOfShiftedChars
, numOfUnshiftedChars
));
6507 PRUint32 skipUniChars
= num
- numOfUniChars
;
6508 PRUint32 skipShiftedChars
= num
- numOfShiftedChars
;
6509 PRUint32 skipUnshiftedChars
= num
- numOfUnshiftedChars
;
6510 UINT keyCode
= numOfUniChars
== 0 ? DOMKeyCode
: 0;
6511 for (PRUint32 cnt
= 0; cnt
< num
; cnt
++) {
6512 PRUint16 uniChar
, shiftedChar
, unshiftedChar
;
6513 uniChar
= shiftedChar
= unshiftedChar
= 0;
6514 if (skipUniChars
<= cnt
) {
6515 if (cnt
- skipUniChars
< numOfShiftStates
) {
6516 // If key in combination with Alt and/or Ctrl produces a different
6517 // character than without them then do not report these flags
6518 // because it is separate keyboard layout shift state. If dead-key
6519 // and base character does not produce a valid composite character
6520 // then both produced dead-key character and following base
6521 // character may have different modifier flags, too.
6522 aModKeyState
.mIsShiftDown
=
6523 (shiftStates
[cnt
- skipUniChars
] & eShift
) != 0;
6524 aModKeyState
.mIsControlDown
=
6525 (shiftStates
[cnt
- skipUniChars
] & eCtrl
) != 0;
6526 aModKeyState
.mIsAltDown
=
6527 (shiftStates
[cnt
- skipUniChars
] & eAlt
) != 0;
6529 uniChar
= uniChars
[cnt
- skipUniChars
];
6531 if (skipShiftedChars
<= cnt
)
6532 shiftedChar
= shiftedChars
[cnt
- skipShiftedChars
];
6533 if (skipUnshiftedChars
<= cnt
)
6534 unshiftedChar
= unshiftedChars
[cnt
- skipUnshiftedChars
];
6535 nsAutoTArray
<nsAlternativeCharCode
, 5> altArray
;
6537 if (shiftedChar
|| unshiftedChar
) {
6538 nsAlternativeCharCode
chars(unshiftedChar
, shiftedChar
);
6539 altArray
.AppendElement(chars
);
6541 if (cnt
== num
- 1 && (unshiftedLatinChar
|| shiftedLatinChar
)) {
6542 nsAlternativeCharCode
chars(unshiftedLatinChar
, shiftedLatinChar
);
6543 altArray
.AppendElement(chars
);
6546 DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, &altArray
,
6547 keyCode
, nsnull
, aModKeyState
, extraFlags
);
6550 DispatchKeyEvent(NS_KEY_PRESS
, 0, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
6555 UINT unichar
= ::MapVirtualKey(virtualKeyCode
, MAPVK_VK_TO_CHAR
);
6556 // Check for dead characters or no mapping
6557 if (unichar
& 0x80) {
6560 DispatchKeyEvent(NS_KEY_PRESS
, unichar
, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
6569 LRESULT
nsWindow::OnKeyUp(const MSG
&aMsg
,
6570 nsModifierKeyState
&aModKeyState
,
6571 PRBool
*aEventDispatched
)
6573 UINT virtualKeyCode
= aMsg
.wParam
;
6575 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6576 ("nsWindow::OnKeyUp VK=%d\n", virtualKeyCode
));
6578 if (!nsIMM32Handler::IsComposing(this)) {
6579 virtualKeyCode
= MapFromNativeToDOM(virtualKeyCode
);
6582 if (aEventDispatched
)
6583 *aEventDispatched
= PR_TRUE
;
6584 return DispatchKeyEvent(NS_KEY_UP
, 0, nsnull
, virtualKeyCode
, &aMsg
,
6589 LRESULT
nsWindow::OnChar(const MSG
&aMsg
, nsModifierKeyState
&aModKeyState
,
6590 PRBool
*aEventDispatched
, PRUint32 aFlags
)
6592 return OnCharRaw(aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF, aModKeyState
,
6593 aFlags
, &aMsg
, aEventDispatched
);
6597 LRESULT
nsWindow::OnCharRaw(UINT charCode
, UINT aScanCode
,
6598 nsModifierKeyState
&aModKeyState
, PRUint32 aFlags
,
6599 const MSG
*aMsg
, PRBool
*aEventDispatched
)
6601 // ignore [shift+]alt+space so the OS can handle it
6602 if (aModKeyState
.mIsAltDown
&& !aModKeyState
.mIsControlDown
&&
6603 IS_VK_DOWN(NS_VK_SPACE
)) {
6607 // Ignore Ctrl+Enter (bug 318235)
6608 if (aModKeyState
.mIsControlDown
&& charCode
== 0xA) {
6612 // WM_CHAR with Control and Alt (== AltGr) down really means a normal character
6613 PRBool saveIsAltDown
= aModKeyState
.mIsAltDown
;
6614 PRBool saveIsControlDown
= aModKeyState
.mIsControlDown
;
6615 if (aModKeyState
.mIsAltDown
&& aModKeyState
.mIsControlDown
)
6616 aModKeyState
.mIsAltDown
= aModKeyState
.mIsControlDown
= PR_FALSE
;
6620 if (nsIMM32Handler::IsComposing(this)) {
6624 if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1A) { // Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
6625 // need to account for shift here. bug 16486
6626 if (aModKeyState
.mIsShiftDown
)
6627 uniChar
= charCode
- 1 + 'A';
6629 uniChar
= charCode
- 1 + 'a';
6632 else if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1F) {
6633 // Fix for 50255 - <ctrl><[> and <ctrl><]> are not being processed.
6634 // also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
6635 // for some reason the keypress handler need to have the uniChar code set
6636 // with the addition of a upper case A not the lower case.
6637 uniChar
= charCode
- 1 + 'A';
6639 } else { // 0x20 - SPACE, 0x3D - EQUALS
6640 if (charCode
< 0x20 || (charCode
== 0x3D && aModKeyState
.mIsControlDown
)) {
6648 // Keep the characters unshifted for shortcuts and accesskeys and make sure
6649 // that numbers are always passed as such (among others: bugs 50255 and 351310)
6650 if (uniChar
&& (aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)) {
6651 UINT virtualKeyCode
= ::MapVirtualKeyEx(aScanCode
, MAPVK_VSC_TO_VK
,
6652 gKbdLayout
.GetLayout());
6653 UINT unshiftedCharCode
=
6654 virtualKeyCode
>= '0' && virtualKeyCode
<= '9' ? virtualKeyCode
:
6655 aModKeyState
.mIsShiftDown
? ::MapVirtualKeyEx(virtualKeyCode
,
6657 gKbdLayout
.GetLayout()) : 0;
6658 // ignore diacritics (top bit set) and key mapping errors (char code 0)
6659 if ((INT
)unshiftedCharCode
> 0)
6660 uniChar
= unshiftedCharCode
;
6663 // Fix for bug 285161 (and 295095) which was caused by the initial fix for bug 178110.
6664 // When pressing (alt|ctrl)+char, the char must be lowercase unless shift is
6666 if (!aModKeyState
.mIsShiftDown
&& (saveIsAltDown
|| saveIsControlDown
)) {
6667 uniChar
= towlower(uniChar
);
6670 PRBool result
= DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, nsnull
,
6671 charCode
, aMsg
, aModKeyState
, aFlags
);
6672 if (aEventDispatched
)
6673 *aEventDispatched
= PR_TRUE
;
6674 aModKeyState
.mIsAltDown
= saveIsAltDown
;
6675 aModKeyState
.mIsControlDown
= saveIsControlDown
;
6680 nsWindow::SetupKeyModifiersSequence(nsTArray
<KeyPair
>* aArray
, PRUint32 aModifiers
)
6682 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(sModifierKeyMap
); ++i
) {
6683 const PRUint32
* map
= sModifierKeyMap
[i
];
6684 if (aModifiers
& map
[0]) {
6685 aArray
->AppendElement(KeyPair(map
[1], map
[2]));
6691 nsWindow::ConfigureChildren(const nsTArray
<Configuration
>& aConfigurations
)
6693 // XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos
6694 // here, if that helps in some situations. So far I haven't seen a
6696 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
6697 const Configuration
& configuration
= aConfigurations
[i
];
6698 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
6699 NS_ASSERTION(w
->GetParent() == this,
6700 "Configured widget is not a child");
6702 // MSDN says we should do on WinCE this before moving or resizing the window
6703 // See http://msdn.microsoft.com/en-us/library/aa930600.aspx
6704 // We put the region back just below, anyway.
6705 ::SetWindowRgn(w
->mWnd
, NULL
, TRUE
);
6708 w
->GetBounds(bounds
);
6709 if (bounds
.Size() != configuration
.mBounds
.Size()) {
6710 w
->Resize(configuration
.mBounds
.x
, configuration
.mBounds
.y
,
6711 configuration
.mBounds
.width
, configuration
.mBounds
.height
,
6713 } else if (bounds
.TopLeft() != configuration
.mBounds
.TopLeft()) {
6714 w
->Move(configuration
.mBounds
.x
, configuration
.mBounds
.y
);
6716 nsresult rv
= w
->SetWindowClipRegion(configuration
.mClipRegion
, PR_FALSE
);
6717 NS_ENSURE_SUCCESS(rv
, rv
);
6723 CreateHRGNFromArray(const nsTArray
<nsIntRect
>& aRects
)
6725 PRInt32 size
= sizeof(RGNDATAHEADER
) + sizeof(RECT
)*aRects
.Length();
6726 nsAutoTArray
<PRUint8
,100> buf
;
6727 if (!buf
.SetLength(size
))
6729 RGNDATA
* data
= reinterpret_cast<RGNDATA
*>(buf
.Elements());
6730 RECT
* rects
= reinterpret_cast<RECT
*>(data
->Buffer
);
6731 data
->rdh
.dwSize
= sizeof(data
->rdh
);
6732 data
->rdh
.iType
= RDH_RECTANGLES
;
6733 data
->rdh
.nCount
= aRects
.Length();
6735 for (PRUint32 i
= 0; i
< aRects
.Length(); ++i
) {
6736 const nsIntRect
& r
= aRects
[i
];
6737 bounds
.UnionRect(bounds
, r
);
6738 ::SetRect(&rects
[i
], r
.x
, r
.y
, r
.XMost(), r
.YMost());
6740 ::SetRect(&data
->rdh
.rcBound
, bounds
.x
, bounds
.y
, bounds
.XMost(), bounds
.YMost());
6741 return ::ExtCreateRegion(NULL
, buf
.Length(), data
);
6745 nsWindow::SetWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
,
6746 PRBool aIntersectWithExisting
)
6748 if (!aIntersectWithExisting
) {
6749 if (!StoreWindowClipRegion(aRects
))
6753 HRGN dest
= CreateHRGNFromArray(aRects
);
6755 return NS_ERROR_OUT_OF_MEMORY
;
6757 if (aIntersectWithExisting
) {
6758 HRGN current
= ::CreateRectRgn(0, 0, 0, 0);
6760 if (::GetWindowRgn(mWnd
, current
) != 0 /*ERROR*/) {
6761 ::CombineRgn(dest
, dest
, current
, RGN_AND
);
6763 ::DeleteObject(current
);
6767 if (!::SetWindowRgn(mWnd
, dest
, TRUE
)) {
6768 ::DeleteObject(dest
);
6769 return NS_ERROR_FAILURE
;
6774 // WM_DESTROY event handler
6775 void nsWindow::OnDestroy()
6777 mOnDestroyCalled
= PR_TRUE
;
6779 // Make sure we don't get destroyed in the process of tearing down.
6780 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
6782 // Dispatch the NS_DESTROY event. Must be called before mEventCallback is cleared.
6784 DispatchStandardEvent(NS_DESTROY
);
6786 // Prevent the widget from sending additional events.
6787 mEventCallback
= nsnull
;
6789 // Free our subclass and clear |this| stored in the window props. We will no longer
6790 // receive events from Windows after this point.
6791 SubclassWindow(FALSE
);
6793 // Once mEventCallback is cleared and the subclass is reset, sCurrentWindow can be
6794 // cleared. (It's used in tracking windows for mouse events.)
6795 if (sCurrentWindow
== this)
6796 sCurrentWindow
= nsnull
;
6798 // Disconnects us from our parent, will call our GetParent().
6799 nsBaseWidget::Destroy();
6801 // Release references to children, device context, toolkit, and app shell.
6802 nsBaseWidget::OnDestroy();
6804 // Clear our native parent handle.
6805 // XXX Windows will take care of this in the proper order, and SetParent(nsnull)'s
6806 // remove child on the parent already took place in nsBaseWidget's Destroy call above.
6807 //SetParent(nsnull);
6810 // We have to destroy the native drag target before we null out our window pointer.
6811 EnableDragDrop(PR_FALSE
);
6813 // If we're going away and for some reason we're still the rollup widget, rollup and
6814 // turn off capture.
6815 if ( this == sRollupWidget
) {
6816 if ( sRollupListener
)
6817 sRollupListener
->Rollup(nsnull
, nsnull
);
6818 CaptureRollupEvents(nsnull
, nsnull
, PR_FALSE
, PR_TRUE
);
6821 // If IME is disabled, restore it.
6823 mOldIMC
= ::ImmAssociateContext(mWnd
, mOldIMC
);
6824 NS_ASSERTION(!mOldIMC
, "Another IMC was associated");
6827 // Turn off mouse trails if enabled.
6828 MouseTrailer
* mtrailer
= nsToolkit::gMouseTrailer
;
6830 if (mtrailer
->GetMouseTrailerWindow() == mWnd
)
6831 mtrailer
->DestroyTimer();
6833 if (mtrailer
->GetCaptureWindow() == mWnd
)
6834 mtrailer
->SetCaptureWindow(nsnull
);
6837 // Free GDI window class objects
6839 VERIFY(::DeleteObject(mBrush
));
6843 // Free app icon resources.
6845 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
) 0);
6847 ::DestroyIcon(icon
);
6849 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
) 0);
6851 ::DestroyIcon(icon
);
6853 // Destroy any custom cursor resources.
6855 SetCursor(eCursor_standard
);
6858 // Reset transparency
6859 if (eTransparencyTransparent
== mTransparencyMode
)
6860 SetupTranslucentWindowMemoryBitmap(eTransparencyOpaque
);
6863 #if defined(WINCE_HAVE_SOFTKB)
6864 // Revert the changes made for the software keyboard settings
6865 nsWindowCE::ResetSoftKB(mWnd
);
6869 // Finalize panning feedback to possibly restore window displacement
6870 mGesture
.PanFeedbackFinalize(mWnd
, PR_TRUE
);
6873 // Clear the main HWND.
6878 PRBool
nsWindow::OnMove(PRInt32 aX
, PRInt32 aY
)
6883 nsGUIEvent
event(PR_TRUE
, NS_MOVE
, this);
6885 event
.refPoint
.x
= aX
;
6886 event
.refPoint
.y
= aY
;
6888 return DispatchWindowEvent(&event
);
6891 // Send a resize message to the listener
6892 PRBool
nsWindow::OnResize(nsIntRect
&aWindowRect
)
6894 #ifdef CAIRO_HAS_D2D_SURFACE
6895 if (mD2DWindowSurface
) {
6896 mD2DWindowSurface
= NULL
;
6897 Invalidate(PR_FALSE
);
6900 // call the event callback
6901 if (mEventCallback
) {
6902 nsSizeEvent
event(PR_TRUE
, NS_SIZE
, this);
6904 event
.windowSize
= &aWindowRect
;
6906 if (::GetWindowRect(mWnd
, &r
)) {
6907 event
.mWinWidth
= PRInt32(r
.right
- r
.left
);
6908 event
.mWinHeight
= PRInt32(r
.bottom
- r
.top
);
6910 event
.mWinWidth
= 0;
6911 event
.mWinHeight
= 0;
6915 printf("[%X] OnResize: client:(%d x %d x %d x %d) window:(%d x %d)\n", this,
6916 aWindowRect
.x
, aWindowRect
.y
, aWindowRect
.width
, aWindowRect
.height
,
6917 event
.mWinWidth
, event
.mWinHeight
);
6920 return DispatchWindowEvent(&event
);
6926 #if !defined(WINCE) // implemented in nsWindowCE.cpp
6927 PRBool
nsWindow::OnHotKey(WPARAM wParam
, LPARAM lParam
)
6931 #endif // !defined(WINCE)
6933 void nsWindow::OnSettingsChange(WPARAM wParam
, LPARAM lParam
)
6935 if (mWindowType
== eWindowType_dialog
||
6936 mWindowType
== eWindowType_toplevel
)
6937 nsWindowGfx::OnSettingsChangeGfx(wParam
);
6940 static PRBool
IsOurProcessWindow(HWND aHWND
)
6942 DWORD processId
= 0;
6943 ::GetWindowThreadProcessId(aHWND
, &processId
);
6944 return processId
== ::GetCurrentProcessId();
6947 static HWND
FindOurProcessWindow(HWND aHWND
)
6949 for (HWND wnd
= ::GetParent(aHWND
); wnd
; wnd
= ::GetParent(wnd
)) {
6950 if (IsOurProcessWindow(wnd
)) {
6957 // Scrolling helper function for handling plugins.
6958 // Return value indicates whether the calling function should handle this
6959 // aHandled indicates whether this was handled at all
6960 // aQuitProcessing tells whether or not to continue processing the message
6961 PRBool
nsWindow::HandleScrollingPlugins(UINT aMsg
, WPARAM aWParam
,
6962 LPARAM aLParam
, PRBool
& aHandled
,
6964 PRBool
& aQuitProcessing
)
6966 // The scroll event will be dispatched to the toplevel
6967 // window. We need to give it to the child window
6968 aQuitProcessing
= PR_FALSE
; // default is to not stop processing
6970 DWORD dwPoints
= ::GetMessagePos();
6971 point
.x
= GET_X_LPARAM(dwPoints
);
6972 point
.y
= GET_Y_LPARAM(dwPoints
);
6974 static PRBool sIsProcessing
= PR_FALSE
;
6975 if (sIsProcessing
) {
6976 return PR_TRUE
; // the caller should handle this.
6979 static PRBool sMayBeUsingLogitechMouse
= PR_FALSE
;
6980 if (aMsg
== WM_MOUSEHWHEEL
) {
6981 // Logitech (Logicool) mouse driver (confirmed with 4.82.11 and MX-1100)
6982 // always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs one
6983 // message at first time, this time, ::GetMessagePos works fine.
6984 // Then, we will return 0 (0 means we process it) to the message. Then, the
6985 // driver will POST the same messages continuously during the wheel tilted.
6986 // But ::GetMessagePos API always returns (0, 0), even if the actual mouse
6987 // cursor isn't 0,0. Therefore, we cannot trust the result of
6988 // ::GetMessagePos API if the sender is the driver.
6989 if (!sMayBeUsingLogitechMouse
&& aLParam
== 0 && aLParam
!= dwPoints
&&
6990 ::InSendMessage()) {
6991 sMayBeUsingLogitechMouse
= PR_TRUE
;
6992 } else if (sMayBeUsingLogitechMouse
&& aLParam
!= 0 && ::InSendMessage()) {
6993 // The user has changed the mouse from Logitech's to another one (e.g.,
6994 // the user has changed to the touchpad of the notebook.
6995 sMayBeUsingLogitechMouse
= PR_FALSE
;
6997 // If the WM_MOUSEHWHEEL comes from Logitech's mouse driver, and the
6998 // ::GetMessagePos isn't correct, probably, we should use ::GetCursorPos
7000 if (sMayBeUsingLogitechMouse
&& aLParam
== 0 && dwPoints
== 0) {
7001 ::GetCursorPos(&point
);
7005 HWND destWnd
= ::WindowFromPoint(point
);
7006 // Since we receive scroll events for as long as
7007 // we are focused, it's entirely possible that there
7008 // is another app's window or no window under the
7012 // No window is under the pointer
7013 return PR_FALSE
; // break, but continue processing
7016 nsWindow
* destWindow
;
7018 // We don't handle the message if the found window belongs to another
7019 // process's top window. If it belongs window, that is a plug-in's window.
7020 // Then, we need to send the message to the plug-in window.
7021 if (!IsOurProcessWindow(destWnd
)) {
7022 HWND ourPluginWnd
= FindOurProcessWindow(destWnd
);
7023 if (!ourPluginWnd
) {
7024 // Somebody elses window
7025 return PR_FALSE
; // break, but continue processing
7027 destWindow
= GetNSWindowPtr(ourPluginWnd
);
7029 destWindow
= GetNSWindowPtr(destWnd
);
7032 if (destWindow
== this && mWindowType
== eWindowType_plugin
) {
7033 // If this is plug-in window, the message came from the plug-in window.
7034 // Then, the message should be processed on the parent window.
7035 destWindow
= static_cast<nsWindow
*>(GetParent());
7036 NS_ENSURE_TRUE(destWindow
, PR_FALSE
); // break, but continue processing
7037 destWnd
= destWindow
->mWnd
;
7038 NS_ENSURE_TRUE(destWnd
, PR_FALSE
); // break, but continue processing
7041 if (!destWindow
|| destWindow
->mWindowType
== eWindowType_plugin
) {
7042 // Some other app, or a plugin window.
7043 // Windows directs scrolling messages to the focused window.
7044 // However, Mozilla does not like plugins having focus, so a
7045 // Mozilla window (ie, the plugin's parent (us!) has focus.)
7046 // Therefore, plugins etc _should_ get first grab at the
7047 // message, but this focus vaguary means the plugin misses
7048 // out. If the window is a child of ours, forward it on.
7049 // Determine if a child by walking the parent list until
7050 // we find a parent matching our wndproc.
7051 HWND parentWnd
= ::GetParent(destWnd
);
7053 nsWindow
* parentWindow
= GetNSWindowPtr(parentWnd
);
7055 // We have a child window - quite possibly a plugin window.
7056 // However, not all plugins are created equal - some will handle this
7057 // message themselves, some will forward directly back to us, while
7058 // others will call DefWndProc, which itself still forwards back to us.
7059 // So if we have sent it once, we need to handle it ourself.
7062 // XXX The message shouldn't come from the plugin window at here.
7063 // But the message might come from it due to some bugs. If it happens,
7064 // SendMessage causes deadlock. For safety, we should unlock the
7066 ::ReplyMessage(aMsg
== WM_MOUSEHWHEEL
? TRUE
: 0);
7069 // First time we have seen this message.
7070 // Call the child - either it will consume it, or
7071 // it will wind it's way back to us,triggering the destWnd case above
7072 // either way,when the call returns,we are all done with the message,
7073 sIsProcessing
= PR_TRUE
;
7074 ::SendMessageW(destWnd
, aMsg
, aWParam
, aLParam
);
7075 sIsProcessing
= PR_FALSE
;
7077 aQuitProcessing
= PR_TRUE
;
7078 return PR_FALSE
; // break, and stop processing
7080 parentWnd
= ::GetParent(parentWnd
);
7081 } // while parentWnd
7083 if (destWnd
== nsnull
)
7085 if (destWnd
!= mWnd
) {
7087 sIsProcessing
= PR_TRUE
;
7088 aHandled
= destWindow
->ProcessMessage(aMsg
, aWParam
, aLParam
, aRetValue
);
7089 sIsProcessing
= PR_FALSE
;
7090 aQuitProcessing
= PR_TRUE
;
7091 return PR_FALSE
; // break, and stop processing
7095 printf("WARNING: couldn't get child window for SCROLL event\n");
7098 return PR_TRUE
; // caller should handle this
7101 PRBool
nsWindow::OnScroll(UINT aMsg
, WPARAM aWParam
, LPARAM aLParam
)
7103 static PRInt8 sMouseWheelEmulation
= -1;
7104 if (sMouseWheelEmulation
< 0) {
7105 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
7106 NS_ENSURE_TRUE(prefs
, PR_FALSE
);
7107 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
7108 prefs
->GetBranch(0, getter_AddRefs(prefBranch
));
7109 NS_ENSURE_TRUE(prefBranch
, PR_FALSE
);
7112 prefBranch
->GetBoolPref("mousewheel.emulate_at_wm_scroll", &emulate
);
7113 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
7114 sMouseWheelEmulation
= PRInt8(emulate
);
7117 if (aLParam
|| sMouseWheelEmulation
) {
7118 // Scroll message generated by Thinkpad Trackpoint Driver or similar
7119 // Treat as a mousewheel message and scroll appropriately
7120 PRBool quit
, result
;
7123 if (!HandleScrollingPlugins(aMsg
, aWParam
, aLParam
, result
, &retVal
, quit
))
7124 return quit
; // Return if it's not our message or has been dispatched
7126 nsMouseScrollEvent
scrollevent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
7127 scrollevent
.scrollFlags
= (aMsg
== WM_VSCROLL
)
7128 ? nsMouseScrollEvent::kIsVertical
7129 : nsMouseScrollEvent::kIsHorizontal
;
7130 switch (LOWORD(aWParam
))
7133 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
7135 scrollevent
.delta
= 1;
7138 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
7140 scrollevent
.delta
= -1;
7146 // The event may go to a plug-in which already dispatched this message.
7147 // Then, the event can cause deadlock. We should unlock the sender here.
7150 scrollevent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
7151 scrollevent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
7152 scrollevent
.isMeta
= PR_FALSE
;
7153 scrollevent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
7154 InitEvent(scrollevent
);
7155 if (nsnull
!= mEventCallback
)
7157 DispatchWindowEvent(&scrollevent
);
7162 // Scroll message generated by external application
7163 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_SCROLL
, this);
7165 command
.mScroll
.mIsHorizontal
= (aMsg
== WM_HSCROLL
);
7167 switch (LOWORD(aWParam
))
7169 case SB_LINEUP
: // SB_LINELEFT
7170 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Line
;
7171 command
.mScroll
.mAmount
= -1;
7173 case SB_LINEDOWN
: // SB_LINERIGHT
7174 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Line
;
7175 command
.mScroll
.mAmount
= 1;
7177 case SB_PAGEUP
: // SB_PAGELEFT
7178 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Page
;
7179 command
.mScroll
.mAmount
= -1;
7181 case SB_PAGEDOWN
: // SB_PAGERIGHT
7182 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Page
;
7183 command
.mScroll
.mAmount
= 1;
7185 case SB_TOP
: // SB_LEFT
7186 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Whole
;
7187 command
.mScroll
.mAmount
= -1;
7189 case SB_BOTTOM
: // SB_RIGHT
7190 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Whole
;
7191 command
.mScroll
.mAmount
= 1;
7196 DispatchWindowEvent(&command
);
7200 // Can be overriden. Controls auto-erase of background.
7201 PRBool
nsWindow::AutoErase(HDC dc
)
7206 /**************************************************************
7207 **************************************************************
7209 ** BLOCK: IME management and accessibility
7211 ** Handles managing IME input and accessibility.
7213 **************************************************************
7214 **************************************************************/
7216 NS_IMETHODIMP
nsWindow::ResetInputState()
7218 #ifdef DEBUG_KBSTATE
7219 printf("ResetInputState\n");
7222 #ifdef NS_ENABLE_TSF
7223 nsTextStore::CommitComposition(PR_FALSE
);
7224 #endif //NS_ENABLE_TSF
7226 nsIMEContext
IMEContext(mWnd
);
7227 if (IMEContext
.IsValid()) {
7228 ::ImmNotifyIME(IMEContext
.get(), NI_COMPOSITIONSTR
, CPS_COMPLETE
, NULL
);
7229 ::ImmNotifyIME(IMEContext
.get(), NI_COMPOSITIONSTR
, CPS_CANCEL
, NULL
);
7234 NS_IMETHODIMP
nsWindow::SetIMEOpenState(PRBool aState
)
7236 #ifdef DEBUG_KBSTATE
7237 printf("SetIMEOpenState %s\n", (aState
? "Open" : "Close"));
7240 #ifdef NS_ENABLE_TSF
7241 nsTextStore::SetIMEOpenState(aState
);
7242 #endif //NS_ENABLE_TSF
7244 nsIMEContext
IMEContext(mWnd
);
7245 if (IMEContext
.IsValid()) {
7246 ::ImmSetOpenStatus(IMEContext
.get(), aState
? TRUE
: FALSE
);
7251 NS_IMETHODIMP
nsWindow::GetIMEOpenState(PRBool
* aState
)
7253 nsIMEContext
IMEContext(mWnd
);
7254 if (IMEContext
.IsValid()) {
7255 BOOL isOpen
= ::ImmGetOpenStatus(IMEContext
.get());
7256 *aState
= isOpen
? PR_TRUE
: PR_FALSE
;
7260 #ifdef NS_ENABLE_TSF
7261 *aState
|= nsTextStore::GetIMEOpenState();
7262 #endif //NS_ENABLE_TSF
7267 NS_IMETHODIMP
nsWindow::SetIMEEnabled(PRUint32 aState
)
7269 #ifdef NS_ENABLE_TSF
7270 nsTextStore::SetIMEEnabled(aState
);
7271 #endif //NS_ENABLE_TSF
7272 #ifdef DEBUG_KBSTATE
7273 printf("SetIMEEnabled: %s\n", (aState
== nsIWidget::IME_STATUS_ENABLED
||
7274 aState
== nsIWidget::IME_STATUS_PLUGIN
)?
7275 "Enabled": "Disabled");
7277 if (nsIMM32Handler::IsComposing(this))
7279 mIMEEnabled
= aState
;
7280 PRBool enable
= (aState
== nsIWidget::IME_STATUS_ENABLED
||
7281 aState
== nsIWidget::IME_STATUS_PLUGIN
);
7283 #if defined(WINCE_HAVE_SOFTKB)
7284 sSoftKeyboardState
= (aState
!= nsIWidget::IME_STATUS_DISABLED
);
7285 nsWindowCE::ToggleSoftKB(mWnd
, sSoftKeyboardState
);
7288 if (!enable
!= !mOldIMC
)
7290 mOldIMC
= ::ImmAssociateContext(mWnd
, enable
? mOldIMC
: NULL
);
7291 NS_ASSERTION(!enable
|| !mOldIMC
, "Another IMC was associated");
7296 NS_IMETHODIMP
nsWindow::GetIMEEnabled(PRUint32
* aState
)
7298 #ifdef DEBUG_KBSTATE
7299 printf("GetIMEEnabled: %s\n", mIMEEnabled
? "Enabled": "Disabled");
7301 *aState
= mIMEEnabled
;
7305 NS_IMETHODIMP
nsWindow::CancelIMEComposition()
7307 #ifdef DEBUG_KBSTATE
7308 printf("CancelIMEComposition\n");
7311 #ifdef NS_ENABLE_TSF
7312 nsTextStore::CommitComposition(PR_TRUE
);
7313 #endif //NS_ENABLE_TSF
7315 nsIMEContext
IMEContext(mWnd
);
7316 if (IMEContext
.IsValid()) {
7317 ::ImmNotifyIME(IMEContext
.get(), NI_COMPOSITIONSTR
, CPS_CANCEL
, NULL
);
7323 nsWindow::GetToggledKeyState(PRUint32 aKeyCode
, PRBool
* aLEDState
)
7325 #ifdef DEBUG_KBSTATE
7326 printf("GetToggledKeyState\n");
7328 NS_ENSURE_ARG_POINTER(aLEDState
);
7329 *aLEDState
= (::GetKeyState(aKeyCode
) & 1) != 0;
7333 #ifdef NS_ENABLE_TSF
7335 nsWindow::OnIMEFocusChange(PRBool aFocus
)
7337 nsresult rv
= nsTextStore::OnFocusChange(aFocus
, this, mIMEEnabled
);
7338 if (rv
== NS_ERROR_NOT_AVAILABLE
)
7339 rv
= NS_ERROR_NOT_IMPLEMENTED
; // TSF is not enabled, maybe.
7344 nsWindow::OnIMETextChange(PRUint32 aStart
,
7348 return nsTextStore::OnTextChange(aStart
, aOldEnd
, aNewEnd
);
7352 nsWindow::OnIMESelectionChange(void)
7354 return nsTextStore::OnSelectionChange();
7356 #endif //NS_ENABLE_TSF
7358 #ifdef ACCESSIBILITY
7360 #ifdef DEBUG_WMGETOBJECT
7361 #define NS_LOG_WMGETOBJECT_WNDACC(aWnd) \
7362 nsAccessible* acc = aWnd ? \
7363 aWnd->DispatchAccessibleEvent(NS_GETACCESSIBLE) : nsnull; \
7364 printf(" acc: %p", acc); \
7366 nsAutoString name; \
7367 acc->GetName(name); \
7368 printf(", accname: %s", NS_ConvertUTF16toUTF8(name).get()); \
7369 nsCOMPtr<nsIAccessibleDocument> doc = do_QueryObject(acc); \
7370 void *hwnd = nsnull; \
7371 doc->GetWindowHandle(&hwnd); \
7372 printf(", acc hwnd: %d", hwnd); \
7375 #define NS_LOG_WMGETOBJECT_THISWND \
7377 printf("\n*******Get Doc Accessible*******\nOrig Window: "); \
7378 printf("\n {\n HWND: %d, parent HWND: %d, wndobj: %p, content type: %d,\n",\
7379 mWnd, ::GetParent(mWnd), this, mContentType); \
7380 NS_LOG_WMGETOBJECT_WNDACC(this) \
7384 #define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd) \
7386 nsWindow* wnd = GetNSWindowPtr(aHwnd); \
7387 printf("Get " aMsg ":\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n", \
7388 aHwnd, ::GetParent(aHwnd), wnd); \
7389 NS_LOG_WMGETOBJECT_WNDACC(wnd); \
7393 #define NS_LOG_WMGETOBJECT_THISWND
7394 #define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd)
7395 #endif // DEBUG_WMGETOBJECT
7398 nsWindow::GetRootAccessible()
7400 // We want the ability to forcibly disable a11y on windows, because
7401 // some non-a11y-related components attempt to bring it up. See bug
7402 // 538530 for details; we have a pref here that allows it to be disabled
7403 // for performance and testing resons.
7405 // This pref is checked only once, and the browser needs a restart to
7406 // pick up any changes.
7407 static int accForceDisable
= -1;
7409 if (accForceDisable
== -1) {
7410 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
7411 PRBool b
= PR_FALSE
;
7412 nsresult rv
= prefs
->GetBoolPref("accessibility.win32.force_disabled", &b
);
7413 if (NS_SUCCEEDED(rv
) && b
) {
7414 accForceDisable
= 1;
7416 accForceDisable
= 0;
7420 // If the pref was true, return null here, disabling a11y.
7421 if (accForceDisable
)
7424 nsWindow::sIsAccessibilityOn
= TRUE
;
7426 if (mInDtor
|| mOnDestroyCalled
|| mWindowType
== eWindowType_invisible
) {
7430 NS_LOG_WMGETOBJECT_THISWND
7432 if (mContentType
!= eContentTypeInherit
) {
7433 // We're on a MozillaContentWindowClass or MozillaUIWindowClass window.
7434 // Search for the correct visible child window to get an accessible
7435 // document from. Make sure to use an active child window. If this window
7436 // doesn't have child windows then return an accessible for it.
7437 HWND accessibleWnd
= ::GetTopWindow(mWnd
);
7438 NS_LOG_WMGETOBJECT_WND("Top Window", accessibleWnd
);
7439 if (!accessibleWnd
) {
7440 NS_LOG_WMGETOBJECT_WND("This Window", mWnd
);
7441 return DispatchAccessibleEvent(NS_GETACCESSIBLE
);
7444 nsWindow
* accessibleWindow
= nsnull
;
7445 while (accessibleWnd
) {
7446 // Loop through windows and find the first one with accessibility info
7447 accessibleWindow
= GetNSWindowPtr(accessibleWnd
);
7448 if (accessibleWindow
) {
7449 nsAccessible
*rootAccessible
=
7450 accessibleWindow
->DispatchAccessibleEvent(NS_GETACCESSIBLE
);
7451 if (rootAccessible
) {
7452 // Success, one of the child windows was active.
7453 return rootAccessible
;
7456 accessibleWnd
= ::GetNextWindow(accessibleWnd
, GW_HWNDNEXT
);
7457 NS_LOG_WMGETOBJECT_WND("Next Window", accessibleWnd
);
7462 NS_LOG_WMGETOBJECT_WND("This Window", mWnd
);
7463 return DispatchAccessibleEvent(NS_GETACCESSIBLE
);
7466 STDMETHODIMP_(LRESULT
)
7467 nsWindow::LresultFromObject(REFIID riid
, WPARAM wParam
, LPUNKNOWN pAcc
)
7469 // open the dll dynamically
7471 sAccLib
=::LoadLibraryW(L
"OLEACC.DLL");
7474 if (!sLresultFromObject
)
7475 sLresultFromObject
= (LPFNLRESULTFROMOBJECT
)GetProcAddress(sAccLib
,"LresultFromObject");
7477 if (sLresultFromObject
)
7478 return sLresultFromObject(riid
,wParam
,pAcc
);
7485 /**************************************************************
7486 **************************************************************
7488 ** BLOCK: Transparency
7490 ** Window transparency helpers.
7492 **************************************************************
7493 **************************************************************/
7497 void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth
, PRInt32 aNewHeight
, PRBool force
)
7499 if (!force
&& aNewWidth
== mBounds
.width
&& aNewHeight
== mBounds
.height
)
7502 #ifdef CAIRO_HAS_D2D_SURFACE
7503 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
7504 gfxWindowsPlatform::RENDER_DIRECT2D
) {
7505 nsRefPtr
<gfxD2DSurface
> newSurface
=
7506 new gfxD2DSurface(gfxIntSize(aNewWidth
, aNewHeight
), gfxASurface::ImageFormatARGB32
);
7507 mTransparentSurface
= newSurface
;
7512 nsRefPtr
<gfxWindowsSurface
> newSurface
=
7513 new gfxWindowsSurface(gfxIntSize(aNewWidth
, aNewHeight
), gfxASurface::ImageFormatARGB32
);
7514 mTransparentSurface
= newSurface
;
7515 mMemoryDC
= newSurface
->GetDC();
7519 void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode
)
7523 if (aMode
== mTransparencyMode
)
7526 // stop on dialogs and popups!
7527 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
7528 nsWindow
* parent
= GetNSWindowPtr(hWnd
);
7532 NS_WARNING("Trying to use transparent chrome in an embedded context");
7536 if (parent
!= this) {
7537 NS_WARNING("Setting SetWindowTranslucencyInner on a parent this is not us!");
7540 if (aMode
== eTransparencyTransparent
) {
7541 // If we're switching to the use of a transparent window, hide the chrome
7543 HideWindowChrome(PR_TRUE
);
7544 } else if (mHideChrome
&& mTransparencyMode
== eTransparencyTransparent
) {
7545 // if we're switching out of transparent, re-enable our parent's chrome.
7546 HideWindowChrome(PR_FALSE
);
7549 LONG_PTR style
= ::GetWindowLongPtrW(hWnd
, GWL_STYLE
),
7550 exStyle
= ::GetWindowLongPtr(hWnd
, GWL_EXSTYLE
);
7552 if (parent
->mIsVisible
)
7553 style
|= WS_VISIBLE
;
7554 if (parent
->mSizeMode
== nsSizeMode_Maximized
)
7555 style
|= WS_MAXIMIZE
;
7556 else if (parent
->mSizeMode
== nsSizeMode_Minimized
)
7557 style
|= WS_MINIMIZE
;
7559 if (aMode
== eTransparencyTransparent
)
7560 exStyle
|= WS_EX_LAYERED
;
7562 exStyle
&= ~WS_EX_LAYERED
;
7564 VERIFY_WINDOW_STYLE(style
);
7565 ::SetWindowLongPtrW(hWnd
, GWL_STYLE
, style
);
7566 ::SetWindowLongPtrW(hWnd
, GWL_EXSTYLE
, exStyle
);
7568 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
7569 if (mTransparencyMode
== eTransparencyGlass
)
7570 memset(&mGlassMargins
, 0, sizeof mGlassMargins
);
7571 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
7572 mTransparencyMode
= aMode
;
7574 SetupTranslucentWindowMemoryBitmap(aMode
);
7576 #endif // #ifndef WINCE
7579 void nsWindow::SetupTranslucentWindowMemoryBitmap(nsTransparencyMode aMode
)
7581 if (eTransparencyTransparent
== aMode
) {
7582 ResizeTranslucentWindow(mBounds
.width
, mBounds
.height
, PR_TRUE
);
7584 mTransparentSurface
= nsnull
;
7589 nsresult
nsWindow::UpdateTranslucentWindow()
7592 if (mBounds
.IsEmpty())
7597 BLENDFUNCTION bf
= { AC_SRC_OVER
, 0, 255, AC_SRC_ALPHA
};
7598 SIZE winSize
= { mBounds
.width
, mBounds
.height
};
7599 POINT srcPos
= { 0, 0 };
7600 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
7602 ::GetWindowRect(hWnd
, &winRect
);
7604 #ifdef CAIRO_HAS_D2D_SURFACE
7605 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
7606 gfxWindowsPlatform::RENDER_DIRECT2D
) {
7607 mMemoryDC
= static_cast<gfxD2DSurface
*>(mTransparentSurface
.get())->
7611 // perform the alpha blend
7612 PRBool updateSuccesful
=
7613 ::UpdateLayeredWindow(hWnd
, NULL
, (POINT
*)&winRect
, &winSize
, mMemoryDC
, &srcPos
, 0, &bf
, ULW_ALPHA
);
7615 #ifdef CAIRO_HAS_D2D_SURFACE
7616 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
7617 gfxWindowsPlatform::RENDER_DIRECT2D
) {
7618 nsIntRect
r(0, 0, 0, 0);
7619 static_cast<gfxD2DSurface
*>(mTransparentSurface
.get())->ReleaseDC(&r
);
7623 if (!updateSuccesful
) {
7624 return NS_ERROR_FAILURE
;
7633 /**************************************************************
7634 **************************************************************
7636 ** BLOCK: Popup rollup hooks
7638 ** Deals with CaptureRollup on popup windows.
7640 **************************************************************
7641 **************************************************************/
7644 // Schedules a timer for a window, so we can rollup after processing the hook event
7645 void nsWindow::ScheduleHookTimer(HWND aWnd
, UINT aMsgId
)
7647 // In some cases multiple hooks may be scheduled
7648 // so ignore any other requests once one timer is scheduled
7649 if (sHookTimerId
== 0) {
7650 // Remember the window handle and the message ID to be used later
7651 sRollupMsgId
= aMsgId
;
7652 sRollupMsgWnd
= aWnd
;
7653 // Schedule native timer for doing the rollup after
7654 // this event is done being processed
7655 sHookTimerId
= ::SetTimer(NULL
, 0, 0, (TIMERPROC
)HookTimerForPopups
);
7656 NS_ASSERTION(sHookTimerId
, "Timer couldn't be created.");
7660 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7661 int gLastMsgCode
= 0;
7662 extern MSGFEventMsgInfo gMSGFEvents
[];
7665 // Process Menu messages, rollup when popup is clicked.
7666 LRESULT CALLBACK
nsWindow::MozSpecialMsgFilter(int code
, WPARAM wParam
, LPARAM lParam
)
7668 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7670 MSG
* pMsg
= (MSG
*)lParam
;
7673 while (gMSGFEvents
[inx
].mId
!= code
&& gMSGFEvents
[inx
].mStr
!= NULL
) {
7676 if (code
!= gLastMsgCode
) {
7677 if (gMSGFEvents
[inx
].mId
== code
) {
7679 printf("MozSpecialMessageProc - code: 0x%X - %s hw: %p\n", code
, gMSGFEvents
[inx
].mStr
, pMsg
->hwnd
);
7683 printf("MozSpecialMessageProc - code: 0x%X - %d hw: %p\n", code
, gMSGFEvents
[inx
].mId
, pMsg
->hwnd
);
7686 gLastMsgCode
= code
;
7688 PrintEvent(pMsg
->message
, FALSE
, FALSE
);
7690 #endif // #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7692 if (sProcessHook
&& code
== MSGF_MENU
) {
7693 MSG
* pMsg
= (MSG
*)lParam
;
7694 ScheduleHookTimer( pMsg
->hwnd
, pMsg
->message
);
7697 return ::CallNextHookEx(sMsgFilterHook
, code
, wParam
, lParam
);
7700 // Process all mouse messages. Roll up when a click is in a native window
7701 // that doesn't have an nsIWidget.
7702 LRESULT CALLBACK
nsWindow::MozSpecialMouseProc(int code
, WPARAM wParam
, LPARAM lParam
)
7706 case WM_LBUTTONDOWN
:
7707 case WM_RBUTTONDOWN
:
7708 case WM_MBUTTONDOWN
:
7710 case WM_MOUSEHWHEEL
:
7712 MOUSEHOOKSTRUCT
* ms
= (MOUSEHOOKSTRUCT
*)lParam
;
7713 nsIWidget
* mozWin
= (nsIWidget
*)GetNSWindowPtr(ms
->hwnd
);
7715 // If this window is windowed plugin window, the mouse events are not
7717 if (static_cast<nsWindow
*>(mozWin
)->mWindowType
== eWindowType_plugin
)
7718 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
7720 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
7726 return ::CallNextHookEx(sCallMouseHook
, code
, wParam
, lParam
);
7729 // Process all messages. Roll up when the window is moving, or
7730 // is resizing or when maximized or mininized.
7731 LRESULT CALLBACK
nsWindow::MozSpecialWndProc(int code
, WPARAM wParam
, LPARAM lParam
)
7733 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7735 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
7736 PrintEvent(cwpt
->message
, FALSE
, FALSE
);
7741 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
7742 if (cwpt
->message
== WM_MOVING
||
7743 cwpt
->message
== WM_SIZING
||
7744 cwpt
->message
== WM_GETMINMAXINFO
) {
7745 ScheduleHookTimer(cwpt
->hwnd
, (UINT
)cwpt
->message
);
7749 return ::CallNextHookEx(sCallProcHook
, code
, wParam
, lParam
);
7752 // Register the special "hooks" for dropdown processing.
7753 void nsWindow::RegisterSpecialDropdownHooks()
7755 NS_ASSERTION(!sMsgFilterHook
, "sMsgFilterHook must be NULL!");
7756 NS_ASSERTION(!sCallProcHook
, "sCallProcHook must be NULL!");
7758 DISPLAY_NMM_PRT("***************** Installing Msg Hooks ***************\n");
7760 //HMODULE hMod = GetModuleHandle("gkwidget.dll");
7762 // Install msg hook for moving the window and resizing
7763 if (!sMsgFilterHook
) {
7764 DISPLAY_NMM_PRT("***** Hooking sMsgFilterHook!\n");
7765 sMsgFilterHook
= SetWindowsHookEx(WH_MSGFILTER
, MozSpecialMsgFilter
, NULL
, GetCurrentThreadId());
7766 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7767 if (!sMsgFilterHook
) {
7768 printf("***** SetWindowsHookEx is NOT installed for WH_MSGFILTER!\n");
7773 // Install msg hook for menus
7774 if (!sCallProcHook
) {
7775 DISPLAY_NMM_PRT("***** Hooking sCallProcHook!\n");
7776 sCallProcHook
= SetWindowsHookEx(WH_CALLWNDPROC
, MozSpecialWndProc
, NULL
, GetCurrentThreadId());
7777 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7778 if (!sCallProcHook
) {
7779 printf("***** SetWindowsHookEx is NOT installed for WH_CALLWNDPROC!\n");
7784 // Install msg hook for the mouse
7785 if (!sCallMouseHook
) {
7786 DISPLAY_NMM_PRT("***** Hooking sCallMouseHook!\n");
7787 sCallMouseHook
= SetWindowsHookEx(WH_MOUSE
, MozSpecialMouseProc
, NULL
, GetCurrentThreadId());
7788 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
7789 if (!sCallMouseHook
) {
7790 printf("***** SetWindowsHookEx is NOT installed for WH_MOUSE!\n");
7796 // Unhook special message hooks for dropdowns.
7797 void nsWindow::UnregisterSpecialDropdownHooks()
7799 DISPLAY_NMM_PRT("***************** De-installing Msg Hooks ***************\n");
7801 if (sCallProcHook
) {
7802 DISPLAY_NMM_PRT("***** Unhooking sCallProcHook!\n");
7803 if (!::UnhookWindowsHookEx(sCallProcHook
)) {
7804 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallProcHook!\n");
7806 sCallProcHook
= NULL
;
7809 if (sMsgFilterHook
) {
7810 DISPLAY_NMM_PRT("***** Unhooking sMsgFilterHook!\n");
7811 if (!::UnhookWindowsHookEx(sMsgFilterHook
)) {
7812 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sMsgFilterHook!\n");
7814 sMsgFilterHook
= NULL
;
7817 if (sCallMouseHook
) {
7818 DISPLAY_NMM_PRT("***** Unhooking sCallMouseHook!\n");
7819 if (!::UnhookWindowsHookEx(sCallMouseHook
)) {
7820 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallMouseHook!\n");
7822 sCallMouseHook
= NULL
;
7826 // This timer is designed to only fire one time at most each time a "hook" function
7827 // is used to rollup the dropdown. In some cases, the timer may be scheduled from the
7828 // hook, but that hook event or a subsequent event may roll up the dropdown before
7829 // this timer function is executed.
7831 // For example, if an MFC control takes focus, the combobox will lose focus and rollup
7832 // before this function fires.
7833 VOID CALLBACK
nsWindow::HookTimerForPopups(HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
7835 if (sHookTimerId
!= 0) {
7836 // if the window is NULL then we need to use the ID to kill the timer
7837 BOOL status
= ::KillTimer(NULL
, sHookTimerId
);
7838 NS_ASSERTION(status
, "Hook Timer was not killed.");
7842 if (sRollupMsgId
!= 0) {
7843 // Note: DealWithPopups does the check to make sure that
7844 // sRollupListener and sRollupWidget are not NULL
7845 LRESULT popupHandlingResult
;
7846 nsAutoRollup autoRollup
;
7847 DealWithPopups(sRollupMsgWnd
, sRollupMsgId
, 0, 0, &popupHandlingResult
);
7849 sRollupMsgWnd
= NULL
;
7854 static PRBool
IsDifferentThreadWindow(HWND aWnd
)
7856 return ::GetCurrentThreadId() != ::GetWindowThreadProcessId(aWnd
, NULL
);
7860 nsWindow::EventIsInsideWindow(UINT Msg
, nsWindow
* aWindow
)
7865 if (Msg
== WM_ACTIVATEAPP
)
7866 // don't care about activation/deactivation
7869 if (Msg
== WM_ACTIVATE
)
7870 // but on Windows CE we do care about
7871 // activation/deactivation because there doesn't exist
7872 // cancelable Mouse Activation events
7876 ::GetWindowRect(aWindow
->mWnd
, &r
);
7877 DWORD pos
= ::GetMessagePos();
7879 mp
.x
= GET_X_LPARAM(pos
);
7880 mp
.y
= GET_Y_LPARAM(pos
);
7882 // was the event inside this window?
7883 return (PRBool
) PtInRect(&r
, mp
);
7886 // Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
7888 nsWindow::DealWithPopups(HWND inWnd
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
, LRESULT
* outResult
)
7890 if (sRollupListener
&& sRollupWidget
&& ::IsWindowVisible(inWnd
)) {
7892 if (inMsg
== WM_LBUTTONDOWN
|| inMsg
== WM_RBUTTONDOWN
|| inMsg
== WM_MBUTTONDOWN
||
7893 inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
|| inMsg
== WM_ACTIVATE
||
7894 (inMsg
== WM_KILLFOCUS
&& IsDifferentThreadWindow((HWND
)inWParam
))
7897 inMsg
== WM_NCRBUTTONDOWN
||
7898 inMsg
== WM_MOVING
||
7899 inMsg
== WM_SIZING
||
7900 inMsg
== WM_NCLBUTTONDOWN
||
7901 inMsg
== WM_NCMBUTTONDOWN
||
7902 inMsg
== WM_MOUSEACTIVATE
||
7903 inMsg
== WM_ACTIVATEAPP
||
7904 inMsg
== WM_MENUSELECT
7908 // Rollup if the event is outside the popup.
7909 PRBool rollup
= !nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)sRollupWidget
);
7911 if (rollup
&& (inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
))
7913 sRollupListener
->ShouldRollupOnMouseWheelEvent(&rollup
);
7914 *outResult
= PR_TRUE
;
7917 // If we're dealing with menus, we probably have submenus and we don't
7918 // want to rollup if the click is in a parent menu of the current submenu.
7919 PRUint32 popupsToRollup
= PR_UINT32_MAX
;
7921 if ( sMenuRollup
) {
7922 nsAutoTArray
<nsIWidget
*, 5> widgetChain
;
7923 PRUint32 sameTypeCount
= sMenuRollup
->GetSubmenuWidgetChain(&widgetChain
);
7924 for ( PRUint32 i
= 0; i
< widgetChain
.Length(); ++i
) {
7925 nsIWidget
* widget
= widgetChain
[i
];
7926 if ( nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)widget
) ) {
7927 // don't roll up if the mouse event occurred within a menu of the
7928 // same type. If the mouse event occurred in a menu higher than
7929 // that, roll up, but pass the number of popups to Rollup so
7930 // that only those of the same type close up.
7931 if (i
< sameTypeCount
) {
7935 popupsToRollup
= sameTypeCount
;
7939 } // foreach parent menu widget
7940 } // if rollup listener knows about menus
7944 if (inMsg
== WM_MOUSEACTIVATE
&& popupsToRollup
== PR_UINT32_MAX
) {
7945 // Prevent the click inside the popup from causing a change in window
7946 // activation. Since the popup is shown non-activated, we need to eat
7947 // any requests to activate the window while it is displayed. Windows
7948 // will automatically activate the popup on the mousedown otherwise.
7950 *outResult
= MA_NOACTIVATE
;
7955 UINT uMsg
= HIWORD(inLParam
);
7956 if (uMsg
== WM_MOUSEMOVE
)
7958 // WM_MOUSEACTIVATE cause by moving the mouse - X-mouse (eg. TweakUI)
7959 // must be enabled in Windows.
7960 sRollupListener
->ShouldRollupOnMouseActivate(&rollup
);
7963 *outResult
= MA_NOACTIVATE
;
7969 // if we've still determined that we should still rollup everything, do it.
7973 // sRollupConsumeEvent may be modified by
7974 // nsIRollupListener::Rollup.
7975 PRBool consumeRollupEvent
= sRollupConsumeEvent
;
7976 // only need to deal with the last rollup for left mouse down events.
7977 sRollupListener
->Rollup(popupsToRollup
, inMsg
== WM_LBUTTONDOWN
? &mLastRollup
: nsnull
);
7979 // Tell hook to stop processing messages
7980 sProcessHook
= PR_FALSE
;
7982 sRollupMsgWnd
= NULL
;
7984 // return TRUE tells Windows that the event is consumed,
7985 // false allows the event to be dispatched
7987 // So if we are NOT supposed to be consuming events, let it go through
7988 if (consumeRollupEvent
&& inMsg
!= WM_RBUTTONDOWN
) {
7993 // if we are only rolling up some popups, don't activate and don't let
7994 // the event go through. This prevents clicks menus higher in the
7995 // chain from opening when a context menu is open
7996 if (popupsToRollup
!= PR_UINT32_MAX
&& inMsg
== WM_MOUSEACTIVATE
) {
7997 *outResult
= MA_NOACTIVATEANDEAT
;
8002 } // if event that might trigger a popup to rollup
8003 } // if rollup listeners registered
8008 /**************************************************************
8009 **************************************************************
8011 ** BLOCK: Misc. utility methods and functions.
8015 **************************************************************
8016 **************************************************************/
8018 // nsModifierKeyState used in various character processing.
8019 nsModifierKeyState::nsModifierKeyState()
8021 mIsShiftDown
= IS_VK_DOWN(NS_VK_SHIFT
);
8022 mIsControlDown
= IS_VK_DOWN(NS_VK_CONTROL
);
8023 mIsAltDown
= IS_VK_DOWN(NS_VK_ALT
);
8027 PRInt32
nsWindow::GetWindowsVersion()
8032 static PRInt32 version
= 0;
8033 static PRBool didCheck
= PR_FALSE
;
8038 OSVERSIONINFOEX osInfo
;
8039 osInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
8040 // This cast is safe and supposed to be here, don't worry
8041 ::GetVersionEx((OSVERSIONINFO
*)&osInfo
);
8042 version
= (osInfo
.dwMajorVersion
& 0xff) << 8 | (osInfo
.dwMinorVersion
& 0xff);
8048 // Note that the result of GetTopLevelWindow method can be different from the
8049 // result of GetTopLevelHWND method. The result can be non-floating window.
8050 // Because our top level window may be contained in another window which is
8051 // not managed by us.
8052 nsWindow
* nsWindow::GetTopLevelWindow(PRBool aStopOnDialogOrPopup
)
8054 nsWindow
* curWindow
= this;
8057 if (aStopOnDialogOrPopup
) {
8058 switch (curWindow
->mWindowType
) {
8059 case eWindowType_dialog
:
8060 case eWindowType_popup
:
8065 // Retrieve the top level parent or owner window
8066 nsWindow
* parentWindow
= curWindow
->GetParentWindow(PR_TRUE
);
8071 curWindow
= parentWindow
;
8075 // Note that the result of GetTopLevelHWND can be different from the result
8076 // of GetTopLevelWindow method. Because this is checking whether the window
8077 // is top level only in Win32 window system. Therefore, the result window
8078 // may not be managed by us.
8079 HWND
nsWindow::GetTopLevelHWND(HWND aWnd
, PRBool aStopOnDialogOrPopup
)
8088 if (aStopOnDialogOrPopup
) {
8089 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
8091 VERIFY_WINDOW_STYLE(style
);
8093 if (!(style
& WS_CHILD
)) // first top-level window
8097 upWnd
= ::GetParent(curWnd
); // Parent or owner (if has no parent)
8100 // For dialog windows, we want just the parent, not the owner.
8101 // For other/popup windows, we want to find the first owner/parent
8102 // that's a dialog and/or has an owner.
8103 if (upWnd
&& ::GetWindow(curWnd
, GW_OWNER
) == upWnd
) {
8104 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
8105 if ((style
& WS_DLGFRAME
) != 0)
8116 static BOOL CALLBACK
gEnumWindowsProc(HWND hwnd
, LPARAM lParam
)
8119 ::GetWindowThreadProcessId(hwnd
, &pid
);
8120 if (pid
== GetCurrentProcessId() && ::IsWindowVisible(hwnd
))
8122 gWindowsVisible
= PR_TRUE
;
8128 PRBool
nsWindow::CanTakeFocus()
8130 gWindowsVisible
= PR_FALSE
;
8131 EnumWindows(gEnumWindowsProc
, 0);
8132 if (!gWindowsVisible
) {
8135 HWND fgWnd
= ::GetForegroundWindow();
8140 GetWindowThreadProcessId(fgWnd
, &pid
);
8141 if (pid
== GetCurrentProcessId()) {
8149 void nsWindow::InitTrackPointHack()
8151 // Init Trackpoint Hack
8155 const WCHAR wstrKeys
[][40] = {L
"Software\\Lenovo\\TrackPoint",
8156 L
"Software\\Lenovo\\UltraNav",
8157 L
"Software\\Alps\\Apoint\\TrackPoint",
8158 L
"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
8159 L
"Software\\Synaptics\\SynTPEnh\\UltraNavPS2"};
8160 // If anything fails turn the hack off
8161 sTrackPointHack
= false;
8162 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
8163 if(NS_SUCCEEDED(rv
) && prefs
) {
8164 prefs
->GetIntPref("ui.trackpoint_hack.enabled", &lHackValue
);
8165 switch (lHackValue
) {
8166 // 0 means hack disabled
8169 // 1 means hack enabled
8171 sTrackPointHack
= true;
8173 // -1 means autodetect
8175 for(int i
= 0; i
< NS_ARRAY_LENGTH(wstrKeys
); i
++) {
8177 lResult
= ::RegOpenKeyExW(HKEY_CURRENT_USER
, (LPCWSTR
)&wstrKeys
[i
],
8178 0, KEY_READ
, &hKey
);
8179 ::RegCloseKey(hKey
);
8180 if(lResult
== ERROR_SUCCESS
) {
8181 // If we detected a registry key belonging to a TrackPoint driver
8183 sTrackPointHack
= true;
8188 // Shouldn't be any other values, but treat them as disabled
8195 #endif // #if !defined(WINCE)
8197 LPARAM
nsWindow::lParamToScreen(LPARAM lParam
)
8200 pt
.x
= GET_X_LPARAM(lParam
);
8201 pt
.y
= GET_Y_LPARAM(lParam
);
8202 ::ClientToScreen(mWnd
, &pt
);
8203 return MAKELPARAM(pt
.x
, pt
.y
);
8206 LPARAM
nsWindow::lParamToClient(LPARAM lParam
)
8209 pt
.x
= GET_X_LPARAM(lParam
);
8210 pt
.y
= GET_Y_LPARAM(lParam
);
8211 ::ScreenToClient(mWnd
, &pt
);
8212 return MAKELPARAM(pt
.x
, pt
.y
);
8215 /**************************************************************
8216 **************************************************************
8218 ** BLOCK: ChildWindow impl.
8220 ** Child window overrides.
8222 **************************************************************
8223 **************************************************************/
8225 // return the style for a child nsWindow
8226 DWORD
ChildWindow::WindowStyle()
8228 DWORD style
= WS_CLIPCHILDREN
| nsWindow::WindowStyle();
8229 if (!(style
& WS_POPUP
))
8230 style
|= WS_CHILD
; // WS_POPUP and WS_CHILD are mutually exclusive.
8231 VERIFY_WINDOW_STYLE(style
);