1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sts=2 sw=2 et cin: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Dean Tessman <dean_tessman@hotmail.com>
25 * Ere Maijala <emaijala@kolumbus.fi>
26 * Mark Hammond <markh@activestate.com>
27 * Michael Lowe <michael.lowe@bigfoot.com>
28 * Peter Bajusz <hyp-x@inf.bme.hu>
29 * Pierre Phaneuf <pp@ludusdesign.com>
30 * Robert O'Callahan <roc+moz@cs.cmu.edu>
31 * Roy Yokoyama <yokoyama@netscape.com>
32 * Makoto Kato <m_kato@ga2.so-net.ne.jp>
33 * Masayuki Nakano <masayuki@d-toybox.com>
34 * Dainis Jonitis <Dainis_Jonitis@swh-t.lv>
35 * Christian Biesinger <cbiesinger@web.de>
36 * Mats Palmgren <matspal@gmail.com>
37 * Ningjie Chen <chenn@email.uc.edu>
38 * Jim Mathies <jmathies@mozilla.com>
39 * Kyle Huey <me@kylehuey.com>
41 * Alternatively, the contents of this file may be used under the terms of
42 * either the GNU General Public License Version 2 or later (the "GPL"), or
43 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
44 * in which case the provisions of the GPL or the LGPL are applicable instead
45 * of those above. If you wish to allow use of your version of this file only
46 * under the terms of either the GPL or the LGPL, and not to allow others to
47 * use your version of this file under the terms of the MPL, indicate your
48 * decision by deleting the provisions above and replace them with the notice
49 * and other provisions required by the GPL or the LGPL. If you do not delete
50 * the provisions above, a recipient may use your version of this file under
51 * the terms of any one of the MPL, the GPL or the LGPL.
53 * ***** END LICENSE BLOCK ***** */
56 * nsWindow - Native window management and event handling.
58 * nsWindow is organized into a set of major blocks and
59 * block subsections. The layout is as follows:
64 * nsIWidget methods and utilities
65 * nsSwitchToUIThread impl.
66 * nsSwitchToUIThread methods and utilities
68 * Event initialization
73 * OnEvent event handlers
74 * IME management and accessibility
80 * Search for "BLOCK:" to find major blocks.
81 * Search for "SECTION:" to find specific sections.
83 * Blocks should be split out into separate files if they
84 * become unmanageable.
88 * nsWindowDefs.h - Definitions, macros, structs, enums
90 * nsWindowDbg.h/.cpp - Debug related code and directives.
91 * nsWindowGfx.h/.cpp - Graphics and painting.
92 * nsWindowCE.h/.cpp - WINCE specific code that can be
93 * split out from nsWindow.
97 /**************************************************************
98 **************************************************************
104 **************************************************************
105 **************************************************************/
108 #include "mozilla/ipc/RPCChannel.h"
111 #include "nsWindow.h"
115 #include <commctrl.h>
123 #include "nsIAppShell.h"
124 #include "nsISupportsPrimitives.h"
125 #include "nsIDOMNSUIEvent.h"
126 #include "nsITheme.h"
127 #include "nsIPrefBranch.h"
128 #include "nsIPrefBranch2.h"
129 #include "nsIPrefService.h"
130 #include "nsIObserverService.h"
131 #include "nsIScreenManager.h"
132 #include "imgIContainer.h"
134 #include "nsIRollupListener.h"
135 #include "nsIMenuRollup.h"
136 #include "nsIRegion.h"
137 #include "nsIServiceManager.h"
138 #include "nsIClipboard.h"
139 #include "nsIMM32Handler.h"
140 #include "nsILocalFile.h"
141 #include "nsIFontMetrics.h"
142 #include "nsIFontEnumerator.h"
143 #include "nsIDeviceContext.h"
144 #include "nsILookAndFeel.h"
145 #include "nsGUIEvent.h"
148 #include "nsThreadUtils.h"
149 #include "nsNativeCharsetUtils.h"
150 #include "nsWidgetAtoms.h"
151 #include "nsUnicharUtils.h"
153 #include "nsAppDirectoryServiceDefs.h"
154 #include "nsXPIDLString.h"
155 #include "nsWidgetsCID.h"
156 #include "nsTHashtable.h"
157 #include "nsHashKeys.h"
158 #include "nsString.h"
159 #include "mozilla/Services.h"
160 #include "nsNativeThemeWin.h"
161 #include "nsWindowsDllInterceptor.h"
162 #include "nsIWindowMediator.h"
163 #include "nsIServiceManager.h"
166 #include "nsWindowCE.h"
169 #if defined(WINCE_WINDOWS_MOBILE)
170 #define KILL_PRIORITY_ID 2444
173 #include "nsWindowGfx.h"
174 #include "gfxWindowsPlatform.h"
177 #ifdef MOZ_ENABLE_D3D9_LAYER
178 #include "LayerManagerD3D9.h"
180 #ifdef MOZ_ENABLE_D3D10_LAYER
181 #include "LayerManagerD3D10.h"
183 #include "LayerManagerOGL.h"
184 #include "nsIGfxInfo.h"
186 #include "BasicLayers.h"
189 #include "nsUXThemeConstants.h"
190 #include "KeyboardLayout.h"
191 #include "nsNativeDragTarget.h"
192 #include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
195 #include <richedit.h>
196 #endif // !defined(WINCE)
198 #if defined(ACCESSIBILITY)
201 #include "nsIAccessibleDocument.h"
202 #if !defined(WINABLEAPI)
204 #endif // !defined(WINABLEAPI)
205 #endif // defined(ACCESSIBILITY)
207 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
208 #include "nsIWinTaskbar.h"
211 #if defined(NS_ENABLE_TSF)
212 #include "nsTextStore.h"
213 #endif // defined(NS_ENABLE_TSF)
215 #if defined(MOZ_SPLASHSCREEN)
216 #include "nsSplashScreen.h"
217 #endif // defined(MOZ_SPLASHSCREEN)
219 // Windowless plugin support
222 #include "nsWindowDefs.h"
224 #include "mozilla/FunctionTimer.h"
226 #ifdef WINCE_WINDOWS_MOBILE
227 #include "nsGfxCIID.h"
230 #include "mozilla/FunctionTimer.h"
232 #ifdef MOZ_CRASHREPORTER
233 #include "nsICrashReporter.h"
236 #include "nsIXULRuntime.h"
238 using namespace mozilla::widget
;
239 using namespace mozilla::layers
;
241 /**************************************************************
242 **************************************************************
246 ** nsWindow Class static initializations and global variables.
248 **************************************************************
249 **************************************************************/
251 /**************************************************************
253 * SECTION: nsWindow statics
255 **************************************************************/
257 PRUint32
nsWindow::sInstanceCount
= 0;
258 PRBool
nsWindow::sSwitchKeyboardLayout
= PR_FALSE
;
259 BOOL
nsWindow::sIsOleInitialized
= FALSE
;
260 HCURSOR
nsWindow::sHCursor
= NULL
;
261 imgIContainer
* nsWindow::sCursorImgContainer
= nsnull
;
262 nsWindow
* nsWindow::sCurrentWindow
= nsnull
;
263 PRBool
nsWindow::sJustGotDeactivate
= PR_FALSE
;
264 PRBool
nsWindow::sJustGotActivate
= PR_FALSE
;
265 PRBool
nsWindow::sIsInMouseCapture
= PR_FALSE
;
267 // imported in nsWidgetFactory.cpp
268 TriStateBool
nsWindow::sCanQuit
= TRI_UNKNOWN
;
270 // Hook Data Memebers for Dropdowns. sProcessHook Tells the
271 // hook methods whether they should be processing the hook
273 HHOOK
nsWindow::sMsgFilterHook
= NULL
;
274 HHOOK
nsWindow::sCallProcHook
= NULL
;
275 HHOOK
nsWindow::sCallMouseHook
= NULL
;
276 PRPackedBool
nsWindow::sProcessHook
= PR_FALSE
;
277 UINT
nsWindow::sRollupMsgId
= 0;
278 HWND
nsWindow::sRollupMsgWnd
= NULL
;
279 UINT
nsWindow::sHookTimerId
= 0;
282 nsIRollupListener
* nsWindow::sRollupListener
= nsnull
;
283 nsIMenuRollup
* nsWindow::sMenuRollup
= nsnull
;
284 nsIWidget
* nsWindow::sRollupWidget
= nsnull
;
285 PRBool
nsWindow::sRollupConsumeEvent
= PR_FALSE
;
287 // Mouse Clicks - static variable definitions for figuring
289 POINT
nsWindow::sLastMousePoint
= {0};
290 POINT
nsWindow::sLastMouseMovePoint
= {0};
291 LONG
nsWindow::sLastMouseDownTime
= 0L;
292 LONG
nsWindow::sLastClickCount
= 0L;
293 BYTE
nsWindow::sLastMouseButton
= 0;
295 // Trim heap on minimize. (initialized, but still true.)
296 int nsWindow::sTrimOnMinimize
= 2;
298 // Default value for Trackpoint hack (used when the pref is set to -1).
299 PRBool
nsWindow::sDefaultTrackPointHack
= PR_FALSE
;
300 // Default value for general window class (used when the pref is the empty string).
301 const char* nsWindow::sDefaultMainWindowClass
= kClassNameGeneral
;
303 // If we're using D3D9, this will not be allowed during initial 5 seconds.
304 bool nsWindow::sAllowD3D9
= false;
307 BOOL
nsWindow::sIsAccessibilityOn
= FALSE
;
308 // Accessibility wm_getobject handler
309 HINSTANCE
nsWindow::sAccLib
= 0;
310 LPFNLRESULTFROMOBJECT
311 nsWindow::sLresultFromObject
= 0;
312 #endif // ACCESSIBILITY
315 // Used in OOPP plugin focus processing.
316 const PRUnichar
* kOOPPPluginFocusEventId
= L
"OOPP Plugin Focus Widget Event";
317 PRUint32
nsWindow::sOOPPPluginFocusEvent
=
318 RegisterWindowMessageW(kOOPPPluginFocusEventId
);
321 MSG
nsWindow::sRedirectedKeyDown
;
323 /**************************************************************
325 * SECTION: globals variables
327 **************************************************************/
329 static const char *sScreenManagerContractID
= "@mozilla.org/gfx/screenmanager;1";
332 PRLogModuleInfo
* gWindowsLog
= nsnull
;
336 // Kbd layout. Used throughout character processing.
337 static KeyboardLayout gKbdLayout
;
340 #ifdef WINCE_WINDOWS_MOBILE
341 // HTC Navigation Wheel Event
342 // This is the defined value for Gesture Mode
343 const int WM_HTCNAV
= 0x0400 + 200;
345 typedef int (__stdcall
* HTCApiNavOpen
)(HANDLE
, int);
346 typedef int (__stdcall
* HTCApiNavSetMode
)(HANDLE
, unsigned int);
348 HTCApiNavOpen gHTCApiNavOpen
= nsnull
;
349 HTCApiNavSetMode gHTCApiNavSetMode
= nsnull
;
350 static PRBool gCheckForHTCApi
= PR_FALSE
;
353 // Global user preference for disabling native theme. Used
354 // in NativeWindowTheme.
355 PRBool gDisableNativeTheme
= PR_FALSE
;
357 // Global used in Show window enumerations.
358 static PRBool gWindowsVisible
= PR_FALSE
;
360 static NS_DEFINE_CID(kCClipboardCID
, NS_CLIPBOARD_CID
);
361 #ifdef WINCE_WINDOWS_MOBILE
362 static NS_DEFINE_CID(kRegionCID
, NS_REGION_CID
);
365 // General purpose user32.dll hook object
366 static WindowsDllInterceptor sUser32Intercept
;
368 // A glass window's opaque rectangle must be at least this height
369 // before we use glass margins. Shorter opaque rectangles lead to
370 // stupid-looking visual effects because Windows (foolishly) makes the
371 // window edge rendering dependent on the opaque rect height.
372 static const int MIN_OPAQUE_RECT_HEIGHT_FOR_GLASS_MARGINS
= 50;
374 // Maximum number of pixels for the left and right horizontal glass margins.
375 // If the margins are bigger than this, we won't use margins at all because
376 // Windows' glaze effect will start to look stupid.
377 static const int MAX_HORIZONTAL_GLASS_MARGIN
= 5;
379 // 2 pixel offset for eTransparencyBorderlessGlass which equals
380 // the size of the default window border Windows paints.
381 static const PRInt32 kGlassMarginAdjustment
= 2;
383 /**************************************************************
384 **************************************************************
386 ** BLOCK: nsIWidget impl.
388 ** nsIWidget interface implementation, broken down into
391 **************************************************************
392 **************************************************************/
394 /**************************************************************
396 * SECTION: nsWindow construction and destruction
398 **************************************************************/
400 nsWindow::nsWindow() : nsBaseWidget()
404 gWindowsLog
= PR_NewLogModule("nsWindowsWidgets");
409 mPrevWndProc
= nsnull
;
411 mNativeDragTarget
= nsnull
;
413 mIsVisible
= PR_FALSE
;
414 mIsTopWidgetWindow
= PR_FALSE
;
415 mUnicodeWidget
= PR_TRUE
;
416 mDisplayPanFeedback
= PR_FALSE
;
417 mTouchWindow
= PR_FALSE
;
418 mCustomNonClient
= PR_FALSE
;
419 mHideChrome
= PR_FALSE
;
420 mFullscreenMode
= PR_FALSE
;
421 mMousePresent
= PR_FALSE
;
422 mWindowType
= eWindowType_child
;
423 mBorderStyle
= eBorderStyle_default
;
424 mPopupType
= ePopupTypeAny
;
425 mOldSizeMode
= nsSizeMode_Normal
;
429 mLastSize
.height
= 0;
433 mLastKeyboardLayout
= 0;
434 mBlurSuppressLevel
= 0;
435 mIMEContext
.mStatus
= nsIWidget::IME_STATUS_ENABLED
;
437 mTransparentSurface
= nsnull
;
439 mTransparencyMode
= eTransparencyOpaque
;
440 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
441 memset(&mGlassMargins
, 0, sizeof mGlassMargins
);
442 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
444 mBackground
= ::GetSysColor(COLOR_BTNFACE
);
445 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
446 mForeground
= ::GetSysColor(COLOR_WINDOWTEXT
);
448 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
449 mTaskbarPreview
= nsnull
;
450 mHasTaskbarIconBeenCreated
= PR_FALSE
;
453 // Global initialization
454 if (!sInstanceCount
) {
456 gKbdLayout
.LoadLayout(::GetKeyboardLayout(0));
460 nsIMM32Handler::Initialize();
463 nsTextStore::Initialize();
467 if (SUCCEEDED(::OleInitialize(NULL
)))
468 sIsOleInitialized
= TRUE
;
469 NS_ASSERTION(sIsOleInitialized
, "***** OLE is not initialized!\n");
473 InitInputHackDefaults();
476 // Init titlebar button info for custom frames.
477 nsUXThemeData::InitTitlebarInfo();
479 nsUXThemeData::UpdateNativeThemeInfo();
481 ForgetRedirectedKeyDownMessage();
484 mIdleService
= nsnull
;
489 nsWindow::~nsWindow()
493 // If the widget was released without calling Destroy() then the native window still
494 // exists, and we need to destroy it. This will also result in a call to OnDestroy.
496 // XXX How could this happen???
503 if (sInstanceCount
== 0) {
505 nsTextStore::Terminate();
509 NS_IF_RELEASE(sCursorImgContainer
);
510 if (sIsOleInitialized
) {
511 ::OleFlushClipboard();
513 sIsOleInitialized
= FALSE
;
515 // delete any of the IME structures that we allocated
516 nsIMM32Handler::Terminate();
517 #endif // !defined(WINCE)
521 NS_IF_RELEASE(mNativeDragTarget
);
522 #endif // !defined(WINCE)
525 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow
, nsBaseWidget
)
527 /**************************************************************
529 * SECTION: nsIWidget::Create, nsIWidget::Destroy
531 * Creating and destroying windows for this widget.
533 **************************************************************/
535 // Allow Derived classes to modify the height that is passed
536 // when the window is created or resized. Also add extra height
537 // if needed (on Windows CE)
538 PRInt32
nsWindow::GetHeight(PRInt32 aProposedHeight
)
542 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
543 DWORD style
= WindowStyle();
544 if ((style
& WS_SYSMENU
) && (style
& WS_POPUP
)) {
545 extra
= GetSystemMetrics(SM_CYCAPTION
);
549 return aProposedHeight
+ extra
;
552 // Create the proper widget
554 nsWindow::Create(nsIWidget
*aParent
,
555 nsNativeWidget aNativeParent
,
556 const nsIntRect
&aRect
,
557 EVENT_CALLBACK aHandleEventFunction
,
558 nsIDeviceContext
*aContext
,
559 nsIAppShell
*aAppShell
,
560 nsIToolkit
*aToolkit
,
561 nsWidgetInitData
*aInitData
)
563 nsWidgetInitData defaultInitData
;
565 aInitData
= &defaultInitData
;
567 mUnicodeWidget
= aInitData
->mUnicode
;
569 nsIWidget
*baseParent
= aInitData
->mWindowType
== eWindowType_dialog
||
570 aInitData
->mWindowType
== eWindowType_toplevel
||
571 aInitData
->mWindowType
== eWindowType_invisible
?
574 mIsTopWidgetWindow
= (nsnull
== baseParent
);
577 BaseCreate(baseParent
, aRect
, aHandleEventFunction
, aContext
,
578 aAppShell
, aToolkit
, aInitData
);
581 if (aParent
) { // has a nsIWidget parent
582 parent
= aParent
? (HWND
)aParent
->GetNativeData(NS_NATIVE_WINDOW
) : NULL
;
584 } else { // has a nsNative parent
585 parent
= (HWND
)aNativeParent
;
586 mParent
= aNativeParent
? GetNSWindowPtr((HWND
)aNativeParent
) : nsnull
;
589 mPopupType
= aInitData
->mPopupHint
;
590 mIsRTL
= aInitData
->mRTL
;
592 DWORD style
= WindowStyle();
593 DWORD extendedStyle
= WindowExStyle();
595 if (mWindowType
== eWindowType_popup
) {
598 } else if (mWindowType
== eWindowType_invisible
) {
599 // Make sure CreateWindowEx succeeds at creating a toplevel window
600 style
&= ~0x40000000; // WS_CHILDWINDOW
602 // See if the caller wants to explictly set clip children and clip siblings
603 if (aInitData
->clipChildren
) {
604 style
|= WS_CLIPCHILDREN
;
606 style
&= ~WS_CLIPCHILDREN
;
608 if (aInitData
->clipSiblings
) {
609 style
|= WS_CLIPSIBLINGS
;
613 nsAutoString className
;
614 if (aInitData
->mDropShadow
) {
615 GetWindowPopupClass(className
);
617 GetWindowClass(className
);
619 mWnd
= ::CreateWindowExW(extendedStyle
,
626 GetHeight(aRect
.height
),
629 nsToolkit::mDllInstance
,
633 NS_WARNING("nsWindow CreateWindowEx failed.");
634 return NS_ERROR_FAILURE
;
637 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
638 if (mIsRTL
&& nsUXThemeData::dwmSetWindowAttributePtr
) {
639 DWORD dwAttribute
= TRUE
;
640 nsUXThemeData::dwmSetWindowAttributePtr(mWnd
, DWMWA_NONCLIENT_RTL_LAYOUT
, &dwAttribute
, sizeof dwAttribute
);
644 if (mWindowType
!= eWindowType_plugin
&&
645 mWindowType
!= eWindowType_invisible
&&
646 UseTrackPointHack()) {
647 // Ugly Thinkpad Driver Hack (Bugs 507222 and 594977)
649 // We create two zero-sized windows as descendants of the top-level window,
652 // Top-level window (MozillaWindowClass)
653 // FAKETRACKPOINTSCROLLCONTAINER (MozillaWindowClass)
654 // FAKETRACKPOINTSCROLLABLE (MozillaWindowClass)
656 // We need to have the middle window, otherwise the Trackpoint driver
657 // will fail to deliver scroll messages. WM_MOUSEWHEEL messages are
658 // sent to the FAKETRACKPOINTSCROLLABLE, which then propagate up the
659 // window hierarchy until they are handled by nsWindow::WindowProc.
660 // WM_HSCROLL messages are also sent to the FAKETRACKPOINTSCROLLABLE,
661 // but these do not propagate automatically, so we have the window
662 // procedure pretend that they were dispatched to the top-level window
665 // The FAKETRACKPOINTSCROLLABLE needs to have the specific window styles it
666 // is given below so that it catches the Trackpoint driver's heuristics.
667 HWND scrollContainerWnd
= ::CreateWindowW
668 (className
.get(), L
"FAKETRACKPOINTSCROLLCONTAINER",
669 WS_CHILD
| WS_VISIBLE
,
670 0, 0, 0, 0, mWnd
, NULL
, nsToolkit::mDllInstance
, NULL
);
671 HWND scrollableWnd
= ::CreateWindowW
672 (className
.get(), L
"FAKETRACKPOINTSCROLLABLE",
673 WS_CHILD
| WS_VISIBLE
| WS_VSCROLL
| WS_TABSTOP
| 0x30,
674 0, 0, 0, 0, scrollContainerWnd
, NULL
, nsToolkit::mDllInstance
, NULL
);
676 // Give the FAKETRACKPOINTSCROLLABLE window a specific ID so that
677 // WindowProcInternal can distinguish it from the top-level window
679 ::SetWindowLongPtrW(scrollableWnd
, GWLP_ID
, eFakeTrackPointScrollableID
);
681 // Make FAKETRACKPOINTSCROLLABLE use nsWindow::WindowProc, and store the
682 // old window procedure in its "user data".
685 oldWndProc
= (WNDPROC
)::SetWindowLongPtrW(scrollableWnd
, GWLP_WNDPROC
,
686 (LONG_PTR
)nsWindow::WindowProc
);
688 oldWndProc
= (WNDPROC
)::SetWindowLongPtrA(scrollableWnd
, GWLP_WNDPROC
,
689 (LONG_PTR
)nsWindow::WindowProc
);
690 ::SetWindowLongPtrW(scrollableWnd
, GWLP_USERDATA
, (LONG_PTR
)oldWndProc
);
693 // call the event callback to notify about creation
695 DispatchStandardEvent(NS_CREATE
);
696 SubclassWindow(TRUE
);
698 if (sTrimOnMinimize
== 2 && mWindowType
== eWindowType_invisible
) {
699 /* The internal variable set by the config.trim_on_minimize pref
700 has not yet been initialized, and this is the hidden window
701 (conveniently created before any visible windows, and after
702 the profile has been initialized).
704 Default config.trim_on_minimize to false, to fix bug 76831
705 for good. If anyone complains about this new default, saying
706 that a Mozilla app hogs too much memory while minimized, they
707 will have that entire bug tattooed on their backside. */
710 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
712 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
713 prefs
->GetBranch(0, getter_AddRefs(prefBranch
));
717 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("config.trim_on_minimize",
722 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("intl.keyboard.per_window_layout",
724 sSwitchKeyboardLayout
= temp
;
726 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("mozilla.widget.disable-native-theme",
728 gDisableNativeTheme
= temp
;
732 #if defined(WINCE_HAVE_SOFTKB)
733 if (mWindowType
== eWindowType_dialog
|| mWindowType
== eWindowType_toplevel
)
734 nsWindowCE::CreateSoftKeyMenuBar(mWnd
);
740 // Close this nsWindow
741 NS_METHOD
nsWindow::Destroy()
743 // WM_DESTROY has already fired, we're done.
747 // During the destruction of all of our children, make sure we don't get deleted.
748 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
751 * On windows the LayerManagerOGL destructor wants the widget to be around for
752 * cleanup. It also would like to have the HWND intact, so we NULL it here.
755 mLayerManager
->Destroy();
757 mLayerManager
= nsnull
;
759 /* We should clear our cached resources now and not wait for the GC to
760 * delete the nsWindow. */
761 ClearCachedResources();
763 // The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
764 // and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
765 // from it. The function also destroys the window's menu, flushes the thread message queue,
766 // destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if
767 // the window is at the top of the viewer chain).
769 // If the specified window is a parent or owner window, DestroyWindow automatically destroys
770 // the associated child or owned windows when it destroys the parent or owner window. The
771 // function first destroys child or owned windows, and then it destroys the parent or owner
773 VERIFY(::DestroyWindow(mWnd
));
775 // Our windows can be subclassed which may prevent us receiving WM_DESTROY. If OnDestroy()
776 // didn't get called, call it now.
777 if (PR_FALSE
== mOnDestroyCalled
) {
779 mWindowHook
.Notify(mWnd
, WM_DESTROY
, 0, 0, &result
);
786 /**************************************************************
788 * SECTION: Window class utilities
790 * Utilities for calculating the proper window class name for
793 **************************************************************/
795 void nsWindow::RegisterWindowClass(const nsString
& aClassName
, UINT aExtraStyle
,
799 if (::GetClassInfoW(nsToolkit::mDllInstance
, aClassName
.get(), &wc
)) {
800 // already registered
804 wc
.style
= CS_DBLCLKS
| aExtraStyle
;
805 wc
.lpfnWndProc
= ::DefWindowProcW
;
808 wc
.hInstance
= nsToolkit::mDllInstance
;
809 wc
.hIcon
= aIconID
? ::LoadIconW(::GetModuleHandleW(NULL
), aIconID
) : NULL
;
811 wc
.hbrBackground
= mBrush
;
812 wc
.lpszMenuName
= NULL
;
813 wc
.lpszClassName
= aClassName
.get();
815 if (!::RegisterClassW(&wc
)) {
816 // For older versions of Win32 (i.e., not XP), the registration may
817 // fail with aExtraStyle, so we have to re-register without it.
818 wc
.style
= CS_DBLCLKS
;
819 ::RegisterClassW(&wc
);
823 static LPWSTR
const gStockApplicationIcon
= MAKEINTRESOURCEW(32512);
825 // Return the proper window class for everything except popups.
826 void nsWindow::GetWindowClass(nsString
& aWindowClass
)
828 switch (mWindowType
) {
829 case eWindowType_invisible
:
830 aWindowClass
.AssignLiteral(kClassNameHidden
);
831 RegisterWindowClass(aWindowClass
, 0, gStockApplicationIcon
);
833 case eWindowType_dialog
:
834 aWindowClass
.AssignLiteral(kClassNameDialog
);
835 RegisterWindowClass(aWindowClass
, 0, 0);
838 GetMainWindowClass(aWindowClass
);
839 RegisterWindowClass(aWindowClass
, 0, gStockApplicationIcon
);
844 // Return the proper popup window class
845 void nsWindow::GetWindowPopupClass(nsString
& aWindowClass
)
847 aWindowClass
.AssignLiteral(kClassNameDropShadow
);
848 RegisterWindowClass(aWindowClass
, CS_XP_DROPSHADOW
, gStockApplicationIcon
);
851 /**************************************************************
853 * SECTION: Window styles utilities
855 * Return the proper windows styles and extended styles.
857 **************************************************************/
859 // Return nsWindow styles
860 #if !defined(WINCE) // implemented in nsWindowCE.cpp
861 DWORD
nsWindow::WindowStyle()
865 switch (mWindowType
) {
866 case eWindowType_plugin
:
867 case eWindowType_child
:
868 style
= WS_OVERLAPPED
;
871 case eWindowType_dialog
:
872 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
| DS_3DLOOK
|
873 DS_MODALFRAME
| WS_CLIPCHILDREN
;
874 if (mBorderStyle
!= eBorderStyle_default
)
875 style
|= WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
878 case eWindowType_popup
:
881 style
|= WS_OVERLAPPED
;
886 NS_ERROR("unknown border style");
889 case eWindowType_toplevel
:
890 case eWindowType_invisible
:
891 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
|
892 WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPCHILDREN
;
896 if (mBorderStyle
!= eBorderStyle_default
&& mBorderStyle
!= eBorderStyle_all
) {
897 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_border
))
900 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_title
)) {
901 style
&= ~WS_DLGFRAME
;
906 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_close
))
908 // XXX The close box can only be removed by changing the window class,
909 // as far as I know --- roc+moz@cs.cmu.edu
911 if (mBorderStyle
== eBorderStyle_none
||
912 !(mBorderStyle
& (eBorderStyle_menu
| eBorderStyle_close
)))
913 style
&= ~WS_SYSMENU
;
914 // Looks like getting rid of the system menu also does away with the
915 // close box. So, we only get rid of the system menu if you want neither it
916 // nor the close box. How does the Windows "Dialog" window class get just
917 // closebox and no sysmenu? Who knows.
919 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_resizeh
))
920 style
&= ~WS_THICKFRAME
;
922 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_minimize
))
923 style
&= ~WS_MINIMIZEBOX
;
925 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_maximize
))
926 style
&= ~WS_MAXIMIZEBOX
;
928 if (IsPopupWithTitleBar()) {
930 if (mBorderStyle
& eBorderStyle_close
) {
936 VERIFY_WINDOW_STYLE(style
);
939 #endif // !defined(WINCE)
941 // Return nsWindow extended styles
942 DWORD
nsWindow::WindowExStyle()
946 case eWindowType_plugin
:
947 case eWindowType_child
:
950 case eWindowType_dialog
:
951 return WS_EX_WINDOWEDGE
| WS_EX_DLGMODALFRAME
;
953 case eWindowType_popup
:
955 DWORD extendedStyle
=
956 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
960 if (mPopupLevel
== ePopupLevelTop
)
961 extendedStyle
|= WS_EX_TOPMOST
;
962 return extendedStyle
;
965 NS_ERROR("unknown border style");
968 case eWindowType_toplevel
:
969 case eWindowType_invisible
:
970 return WS_EX_WINDOWEDGE
;
974 /**************************************************************
976 * SECTION: Window subclassing utilities
978 * Set or clear window subclasses on native windows. Used in
979 * Create and Destroy.
981 **************************************************************/
983 // Subclass (or remove the subclass from) this component's nsWindow
984 void nsWindow::SubclassWindow(BOOL bState
)
987 //NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
988 if (!::IsWindow(mWnd
)) {
989 NS_ERROR("Invalid window handle");
993 // change the nsWindow proc
995 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
,
996 (LONG_PTR
)nsWindow::WindowProc
);
998 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
,
999 (LONG_PTR
)nsWindow::WindowProc
);
1000 NS_ASSERTION(mPrevWndProc
, "Null standard window procedure");
1001 // connect the this pointer to the nsWindow handle
1002 SetNSWindowPtr(mWnd
, this);
1006 ::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
1008 ::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
1009 SetNSWindowPtr(mWnd
, NULL
);
1010 mPrevWndProc
= NULL
;
1015 /**************************************************************
1017 * SECTION: Window properties
1019 * Set and clear native window properties.
1021 **************************************************************/
1023 static PRUnichar sPropName
[40] = L
"";
1024 static PRUnichar
* GetNSWindowPropName()
1028 _snwprintf(sPropName
, 39, L
"MozillansIWidgetPtr%p", GetCurrentProcessId());
1029 sPropName
[39] = '\0';
1034 nsWindow
* nsWindow::GetNSWindowPtr(HWND aWnd
)
1036 return (nsWindow
*) ::GetPropW(aWnd
, GetNSWindowPropName());
1039 BOOL
nsWindow::SetNSWindowPtr(HWND aWnd
, nsWindow
* ptr
)
1042 ::RemovePropW(aWnd
, GetNSWindowPropName());
1045 return ::SetPropW(aWnd
, GetNSWindowPropName(), (HANDLE
)ptr
);
1049 /**************************************************************
1051 * SECTION: nsIWidget::SetParent, nsIWidget::GetParent
1053 * Set or clear the parent widgets using window properties, and
1054 * handles calculating native parent handles.
1056 **************************************************************/
1058 // Get and set parent widgets
1059 NS_IMETHODIMP
nsWindow::SetParent(nsIWidget
*aNewParent
)
1061 mParent
= aNewParent
;
1063 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
1064 nsIWidget
* parent
= GetParent();
1066 parent
->RemoveChild(this);
1069 ReparentNativeWidget(aNewParent
);
1070 aNewParent
->AddChild(this);
1074 // If we have no parent, SetParent should return the desktop.
1075 VERIFY(::SetParent(mWnd
, nsnull
));
1081 nsWindow::ReparentNativeWidget(nsIWidget
* aNewParent
)
1083 NS_PRECONDITION(aNewParent
, "");
1085 mParent
= aNewParent
;
1086 if (mWindowType
== eWindowType_popup
) {
1089 HWND newParent
= (HWND
)aNewParent
->GetNativeData(NS_NATIVE_WINDOW
);
1090 NS_ASSERTION(newParent
, "Parent widget has a null native window handle");
1091 if (newParent
&& mWnd
) {
1092 ::SetParent(mWnd
, newParent
);
1097 nsIWidget
* nsWindow::GetParent(void)
1099 return GetParentWindow(PR_FALSE
);
1102 float nsWindow::GetDPI()
1104 HDC dc
= ::GetDC(mWnd
);
1108 double heightInches
= ::GetDeviceCaps(dc
, VERTSIZE
)/MM_PER_INCH_FLOAT
;
1109 int heightPx
= ::GetDeviceCaps(dc
, VERTRES
);
1110 ::ReleaseDC(mWnd
, dc
);
1111 if (heightInches
< 0.25) {
1112 // Something's broken
1115 return float(heightPx
/heightInches
);
1118 nsWindow
* nsWindow::GetParentWindow(PRBool aIncludeOwner
)
1120 if (mIsTopWidgetWindow
) {
1121 // Must use a flag instead of mWindowType to tell if the window is the
1122 // owned by the topmost widget, because a child window can be embedded inside
1123 // a HWND which is not associated with a nsIWidget.
1127 // If this widget has already been destroyed, pretend we have no parent.
1128 // This corresponds to code in Destroy which removes the destroyed
1129 // widget from its parent's child list.
1130 if (mInDtor
|| mOnDestroyCalled
)
1134 // aIncludeOwner set to true implies walking the parent chain to retrieve the
1135 // root owner. aIncludeOwner set to false implies the search will stop at the
1136 // true parent (default).
1137 nsWindow
* widget
= nsnull
;
1140 HWND parent
= ::GetParent(mWnd
);
1142 HWND parent
= nsnull
;
1144 parent
= ::GetParent(mWnd
);
1146 parent
= ::GetAncestor(mWnd
, GA_PARENT
);
1149 widget
= GetNSWindowPtr(parent
);
1151 // If the widget is in the process of being destroyed then
1153 if (widget
->mInDtor
) {
1164 nsWindow::EnumAllChildWindProc(HWND aWnd
, LPARAM aParam
)
1166 nsWindow
*wnd
= nsWindow::GetNSWindowPtr(aWnd
);
1168 ((nsWindow::WindowEnumCallback
*)aParam
)(wnd
);
1174 nsWindow::EnumAllThreadWindowProc(HWND aWnd
, LPARAM aParam
)
1176 nsWindow
*wnd
= nsWindow::GetNSWindowPtr(aWnd
);
1178 ((nsWindow::WindowEnumCallback
*)aParam
)(wnd
);
1180 EnumChildWindows(aWnd
, EnumAllChildWindProc
, aParam
);
1185 nsWindow::EnumAllWindows(WindowEnumCallback aCallback
)
1187 EnumThreadWindows(GetCurrentThreadId(),
1188 EnumAllThreadWindowProc
,
1192 /**************************************************************
1194 * SECTION: nsIWidget::Show
1196 * Hide or show this component.
1198 **************************************************************/
1200 NS_METHOD
nsWindow::Show(PRBool bState
)
1202 #if defined(MOZ_SPLASHSCREEN)
1203 // we're about to show the first toplevel window,
1204 // so kill off any splash screen if we had one
1205 nsSplashScreen
*splash
= nsSplashScreen::Get();
1206 if (splash
&& splash
->IsOpen() && mWnd
&& bState
&&
1207 (mWindowType
== eWindowType_toplevel
||
1208 mWindowType
== eWindowType_dialog
||
1209 mWindowType
== eWindowType_popup
))
1215 #ifdef NS_FUNCTION_TIMER
1216 static bool firstShow
= true;
1218 (mWindowType
== eWindowType_toplevel
||
1219 mWindowType
== eWindowType_dialog
||
1220 mWindowType
== eWindowType_popup
))
1223 mozilla::FunctionTimer::LogMessage("@ First toplevel/dialog/popup showing");
1227 PRBool syncInvalidate
= PR_FALSE
;
1229 PRBool wasVisible
= mIsVisible
;
1230 // Set the status now so that anyone asking during ShowWindow or
1231 // SetWindowPos would get the correct answer.
1232 mIsVisible
= bState
;
1234 if (!mIsVisible
&& wasVisible
) {
1235 ClearCachedResources();
1240 if (!wasVisible
&& mWindowType
== eWindowType_toplevel
) {
1241 // speed up the initial paint after show for
1242 // top level windows:
1243 syncInvalidate
= PR_TRUE
;
1244 switch (mSizeMode
) {
1246 case nsSizeMode_Fullscreen
:
1247 ::SetForegroundWindow(mWnd
);
1248 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1249 MakeFullScreen(TRUE
);
1252 case nsSizeMode_Maximized
:
1253 ::SetForegroundWindow(mWnd
);
1254 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1256 // use default for nsSizeMode_Minimized on Windows CE
1258 case nsSizeMode_Maximized
:
1259 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1261 case nsSizeMode_Minimized
:
1262 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
1266 if (CanTakeFocus()) {
1268 ::SetForegroundWindow(mWnd
);
1270 ::ShowWindow(mWnd
, SW_SHOWNORMAL
);
1272 // Place the window behind the foreground window
1273 // (as long as it is not topmost)
1274 HWND wndAfter
= ::GetForegroundWindow();
1276 wndAfter
= HWND_BOTTOM
;
1277 else if (GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
)
1278 wndAfter
= HWND_TOP
;
1279 ::SetWindowPos(mWnd
, wndAfter
, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOSIZE
|
1280 SWP_NOMOVE
| SWP_NOACTIVATE
);
1286 DWORD flags
= SWP_NOSIZE
| SWP_NOMOVE
| SWP_SHOWWINDOW
;
1288 flags
|= SWP_NOZORDER
;
1290 if (mWindowType
== eWindowType_popup
) {
1292 // ensure popups are the topmost of the TOPMOST
1293 // layer. Remember not to set the SWP_NOZORDER
1294 // flag as that might allow the taskbar to overlap
1295 // the popup. However on windows ce, we need to
1296 // activate the popup or clicks will not be sent.
1297 flags
|= SWP_NOACTIVATE
;
1299 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
1300 ::SetWindowPos(mWnd
, owner
? 0 : HWND_TOPMOST
, 0, 0, 0, 0, flags
);
1303 if (mWindowType
== eWindowType_dialog
&& !CanTakeFocus())
1304 flags
|= SWP_NOACTIVATE
;
1306 ::SetWindowPos(mWnd
, HWND_TOP
, 0, 0, 0, 0, flags
);
1311 if (!wasVisible
&& (mWindowType
== eWindowType_toplevel
|| mWindowType
== eWindowType_dialog
)) {
1312 // when a toplevel window or dialog is shown, initialize the UI state
1313 ::SendMessageW(mWnd
, WM_CHANGEUISTATE
, MAKEWPARAM(UIS_INITIALIZE
, UISF_HIDEFOCUS
| UISF_HIDEACCEL
), 0);
1317 if (mWindowType
!= eWindowType_dialog
) {
1318 ::ShowWindow(mWnd
, SW_HIDE
);
1320 ::SetWindowPos(mWnd
, 0, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1321 SWP_NOZORDER
| SWP_NOACTIVATE
);
1327 if (!wasVisible
&& bState
)
1328 Invalidate(syncInvalidate
);
1334 /**************************************************************
1336 * SECTION: nsIWidget::IsVisible
1338 * Returns the visibility state.
1340 **************************************************************/
1342 // Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
1343 NS_METHOD
nsWindow::IsVisible(PRBool
& bState
)
1345 bState
= mIsVisible
;
1349 /**************************************************************
1351 * SECTION: Window clipping utilities
1353 * Used in Size and Move operations for setting the proper
1354 * window clipping regions for window transparency.
1356 **************************************************************/
1358 // XP and Vista visual styles sometimes require window clipping regions to be applied for proper
1359 // transparency. These routines are called on size and move operations.
1360 void nsWindow::ClearThemeRegion()
1363 if (nsUXThemeData::sIsVistaOrLater
&& !HasGlass() &&
1364 (mWindowType
== eWindowType_popup
&& !IsPopupWithTitleBar() &&
1365 (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
))) {
1366 SetWindowRgn(mWnd
, NULL
, false);
1371 void nsWindow::SetThemeRegion()
1374 // Popup types that have a visual styles region applied (bug 376408). This can be expanded
1375 // for other window types as needed. The regions are applied generically to the base window
1376 // so default constants are used for part and state. At some point we might need part and
1377 // state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
1378 // change shape based on state haven't come up.
1379 if (nsUXThemeData::sIsVistaOrLater
&& !HasGlass() &&
1380 (mWindowType
== eWindowType_popup
&& !IsPopupWithTitleBar() &&
1381 (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
))) {
1383 RECT rect
= {0,0,mBounds
.width
,mBounds
.height
};
1385 HDC dc
= ::GetDC(mWnd
);
1386 nsUXThemeData::getThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip
), dc
, TTP_STANDARD
, TS_NORMAL
, &rect
, &hRgn
);
1388 if (!SetWindowRgn(mWnd
, hRgn
, false)) // do not delete or alter hRgn if accepted.
1391 ::ReleaseDC(mWnd
, dc
);
1396 /**************************************************************
1398 * SECTION: nsIWidget::RegisterTouchWindow,
1399 * nsIWidget::UnregisterTouchWindow, and helper functions
1401 * Used to register the native window to receive touch events
1403 **************************************************************/
1405 NS_METHOD
nsWindow::RegisterTouchWindow() {
1406 mTouchWindow
= PR_TRUE
;
1408 mGesture
.RegisterTouchWindow(mWnd
);
1409 ::EnumChildWindows(mWnd
, nsWindow::RegisterTouchForDescendants
, 0);
1414 NS_METHOD
nsWindow::UnregisterTouchWindow() {
1415 mTouchWindow
= PR_FALSE
;
1417 mGesture
.UnregisterTouchWindow(mWnd
);
1418 ::EnumChildWindows(mWnd
, nsWindow::UnregisterTouchForDescendants
, 0);
1424 BOOL CALLBACK
nsWindow::RegisterTouchForDescendants(HWND aWnd
, LPARAM aMsg
) {
1425 nsWindow
* win
= GetNSWindowPtr(aWnd
);
1427 win
->mGesture
.RegisterTouchWindow(aWnd
);
1431 BOOL CALLBACK
nsWindow::UnregisterTouchForDescendants(HWND aWnd
, LPARAM aMsg
) {
1432 nsWindow
* win
= GetNSWindowPtr(aWnd
);
1434 win
->mGesture
.UnregisterTouchWindow(aWnd
);
1439 /**************************************************************
1441 * SECTION: nsIWidget::Move, nsIWidget::Resize,
1442 * nsIWidget::Size, nsIWidget::BeginResizeDrag
1444 * Repositioning and sizing a window.
1446 **************************************************************/
1448 // Move this component
1449 NS_METHOD
nsWindow::Move(PRInt32 aX
, PRInt32 aY
)
1451 if (mWindowType
== eWindowType_toplevel
||
1452 mWindowType
== eWindowType_dialog
) {
1453 SetSizeMode(nsSizeMode_Normal
);
1455 // Check to see if window needs to be moved first
1456 // to avoid a costly call to SetWindowPos. This check
1457 // can not be moved to the calling code in nsView, because
1458 // some platforms do not position child windows correctly
1460 // Only perform this check for non-popup windows, since the positioning can
1461 // in fact change even when the x/y do not. We always need to perform the
1462 // check. See bug #97805 for details.
1463 if (mWindowType
!= eWindowType_popup
&& (mBounds
.x
== aX
) && (mBounds
.y
== aY
))
1465 // Nothing to do, since it is already positioned correctly.
1474 // complain if a window is moved offscreen (legal, but potentially worrisome)
1475 if (mIsTopWidgetWindow
) { // only a problem for top-level windows
1476 // Make sure this window is actually on the screen before we move it
1477 // XXX: Needs multiple monitor support
1478 HDC dc
= ::GetDC(mWnd
);
1480 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1482 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &workArea
, 0);
1483 // no annoying assertions. just mention the issue.
1484 if (aX
< 0 || aX
>= workArea
.right
|| aY
< 0 || aY
>= workArea
.bottom
)
1485 printf("window moved to offscreen position\n");
1487 ::ReleaseDC(mWnd
, dc
);
1493 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOSIZE
;
1494 // Workaround SetWindowPos bug with D3D9. If our window has a clip
1495 // region, some drivers or OSes may incorrectly copy into the clipped-out
1497 if (mWindowType
== eWindowType_plugin
&&
1498 (!mLayerManager
|| mLayerManager
->GetBackendType() == LayerManager::LAYERS_D3D9
) &&
1500 (mClipRectCount
!= 1 || mClipRects
[0] != nsIntRect(0, 0, mBounds
.width
, mBounds
.height
))) {
1501 flags
|= SWP_NOCOPYBITS
;
1503 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, 0, 0, flags
));
1510 // Resize this component
1511 NS_METHOD
nsWindow::Resize(PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1513 NS_ASSERTION((aWidth
>=0 ) , "Negative width passed to nsWindow::Resize");
1514 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1516 // Avoid unnecessary resizing calls
1517 if (mBounds
.width
== aWidth
&& mBounds
.height
== aHeight
&& !aRepaint
)
1521 if (eTransparencyTransparent
== mTransparencyMode
)
1522 ResizeTranslucentWindow(aWidth
, aHeight
);
1525 // Set cached value for lightweight and printing
1526 mBounds
.width
= aWidth
;
1527 mBounds
.height
= aHeight
;
1530 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOMOVE
;
1534 flags
|= SWP_NOREDRAW
;
1539 VERIFY(::SetWindowPos(mWnd
, NULL
, 0, 0, aWidth
, GetHeight(aHeight
), flags
));
1544 Invalidate(PR_FALSE
);
1549 // Resize this component
1550 NS_METHOD
nsWindow::Resize(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1552 NS_ASSERTION((aWidth
>=0 ), "Negative width passed to nsWindow::Resize");
1553 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1555 // Avoid unnecessary resizing calls
1556 if (mBounds
.x
== aX
&& mBounds
.y
== aY
&&
1557 mBounds
.width
== aWidth
&& mBounds
.height
== aHeight
&& !aRepaint
)
1561 if (eTransparencyTransparent
== mTransparencyMode
)
1562 ResizeTranslucentWindow(aWidth
, aHeight
);
1565 // Set cached value for lightweight and printing
1568 mBounds
.width
= aWidth
;
1569 mBounds
.height
= aHeight
;
1572 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1575 flags
|= SWP_NOREDRAW
;
1580 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, aWidth
, GetHeight(aHeight
), flags
));
1585 Invalidate(PR_FALSE
);
1590 // Resize the client area and position the widget within it's parent
1591 NS_METHOD
nsWindow::ResizeClient(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1593 NS_ASSERTION((aWidth
>=0) , "Negative width passed to ResizeClient");
1594 NS_ASSERTION((aHeight
>=0), "Negative height passed to ResizeClient");
1596 // Adjust our existing window bounds, based on the new client dims.
1598 GetClientRect(mWnd
, &client
);
1599 nsIntPoint
dims(client
.right
- client
.left
, client
.bottom
- client
.top
);
1600 aWidth
= mBounds
.width
+ (aWidth
- dims
.x
);
1601 aHeight
= mBounds
.height
+ (aHeight
- dims
.y
);
1606 GetScreenBounds(bounds
);
1609 return Resize(aX
, aY
, aWidth
, aHeight
, aRepaint
);
1611 return Resize(aWidth
, aHeight
, aRepaint
);
1616 nsWindow::BeginResizeDrag(nsGUIEvent
* aEvent
, PRInt32 aHorizontal
, PRInt32 aVertical
)
1618 NS_ENSURE_ARG_POINTER(aEvent
);
1620 if (aEvent
->eventStructType
!= NS_MOUSE_EVENT
) {
1621 // you can only begin a resize drag with a mouse event
1622 return NS_ERROR_INVALID_ARG
;
1625 nsMouseEvent
* mouseEvent
= static_cast<nsMouseEvent
*>(aEvent
);
1626 if (mouseEvent
->button
!= nsMouseEvent::eLeftButton
) {
1627 // you can only begin a resize drag with the left mouse button
1628 return NS_ERROR_INVALID_ARG
;
1631 // work out what sizemode we're talking about
1633 if (aVertical
< 0) {
1634 if (aHorizontal
< 0) {
1635 syscommand
= SC_SIZE
| WMSZ_TOPLEFT
;
1636 } else if (aHorizontal
== 0) {
1637 syscommand
= SC_SIZE
| WMSZ_TOP
;
1639 syscommand
= SC_SIZE
| WMSZ_TOPRIGHT
;
1641 } else if (aVertical
== 0) {
1642 if (aHorizontal
< 0) {
1643 syscommand
= SC_SIZE
| WMSZ_LEFT
;
1644 } else if (aHorizontal
== 0) {
1645 return NS_ERROR_INVALID_ARG
;
1647 syscommand
= SC_SIZE
| WMSZ_RIGHT
;
1650 if (aHorizontal
< 0) {
1651 syscommand
= SC_SIZE
| WMSZ_BOTTOMLEFT
;
1652 } else if (aHorizontal
== 0) {
1653 syscommand
= SC_SIZE
| WMSZ_BOTTOM
;
1655 syscommand
= SC_SIZE
| WMSZ_BOTTOMRIGHT
;
1659 // resizing doesn't work if the mouse is already captured
1660 CaptureMouse(PR_FALSE
);
1662 // find the top-level window
1663 HWND toplevelWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
1665 // tell Windows to start the resize
1666 ::PostMessage(toplevelWnd
, WM_SYSCOMMAND
, syscommand
,
1667 POINTTOPOINTS(aEvent
->refPoint
));
1672 /**************************************************************
1674 * SECTION: Window Z-order and state.
1676 * nsIWidget::PlaceBehind, nsIWidget::SetSizeMode,
1677 * nsIWidget::ConstrainPosition
1679 * Z-order, positioning, restore, minimize, and maximize.
1681 **************************************************************/
1683 // Position the window behind the given window
1684 NS_METHOD
nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
1685 nsIWidget
*aWidget
, PRBool aActivate
)
1687 HWND behind
= HWND_TOP
;
1688 if (aPlacement
== eZPlacementBottom
)
1689 behind
= HWND_BOTTOM
;
1690 else if (aPlacement
== eZPlacementBelow
&& aWidget
)
1691 behind
= (HWND
)aWidget
->GetNativeData(NS_NATIVE_WINDOW
);
1692 UINT flags
= SWP_NOMOVE
| SWP_NOREPOSITION
| SWP_NOSIZE
;
1694 flags
|= SWP_NOACTIVATE
;
1696 if (!CanTakeFocus() && behind
== HWND_TOP
)
1698 // Can't place the window to top so place it behind the foreground window
1699 // (as long as it is not topmost)
1700 HWND wndAfter
= ::GetForegroundWindow();
1702 behind
= HWND_BOTTOM
;
1703 else if (!(GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
))
1705 flags
|= SWP_NOACTIVATE
;
1708 ::SetWindowPos(mWnd
, behind
, 0, 0, 0, 0, flags
);
1712 // Maximize, minimize or restore the window.
1713 #if !defined(WINCE) // implemented in nsWindowCE.cpp
1714 NS_IMETHODIMP
nsWindow::SetSizeMode(PRInt32 aMode
) {
1718 // Let's not try and do anything if we're already in that state.
1719 // (This is needed to prevent problems when calling window.minimize(), which
1720 // calls us directly, and then the OS triggers another call to us.)
1721 if (aMode
== mSizeMode
)
1724 // save the requested state
1725 rv
= nsBaseWidget::SetSizeMode(aMode
);
1726 if (NS_SUCCEEDED(rv
) && mIsVisible
) {
1730 case nsSizeMode_Fullscreen
:
1734 case nsSizeMode_Maximized
:
1738 case nsSizeMode_Minimized
:
1739 // Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
1740 // keeps the window active in the tray. So after the window is minimized,
1741 // windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
1742 // we will do some additional processing to get the active window set right.
1743 // If sTrimOnMinimize is set, we let windows handle minimization normally
1744 // using SW_MINIMIZE.
1745 mode
= sTrimOnMinimize
? SW_MINIMIZE
: SW_SHOWMINIMIZED
;
1751 ::ShowWindow(mWnd
, mode
);
1752 // we dispatch an activate event here to ensure that the right child window
1754 if (mode
== SW_RESTORE
|| mode
== SW_MAXIMIZE
)
1755 DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
1759 #endif // !defined(WINCE)
1761 // Constrain a potential move to fit onscreen
1762 NS_METHOD
nsWindow::ConstrainPosition(PRBool aAllowSlop
,
1763 PRInt32
*aX
, PRInt32
*aY
)
1765 if (!mIsTopWidgetWindow
) // only a problem for top-level windows
1768 PRBool doConstrain
= PR_FALSE
; // whether we have enough info to do anything
1770 /* get our playing field. use the current screen, or failing that
1771 for any reason, use device caps for the default screen. */
1774 nsCOMPtr
<nsIScreenManager
> screenmgr
= do_GetService(sScreenManagerContractID
);
1776 nsCOMPtr
<nsIScreen
> screen
;
1777 PRInt32 left
, top
, width
, height
;
1779 // zero size rects confuse the screen manager
1780 width
= mBounds
.width
> 0 ? mBounds
.width
: 1;
1781 height
= mBounds
.height
> 0 ? mBounds
.height
: 1;
1782 screenmgr
->ScreenForRect(*aX
, *aY
, width
, height
,
1783 getter_AddRefs(screen
));
1785 if (mSizeMode
!= nsSizeMode_Fullscreen
) {
1786 // For normalized windows, use the desktop work area.
1787 screen
->GetAvailRect(&left
, &top
, &width
, &height
);
1789 // For full screen windows, use the desktop.
1790 screen
->GetRect(&left
, &top
, &width
, &height
);
1792 screenRect
.left
= left
;
1793 screenRect
.right
= left
+width
;
1794 screenRect
.top
= top
;
1795 screenRect
.bottom
= top
+height
;
1796 doConstrain
= PR_TRUE
;
1800 HDC dc
= ::GetDC(mWnd
);
1802 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1803 if (mSizeMode
!= nsSizeMode_Fullscreen
) {
1804 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &screenRect
, 0);
1806 screenRect
.left
= screenRect
.top
= 0;
1807 screenRect
.right
= GetSystemMetrics(SM_CXFULLSCREEN
);
1808 screenRect
.bottom
= GetSystemMetrics(SM_CYFULLSCREEN
);
1810 doConstrain
= PR_TRUE
;
1812 ::ReleaseDC(mWnd
, dc
);
1818 if (*aX
< screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
)
1819 *aX
= screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
;
1820 else if (*aX
>= screenRect
.right
- kWindowPositionSlop
)
1821 *aX
= screenRect
.right
- kWindowPositionSlop
;
1823 if (*aY
< screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
)
1824 *aY
= screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
;
1825 else if (*aY
>= screenRect
.bottom
- kWindowPositionSlop
)
1826 *aY
= screenRect
.bottom
- kWindowPositionSlop
;
1830 if (*aX
< screenRect
.left
)
1831 *aX
= screenRect
.left
;
1832 else if (*aX
>= screenRect
.right
- mBounds
.width
)
1833 *aX
= screenRect
.right
- mBounds
.width
;
1835 if (*aY
< screenRect
.top
)
1836 *aY
= screenRect
.top
;
1837 else if (*aY
>= screenRect
.bottom
- mBounds
.height
)
1838 *aY
= screenRect
.bottom
- mBounds
.height
;
1844 /**************************************************************
1846 * SECTION: nsIWidget::Enable, nsIWidget::IsEnabled
1848 * Enabling and disabling the widget.
1850 **************************************************************/
1852 // Enable/disable this component
1853 NS_METHOD
nsWindow::Enable(PRBool bState
)
1856 ::EnableWindow(mWnd
, bState
);
1861 // Return the current enable state
1862 NS_METHOD
nsWindow::IsEnabled(PRBool
*aState
)
1864 NS_ENSURE_ARG_POINTER(aState
);
1867 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(::GetAncestor(mWnd
, GA_ROOT
)));
1869 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(mWnd
));
1876 /**************************************************************
1878 * SECTION: nsIWidget::SetFocus
1880 * Give the focus to this widget.
1882 **************************************************************/
1884 NS_METHOD
nsWindow::SetFocus(PRBool aRaise
)
1887 #ifdef WINSTATE_DEBUG_OUTPUT
1888 if (mWnd
== GetTopLevelHWND(mWnd
))
1889 printf("*** SetFocus: [ top] raise=%d\n", aRaise
);
1891 printf("*** SetFocus: [child] raise=%d\n", aRaise
);
1893 // Uniconify, if necessary
1894 HWND toplevelWnd
= GetTopLevelHWND(mWnd
);
1895 if (aRaise
&& ::IsIconic(toplevelWnd
)) {
1896 ::ShowWindow(toplevelWnd
, SW_RESTORE
);
1904 /**************************************************************
1908 * GetBounds, GetClientBounds, GetScreenBounds, GetClientOffset
1909 * SetDrawsInTitlebar, GetNonClientMargins, SetNonClientMargins
1911 * Bound calculations.
1913 **************************************************************/
1915 // Return the window's full dimensions in screen coordinates.
1916 // If the window has a parent, converts the origin to an offset
1917 // of the parent's screen origin.
1918 NS_METHOD
nsWindow::GetBounds(nsIntRect
&aRect
)
1922 VERIFY(::GetWindowRect(mWnd
, &r
));
1925 aRect
.width
= r
.right
- r
.left
;
1926 aRect
.height
= r
.bottom
- r
.top
;
1928 // chrome on parent:
1929 // ___ 5,5 (chrome start)
1930 // | ____ 10,10 (client start)
1931 // | | ____ 20,20 (child start)
1933 // 20,20 - 5,5 = 15,15 (??)
1934 // minus GetClientOffset:
1935 // 15,15 - 5,5 = 10,10
1937 // no chrome on parent:
1938 // ______ 10,10 (win start)
1939 // | ____ 20,20 (child start)
1941 // 20,20 - 10,10 = 10,10
1943 // walking the chain:
1944 // ___ 5,5 (chrome start)
1945 // | ___ 10,10 (client start)
1946 // | | ___ 20,20 (child start)
1947 // | | | __ 30,30 (child start)
1949 // 30,30 - 20,20 = 10,10 (offset from second child to first)
1950 // 20,20 - 5,5 = 15,15 + 10,10 = 25,25 (??)
1951 // minus GetClientOffset:
1952 // 25,25 - 5,5 = 20,20 (offset from second child to parent client)
1954 // convert coordinates if parent exists
1955 HWND parent
= ::GetParent(mWnd
);
1958 VERIFY(::GetWindowRect(parent
, &pr
));
1961 // adjust for chrome
1962 nsWindow
* pWidget
= static_cast<nsWindow
*>(GetParent());
1963 if (pWidget
&& pWidget
->IsTopLevelWidget()) {
1964 nsIntPoint clientOffset
= pWidget
->GetClientOffset();
1965 r
.left
-= clientOffset
.x
;
1966 r
.top
-= clientOffset
.y
;
1978 // Get this component dimension
1979 NS_METHOD
nsWindow::GetClientBounds(nsIntRect
&aRect
)
1983 VERIFY(::GetClientRect(mWnd
, &r
));
1988 aRect
.width
= r
.right
- r
.left
;
1989 aRect
.height
= r
.bottom
- r
.top
;
1992 aRect
.SetRect(0,0,0,0);
1997 // Like GetBounds, but don't offset by the parent
1998 NS_METHOD
nsWindow::GetScreenBounds(nsIntRect
&aRect
)
2002 VERIFY(::GetWindowRect(mWnd
, &r
));
2004 aRect
.width
= r
.right
- r
.left
;
2005 aRect
.height
= r
.bottom
- r
.top
;
2014 // return the x,y offset of the client area from the origin
2015 // of the window. If the window is borderless returns (0,0).
2016 nsIntPoint
nsWindow::GetClientOffset()
2019 return nsIntPoint(0, 0);
2023 GetWindowRect(mWnd
, &r1
);
2024 nsIntPoint pt
= WidgetToScreenOffset();
2025 return nsIntPoint(pt
.x
- r1
.left
, pt
.y
- r1
.top
);
2029 nsWindow::SetDrawsInTitlebar(PRBool aState
)
2031 nsWindow
* window
= GetTopLevelWindow(PR_TRUE
);
2032 if (window
&& window
!= this) {
2033 return window
->SetDrawsInTitlebar(aState
);
2037 // left, top, right, bottom for nsIntMargin
2038 nsIntMargin
margins(-1, 0, -1, -1);
2039 SetNonClientMargins(margins
);
2042 nsIntMargin
margins(-1, -1, -1, -1);
2043 SetNonClientMargins(margins
);
2048 nsWindow::GetNonClientMargins(nsIntMargin
&margins
)
2050 nsWindow
* window
= GetTopLevelWindow(PR_TRUE
);
2051 if (window
&& window
!= this) {
2052 return window
->GetNonClientMargins(margins
);
2055 if (mCustomNonClient
) {
2056 margins
= mNonClientMargins
;
2060 margins
.top
= GetSystemMetrics(SM_CYCAPTION
);
2061 margins
.bottom
= GetSystemMetrics(SM_CYFRAME
);
2062 margins
.top
+= margins
.bottom
;
2063 margins
.left
= margins
.right
= GetSystemMetrics(SM_CYFRAME
);
2069 nsWindow::ResetLayout()
2071 // This will trigger a frame changed event, triggering
2072 // nc calc size and a sizemode gecko event.
2073 SetWindowPos(mWnd
, 0, 0, 0, 0, 0,
2074 SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|
2075 SWP_NOOWNERZORDER
|SWP_NOSIZE
|SWP_NOZORDER
);
2077 // If hidden, just send the frame changed event for now.
2081 // Send a gecko size event to trigger reflow.
2082 RECT clientRc
= {0};
2083 GetClientRect(mWnd
, &clientRc
);
2084 nsIntRect
evRect(nsWindowGfx::ToIntRect(clientRc
));
2087 // Invalidate and update
2088 Invalidate(PR_FALSE
);
2091 // Internally track the caption status via a window property. Required
2092 // due to our internal handling of WM_NCACTIVATE when custom client
2094 static const PRUnichar kManageWindowInfoProperty
[] = L
"ManageWindowInfoProperty";
2095 typedef BOOL (WINAPI
*GetWindowInfoPtr
)(HWND hwnd
, PWINDOWINFO pwi
);
2096 static GetWindowInfoPtr sGetWindowInfoPtrStub
= NULL
;
2099 GetWindowInfoHook(HWND hWnd
, PWINDOWINFO pwi
)
2101 if (!sGetWindowInfoPtrStub
) {
2102 NS_ASSERTION(FALSE
, "Something is horribly wrong in GetWindowInfoHook!");
2106 reinterpret_cast<LONG_PTR
>(GetPropW(hWnd
, kManageWindowInfoProperty
));
2107 // No property set, return the default data.
2109 return sGetWindowInfoPtrStub(hWnd
, pwi
);
2110 // Call GetWindowInfo and update dwWindowStatus with our
2111 // internally tracked value.
2112 BOOL result
= sGetWindowInfoPtrStub(hWnd
, pwi
);
2114 pwi
->dwWindowStatus
= (windowStatus
== 1 ? 0 : WS_ACTIVECAPTION
);
2119 nsWindow::UpdateGetWindowInfoCaptionStatus(PRBool aActiveCaption
)
2124 if (!sGetWindowInfoPtrStub
) {
2125 sUser32Intercept
.Init("user32.dll");
2126 if (!sUser32Intercept
.AddHook("GetWindowInfo", (void*)GetWindowInfoHook
,
2127 (void**) &sGetWindowInfoPtrStub
))
2130 // Update our internally tracked caption status
2131 SetPropW(mWnd
, kManageWindowInfoProperty
,
2132 reinterpret_cast<HANDLE
>(static_cast<int>(aActiveCaption
) + 1));
2135 // Called when the window layout changes: full screen mode transitions,
2136 // theme changes, and composition changes. Calculates the new non-client
2137 // margins and fires off a frame changed event, which triggers an nc calc
2138 // size windows event, kicking the changes in.
2140 nsWindow::UpdateNonClientMargins(PRInt32 aSizeMode
, PRBool aReflowWindow
)
2142 if (!mCustomNonClient
)
2145 mNonClientOffset
.top
= mNonClientOffset
.bottom
=
2146 mNonClientOffset
.left
= mNonClientOffset
.right
= 0;
2148 if (aSizeMode
== -1)
2149 aSizeMode
= mSizeMode
;
2151 if (aSizeMode
== nsSizeMode_Minimized
||
2152 aSizeMode
== nsSizeMode_Fullscreen
) {
2153 mCaptionHeight
= mVertResizeMargin
= mHorResizeMargin
= 0;
2157 // Note, for maximized windows, we need to continue to offset the client by
2158 // thick frame margins of a normal window, since windows expects this
2159 // in it's DwmDefWndProc hit testing.
2160 mCaptionHeight
= GetSystemMetrics(SM_CYCAPTION
);
2161 mHorResizeMargin
= GetSystemMetrics(SM_CXFRAME
);
2162 mVertResizeMargin
= GetSystemMetrics(SM_CYFRAME
);
2164 mCaptionHeight
+= mVertResizeMargin
;
2166 // If a margin value is 0, set the offset to the default size of the frame.
2167 // If a margin is -1, leave as default, and if a margin > 0, set the offset
2168 // so that the frame size is equal to the margin value.
2169 if (!mNonClientMargins
.top
)
2170 mNonClientOffset
.top
= mCaptionHeight
;
2171 else if (mNonClientMargins
.top
> 0)
2172 mNonClientOffset
.top
= mCaptionHeight
- mNonClientMargins
.top
;
2174 if (!mNonClientMargins
.left
)
2175 mNonClientOffset
.left
= mHorResizeMargin
;
2176 else if (mNonClientMargins
.left
> 0)
2177 mNonClientOffset
.left
= mHorResizeMargin
- mNonClientMargins
.left
;
2179 if (!mNonClientMargins
.right
)
2180 mNonClientOffset
.right
= mHorResizeMargin
;
2181 else if (mNonClientMargins
.right
> 0)
2182 mNonClientOffset
.right
= mHorResizeMargin
- mNonClientMargins
.right
;
2184 if (!mNonClientMargins
.bottom
)
2185 mNonClientOffset
.bottom
= mVertResizeMargin
;
2186 else if (mNonClientMargins
.bottom
> 0)
2187 mNonClientOffset
.bottom
= mVertResizeMargin
- mNonClientMargins
.bottom
;
2190 if (aSizeMode
== nsSizeMode_Maximized
) {
2191 // Address an issue with auto-hide taskbars which fall behind the window.
2192 // Ensure a 1 pixel margin at the bottom of the monitor so that unhiding
2193 // the taskbar works properly.
2194 MONITORINFO info
= {sizeof(MONITORINFO
)};
2195 if (::GetMonitorInfo(::MonitorFromWindow(mWnd
, MONITOR_DEFAULTTOPRIMARY
),
2198 if (::GetWindowRect(mWnd
, &r
)) {
2199 // Adjust window rect to account for non-client margins.
2200 r
.top
+= mVertResizeMargin
- mNonClientOffset
.top
;
2201 r
.left
+= mHorResizeMargin
- mNonClientOffset
.left
;
2202 r
.bottom
-= mVertResizeMargin
- mNonClientOffset
.bottom
;
2203 r
.right
-= mHorResizeMargin
- mNonClientOffset
.right
;
2204 // Leave the 1 pixel margin if the window covers the monitor.
2205 if (r
.top
<= info
.rcMonitor
.top
&&
2206 r
.left
<= info
.rcMonitor
.left
&&
2207 r
.right
>= info
.rcMonitor
.right
&&
2208 r
.bottom
>= info
.rcMonitor
.bottom
)
2209 mNonClientOffset
.bottom
-= r
.bottom
- info
.rcMonitor
.bottom
+ 1;
2215 if (aReflowWindow
) {
2216 // Force a reflow of content based on the new client
2225 nsWindow::SetNonClientMargins(nsIntMargin
&margins
)
2227 if (!mIsTopWidgetWindow
||
2228 mBorderStyle
& eBorderStyle_none
||
2230 return NS_ERROR_INVALID_ARG
;
2232 // Request for a reset
2233 if (margins
.top
== -1 && margins
.left
== -1 &&
2234 margins
.right
== -1 && margins
.bottom
== -1) {
2235 mCustomNonClient
= PR_FALSE
;
2236 mNonClientMargins
= margins
;
2237 RemovePropW(mWnd
, kManageWindowInfoProperty
);
2238 // Force a reflow of content based on the new client
2244 if (margins
.top
< -1 || margins
.bottom
< -1 ||
2245 margins
.left
< -1 || margins
.right
< -1)
2246 return NS_ERROR_INVALID_ARG
;
2248 mNonClientMargins
= margins
;
2249 mCustomNonClient
= PR_TRUE
;
2250 if (!UpdateNonClientMargins()) {
2251 NS_WARNING("UpdateNonClientMargins failed!");
2259 nsWindow::InvalidateNonClientRegion()
2261 // +-+-----------------------+-+
2262 // | | app non-client chrome | |
2263 // | +-----------------------+ |
2264 // | | app client chrome | | }
2265 // | +-----------------------+ | }
2266 // | | app content | | } area we don't want to invalidate
2267 // | +-----------------------+ | }
2268 // | | app client chrome | | }
2269 // | +-----------------------+ |
2270 // +---------------------------+ <
2271 // ^ ^ windows non-client chrome
2272 // client area = app *
2274 GetWindowRect(mWnd
, &rect
);
2275 MapWindowPoints(NULL
, mWnd
, (LPPOINT
)&rect
, 2);
2276 HRGN winRgn
= CreateRectRgnIndirect(&rect
);
2278 // Subtract app client chrome and app content leaving
2279 // windows non-client chrome and app non-client chrome
2281 GetWindowRect(mWnd
, &rect
);
2282 rect
.top
+= mCaptionHeight
;
2283 rect
.right
-= mHorResizeMargin
;
2284 rect
.bottom
-= mHorResizeMargin
;
2285 rect
.left
+= mVertResizeMargin
;
2286 MapWindowPoints(NULL
, mWnd
, (LPPOINT
)&rect
, 2);
2287 HRGN clientRgn
= CreateRectRgnIndirect(&rect
);
2288 CombineRgn(winRgn
, winRgn
, clientRgn
, RGN_DIFF
);
2289 DeleteObject(clientRgn
);
2291 // triggers ncpaint and paint events for the two areas
2292 RedrawWindow(mWnd
, NULL
, winRgn
, RDW_FRAME
|RDW_INVALIDATE
);
2293 DeleteObject(winRgn
);
2297 nsWindow::ExcludeNonClientFromPaintRegion(HRGN aRegion
)
2301 if (aRegion
== (HRGN
)1) { // undocumented value indicating a full refresh
2302 GetWindowRect(mWnd
, &rect
);
2303 rgn
= CreateRectRgnIndirect(&rect
);
2307 GetClientRect(mWnd
, &rect
);
2308 MapWindowPoints(mWnd
, NULL
, (LPPOINT
)&rect
, 2);
2309 HRGN nonClientRgn
= CreateRectRgnIndirect(&rect
);
2310 CombineRgn(rgn
, rgn
, nonClientRgn
, RGN_DIFF
);
2311 DeleteObject(nonClientRgn
);
2315 /**************************************************************
2317 * SECTION: nsIWidget::SetBackgroundColor
2319 * Sets the window background paint color.
2321 **************************************************************/
2323 NS_METHOD
nsWindow::SetBackgroundColor(const nscolor
&aColor
)
2325 nsBaseWidget::SetBackgroundColor(aColor
);
2328 ::DeleteObject(mBrush
);
2330 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
2333 ::SetClassLongPtrW(mWnd
, GCLP_HBRBACKGROUND
, (LONG_PTR
)mBrush
);
2339 /**************************************************************
2341 * SECTION: nsIWidget::SetCursor
2343 * SetCursor and related utilities for manging cursor state.
2345 **************************************************************/
2347 // Set this component cursor
2348 NS_METHOD
nsWindow::SetCursor(nsCursor aCursor
)
2350 // Only change cursor if it's changing
2352 //XXX mCursor isn't always right. Scrollbars and others change it, too.
2353 //XXX If we want this optimization we need a better way to do it.
2354 //if (aCursor != mCursor) {
2355 HCURSOR newCursor
= NULL
;
2358 case eCursor_select
:
2359 newCursor
= ::LoadCursor(NULL
, IDC_IBEAM
);
2363 newCursor
= ::LoadCursor(NULL
, IDC_WAIT
);
2366 case eCursor_hyperlink
:
2368 newCursor
= ::LoadCursor(NULL
, IDC_HAND
);
2372 case eCursor_standard
:
2373 newCursor
= ::LoadCursor(NULL
, IDC_ARROW
);
2376 case eCursor_n_resize
:
2377 case eCursor_s_resize
:
2378 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
2381 case eCursor_w_resize
:
2382 case eCursor_e_resize
:
2383 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
2386 case eCursor_nw_resize
:
2387 case eCursor_se_resize
:
2388 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
2391 case eCursor_ne_resize
:
2392 case eCursor_sw_resize
:
2393 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
2396 case eCursor_crosshair
:
2397 newCursor
= ::LoadCursor(NULL
, IDC_CROSS
);
2401 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
2405 newCursor
= ::LoadCursor(NULL
, IDC_HELP
);
2408 case eCursor_copy
: // CSS3
2409 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COPY
));
2413 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ALIAS
));
2417 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_CELL
));
2421 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRAB
));
2424 case eCursor_grabbing
:
2425 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRABBING
));
2428 case eCursor_spinning
:
2429 newCursor
= ::LoadCursor(NULL
, IDC_APPSTARTING
);
2432 case eCursor_context_menu
:
2433 // XXX this CSS3 cursor needs to be implemented
2436 case eCursor_zoom_in
:
2437 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMIN
));
2440 case eCursor_zoom_out
:
2441 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMOUT
));
2444 case eCursor_not_allowed
:
2445 case eCursor_no_drop
:
2446 newCursor
= ::LoadCursor(NULL
, IDC_NO
);
2449 case eCursor_col_resize
:
2450 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COLRESIZE
));
2453 case eCursor_row_resize
:
2454 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ROWRESIZE
));
2457 case eCursor_vertical_text
:
2458 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_VERTICALTEXT
));
2461 case eCursor_all_scroll
:
2462 // XXX not 100% appropriate perhaps
2463 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
2466 case eCursor_nesw_resize
:
2467 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
2470 case eCursor_nwse_resize
:
2471 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
2474 case eCursor_ns_resize
:
2475 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
2478 case eCursor_ew_resize
:
2479 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
2483 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_NONE
));
2487 NS_ERROR("Invalid cursor type");
2491 if (NULL
!= newCursor
) {
2493 HCURSOR oldCursor
= ::SetCursor(newCursor
);
2495 if (sHCursor
== oldCursor
) {
2496 NS_IF_RELEASE(sCursorImgContainer
);
2497 if (sHCursor
!= NULL
)
2498 ::DestroyIcon(sHCursor
);
2506 // Setting the actual cursor
2507 NS_IMETHODIMP
nsWindow::SetCursor(imgIContainer
* aCursor
,
2508 PRUint32 aHotspotX
, PRUint32 aHotspotY
)
2510 if (sCursorImgContainer
== aCursor
&& sHCursor
) {
2511 ::SetCursor(sHCursor
);
2519 rv
= aCursor
->GetWidth(&width
);
2520 NS_ENSURE_SUCCESS(rv
, rv
);
2521 rv
= aCursor
->GetHeight(&height
);
2522 NS_ENSURE_SUCCESS(rv
, rv
);
2524 // Reject cursors greater than 128 pixels in either direction, to prevent
2526 // XXX ideally we should rescale. Also, we could modify the API to
2527 // allow trusted content to set larger cursors.
2528 if (width
> 128 || height
> 128)
2529 return NS_ERROR_NOT_AVAILABLE
;
2532 rv
= nsWindowGfx::CreateIcon(aCursor
, PR_TRUE
, aHotspotX
, aHotspotY
, &cursor
);
2533 NS_ENSURE_SUCCESS(rv
, rv
);
2535 mCursor
= nsCursor(-1);
2536 ::SetCursor(cursor
);
2538 NS_IF_RELEASE(sCursorImgContainer
);
2539 sCursorImgContainer
= aCursor
;
2540 NS_ADDREF(sCursorImgContainer
);
2542 if (sHCursor
!= NULL
)
2543 ::DestroyIcon(sHCursor
);
2549 /**************************************************************
2551 * SECTION: nsIWidget::Get/SetTransparencyMode
2553 * Manage the transparency mode of the top-level window
2554 * containing this widget.
2556 **************************************************************/
2559 nsTransparencyMode
nsWindow::GetTransparencyMode()
2561 return GetTopLevelWindow(PR_TRUE
)->GetWindowTranslucencyInner();
2564 void nsWindow::SetTransparencyMode(nsTransparencyMode aMode
)
2566 GetTopLevelWindow(PR_TRUE
)->SetWindowTranslucencyInner(aMode
);
2569 static const nsIntRegion
2570 RegionFromArray(const nsTArray
<nsIntRect
>& aRects
)
2573 for (PRUint32 i
= 0; i
< aRects
.Length(); ++i
) {
2574 region
.Or(region
, aRects
[i
]);
2579 void nsWindow::UpdateTransparentRegion(const nsIntRegion
&aTransparentRegion
)
2581 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2582 if (!HasGlass() || GetParent())
2585 nsIntRect clientBounds
;
2586 GetClientBounds(clientBounds
);
2588 // calculate the known fully opaque region by subtracting the transparent
2589 // areas from client bounds. We'll use this to calculate our new glass
2591 nsIntRegion opaqueRegion
;
2592 opaqueRegion
.Sub(clientBounds
, aTransparentRegion
);
2594 // If there is no opaque region or hidechrome=true, set margins
2595 // to support a full sheet of glass. Comments in MSDN indicate
2596 // all values must be set to -1 to get a full sheet of glass.
2597 MARGINS margins
= { -1, -1, -1, -1 };
2598 bool visiblePlugin
= false;
2599 if (!opaqueRegion
.IsEmpty() && !mHideChrome
) {
2600 nsIntRect pluginBounds
;
2601 for (nsIWidget
* child
= GetFirstChild(); child
; child
= child
->GetNextSibling()) {
2603 child
->GetWindowType(type
);
2604 if (type
== eWindowType_plugin
) {
2605 // Collect the bounds of all plugins for GetLargestRectangle.
2606 nsIntRect childBounds
;
2607 child
->GetBounds(childBounds
);
2608 pluginBounds
.UnionRect(pluginBounds
, childBounds
);
2609 // Detect if any region of a plugin is visible.
2610 nsTArray
<nsIntRect
> currentRects
;
2611 child
->GetWindowClipRegion(¤tRects
);
2612 nsIntRegion currentClipRegion
= RegionFromArray(currentRects
);
2613 nsIntRect bounds
= currentClipRegion
.GetBounds();
2614 if (!bounds
.IsEmpty()) {
2615 visiblePlugin
= true;
2620 // Find the largest rectangle and use that to calculate the inset. Our top
2621 // priority is to include the bounds of all plugins.
2622 // Also don't let MIN_OPAQUE_RECT_HEIGHT_FOR_GLASS_MARGINS override content
2623 // that contains a visible plugin since glass over plugins looks bad.
2624 nsIntRect largest
= opaqueRegion
.GetLargestRectangle(pluginBounds
);
2625 if (visiblePlugin
||
2626 (largest
.x
<= MAX_HORIZONTAL_GLASS_MARGIN
&&
2627 clientBounds
.width
- largest
.XMost() <= MAX_HORIZONTAL_GLASS_MARGIN
&&
2628 largest
.height
>= MIN_OPAQUE_RECT_HEIGHT_FOR_GLASS_MARGINS
)) {
2629 margins
.cxLeftWidth
= largest
.x
;
2630 margins
.cxRightWidth
= clientBounds
.width
- largest
.XMost();
2631 margins
.cyBottomHeight
= clientBounds
.height
- largest
.YMost();
2633 if (mCustomNonClient
) {
2634 // The minimum glass height must be the caption buttons height,
2635 // otherwise the buttons are drawn incorrectly.
2636 largest
.y
= PR_MAX(largest
.y
,
2637 nsUXThemeData::sCommandButtons
[CMDBUTTONIDX_BUTTONBOX
].cy
);
2639 margins
.cyTopHeight
= largest
.y
;
2643 // Only update glass area if there are changes
2644 if (memcmp(&mGlassMargins
, &margins
, sizeof mGlassMargins
)) {
2645 mGlassMargins
= margins
;
2648 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2651 void nsWindow::UpdateGlass()
2653 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2654 MARGINS margins
= mGlassMargins
;
2656 // DWMNCRP_USEWINDOWSTYLE - The non-client rendering area is
2657 // rendered based on the window style.
2658 // DWMNCRP_ENABLED - The non-client area rendering is
2659 // enabled; the window style is ignored.
2660 DWMNCRENDERINGPOLICY policy
= DWMNCRP_USEWINDOWSTYLE
;
2661 switch (mTransparencyMode
) {
2662 case eTransparencyBorderlessGlass
:
2663 // Only adjust if there is some opaque rectangle
2664 if (margins
.cxLeftWidth
>= 0) {
2665 margins
.cxLeftWidth
+= kGlassMarginAdjustment
;
2666 margins
.cyTopHeight
+= kGlassMarginAdjustment
;
2667 margins
.cxRightWidth
+= kGlassMarginAdjustment
;
2668 margins
.cyBottomHeight
+= kGlassMarginAdjustment
;
2671 case eTransparencyGlass
:
2672 policy
= DWMNCRP_ENABLED
;
2676 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
2677 ("glass margins: left:%d top:%d right:%d bottom:%d\n",
2678 margins
.cxLeftWidth
, margins
.cyTopHeight
,
2679 margins
.cxRightWidth
, margins
.cyBottomHeight
));
2681 // Extends the window frame behind the client area
2682 if(nsUXThemeData::CheckForCompositor()) {
2683 nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(mWnd
, &margins
);
2684 nsUXThemeData::dwmSetWindowAttributePtr(mWnd
, DWMWA_NCRENDERING_POLICY
, &policy
, sizeof policy
);
2686 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
2690 /**************************************************************
2692 * SECTION: nsIWidget::HideWindowChrome
2694 * Show or hide window chrome.
2696 **************************************************************/
2698 NS_IMETHODIMP
nsWindow::HideWindowChrome(PRBool aShouldHide
)
2700 HWND hwnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2701 if (!GetNSWindowPtr(hwnd
))
2703 NS_WARNING("Trying to hide window decorations in an embedded context");
2704 return NS_ERROR_FAILURE
;
2707 if (mHideChrome
== aShouldHide
)
2710 DWORD_PTR style
, exStyle
;
2711 mHideChrome
= aShouldHide
;
2713 DWORD_PTR tempStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2714 DWORD_PTR tempExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2716 style
= tempStyle
& ~(WS_CAPTION
| WS_THICKFRAME
);
2717 exStyle
= tempExStyle
& ~(WS_EX_DLGMODALFRAME
| WS_EX_WINDOWEDGE
|
2718 WS_EX_CLIENTEDGE
| WS_EX_STATICEDGE
);
2720 mOldStyle
= tempStyle
;
2721 mOldExStyle
= tempExStyle
;
2724 if (!mOldStyle
|| !mOldExStyle
) {
2725 mOldStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2726 mOldExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2730 exStyle
= mOldExStyle
;
2733 VERIFY_WINDOW_STYLE(style
);
2734 ::SetWindowLongPtrW(hwnd
, GWL_STYLE
, style
);
2735 ::SetWindowLongPtrW(hwnd
, GWL_EXSTYLE
, exStyle
);
2740 /**************************************************************
2742 * SECTION: nsIWidget::Invalidate
2744 * Invalidate an area of the client for painting.
2746 **************************************************************/
2748 // Invalidate this component visible area
2749 NS_METHOD
nsWindow::Invalidate(PRBool aIsSynchronous
)
2753 #ifdef WIDGET_DEBUG_OUTPUT
2754 debug_DumpInvalidate(stdout
,
2758 nsCAutoString("noname"),
2760 #endif // WIDGET_DEBUG_OUTPUT
2762 VERIFY(::InvalidateRect(mWnd
, NULL
, FALSE
));
2764 if (aIsSynchronous
) {
2765 VERIFY(::UpdateWindow(mWnd
));
2771 // Invalidate this component visible area
2772 NS_METHOD
nsWindow::Invalidate(const nsIntRect
& aRect
, PRBool aIsSynchronous
)
2776 #ifdef WIDGET_DEBUG_OUTPUT
2777 debug_DumpInvalidate(stdout
,
2781 nsCAutoString("noname"),
2783 #endif // WIDGET_DEBUG_OUTPUT
2787 rect
.left
= aRect
.x
;
2789 rect
.right
= aRect
.x
+ aRect
.width
;
2790 rect
.bottom
= aRect
.y
+ aRect
.height
;
2792 VERIFY(::InvalidateRect(mWnd
, &rect
, FALSE
));
2794 if (aIsSynchronous
) {
2795 VERIFY(::UpdateWindow(mWnd
));
2802 nsWindow::MakeFullScreen(PRBool aFullScreen
)
2804 #if WINCE_WINDOWS_MOBILE
2807 SetForegroundWindow(mWnd
);
2808 if (nsWindowCE::sMenuBarShown
) {
2810 memset(&sipInfo
, 0, sizeof(SIPINFO
));
2811 sipInfo
.cbSize
= sizeof(SIPINFO
);
2812 if (SipGetInfo(&sipInfo
))
2813 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
),
2814 sipInfo
.rcVisibleDesktop
.bottom
);
2816 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
),
2817 GetSystemMetrics(SM_CYSCREEN
));
2819 if (GetWindowRect(nsWindowCE::sSoftKeyMenuBarHandle
, &menuBarRect
) &&
2820 menuBarRect
.top
< rc
.bottom
)
2821 rc
.bottom
= menuBarRect
.top
;
2822 SHFullScreen(mWnd
, SHFS_HIDETASKBAR
| SHFS_HIDESTARTICON
| SHFS_SHOWSIPBUTTON
);
2825 SHFullScreen(mWnd
, SHFS_HIDETASKBAR
| SHFS_HIDESTARTICON
| SHFS_HIDESIPBUTTON
);
2826 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2830 SHFullScreen(mWnd
, SHFS_SHOWTASKBAR
| SHFS_SHOWSTARTICON
);
2831 SystemParametersInfo(SPI_GETWORKAREA
, 0, &rc
, FALSE
);
2835 mSizeMode
= nsSizeMode_Fullscreen
;
2837 // nsBaseWidget hides the chrome and resizes the window, replicate that here
2838 HideWindowChrome(aFullScreen
);
2839 Resize(rc
.left
, rc
.top
, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, PR_TRUE
);
2845 mFullscreenMode
= aFullScreen
;
2847 if (mSizeMode
== nsSizeMode_Fullscreen
)
2849 mOldSizeMode
= mSizeMode
;
2850 SetSizeMode(nsSizeMode_Fullscreen
);
2852 SetSizeMode(mOldSizeMode
);
2855 UpdateNonClientMargins();
2857 // Prevent window updates during the transition.
2859 if (nsUXThemeData::CheckForCompositor()) {
2860 style
= GetWindowLong(mWnd
, GWL_STYLE
);
2861 SetWindowLong(mWnd
, GWL_STYLE
, style
& ~WS_VISIBLE
);
2864 // Will call hide chrome, reposition window. Note this will
2865 // also cache dimensions for restoration, so it should only
2866 // be called once per fullscreen request.
2867 nsresult rv
= nsBaseWidget::MakeFullScreen(aFullScreen
);
2869 if (nsUXThemeData::CheckForCompositor()) {
2870 style
= GetWindowLong(mWnd
, GWL_STYLE
);
2871 SetWindowLong(mWnd
, GWL_STYLE
, style
| WS_VISIBLE
);
2872 Invalidate(PR_FALSE
);
2875 // Let the dom know via web shell window
2876 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
2877 event
.mSizeMode
= mSizeMode
;
2879 DispatchWindowEvent(&event
);
2885 /**************************************************************
2887 * SECTION: nsIWidget::Update
2889 * Force a synchronous repaint of the window.
2891 **************************************************************/
2893 NS_IMETHODIMP
nsWindow::Update()
2895 nsresult rv
= NS_OK
;
2897 // updates can come through for windows no longer holding an mWnd during
2898 // deletes triggered by JavaScript in buttons with mouse feedback
2900 VERIFY(::UpdateWindow(mWnd
));
2905 /**************************************************************
2907 * SECTION: Native data storage
2909 * nsIWidget::GetNativeData
2910 * nsIWidget::FreeNativeData
2912 * Set or clear native data based on a constant.
2914 **************************************************************/
2916 // Return some native data according to aDataType
2917 void* nsWindow::GetNativeData(PRUint32 aDataType
)
2919 nsAutoString className
;
2920 switch (aDataType
) {
2921 case NS_NATIVE_TMP_WINDOW
:
2922 GetWindowClass(className
);
2923 return (void*)::CreateWindowExW(mIsRTL
? WS_EX_LAYOUTRTL
: 0,
2933 nsToolkit::mDllInstance
,
2935 case NS_NATIVE_PLUGIN_PORT
:
2936 case NS_NATIVE_WIDGET
:
2937 case NS_NATIVE_WINDOW
:
2939 case NS_NATIVE_GRAPHIC
:
2940 // XXX: This is sleezy!! Remember to Release the DC after using it!
2942 return (void*)(eTransparencyTransparent
== mTransparencyMode
) ?
2943 mMemoryDC
: ::GetDC(mWnd
);
2945 return (void*)::GetDC(mWnd
);
2948 #ifdef NS_ENABLE_TSF
2949 case NS_NATIVE_TSF_THREAD_MGR
:
2950 return nsTextStore::GetThreadMgr();
2951 case NS_NATIVE_TSF_CATEGORY_MGR
:
2952 return nsTextStore::GetCategoryMgr();
2953 case NS_NATIVE_TSF_DISPLAY_ATTR_MGR
:
2954 return nsTextStore::GetDisplayAttrMgr();
2955 #endif //NS_ENABLE_TSF
2964 // Free some native data according to aDataType
2965 void nsWindow::FreeNativeData(void * data
, PRUint32 aDataType
)
2969 case NS_NATIVE_GRAPHIC
:
2971 if (eTransparencyTransparent
!= mTransparencyMode
)
2972 ::ReleaseDC(mWnd
, (HDC
)data
);
2974 ::ReleaseDC(mWnd
, (HDC
)data
);
2977 case NS_NATIVE_WIDGET
:
2978 case NS_NATIVE_WINDOW
:
2979 case NS_NATIVE_PLUGIN_PORT
:
2986 /**************************************************************
2988 * SECTION: nsIWidget::SetTitle
2990 * Set the main windows title text.
2992 **************************************************************/
2994 NS_METHOD
nsWindow::SetTitle(const nsAString
& aTitle
)
2996 const nsString
& strTitle
= PromiseFlatString(aTitle
);
2997 ::SendMessageW(mWnd
, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)(LPCWSTR
)strTitle
.get());
3001 /**************************************************************
3003 * SECTION: nsIWidget::SetIcon
3005 * Set the main windows icon.
3007 **************************************************************/
3009 NS_METHOD
nsWindow::SetIcon(const nsAString
& aIconSpec
)
3012 // Assume the given string is a local identifier for an icon file.
3014 nsCOMPtr
<nsILocalFile
> iconFile
;
3015 ResolveIconName(aIconSpec
, NS_LITERAL_STRING(".ico"),
3016 getter_AddRefs(iconFile
));
3018 return NS_OK
; // not an error if icon is not found
3020 nsAutoString iconPath
;
3021 iconFile
->GetPath(iconPath
);
3023 // XXX this should use MZLU (see bug 239279)
3027 HICON bigIcon
= (HICON
)::LoadImageW(NULL
,
3028 (LPCWSTR
)iconPath
.get(),
3030 ::GetSystemMetrics(SM_CXICON
),
3031 ::GetSystemMetrics(SM_CYICON
),
3033 HICON smallIcon
= (HICON
)::LoadImageW(NULL
,
3034 (LPCWSTR
)iconPath
.get(),
3036 ::GetSystemMetrics(SM_CXSMICON
),
3037 ::GetSystemMetrics(SM_CYSMICON
),
3041 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
)bigIcon
);
3043 ::DestroyIcon(icon
);
3045 #ifdef DEBUG_SetIcon
3047 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
3048 printf( "\nIcon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
3052 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
)smallIcon
);
3054 ::DestroyIcon(icon
);
3056 #ifdef DEBUG_SetIcon
3058 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
3059 printf( "\nSmall icon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
3066 /**************************************************************
3068 * SECTION: nsIWidget::WidgetToScreenOffset
3070 * Return this widget's origin in screen coordinates.
3072 **************************************************************/
3074 nsIntPoint
nsWindow::WidgetToScreenOffset()
3079 ::ClientToScreen(mWnd
, &point
);
3080 return nsIntPoint(point
.x
, point
.y
);
3083 nsIntSize
nsWindow::ClientToWindowSize(const nsIntSize
& aClientSize
)
3085 if (!IsPopupWithTitleBar())
3088 // just use (200, 200) as the position
3092 r
.right
= 200 + aClientSize
.width
;
3093 r
.bottom
= 200 + aClientSize
.height
;
3094 ::AdjustWindowRectEx(&r
, WindowStyle(), PR_FALSE
, WindowExStyle());
3096 return nsIntSize(r
.right
- r
.left
, r
.bottom
- r
.top
);
3099 /**************************************************************
3101 * SECTION: nsIWidget::EnableDragDrop
3103 * Enables/Disables drag and drop of files on this widget.
3105 **************************************************************/
3107 #if !defined(WINCE) // implemented in nsWindowCE.cpp
3108 NS_METHOD
nsWindow::EnableDragDrop(PRBool aEnable
)
3110 NS_ASSERTION(mWnd
, "nsWindow::EnableDragDrop() called after Destroy()");
3112 nsresult rv
= NS_ERROR_FAILURE
;
3114 if (nsnull
== mNativeDragTarget
) {
3115 mNativeDragTarget
= new nsNativeDragTarget(this);
3116 if (NULL
!= mNativeDragTarget
) {
3117 mNativeDragTarget
->AddRef();
3118 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
,TRUE
,FALSE
)) {
3119 if (S_OK
== ::RegisterDragDrop(mWnd
, (LPDROPTARGET
)mNativeDragTarget
)) {
3126 if (nsnull
!= mWnd
&& NULL
!= mNativeDragTarget
) {
3127 ::RevokeDragDrop(mWnd
);
3128 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
, FALSE
, TRUE
)) {
3131 mNativeDragTarget
->DragCancel();
3132 NS_RELEASE(mNativeDragTarget
);
3139 /**************************************************************
3141 * SECTION: nsIWidget::CaptureMouse
3143 * Enables/Disables system mouse capture.
3145 **************************************************************/
3147 NS_METHOD
nsWindow::CaptureMouse(PRBool aCapture
)
3149 if (!nsToolkit::gMouseTrailer
) {
3150 NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
3155 nsToolkit::gMouseTrailer
->SetCaptureWindow(mWnd
);
3158 nsToolkit::gMouseTrailer
->SetCaptureWindow(NULL
);
3161 sIsInMouseCapture
= aCapture
;
3165 /**************************************************************
3167 * SECTION: nsIWidget::CaptureRollupEvents
3169 * Dealing with event rollup on destroy for popups. Enables &
3170 * Disables system capture of any and all events that would
3171 * cause a dropdown to be rolled up.
3173 **************************************************************/
3175 NS_IMETHODIMP
nsWindow::CaptureRollupEvents(nsIRollupListener
* aListener
,
3176 nsIMenuRollup
* aMenuRollup
,
3178 PRBool aConsumeRollupEvent
)
3181 /* we haven't bothered carrying a weak reference to sRollupWidget because
3182 we believe lifespan is properly scoped. this next assertion helps
3183 assure that remains true. */
3184 NS_ASSERTION(!sRollupWidget
, "rollup widget reassigned before release");
3185 sRollupConsumeEvent
= aConsumeRollupEvent
;
3186 NS_IF_RELEASE(sRollupWidget
);
3187 NS_IF_RELEASE(sMenuRollup
);
3188 sRollupListener
= aListener
;
3189 sMenuRollup
= aMenuRollup
;
3190 NS_IF_ADDREF(aMenuRollup
);
3191 sRollupWidget
= this;
3195 if (!sMsgFilterHook
&& !sCallProcHook
&& !sCallMouseHook
) {
3196 RegisterSpecialDropdownHooks();
3198 sProcessHook
= PR_TRUE
;
3202 sRollupListener
= nsnull
;
3203 NS_IF_RELEASE(sMenuRollup
);
3204 NS_IF_RELEASE(sRollupWidget
);
3207 sProcessHook
= PR_FALSE
;
3208 UnregisterSpecialDropdownHooks();
3215 /**************************************************************
3217 * SECTION: nsIWidget::GetAttention
3219 * Bring this window to the user's attention.
3221 **************************************************************/
3223 // Draw user's attention to this window until it comes to foreground.
3225 nsWindow::GetAttention(PRInt32 aCycleCount
)
3230 return NS_ERROR_NOT_INITIALIZED
;
3232 // Don't flash if the flash count is 0 or if the
3233 // top level window is already active.
3234 HWND fgWnd
= ::GetForegroundWindow();
3235 if (aCycleCount
== 0 || fgWnd
== GetTopLevelHWND(mWnd
))
3238 HWND flashWnd
= mWnd
;
3239 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
3240 flashWnd
= ownerWnd
;
3243 // Don't flash if the owner window is active either.
3244 if (fgWnd
== flashWnd
)
3247 DWORD defaultCycleCount
= 0;
3248 ::SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT
, 0, &defaultCycleCount
, 0);
3250 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
3251 FLASHW_ALL
, aCycleCount
> 0 ? aCycleCount
: defaultCycleCount
, 0 };
3252 ::FlashWindowEx(&flashInfo
);
3257 void nsWindow::StopFlashing()
3260 HWND flashWnd
= mWnd
;
3261 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
3262 flashWnd
= ownerWnd
;
3265 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
3266 FLASHW_STOP
, 0, 0 };
3267 ::FlashWindowEx(&flashInfo
);
3271 /**************************************************************
3273 * SECTION: nsIWidget::HasPendingInputEvent
3275 * Ask whether there user input events pending. All input events are
3276 * included, including those not targeted at this nsIwidget instance.
3278 **************************************************************/
3281 nsWindow::HasPendingInputEvent()
3283 // If there is pending input or the user is currently
3284 // moving the window then return true.
3285 // Note: When the user is moving the window WIN32 spins
3286 // a separate event loop and input events are not
3287 // reported to the application.
3288 if (HIWORD(GetQueueStatus(QS_INPUT
)))
3293 GUITHREADINFO guiInfo
;
3294 guiInfo
.cbSize
= sizeof(GUITHREADINFO
);
3295 if (!GetGUIThreadInfo(GetCurrentThreadId(), &guiInfo
))
3297 return GUI_INMOVESIZE
== (guiInfo
.flags
& GUI_INMOVESIZE
);
3301 /**************************************************************
3303 * SECTION: nsIWidget::GetLayerManager
3305 * Get the layer manager associated with this widget.
3307 **************************************************************/
3309 struct LayerManagerPrefs
{
3311 : mAccelerateByDefault(PR_TRUE
)
3312 , mDisableAcceleration(PR_FALSE
)
3313 , mPreferOpenGL(PR_FALSE
)
3314 , mPreferD3D9(PR_FALSE
)
3316 PRBool mAccelerateByDefault
;
3317 PRBool mDisableAcceleration
;
3318 PRBool mForceAcceleration
;
3319 PRBool mPreferOpenGL
;
3324 GetLayerManagerPrefs(LayerManagerPrefs
* aManagerPrefs
)
3326 nsCOMPtr
<nsIPrefBranch2
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
3328 prefs
->GetBoolPref("layers.acceleration.disabled",
3329 &aManagerPrefs
->mDisableAcceleration
);
3330 prefs
->GetBoolPref("layers.acceleration.force-enabled",
3331 &aManagerPrefs
->mForceAcceleration
);
3332 prefs
->GetBoolPref("layers.prefer-opengl",
3333 &aManagerPrefs
->mPreferOpenGL
);
3334 prefs
->GetBoolPref("layers.prefer-d3d9",
3335 &aManagerPrefs
->mPreferD3D9
);
3338 const char *acceleratedEnv
= PR_GetEnv("MOZ_ACCELERATED");
3339 aManagerPrefs
->mAccelerateByDefault
=
3340 aManagerPrefs
->mAccelerateByDefault
||
3341 (acceleratedEnv
&& (*acceleratedEnv
!= '0'));
3343 PRBool safeMode
= PR_FALSE
;
3344 nsCOMPtr
<nsIXULRuntime
> xr
= do_GetService("@mozilla.org/xre/runtime;1");
3346 xr
->GetInSafeMode(&safeMode
);
3347 aManagerPrefs
->mDisableAcceleration
=
3348 aManagerPrefs
->mDisableAcceleration
|| safeMode
;
3351 mozilla::layers::LayerManager
*
3352 nsWindow::GetLayerManager(LayerManagerPersistence aPersistence
, bool* aAllowRetaining
)
3354 if (aAllowRetaining
) {
3355 *aAllowRetaining
= true;
3359 #ifdef MOZ_ENABLE_D3D10_LAYER
3360 if (mLayerManager
) {
3361 if (mLayerManager
->GetBackendType() ==
3362 mozilla::layers::LayerManager::LAYERS_D3D10
)
3364 mozilla::layers::LayerManagerD3D10
*layerManagerD3D10
=
3365 static_cast<mozilla::layers::LayerManagerD3D10
*>(mLayerManager
.get());
3366 if (layerManagerD3D10
->device() !=
3367 gfxWindowsPlatform::GetPlatform()->GetD3D10Device())
3369 mLayerManager
->Destroy();
3370 mLayerManager
= nsnull
;
3376 if (!mLayerManager
||
3377 (!sAllowD3D9
&& aPersistence
== LAYER_MANAGER_PERSISTENT
&&
3378 mLayerManager
->GetBackendType() ==
3379 mozilla::layers::LayerManager::LAYERS_BASIC
)) {
3380 // If D3D9 is not currently allowed but the permanent manager is required,
3381 // -and- we're currently using basic layers, run through this check.
3382 LayerManagerPrefs prefs
;
3383 GetLayerManagerPrefs(&prefs
);
3385 /* We don't currently support using an accelerated layer manager with
3386 * transparent windows so don't even try. I'm also not sure if we even
3387 * want to support this case. See bug #593471 */
3388 if (eTransparencyTransparent
== mTransparencyMode
||
3389 prefs
.mDisableAcceleration
)
3390 mUseAcceleratedRendering
= PR_FALSE
;
3391 else if (prefs
.mAccelerateByDefault
)
3392 mUseAcceleratedRendering
= PR_TRUE
;
3394 if (mUseAcceleratedRendering
) {
3395 if (aPersistence
== LAYER_MANAGER_PERSISTENT
&& !sAllowD3D9
) {
3396 // This will clear out our existing layer manager if we have one since
3397 // if we hit this with a LayerManager we're always using BasicLayers.
3398 nsToolkit::StartAllowingD3D9();
3401 #ifdef MOZ_ENABLE_D3D10_LAYER
3402 if (!prefs
.mPreferD3D9
) {
3403 nsRefPtr
<mozilla::layers::LayerManagerD3D10
> layerManager
=
3404 new mozilla::layers::LayerManagerD3D10(this);
3405 if (layerManager
->Initialize()) {
3406 mLayerManager
= layerManager
;
3410 #ifdef MOZ_ENABLE_D3D9_LAYER
3411 if (!prefs
.mPreferOpenGL
&& !mLayerManager
&& sAllowD3D9
) {
3412 nsRefPtr
<mozilla::layers::LayerManagerD3D9
> layerManager
=
3413 new mozilla::layers::LayerManagerD3D9(this);
3414 if (layerManager
->Initialize()) {
3415 mLayerManager
= layerManager
;
3419 if (!mLayerManager
&& prefs
.mPreferOpenGL
) {
3420 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= do_GetService("@mozilla.org/gfx/info;1");
3421 PRInt32 status
= nsIGfxInfo::FEATURE_NO_INFO
;
3423 if (gfxInfo
&& !prefs
.mForceAcceleration
) {
3424 gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS
, &status
);
3427 if (status
== nsIGfxInfo::FEATURE_NO_INFO
) {
3428 nsRefPtr
<mozilla::layers::LayerManagerOGL
> layerManager
=
3429 new mozilla::layers::LayerManagerOGL(this);
3430 if (layerManager
->Initialize()) {
3431 mLayerManager
= layerManager
;
3435 NS_WARNING("OpenGL accelerated layers are not supported on this system.");
3440 // Fall back to software if we couldn't use any hardware backends.
3442 mLayerManager
= CreateBasicLayerManager();
3446 return mLayerManager
;
3449 /**************************************************************
3451 * SECTION: nsIWidget::GetThebesSurface
3453 * Get the Thebes surface associated with this widget.
3455 **************************************************************/
3457 gfxASurface
*nsWindow::GetThebesSurface()
3459 #ifdef CAIRO_HAS_D2D_SURFACE
3460 if (mD2DWindowSurface
) {
3461 return mD2DWindowSurface
;
3465 return (new gfxWindowsSurface(mPaintDC
));
3467 #ifdef CAIRO_HAS_D2D_SURFACE
3468 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
3469 gfxWindowsPlatform::RENDER_DIRECT2D
) {
3470 gfxASurface::gfxContentType content
= gfxASurface::CONTENT_COLOR
;
3471 #if defined(MOZ_XUL)
3472 if (mTransparencyMode
!= eTransparencyOpaque
) {
3473 content
= gfxASurface::CONTENT_COLOR_ALPHA
;
3476 return (new gfxD2DSurface(mWnd
, content
));
3479 PRUint32 flags
= gfxWindowsSurface::FLAG_TAKE_DC
;
3480 if (mTransparencyMode
!= eTransparencyOpaque
) {
3481 flags
|= gfxWindowsSurface::FLAG_IS_TRANSPARENT
;
3483 return (new gfxWindowsSurface(mWnd
, flags
));
3484 #ifdef CAIRO_HAS_D2D_SURFACE
3489 /**************************************************************
3491 * SECTION: nsIWidget::OnDefaultButtonLoaded
3493 * Called after the dialog is loaded and it has a default button.
3495 **************************************************************/
3498 nsWindow::OnDefaultButtonLoaded(const nsIntRect
&aButtonRect
)
3501 return NS_ERROR_NOT_IMPLEMENTED
;
3503 if (aButtonRect
.IsEmpty())
3506 // Don't snap when we are not active.
3507 HWND activeWnd
= ::GetActiveWindow();
3508 if (activeWnd
!= ::GetForegroundWindow() ||
3509 GetTopLevelHWND(mWnd
, PR_TRUE
) != GetTopLevelHWND(activeWnd
, PR_TRUE
)) {
3513 PRBool isAlwaysSnapCursor
= PR_FALSE
;
3514 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
3516 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
3517 prefs
->GetBranch(nsnull
, getter_AddRefs(prefBranch
));
3519 prefBranch
->GetBoolPref("ui.cursor_snapping.always_enabled",
3520 &isAlwaysSnapCursor
);
3524 if (!isAlwaysSnapCursor
) {
3525 BOOL snapDefaultButton
;
3526 if (!::SystemParametersInfo(SPI_GETSNAPTODEFBUTTON
, 0,
3527 &snapDefaultButton
, 0) || !snapDefaultButton
)
3531 nsIntRect widgetRect
;
3532 nsresult rv
= GetScreenBounds(widgetRect
);
3533 NS_ENSURE_SUCCESS(rv
, rv
);
3534 nsIntRect
buttonRect(aButtonRect
+ widgetRect
.TopLeft());
3536 nsIntPoint
centerOfButton(buttonRect
.x
+ buttonRect
.width
/ 2,
3537 buttonRect
.y
+ buttonRect
.height
/ 2);
3538 // The center of the button can be outside of the widget.
3539 // E.g., it could be hidden by scrolling.
3540 if (!widgetRect
.Contains(centerOfButton
)) {
3544 if (!::SetCursorPos(centerOfButton
.x
, centerOfButton
.y
)) {
3545 NS_ERROR("SetCursorPos failed");
3546 return NS_ERROR_FAILURE
;
3553 nsWindow::OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta
,
3554 PRBool aIsHorizontal
,
3555 PRInt32
&aOverriddenDelta
)
3557 // The default vertical and horizontal scrolling speed is 3, this is defined
3558 // on the document of SystemParametersInfo in MSDN.
3559 const PRUint32 kSystemDefaultScrollingSpeed
= 3;
3561 PRInt32 absOriginDelta
= PR_ABS(aOriginalDelta
);
3563 // Compute the simple overridden speed.
3564 PRInt32 absComputedOverriddenDelta
;
3566 nsBaseWidget::OverrideSystemMouseScrollSpeed(absOriginDelta
, aIsHorizontal
,
3567 absComputedOverriddenDelta
);
3568 NS_ENSURE_SUCCESS(rv
, rv
);
3570 aOverriddenDelta
= aOriginalDelta
;
3572 if (absComputedOverriddenDelta
== absOriginDelta
) {
3573 // We don't override now.
3577 // Otherwise, we should check whether the user customized the system settings
3578 // or not. If the user did it, we should respect the will.
3580 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, &systemSpeed
, 0)) {
3581 return NS_ERROR_FAILURE
;
3583 // The default vertical scrolling speed is 3, this is defined on the document
3584 // of SystemParametersInfo in MSDN.
3585 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
3589 // Only Vista and later, Windows has the system setting of horizontal
3590 // scrolling by the mouse wheel.
3591 if (GetWindowsVersion() >= VISTA_VERSION
) {
3592 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0, &systemSpeed
, 0)) {
3593 return NS_ERROR_FAILURE
;
3595 // The default horizontal scrolling speed is 3, this is defined on the
3596 // document of SystemParametersInfo in MSDN.
3597 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
3602 // Limit the overridden delta value from the system settings. The mouse
3603 // driver might accelerate the scrolling speed already. If so, we shouldn't
3604 // override the scrolling speed for preventing the unexpected high speed
3606 PRInt32 absDeltaLimit
;
3608 nsBaseWidget::OverrideSystemMouseScrollSpeed(kSystemDefaultScrollingSpeed
,
3609 aIsHorizontal
, absDeltaLimit
);
3610 NS_ENSURE_SUCCESS(rv
, rv
);
3612 // If the given delta is larger than our computed limitation value, the delta
3613 // was accelerated by the mouse driver. So, we should do nothing here.
3614 if (absDeltaLimit
<= absOriginDelta
) {
3618 absComputedOverriddenDelta
=
3619 PR_MIN(absComputedOverriddenDelta
, absDeltaLimit
);
3621 aOverriddenDelta
= (aOriginalDelta
> 0) ? absComputedOverriddenDelta
:
3622 -absComputedOverriddenDelta
;
3626 /**************************************************************
3627 **************************************************************
3629 ** BLOCK: Moz Events
3631 ** Moz GUI event management.
3633 **************************************************************
3634 **************************************************************/
3636 /**************************************************************
3638 * SECTION: Mozilla event initialization
3640 * Helpers for initializing moz events.
3642 **************************************************************/
3644 // Event intialization
3645 MSG
nsWindow::InitMSG(UINT aMessage
, WPARAM wParam
, LPARAM lParam
)
3648 msg
.message
= aMessage
;
3649 msg
.wParam
= wParam
;
3650 msg
.lParam
= lParam
;
3654 void nsWindow::InitEvent(nsGUIEvent
& event
, nsIntPoint
* aPoint
)
3656 if (nsnull
== aPoint
) { // use the point from the event
3657 // get the message position in client coordinates
3660 DWORD pos
= ::GetMessagePos();
3663 cpos
.x
= GET_X_LPARAM(pos
);
3664 cpos
.y
= GET_Y_LPARAM(pos
);
3666 ::ScreenToClient(mWnd
, &cpos
);
3667 event
.refPoint
.x
= cpos
.x
;
3668 event
.refPoint
.y
= cpos
.y
;
3670 event
.refPoint
.x
= 0;
3671 event
.refPoint
.y
= 0;
3675 // use the point override if provided
3676 event
.refPoint
.x
= aPoint
->x
;
3677 event
.refPoint
.y
= aPoint
->y
;
3681 event
.time
= ::GetMessageTime();
3683 event
.time
= PR_Now() / 1000;
3686 mLastPoint
= event
.refPoint
;
3689 /**************************************************************
3691 * SECTION: Moz event dispatch helpers
3693 * Helpers for dispatching different types of moz events.
3695 **************************************************************/
3697 // Main event dispatch. Invokes callback and ProcessEvent method on
3698 // Event Listener object. Part of nsIWidget.
3699 NS_IMETHODIMP
nsWindow::DispatchEvent(nsGUIEvent
* event
, nsEventStatus
& aStatus
)
3701 #ifdef WIDGET_DEBUG_OUTPUT
3702 debug_DumpEvent(stdout
,
3705 nsCAutoString("something"),
3707 #endif // WIDGET_DEBUG_OUTPUT
3709 aStatus
= nsEventStatus_eIgnore
;
3711 // skip processing of suppressed blur events
3712 if (event
->message
== NS_DEACTIVATE
&& BlurEventsSuppressed())
3715 // Top level windows can have a view attached which requires events be sent
3716 // to the underlying base window and the view. Added when we combined the
3717 // base chrome window with the main content child for nc client area (title
3719 if (mViewCallback
) {
3720 // A subset of events are sent to the base xul window first
3721 switch(event
->message
) {
3722 // send to the base window (view mgr ignores these for the view)
3723 case NS_UISTATECHANGED
:
3728 (*mEventCallback
)(event
); // web shell / xul window
3731 // sent to the base window, then to the view
3736 (*mEventCallback
)(event
); // web shell / xul window
3739 // attached view events
3740 aStatus
= (*mViewCallback
)(event
);
3742 else if (mEventCallback
) {
3743 aStatus
= (*mEventCallback
)(event
);
3746 // the window can be destroyed during processing of seemingly innocuous events like, say,
3747 // mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
3748 // which causes problems with the deleted window. therefore:
3749 if (mOnDestroyCalled
)
3750 aStatus
= nsEventStatus_eConsumeNoDefault
;
3754 PRBool
nsWindow::DispatchStandardEvent(PRUint32 aMsg
)
3756 nsGUIEvent
event(PR_TRUE
, aMsg
, this);
3759 PRBool result
= DispatchWindowEvent(&event
);
3763 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
)
3765 nsEventStatus status
;
3766 DispatchEvent(event
, status
);
3767 return ConvertStatus(status
);
3770 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
, nsEventStatus
&aStatus
) {
3771 DispatchEvent(event
, aStatus
);
3772 return ConvertStatus(aStatus
);
3775 PRBool
nsWindow::DispatchKeyEvent(PRUint32 aEventType
, WORD aCharCode
,
3776 const nsTArray
<nsAlternativeCharCode
>* aAlternativeCharCodes
,
3777 UINT aVirtualCharCode
, const MSG
*aMsg
,
3778 const nsModifierKeyState
&aModKeyState
,
3783 nsKeyEvent
event(PR_TRUE
, aEventType
, this);
3784 nsIntPoint
point(0, 0);
3786 InitEvent(event
, &point
); // this add ref's event.widget
3788 event
.flags
|= aFlags
;
3789 event
.charCode
= aCharCode
;
3790 if (aAlternativeCharCodes
)
3791 event
.alternativeCharCodes
.AppendElements(*aAlternativeCharCodes
);
3792 event
.keyCode
= aVirtualCharCode
;
3796 printf("%d DispatchKE Type: %s charCode %d keyCode %d ", cnt
++,
3797 (NS_KEY_PRESS
== aEventType
) ? "PRESS" : (aEventType
== NS_KEY_UP
? "Up" : "Down"),
3798 event
.charCode
, event
.keyCode
);
3799 printf("Shift: %s Control %s Alt: %s \n",
3800 (mIsShiftDown
? "D" : "U"), (mIsControlDown
? "D" : "U"), (mIsAltDown
? "D" : "U"));
3801 printf("[%c][%c][%c] <== [%c][%c][%c][ space bar ][%c][%c][%c]\n",
3802 IS_VK_DOWN(NS_VK_SHIFT
) ? 'S' : ' ',
3803 IS_VK_DOWN(NS_VK_CONTROL
) ? 'C' : ' ',
3804 IS_VK_DOWN(NS_VK_ALT
) ? 'A' : ' ',
3805 IS_VK_DOWN(VK_LSHIFT
) ? 'S' : ' ',
3806 IS_VK_DOWN(VK_LCONTROL
) ? 'C' : ' ',
3807 IS_VK_DOWN(VK_LMENU
) ? 'A' : ' ',
3808 IS_VK_DOWN(VK_RMENU
) ? 'A' : ' ',
3809 IS_VK_DOWN(VK_RCONTROL
) ? 'C' : ' ',
3810 IS_VK_DOWN(VK_RSHIFT
) ? 'S' : ' ');
3813 event
.isShift
= aModKeyState
.mIsShiftDown
;
3814 event
.isControl
= aModKeyState
.mIsControlDown
;
3815 event
.isMeta
= PR_FALSE
;
3816 event
.isAlt
= aModKeyState
.mIsAltDown
;
3818 NPEvent pluginEvent
;
3819 if (aMsg
&& PluginHasFocus()) {
3820 pluginEvent
.event
= aMsg
->message
;
3821 pluginEvent
.wParam
= aMsg
->wParam
;
3822 pluginEvent
.lParam
= aMsg
->lParam
;
3823 event
.pluginEvent
= (void *)&pluginEvent
;
3826 PRBool result
= DispatchWindowEvent(&event
);
3831 PRBool
nsWindow::DispatchCommandEvent(PRUint32 aEventCommand
)
3833 nsCOMPtr
<nsIAtom
> command
;
3834 switch (aEventCommand
) {
3835 case APPCOMMAND_BROWSER_BACKWARD
:
3836 command
= nsWidgetAtoms::Back
;
3838 case APPCOMMAND_BROWSER_FORWARD
:
3839 command
= nsWidgetAtoms::Forward
;
3841 case APPCOMMAND_BROWSER_REFRESH
:
3842 command
= nsWidgetAtoms::Reload
;
3844 case APPCOMMAND_BROWSER_STOP
:
3845 command
= nsWidgetAtoms::Stop
;
3847 case APPCOMMAND_BROWSER_SEARCH
:
3848 command
= nsWidgetAtoms::Search
;
3850 case APPCOMMAND_BROWSER_FAVORITES
:
3851 command
= nsWidgetAtoms::Bookmarks
;
3853 case APPCOMMAND_BROWSER_HOME
:
3854 command
= nsWidgetAtoms::Home
;
3859 nsCommandEvent
event(PR_TRUE
, nsWidgetAtoms::onAppCommand
, command
, this);
3862 DispatchWindowEvent(&event
);
3867 // Recursively dispatch synchronous paints for nsIWidget
3868 // descendants with invalidated rectangles.
3869 BOOL CALLBACK
nsWindow::DispatchStarvedPaints(HWND aWnd
, LPARAM aMsg
)
3871 LONG_PTR proc
= ::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
3872 if (proc
== (LONG_PTR
)&nsWindow::WindowProc
) {
3873 // its one of our windows so check to see if it has a
3874 // invalidated rect. If it does. Dispatch a synchronous
3876 if (GetUpdateRect(aWnd
, NULL
, FALSE
))
3877 VERIFY(::UpdateWindow(aWnd
));
3882 // Check for pending paints and dispatch any pending paint
3883 // messages for any nsIWidget which is a descendant of the
3884 // top-level window that *this* window is embedded within.
3886 // Note: We do not dispatch pending paint messages for non
3887 // nsIWidget managed windows.
3888 void nsWindow::DispatchPendingEvents()
3891 NS_WARNING("We were asked to dispatch pending events during painting, "
3892 "denying since that's unsafe.");
3896 // We need to ensure that reflow events do not get starved.
3897 // At the same time, we don't want to recurse through here
3898 // as that would prevent us from dispatching starved paints.
3899 static int recursionBlocker
= 0;
3900 if (recursionBlocker
++ == 0) {
3901 NS_ProcessPendingEvents(nsnull
, PR_MillisecondsToInterval(100));
3905 // Quickly check to see if there are any paint events pending,
3906 // but only dispatch them if it has been long enough since the
3907 // last paint completed.
3908 if (::GetQueueStatus(QS_PAINT
) &&
3909 (mLastPaintEndTime
.IsNull() ||
3910 (TimeStamp::Now() - mLastPaintEndTime
).ToMilliseconds() >= 50)) {
3911 // Find the top level window.
3912 HWND topWnd
= GetTopLevelHWND(mWnd
);
3914 // Dispatch pending paints for topWnd and all its descendant windows.
3915 // Note: EnumChildWindows enumerates all descendant windows not just
3916 // the children (but not the window itself).
3917 nsWindow::DispatchStarvedPaints(topWnd
, 0);
3919 ::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, 0);
3921 nsWindowCE::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, NULL
);
3926 // Deal with plugin events
3927 PRBool
nsWindow::DispatchPluginEvent(const MSG
&aMsg
)
3929 if (!PluginHasFocus())
3932 nsGUIEvent
event(PR_TRUE
, NS_PLUGIN_EVENT
, this);
3933 nsIntPoint
point(0, 0);
3934 InitEvent(event
, &point
);
3935 NPEvent pluginEvent
;
3936 pluginEvent
.event
= aMsg
.message
;
3937 pluginEvent
.wParam
= aMsg
.wParam
;
3938 pluginEvent
.lParam
= aMsg
.lParam
;
3939 event
.pluginEvent
= (void *)&pluginEvent
;
3940 return DispatchWindowEvent(&event
);
3943 PRBool
nsWindow::DispatchPluginEvent(UINT aMessage
,
3946 PRBool aDispatchPendingEvents
)
3948 PRBool ret
= DispatchPluginEvent(InitMSG(aMessage
, aWParam
, aLParam
));
3949 if (aDispatchPendingEvents
) {
3950 DispatchPendingEvents();
3955 void nsWindow::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg
,
3959 ::GetMessageW(&msg
, mWnd
, aFirstMsg
, aLastMsg
);
3960 DispatchPluginEvent(msg
);
3963 // Deal with all sort of mouse event
3964 PRBool
nsWindow::DispatchMouseEvent(PRUint32 aEventType
, WPARAM wParam
,
3965 LPARAM lParam
, PRBool aIsContextMenuKey
,
3966 PRInt16 aButton
, PRUint16 aInputSource
)
3968 PRBool result
= PR_FALSE
;
3972 if (!mEventCallback
) {
3976 switch (aEventType
) {
3977 case NS_MOUSE_BUTTON_DOWN
:
3978 CaptureMouse(PR_TRUE
);
3981 // NS_MOUSE_MOVE and NS_MOUSE_EXIT are here because we need to make sure capture flag
3982 // isn't left on after a drag where we wouldn't see a button up message (see bug 324131).
3983 case NS_MOUSE_BUTTON_UP
:
3986 if (!(wParam
& (MK_LBUTTON
| MK_MBUTTON
| MK_RBUTTON
)) && sIsInMouseCapture
)
3987 CaptureMouse(PR_FALSE
);
3995 nsIntPoint eventPoint
;
3996 eventPoint
.x
= GET_X_LPARAM(lParam
);
3997 eventPoint
.y
= GET_Y_LPARAM(lParam
);
3999 nsMouseEvent
event(PR_TRUE
, aEventType
, this, nsMouseEvent::eReal
,
4001 ? nsMouseEvent::eContextMenuKey
4002 : nsMouseEvent::eNormal
);
4003 if (aEventType
== NS_CONTEXTMENU
&& aIsContextMenuKey
) {
4004 nsIntPoint
zero(0, 0);
4005 InitEvent(event
, &zero
);
4007 InitEvent(event
, &eventPoint
);
4010 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
4011 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
4012 event
.isMeta
= PR_FALSE
;
4013 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
4014 event
.button
= aButton
;
4015 event
.inputSource
= aInputSource
;
4017 nsIntPoint mpScreen
= eventPoint
+ WidgetToScreenOffset();
4019 // Suppress mouse moves caused by widget creation
4020 if (aEventType
== NS_MOUSE_MOVE
)
4022 if ((sLastMouseMovePoint
.x
== mpScreen
.x
) && (sLastMouseMovePoint
.y
== mpScreen
.y
))
4024 sLastMouseMovePoint
.x
= mpScreen
.x
;
4025 sLastMouseMovePoint
.y
= mpScreen
.y
;
4028 PRBool insideMovementThreshold
= (abs(sLastMousePoint
.x
- eventPoint
.x
) < (short)::GetSystemMetrics(SM_CXDOUBLECLK
)) &&
4029 (abs(sLastMousePoint
.y
- eventPoint
.y
) < (short)::GetSystemMetrics(SM_CYDOUBLECLK
));
4033 case nsMouseEvent::eLeftButton
:
4034 eventButton
= VK_LBUTTON
;
4036 case nsMouseEvent::eMiddleButton
:
4037 eventButton
= VK_MBUTTON
;
4039 case nsMouseEvent::eRightButton
:
4040 eventButton
= VK_RBUTTON
;
4047 // Doubleclicks are used to set the click count, then changed to mousedowns
4048 // We're going to time double-clicks from mouse *up* to next mouse *down*
4050 LONG curMsgTime
= ::GetMessageTime();
4052 LONG curMsgTime
= PR_Now() / 1000;
4055 if (aEventType
== NS_MOUSE_DOUBLECLICK
) {
4056 event
.message
= NS_MOUSE_BUTTON_DOWN
;
4057 event
.button
= aButton
;
4058 sLastClickCount
= 2;
4060 else if (aEventType
== NS_MOUSE_BUTTON_UP
) {
4061 // remember when this happened for the next mouse down
4062 sLastMousePoint
.x
= eventPoint
.x
;
4063 sLastMousePoint
.y
= eventPoint
.y
;
4064 sLastMouseButton
= eventButton
;
4066 else if (aEventType
== NS_MOUSE_BUTTON_DOWN
) {
4067 // now look to see if we want to convert this to a double- or triple-click
4068 if (((curMsgTime
- sLastMouseDownTime
) < (LONG
)::GetDoubleClickTime()) && insideMovementThreshold
&&
4069 eventButton
== sLastMouseButton
) {
4072 // reset the click count, to count *this* click
4073 sLastClickCount
= 1;
4075 // Set last Click time on MouseDown only
4076 sLastMouseDownTime
= curMsgTime
;
4078 else if (aEventType
== NS_MOUSE_MOVE
&& !insideMovementThreshold
) {
4079 sLastClickCount
= 0;
4081 else if (aEventType
== NS_MOUSE_EXIT
) {
4082 event
.exit
= IsTopLevelMouseExit(mWnd
) ? nsMouseEvent::eTopLevel
: nsMouseEvent::eChild
;
4084 else if (aEventType
== NS_MOUSE_MOZHITTEST
)
4086 event
.flags
|= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH
;
4088 event
.clickCount
= sLastClickCount
;
4091 printf("Msg Time: %d Click Count: %d\n", curMsgTime
, event
.clickCount
);
4094 NPEvent pluginEvent
;
4098 case NS_MOUSE_BUTTON_DOWN
:
4100 case nsMouseEvent::eLeftButton
:
4101 pluginEvent
.event
= WM_LBUTTONDOWN
;
4103 case nsMouseEvent::eMiddleButton
:
4104 pluginEvent
.event
= WM_MBUTTONDOWN
;
4106 case nsMouseEvent::eRightButton
:
4107 pluginEvent
.event
= WM_RBUTTONDOWN
;
4113 case NS_MOUSE_BUTTON_UP
:
4115 case nsMouseEvent::eLeftButton
:
4116 pluginEvent
.event
= WM_LBUTTONUP
;
4118 case nsMouseEvent::eMiddleButton
:
4119 pluginEvent
.event
= WM_MBUTTONUP
;
4121 case nsMouseEvent::eRightButton
:
4122 pluginEvent
.event
= WM_RBUTTONUP
;
4128 case NS_MOUSE_DOUBLECLICK
:
4130 case nsMouseEvent::eLeftButton
:
4131 pluginEvent
.event
= WM_LBUTTONDBLCLK
;
4133 case nsMouseEvent::eMiddleButton
:
4134 pluginEvent
.event
= WM_MBUTTONDBLCLK
;
4136 case nsMouseEvent::eRightButton
:
4137 pluginEvent
.event
= WM_RBUTTONDBLCLK
;
4144 pluginEvent
.event
= WM_MOUSEMOVE
;
4147 pluginEvent
.event
= WM_MOUSELEAVE
;
4150 pluginEvent
.event
= WM_NULL
;
4154 pluginEvent
.wParam
= wParam
; // plugins NEED raw OS event flags!
4155 pluginEvent
.lParam
= lParam
;
4157 event
.pluginEvent
= (void *)&pluginEvent
;
4159 // call the event callback
4160 if (nsnull
!= mEventCallback
) {
4161 if (nsToolkit::gMouseTrailer
)
4162 nsToolkit::gMouseTrailer
->Disable();
4163 if (aEventType
== NS_MOUSE_MOVE
) {
4164 if (nsToolkit::gMouseTrailer
&& !sIsInMouseCapture
) {
4165 nsToolkit::gMouseTrailer
->SetMouseTrailerWindow(mWnd
);
4172 if (rect
.Contains(event
.refPoint
)) {
4173 if (sCurrentWindow
== NULL
|| sCurrentWindow
!= this) {
4174 if ((nsnull
!= sCurrentWindow
) && (!sCurrentWindow
->mInDtor
)) {
4175 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
4176 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_EXIT
, wParam
, pos
, PR_FALSE
,
4177 nsMouseEvent::eLeftButton
, aInputSource
);
4179 sCurrentWindow
= this;
4181 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
4182 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_ENTER
, wParam
, pos
, PR_FALSE
,
4183 nsMouseEvent::eLeftButton
, aInputSource
);
4187 } else if (aEventType
== NS_MOUSE_EXIT
) {
4188 if (sCurrentWindow
== this) {
4189 sCurrentWindow
= nsnull
;
4193 result
= DispatchWindowEvent(&event
);
4195 if (nsToolkit::gMouseTrailer
)
4196 nsToolkit::gMouseTrailer
->Enable();
4198 // Release the widget with NS_IF_RELEASE() just in case
4199 // the context menu key code in nsEventListenerManager::HandleEvent()
4200 // released it already.
4207 // Deal with accessibile event
4208 #ifdef ACCESSIBILITY
4210 nsWindow::DispatchAccessibleEvent(PRUint32 aEventType
)
4212 if (nsnull
== mEventCallback
) {
4216 nsAccessibleEvent
event(PR_TRUE
, aEventType
, this);
4217 InitEvent(event
, nsnull
);
4219 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
4220 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
4221 event
.isMeta
= PR_FALSE
;
4222 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
4224 DispatchWindowEvent(&event
);
4226 return event
.mAccessible
;
4230 PRBool
nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType
)
4232 if (aEventType
== NS_ACTIVATE
)
4233 sJustGotActivate
= PR_FALSE
;
4234 sJustGotDeactivate
= PR_FALSE
;
4236 // retrive the toplevel window or dialog
4238 HWND toplevelWnd
= NULL
;
4240 toplevelWnd
= curWnd
;
4242 nsWindow
*win
= GetNSWindowPtr(curWnd
);
4244 nsWindowType wintype
;
4245 win
->GetWindowType(wintype
);
4246 if (wintype
== eWindowType_toplevel
|| wintype
== eWindowType_dialog
)
4250 curWnd
= ::GetParent(curWnd
); // Parent or owner (if has no parent)
4254 nsWindow
*win
= GetNSWindowPtr(toplevelWnd
);
4256 return win
->DispatchFocus(aEventType
);
4262 // Deal with focus messages
4263 PRBool
nsWindow::DispatchFocus(PRUint32 aEventType
)
4265 // call the event callback
4266 if (mEventCallback
) {
4267 nsGUIEvent
event(PR_TRUE
, aEventType
, this);
4270 //focus and blur event should go to their base widget loc, not current mouse pos
4271 event
.refPoint
.x
= 0;
4272 event
.refPoint
.y
= 0;
4274 NPEvent pluginEvent
;
4279 pluginEvent
.event
= WM_SETFOCUS
;
4282 pluginEvent
.event
= WM_KILLFOCUS
;
4284 case NS_PLUGIN_ACTIVATE
:
4285 pluginEvent
.event
= WM_KILLFOCUS
;
4291 event
.pluginEvent
= (void *)&pluginEvent
;
4293 return DispatchWindowEvent(&event
);
4298 PRBool
nsWindow::IsTopLevelMouseExit(HWND aWnd
)
4300 DWORD pos
= ::GetMessagePos();
4302 mp
.x
= GET_X_LPARAM(pos
);
4303 mp
.y
= GET_Y_LPARAM(pos
);
4304 HWND mouseWnd
= ::WindowFromPoint(mp
);
4306 // GetTopLevelHWND will return a HWND for the window frame (which includes
4307 // the non-client area). If the mouse has moved into the non-client area,
4308 // we should treat it as a top-level exit.
4309 HWND mouseTopLevel
= nsWindow::GetTopLevelHWND(mouseWnd
);
4310 if (mouseWnd
== mouseTopLevel
)
4313 return nsWindow::GetTopLevelHWND(aWnd
) != mouseTopLevel
;
4316 PRBool
nsWindow::BlurEventsSuppressed()
4318 // are they suppressed in this window?
4319 if (mBlurSuppressLevel
> 0)
4322 // are they suppressed by any container widget?
4323 HWND parentWnd
= ::GetParent(mWnd
);
4325 nsWindow
*parent
= GetNSWindowPtr(parentWnd
);
4327 return parent
->BlurEventsSuppressed();
4332 // In some circumstances (opening dependent windows) it makes more sense
4333 // (and fixes a crash bug) to not blur the parent window. Called from
4335 void nsWindow::SuppressBlurEvents(PRBool aSuppress
)
4338 ++mBlurSuppressLevel
; // for this widget
4340 NS_ASSERTION(mBlurSuppressLevel
> 0, "unbalanced blur event suppression");
4341 if (mBlurSuppressLevel
> 0)
4342 --mBlurSuppressLevel
;
4346 PRBool
nsWindow::ConvertStatus(nsEventStatus aStatus
)
4348 return aStatus
== nsEventStatus_eConsumeNoDefault
;
4351 /**************************************************************
4355 * IPC related helpers.
4357 **************************************************************/
4363 nsWindow::IsAsyncResponseEvent(UINT aMsg
, LRESULT
& aResult
)
4369 case WM_WINDOWPOSCHANGING
:
4370 case WM_WINDOWPOSCHANGED
:
4371 case WM_PARENTNOTIFY
:
4372 case WM_ACTIVATEAPP
:
4375 case WM_CHILDACTIVATE
:
4376 case WM_IME_SETCONTEXT
:
4380 case WM_MOUSEACTIVATE
:
4381 case WM_CONTEXTMENU
:
4385 case WM_SETTINGCHANGE
:
4393 "An unhandled ISMEX_SEND message was received during spin loop! (%X)", aMsg
);
4401 nsWindow::IPCWindowProcHandler(UINT
& msg
, WPARAM
& wParam
, LPARAM
& lParam
)
4403 NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
4404 "Failed to prevent a nonqueued message from running!");
4406 // Modal UI being displayed in windowless plugins.
4407 if (mozilla::ipc::RPCChannel::IsSpinLoopActive() &&
4408 (InSendMessageEx(NULL
)&(ISMEX_REPLIED
|ISMEX_SEND
)) == ISMEX_SEND
) {
4410 if (IsAsyncResponseEvent(msg
, res
)) {
4416 // Handle certain sync plugin events sent to the parent which
4417 // trigger ipc calls that result in deadlocks.
4420 PRBool handled
= PR_FALSE
;
4423 // Windowless flash sending WM_ACTIVATE events to the main window
4424 // via calls to ShowWindow.
4426 if (lParam
!= 0 && LOWORD(wParam
) == WA_ACTIVE
&&
4427 IsWindow((HWND
)lParam
))
4430 // Wheel events forwarded from the child.
4432 case WM_MOUSEHWHEEL
:
4435 // Plugins taking or losing focus triggering focus app messages.
4438 // Windowed plugins that pass sys key events to defwndproc generate
4439 // WM_SYSCOMMAND events to the main window.
4441 // Windowed plugins that fire context menu selection events to parent
4443 case WM_CONTEXTMENU
:
4444 // IME events fired as a result of synchronous focus changes
4445 case WM_IME_SETCONTEXT
:
4451 (InSendMessageEx(NULL
)&(ISMEX_REPLIED
|ISMEX_SEND
)) == ISMEX_SEND
) {
4452 ReplyMessage(dwResult
);
4458 /**************************************************************
4459 **************************************************************
4461 ** BLOCK: Native events
4463 ** Main Windows message handlers and OnXXX handlers for
4464 ** Windows event handling.
4466 **************************************************************
4467 **************************************************************/
4469 /**************************************************************
4471 * SECTION: Wind proc.
4473 * The main Windows event procedures and associated
4474 * message processing methods.
4476 **************************************************************/
4479 static int ReportException(EXCEPTION_POINTERS
*aExceptionInfo
)
4481 #ifdef MOZ_CRASHREPORTER
4482 nsCOMPtr
<nsICrashReporter
> cr
=
4483 do_GetService("@mozilla.org/toolkit/crash-reporter;1");
4485 cr
->WriteMinidumpForException(aExceptionInfo
);
4487 return EXCEPTION_EXECUTE_HANDLER
;
4492 DisplaySystemMenu(HWND hWnd
, nsSizeMode sizeMode
, PRBool isRtl
, PRInt32 x
, PRInt32 y
)
4494 GetSystemMenu(hWnd
, TRUE
); // reset the system menu
4495 HMENU hMenu
= GetSystemMenu(hWnd
, FALSE
);
4497 // update the options
4499 case nsSizeMode_Fullscreen
:
4500 EnableMenuItem(hMenu
, SC_RESTORE
, MF_BYCOMMAND
| MF_GRAYED
);
4501 // intentional fall through
4502 case nsSizeMode_Maximized
:
4503 EnableMenuItem(hMenu
, SC_SIZE
, MF_BYCOMMAND
| MF_GRAYED
);
4504 EnableMenuItem(hMenu
, SC_MOVE
, MF_BYCOMMAND
| MF_GRAYED
);
4505 EnableMenuItem(hMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
| MF_GRAYED
);
4507 case nsSizeMode_Minimized
:
4508 EnableMenuItem(hMenu
, SC_MINIMIZE
, MF_BYCOMMAND
| MF_GRAYED
);
4510 case nsSizeMode_Normal
:
4511 EnableMenuItem(hMenu
, SC_RESTORE
, MF_BYCOMMAND
| MF_GRAYED
);
4515 TrackPopupMenu(hMenu
,
4516 (TPM_LEFTBUTTON
|TPM_RIGHTBUTTON
|
4517 TPM_RETURNCMD
|TPM_TOPALIGN
|
4518 (isRtl
? TPM_RIGHTALIGN
: TPM_LEFTALIGN
)),
4519 x
, y
, 0, hWnd
, NULL
);
4521 PostMessage(hWnd
, WM_SYSCOMMAND
, cmd
, 0);
4528 // The WndProc procedure for all nsWindows in this toolkit. This merely catches
4529 // exceptions and passes the real work to WindowProcInternal. See bug 587406
4530 // and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx
4531 LRESULT CALLBACK
nsWindow::WindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
4535 return WindowProcInternal(hWnd
, msg
, wParam
, lParam
);
4537 __except(ReportException(GetExceptionInformation())) {
4538 ::TerminateProcess(::GetCurrentProcess(), 253);
4541 return WindowProcInternal(hWnd
, msg
, wParam
, lParam
);
4545 LRESULT CALLBACK
nsWindow::WindowProcInternal(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
4547 NS_TIME_FUNCTION_MIN_FMT(5.0, "%s (line %d) (hWnd: %p, msg: %p, wParam: %p, lParam: %p",
4548 MOZ_FUNCTION_NAME
, __LINE__
, hWnd
, msg
,
4551 if (::GetWindowLongPtrW(hWnd
, GWLP_ID
) == eFakeTrackPointScrollableID
) {
4552 // This message was sent to the FAKETRACKPOINTSCROLLABLE.
4553 if (msg
== WM_HSCROLL
) {
4554 // Route WM_HSCROLL messages to the main window.
4555 hWnd
= ::GetParent(::GetParent(hWnd
));
4557 // Handle all other messages with its original window procedure.
4558 WNDPROC prevWindowProc
= (WNDPROC
)::GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
4559 return ::CallWindowProcW(prevWindowProc
, hWnd
, msg
, wParam
, lParam
);
4563 // Get the window which caused the event and ask it to process the message
4564 nsWindow
*someWindow
= GetNSWindowPtr(hWnd
);
4568 someWindow
->IPCWindowProcHandler(msg
, wParam
, lParam
);
4571 // create this here so that we store the last rolled up popup until after
4572 // the event has been processed.
4573 nsAutoRollup autoRollup
;
4575 LRESULT popupHandlingResult
;
4576 if (DealWithPopups(hWnd
, msg
, wParam
, lParam
, &popupHandlingResult
))
4577 return popupHandlingResult
;
4579 // XXX This fixes 50208 and we are leaving 51174 open to further investigate
4580 // why we are hitting this assert
4581 if (nsnull
== someWindow
) {
4582 NS_ASSERTION(someWindow
, "someWindow is null, cannot call any CallWindowProc");
4583 return ::DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
4586 // hold on to the window for the life of this method, in case it gets
4587 // deleted during processing. yes, it's a double hack, since someWindow
4588 // is not really an interface.
4589 nsCOMPtr
<nsISupports
> kungFuDeathGrip
;
4590 if (!someWindow
->mInDtor
) // not if we're in the destructor!
4591 kungFuDeathGrip
= do_QueryInterface((nsBaseWidget
*)someWindow
);
4593 // Call ProcessMessage
4595 if (PR_TRUE
== someWindow
->ProcessMessage(msg
, wParam
, lParam
, &retValue
)) {
4599 LRESULT res
= ::CallWindowProcW(someWindow
->GetPrevWindowProc(),
4600 hWnd
, msg
, wParam
, lParam
);
4605 // The main windows message processing method for plugins.
4606 // The result means whether this method processed the native
4607 // event for plugin. If false, the native event should be
4608 // processed by the caller self.
4610 nsWindow::ProcessMessageForPlugin(const MSG
&aMsg
,
4612 PRBool
&aCallDefWndProc
)
4614 NS_PRECONDITION(aResult
, "aResult must be non-null.");
4617 aCallDefWndProc
= PR_FALSE
;
4618 PRBool eventDispatched
= PR_FALSE
;
4619 switch (aMsg
.message
) {
4622 *aResult
= ProcessCharMessage(aMsg
, &eventDispatched
);
4627 *aResult
= ProcessKeyUpMessage(aMsg
, &eventDispatched
);
4632 *aResult
= ProcessKeyDownMessage(aMsg
, &eventDispatched
);
4636 case WM_SYSDEADCHAR
:
4649 if (!eventDispatched
)
4650 aCallDefWndProc
= !DispatchPluginEvent(aMsg
);
4651 DispatchPendingEvents();
4655 // The main windows message processing method.
4656 PRBool
nsWindow::ProcessMessage(UINT msg
, WPARAM
&wParam
, LPARAM
&lParam
,
4659 // (Large blocks of code should be broken out into OnEvent handlers.)
4660 if (mWindowHook
.Notify(mWnd
, msg
, wParam
, lParam
, aRetValue
))
4663 #if defined(EVENT_DEBUG_OUTPUT)
4664 // First param shows all events, second param indicates whether
4665 // to show mouse move events. See nsWindowDbg for details.
4666 PrintEvent(msg
, SHOW_REPEAT_EVENTS
, SHOW_MOUSEMOVE_EVENTS
);
4670 if (nsIMM32Handler::ProcessMessage(this, msg
, wParam
, lParam
, aRetValue
,
4672 return mWnd
? eatMessage
: PR_TRUE
;
4675 if (PluginHasFocus()) {
4676 PRBool callDefaultWndProc
;
4677 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
4678 if (ProcessMessageForPlugin(nativeMsg
, aRetValue
, callDefaultWndProc
)) {
4679 return mWnd
? !callDefaultWndProc
: PR_TRUE
;
4683 PRBool result
= PR_FALSE
; // call the default nsWindow proc
4686 static PRBool getWheelInfo
= PR_TRUE
;
4688 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4689 // Glass hit testing w/custom transparent margins
4690 LRESULT dwmHitResult
;
4691 if (mCustomNonClient
&&
4692 nsUXThemeData::CheckForCompositor() &&
4693 nsUXThemeData::dwmDwmDefWindowProcPtr(mWnd
, msg
, wParam
, lParam
, &dwmHitResult
)) {
4694 *aRetValue
= dwmHitResult
;
4697 #endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4701 // WM_QUERYENDSESSION must be handled by all windows.
4702 // Otherwise Windows thinks the window can just be killed at will.
4703 case WM_QUERYENDSESSION
:
4704 if (sCanQuit
== TRI_UNKNOWN
)
4706 // Ask if it's ok to quit, and store the answer until we
4707 // get WM_ENDSESSION signaling the round is complete.
4708 nsCOMPtr
<nsIObserverService
> obsServ
=
4709 mozilla::services::GetObserverService();
4710 nsCOMPtr
<nsISupportsPRBool
> cancelQuit
=
4711 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID
);
4712 cancelQuit
->SetData(PR_FALSE
);
4713 obsServ
->NotifyObservers(cancelQuit
, "quit-application-requested", nsnull
);
4716 cancelQuit
->GetData(&abortQuit
);
4717 sCanQuit
= abortQuit
? TRI_FALSE
: TRI_TRUE
;
4719 *aRetValue
= sCanQuit
? TRUE
: FALSE
;
4727 case MOZ_WM_APP_QUIT
:
4728 if (msg
== MOZ_WM_APP_QUIT
|| (wParam
== TRUE
&& sCanQuit
== TRI_TRUE
))
4730 // Let's fake a shutdown sequence without actually closing windows etc.
4731 // to avoid Windows killing us in the middle. A proper shutdown would
4732 // require having a chance to pump some messages. Unfortunately
4733 // Windows won't let us do that. Bug 212316.
4734 nsCOMPtr
<nsIObserverService
> obsServ
=
4735 mozilla::services::GetObserverService();
4736 NS_NAMED_LITERAL_STRING(context
, "shutdown-persist");
4737 obsServ
->NotifyObservers(nsnull
, "quit-application-granted", nsnull
);
4738 obsServ
->NotifyObservers(nsnull
, "quit-application-forced", nsnull
);
4739 obsServ
->NotifyObservers(nsnull
, "quit-application", nsnull
);
4740 obsServ
->NotifyObservers(nsnull
, "profile-change-net-teardown", context
.get());
4741 obsServ
->NotifyObservers(nsnull
, "profile-change-teardown", context
.get());
4742 obsServ
->NotifyObservers(nsnull
, "profile-before-change", context
.get());
4743 // Then a controlled but very quick exit.
4746 sCanQuit
= TRI_UNKNOWN
;
4751 case WM_DISPLAYCHANGE
:
4752 DispatchStandardEvent(NS_DISPLAYCHANGED
);
4756 case WM_SYSCOLORCHANGE
:
4757 // Note: This is sent for child windows as well as top-level windows.
4758 // The Win32 toolkit normally only sends these events to top-level windows.
4759 // But we cycle through all of the childwindows and send it to them as well
4760 // so all presentations get notified properly.
4761 // See nsWindow::GlobalMsgWindowProc.
4762 DispatchStandardEvent(NS_SYSCOLORCHANGED
);
4768 LPNMHDR pnmh
= (LPNMHDR
) lParam
;
4770 switch (pnmh
->code
) {
4773 DispatchStandardEvent(NS_TABCHANGE
);
4781 case WM_THEMECHANGED
:
4783 // Update non-client margin offsets
4784 UpdateNonClientMargins();
4785 nsUXThemeData::InitTitlebarInfo();
4786 nsUXThemeData::UpdateNativeThemeInfo();
4788 DispatchStandardEvent(NS_THEMECHANGED
);
4790 // Invalidate the window so that the repaint will
4791 // pick up the new theme.
4792 Invalidate(PR_FALSE
);
4799 PRBool didChange
= PR_FALSE
;
4801 // update the global font list
4802 nsCOMPtr
<nsIFontEnumerator
> fontEnum
= do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv
);
4803 if (NS_SUCCEEDED(rv
)) {
4804 fontEnum
->UpdateFontList(&didChange
);
4805 //didChange is TRUE only if new font langGroup is added to the list.
4807 // update device context font cache
4808 // Dirty but easiest way:
4809 // Changing nsIPrefBranch entry which triggers callbacks
4810 // and flows into calling mDeviceContext->FlushFontCache()
4811 // to update the font cache in all the instance of Browsers
4812 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
4814 nsCOMPtr
<nsIPrefBranch
> fiPrefs
;
4815 prefs
->GetBranch("font.internaluseonly.", getter_AddRefs(fiPrefs
));
4817 PRBool fontInternalChange
= PR_FALSE
;
4818 fiPrefs
->GetBoolPref("changed", &fontInternalChange
);
4819 fiPrefs
->SetBoolPref("changed", !fontInternalChange
);
4823 } //if (NS_SUCCEEDED(rv))
4829 // If wParam is TRUE, it specifies that the application should indicate
4830 // which part of the client area contains valid information. The system
4831 // copies the valid information to the specified area within the new
4832 // client area. If the wParam parameter is FALSE, the application should
4834 if (mCustomNonClient
) {
4842 // rgrc[0]: the proposed window
4843 // rgrc[1]: the current window
4844 // rgrc[2]: the source client area
4845 // pncsp->lppos: move/size data
4847 // rgrc[0]: the new client area
4848 // rgrc[1]: the destination window
4849 // rgrc[2]: the source client area
4850 // (all values in screen coordiantes)
4851 NCCALCSIZE_PARAMS
*pncsp
= reinterpret_cast<NCCALCSIZE_PARAMS
*>(lParam
);
4852 LRESULT res
= CallWindowProcW(GetPrevWindowProc(), mWnd
, msg
, wParam
, lParam
);
4853 pncsp
->rgrc
[0].top
-= mNonClientOffset
.top
;
4854 pncsp
->rgrc
[0].left
-= mNonClientOffset
.left
;
4855 pncsp
->rgrc
[0].right
+= mNonClientOffset
.right
;
4856 pncsp
->rgrc
[0].bottom
+= mNonClientOffset
.bottom
;
4867 * If an nc client area margin has been moved, we are responsible
4868 * for calculating where the resize margins are and returning the
4869 * appropriate set of hit test constants. DwmDefWindowProc (above)
4870 * will handle hit testing on it's command buttons if we are on a
4871 * composited desktop.
4874 if (!mCustomNonClient
)
4878 ClientMarginHitTestPoint(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
4885 * WM_SETTEXT paints the titlebar area. Avoid this if we have a
4886 * custom titlebar we paint ourselves.
4889 if (!mCustomNonClient
|| mNonClientMargins
.top
== -1)
4893 // From msdn, the way around this is to disable the visible state
4894 // temporarily. We need the text to be set but we don't want the
4896 DWORD style
= GetWindowLong(mWnd
, GWL_STYLE
);
4897 SetWindowLong(mWnd
, GWL_STYLE
, style
& ~WS_VISIBLE
);
4898 *aRetValue
= CallWindowProcW(GetPrevWindowProc(), mWnd
,
4899 msg
, wParam
, lParam
);
4900 SetWindowLong(mWnd
, GWL_STYLE
, style
);
4907 * WM_NCACTIVATE paints nc areas. Avoid this and re-route painting
4908 * through WM_NCPAINT via InvalidateNonClientRegion.
4911 if (!mCustomNonClient
)
4914 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4915 // let the dwm handle nc painting on glass
4916 if(nsUXThemeData::CheckForCompositor())
4920 if (wParam
== TRUE
) {
4922 *aRetValue
= FALSE
; // ignored
4924 UpdateGetWindowInfoCaptionStatus(PR_TRUE
);
4925 // invalidate to trigger a paint
4926 InvalidateNonClientRegion();
4930 *aRetValue
= TRUE
; // go ahead and deactive
4932 UpdateGetWindowInfoCaptionStatus(PR_FALSE
);
4933 // invalidate to trigger a paint
4934 InvalidateNonClientRegion();
4942 * Reset the non-client paint region so that it excludes the
4943 * non-client areas we paint manually. Then call defwndproc
4944 * to do the actual painting.
4947 if (!mCustomNonClient
)
4950 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4951 // let the dwm handle nc painting on glass
4952 if(nsUXThemeData::CheckForCompositor())
4956 HRGN paintRgn
= ExcludeNonClientFromPaintRegion((HRGN
)wParam
);
4957 LRESULT res
= CallWindowProcW(GetPrevWindowProc(), mWnd
,
4958 msg
, (WPARAM
)paintRgn
, lParam
);
4959 if (paintRgn
!= (HRGN
)wParam
)
4960 DeleteObject(paintRgn
);
4967 case WM_POWERBROADCAST
:
4968 // only hidden window handle this
4969 // to prevent duplicate notification
4970 if (mWindowType
== eWindowType_invisible
) {
4973 case PBT_APMSUSPEND
:
4974 PostSleepWakeNotification("sleep_notification");
4976 case PBT_APMRESUMEAUTOMATIC
:
4977 case PBT_APMRESUMECRITICAL
:
4978 case PBT_APMRESUMESUSPEND
:
4979 PostSleepWakeNotification("wake_notification");
4986 case WM_MOVE
: // Window moved
4989 ::GetWindowRect(mWnd
, &rect
);
4990 result
= OnMove(rect
.left
, rect
.top
);
4994 case WM_CLOSE
: // close request
4995 DispatchStandardEvent(NS_XUL_CLOSE
);
4996 result
= PR_TRUE
; // abort window closure
5006 *aRetValue
= (int) OnPaint(NULL
, 0);
5011 case WM_PRINTCLIENT
:
5012 result
= OnPaint((HDC
) wParam
, 0);
5017 result
= OnHotKey(wParam
, lParam
);
5023 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
5024 result
= ProcessCharMessage(nativeMsg
, nsnull
);
5025 DispatchPendingEvents();
5032 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
5033 result
= ProcessKeyUpMessage(nativeMsg
, nsnull
);
5034 DispatchPendingEvents();
5041 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
5042 result
= ProcessKeyDownMessage(nativeMsg
, nsnull
);
5043 DispatchPendingEvents();
5047 // say we've dealt with erase background if widget does
5048 // not need auto-erasing
5050 if (!AutoErase((HDC
)wParam
)) {
5058 #ifdef WINCE_WINDOWS_MOBILE
5059 // Reset the kill timer so that we can continue at this
5061 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2seconds */, NULL
);
5063 mMousePresent
= PR_TRUE
;
5065 // Suppress dispatch of pending events
5066 // when mouse moves are generated by widget
5067 // creation instead of user input.
5068 LPARAM lParamScreen
= lParamToScreen(lParam
);
5070 mp
.x
= GET_X_LPARAM(lParamScreen
);
5071 mp
.y
= GET_Y_LPARAM(lParamScreen
);
5072 PRBool userMovedMouse
= PR_FALSE
;
5073 if ((sLastMouseMovePoint
.x
!= mp
.x
) || (sLastMouseMovePoint
.y
!= mp
.y
)) {
5074 userMovedMouse
= PR_TRUE
;
5077 result
= DispatchMouseEvent(NS_MOUSE_MOVE
, wParam
, lParam
,
5078 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5079 if (userMovedMouse
) {
5080 DispatchPendingEvents();
5085 case WM_NCMOUSEMOVE
:
5086 // If we receive a mouse move event on non-client chrome, make sure and
5087 // send an NS_MOUSE_EXIT event as well.
5088 if (mMousePresent
&& !sIsInMouseCapture
)
5089 SendMessage(mWnd
, WM_MOUSELEAVE
, 0, 0);
5092 #ifdef WINCE_WINDOWS_MOBILE
5094 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
5095 KillTimer(mWnd
, KILL_PRIORITY_ID
);
5099 case WM_LBUTTONDOWN
:
5101 #ifdef WINCE_WINDOWS_MOBILE
5102 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
5103 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2 seconds */, NULL
);
5105 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
,
5106 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5107 DispatchPendingEvents();
5113 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
,
5114 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5115 DispatchPendingEvents();
5117 #ifdef WINCE_WINDOWS_MOBILE
5118 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
5119 KillTimer(mWnd
, KILL_PRIORITY_ID
);
5129 mMousePresent
= PR_FALSE
;
5131 // We need to check mouse button states and put them in for
5133 WPARAM mouseState
= (GetKeyState(VK_LBUTTON
) ? MK_LBUTTON
: 0)
5134 | (GetKeyState(VK_MBUTTON
) ? MK_MBUTTON
: 0)
5135 | (GetKeyState(VK_RBUTTON
) ? MK_RBUTTON
: 0);
5136 // Synthesize an event position because we don't get one from
5138 LPARAM pos
= lParamToClient(::GetMessagePos());
5139 DispatchMouseEvent(NS_MOUSE_EXIT
, mouseState
, pos
, PR_FALSE
,
5140 nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5145 case WM_CONTEXTMENU
:
5147 // if the context menu is brought up from the keyboard, |lParam|
5150 PRBool contextMenukey
= PR_FALSE
;
5153 contextMenukey
= PR_TRUE
;
5154 pos
= lParamToClient(GetMessagePos());
5158 pos
= lParamToClient(lParam
);
5161 result
= DispatchMouseEvent(NS_CONTEXTMENU
, wParam
, pos
, contextMenukey
,
5163 nsMouseEvent::eLeftButton
:
5164 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
5165 if (lParam
!= -1 && !result
&& mCustomNonClient
&&
5166 DispatchMouseEvent(NS_MOUSE_MOZHITTEST
, wParam
, pos
,
5167 PR_FALSE
, nsMouseEvent::eLeftButton
,
5168 MOUSE_INPUT_SOURCE())) {
5169 // Blank area hit, throw up the system menu.
5170 DisplaySystemMenu(mWnd
, mSizeMode
, mIsRTL
, GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
5176 case WM_LBUTTONDBLCLK
:
5177 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
5178 nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5179 DispatchPendingEvents();
5182 case WM_MBUTTONDOWN
:
5183 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
5184 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
5185 DispatchPendingEvents();
5189 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
5190 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
5191 DispatchPendingEvents();
5194 case WM_MBUTTONDBLCLK
:
5195 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
5196 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
5197 DispatchPendingEvents();
5200 case WM_NCMBUTTONDOWN
:
5201 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, 0, lParamToClient(lParam
), PR_FALSE
,
5202 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
5203 DispatchPendingEvents();
5206 case WM_NCMBUTTONUP
:
5207 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, 0, lParamToClient(lParam
), PR_FALSE
,
5208 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
5209 DispatchPendingEvents();
5212 case WM_NCMBUTTONDBLCLK
:
5213 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, 0, lParamToClient(lParam
), PR_FALSE
,
5214 nsMouseEvent::eMiddleButton
, MOUSE_INPUT_SOURCE());
5215 DispatchPendingEvents();
5218 case WM_RBUTTONDOWN
:
5219 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
5220 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
5221 DispatchPendingEvents();
5225 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
5226 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
5227 DispatchPendingEvents();
5230 case WM_RBUTTONDBLCLK
:
5231 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
5232 nsMouseEvent::eRightButton
, MOUSE_INPUT_SOURCE());
5233 DispatchPendingEvents();
5236 case WM_NCRBUTTONDOWN
:
5237 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, 0, lParamToClient(lParam
),
5238 PR_FALSE
, nsMouseEvent::eRightButton
,
5239 MOUSE_INPUT_SOURCE());
5240 DispatchPendingEvents();
5243 case WM_NCRBUTTONUP
:
5244 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, 0, lParamToClient(lParam
),
5245 PR_FALSE
, nsMouseEvent::eRightButton
,
5246 MOUSE_INPUT_SOURCE());
5247 DispatchPendingEvents();
5250 case WM_NCRBUTTONDBLCLK
:
5251 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, 0, lParamToClient(lParam
),
5252 PR_FALSE
, nsMouseEvent::eRightButton
,
5253 MOUSE_INPUT_SOURCE());
5254 DispatchPendingEvents();
5259 PRUint32 appCommand
= GET_APPCOMMAND_LPARAM(lParam
);
5263 case APPCOMMAND_BROWSER_BACKWARD
:
5264 case APPCOMMAND_BROWSER_FORWARD
:
5265 case APPCOMMAND_BROWSER_REFRESH
:
5266 case APPCOMMAND_BROWSER_STOP
:
5267 case APPCOMMAND_BROWSER_SEARCH
:
5268 case APPCOMMAND_BROWSER_FAVORITES
:
5269 case APPCOMMAND_BROWSER_HOME
:
5270 DispatchCommandEvent(appCommand
);
5271 // tell the driver that we handled the event
5276 // default = PR_FALSE - tell the driver that the event was not handled
5283 result
= OnScroll(msg
, wParam
, lParam
);
5286 // The WM_ACTIVATE event is fired when a window is raised or lowered,
5287 // and the loword of wParam specifies which. But we don't want to tell
5288 // the focus system about this until the WM_SETFOCUS or WM_KILLFOCUS
5289 // events are fired. Instead, set either the sJustGotActivate or
5290 // gJustGotDeativate flags and fire the NS_ACTIVATE or NS_DEACTIVATE
5291 // events once the focus events arrive.
5293 if (mEventCallback
) {
5294 PRInt32 fActive
= LOWORD(wParam
);
5296 #if defined(WINCE_HAVE_SOFTKB)
5297 if (mIsTopWidgetWindow
&& sSoftKeyboardState
)
5298 nsWindowCE::ToggleSoftKB(mWnd
, fActive
);
5299 if (nsWindowCE::sShowSIPButton
== TRI_FALSE
&& WA_INACTIVE
!= fActive
) {
5300 HWND hWndSIPB
= FindWindowW(L
"MS_SIPBUTTON", NULL
);
5302 ShowWindow(hWndSIPB
, SW_HIDE
);
5307 if (WA_INACTIVE
== fActive
) {
5308 // when minimizing a window, the deactivation and focus events will
5309 // be fired in the reverse order. Instead, just dispatch
5310 // NS_DEACTIVATE right away.
5312 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
5314 sJustGotDeactivate
= PR_TRUE
;
5316 if (mIsTopWidgetWindow
)
5317 mLastKeyboardLayout
= gKbdLayout
.GetLayout();
5323 sJustGotActivate
= PR_TRUE
;
5324 nsMouseEvent
event(PR_TRUE
, NS_MOUSE_ACTIVATE
, this,
5325 nsMouseEvent::eReal
);
5327 DispatchWindowEvent(&event
);
5329 if (sSwitchKeyboardLayout
&& mLastKeyboardLayout
)
5330 ActivateKeyboardLayout(mLastKeyboardLayout
, 0);
5334 #ifdef WINCE_WINDOWS_MOBILE
5335 if (!gCheckForHTCApi
&& gHTCApiNavOpen
== nsnull
) {
5336 gCheckForHTCApi
= PR_TRUE
;
5338 HINSTANCE library
= LoadLibrary(L
"HTCAPI.dll");
5339 gHTCApiNavOpen
= (HTCApiNavOpen
) GetProcAddress(library
, "HTCNavOpen");
5340 gHTCApiNavSetMode
= (HTCApiNavSetMode
) GetProcAddress(library
,"HTCNavSetMode");
5343 if (gHTCApiNavOpen
!= nsnull
) {
5344 gHTCApiNavOpen(mWnd
, 1 /* undocumented value */);
5346 if (gHTCApiNavSetMode
!= nsnull
)
5347 gHTCApiNavSetMode ( mWnd
, 4);
5348 // 4 is Gesture Mode. This will generate WM_HTCNAV events to the window
5354 case WM_MOUSEACTIVATE
:
5355 if (mWindowType
== eWindowType_popup
) {
5356 // a popup with a parent owner should not be activated when clicked
5357 // but should still allow the mouse event to be fired, so the return
5358 // value is set to MA_NOACTIVATE. But if the owner isn't the frontmost
5359 // window, just use default processing so that the window is activated.
5360 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
5361 if (owner
&& owner
== ::GetForegroundWindow()) {
5362 *aRetValue
= MA_NOACTIVATE
;
5368 case WM_WINDOWPOSCHANGING
:
5370 LPWINDOWPOS info
= (LPWINDOWPOS
) lParam
;
5371 OnWindowPosChanging(info
);
5377 // If previous focused window isn't ours, it must have received the
5378 // redirected message. So, we should forget it.
5379 if (!IsOurProcessWindow(HWND(wParam
))) {
5380 ForgetRedirectedKeyDownMessage();
5382 if (sJustGotActivate
) {
5383 result
= DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
5386 #ifdef ACCESSIBILITY
5387 if (nsWindow::sIsAccessibilityOn
) {
5388 // Create it for the first time so that it can start firing events
5389 nsAccessible
*rootAccessible
= GetRootAccessible();
5393 #if defined(WINCE_HAVE_SOFTKB)
5395 // On Windows CE, we have a window that overlaps
5396 // the ISP button. In this case, we should always
5397 // try to hide it when we are activated
5399 nsIMEContext
IMEContext(mWnd
);
5401 ImmSetOpenStatus(IMEContext
.get(), TRUE
);
5407 #if defined(WINCE_HAVE_SOFTKB)
5409 nsIMEContext
IMEContext(mWnd
);
5410 ImmSetOpenStatus(IMEContext
.get(), FALSE
);
5413 if (sJustGotDeactivate
) {
5414 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
5418 case WM_WINDOWPOSCHANGED
:
5420 WINDOWPOS
*wp
= (LPWINDOWPOS
)lParam
;
5421 OnWindowPosChanged(wp
, result
);
5425 case WM_SETTINGCHANGE
:
5426 #if !defined (WINCE_WINDOWS_MOBILE)
5427 getWheelInfo
= PR_TRUE
;
5430 case SPI_SETSIPINFO
:
5431 case SPI_SETCURRENTIM
:
5432 nsWindowCE::OnSoftKbSettingsChange(mWnd
);
5434 case SETTINGCHANGE_RESET
:
5435 if (mWindowType
== eWindowType_invisible
) {
5436 // The OS sees to get confused and think that the invisable window
5437 // is in the foreground after an orientation change. By actually
5438 // setting it to the foreground and hiding it, we set it strait.
5439 // See bug 514007 for details.
5440 SetForegroundWindow(mWnd
);
5441 ShowWindow(mWnd
, SW_HIDE
);
5446 OnSettingsChange(wParam
, lParam
);
5450 case WM_INPUTLANGCHANGEREQUEST
:
5455 case WM_INPUTLANGCHANGE
:
5456 result
= OnInputLangChange((HKL
)lParam
);
5460 case WM_DESTROYCLIPBOARD
:
5462 nsIClipboard
* clipboard
;
5463 nsresult rv
= CallGetService(kCClipboardCID
, &clipboard
);
5464 if(NS_SUCCEEDED(rv
)) {
5465 clipboard
->EmptyClipboard(nsIClipboard::kGlobalClipboard
);
5466 NS_RELEASE(clipboard
);
5471 #ifdef ACCESSIBILITY
5475 if (lParam
== OBJID_CLIENT
) { // oleacc.dll will be loaded dynamically
5476 nsAccessible
*rootAccessible
= GetRootAccessible(); // Held by a11y cache
5477 if (rootAccessible
) {
5478 IAccessible
*msaaAccessible
= NULL
;
5479 rootAccessible
->GetNativeInterface((void**)&msaaAccessible
); // does an addref
5480 if (msaaAccessible
) {
5481 *aRetValue
= LresultFromObject(IID_IAccessible
, wParam
, msaaAccessible
); // does an addref
5482 msaaAccessible
->Release(); // release extra addref
5483 result
= PR_TRUE
; // We handled the WM_GETOBJECT message
5493 WPARAM filteredWParam
= (wParam
&0xFFF0);
5494 // prevent Windows from trimming the working set. bug 76831
5495 if (!sTrimOnMinimize
&& filteredWParam
== SC_MINIMIZE
) {
5496 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
5500 // Handle the system menu manually when we're in full screen mode
5501 // so we can set the appropriate options.
5502 if (filteredWParam
== SC_KEYMENU
&& lParam
== VK_SPACE
&&
5503 mSizeMode
== nsSizeMode_Fullscreen
) {
5504 DisplaySystemMenu(mWnd
, mSizeMode
, mIsRTL
,
5505 MOZ_SYSCONTEXT_X_POS
,
5506 MOZ_SYSCONTEXT_Y_POS
);
5516 nsMemory::HeapMinimize(PR_TRUE
);
5521 case WM_MOUSEHWHEEL
:
5523 // If OnMouseWheel returns true, the event was forwarded directly to another
5524 // mozilla window message handler (ProcessMessage). In this case the return
5525 // value of the forwarded event is in 'result' which we should return immediately.
5526 // If OnMouseWheel returns false, OnMouseWheel processed the event internally.
5527 // 'result' and 'aRetValue' will be set based on what we did with the event, so
5528 // we should fall through.
5529 if (OnMouseWheel(msg
, wParam
, lParam
, getWheelInfo
, result
, aRetValue
))
5535 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
5536 case WM_DWMCOMPOSITIONCHANGED
:
5537 // First, update the compositor state to latest one. All other methods
5538 // should use same state as here for consistency painting.
5539 nsUXThemeData::CheckForCompositor(PR_TRUE
);
5541 UpdateNonClientMargins();
5542 RemovePropW(mWnd
, kManageWindowInfoProperty
);
5543 BroadcastMsg(mWnd
, WM_DWMCOMPOSITIONCHANGED
);
5544 DispatchStandardEvent(NS_THEMECHANGED
);
5546 Invalidate(PR_FALSE
);
5550 case WM_UPDATEUISTATE
:
5552 // If the UI state has changed, fire an event so the UI updates the
5553 // keyboard cues based on the system setting and how the window was
5554 // opened. For example, a dialog opened via a keyboard press on a button
5555 // should enable cues, whereas the same dialog opened via a mouse click of
5556 // the button should not.
5557 PRInt32 action
= LOWORD(wParam
);
5558 if (action
== UIS_SET
|| action
== UIS_CLEAR
) {
5559 nsUIStateChangeEvent
event(PR_TRUE
, NS_UISTATECHANGED
, this);
5560 PRInt32 flags
= HIWORD(wParam
);
5561 if (flags
& UISF_HIDEACCEL
)
5562 event
.showAccelerators
= (action
== UIS_SET
) ? UIStateChangeType_Clear
: UIStateChangeType_Set
;
5563 if (flags
& UISF_HIDEFOCUS
)
5564 event
.showFocusRings
= (action
== UIS_SET
) ? UIStateChangeType_Clear
: UIStateChangeType_Set
;
5565 DispatchWindowEvent(&event
);
5571 /* Gesture support events */
5572 case WM_TABLET_QUERYSYSTEMGESTURESTATUS
:
5573 // According to MS samples, this must be handled to enable
5574 // rotational support in multi-touch drivers.
5576 *aRetValue
= TABLET_ROTATE_GESTURE_ENABLE
;
5579 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
5581 result
= OnTouch(wParam
, lParam
);
5589 result
= OnGesture(wParam
, lParam
);
5592 case WM_GESTURENOTIFY
:
5594 if (mWindowType
!= eWindowType_invisible
&&
5595 mWindowType
!= eWindowType_plugin
) {
5596 // A GestureNotify event is dispatched to decide which single-finger panning
5597 // direction should be active (including none) and if pan feedback should
5598 // be displayed. Java and plugin windows can make their own calls.
5599 GESTURENOTIFYSTRUCT
* gestureinfo
= (GESTURENOTIFYSTRUCT
*)lParam
;
5600 nsPointWin touchPoint
;
5601 touchPoint
= gestureinfo
->ptsLocation
;
5602 touchPoint
.ScreenToClient(mWnd
);
5603 nsGestureNotifyEvent
gestureNotifyEvent(PR_TRUE
, NS_GESTURENOTIFY_EVENT_START
, this);
5604 gestureNotifyEvent
.refPoint
= touchPoint
;
5605 nsEventStatus status
;
5606 DispatchEvent(&gestureNotifyEvent
, status
);
5607 mDisplayPanFeedback
= gestureNotifyEvent
.displayPanFeedback
;
5609 mGesture
.SetWinGestureSupport(mWnd
, gestureNotifyEvent
.panDirection
);
5611 result
= PR_FALSE
; //should always bubble to DefWindowProc
5614 #endif // !defined(WINCE)
5618 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_DELETE
, this);
5619 DispatchWindowEvent(&command
);
5626 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_CUT
, this);
5627 DispatchWindowEvent(&command
);
5634 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_COPY
, this);
5635 DispatchWindowEvent(&command
);
5642 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
, this);
5643 DispatchWindowEvent(&command
);
5651 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
, this);
5652 DispatchWindowEvent(&command
);
5653 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5660 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
, this);
5661 DispatchWindowEvent(&command
);
5662 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5669 // Support EM_CANPASTE message only when wParam isn't specified or
5670 // is plain text format.
5671 if (wParam
== 0 || wParam
== CF_TEXT
|| wParam
== CF_UNICODETEXT
) {
5672 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
,
5674 DispatchWindowEvent(&command
);
5675 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5683 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
,
5685 DispatchWindowEvent(&command
);
5686 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5693 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
,
5695 DispatchWindowEvent(&command
);
5696 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
5702 #ifdef WINCE_WINDOWS_MOBILE
5703 //HTC NAVIGATION WHEEL EVENT
5706 int distance
= wParam
& 0x000000FF;
5707 if ( (wParam
& 0x000000100) != 0) // Counter Clockwise
5709 if (OnMouseWheel(WM_MOUSEWHEEL
, MAKEWPARAM(0, distance
),
5710 MAKELPARAM(GetSystemMetrics(SM_CXSCREEN
) / 2,
5711 GetSystemMetrics(SM_CYSCREEN
) / 2),
5712 getWheelInfo
, result
, aRetValue
))
5720 #ifdef NS_ENABLE_TSF
5721 if (msg
== WM_USER_TSF_TEXTCHANGE
) {
5722 nsTextStore::OnTextChangeMsg();
5724 #endif //NS_ENABLE_TSF
5725 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
5726 if (msg
== nsAppShell::GetTaskbarButtonCreatedMessage())
5727 SetHasTaskbarIconBeenCreated();
5730 if (msg
== sOOPPPluginFocusEvent
) {
5732 // With OOPP, the plugin window exists in another process and is a child of
5733 // this window. This window is a placeholder plugin window for the dom. We
5734 // receive this event when the child window receives focus. (sent from
5735 // PluginInstanceParent.cpp)
5736 ::SendMessage(mWnd
, WM_MOUSEACTIVATE
, 0, 0); // See nsPluginNativeWindowWin.cpp
5738 // WM_KILLFOCUS was received by the child process.
5739 if (sJustGotDeactivate
) {
5740 DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
5749 //*aRetValue = result;
5754 //Events which caused mWnd destruction and aren't consumed
5755 //will crash during the Windows default processing.
5760 /**************************************************************
5762 * SECTION: Broadcast messaging
5764 * Broadcast messages to all windows.
5766 **************************************************************/
5768 // Enumerate all child windows sending aMsg to each of them
5769 BOOL CALLBACK
nsWindow::BroadcastMsgToChildren(HWND aWnd
, LPARAM aMsg
)
5771 WNDPROC winProc
= (WNDPROC
)::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
5772 if (winProc
== &nsWindow::WindowProc
) {
5773 // it's one of our windows so go ahead and send a message to it
5774 ::CallWindowProcW(winProc
, aWnd
, aMsg
, 0, 0);
5779 // Enumerate all top level windows specifying that the children of each
5780 // top level window should be enumerated. Do *not* send the message to
5781 // each top level window since it is assumed that the toolkit will send
5782 // aMsg to them directly.
5783 BOOL CALLBACK
nsWindow::BroadcastMsg(HWND aTopWindow
, LPARAM aMsg
)
5785 // Iterate each of aTopWindows child windows sending the aMsg
5788 ::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
5790 nsWindowCE::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
5795 // This method is called from nsToolkit::WindowProc to forward global
5796 // messages which need to be dispatched to all child windows.
5797 void nsWindow::GlobalMsgWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
5800 case WM_SYSCOLORCHANGE
:
5801 // Code to dispatch WM_SYSCOLORCHANGE message to all child windows.
5802 // WM_SYSCOLORCHANGE is only sent to top-level windows, but the
5803 // cross platform API requires that NS_SYSCOLORCHANGE message be sent to
5804 // all child windows as well. When running in an embedded application
5805 // we may not receive a WM_SYSCOLORCHANGE message because the top
5806 // level window is owned by the embeddor.
5807 // System color changes are posted to top-level windows only.
5808 // The NS_SYSCOLORCHANGE must be dispatched to all child
5811 ::EnumThreadWindows(GetCurrentThreadId(), nsWindow::BroadcastMsg
, msg
);
5817 /**************************************************************
5819 * SECTION: Event processing helpers
5821 * Special processing for certain event types and
5822 * synthesized events.
5824 **************************************************************/
5827 nsWindow::ClientMarginHitTestPoint(PRInt32 mx
, PRInt32 my
)
5829 // Calculations are done in screen coords
5831 GetWindowRect(mWnd
, &winRect
);
5833 // hit return constants:
5834 // HTBORDER - non-resizable border
5835 // HTBOTTOM, HTLEFT, HTRIGHT, HTTOP - resizable border
5836 // HTBOTTOMLEFT, HTBOTTOMRIGHT - resizable corner
5837 // HTTOPLEFT, HTTOPRIGHT - resizable corner
5838 // HTCAPTION - general title bar area
5839 // HTCLIENT - area considered the client
5840 // HTCLOSE - hovering over the close button
5841 // HTMAXBUTTON - maximize button
5842 // HTMINBUTTON - minimize button
5844 PRInt32 testResult
= HTCLIENT
;
5846 PRBool top
= PR_FALSE
;
5847 PRBool bottom
= PR_FALSE
;
5848 PRBool left
= PR_FALSE
;
5849 PRBool right
= PR_FALSE
;
5851 if (my
>= winRect
.top
&& my
<
5852 (winRect
.top
+ mVertResizeMargin
+ (mCaptionHeight
- mNonClientOffset
.top
)))
5854 else if (my
< winRect
.bottom
&& my
>= (winRect
.bottom
- mVertResizeMargin
))
5857 if (mx
>= winRect
.left
&& mx
< (winRect
.left
+
5858 (bottom
? (2*mHorResizeMargin
) : mHorResizeMargin
)))
5860 else if (mx
< winRect
.right
&& mx
>= (winRect
.right
-
5861 (bottom
? (2*mHorResizeMargin
) : mHorResizeMargin
)))
5867 testResult
= HTTOPLEFT
;
5869 testResult
= HTTOPRIGHT
;
5870 } else if (bottom
) {
5871 testResult
= HTBOTTOM
;
5873 testResult
= HTBOTTOMLEFT
;
5875 testResult
= HTBOTTOMRIGHT
;
5878 testResult
= HTLEFT
;
5880 testResult
= HTRIGHT
;
5883 PRBool contentOverlap
= PR_TRUE
;
5885 if (mSizeMode
== nsSizeMode_Maximized
) {
5886 // There's no HTTOP in maximized state (bug 575493)
5887 if (testResult
== HTTOP
) {
5888 testResult
= HTCAPTION
;
5891 PRInt32 leftMargin
= mNonClientMargins
.left
== -1 ? mHorResizeMargin
: mNonClientMargins
.left
;
5892 PRInt32 rightMargin
= mNonClientMargins
.right
== -1 ? mHorResizeMargin
: mNonClientMargins
.right
;
5893 PRInt32 topMargin
= mNonClientMargins
.top
== -1 ? mVertResizeMargin
: mNonClientMargins
.top
;
5894 PRInt32 bottomMargin
= mNonClientMargins
.bottom
== -1 ? mVertResizeMargin
: mNonClientMargins
.bottom
;
5896 contentOverlap
= mx
>= winRect
.left
+ leftMargin
&&
5897 mx
<= winRect
.right
- rightMargin
&&
5898 my
>= winRect
.top
+ topMargin
&&
5899 my
<= winRect
.bottom
- bottomMargin
;
5902 if (!sIsInMouseCapture
&&
5904 (testResult
== HTCLIENT
||
5905 testResult
== HTTOP
||
5906 testResult
== HTTOPLEFT
||
5907 testResult
== HTCAPTION
)) {
5908 LPARAM lParam
= MAKELPARAM(mx
, my
);
5909 LPARAM lParamClient
= lParamToClient(lParam
);
5910 PRBool result
= DispatchMouseEvent(NS_MOUSE_MOZHITTEST
, 0, lParamClient
,
5911 PR_FALSE
, nsMouseEvent::eLeftButton
, MOUSE_INPUT_SOURCE());
5913 // The mouse is over a blank area
5914 testResult
= testResult
== HTCLIENT
? HTCAPTION
: testResult
;
5917 // There's content over the mouse pointer. Set HTCLIENT
5918 // to possibly override a resizer border.
5919 testResult
= HTCLIENT
;
5927 void nsWindow::PostSleepWakeNotification(const char* aNotification
)
5929 nsCOMPtr
<nsIObserverService
> observerService
=
5930 mozilla::services::GetObserverService();
5931 if (observerService
)
5932 observerService
->NotifyObservers(nsnull
, aNotification
, nsnull
);
5936 // RemoveNextCharMessage() should be called by WM_KEYDOWN or WM_SYSKEYDOWM
5937 // message handler. If there is no WM_(SYS)CHAR message for it, this
5938 // method does nothing.
5939 // NOTE: WM_(SYS)CHAR message is posted by TranslateMessage() API which is
5940 // called in message loop. So, WM_(SYS)KEYDOWN message should have
5941 // WM_(SYS)CHAR message in the queue if the keydown event causes character
5945 void nsWindow::RemoveNextCharMessage(HWND aWnd
)
5948 if (::PeekMessageW(&msg
, aWnd
,
5949 WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
) &&
5950 (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
)) {
5951 ::GetMessageW(&msg
, aWnd
, msg
.message
, msg
.message
);
5955 LRESULT
nsWindow::ProcessCharMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
5957 NS_PRECONDITION(aMsg
.message
== WM_CHAR
|| aMsg
.message
== WM_SYSCHAR
,
5958 "message is not keydown event");
5959 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5960 ("%s charCode=%d scanCode=%d\n",
5961 aMsg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
5962 aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF));
5964 // These must be checked here too as a lone WM_CHAR could be received
5965 // if a child window didn't handle it (for example Alt+Space in a content window)
5966 nsModifierKeyState modKeyState
;
5967 return OnChar(aMsg
, modKeyState
, aEventDispatched
);
5970 LRESULT
nsWindow::ProcessKeyUpMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
5972 NS_PRECONDITION(aMsg
.message
== WM_KEYUP
|| aMsg
.message
== WM_SYSKEYUP
,
5973 "message is not keydown event");
5974 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5975 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
5976 "WM_SYSKEYUP" : "WM_KEYUP", aMsg
.wParam
));
5978 nsModifierKeyState modKeyState
;
5980 // Note: the original code passed (HIWORD(lParam)) to OnKeyUp as
5981 // scan code. However, this breaks Alt+Num pad input.
5982 // MSDN states the following:
5983 // Typically, ToAscii performs the translation based on the
5984 // virtual-key code. In some cases, however, bit 15 of the
5985 // uScanCode parameter may be used to distinguish between a key
5986 // press and a key release. The scan code is used for
5987 // translating ALT+number key combinations.
5989 // ignore [shift+]alt+space so the OS can handle it
5990 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
5991 IS_VK_DOWN(NS_VK_SPACE
)) {
5995 if (!nsIMM32Handler::IsComposingOn(this) &&
5996 (aMsg
.message
!= WM_KEYUP
|| aMsg
.wParam
!= VK_MENU
)) {
5997 // Ignore VK_MENU if it's not a system key release, so that the menu bar does not trigger
5998 // This helps avoid triggering the menu bar for ALT key accelerators used in
5999 // assistive technologies such as Window-Eyes and ZoomText, and when using Alt+Tab
6000 // to switch back to Mozilla in Windows 95 and Windows 98
6001 return OnKeyUp(aMsg
, modKeyState
, aEventDispatched
);
6007 LRESULT
nsWindow::ProcessKeyDownMessage(const MSG
&aMsg
,
6008 PRBool
*aEventDispatched
)
6010 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6011 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
6012 "WM_SYSKEYDOWN" : "WM_KEYDOWN", aMsg
.wParam
));
6013 NS_PRECONDITION(aMsg
.message
== WM_KEYDOWN
|| aMsg
.message
== WM_SYSKEYDOWN
,
6014 "message is not keydown event");
6016 // If this method doesn't call OnKeyDown(), this method must clean up the
6017 // redirected message information itself. For more information, see above
6018 // comment of AutoForgetRedirectedKeyDownMessage struct definition in
6020 AutoForgetRedirectedKeyDownMessage
forgetRedirectedMessage(this, aMsg
);
6022 nsModifierKeyState modKeyState
;
6024 // Note: the original code passed (HIWORD(lParam)) to OnKeyDown as
6025 // scan code. However, this breaks Alt+Num pad input.
6026 // MSDN states the following:
6027 // Typically, ToAscii performs the translation based on the
6028 // virtual-key code. In some cases, however, bit 15 of the
6029 // uScanCode parameter may be used to distinguish between a key
6030 // press and a key release. The scan code is used for
6031 // translating ALT+number key combinations.
6033 // ignore [shift+]alt+space so the OS can handle it
6034 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
6035 IS_VK_DOWN(NS_VK_SPACE
))
6039 if (modKeyState
.mIsAltDown
&& nsIMM32Handler::IsStatusChanged()) {
6040 nsIMM32Handler::NotifyEndStatusChange();
6041 } else if (!nsIMM32Handler::IsComposingOn(this)) {
6042 result
= OnKeyDown(aMsg
, modKeyState
, aEventDispatched
, nsnull
);
6043 // OnKeyDown cleaned up the redirected message information itself, so,
6044 // we should do nothing.
6045 forgetRedirectedMessage
.mCancel
= PR_TRUE
;
6049 if (aMsg
.wParam
== VK_MENU
||
6050 (aMsg
.wParam
== VK_F10
&& !modKeyState
.mIsShiftDown
)) {
6051 // We need to let Windows handle this keypress,
6052 // by returning PR_FALSE, if there's a native menu
6053 // bar somewhere in our containing window hierarchy.
6054 // Otherwise we handle the keypress and don't pass
6055 // it on to Windows, by returning PR_TRUE.
6056 PRBool hasNativeMenu
= PR_FALSE
;
6059 if (::GetMenu(hWnd
)) {
6060 hasNativeMenu
= PR_TRUE
;
6063 hWnd
= ::GetParent(hWnd
);
6065 result
= !hasNativeMenu
;
6073 nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout
,
6074 PRInt32 aNativeKeyCode
,
6075 PRUint32 aModifierFlags
,
6076 const nsAString
& aCharacters
,
6077 const nsAString
& aUnmodifiedCharacters
)
6079 #ifndef WINCE //Win CE doesn't support many of the calls used in this method, perhaps theres another way
6080 nsPrintfCString
layoutName("%08x", aNativeKeyboardLayout
);
6081 HKL loadedLayout
= LoadKeyboardLayoutA(layoutName
.get(), KLF_NOTELLSHELL
);
6082 if (loadedLayout
== NULL
)
6083 return NS_ERROR_NOT_AVAILABLE
;
6085 // Setup clean key state and load desired layout
6086 BYTE originalKbdState
[256];
6087 ::GetKeyboardState(originalKbdState
);
6089 memset(kbdState
, 0, sizeof(kbdState
));
6090 // This changes the state of the keyboard for the current thread only,
6091 // and we'll restore it soon, so this should be OK.
6092 ::SetKeyboardState(kbdState
);
6093 HKL oldLayout
= gKbdLayout
.GetLayout();
6094 gKbdLayout
.LoadLayout(loadedLayout
);
6096 nsAutoTArray
<KeyPair
,10> keySequence
;
6097 SetupKeyModifiersSequence(&keySequence
, aModifierFlags
);
6098 NS_ASSERTION(aNativeKeyCode
>= 0 && aNativeKeyCode
< 256,
6099 "Native VK key code out of range");
6100 keySequence
.AppendElement(KeyPair(aNativeKeyCode
, 0));
6102 // Simulate the pressing of each modifier key and then the real key
6103 for (PRUint32 i
= 0; i
< keySequence
.Length(); ++i
) {
6104 PRUint8 key
= keySequence
[i
].mGeneral
;
6105 PRUint8 keySpecific
= keySequence
[i
].mSpecific
;
6106 kbdState
[key
] = 0x81; // key is down and toggled on if appropriate
6108 kbdState
[keySpecific
] = 0x81;
6110 ::SetKeyboardState(kbdState
);
6111 nsModifierKeyState modKeyState
;
6112 MSG msg
= InitMSG(WM_KEYDOWN
, key
, 0);
6113 if (i
== keySequence
.Length() - 1 && aCharacters
.Length() > 0) {
6114 UINT scanCode
= ::MapVirtualKeyEx(aNativeKeyCode
, MAPVK_VK_TO_VSC
,
6115 gKbdLayout
.GetLayout());
6116 nsFakeCharMessage fakeMsg
= { aCharacters
.CharAt(0), scanCode
};
6117 OnKeyDown(msg
, modKeyState
, nsnull
, &fakeMsg
);
6119 OnKeyDown(msg
, modKeyState
, nsnull
, nsnull
);
6122 for (PRUint32 i
= keySequence
.Length(); i
> 0; --i
) {
6123 PRUint8 key
= keySequence
[i
- 1].mGeneral
;
6124 PRUint8 keySpecific
= keySequence
[i
- 1].mSpecific
;
6125 kbdState
[key
] = 0; // key is up and toggled off if appropriate
6127 kbdState
[keySpecific
] = 0;
6129 ::SetKeyboardState(kbdState
);
6130 nsModifierKeyState modKeyState
;
6131 MSG msg
= InitMSG(WM_KEYUP
, key
, 0);
6132 OnKeyUp(msg
, modKeyState
, nsnull
);
6135 // Restore old key state and layout
6136 ::SetKeyboardState(originalKbdState
);
6137 gKbdLayout
.LoadLayout(oldLayout
);
6139 UnloadKeyboardLayout(loadedLayout
);
6141 #else //XXX: is there another way to do this?
6142 return NS_ERROR_NOT_IMPLEMENTED
;
6147 nsWindow::SynthesizeNativeMouseEvent(nsIntPoint aPoint
,
6148 PRUint32 aNativeMessage
,
6149 PRUint32 aModifierFlags
)
6151 #ifndef WINCE // I don't think WINCE supports SendInput
6153 ::GetWindowRect(mWnd
, &r
);
6154 ::SetCursorPos(r
.left
+ aPoint
.x
, r
.top
+ aPoint
.y
);
6157 memset(&input
, 0, sizeof(input
));
6159 input
.type
= INPUT_MOUSE
;
6160 input
.mi
.dwFlags
= aNativeMessage
;
6161 ::SendInput(1, &input
, sizeof(INPUT
));
6165 return NS_ERROR_NOT_IMPLEMENTED
;
6169 /**************************************************************
6171 * SECTION: OnXXX message handlers
6173 * For message handlers that need to be broken out or
6174 * implemented in specific platform code.
6176 **************************************************************/
6178 BOOL
nsWindow::OnInputLangChange(HKL aHKL
)
6181 printf("OnInputLanguageChange\n");
6185 gKbdLayout
.LoadLayout(aHKL
);
6188 return PR_FALSE
; // always pass to child window
6191 #if !defined(WINCE) // implemented in nsWindowCE.cpp
6192 void nsWindow::OnWindowPosChanged(WINDOWPOS
*wp
, PRBool
& result
)
6197 #ifdef WINSTATE_DEBUG_OUTPUT
6198 if (mWnd
== GetTopLevelHWND(mWnd
))
6199 printf("*** OnWindowPosChanged: [ top] ");
6201 printf("*** OnWindowPosChanged: [child] ");
6202 printf("WINDOWPOS flags:");
6203 if (wp
->flags
& SWP_FRAMECHANGED
)
6204 printf("SWP_FRAMECHANGED ");
6205 if (wp
->flags
& SWP_SHOWWINDOW
)
6206 printf("SWP_SHOWWINDOW ");
6207 if (wp
->flags
& SWP_NOSIZE
)
6208 printf("SWP_NOSIZE ");
6209 if (wp
->flags
& SWP_HIDEWINDOW
)
6210 printf("SWP_HIDEWINDOW ");
6211 if (wp
->flags
& SWP_NOZORDER
)
6212 printf("SWP_NOZORDER ");
6213 if (wp
->flags
& SWP_NOACTIVATE
)
6214 printf("SWP_NOACTIVATE ");
6218 // Handle window size mode changes
6219 if (wp
->flags
& SWP_FRAMECHANGED
&& mSizeMode
!= nsSizeMode_Fullscreen
) {
6221 // Bug 566135 - Windows theme code calls show window on SW_SHOWMINIMIZED
6222 // windows when fullscreen games disable desktop composition. If we're
6223 // minimized and not being activated, ignore the event and let windows
6225 if (mSizeMode
== nsSizeMode_Minimized
&& (wp
->flags
& SWP_NOACTIVATE
))
6228 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
6231 pl
.length
= sizeof(pl
);
6232 ::GetWindowPlacement(mWnd
, &pl
);
6234 if (pl
.showCmd
== SW_SHOWMAXIMIZED
)
6235 event
.mSizeMode
= (mFullscreenMode
? nsSizeMode_Fullscreen
: nsSizeMode_Maximized
);
6236 else if (pl
.showCmd
== SW_SHOWMINIMIZED
)
6237 event
.mSizeMode
= nsSizeMode_Minimized
;
6239 event
.mSizeMode
= nsSizeMode_Normal
;
6241 // Windows has just changed the size mode of this window. The following
6242 // NS_SIZEMODE event will trigger a call into SetSizeMode where we will
6243 // set the min/max window state again or for nsSizeMode_Normal, call
6244 // SetWindow with a parameter of SW_RESTORE. There's no need however as
6245 // this window's mode has already changed. Updating mSizeMode here
6246 // insures the SetSizeMode call is a no-op. Addresses a bug on Win7 related
6247 // to window docking. (bug 489258)
6248 mSizeMode
= event
.mSizeMode
;
6250 // If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
6251 // SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
6252 // prevents the working set from being trimmed but keeps the window active.
6253 // After the window is minimized, we need to do some touch up work on the
6254 // active window. (bugs 76831 & 499816)
6255 if (!sTrimOnMinimize
&& nsSizeMode_Minimized
== event
.mSizeMode
)
6256 ActivateOtherWindowHelper(mWnd
);
6258 #ifdef WINSTATE_DEBUG_OUTPUT
6259 switch (mSizeMode
) {
6260 case nsSizeMode_Normal
:
6261 printf("*** mSizeMode: nsSizeMode_Normal\n");
6263 case nsSizeMode_Minimized
:
6264 printf("*** mSizeMode: nsSizeMode_Minimized\n");
6266 case nsSizeMode_Maximized
:
6267 printf("*** mSizeMode: nsSizeMode_Maximized\n");
6270 printf("*** mSizeMode: ??????\n");
6277 result
= DispatchWindowEvent(&event
);
6279 // Skip window size change events below on minimization.
6280 if (mSizeMode
== nsSizeMode_Minimized
)
6284 // Handle window size changes
6285 if (!(wp
->flags
& SWP_NOSIZE
)) {
6287 PRInt32 newWidth
, newHeight
;
6289 ::GetWindowRect(mWnd
, &r
);
6291 newWidth
= r
.right
- r
.left
;
6292 newHeight
= r
.bottom
- r
.top
;
6293 nsIntRect
rect(wp
->x
, wp
->y
, newWidth
, newHeight
);
6296 if (eTransparencyTransparent
== mTransparencyMode
)
6297 ResizeTranslucentWindow(newWidth
, newHeight
);
6300 if (newWidth
> mLastSize
.width
)
6305 drect
.left
= wp
->x
+ mLastSize
.width
;
6307 drect
.right
= drect
.left
+ (newWidth
- mLastSize
.width
);
6308 drect
.bottom
= drect
.top
+ newHeight
;
6310 ::RedrawWindow(mWnd
, &drect
, NULL
,
6313 RDW_NOINTERNALPAINT
|
6317 if (newHeight
> mLastSize
.height
)
6323 drect
.top
= wp
->y
+ mLastSize
.height
;
6324 drect
.right
= drect
.left
+ newWidth
;
6325 drect
.bottom
= drect
.top
+ (newHeight
- mLastSize
.height
);
6327 ::RedrawWindow(mWnd
, &drect
, NULL
,
6330 RDW_NOINTERNALPAINT
|
6335 mBounds
.width
= newWidth
;
6336 mBounds
.height
= newHeight
;
6337 mLastSize
.width
= newWidth
;
6338 mLastSize
.height
= newHeight
;
6340 #ifdef WINSTATE_DEBUG_OUTPUT
6341 printf("*** Resize window: %d x %d x %d x %d\n", wp
->x
, wp
->y
, newWidth
, newHeight
);
6344 // If a maximized window is resized, recalculate the non-client margins and
6345 // ensure a 1 pixel margin at screen bottom to allow taskbar unhiding to
6347 if (mSizeMode
== nsSizeMode_Maximized
) {
6348 if (UpdateNonClientMargins(nsSizeMode_Maximized
, PR_TRUE
)) {
6349 // gecko resize event already sent by UpdateNonClientMargins.
6355 // Recalculate the width and height based on the client area for gecko events.
6356 if (::GetClientRect(mWnd
, &r
)) {
6357 rect
.width
= r
.right
- r
.left
;
6358 rect
.height
= r
.bottom
- r
.top
;
6361 // Send a gecko resize event
6362 result
= OnResize(rect
);
6367 void nsWindow::ActivateOtherWindowHelper(HWND aWnd
)
6369 // Find the next window that is enabled, visible, and not minimized.
6370 HWND hwndBelow
= ::GetNextWindow(aWnd
, GW_HWNDNEXT
);
6371 while (hwndBelow
&& (!::IsWindowEnabled(hwndBelow
) || !::IsWindowVisible(hwndBelow
) ||
6372 ::IsIconic(hwndBelow
))) {
6373 hwndBelow
= ::GetNextWindow(hwndBelow
, GW_HWNDNEXT
);
6376 // Push ourselves to the bottom of the stack, then activate the
6378 ::SetWindowPos(aWnd
, HWND_BOTTOM
, 0, 0, 0, 0,
6379 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
6381 ::SetForegroundWindow(hwndBelow
);
6383 // Play the minimize sound while we're here, since that is also
6384 // forgotten when we use SW_SHOWMINIMIZED.
6385 ::PlaySoundW(L
"Minimize", nsnull
, SND_ALIAS
| SND_NODEFAULT
| SND_ASYNC
);
6387 #endif // !defined(WINCE)
6390 void nsWindow::OnWindowPosChanging(LPWINDOWPOS
& info
)
6392 // Update non-client margins if the frame size is changing, and let the
6393 // browser know we are changing size modes, so alternative css can kick in.
6394 // If we're going into fullscreen mode, ignore this, since it'll reset
6395 // margins to normal mode.
6396 if ((info
->flags
& SWP_FRAMECHANGED
&& !(info
->flags
& SWP_NOSIZE
)) &&
6397 mSizeMode
!= nsSizeMode_Fullscreen
) {
6399 pl
.length
= sizeof(pl
);
6400 ::GetWindowPlacement(mWnd
, &pl
);
6402 if (pl
.showCmd
== SW_SHOWMAXIMIZED
)
6403 sizeMode
= (mFullscreenMode
? nsSizeMode_Fullscreen
: nsSizeMode_Maximized
);
6404 else if (pl
.showCmd
== SW_SHOWMINIMIZED
)
6405 sizeMode
= nsSizeMode_Minimized
;
6407 sizeMode
= nsSizeMode_Normal
;
6409 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
6412 event
.mSizeMode
= static_cast<nsSizeMode
>(sizeMode
);
6413 DispatchWindowEvent(&event
);
6415 UpdateNonClientMargins(sizeMode
, PR_FALSE
);
6418 // enforce local z-order rules
6419 if (!(info
->flags
& SWP_NOZORDER
)) {
6420 HWND hwndAfter
= info
->hwndInsertAfter
;
6422 nsZLevelEvent
event(PR_TRUE
, NS_SETZLEVEL
, this);
6423 nsWindow
*aboveWindow
= 0;
6427 if (hwndAfter
== HWND_BOTTOM
)
6428 event
.mPlacement
= nsWindowZBottom
;
6429 else if (hwndAfter
== HWND_TOP
|| hwndAfter
== HWND_TOPMOST
|| hwndAfter
== HWND_NOTOPMOST
)
6430 event
.mPlacement
= nsWindowZTop
;
6432 event
.mPlacement
= nsWindowZRelative
;
6433 aboveWindow
= GetNSWindowPtr(hwndAfter
);
6435 event
.mReqBelow
= aboveWindow
;
6436 event
.mActualBelow
= nsnull
;
6438 event
.mImmediate
= PR_FALSE
;
6439 event
.mAdjusted
= PR_FALSE
;
6440 DispatchWindowEvent(&event
);
6442 if (event
.mAdjusted
) {
6443 if (event
.mPlacement
== nsWindowZBottom
)
6444 info
->hwndInsertAfter
= HWND_BOTTOM
;
6445 else if (event
.mPlacement
== nsWindowZTop
)
6446 info
->hwndInsertAfter
= HWND_TOP
;
6448 info
->hwndInsertAfter
= (HWND
)event
.mActualBelow
->GetNativeData(NS_NATIVE_WINDOW
);
6451 NS_IF_RELEASE(event
.mActualBelow
);
6453 // prevent rude external programs from making hidden window visible
6454 if (mWindowType
== eWindowType_invisible
)
6455 info
->flags
&= ~SWP_SHOWWINDOW
;
6459 void nsWindow::UserActivity()
6461 // Check if we have the idle service, if not we try to get it.
6462 if (!mIdleService
) {
6463 mIdleService
= do_GetService("@mozilla.org/widget/idleservice;1");
6466 // Check that we now have the idle service.
6468 mIdleService
->ResetIdleTimeOut();
6472 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
6473 PRBool
nsWindow::OnTouch(WPARAM wParam
, LPARAM lParam
)
6475 PRUint32 cInputs
= LOWORD(wParam
);
6476 PTOUCHINPUT pInputs
= new TOUCHINPUT
[cInputs
];
6478 if (mGesture
.GetTouchInputInfo((HTOUCHINPUT
)lParam
, cInputs
, pInputs
)) {
6479 for (PRUint32 i
= 0; i
< cInputs
; i
++) {
6481 if (pInputs
[i
].dwFlags
& TOUCHEVENTF_MOVE
) {
6482 msg
= NS_MOZTOUCH_MOVE
;
6483 } else if (pInputs
[i
].dwFlags
& TOUCHEVENTF_DOWN
) {
6484 msg
= NS_MOZTOUCH_DOWN
;
6485 } else if (pInputs
[i
].dwFlags
& TOUCHEVENTF_UP
) {
6486 msg
= NS_MOZTOUCH_UP
;
6491 nsPointWin touchPoint
;
6492 touchPoint
.x
= TOUCH_COORD_TO_PIXEL(pInputs
[i
].x
);
6493 touchPoint
.y
= TOUCH_COORD_TO_PIXEL(pInputs
[i
].y
);
6494 touchPoint
.ScreenToClient(mWnd
);
6496 nsMozTouchEvent
touchEvent(PR_TRUE
, msg
, this, pInputs
[i
].dwID
);
6497 touchEvent
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6498 touchEvent
.refPoint
= touchPoint
;
6500 nsEventStatus status
;
6501 DispatchEvent(&touchEvent
, status
);
6506 mGesture
.CloseTouchInputHandle((HTOUCHINPUT
)lParam
);
6511 // Gesture event processing. Handles WM_GESTURE events.
6513 PRBool
nsWindow::OnGesture(WPARAM wParam
, LPARAM lParam
)
6515 // Treatment for pan events which translate into scroll events:
6516 if (mGesture
.IsPanEvent(lParam
)) {
6517 nsMouseScrollEvent
event(PR_TRUE
, NS_MOUSE_PIXEL_SCROLL
, this);
6519 if ( !mGesture
.ProcessPanMessage(mWnd
, wParam
, lParam
) )
6520 return PR_FALSE
; // ignore
6522 nsEventStatus status
;
6524 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6525 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6526 event
.isMeta
= PR_FALSE
;
6527 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6529 event
.time
= ::GetMessageTime();
6530 event
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6532 PRBool endFeedback
= PR_TRUE
;
6534 PRInt32 scrollOverflowX
= 0;
6535 PRInt32 scrollOverflowY
= 0;
6537 if (mGesture
.PanDeltaToPixelScrollX(event
)) {
6538 DispatchEvent(&event
, status
);
6539 scrollOverflowX
= event
.scrollOverflow
;
6542 if (mGesture
.PanDeltaToPixelScrollY(event
)) {
6543 DispatchEvent(&event
, status
);
6544 scrollOverflowY
= event
.scrollOverflow
;
6547 if (mDisplayPanFeedback
) {
6548 mGesture
.UpdatePanFeedbackX(mWnd
, scrollOverflowX
, endFeedback
);
6549 mGesture
.UpdatePanFeedbackY(mWnd
, scrollOverflowY
, endFeedback
);
6550 mGesture
.PanFeedbackFinalize(mWnd
, endFeedback
);
6553 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
6558 // Other gestures translate into simple gesture events:
6559 nsSimpleGestureEvent
event(PR_TRUE
, 0, this, 0, 0.0);
6560 if ( !mGesture
.ProcessGestureMessage(mWnd
, wParam
, lParam
, event
) ) {
6561 return PR_FALSE
; // fall through to DefWndProc
6564 // Polish up and send off the new event
6565 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6566 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6567 event
.isMeta
= PR_FALSE
;
6568 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6570 event
.time
= ::GetMessageTime();
6571 event
.inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
;
6573 nsEventStatus status
;
6574 DispatchEvent(&event
, status
);
6575 if (status
== nsEventStatus_eIgnore
) {
6576 return PR_FALSE
; // Ignored, fall through
6579 // Only close this if we process and return true.
6580 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
6582 return PR_TRUE
; // Handled
6584 #endif // !defined(WINCE)
6587 PRUint16
nsWindow::GetMouseInputSource()
6589 PRUint16 inputSource
= nsIDOMNSMouseEvent::MOZ_SOURCE_MOUSE
;
6590 LPARAM lParamExtraInfo
= ::GetMessageExtraInfo();
6591 if ((lParamExtraInfo
& TABLET_INK_SIGNATURE
) == TABLET_INK_CHECK
) {
6592 inputSource
= (lParamExtraInfo
& TABLET_INK_TOUCH
) ?
6593 PRUint16(nsIDOMNSMouseEvent::MOZ_SOURCE_TOUCH
) : nsIDOMNSMouseEvent::MOZ_SOURCE_PEN
;
6599 * OnMouseWheel - mouse wheele event processing. This was originally embedded
6600 * within the message case block. If returning true result should be returned
6601 * immediately (no more processing).
6603 PRBool
nsWindow::OnMouseWheel(UINT msg
, WPARAM wParam
, LPARAM lParam
, PRBool
& getWheelInfo
, PRBool
& result
, LRESULT
*aRetValue
)
6605 // Handle both flavors of mouse wheel events.
6606 static int iDeltaPerLine
, iDeltaPerChar
;
6607 static ULONG ulScrollLines
, ulScrollChars
= 1;
6608 static int currentVDelta
, currentHDelta
;
6609 static HWND currentWindow
= 0;
6611 PRBool isVertical
= msg
== WM_MOUSEWHEEL
;
6613 // Get mouse wheel metrics (but only once).
6615 getWheelInfo
= PR_FALSE
;
6617 SystemParametersInfo (SPI_GETWHEELSCROLLLINES
, 0, &ulScrollLines
, 0);
6619 // ulScrollLines usually equals 3 or 0 (for no scrolling)
6620 // WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
6622 // However, if ulScrollLines > WHEEL_DELTA, we assume that
6623 // the mouse driver wants a page scroll. The docs state that
6624 // ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
6625 // since some mouse drivers use an arbitrary large number instead,
6626 // we have to handle that as well.
6629 if (ulScrollLines
) {
6630 if (ulScrollLines
<= WHEEL_DELTA
) {
6631 iDeltaPerLine
= WHEEL_DELTA
/ ulScrollLines
;
6633 ulScrollLines
= WHEEL_PAGESCROLL
;
6637 if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0,
6638 &ulScrollChars
, 0)) {
6639 // Note that we may always fail to get the value before Win Vista.
6644 if (ulScrollChars
) {
6645 if (ulScrollChars
<= WHEEL_DELTA
) {
6646 iDeltaPerChar
= WHEEL_DELTA
/ ulScrollChars
;
6648 ulScrollChars
= WHEEL_PAGESCROLL
;
6653 if ((isVertical
&& ulScrollLines
!= WHEEL_PAGESCROLL
&& !iDeltaPerLine
) ||
6654 (!isVertical
&& ulScrollChars
!= WHEEL_PAGESCROLL
&& !iDeltaPerChar
))
6655 return PR_FALSE
; // break
6657 // The mousewheel event will be dispatched to the toplevel
6658 // window. We need to give it to the child window
6660 if (!HandleScrollingPlugins(msg
, wParam
, lParam
, result
, aRetValue
, quit
))
6661 return quit
; // return immediately if its not our window
6663 // We should cancel the surplus delta if the current window is not
6664 // same as previous.
6665 if (currentWindow
!= mWnd
) {
6668 currentWindow
= mWnd
;
6671 nsMouseScrollEvent
scrollEvent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
6672 scrollEvent
.delta
= 0;
6674 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsVertical
;
6675 if (ulScrollLines
== WHEEL_PAGESCROLL
) {
6676 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6677 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? -1 : 1;
6679 currentVDelta
-= (short) HIWORD (wParam
);
6680 if (PR_ABS(currentVDelta
) >= iDeltaPerLine
) {
6681 scrollEvent
.delta
= currentVDelta
/ iDeltaPerLine
;
6682 currentVDelta
%= iDeltaPerLine
;
6686 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsHorizontal
;
6687 if (ulScrollChars
== WHEEL_PAGESCROLL
) {
6688 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6689 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? 1 : -1;
6691 currentHDelta
+= (short) HIWORD (wParam
);
6692 if (PR_ABS(currentHDelta
) >= iDeltaPerChar
) {
6693 scrollEvent
.delta
= currentHDelta
/ iDeltaPerChar
;
6694 currentHDelta
%= iDeltaPerChar
;
6699 if (!scrollEvent
.delta
) {
6700 // We store the wheel delta, and it will be used next wheel message, so,
6701 // we consume this message actually. We shouldn't call next wndproc.
6703 return PR_FALSE
; // break
6707 // The event may go to a plug-in which already dispatched this message.
6708 // Then, the event can cause deadlock. We should unlock the sender here.
6709 ::ReplyMessage(isVertical
? 0 : TRUE
);
6712 scrollEvent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6713 scrollEvent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6714 scrollEvent
.isMeta
= PR_FALSE
;
6715 scrollEvent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6716 InitEvent(scrollEvent
);
6717 if (nsnull
!= mEventCallback
) {
6718 result
= DispatchWindowEvent(&scrollEvent
);
6720 // Note that we should return zero if we process WM_MOUSEWHEEL.
6721 // But if we process WM_MOUSEHWHEEL, we should return non-zero.
6724 *aRetValue
= isVertical
? 0 : TRUE
;
6726 return PR_FALSE
; // break;
6730 StringCaseInsensitiveEquals(const PRUnichar
* aChars1
, const PRUint32 aNumChars1
,
6731 const PRUnichar
* aChars2
, const PRUint32 aNumChars2
)
6733 if (aNumChars1
!= aNumChars2
)
6736 nsCaseInsensitiveStringComparator comp
;
6737 return comp(aChars1
, aChars2
, aNumChars1
, aNumChars2
) == 0;
6740 UINT
nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode
)
6743 switch (aNativeKeyCode
) {
6744 case VK_OEM_1
: return NS_VK_SEMICOLON
; // 0xBA, For the US standard keyboard, the ';:' key
6745 case VK_OEM_PLUS
: return NS_VK_ADD
; // 0xBB, For any country/region, the '+' key
6746 case VK_OEM_MINUS
: return NS_VK_SUBTRACT
; // 0xBD, For any country/region, the '-' key
6750 return aNativeKeyCode
;
6754 PRBool
nsWindow::IsRedirectedKeyDownMessage(const MSG
&aMsg
)
6756 return (aMsg
.message
== WM_KEYDOWN
|| aMsg
.message
== WM_SYSKEYDOWN
) &&
6757 (sRedirectedKeyDown
.message
== aMsg
.message
&&
6758 GetScanCode(sRedirectedKeyDown
.lParam
) == GetScanCode(aMsg
.lParam
));
6762 * nsWindow::OnKeyDown peeks into the message queue and pulls out
6763 * WM_CHAR messages for processing. During testing we don't want to
6764 * mess with the real message queue. Instead we pass a
6765 * pseudo-WM_CHAR-message using this structure, and OnKeyDown will use
6766 * that as if it was in the message queue, and refrain from actually
6767 * looking at or touching the message queue.
6769 LRESULT
nsWindow::OnKeyDown(const MSG
&aMsg
,
6770 nsModifierKeyState
&aModKeyState
,
6771 PRBool
*aEventDispatched
,
6772 nsFakeCharMessage
* aFakeCharMessage
)
6774 UINT virtualKeyCode
=
6775 aMsg
.wParam
!= VK_PROCESSKEY
? aMsg
.wParam
: ::ImmGetVirtualKey(mWnd
);
6778 gKbdLayout
.OnKeyDown(virtualKeyCode
);
6781 // Use only DOMKeyCode for XP processing.
6782 // Use virtualKeyCode for gKbdLayout and native processing.
6783 UINT DOMKeyCode
= nsIMM32Handler::IsComposingOn(this) ?
6784 virtualKeyCode
: MapFromNativeToDOM(virtualKeyCode
);
6787 //printf("In OnKeyDown virt: %d\n", DOMKeyCode);
6790 static PRBool sRedirectedKeyDownEventPreventedDefault
= PR_FALSE
;
6792 if (aFakeCharMessage
|| !IsRedirectedKeyDownMessage(aMsg
)) {
6793 HIMC oldIMC
= mOldIMC
;
6795 DispatchKeyEvent(NS_KEY_DOWN
, 0, nsnull
, DOMKeyCode
, &aMsg
, aModKeyState
);
6796 if (aEventDispatched
) {
6797 *aEventDispatched
= PR_TRUE
;
6800 // If IMC wasn't associated to the window but is associated it now (i.e.,
6801 // focus is moved from a non-editable editor to an editor by keydown
6802 // event handler), WM_CHAR and WM_SYSCHAR shouldn't cause first character
6803 // inputting if IME is opened. But then, we should redirect the native
6804 // keydown message to IME.
6805 // However, note that if focus has been already moved to another
6806 // application, we shouldn't redirect the message to it because the keydown
6807 // message is processed by us, so, nobody shouldn't process it.
6808 HWND focusedWnd
= ::GetFocus();
6809 if (!noDefault
&& !aFakeCharMessage
&& oldIMC
&& !mOldIMC
&& focusedWnd
&&
6810 !PluginHasFocus()) {
6811 RemoveNextCharMessage(focusedWnd
);
6814 keyinput
.type
= INPUT_KEYBOARD
;
6815 keyinput
.ki
.wVk
= aMsg
.wParam
;
6816 keyinput
.ki
.wScan
= GetScanCode(aMsg
.lParam
);
6817 keyinput
.ki
.dwFlags
= KEYEVENTF_SCANCODE
;
6818 if (IsExtendedScanCode(aMsg
.lParam
)) {
6819 keyinput
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
6821 keyinput
.ki
.time
= 0;
6822 keyinput
.ki
.dwExtraInfo
= NULL
;
6824 sRedirectedKeyDownEventPreventedDefault
= noDefault
;
6825 sRedirectedKeyDown
= aMsg
;
6827 ::SendInput(1, &keyinput
, sizeof(keyinput
));
6829 // Return here. We shouldn't dispatch keypress event for this WM_KEYDOWN.
6830 // If it's needed, it will be dispatched after next (redirected)
6835 if (mOnDestroyCalled
) {
6836 // If this was destroyed by the keydown event handler, we shouldn't
6837 // dispatch keypress event on this window.
6841 noDefault
= sRedirectedKeyDownEventPreventedDefault
;
6842 // If this is redirected keydown message, we have dispatched the keydown
6844 if (aEventDispatched
) {
6845 *aEventDispatched
= PR_TRUE
;
6849 ForgetRedirectedKeyDownMessage();
6851 // If the key was processed by IME, we shouldn't dispatch keypress event.
6852 if (aMsg
.wParam
== VK_PROCESSKEY
) {
6856 // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
6857 // for almost all keys
6858 switch (DOMKeyCode
) {
6862 case NS_VK_CAPS_LOCK
:
6863 case NS_VK_NUM_LOCK
:
6864 case NS_VK_SCROLL_LOCK
: return noDefault
;
6867 PRUint32 extraFlags
= (noDefault
? NS_EVENT_FLAG_NO_DEFAULT
: 0);
6869 BOOL gotMsg
= aFakeCharMessage
||
6870 ::PeekMessageW(&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
6871 // Enter and backspace are always handled here to avoid for example the
6872 // confusion between ctrl-enter and ctrl-J.
6873 if (DOMKeyCode
== NS_VK_RETURN
|| DOMKeyCode
== NS_VK_BACK
||
6874 ((aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)
6878 && !gKbdLayout
.IsDeadKey() && KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)))
6881 // Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
6882 // They can be more than one because of:
6883 // * Dead-keys not pairing with base character
6884 // * Some keyboard layouts may map up to 4 characters to the single key
6885 PRBool anyCharMessagesRemoved
= PR_FALSE
;
6887 if (aFakeCharMessage
) {
6888 anyCharMessagesRemoved
= PR_TRUE
;
6890 while (gotMsg
&& (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
))
6892 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6893 ("%s charCode=%d scanCode=%d\n", msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
6894 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
6895 RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST
, WM_KEYLAST
);
6896 anyCharMessagesRemoved
= PR_TRUE
;
6898 gotMsg
= ::PeekMessageW (&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
6902 if (!anyCharMessagesRemoved
&& DOMKeyCode
== NS_VK_BACK
&&
6903 nsIMM32Handler::IsDoingKakuteiUndo(mWnd
)) {
6904 NS_ASSERTION(!aFakeCharMessage
,
6905 "We shouldn't be touching the real msg queue");
6906 RemoveMessageAndDispatchPluginEvent(WM_CHAR
, WM_CHAR
);
6910 (aFakeCharMessage
||
6911 msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
|| msg
.message
== WM_DEADCHAR
)) {
6912 if (aFakeCharMessage
)
6913 return OnCharRaw(aFakeCharMessage
->mCharCode
,
6914 aFakeCharMessage
->mScanCode
, aModKeyState
, extraFlags
);
6916 // If prevent default set for keydown, do same for keypress
6917 ::GetMessageW(&msg
, mWnd
, msg
.message
, msg
.message
);
6919 if (msg
.message
== WM_DEADCHAR
) {
6920 if (!PluginHasFocus())
6923 // We need to send the removed message to focused plug-in.
6924 DispatchPluginEvent(msg
);
6928 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
6929 ("%s charCode=%d scanCode=%d\n",
6930 msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
6931 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
6933 BOOL result
= OnChar(msg
, aModKeyState
, nsnull
, extraFlags
);
6934 // If a syschar keypress wasn't processed, Windows may want to
6935 // handle it to activate a native menu.
6936 if (!result
&& msg
.message
== WM_SYSCHAR
)
6937 ::DefWindowProcW(mWnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
6941 else if (!aModKeyState
.mIsControlDown
&& !aModKeyState
.mIsAltDown
&&
6942 (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
) ||
6943 KeyboardLayout::IsNumpadKey(virtualKeyCode
)))
6945 // If this is simple KeyDown event but next message is not WM_CHAR,
6946 // this event may not input text, so we should ignore this event.
6948 return PluginHasFocus() && noDefault
;
6951 if (gKbdLayout
.IsDeadKey ())
6952 return PluginHasFocus() && noDefault
;
6954 PRUint8 shiftStates
[5];
6955 PRUnichar uniChars
[5];
6956 PRUnichar shiftedChars
[5] = {0, 0, 0, 0, 0};
6957 PRUnichar unshiftedChars
[5] = {0, 0, 0, 0, 0};
6958 PRUnichar shiftedLatinChar
= 0;
6959 PRUnichar unshiftedLatinChar
= 0;
6960 PRUint32 numOfUniChars
= 0;
6961 PRUint32 numOfShiftedChars
= 0;
6962 PRUint32 numOfUnshiftedChars
= 0;
6963 PRUint32 numOfShiftStates
= 0;
6965 switch (virtualKeyCode
) {
6966 // keys to be sent as characters
6967 case VK_ADD
: uniChars
[0] = '+'; numOfUniChars
= 1; break;
6968 case VK_SUBTRACT
: uniChars
[0] = '-'; numOfUniChars
= 1; break;
6969 case VK_DIVIDE
: uniChars
[0] = '/'; numOfUniChars
= 1; break;
6970 case VK_MULTIPLY
: uniChars
[0] = '*'; numOfUniChars
= 1; break;
6981 uniChars
[0] = virtualKeyCode
- VK_NUMPAD0
+ '0';
6985 if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)) {
6986 numOfUniChars
= numOfShiftStates
=
6987 gKbdLayout
.GetUniChars(uniChars
, shiftStates
,
6988 NS_ARRAY_LENGTH(uniChars
));
6991 if (aModKeyState
.mIsControlDown
^ aModKeyState
.mIsAltDown
) {
6992 PRUint8 capsLockState
= (::GetKeyState(VK_CAPITAL
) & 1) ? eCapsLock
: 0;
6993 numOfUnshiftedChars
=
6994 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
, capsLockState
,
6995 unshiftedChars
, NS_ARRAY_LENGTH(unshiftedChars
));
6997 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
,
6998 capsLockState
| eShift
,
6999 shiftedChars
, NS_ARRAY_LENGTH(shiftedChars
));
7001 // The current keyboard cannot input alphabets or numerics,
7002 // we should append them for Shortcut/Access keys.
7003 // E.g., for Cyrillic keyboard layout.
7004 if (NS_VK_A
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_Z
) {
7005 shiftedLatinChar
= unshiftedLatinChar
= DOMKeyCode
;
7007 shiftedLatinChar
+= 0x20;
7009 unshiftedLatinChar
+= 0x20;
7010 if (unshiftedLatinChar
== unshiftedChars
[0] &&
7011 shiftedLatinChar
== shiftedChars
[0]) {
7012 shiftedLatinChar
= unshiftedLatinChar
= 0;
7016 if (NS_VK_0
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_9
) {
7019 switch (virtualKeyCode
) {
7020 case VK_OEM_PLUS
: ch
= '+'; break;
7021 case VK_OEM_MINUS
: ch
= '-'; break;
7024 if (ch
&& unshiftedChars
[0] != ch
&& shiftedChars
[0] != ch
) {
7025 // Windows has assigned a virtual key code to the key even though
7026 // the character can't be produced with this key. That probably
7027 // means the character can't be produced with any key in the
7028 // current layout and so the assignment is based on a QWERTY
7029 // layout. Append this code so that users can access the shortcut.
7030 unshiftedLatinChar
= ch
;
7034 // If the charCode is not ASCII character, we should replace the
7035 // charCode with ASCII character only when Ctrl is pressed.
7036 // But don't replace the charCode when the charCode is not same as
7037 // unmodified characters. In such case, Ctrl is sometimes used for a
7038 // part of character inputting key combination like Shift.
7039 if (aModKeyState
.mIsControlDown
) {
7040 PRUint8 currentState
= eCtrl
;
7041 if (aModKeyState
.mIsShiftDown
)
7042 currentState
|= eShift
;
7045 aModKeyState
.mIsShiftDown
? shiftedLatinChar
: unshiftedLatinChar
;
7047 (numOfUniChars
== 0 ||
7048 StringCaseInsensitiveEquals(uniChars
, numOfUniChars
,
7049 aModKeyState
.mIsShiftDown
? shiftedChars
: unshiftedChars
,
7050 aModKeyState
.mIsShiftDown
? numOfShiftedChars
:
7051 numOfUnshiftedChars
))) {
7052 numOfUniChars
= numOfShiftStates
= 1;
7054 shiftStates
[0] = currentState
;
7060 if (numOfUniChars
> 0 || numOfShiftedChars
> 0 || numOfUnshiftedChars
> 0) {
7061 PRUint32 num
= PR_MAX(numOfUniChars
,
7062 PR_MAX(numOfShiftedChars
, numOfUnshiftedChars
));
7063 PRUint32 skipUniChars
= num
- numOfUniChars
;
7064 PRUint32 skipShiftedChars
= num
- numOfShiftedChars
;
7065 PRUint32 skipUnshiftedChars
= num
- numOfUnshiftedChars
;
7066 UINT keyCode
= numOfUniChars
== 0 ? DOMKeyCode
: 0;
7067 for (PRUint32 cnt
= 0; cnt
< num
; cnt
++) {
7068 PRUint16 uniChar
, shiftedChar
, unshiftedChar
;
7069 uniChar
= shiftedChar
= unshiftedChar
= 0;
7070 if (skipUniChars
<= cnt
) {
7071 if (cnt
- skipUniChars
< numOfShiftStates
) {
7072 // If key in combination with Alt and/or Ctrl produces a different
7073 // character than without them then do not report these flags
7074 // because it is separate keyboard layout shift state. If dead-key
7075 // and base character does not produce a valid composite character
7076 // then both produced dead-key character and following base
7077 // character may have different modifier flags, too.
7078 aModKeyState
.mIsShiftDown
=
7079 (shiftStates
[cnt
- skipUniChars
] & eShift
) != 0;
7080 aModKeyState
.mIsControlDown
=
7081 (shiftStates
[cnt
- skipUniChars
] & eCtrl
) != 0;
7082 aModKeyState
.mIsAltDown
=
7083 (shiftStates
[cnt
- skipUniChars
] & eAlt
) != 0;
7085 uniChar
= uniChars
[cnt
- skipUniChars
];
7087 if (skipShiftedChars
<= cnt
)
7088 shiftedChar
= shiftedChars
[cnt
- skipShiftedChars
];
7089 if (skipUnshiftedChars
<= cnt
)
7090 unshiftedChar
= unshiftedChars
[cnt
- skipUnshiftedChars
];
7091 nsAutoTArray
<nsAlternativeCharCode
, 5> altArray
;
7093 if (shiftedChar
|| unshiftedChar
) {
7094 nsAlternativeCharCode
chars(unshiftedChar
, shiftedChar
);
7095 altArray
.AppendElement(chars
);
7097 if (cnt
== num
- 1 && (unshiftedLatinChar
|| shiftedLatinChar
)) {
7098 nsAlternativeCharCode
chars(unshiftedLatinChar
, shiftedLatinChar
);
7099 altArray
.AppendElement(chars
);
7102 DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, &altArray
,
7103 keyCode
, nsnull
, aModKeyState
, extraFlags
);
7106 DispatchKeyEvent(NS_KEY_PRESS
, 0, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
7111 UINT unichar
= ::MapVirtualKey(virtualKeyCode
, MAPVK_VK_TO_CHAR
);
7112 // Check for dead characters or no mapping
7113 if (unichar
& 0x80) {
7116 DispatchKeyEvent(NS_KEY_PRESS
, unichar
, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
7125 LRESULT
nsWindow::OnKeyUp(const MSG
&aMsg
,
7126 nsModifierKeyState
&aModKeyState
,
7127 PRBool
*aEventDispatched
)
7129 UINT virtualKeyCode
= aMsg
.wParam
;
7131 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
7132 ("nsWindow::OnKeyUp VK=%d\n", virtualKeyCode
));
7134 if (!nsIMM32Handler::IsComposingOn(this)) {
7135 virtualKeyCode
= MapFromNativeToDOM(virtualKeyCode
);
7138 if (aEventDispatched
)
7139 *aEventDispatched
= PR_TRUE
;
7140 return DispatchKeyEvent(NS_KEY_UP
, 0, nsnull
, virtualKeyCode
, &aMsg
,
7145 LRESULT
nsWindow::OnChar(const MSG
&aMsg
, nsModifierKeyState
&aModKeyState
,
7146 PRBool
*aEventDispatched
, PRUint32 aFlags
)
7148 return OnCharRaw(aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF, aModKeyState
,
7149 aFlags
, &aMsg
, aEventDispatched
);
7153 LRESULT
nsWindow::OnCharRaw(UINT charCode
, UINT aScanCode
,
7154 nsModifierKeyState
&aModKeyState
, PRUint32 aFlags
,
7155 const MSG
*aMsg
, PRBool
*aEventDispatched
)
7157 // ignore [shift+]alt+space so the OS can handle it
7158 if (aModKeyState
.mIsAltDown
&& !aModKeyState
.mIsControlDown
&&
7159 IS_VK_DOWN(NS_VK_SPACE
)) {
7163 // Ignore Ctrl+Enter (bug 318235)
7164 if (aModKeyState
.mIsControlDown
&& charCode
== 0xA) {
7168 // WM_CHAR with Control and Alt (== AltGr) down really means a normal character
7169 PRBool saveIsAltDown
= aModKeyState
.mIsAltDown
;
7170 PRBool saveIsControlDown
= aModKeyState
.mIsControlDown
;
7171 if (aModKeyState
.mIsAltDown
&& aModKeyState
.mIsControlDown
)
7172 aModKeyState
.mIsAltDown
= aModKeyState
.mIsControlDown
= PR_FALSE
;
7176 if (nsIMM32Handler::IsComposingOn(this)) {
7180 if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1A) { // Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
7181 // need to account for shift here. bug 16486
7182 if (aModKeyState
.mIsShiftDown
)
7183 uniChar
= charCode
- 1 + 'A';
7185 uniChar
= charCode
- 1 + 'a';
7188 else if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1F) {
7189 // Fix for 50255 - <ctrl><[> and <ctrl><]> are not being processed.
7190 // also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
7191 // for some reason the keypress handler need to have the uniChar code set
7192 // with the addition of a upper case A not the lower case.
7193 uniChar
= charCode
- 1 + 'A';
7195 } else { // 0x20 - SPACE, 0x3D - EQUALS
7196 if (charCode
< 0x20 || (charCode
== 0x3D && aModKeyState
.mIsControlDown
)) {
7204 // Keep the characters unshifted for shortcuts and accesskeys and make sure
7205 // that numbers are always passed as such (among others: bugs 50255 and 351310)
7206 if (uniChar
&& (aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)) {
7207 UINT virtualKeyCode
= ::MapVirtualKeyEx(aScanCode
, MAPVK_VSC_TO_VK
,
7208 gKbdLayout
.GetLayout());
7209 UINT unshiftedCharCode
=
7210 virtualKeyCode
>= '0' && virtualKeyCode
<= '9' ? virtualKeyCode
:
7211 aModKeyState
.mIsShiftDown
? ::MapVirtualKeyEx(virtualKeyCode
,
7213 gKbdLayout
.GetLayout()) : 0;
7214 // ignore diacritics (top bit set) and key mapping errors (char code 0)
7215 if ((INT
)unshiftedCharCode
> 0)
7216 uniChar
= unshiftedCharCode
;
7219 // Fix for bug 285161 (and 295095) which was caused by the initial fix for bug 178110.
7220 // When pressing (alt|ctrl)+char, the char must be lowercase unless shift is
7222 if (!aModKeyState
.mIsShiftDown
&& (saveIsAltDown
|| saveIsControlDown
)) {
7223 uniChar
= towlower(uniChar
);
7226 PRBool result
= DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, nsnull
,
7227 charCode
, aMsg
, aModKeyState
, aFlags
);
7228 if (aEventDispatched
)
7229 *aEventDispatched
= PR_TRUE
;
7230 aModKeyState
.mIsAltDown
= saveIsAltDown
;
7231 aModKeyState
.mIsControlDown
= saveIsControlDown
;
7236 nsWindow::SetupKeyModifiersSequence(nsTArray
<KeyPair
>* aArray
, PRUint32 aModifiers
)
7238 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(sModifierKeyMap
); ++i
) {
7239 const PRUint32
* map
= sModifierKeyMap
[i
];
7240 if (aModifiers
& map
[0]) {
7241 aArray
->AppendElement(KeyPair(map
[1], map
[2]));
7247 nsWindow::ConfigureChildren(const nsTArray
<Configuration
>& aConfigurations
)
7249 // XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos
7250 // here, if that helps in some situations. So far I haven't seen a
7252 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
7253 const Configuration
& configuration
= aConfigurations
[i
];
7254 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
7255 NS_ASSERTION(w
->GetParent() == this,
7256 "Configured widget is not a child");
7258 // MSDN says we should do on WinCE this before moving or resizing the window
7259 // See http://msdn.microsoft.com/en-us/library/aa930600.aspx
7260 // We put the region back just below, anyway.
7261 ::SetWindowRgn(w
->mWnd
, NULL
, TRUE
);
7263 nsresult rv
= w
->SetWindowClipRegion(configuration
.mClipRegion
, PR_TRUE
);
7264 NS_ENSURE_SUCCESS(rv
, rv
);
7266 w
->GetBounds(bounds
);
7267 if (bounds
.Size() != configuration
.mBounds
.Size()) {
7268 w
->Resize(configuration
.mBounds
.x
, configuration
.mBounds
.y
,
7269 configuration
.mBounds
.width
, configuration
.mBounds
.height
,
7271 } else if (bounds
.TopLeft() != configuration
.mBounds
.TopLeft()) {
7272 w
->Move(configuration
.mBounds
.x
, configuration
.mBounds
.y
);
7275 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
7276 gfxWindowsPlatform::RENDER_DIRECT2D
||
7277 GetLayerManager()->GetBackendType() != LayerManager::LAYERS_BASIC
) {
7278 // XXX - Workaround for Bug 587508. This will invalidate the part of the
7279 // plugin window that might be touched by moving content somehow. The
7280 // underlying problem should be found and fixed!
7282 r
.Sub(bounds
, configuration
.mBounds
);
7285 w
->Invalidate(r
.GetBounds(), PR_FALSE
);
7288 rv
= w
->SetWindowClipRegion(configuration
.mClipRegion
, PR_FALSE
);
7289 NS_ENSURE_SUCCESS(rv
, rv
);
7295 CreateHRGNFromArray(const nsTArray
<nsIntRect
>& aRects
)
7297 PRInt32 size
= sizeof(RGNDATAHEADER
) + sizeof(RECT
)*aRects
.Length();
7298 nsAutoTArray
<PRUint8
,100> buf
;
7299 if (!buf
.SetLength(size
))
7301 RGNDATA
* data
= reinterpret_cast<RGNDATA
*>(buf
.Elements());
7302 RECT
* rects
= reinterpret_cast<RECT
*>(data
->Buffer
);
7303 data
->rdh
.dwSize
= sizeof(data
->rdh
);
7304 data
->rdh
.iType
= RDH_RECTANGLES
;
7305 data
->rdh
.nCount
= aRects
.Length();
7307 for (PRUint32 i
= 0; i
< aRects
.Length(); ++i
) {
7308 const nsIntRect
& r
= aRects
[i
];
7309 bounds
.UnionRect(bounds
, r
);
7310 ::SetRect(&rects
[i
], r
.x
, r
.y
, r
.XMost(), r
.YMost());
7312 ::SetRect(&data
->rdh
.rcBound
, bounds
.x
, bounds
.y
, bounds
.XMost(), bounds
.YMost());
7313 return ::ExtCreateRegion(NULL
, buf
.Length(), data
);
7316 static const nsTArray
<nsIntRect
>
7317 ArrayFromRegion(const nsIntRegion
& aRegion
)
7319 nsTArray
<nsIntRect
> rects
;
7321 for (nsIntRegionRectIterator
iter(aRegion
); (r
= iter
.Next());) {
7322 rects
.AppendElement(*r
);
7328 nsWindow::SetWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
,
7329 PRBool aIntersectWithExisting
)
7331 if (!aIntersectWithExisting
) {
7332 if (!StoreWindowClipRegion(aRects
))
7335 // In this case still early return if nothing changed.
7336 if (mClipRects
&& mClipRectCount
== aRects
.Length() &&
7339 sizeof(nsIntRect
)*mClipRectCount
) == 0) {
7343 // get current rects
7344 nsTArray
<nsIntRect
> currentRects
;
7345 GetWindowClipRegion(¤tRects
);
7346 // create region from them
7347 nsIntRegion currentRegion
= RegionFromArray(currentRects
);
7348 // create region from new rects
7349 nsIntRegion newRegion
= RegionFromArray(aRects
);
7350 // intersect regions
7351 nsIntRegion intersection
;
7352 intersection
.And(currentRegion
, newRegion
);
7353 // create int rect array from intersection
7354 nsTArray
<nsIntRect
> rects
= ArrayFromRegion(intersection
);
7356 if (!StoreWindowClipRegion(rects
))
7360 HRGN dest
= CreateHRGNFromArray(aRects
);
7362 return NS_ERROR_OUT_OF_MEMORY
;
7364 if (aIntersectWithExisting
) {
7365 HRGN current
= ::CreateRectRgn(0, 0, 0, 0);
7367 if (::GetWindowRgn(mWnd
, current
) != 0 /*ERROR*/) {
7368 ::CombineRgn(dest
, dest
, current
, RGN_AND
);
7370 ::DeleteObject(current
);
7374 if (!::SetWindowRgn(mWnd
, dest
, TRUE
)) {
7375 ::DeleteObject(dest
);
7376 return NS_ERROR_FAILURE
;
7381 // WM_DESTROY event handler
7382 void nsWindow::OnDestroy()
7384 mOnDestroyCalled
= PR_TRUE
;
7386 // Make sure we don't get destroyed in the process of tearing down.
7387 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
7389 // Dispatch the NS_DESTROY event. Must be called before mEventCallback is cleared.
7391 DispatchStandardEvent(NS_DESTROY
);
7393 // Prevent the widget from sending additional events.
7394 mEventCallback
= nsnull
;
7396 // Free our subclass and clear |this| stored in the window props. We will no longer
7397 // receive events from Windows after this point.
7398 SubclassWindow(FALSE
);
7400 // Once mEventCallback is cleared and the subclass is reset, sCurrentWindow can be
7401 // cleared. (It's used in tracking windows for mouse events.)
7402 if (sCurrentWindow
== this)
7403 sCurrentWindow
= nsnull
;
7405 // Disconnects us from our parent, will call our GetParent().
7406 nsBaseWidget::Destroy();
7408 // Release references to children, device context, toolkit, and app shell.
7409 nsBaseWidget::OnDestroy();
7411 // Clear our native parent handle.
7412 // XXX Windows will take care of this in the proper order, and SetParent(nsnull)'s
7413 // remove child on the parent already took place in nsBaseWidget's Destroy call above.
7414 //SetParent(nsnull);
7417 // We have to destroy the native drag target before we null out our window pointer.
7418 EnableDragDrop(PR_FALSE
);
7420 // If we're going away and for some reason we're still the rollup widget, rollup and
7421 // turn off capture.
7422 if ( this == sRollupWidget
) {
7423 if ( sRollupListener
)
7424 sRollupListener
->Rollup(nsnull
, nsnull
);
7425 CaptureRollupEvents(nsnull
, nsnull
, PR_FALSE
, PR_TRUE
);
7428 // If IME is disabled, restore it.
7430 mOldIMC
= ::ImmAssociateContext(mWnd
, mOldIMC
);
7431 NS_ASSERTION(!mOldIMC
, "Another IMC was associated");
7434 // Turn off mouse trails if enabled.
7435 MouseTrailer
* mtrailer
= nsToolkit::gMouseTrailer
;
7437 if (mtrailer
->GetMouseTrailerWindow() == mWnd
)
7438 mtrailer
->DestroyTimer();
7440 if (mtrailer
->GetCaptureWindow() == mWnd
)
7441 mtrailer
->SetCaptureWindow(nsnull
);
7444 // Free GDI window class objects
7446 VERIFY(::DeleteObject(mBrush
));
7450 // Free app icon resources.
7452 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
) 0);
7454 ::DestroyIcon(icon
);
7456 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
) 0);
7458 ::DestroyIcon(icon
);
7460 // Destroy any custom cursor resources.
7462 SetCursor(eCursor_standard
);
7465 // Reset transparency
7466 if (eTransparencyTransparent
== mTransparencyMode
)
7467 SetupTranslucentWindowMemoryBitmap(eTransparencyOpaque
);
7470 #if defined(WINCE_HAVE_SOFTKB)
7471 // Revert the changes made for the software keyboard settings
7472 nsWindowCE::ResetSoftKB(mWnd
);
7476 // Finalize panning feedback to possibly restore window displacement
7477 mGesture
.PanFeedbackFinalize(mWnd
, PR_TRUE
);
7480 // Clear the main HWND.
7485 PRBool
nsWindow::OnMove(PRInt32 aX
, PRInt32 aY
)
7490 nsGUIEvent
event(PR_TRUE
, NS_MOVE
, this);
7492 event
.refPoint
.x
= aX
;
7493 event
.refPoint
.y
= aY
;
7495 return DispatchWindowEvent(&event
);
7498 // Send a resize message to the listener
7499 PRBool
nsWindow::OnResize(nsIntRect
&aWindowRect
)
7501 #ifdef CAIRO_HAS_D2D_SURFACE
7502 if (mD2DWindowSurface
) {
7503 mD2DWindowSurface
= NULL
;
7504 Invalidate(PR_FALSE
);
7508 // call the event callback
7509 if (mEventCallback
) {
7510 nsSizeEvent
event(PR_TRUE
, NS_SIZE
, this);
7512 event
.windowSize
= &aWindowRect
;
7514 if (::GetWindowRect(mWnd
, &r
)) {
7515 event
.mWinWidth
= PRInt32(r
.right
- r
.left
);
7516 event
.mWinHeight
= PRInt32(r
.bottom
- r
.top
);
7518 event
.mWinWidth
= 0;
7519 event
.mWinHeight
= 0;
7523 printf("[%X] OnResize: client:(%d x %d x %d x %d) window:(%d x %d)\n", this,
7524 aWindowRect
.x
, aWindowRect
.y
, aWindowRect
.width
, aWindowRect
.height
,
7525 event
.mWinWidth
, event
.mWinHeight
);
7528 return DispatchWindowEvent(&event
);
7534 #if !defined(WINCE) // implemented in nsWindowCE.cpp
7535 PRBool
nsWindow::OnHotKey(WPARAM wParam
, LPARAM lParam
)
7539 #endif // !defined(WINCE)
7541 void nsWindow::OnSettingsChange(WPARAM wParam
, LPARAM lParam
)
7543 if (mWindowType
== eWindowType_dialog
||
7544 mWindowType
== eWindowType_toplevel
)
7545 nsWindowGfx::OnSettingsChangeGfx(wParam
);
7549 PRBool
nsWindow::IsOurProcessWindow(HWND aHWND
)
7554 DWORD processId
= 0;
7555 ::GetWindowThreadProcessId(aHWND
, &processId
);
7556 return processId
== ::GetCurrentProcessId();
7560 HWND
nsWindow::FindOurProcessWindow(HWND aHWND
)
7562 for (HWND wnd
= ::GetParent(aHWND
); wnd
; wnd
= ::GetParent(wnd
)) {
7563 if (IsOurProcessWindow(wnd
)) {
7570 // Scrolling helper function for handling plugins.
7571 // Return value indicates whether the calling function should handle this
7572 // aHandled indicates whether this was handled at all
7573 // aQuitProcessing tells whether or not to continue processing the message
7574 PRBool
nsWindow::HandleScrollingPlugins(UINT aMsg
, WPARAM aWParam
,
7575 LPARAM aLParam
, PRBool
& aHandled
,
7577 PRBool
& aQuitProcessing
)
7579 // The scroll event will be dispatched to the toplevel
7580 // window. We need to give it to the child window
7581 aQuitProcessing
= PR_FALSE
; // default is to not stop processing
7583 DWORD dwPoints
= ::GetMessagePos();
7584 point
.x
= GET_X_LPARAM(dwPoints
);
7585 point
.y
= GET_Y_LPARAM(dwPoints
);
7587 static PRBool sIsProcessing
= PR_FALSE
;
7588 if (sIsProcessing
) {
7589 return PR_TRUE
; // the caller should handle this.
7592 static PRBool sMayBeUsingLogitechMouse
= PR_FALSE
;
7593 if (aMsg
== WM_MOUSEHWHEEL
) {
7594 // Logitech (Logicool) mouse driver (confirmed with 4.82.11 and MX-1100)
7595 // always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs one
7596 // message at first time, this time, ::GetMessagePos works fine.
7597 // Then, we will return 0 (0 means we process it) to the message. Then, the
7598 // driver will POST the same messages continuously during the wheel tilted.
7599 // But ::GetMessagePos API always returns (0, 0), even if the actual mouse
7600 // cursor isn't 0,0. Therefore, we cannot trust the result of
7601 // ::GetMessagePos API if the sender is the driver.
7602 if (!sMayBeUsingLogitechMouse
&& aLParam
== 0 && (DWORD
)aLParam
!= dwPoints
&&
7603 ::InSendMessage()) {
7604 sMayBeUsingLogitechMouse
= PR_TRUE
;
7605 } else if (sMayBeUsingLogitechMouse
&& aLParam
!= 0 && ::InSendMessage()) {
7606 // The user has changed the mouse from Logitech's to another one (e.g.,
7607 // the user has changed to the touchpad of the notebook.
7608 sMayBeUsingLogitechMouse
= PR_FALSE
;
7610 // If the WM_MOUSEHWHEEL comes from Logitech's mouse driver, and the
7611 // ::GetMessagePos isn't correct, probably, we should use ::GetCursorPos
7613 if (sMayBeUsingLogitechMouse
&& aLParam
== 0 && dwPoints
== 0) {
7614 ::GetCursorPos(&point
);
7618 HWND destWnd
= ::WindowFromPoint(point
);
7619 // Since we receive scroll events for as long as
7620 // we are focused, it's entirely possible that there
7621 // is another app's window or no window under the
7625 // No window is under the pointer
7626 return PR_FALSE
; // break, but continue processing
7629 nsWindow
* destWindow
;
7631 // We don't handle the message if the found window belongs to another
7632 // process's top window. If it belongs window, that is a plug-in's window.
7633 // Then, we need to send the message to the plug-in window.
7634 if (!IsOurProcessWindow(destWnd
)) {
7635 HWND ourPluginWnd
= FindOurProcessWindow(destWnd
);
7636 if (!ourPluginWnd
) {
7637 // Somebody elses window
7638 return PR_FALSE
; // break, but continue processing
7640 destWindow
= GetNSWindowPtr(ourPluginWnd
);
7642 destWindow
= GetNSWindowPtr(destWnd
);
7645 if (destWindow
== this && mWindowType
== eWindowType_plugin
) {
7646 // If this is plug-in window, the message came from the plug-in window.
7647 // Then, the message should be processed on the parent window.
7648 destWindow
= static_cast<nsWindow
*>(GetParent());
7649 NS_ENSURE_TRUE(destWindow
, PR_FALSE
); // break, but continue processing
7650 destWnd
= destWindow
->mWnd
;
7651 NS_ENSURE_TRUE(destWnd
, PR_FALSE
); // break, but continue processing
7654 if (!destWindow
|| destWindow
->mWindowType
== eWindowType_plugin
) {
7655 // Some other app, or a plugin window.
7656 // Windows directs scrolling messages to the focused window.
7657 // However, Mozilla does not like plugins having focus, so a
7658 // Mozilla window (ie, the plugin's parent (us!) has focus.)
7659 // Therefore, plugins etc _should_ get first grab at the
7660 // message, but this focus vaguary means the plugin misses
7661 // out. If the window is a child of ours, forward it on.
7662 // Determine if a child by walking the parent list until
7663 // we find a parent matching our wndproc.
7664 HWND parentWnd
= ::GetParent(destWnd
);
7666 nsWindow
* parentWindow
= GetNSWindowPtr(parentWnd
);
7668 // We have a child window - quite possibly a plugin window.
7669 // However, not all plugins are created equal - some will handle this
7670 // message themselves, some will forward directly back to us, while
7671 // others will call DefWndProc, which itself still forwards back to us.
7672 // So if we have sent it once, we need to handle it ourself.
7675 // XXX The message shouldn't come from the plugin window at here.
7676 // But the message might come from it due to some bugs. If it happens,
7677 // SendMessage causes deadlock. For safety, we should unlock the
7679 ::ReplyMessage(aMsg
== WM_MOUSEHWHEEL
? TRUE
: 0);
7682 // First time we have seen this message.
7683 // Call the child - either it will consume it, or
7684 // it will wind it's way back to us,triggering the destWnd case above
7685 // either way,when the call returns,we are all done with the message,
7686 sIsProcessing
= PR_TRUE
;
7687 ::SendMessageW(destWnd
, aMsg
, aWParam
, aLParam
);
7688 sIsProcessing
= PR_FALSE
;
7690 aQuitProcessing
= PR_TRUE
;
7691 return PR_FALSE
; // break, and stop processing
7693 parentWnd
= ::GetParent(parentWnd
);
7694 } // while parentWnd
7696 if (destWnd
== nsnull
)
7698 if (destWnd
!= mWnd
) {
7700 sIsProcessing
= PR_TRUE
;
7701 aHandled
= destWindow
->ProcessMessage(aMsg
, aWParam
, aLParam
, aRetValue
);
7702 sIsProcessing
= PR_FALSE
;
7703 aQuitProcessing
= PR_TRUE
;
7704 return PR_FALSE
; // break, and stop processing
7708 printf("WARNING: couldn't get child window for SCROLL event\n");
7711 return PR_TRUE
; // caller should handle this
7714 PRBool
nsWindow::OnScroll(UINT aMsg
, WPARAM aWParam
, LPARAM aLParam
)
7716 static PRInt8 sMouseWheelEmulation
= -1;
7717 if (sMouseWheelEmulation
< 0) {
7718 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
7719 NS_ENSURE_TRUE(prefs
, PR_FALSE
);
7720 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
7721 prefs
->GetBranch(0, getter_AddRefs(prefBranch
));
7722 NS_ENSURE_TRUE(prefBranch
, PR_FALSE
);
7725 prefBranch
->GetBoolPref("mousewheel.emulate_at_wm_scroll", &emulate
);
7726 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
7727 sMouseWheelEmulation
= PRInt8(emulate
);
7730 if (aLParam
|| sMouseWheelEmulation
) {
7731 // Scroll message generated by Thinkpad Trackpoint Driver or similar
7732 // Treat as a mousewheel message and scroll appropriately
7733 PRBool quit
, result
;
7736 if (!HandleScrollingPlugins(aMsg
, aWParam
, aLParam
, result
, &retVal
, quit
))
7737 return quit
; // Return if it's not our message or has been dispatched
7739 nsMouseScrollEvent
scrollevent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
7740 scrollevent
.scrollFlags
= (aMsg
== WM_VSCROLL
)
7741 ? nsMouseScrollEvent::kIsVertical
7742 : nsMouseScrollEvent::kIsHorizontal
;
7743 switch (LOWORD(aWParam
))
7746 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
7748 scrollevent
.delta
= 1;
7751 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
7753 scrollevent
.delta
= -1;
7759 // The event may go to a plug-in which already dispatched this message.
7760 // Then, the event can cause deadlock. We should unlock the sender here.
7763 scrollevent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
7764 scrollevent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
7765 scrollevent
.isMeta
= PR_FALSE
;
7766 scrollevent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
7767 InitEvent(scrollevent
);
7768 if (nsnull
!= mEventCallback
)
7770 DispatchWindowEvent(&scrollevent
);
7775 // Scroll message generated by external application
7776 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_SCROLL
, this);
7778 command
.mScroll
.mIsHorizontal
= (aMsg
== WM_HSCROLL
);
7780 switch (LOWORD(aWParam
))
7782 case SB_LINEUP
: // SB_LINELEFT
7783 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Line
;
7784 command
.mScroll
.mAmount
= -1;
7786 case SB_LINEDOWN
: // SB_LINERIGHT
7787 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Line
;
7788 command
.mScroll
.mAmount
= 1;
7790 case SB_PAGEUP
: // SB_PAGELEFT
7791 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Page
;
7792 command
.mScroll
.mAmount
= -1;
7794 case SB_PAGEDOWN
: // SB_PAGERIGHT
7795 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Page
;
7796 command
.mScroll
.mAmount
= 1;
7798 case SB_TOP
: // SB_LEFT
7799 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Whole
;
7800 command
.mScroll
.mAmount
= -1;
7802 case SB_BOTTOM
: // SB_RIGHT
7803 command
.mScroll
.mUnit
= nsContentCommandEvent::eCmdScrollUnit_Whole
;
7804 command
.mScroll
.mAmount
= 1;
7809 DispatchWindowEvent(&command
);
7813 // Can be overriden. Controls auto-erase of background.
7814 PRBool
nsWindow::AutoErase(HDC dc
)
7820 nsWindow::AllowD3D9Callback(nsWindow
*aWindow
)
7822 if (aWindow
->mLayerManager
) {
7823 aWindow
->mLayerManager
->Destroy();
7824 aWindow
->mLayerManager
= NULL
;
7829 nsWindow::AllowD3D9WithReinitializeCallback(nsWindow
*aWindow
)
7831 if (aWindow
->mLayerManager
) {
7832 aWindow
->mLayerManager
->Destroy();
7833 aWindow
->mLayerManager
= NULL
;
7834 (void) aWindow
->GetLayerManager();
7839 nsWindow::StartAllowingD3D9(bool aReinitialize
)
7843 LayerManagerPrefs prefs
;
7844 GetLayerManagerPrefs(&prefs
);
7845 if (prefs
.mDisableAcceleration
) {
7846 // The guarantee here is, if there's *any* chance that after we
7847 // throw out our layer managers we'd create at least one new,
7848 // accelerated one, we *will* throw out all the current layer
7849 // managers. We early-return here because currently, if
7850 // |disableAcceleration|, we will always use basic managers and
7851 // it's a waste to recreate them.
7853 // NB: the above implies that it's eminently possible for us to
7854 // skip this early return but still recreate basic managers.
7855 // That's OK. It's *not* OK to take this early return when we
7856 // *might* have created an accelerated manager.
7860 if (aReinitialize
) {
7861 EnumAllWindows(AllowD3D9WithReinitializeCallback
);
7863 EnumAllWindows(AllowD3D9Callback
);
7867 /**************************************************************
7868 **************************************************************
7870 ** BLOCK: IME management and accessibility
7872 ** Handles managing IME input and accessibility.
7874 **************************************************************
7875 **************************************************************/
7877 NS_IMETHODIMP
nsWindow::ResetInputState()
7879 #ifdef DEBUG_KBSTATE
7880 printf("ResetInputState\n");
7883 #ifdef NS_ENABLE_TSF
7884 nsTextStore::CommitComposition(PR_FALSE
);
7885 #endif //NS_ENABLE_TSF
7887 nsIMM32Handler::CommitComposition(this);
7891 NS_IMETHODIMP
nsWindow::SetIMEOpenState(PRBool aState
)
7893 #ifdef DEBUG_KBSTATE
7894 printf("SetIMEOpenState %s\n", (aState
? "Open" : "Close"));
7897 #ifdef NS_ENABLE_TSF
7898 nsTextStore::SetIMEOpenState(aState
);
7899 #endif //NS_ENABLE_TSF
7901 nsIMEContext
IMEContext(mWnd
);
7902 if (IMEContext
.IsValid()) {
7903 ::ImmSetOpenStatus(IMEContext
.get(), aState
? TRUE
: FALSE
);
7908 NS_IMETHODIMP
nsWindow::GetIMEOpenState(PRBool
* aState
)
7910 nsIMEContext
IMEContext(mWnd
);
7911 if (IMEContext
.IsValid()) {
7912 BOOL isOpen
= ::ImmGetOpenStatus(IMEContext
.get());
7913 *aState
= isOpen
? PR_TRUE
: PR_FALSE
;
7917 #ifdef NS_ENABLE_TSF
7918 *aState
|= nsTextStore::GetIMEOpenState();
7919 #endif //NS_ENABLE_TSF
7924 NS_IMETHODIMP
nsWindow::SetInputMode(const IMEContext
& aContext
)
7926 PRUint32 status
= aContext
.mStatus
;
7927 #ifdef NS_ENABLE_TSF
7928 nsTextStore::SetInputMode(aContext
);
7929 #endif //NS_ENABLE_TSF
7930 #ifdef DEBUG_KBSTATE
7931 printf("SetInputMode: %s\n", (status
== nsIWidget::IME_STATUS_ENABLED
||
7932 status
== nsIWidget::IME_STATUS_PLUGIN
) ?
7933 "Enabled" : "Disabled");
7935 if (nsIMM32Handler::IsComposing()) {
7938 mIMEContext
= aContext
;
7939 PRBool enable
= (status
== nsIWidget::IME_STATUS_ENABLED
||
7940 status
== nsIWidget::IME_STATUS_PLUGIN
);
7942 #if defined(WINCE_HAVE_SOFTKB)
7943 sSoftKeyboardState
= (status
!= nsIWidget::IME_STATUS_DISABLED
);
7944 nsWindowCE::ToggleSoftKB(mWnd
, sSoftKeyboardState
);
7947 if (!enable
!= !mOldIMC
)
7949 mOldIMC
= ::ImmAssociateContext(mWnd
, enable
? mOldIMC
: NULL
);
7950 NS_ASSERTION(!enable
|| !mOldIMC
, "Another IMC was associated");
7955 NS_IMETHODIMP
nsWindow::GetInputMode(IMEContext
& aContext
)
7957 #ifdef DEBUG_KBSTATE
7958 printf("GetInputMode: %s\n", mIMEContext
.mStatus
? "Enabled" : "Disabled");
7960 aContext
= mIMEContext
;
7964 NS_IMETHODIMP
nsWindow::CancelIMEComposition()
7966 #ifdef DEBUG_KBSTATE
7967 printf("CancelIMEComposition\n");
7970 #ifdef NS_ENABLE_TSF
7971 nsTextStore::CommitComposition(PR_TRUE
);
7972 #endif //NS_ENABLE_TSF
7974 nsIMM32Handler::CancelComposition(this);
7979 nsWindow::GetToggledKeyState(PRUint32 aKeyCode
, PRBool
* aLEDState
)
7981 #ifdef DEBUG_KBSTATE
7982 printf("GetToggledKeyState\n");
7984 NS_ENSURE_ARG_POINTER(aLEDState
);
7985 *aLEDState
= (::GetKeyState(aKeyCode
) & 1) != 0;
7989 #ifdef NS_ENABLE_TSF
7991 nsWindow::OnIMEFocusChange(PRBool aFocus
)
7993 nsresult rv
= nsTextStore::OnFocusChange(aFocus
, this, mIMEContext
.mStatus
);
7994 if (rv
== NS_ERROR_NOT_AVAILABLE
)
7995 rv
= NS_ERROR_NOT_IMPLEMENTED
; // TSF is not enabled, maybe.
8000 nsWindow::OnIMETextChange(PRUint32 aStart
,
8004 return nsTextStore::OnTextChange(aStart
, aOldEnd
, aNewEnd
);
8008 nsWindow::OnIMESelectionChange(void)
8010 return nsTextStore::OnSelectionChange();
8012 #endif //NS_ENABLE_TSF
8014 #ifdef ACCESSIBILITY
8016 #ifdef DEBUG_WMGETOBJECT
8017 #define NS_LOG_WMGETOBJECT_WNDACC(aWnd) \
8018 nsAccessible* acc = aWnd ? \
8019 aWnd->DispatchAccessibleEvent(NS_GETACCESSIBLE) : nsnull; \
8020 printf(" acc: %p", acc); \
8022 nsAutoString name; \
8023 acc->GetName(name); \
8024 printf(", accname: %s", NS_ConvertUTF16toUTF8(name).get()); \
8025 nsCOMPtr<nsIAccessibleDocument> doc = do_QueryObject(acc); \
8026 void *hwnd = nsnull; \
8027 doc->GetWindowHandle(&hwnd); \
8028 printf(", acc hwnd: %d", hwnd); \
8031 #define NS_LOG_WMGETOBJECT_THISWND \
8033 printf("\n*******Get Doc Accessible*******\nOrig Window: "); \
8034 printf("\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n", \
8035 mWnd, ::GetParent(mWnd), this); \
8036 NS_LOG_WMGETOBJECT_WNDACC(this) \
8040 #define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd) \
8042 nsWindow* wnd = GetNSWindowPtr(aHwnd); \
8043 printf("Get " aMsg ":\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n", \
8044 aHwnd, ::GetParent(aHwnd), wnd); \
8045 NS_LOG_WMGETOBJECT_WNDACC(wnd); \
8049 #define NS_LOG_WMGETOBJECT_THISWND
8050 #define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd)
8051 #endif // DEBUG_WMGETOBJECT
8054 nsWindow::GetRootAccessible()
8056 // We want the ability to forcibly disable a11y on windows, because
8057 // some non-a11y-related components attempt to bring it up. See bug
8058 // 538530 for details; we have a pref here that allows it to be disabled
8059 // for performance and testing resons.
8061 // This pref is checked only once, and the browser needs a restart to
8062 // pick up any changes.
8063 static int accForceDisable
= -1;
8065 if (accForceDisable
== -1) {
8066 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
8067 PRBool b
= PR_FALSE
;
8068 nsresult rv
= prefs
->GetBoolPref("accessibility.win32.force_disabled", &b
);
8069 if (NS_SUCCEEDED(rv
) && b
) {
8070 accForceDisable
= 1;
8072 accForceDisable
= 0;
8076 // If the pref was true, return null here, disabling a11y.
8077 if (accForceDisable
)
8080 nsWindow::sIsAccessibilityOn
= TRUE
;
8082 if (mInDtor
|| mOnDestroyCalled
|| mWindowType
== eWindowType_invisible
) {
8086 NS_LOG_WMGETOBJECT_THISWND
8087 NS_LOG_WMGETOBJECT_WND("This Window", mWnd
);
8089 return DispatchAccessibleEvent(NS_GETACCESSIBLE
);
8092 STDMETHODIMP_(LRESULT
)
8093 nsWindow::LresultFromObject(REFIID riid
, WPARAM wParam
, LPUNKNOWN pAcc
)
8095 // open the dll dynamically
8097 sAccLib
=::LoadLibraryW(L
"OLEACC.DLL");
8100 if (!sLresultFromObject
)
8101 sLresultFromObject
= (LPFNLRESULTFROMOBJECT
)GetProcAddress(sAccLib
,"LresultFromObject");
8103 if (sLresultFromObject
)
8104 return sLresultFromObject(riid
,wParam
,pAcc
);
8111 /**************************************************************
8112 **************************************************************
8114 ** BLOCK: Transparency
8116 ** Window transparency helpers.
8118 **************************************************************
8119 **************************************************************/
8123 void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth
, PRInt32 aNewHeight
, PRBool force
)
8125 if (!force
&& aNewWidth
== mBounds
.width
&& aNewHeight
== mBounds
.height
)
8128 #ifdef CAIRO_HAS_D2D_SURFACE
8129 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
8130 gfxWindowsPlatform::RENDER_DIRECT2D
) {
8131 nsRefPtr
<gfxD2DSurface
> newSurface
=
8132 new gfxD2DSurface(gfxIntSize(aNewWidth
, aNewHeight
), gfxASurface::ImageFormatARGB32
);
8133 mTransparentSurface
= newSurface
;
8138 nsRefPtr
<gfxWindowsSurface
> newSurface
=
8139 new gfxWindowsSurface(gfxIntSize(aNewWidth
, aNewHeight
), gfxASurface::ImageFormatARGB32
);
8140 mTransparentSurface
= newSurface
;
8141 mMemoryDC
= newSurface
->GetDC();
8145 void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode
)
8149 if (aMode
== mTransparencyMode
)
8152 // stop on dialogs and popups!
8153 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
8154 nsWindow
* parent
= GetNSWindowPtr(hWnd
);
8158 NS_WARNING("Trying to use transparent chrome in an embedded context");
8162 if (parent
!= this) {
8163 NS_WARNING("Setting SetWindowTranslucencyInner on a parent this is not us!");
8166 if (aMode
== eTransparencyTransparent
) {
8167 // If we're switching to the use of a transparent window, hide the chrome
8169 HideWindowChrome(PR_TRUE
);
8170 } else if (mHideChrome
&& mTransparencyMode
== eTransparencyTransparent
) {
8171 // if we're switching out of transparent, re-enable our parent's chrome.
8172 HideWindowChrome(PR_FALSE
);
8175 LONG_PTR style
= ::GetWindowLongPtrW(hWnd
, GWL_STYLE
),
8176 exStyle
= ::GetWindowLongPtr(hWnd
, GWL_EXSTYLE
);
8178 if (parent
->mIsVisible
)
8179 style
|= WS_VISIBLE
;
8180 if (parent
->mSizeMode
== nsSizeMode_Maximized
)
8181 style
|= WS_MAXIMIZE
;
8182 else if (parent
->mSizeMode
== nsSizeMode_Minimized
)
8183 style
|= WS_MINIMIZE
;
8185 if (aMode
== eTransparencyTransparent
)
8186 exStyle
|= WS_EX_LAYERED
;
8188 exStyle
&= ~WS_EX_LAYERED
;
8190 VERIFY_WINDOW_STYLE(style
);
8191 ::SetWindowLongPtrW(hWnd
, GWL_STYLE
, style
);
8192 ::SetWindowLongPtrW(hWnd
, GWL_EXSTYLE
, exStyle
);
8194 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
8196 memset(&mGlassMargins
, 0, sizeof mGlassMargins
);
8197 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
8198 mTransparencyMode
= aMode
;
8200 SetupTranslucentWindowMemoryBitmap(aMode
);
8202 #endif // #ifndef WINCE
8205 void nsWindow::SetupTranslucentWindowMemoryBitmap(nsTransparencyMode aMode
)
8207 if (eTransparencyTransparent
== aMode
) {
8208 ResizeTranslucentWindow(mBounds
.width
, mBounds
.height
, PR_TRUE
);
8210 mTransparentSurface
= nsnull
;
8215 nsresult
nsWindow::UpdateTranslucentWindow()
8218 if (mBounds
.IsEmpty())
8223 BLENDFUNCTION bf
= { AC_SRC_OVER
, 0, 255, AC_SRC_ALPHA
};
8224 SIZE winSize
= { mBounds
.width
, mBounds
.height
};
8225 POINT srcPos
= { 0, 0 };
8226 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
8228 ::GetWindowRect(hWnd
, &winRect
);
8230 #ifdef CAIRO_HAS_D2D_SURFACE
8231 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
8232 gfxWindowsPlatform::RENDER_DIRECT2D
) {
8233 mMemoryDC
= static_cast<gfxD2DSurface
*>(mTransparentSurface
.get())->
8237 // perform the alpha blend
8238 PRBool updateSuccesful
=
8239 ::UpdateLayeredWindow(hWnd
, NULL
, (POINT
*)&winRect
, &winSize
, mMemoryDC
, &srcPos
, 0, &bf
, ULW_ALPHA
);
8241 #ifdef CAIRO_HAS_D2D_SURFACE
8242 if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
8243 gfxWindowsPlatform::RENDER_DIRECT2D
) {
8244 nsIntRect
r(0, 0, 0, 0);
8245 static_cast<gfxD2DSurface
*>(mTransparentSurface
.get())->ReleaseDC(&r
);
8249 if (!updateSuccesful
) {
8250 return NS_ERROR_FAILURE
;
8259 /**************************************************************
8260 **************************************************************
8262 ** BLOCK: Popup rollup hooks
8264 ** Deals with CaptureRollup on popup windows.
8266 **************************************************************
8267 **************************************************************/
8270 // Schedules a timer for a window, so we can rollup after processing the hook event
8271 void nsWindow::ScheduleHookTimer(HWND aWnd
, UINT aMsgId
)
8273 // In some cases multiple hooks may be scheduled
8274 // so ignore any other requests once one timer is scheduled
8275 if (sHookTimerId
== 0) {
8276 // Remember the window handle and the message ID to be used later
8277 sRollupMsgId
= aMsgId
;
8278 sRollupMsgWnd
= aWnd
;
8279 // Schedule native timer for doing the rollup after
8280 // this event is done being processed
8281 sHookTimerId
= ::SetTimer(NULL
, 0, 0, (TIMERPROC
)HookTimerForPopups
);
8282 NS_ASSERTION(sHookTimerId
, "Timer couldn't be created.");
8286 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
8287 int gLastMsgCode
= 0;
8288 extern MSGFEventMsgInfo gMSGFEvents
[];
8291 // Process Menu messages, rollup when popup is clicked.
8292 LRESULT CALLBACK
nsWindow::MozSpecialMsgFilter(int code
, WPARAM wParam
, LPARAM lParam
)
8294 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
8296 MSG
* pMsg
= (MSG
*)lParam
;
8299 while (gMSGFEvents
[inx
].mId
!= code
&& gMSGFEvents
[inx
].mStr
!= NULL
) {
8302 if (code
!= gLastMsgCode
) {
8303 if (gMSGFEvents
[inx
].mId
== code
) {
8305 printf("MozSpecialMessageProc - code: 0x%X - %s hw: %p\n", code
, gMSGFEvents
[inx
].mStr
, pMsg
->hwnd
);
8309 printf("MozSpecialMessageProc - code: 0x%X - %d hw: %p\n", code
, gMSGFEvents
[inx
].mId
, pMsg
->hwnd
);
8312 gLastMsgCode
= code
;
8314 PrintEvent(pMsg
->message
, FALSE
, FALSE
);
8316 #endif // #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
8318 if (sProcessHook
&& code
== MSGF_MENU
) {
8319 MSG
* pMsg
= (MSG
*)lParam
;
8320 ScheduleHookTimer( pMsg
->hwnd
, pMsg
->message
);
8323 return ::CallNextHookEx(sMsgFilterHook
, code
, wParam
, lParam
);
8326 // Process all mouse messages. Roll up when a click is in a native window
8327 // that doesn't have an nsIWidget.
8328 LRESULT CALLBACK
nsWindow::MozSpecialMouseProc(int code
, WPARAM wParam
, LPARAM lParam
)
8332 case WM_LBUTTONDOWN
:
8333 case WM_RBUTTONDOWN
:
8334 case WM_MBUTTONDOWN
:
8336 case WM_MOUSEHWHEEL
:
8338 MOUSEHOOKSTRUCT
* ms
= (MOUSEHOOKSTRUCT
*)lParam
;
8339 nsIWidget
* mozWin
= (nsIWidget
*)GetNSWindowPtr(ms
->hwnd
);
8341 // If this window is windowed plugin window, the mouse events are not
8343 if (static_cast<nsWindow
*>(mozWin
)->mWindowType
== eWindowType_plugin
)
8344 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
8346 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
8352 return ::CallNextHookEx(sCallMouseHook
, code
, wParam
, lParam
);
8355 // Process all messages. Roll up when the window is moving, or
8356 // is resizing or when maximized or mininized.
8357 LRESULT CALLBACK
nsWindow::MozSpecialWndProc(int code
, WPARAM wParam
, LPARAM lParam
)
8359 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
8361 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
8362 PrintEvent(cwpt
->message
, FALSE
, FALSE
);
8367 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
8368 if (cwpt
->message
== WM_MOVING
||
8369 cwpt
->message
== WM_SIZING
||
8370 cwpt
->message
== WM_GETMINMAXINFO
) {
8371 ScheduleHookTimer(cwpt
->hwnd
, (UINT
)cwpt
->message
);
8375 return ::CallNextHookEx(sCallProcHook
, code
, wParam
, lParam
);
8378 // Register the special "hooks" for dropdown processing.
8379 void nsWindow::RegisterSpecialDropdownHooks()
8381 NS_ASSERTION(!sMsgFilterHook
, "sMsgFilterHook must be NULL!");
8382 NS_ASSERTION(!sCallProcHook
, "sCallProcHook must be NULL!");
8384 DISPLAY_NMM_PRT("***************** Installing Msg Hooks ***************\n");
8386 //HMODULE hMod = GetModuleHandle("gkwidget.dll");
8388 // Install msg hook for moving the window and resizing
8389 if (!sMsgFilterHook
) {
8390 DISPLAY_NMM_PRT("***** Hooking sMsgFilterHook!\n");
8391 sMsgFilterHook
= SetWindowsHookEx(WH_MSGFILTER
, MozSpecialMsgFilter
, NULL
, GetCurrentThreadId());
8392 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
8393 if (!sMsgFilterHook
) {
8394 printf("***** SetWindowsHookEx is NOT installed for WH_MSGFILTER!\n");
8399 // Install msg hook for menus
8400 if (!sCallProcHook
) {
8401 DISPLAY_NMM_PRT("***** Hooking sCallProcHook!\n");
8402 sCallProcHook
= SetWindowsHookEx(WH_CALLWNDPROC
, MozSpecialWndProc
, NULL
, GetCurrentThreadId());
8403 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
8404 if (!sCallProcHook
) {
8405 printf("***** SetWindowsHookEx is NOT installed for WH_CALLWNDPROC!\n");
8410 // Install msg hook for the mouse
8411 if (!sCallMouseHook
) {
8412 DISPLAY_NMM_PRT("***** Hooking sCallMouseHook!\n");
8413 sCallMouseHook
= SetWindowsHookEx(WH_MOUSE
, MozSpecialMouseProc
, NULL
, GetCurrentThreadId());
8414 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
8415 if (!sCallMouseHook
) {
8416 printf("***** SetWindowsHookEx is NOT installed for WH_MOUSE!\n");
8422 // Unhook special message hooks for dropdowns.
8423 void nsWindow::UnregisterSpecialDropdownHooks()
8425 DISPLAY_NMM_PRT("***************** De-installing Msg Hooks ***************\n");
8427 if (sCallProcHook
) {
8428 DISPLAY_NMM_PRT("***** Unhooking sCallProcHook!\n");
8429 if (!::UnhookWindowsHookEx(sCallProcHook
)) {
8430 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallProcHook!\n");
8432 sCallProcHook
= NULL
;
8435 if (sMsgFilterHook
) {
8436 DISPLAY_NMM_PRT("***** Unhooking sMsgFilterHook!\n");
8437 if (!::UnhookWindowsHookEx(sMsgFilterHook
)) {
8438 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sMsgFilterHook!\n");
8440 sMsgFilterHook
= NULL
;
8443 if (sCallMouseHook
) {
8444 DISPLAY_NMM_PRT("***** Unhooking sCallMouseHook!\n");
8445 if (!::UnhookWindowsHookEx(sCallMouseHook
)) {
8446 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallMouseHook!\n");
8448 sCallMouseHook
= NULL
;
8452 // This timer is designed to only fire one time at most each time a "hook" function
8453 // is used to rollup the dropdown. In some cases, the timer may be scheduled from the
8454 // hook, but that hook event or a subsequent event may roll up the dropdown before
8455 // this timer function is executed.
8457 // For example, if an MFC control takes focus, the combobox will lose focus and rollup
8458 // before this function fires.
8459 VOID CALLBACK
nsWindow::HookTimerForPopups(HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
8461 if (sHookTimerId
!= 0) {
8462 // if the window is NULL then we need to use the ID to kill the timer
8463 BOOL status
= ::KillTimer(NULL
, sHookTimerId
);
8464 NS_ASSERTION(status
, "Hook Timer was not killed.");
8468 if (sRollupMsgId
!= 0) {
8469 // Note: DealWithPopups does the check to make sure that
8470 // sRollupListener and sRollupWidget are not NULL
8471 LRESULT popupHandlingResult
;
8472 nsAutoRollup autoRollup
;
8473 DealWithPopups(sRollupMsgWnd
, sRollupMsgId
, 0, 0, &popupHandlingResult
);
8475 sRollupMsgWnd
= NULL
;
8480 BOOL CALLBACK
nsWindow::ClearResourcesCallback(HWND aWnd
, LPARAM aMsg
)
8482 nsWindow
*window
= nsWindow::GetNSWindowPtr(aWnd
);
8484 window
->ClearCachedResources();
8490 nsWindow::ClearCachedResources()
8492 #ifdef CAIRO_HAS_D2D_SURFACE
8493 mD2DWindowSurface
= nsnull
;
8495 if (mLayerManager
&&
8496 mLayerManager
->GetBackendType() == LayerManager::LAYERS_BASIC
) {
8497 static_cast<BasicLayerManager
*>(mLayerManager
.get())->
8498 ClearCachedResources();
8500 ::EnumChildWindows(mWnd
, nsWindow::ClearResourcesCallback
, 0);
8503 static PRBool
IsDifferentThreadWindow(HWND aWnd
)
8505 return ::GetCurrentThreadId() != ::GetWindowThreadProcessId(aWnd
, NULL
);
8509 nsWindow::EventIsInsideWindow(UINT Msg
, nsWindow
* aWindow
)
8514 if (Msg
== WM_ACTIVATEAPP
)
8515 // don't care about activation/deactivation
8518 if (Msg
== WM_ACTIVATE
)
8519 // but on Windows CE we do care about
8520 // activation/deactivation because there doesn't exist
8521 // cancelable Mouse Activation events
8525 ::GetWindowRect(aWindow
->mWnd
, &r
);
8526 DWORD pos
= ::GetMessagePos();
8528 mp
.x
= GET_X_LPARAM(pos
);
8529 mp
.y
= GET_Y_LPARAM(pos
);
8531 // was the event inside this window?
8532 return (PRBool
) PtInRect(&r
, mp
);
8535 // Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
8537 nsWindow::DealWithPopups(HWND inWnd
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
, LRESULT
* outResult
)
8539 if (sRollupListener
&& sRollupWidget
&& ::IsWindowVisible(inWnd
)) {
8541 if (inMsg
== WM_LBUTTONDOWN
|| inMsg
== WM_RBUTTONDOWN
|| inMsg
== WM_MBUTTONDOWN
||
8542 inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
|| inMsg
== WM_ACTIVATE
||
8543 (inMsg
== WM_KILLFOCUS
&& IsDifferentThreadWindow((HWND
)inWParam
))
8546 inMsg
== WM_NCRBUTTONDOWN
||
8547 inMsg
== WM_MOVING
||
8548 inMsg
== WM_SIZING
||
8549 inMsg
== WM_NCLBUTTONDOWN
||
8550 inMsg
== WM_NCMBUTTONDOWN
||
8551 inMsg
== WM_MOUSEACTIVATE
||
8552 inMsg
== WM_ACTIVATEAPP
||
8553 inMsg
== WM_MENUSELECT
8557 // Rollup if the event is outside the popup.
8558 PRBool rollup
= !nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)sRollupWidget
);
8560 if (rollup
&& (inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
))
8562 sRollupListener
->ShouldRollupOnMouseWheelEvent(&rollup
);
8563 *outResult
= PR_TRUE
;
8566 // If we're dealing with menus, we probably have submenus and we don't
8567 // want to rollup if the click is in a parent menu of the current submenu.
8568 PRUint32 popupsToRollup
= PR_UINT32_MAX
;
8570 if ( sMenuRollup
) {
8571 nsAutoTArray
<nsIWidget
*, 5> widgetChain
;
8572 PRUint32 sameTypeCount
= sMenuRollup
->GetSubmenuWidgetChain(&widgetChain
);
8573 for ( PRUint32 i
= 0; i
< widgetChain
.Length(); ++i
) {
8574 nsIWidget
* widget
= widgetChain
[i
];
8575 if ( nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)widget
) ) {
8576 // don't roll up if the mouse event occurred within a menu of the
8577 // same type. If the mouse event occurred in a menu higher than
8578 // that, roll up, but pass the number of popups to Rollup so
8579 // that only those of the same type close up.
8580 if (i
< sameTypeCount
) {
8584 popupsToRollup
= sameTypeCount
;
8588 } // foreach parent menu widget
8589 } // if rollup listener knows about menus
8593 if (inMsg
== WM_MOUSEACTIVATE
&& popupsToRollup
== PR_UINT32_MAX
) {
8594 // Prevent the click inside the popup from causing a change in window
8595 // activation. Since the popup is shown non-activated, we need to eat
8596 // any requests to activate the window while it is displayed. Windows
8597 // will automatically activate the popup on the mousedown otherwise.
8599 *outResult
= MA_NOACTIVATE
;
8604 UINT uMsg
= HIWORD(inLParam
);
8605 if (uMsg
== WM_MOUSEMOVE
)
8607 // WM_MOUSEACTIVATE cause by moving the mouse - X-mouse (eg. TweakUI)
8608 // must be enabled in Windows.
8609 sRollupListener
->ShouldRollupOnMouseActivate(&rollup
);
8612 *outResult
= MA_NOACTIVATE
;
8618 // if we've still determined that we should still rollup everything, do it.
8622 // sRollupConsumeEvent may be modified by
8623 // nsIRollupListener::Rollup.
8624 PRBool consumeRollupEvent
= sRollupConsumeEvent
;
8625 // only need to deal with the last rollup for left mouse down events.
8626 sRollupListener
->Rollup(popupsToRollup
, inMsg
== WM_LBUTTONDOWN
? &mLastRollup
: nsnull
);
8628 // Tell hook to stop processing messages
8629 sProcessHook
= PR_FALSE
;
8631 sRollupMsgWnd
= NULL
;
8633 // return TRUE tells Windows that the event is consumed,
8634 // false allows the event to be dispatched
8636 // So if we are NOT supposed to be consuming events, let it go through
8637 if (consumeRollupEvent
&& inMsg
!= WM_RBUTTONDOWN
) {
8638 *outResult
= MA_ACTIVATE
;
8640 // However, don't activate panels
8642 if (inMsg
== WM_MOUSEACTIVATE
) {
8643 nsWindow
* activateWindow
= GetNSWindowPtr(inWnd
);
8644 if (activateWindow
) {
8645 nsWindowType wintype
;
8646 activateWindow
->GetWindowType(wintype
);
8647 if (wintype
== eWindowType_popup
&& activateWindow
->PopupType() == ePopupTypePanel
) {
8648 *outResult
= MA_NOACTIVATE
;
8657 // if we are only rolling up some popups, don't activate and don't let
8658 // the event go through. This prevents clicks menus higher in the
8659 // chain from opening when a context menu is open
8660 if (popupsToRollup
!= PR_UINT32_MAX
&& inMsg
== WM_MOUSEACTIVATE
) {
8661 *outResult
= MA_NOACTIVATEANDEAT
;
8666 } // if event that might trigger a popup to rollup
8667 } // if rollup listeners registered
8672 /**************************************************************
8673 **************************************************************
8675 ** BLOCK: Misc. utility methods and functions.
8679 **************************************************************
8680 **************************************************************/
8682 // nsModifierKeyState used in various character processing.
8683 nsModifierKeyState::nsModifierKeyState()
8685 mIsShiftDown
= IS_VK_DOWN(NS_VK_SHIFT
);
8686 mIsControlDown
= IS_VK_DOWN(NS_VK_CONTROL
);
8687 mIsAltDown
= IS_VK_DOWN(NS_VK_ALT
);
8691 PRInt32
nsWindow::GetWindowsVersion()
8696 static PRInt32 version
= 0;
8697 static PRBool didCheck
= PR_FALSE
;
8702 OSVERSIONINFOEX osInfo
;
8703 osInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
8704 // This cast is safe and supposed to be here, don't worry
8705 ::GetVersionEx((OSVERSIONINFO
*)&osInfo
);
8706 version
= (osInfo
.dwMajorVersion
& 0xff) << 8 | (osInfo
.dwMinorVersion
& 0xff);
8712 // Note that the result of GetTopLevelWindow method can be different from the
8713 // result of GetTopLevelHWND method. The result can be non-floating window.
8714 // Because our top level window may be contained in another window which is
8715 // not managed by us.
8716 nsWindow
* nsWindow::GetTopLevelWindow(PRBool aStopOnDialogOrPopup
)
8718 nsWindow
* curWindow
= this;
8721 if (aStopOnDialogOrPopup
) {
8722 switch (curWindow
->mWindowType
) {
8723 case eWindowType_dialog
:
8724 case eWindowType_popup
:
8731 // Retrieve the top level parent or owner window
8732 nsWindow
* parentWindow
= curWindow
->GetParentWindow(PR_TRUE
);
8737 curWindow
= parentWindow
;
8741 // Note that the result of GetTopLevelHWND can be different from the result
8742 // of GetTopLevelWindow method. Because this is checking whether the window
8743 // is top level only in Win32 window system. Therefore, the result window
8744 // may not be managed by us.
8745 HWND
nsWindow::GetTopLevelHWND(HWND aWnd
, PRBool aStopOnDialogOrPopup
)
8754 if (aStopOnDialogOrPopup
) {
8755 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
8757 VERIFY_WINDOW_STYLE(style
);
8759 if (!(style
& WS_CHILD
)) // first top-level window
8763 upWnd
= ::GetParent(curWnd
); // Parent or owner (if has no parent)
8766 // For dialog windows, we want just the parent, not the owner.
8767 // For other/popup windows, we want to find the first owner/parent
8768 // that's a dialog and/or has an owner.
8769 if (upWnd
&& ::GetWindow(curWnd
, GW_OWNER
) == upWnd
) {
8770 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
8771 if ((style
& WS_DLGFRAME
) != 0)
8782 static BOOL CALLBACK
gEnumWindowsProc(HWND hwnd
, LPARAM lParam
)
8785 ::GetWindowThreadProcessId(hwnd
, &pid
);
8786 if (pid
== GetCurrentProcessId() && ::IsWindowVisible(hwnd
))
8788 gWindowsVisible
= PR_TRUE
;
8794 PRBool
nsWindow::CanTakeFocus()
8796 gWindowsVisible
= PR_FALSE
;
8797 EnumWindows(gEnumWindowsProc
, 0);
8798 if (!gWindowsVisible
) {
8801 HWND fgWnd
= ::GetForegroundWindow();
8806 GetWindowThreadProcessId(fgWnd
, &pid
);
8807 if (pid
== GetCurrentProcessId()) {
8814 void nsWindow::GetMainWindowClass(nsAString
& aClass
)
8817 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
8818 if (NS_SUCCEEDED(rv
) && prefs
) {
8819 nsXPIDLCString name
;
8820 rv
= prefs
->GetCharPref("ui.window_class_override", getter_Copies(name
));
8821 if (NS_SUCCEEDED(rv
) && !name
.IsEmpty()) {
8822 aClass
.AssignASCII(name
.get());
8826 aClass
.AssignASCII(sDefaultMainWindowClass
);
8829 PRBool
nsWindow::UseTrackPointHack()
8832 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
8833 if (NS_SUCCEEDED(rv
) && prefs
) {
8835 rv
= prefs
->GetIntPref("ui.trackpoint_hack.enabled", &lHackValue
);
8836 if (NS_SUCCEEDED(rv
)) {
8837 switch (lHackValue
) {
8842 default: // -1: autodetect
8847 return sDefaultTrackPointHack
;
8852 HasRegistryKey(HKEY aRoot
, LPCWSTR aName
)
8855 LONG result
= ::RegOpenKeyExW(aRoot
, aName
, 0, KEY_READ
, &key
);
8856 if (result
!= ERROR_SUCCESS
)
8863 IsObsoleteSynapticsDriver()
8866 LONG result
= ::RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
8867 L
"Software\\Synaptics\\SynTP\\Install", 0, KEY_READ
, &key
);
8868 if (result
!= ERROR_SUCCESS
)
8872 DWORD buflen
= sizeof(buf
);
8873 result
= ::RegQueryValueExW(key
, L
"DriverVersion", NULL
, &type
, (BYTE
*)buf
, &buflen
);
8875 if (result
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
8877 buf
[NS_ARRAY_LENGTH(buf
) - 1] = 0;
8879 int majorVersion
= wcstol(buf
, NULL
, 10);
8880 return majorVersion
< 15;
8883 void nsWindow::InitInputHackDefaults()
8885 if (HasRegistryKey(HKEY_CURRENT_USER
, L
"Software\\Lenovo\\TrackPoint")) {
8886 sDefaultTrackPointHack
= PR_TRUE
;
8887 } else if (HasRegistryKey(HKEY_CURRENT_USER
, L
"Software\\Lenovo\\UltraNav")) {
8888 sDefaultTrackPointHack
= PR_TRUE
;
8889 } else if (HasRegistryKey(HKEY_CURRENT_USER
, L
"Software\\Alps\\Apoint\\TrackPoint")) {
8890 sDefaultTrackPointHack
= PR_TRUE
;
8891 } else if ((HasRegistryKey(HKEY_CURRENT_USER
, L
"Software\\Synaptics\\SynTPEnh\\UltraNavUSB") ||
8892 HasRegistryKey(HKEY_CURRENT_USER
, L
"Software\\Synaptics\\SynTPEnh\\UltraNavPS2")) &&
8893 IsObsoleteSynapticsDriver()) {
8894 sDefaultTrackPointHack
= PR_TRUE
;
8897 #endif // #if !defined(WINCE)
8899 LPARAM
nsWindow::lParamToScreen(LPARAM lParam
)
8902 pt
.x
= GET_X_LPARAM(lParam
);
8903 pt
.y
= GET_Y_LPARAM(lParam
);
8904 ::ClientToScreen(mWnd
, &pt
);
8905 return MAKELPARAM(pt
.x
, pt
.y
);
8908 LPARAM
nsWindow::lParamToClient(LPARAM lParam
)
8911 pt
.x
= GET_X_LPARAM(lParam
);
8912 pt
.y
= GET_Y_LPARAM(lParam
);
8913 ::ScreenToClient(mWnd
, &pt
);
8914 return MAKELPARAM(pt
.x
, pt
.y
);
8917 /**************************************************************
8918 **************************************************************
8920 ** BLOCK: ChildWindow impl.
8922 ** Child window overrides.
8924 **************************************************************
8925 **************************************************************/
8927 // return the style for a child nsWindow
8928 DWORD
ChildWindow::WindowStyle()
8930 DWORD style
= WS_CLIPCHILDREN
| nsWindow::WindowStyle();
8931 if (!(style
& WS_POPUP
))
8932 style
|= WS_CHILD
; // WS_POPUP and WS_CHILD are mutually exclusive.
8933 VERIFY_WINDOW_STYLE(style
);