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 <mats.palmgren@bredband.net>
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 **************************************************************/
107 #include "nsWindow.h"
111 #include <commctrl.h>
119 #include "nsIAppShell.h"
120 #include "nsISupportsPrimitives.h"
121 #include "nsIDOMNSUIEvent.h"
122 #include "nsITheme.h"
123 #include "nsIPrefBranch.h"
124 #include "nsIPrefService.h"
125 #include "nsIObserverService.h"
126 #include "nsIScreenManager.h"
127 #include "imgIContainer.h"
129 #include "nsIRollupListener.h"
130 #include "nsIMenuRollup.h"
131 #include "nsIRegion.h"
132 #include "nsIServiceManager.h"
133 #include "nsIClipboard.h"
134 #include "nsIMM32Handler.h"
135 #include "nsILocalFile.h"
136 #include "nsIFontMetrics.h"
137 #include "nsIFontEnumerator.h"
138 #include "nsIDeviceContext.h"
139 #include "nsIdleService.h"
140 #include "nsGUIEvent.h"
143 #include "nsThreadUtils.h"
144 #include "nsNativeCharsetUtils.h"
145 #include "nsWidgetAtoms.h"
146 #include "nsUnicharUtils.h"
148 #include "nsAppDirectoryServiceDefs.h"
149 #include "nsXPIDLString.h"
150 #include "nsWidgetsCID.h"
151 #include "nsTHashtable.h"
152 #include "nsHashKeys.h"
153 #include "nsString.h"
156 #include "nsWindowCE.h"
159 #if defined(WINCE_WINDOWS_MOBILE)
160 #define KILL_PRIORITY_ID 2444
163 #include "nsWindowGfx.h"
166 #include "nsUXThemeData.h"
167 #include "nsUXThemeConstants.h"
168 #include "nsKeyboardLayout.h"
169 #include "nsNativeDragTarget.h"
170 #include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
173 #include <richedit.h>
174 #endif // !defined(WINCE)
176 #if defined(ACCESSIBILITY)
179 #if !defined(WINABLEAPI)
181 #endif // !defined(WINABLEAPI)
182 #include "nsIAccessible.h"
183 #include "nsIAccessibleDocument.h"
184 #include "nsIAccessNode.h"
185 #endif // defined(ACCESSIBILITY)
187 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
188 #include "nsIWinTaskbar.h"
191 #if defined(NS_ENABLE_TSF)
192 #include "nsTextStore.h"
193 #endif // defined(NS_ENABLE_TSF)
195 #if defined(MOZ_SPLASHSCREEN)
196 #include "nsSplashScreen.h"
197 #endif // defined(MOZ_SPLASHSCREEN)
199 // Windowless plugin support
202 #include "nsWindowDefs.h"
204 #ifdef WINCE_WINDOWS_MOBILE
205 #include "nsGfxCIID.h"
208 // A magic APP message that can be sent to quit, sort of like a QUERYENDSESSION/ENDSESSION,
209 // but without the query.
210 #define MOZ_WM_APP_QUIT (WM_APP+0x0300)
212 /**************************************************************
213 **************************************************************
217 ** nsWindow Class static initializations and global variables.
219 **************************************************************
220 **************************************************************/
222 /**************************************************************
224 * SECTION: nsWindow statics
226 **************************************************************/
228 PRUint32
nsWindow::sInstanceCount
= 0;
229 PRBool
nsWindow::sSwitchKeyboardLayout
= PR_FALSE
;
230 BOOL
nsWindow::sIsRegistered
= FALSE
;
231 BOOL
nsWindow::sIsPopupClassRegistered
= FALSE
;
232 BOOL
nsWindow::sIsOleInitialized
= FALSE
;
233 HCURSOR
nsWindow::sHCursor
= NULL
;
234 imgIContainer
* nsWindow::sCursorImgContainer
= nsnull
;
235 nsWindow
* nsWindow::sCurrentWindow
= nsnull
;
236 PRBool
nsWindow::sJustGotDeactivate
= PR_FALSE
;
237 PRBool
nsWindow::sJustGotActivate
= PR_FALSE
;
239 // imported in nsWidgetFactory.cpp
240 TriStateBool
nsWindow::sCanQuit
= TRI_UNKNOWN
;
242 // Hook Data Memebers for Dropdowns. sProcessHook Tells the
243 // hook methods whether they should be processing the hook
245 HHOOK
nsWindow::sMsgFilterHook
= NULL
;
246 HHOOK
nsWindow::sCallProcHook
= NULL
;
247 HHOOK
nsWindow::sCallMouseHook
= NULL
;
248 PRPackedBool
nsWindow::sProcessHook
= PR_FALSE
;
249 UINT
nsWindow::sRollupMsgId
= 0;
250 HWND
nsWindow::sRollupMsgWnd
= NULL
;
251 UINT
nsWindow::sHookTimerId
= 0;
254 nsIRollupListener
* nsWindow::sRollupListener
= nsnull
;
255 nsIWidget
* nsWindow::sRollupWidget
= nsnull
;
256 PRBool
nsWindow::sRollupConsumeEvent
= PR_FALSE
;
258 // Mouse Clicks - static variable definitions for figuring
260 POINT
nsWindow::sLastMousePoint
= {0};
261 POINT
nsWindow::sLastMouseMovePoint
= {0};
262 LONG
nsWindow::sLastMouseDownTime
= 0L;
263 LONG
nsWindow::sLastClickCount
= 0L;
264 BYTE
nsWindow::sLastMouseButton
= 0;
266 // Trim heap on minimize. (initialized, but still true.)
267 int nsWindow::sTrimOnMinimize
= 2;
269 // Default Trackpoint Hack to off
270 PRBool
nsWindow::sTrackPointHack
= PR_FALSE
;
273 BOOL
nsWindow::sIsAccessibilityOn
= FALSE
;
274 // Accessibility wm_getobject handler
275 HINSTANCE
nsWindow::sAccLib
= 0;
276 LPFNLRESULTFROMOBJECT
277 nsWindow::sLresultFromObject
= 0;
278 #endif // ACCESSIBILITY
280 /**************************************************************
282 * SECTION: globals variables
284 **************************************************************/
286 static const char *sScreenManagerContractID
= "@mozilla.org/gfx/screenmanager;1";
289 PRLogModuleInfo
* gWindowsLog
= nsnull
;
293 // Kbd layout. Used throughout character processing.
294 static KeyboardLayout gKbdLayout
;
297 #ifdef WINCE_WINDOWS_MOBILE
298 // HTC Navigation Wheel Event
299 // This is the defined value for Gesture Mode
300 const int WM_HTCNAV
= 0x0400 + 200;
302 typedef int (__stdcall
* HTCApiNavOpen
)(HANDLE
, int);
303 typedef int (__stdcall
* HTCApiNavSetMode
)(HANDLE
, unsigned int);
305 HTCApiNavOpen gHTCApiNavOpen
= nsnull
;
306 HTCApiNavSetMode gHTCApiNavSetMode
= nsnull
;
307 static PRBool gCheckForHTCApi
= PR_FALSE
;
310 // The last user input event time in microseconds. If
311 // there are any pending native toolkit input events
312 // it returns the current time. The value is compatible
313 // with PR_IntervalToMicroseconds(PR_IntervalNow()).
315 static PRUint32 gLastInputEventTime
= 0;
317 PRUint32 gLastInputEventTime
= 0;
320 static void UpdateLastInputEventTime() {
321 gLastInputEventTime
= PR_IntervalToMicroseconds(PR_IntervalNow());
322 nsCOMPtr
<nsIIdleService
> idleService
= do_GetService("@mozilla.org/widget/idleservice;1");
323 nsIdleService
* is
= static_cast<nsIdleService
*>(idleService
.get());
325 is
->IdleTimeWasModified();
329 // Global user preference for disabling native theme. Used
330 // in NativeWindowTheme.
331 PRBool gDisableNativeTheme
= PR_FALSE
;
333 // Global used in Show window enumerations.
334 static PRBool gWindowsVisible
= PR_FALSE
;
336 static NS_DEFINE_CID(kCClipboardCID
, NS_CLIPBOARD_CID
);
337 #ifdef WINCE_WINDOWS_MOBILE
338 static NS_DEFINE_CID(kRegionCID
, NS_REGION_CID
);
341 /**************************************************************
342 **************************************************************
344 ** BLOCK: nsIWidget impl.
346 ** nsIWidget interface implementation, broken down into
349 **************************************************************
350 **************************************************************/
352 /**************************************************************
354 * SECTION: nsWindow construction and destruction
356 **************************************************************/
358 nsWindow::nsWindow() : nsBaseWidget()
362 gWindowsLog
= PR_NewLogModule("nsWindowsWidgets");
367 mPrevWndProc
= nsnull
;
369 mNativeDragTarget
= nsnull
;
371 mIsVisible
= PR_FALSE
;
372 mHas3DBorder
= PR_FALSE
;
373 mIsInMouseCapture
= PR_FALSE
;
374 mIsTopWidgetWindow
= PR_FALSE
;
375 mInScrollProcessing
= PR_FALSE
;
376 mUnicodeWidget
= PR_TRUE
;
377 mWindowType
= eWindowType_child
;
378 mBorderStyle
= eBorderStyle_default
;
379 mPopupType
= ePopupTypeAny
;
380 mDisplayPanFeedback
= PR_FALSE
;
384 mLastSize
.height
= 0;
388 mLastKeyboardLayout
= 0;
389 mBlurSuppressLevel
= 0;
390 mIMEEnabled
= nsIWidget::IME_STATUS_ENABLED
;
393 mTransparentSurface
= nsnull
;
395 mTransparencyMode
= eTransparencyOpaque
;
397 mBackground
= ::GetSysColor(COLOR_BTNFACE
);
398 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
399 mForeground
= ::GetSysColor(COLOR_WINDOWTEXT
);
401 #ifdef WINCE_WINDOWS_MOBILE
402 mInvalidatedRegion
= do_CreateInstance(kRegionCID
);
403 mInvalidatedRegion
->Init();
406 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
407 mTaskbarPreview
= nsnull
;
408 mHasTaskbarIconBeenCreated
= PR_FALSE
;
411 // Global initialization
412 if (!sInstanceCount
) {
414 gKbdLayout
.LoadLayout(::GetKeyboardLayout(0));
418 nsIMM32Handler::Initialize();
421 nsTextStore::Initialize();
425 if (SUCCEEDED(::OleInitialize(NULL
)))
426 sIsOleInitialized
= TRUE
;
427 NS_ASSERTION(sIsOleInitialized
, "***** OLE is not initialized!\n");
430 #if defined(HEAP_DUMP_EVENT)
435 InitTrackPointHack();
439 // Set gLastInputEventTime to some valid number
440 gLastInputEventTime
= PR_IntervalToMicroseconds(PR_IntervalNow());
445 nsWindow::~nsWindow()
449 // If the widget was released without calling Destroy() then the native window still
450 // exists, and we need to destroy it. This will also result in a call to OnDestroy.
452 // XXX How could this happen???
459 if (sInstanceCount
== 0) {
461 nsTextStore::Terminate();
465 NS_IF_RELEASE(sCursorImgContainer
);
466 if (sIsOleInitialized
) {
467 ::OleFlushClipboard();
469 sIsOleInitialized
= FALSE
;
471 // delete any of the IME structures that we allocated
472 nsIMM32Handler::Terminate();
473 #endif // !defined(WINCE)
477 NS_IF_RELEASE(mNativeDragTarget
);
478 #endif // !defined(WINCE)
481 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow
, nsBaseWidget
)
483 /**************************************************************
485 * SECTION: nsIWidget::Create, nsIWidget::Destroy
487 * Creating and destroying windows for this widget.
489 **************************************************************/
491 // Allow Derived classes to modify the height that is passed
492 // when the window is created or resized. Also add extra height
493 // if needed (on Windows CE)
494 PRInt32
nsWindow::GetHeight(PRInt32 aProposedHeight
)
498 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
499 DWORD style
= WindowStyle();
500 if ((style
& WS_SYSMENU
) && (style
& WS_POPUP
)) {
501 extra
= GetSystemMetrics(SM_CYCAPTION
);
505 return aProposedHeight
+ extra
;
508 // Create the proper widget
510 nsWindow::Create(nsIWidget
*aParent
,
511 nsNativeWidget aNativeParent
,
512 const nsIntRect
&aRect
,
513 EVENT_CALLBACK aHandleEventFunction
,
514 nsIDeviceContext
*aContext
,
515 nsIAppShell
*aAppShell
,
516 nsIToolkit
*aToolkit
,
517 nsWidgetInitData
*aInitData
)
520 mUnicodeWidget
= aInitData
->mUnicode
;
522 nsIWidget
*baseParent
= aInitData
&&
523 (aInitData
->mWindowType
== eWindowType_dialog
||
524 aInitData
->mWindowType
== eWindowType_toplevel
||
525 aInitData
->mWindowType
== eWindowType_invisible
) ?
528 mIsTopWidgetWindow
= (nsnull
== baseParent
);
529 mBounds
.width
= aRect
.width
;
530 mBounds
.height
= aRect
.height
;
532 BaseCreate(baseParent
, aRect
, aHandleEventFunction
, aContext
,
533 aAppShell
, aToolkit
, aInitData
);
536 if (nsnull
!= aParent
) { // has a nsIWidget parent
537 parent
= ((aParent
) ? (HWND
)aParent
->GetNativeData(NS_NATIVE_WINDOW
) : nsnull
);
538 } else { // has a nsNative parent
539 parent
= (HWND
)aNativeParent
;
542 if (nsnull
!= aInitData
) {
543 mPopupType
= aInitData
->mPopupHint
;
546 mContentType
= aInitData
? aInitData
->mContentType
: eContentTypeInherit
;
548 DWORD style
= WindowStyle();
549 DWORD extendedStyle
= WindowExStyle();
551 if (mWindowType
== eWindowType_popup
) {
552 // if a parent was specified, don't use WS_EX_TOPMOST so that the popup
553 // only appears above the parent, instead of all windows
555 extendedStyle
= WS_EX_TOOLWINDOW
;
558 } else if (mWindowType
== eWindowType_invisible
) {
559 // Make sure CreateWindowEx succeeds at creating a toplevel window
560 style
&= ~0x40000000; // WS_CHILDWINDOW
561 } else if (nsnull
!= aInitData
) {
562 // See if the caller wants to explictly set clip children and clip siblings
563 if (aInitData
->clipChildren
) {
564 style
|= WS_CLIPCHILDREN
;
566 style
&= ~WS_CLIPCHILDREN
;
568 if (aInitData
->clipSiblings
) {
569 style
|= WS_CLIPSIBLINGS
;
573 mHas3DBorder
= (extendedStyle
& WS_EX_CLIENTEDGE
) > 0;
575 mWnd
= ::CreateWindowExW(extendedStyle
,
576 aInitData
&& aInitData
->mDropShadow
?
577 WindowPopupClass() : WindowClass(),
583 GetHeight(aRect
.height
),
586 nsToolkit::mDllInstance
,
590 return NS_ERROR_FAILURE
;
592 if (nsWindow::sTrackPointHack
&&
593 mWindowType
!= eWindowType_plugin
&&
594 mWindowType
!= eWindowType_invisible
) {
595 // Ugly Thinkpad Driver Hack (Bug 507222)
596 // We create an invisible scrollbar to trick the
597 // Trackpoint driver into sending us scrolling messages
598 ::CreateWindowW(L
"SCROLLBAR", L
"FAKETRACKPOINTSCROLLBAR",
599 WS_CHILD
| WS_VISIBLE
, 0,0,0,0, mWnd
, NULL
,
600 nsToolkit::mDllInstance
, NULL
);
603 // call the event callback to notify about creation
605 DispatchStandardEvent(NS_CREATE
);
606 SubclassWindow(TRUE
);
608 if (sTrimOnMinimize
== 2 && mWindowType
== eWindowType_invisible
) {
609 /* The internal variable set by the config.trim_on_minimize pref
610 has not yet been initialized, and this is the hidden window
611 (conveniently created before any visible windows, and after
612 the profile has been initialized).
614 Default config.trim_on_minimize to false, to fix bug 76831
615 for good. If anyone complains about this new default, saying
616 that a Mozilla app hogs too much memory while minimized, they
617 will have that entire bug tattooed on their backside. */
620 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
622 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
623 prefs
->GetBranch(0, getter_AddRefs(prefBranch
));
627 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("config.trim_on_minimize",
632 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("intl.keyboard.per_window_layout",
634 sSwitchKeyboardLayout
= temp
;
636 if (NS_SUCCEEDED(prefBranch
->GetBoolPref("mozilla.widget.disable-native-theme",
638 gDisableNativeTheme
= temp
;
642 #if defined(WINCE_HAVE_SOFTKB)
643 if (mWindowType
== eWindowType_dialog
|| mWindowType
== eWindowType_toplevel
)
644 nsWindowCE::CreateSoftKeyMenuBar(mWnd
);
650 // Close this nsWindow
651 NS_METHOD
nsWindow::Destroy()
653 // WM_DESTROY has already fired, we're done.
657 // During the destruction of all of our children, make sure we don't get deleted.
658 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
660 // The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
661 // and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
662 // from it. The function also destroys the window's menu, flushes the thread message queue,
663 // destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if
664 // the window is at the top of the viewer chain).
666 // If the specified window is a parent or owner window, DestroyWindow automatically destroys
667 // the associated child or owned windows when it destroys the parent or owner window. The
668 // function first destroys child or owned windows, and then it destroys the parent or owner
670 VERIFY(::DestroyWindow(mWnd
));
672 // Our windows can be subclassed which may prevent us receiving WM_DESTROY. If OnDestroy()
673 // didn't get called, call it now.
674 if (PR_FALSE
== mOnDestroyCalled
)
680 /**************************************************************
682 * SECTION: Window class utilities
684 * Utilities for calculating the proper window class name for
687 **************************************************************/
689 // Return the proper window class for everything except popups.
690 LPCWSTR
nsWindow::WindowClass()
692 if (!nsWindow::sIsRegistered
) {
695 // wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
696 wc
.style
= CS_DBLCLKS
;
697 wc
.lpfnWndProc
= ::DefWindowProcW
;
700 wc
.hInstance
= nsToolkit::mDllInstance
;
701 wc
.hIcon
= ::LoadIconW(::GetModuleHandleW(NULL
), (LPWSTR
)IDI_APPLICATION
);
703 wc
.hbrBackground
= mBrush
;
704 wc
.lpszMenuName
= NULL
;
705 wc
.lpszClassName
= kClassNameHidden
;
707 BOOL succeeded
= ::RegisterClassW(&wc
) != 0 &&
708 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError();
709 nsWindow::sIsRegistered
= succeeded
;
711 wc
.lpszClassName
= kClassNameContentFrame
;
712 if (!::RegisterClassW(&wc
) &&
713 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
714 nsWindow::sIsRegistered
= FALSE
;
717 wc
.lpszClassName
= kClassNameContent
;
718 if (!::RegisterClassW(&wc
) &&
719 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
720 nsWindow::sIsRegistered
= FALSE
;
723 wc
.lpszClassName
= kClassNameUI
;
724 if (!::RegisterClassW(&wc
) &&
725 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
726 nsWindow::sIsRegistered
= FALSE
;
729 wc
.lpszClassName
= kClassNameGeneral
;
730 ATOM generalClassAtom
= ::RegisterClassW(&wc
);
731 if (!generalClassAtom
&&
732 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
733 nsWindow::sIsRegistered
= FALSE
;
736 wc
.lpszClassName
= kClassNameDialog
;
738 if (!::RegisterClassW(&wc
) &&
739 ERROR_CLASS_ALREADY_EXISTS
!= GetLastError()) {
740 nsWindow::sIsRegistered
= FALSE
;
744 if (mWindowType
== eWindowType_invisible
) {
745 return kClassNameHidden
;
747 if (mWindowType
== eWindowType_dialog
) {
748 return kClassNameDialog
;
750 if (mContentType
== eContentTypeContent
) {
751 return kClassNameContent
;
753 if (mContentType
== eContentTypeContentFrame
) {
754 return kClassNameContentFrame
;
756 if (mContentType
== eContentTypeUI
) {
759 return kClassNameGeneral
;
762 // Return the proper popup window class
763 LPCWSTR
nsWindow::WindowPopupClass()
765 if (!nsWindow::sIsPopupClassRegistered
) {
768 wc
.style
= CS_DBLCLKS
| CS_XP_DROPSHADOW
;
769 wc
.lpfnWndProc
= ::DefWindowProcW
;
772 wc
.hInstance
= nsToolkit::mDllInstance
;
773 wc
.hIcon
= ::LoadIconW(::GetModuleHandleW(NULL
), (LPWSTR
)IDI_APPLICATION
);
775 wc
.hbrBackground
= mBrush
;
776 wc
.lpszMenuName
= NULL
;
777 wc
.lpszClassName
= kClassNameDropShadow
;
779 nsWindow::sIsPopupClassRegistered
= ::RegisterClassW(&wc
);
780 if (!nsWindow::sIsPopupClassRegistered
) {
781 // For older versions of Win32 (i.e., not XP), the registration will
782 // fail, so we have to re-register without the CS_XP_DROPSHADOW flag.
783 wc
.style
= CS_DBLCLKS
;
784 nsWindow::sIsPopupClassRegistered
= ::RegisterClassW(&wc
);
788 return kClassNameDropShadow
;
791 /**************************************************************
793 * SECTION: Window styles utilities
795 * Return the proper windows styles and extended styles.
797 **************************************************************/
799 // Return nsWindow styles
800 #if !defined(WINCE) // implemented in nsWindowCE.cpp
801 DWORD
nsWindow::WindowStyle()
805 switch (mWindowType
) {
806 case eWindowType_plugin
:
807 case eWindowType_child
:
808 style
= WS_OVERLAPPED
;
811 case eWindowType_dialog
:
812 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
| DS_3DLOOK
| DS_MODALFRAME
;
813 if (mBorderStyle
!= eBorderStyle_default
)
814 style
|= WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
817 case eWindowType_popup
:
819 if (mTransparencyMode
!= eTransparencyGlass
) {
820 style
|= WS_OVERLAPPED
;
825 NS_ERROR("unknown border style");
828 case eWindowType_toplevel
:
829 case eWindowType_invisible
:
830 style
= WS_OVERLAPPED
| WS_BORDER
| WS_DLGFRAME
| WS_SYSMENU
|
831 WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
835 if (mBorderStyle
!= eBorderStyle_default
&& mBorderStyle
!= eBorderStyle_all
) {
836 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_border
))
839 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_title
)) {
840 style
&= ~WS_DLGFRAME
;
845 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_close
))
847 // XXX The close box can only be removed by changing the window class,
848 // as far as I know --- roc+moz@cs.cmu.edu
850 if (mBorderStyle
== eBorderStyle_none
||
851 !(mBorderStyle
& (eBorderStyle_menu
| eBorderStyle_close
)))
852 style
&= ~WS_SYSMENU
;
853 // Looks like getting rid of the system menu also does away with the
854 // close box. So, we only get rid of the system menu if you want neither it
855 // nor the close box. How does the Windows "Dialog" window class get just
856 // closebox and no sysmenu? Who knows.
858 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_resizeh
))
859 style
&= ~WS_THICKFRAME
;
861 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_minimize
))
862 style
&= ~WS_MINIMIZEBOX
;
864 if (mBorderStyle
== eBorderStyle_none
|| !(mBorderStyle
& eBorderStyle_maximize
))
865 style
&= ~WS_MAXIMIZEBOX
;
867 VERIFY_WINDOW_STYLE(style
);
870 #endif // !defined(WINCE)
872 // Return nsWindow extended styles
873 DWORD
nsWindow::WindowExStyle()
877 case eWindowType_plugin
:
878 case eWindowType_child
:
881 case eWindowType_dialog
:
882 return WS_EX_WINDOWEDGE
| WS_EX_DLGMODALFRAME
;
884 case eWindowType_popup
:
886 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
889 WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
892 NS_ERROR("unknown border style");
895 case eWindowType_toplevel
:
896 case eWindowType_invisible
:
897 return WS_EX_WINDOWEDGE
;
901 /**************************************************************
903 * SECTION: Window subclassing utilities
905 * Set or clear window subclasses on native windows. Used in
906 * Create and Destroy.
908 **************************************************************/
910 // Subclass (or remove the subclass from) this component's nsWindow
911 void nsWindow::SubclassWindow(BOOL bState
)
914 //NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
915 if (!::IsWindow(mWnd
)) {
916 NS_ERROR("Invalid window handle");
920 // change the nsWindow proc
922 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
,
923 (LONG_PTR
)nsWindow::WindowProc
);
925 mPrevWndProc
= (WNDPROC
)::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
,
926 (LONG_PTR
)nsWindow::WindowProc
);
927 NS_ASSERTION(mPrevWndProc
, "Null standard window procedure");
928 // connect the this pointer to the nsWindow handle
929 SetNSWindowPtr(mWnd
, this);
933 ::SetWindowLongPtrW(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
935 ::SetWindowLongPtrA(mWnd
, GWLP_WNDPROC
, (LONG_PTR
)mPrevWndProc
);
936 SetNSWindowPtr(mWnd
, NULL
);
942 /**************************************************************
944 * SECTION: Window properties
946 * Set and clear native window properties.
948 **************************************************************/
950 static PRUnichar sPropName
[40] = L
"";
951 static PRUnichar
* GetNSWindowPropName()
955 _snwprintf(sPropName
, 39, L
"MozillansIWidgetPtr%p", GetCurrentProcessId());
956 sPropName
[39] = '\0';
961 nsWindow
* nsWindow::GetNSWindowPtr(HWND aWnd
)
963 return (nsWindow
*) ::GetPropW(aWnd
, GetNSWindowPropName());
966 BOOL
nsWindow::SetNSWindowPtr(HWND aWnd
, nsWindow
* ptr
)
969 ::RemovePropW(aWnd
, GetNSWindowPropName());
972 return ::SetPropW(aWnd
, GetNSWindowPropName(), (HANDLE
)ptr
);
976 /**************************************************************
978 * SECTION: nsIWidget::SetParent, nsIWidget::GetParent
980 * Set or clear the parent widgets using window properties, and
981 * handles calculating native parent handles.
983 **************************************************************/
985 // Get and set parent widgets
986 NS_IMETHODIMP
nsWindow::SetParent(nsIWidget
*aNewParent
)
989 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
991 nsIWidget
* parent
= GetParent();
993 parent
->RemoveChild(this);
996 HWND newParent
= (HWND
)aNewParent
->GetNativeData(NS_NATIVE_WINDOW
);
997 NS_ASSERTION(newParent
, "Parent widget has a null native window handle");
998 if (newParent
&& mWnd
) {
999 ::SetParent(mWnd
, newParent
);
1002 aNewParent
->AddChild(this);
1007 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
1009 nsIWidget
* parent
= GetParent();
1012 parent
->RemoveChild(this);
1016 // If we have no parent, SetParent should return the desktop.
1017 VERIFY(::SetParent(mWnd
, nsnull
));
1023 nsIWidget
* nsWindow::GetParent(void)
1025 return GetParentWindow(PR_FALSE
);
1028 nsWindow
* nsWindow::GetParentWindow(PRBool aIncludeOwner
)
1030 if (mIsTopWidgetWindow
) {
1031 // Must use a flag instead of mWindowType to tell if the window is the
1032 // owned by the topmost widget, because a child window can be embedded inside
1033 // a HWND which is not associated with a nsIWidget.
1037 // If this widget has already been destroyed, pretend we have no parent.
1038 // This corresponds to code in Destroy which removes the destroyed
1039 // widget from its parent's child list.
1040 if (mInDtor
|| mOnDestroyCalled
)
1044 // aIncludeOwner set to true implies walking the parent chain to retrieve the
1045 // root owner. aIncludeOwner set to false implies the search will stop at the
1046 // true parent (default).
1047 nsWindow
* widget
= nsnull
;
1050 HWND parent
= ::GetParent(mWnd
);
1052 HWND parent
= nsnull
;
1054 parent
= ::GetParent(mWnd
);
1056 parent
= ::GetAncestor(mWnd
, GA_PARENT
);
1059 widget
= GetNSWindowPtr(parent
);
1061 // If the widget is in the process of being destroyed then
1063 if (widget
->mInDtor
) {
1073 /**************************************************************
1075 * SECTION: nsIWidget::Show
1077 * Hide or show this component.
1079 **************************************************************/
1081 NS_METHOD
nsWindow::Show(PRBool bState
)
1083 #if defined(MOZ_SPLASHSCREEN)
1084 // we're about to show the first toplevel window,
1085 // so kill off any splash screen if we had one
1086 nsSplashScreen
*splash
= nsSplashScreen::Get();
1087 if (splash
&& splash
->IsOpen() && mWnd
&& bState
&&
1088 (mWindowType
== eWindowType_toplevel
||
1089 mWindowType
== eWindowType_dialog
||
1090 mWindowType
== eWindowType_popup
))
1096 PRBool wasVisible
= mIsVisible
;
1097 // Set the status now so that anyone asking during ShowWindow or
1098 // SetWindowPos would get the correct answer.
1099 mIsVisible
= bState
;
1103 if (!wasVisible
&& mWindowType
== eWindowType_toplevel
) {
1104 switch (mSizeMode
) {
1106 case nsSizeMode_Fullscreen
:
1107 ::SetForegroundWindow(mWnd
);
1108 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1109 MakeFullScreen(TRUE
);
1112 case nsSizeMode_Maximized
:
1113 ::SetForegroundWindow(mWnd
);
1114 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1116 // use default for nsSizeMode_Minimized on Windows CE
1118 case nsSizeMode_Fullscreen
:
1119 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1122 case nsSizeMode_Maximized
:
1123 ::ShowWindow(mWnd
, SW_SHOWMAXIMIZED
);
1125 case nsSizeMode_Minimized
:
1126 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
1130 if (CanTakeFocus()) {
1132 ::SetForegroundWindow(mWnd
);
1134 ::ShowWindow(mWnd
, SW_SHOWNORMAL
);
1136 // Place the window behind the foreground window
1137 // (as long as it is not topmost)
1138 HWND wndAfter
= ::GetForegroundWindow();
1140 wndAfter
= HWND_BOTTOM
;
1141 else if (GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
)
1142 wndAfter
= HWND_TOP
;
1143 ::SetWindowPos(mWnd
, wndAfter
, 0, 0, 0, 0, SWP_SHOWWINDOW
| SWP_NOSIZE
|
1144 SWP_NOMOVE
| SWP_NOACTIVATE
);
1150 DWORD flags
= SWP_NOSIZE
| SWP_NOMOVE
| SWP_SHOWWINDOW
;
1152 flags
|= SWP_NOZORDER
;
1154 if (mWindowType
== eWindowType_popup
) {
1156 // ensure popups are the topmost of the TOPMOST
1157 // layer. Remember not to set the SWP_NOZORDER
1158 // flag as that might allow the taskbar to overlap
1159 // the popup. However on windows ce, we need to
1160 // activate the popup or clicks will not be sent.
1161 flags
|= SWP_NOACTIVATE
;
1163 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
1164 ::SetWindowPos(mWnd
, owner
? 0 : HWND_TOPMOST
, 0, 0, 0, 0, flags
);
1167 if (mWindowType
== eWindowType_dialog
&& !CanTakeFocus())
1168 flags
|= SWP_NOACTIVATE
;
1170 ::SetWindowPos(mWnd
, HWND_TOP
, 0, 0, 0, 0, flags
);
1174 if (mWindowType
!= eWindowType_dialog
) {
1175 ::ShowWindow(mWnd
, SW_HIDE
);
1177 ::SetWindowPos(mWnd
, 0, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1178 SWP_NOZORDER
| SWP_NOACTIVATE
);
1184 if (!wasVisible
&& bState
)
1185 Invalidate(PR_FALSE
);
1191 /**************************************************************
1193 * SECTION: nsIWidget::IsVisible
1195 * Returns the visibility state.
1197 **************************************************************/
1199 // Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
1200 NS_METHOD
nsWindow::IsVisible(PRBool
& bState
)
1202 bState
= mIsVisible
;
1206 /**************************************************************
1208 * SECTION: Window clipping utilities
1210 * Used in Size and Move operations for setting the proper
1211 * window clipping regions for window transparency.
1213 **************************************************************/
1215 // XP and Vista visual styles sometimes require window clipping regions to be applied for proper
1216 // transparency. These routines are called on size and move operations.
1217 void nsWindow::ClearThemeRegion()
1220 if (nsUXThemeData::sIsVistaOrLater
&& mTransparencyMode
!= eTransparencyGlass
&&
1221 mWindowType
== eWindowType_popup
&& (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
)) {
1222 SetWindowRgn(mWnd
, NULL
, false);
1227 void nsWindow::SetThemeRegion()
1230 // Popup types that have a visual styles region applied (bug 376408). This can be expanded
1231 // for other window types as needed. The regions are applied generically to the base window
1232 // so default constants are used for part and state. At some point we might need part and
1233 // state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
1234 // change shape based on state haven't come up.
1235 if (nsUXThemeData::sIsVistaOrLater
&& mTransparencyMode
!= eTransparencyGlass
&&
1236 mWindowType
== eWindowType_popup
&& (mPopupType
== ePopupTypeTooltip
|| mPopupType
== ePopupTypePanel
)) {
1238 RECT rect
= {0,0,mBounds
.width
,mBounds
.height
};
1240 nsUXThemeData::getThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip
), GetDC(mWnd
), TTP_STANDARD
, TS_NORMAL
, &rect
, &hRgn
);
1242 if (!SetWindowRgn(mWnd
, hRgn
, false)) // do not delete or alter hRgn if accepted.
1249 /**************************************************************
1251 * SECTION: nsIWidget::Move, nsIWidget::Resize,
1252 * nsIWidget::Size, nsIWidget::BeginResizeDrag
1254 * Repositioning and sizing a window.
1256 **************************************************************/
1258 // Move this component
1259 NS_METHOD
nsWindow::Move(PRInt32 aX
, PRInt32 aY
)
1261 if (mWindowType
== eWindowType_toplevel
||
1262 mWindowType
== eWindowType_dialog
) {
1263 SetSizeMode(nsSizeMode_Normal
);
1265 // Check to see if window needs to be moved first
1266 // to avoid a costly call to SetWindowPos. This check
1267 // can not be moved to the calling code in nsView, because
1268 // some platforms do not position child windows correctly
1270 // Only perform this check for non-popup windows, since the positioning can
1271 // in fact change even when the x/y do not. We always need to perform the
1272 // check. See bug #97805 for details.
1273 if (mWindowType
!= eWindowType_popup
&& (mBounds
.x
== aX
) && (mBounds
.y
== aY
))
1275 // Nothing to do, since it is already positioned correctly.
1284 // complain if a window is moved offscreen (legal, but potentially worrisome)
1285 if (mIsTopWidgetWindow
) { // only a problem for top-level windows
1286 // Make sure this window is actually on the screen before we move it
1287 // XXX: Needs multiple monitor support
1288 HDC dc
= ::GetDC(mWnd
);
1290 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1292 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &workArea
, 0);
1293 // no annoying assertions. just mention the issue.
1294 if (aX
< 0 || aX
>= workArea
.right
|| aY
< 0 || aY
>= workArea
.bottom
)
1295 printf("window moved to offscreen position\n");
1297 ::ReleaseDC(mWnd
, dc
);
1302 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, 0, 0,
1303 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOSIZE
));
1309 // Resize this component
1310 NS_METHOD
nsWindow::Resize(PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1312 NS_ASSERTION((aWidth
>=0 ) , "Negative width passed to nsWindow::Resize");
1313 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1316 if (eTransparencyTransparent
== mTransparencyMode
)
1317 ResizeTranslucentWindow(aWidth
, aHeight
);
1320 // Set cached value for lightweight and printing
1321 mBounds
.width
= aWidth
;
1322 mBounds
.height
= aHeight
;
1325 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOMOVE
;
1329 flags
|= SWP_NOREDRAW
;
1334 VERIFY(::SetWindowPos(mWnd
, NULL
, 0, 0, aWidth
, GetHeight(aHeight
), flags
));
1339 Invalidate(PR_FALSE
);
1344 // Resize this component
1345 NS_METHOD
nsWindow::Resize(PRInt32 aX
, PRInt32 aY
, PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
1347 NS_ASSERTION((aWidth
>=0 ), "Negative width passed to nsWindow::Resize");
1348 NS_ASSERTION((aHeight
>=0 ), "Negative height passed to nsWindow::Resize");
1351 if (eTransparencyTransparent
== mTransparencyMode
)
1352 ResizeTranslucentWindow(aWidth
, aHeight
);
1355 // Set cached value for lightweight and printing
1358 mBounds
.width
= aWidth
;
1359 mBounds
.height
= aHeight
;
1362 UINT flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1365 flags
|= SWP_NOREDRAW
;
1370 VERIFY(::SetWindowPos(mWnd
, NULL
, aX
, aY
, aWidth
, GetHeight(aHeight
), flags
));
1375 Invalidate(PR_FALSE
);
1382 nsWindow::BeginResizeDrag(nsGUIEvent
* aEvent
, PRInt32 aHorizontal
, PRInt32 aVertical
)
1384 NS_ENSURE_ARG_POINTER(aEvent
);
1386 if (aEvent
->eventStructType
!= NS_MOUSE_EVENT
) {
1387 // you can only begin a resize drag with a mouse event
1388 return NS_ERROR_INVALID_ARG
;
1391 nsMouseEvent
* mouseEvent
= static_cast<nsMouseEvent
*>(aEvent
);
1392 if (mouseEvent
->button
!= nsMouseEvent::eLeftButton
) {
1393 // you can only begin a resize drag with the left mouse button
1394 return NS_ERROR_INVALID_ARG
;
1397 // work out what sizemode we're talking about
1399 if (aVertical
< 0) {
1400 if (aHorizontal
< 0) {
1401 syscommand
= SC_SIZE
| WMSZ_TOPLEFT
;
1402 } else if (aHorizontal
== 0) {
1403 syscommand
= SC_SIZE
| WMSZ_TOP
;
1405 syscommand
= SC_SIZE
| WMSZ_TOPRIGHT
;
1407 } else if (aVertical
== 0) {
1408 if (aHorizontal
< 0) {
1409 syscommand
= SC_SIZE
| WMSZ_LEFT
;
1410 } else if (aHorizontal
== 0) {
1411 return NS_ERROR_INVALID_ARG
;
1413 syscommand
= SC_SIZE
| WMSZ_RIGHT
;
1416 if (aHorizontal
< 0) {
1417 syscommand
= SC_SIZE
| WMSZ_BOTTOMLEFT
;
1418 } else if (aHorizontal
== 0) {
1419 syscommand
= SC_SIZE
| WMSZ_BOTTOM
;
1421 syscommand
= SC_SIZE
| WMSZ_BOTTOMRIGHT
;
1425 // resizing doesn't work if the mouse is already captured
1426 CaptureMouse(PR_FALSE
);
1428 // find the top-level window
1429 HWND toplevelWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
1431 // tell Windows to start the resize
1432 ::PostMessage(toplevelWnd
, WM_SYSCOMMAND
, syscommand
,
1433 POINTTOPOINTS(aEvent
->refPoint
));
1438 /**************************************************************
1440 * SECTION: Window Z-order and state.
1442 * nsIWidget::PlaceBehind, nsIWidget::SetSizeMode,
1443 * nsIWidget::ConstrainPosition
1445 * Z-order, positioning, restore, minimize, and maximize.
1447 **************************************************************/
1449 // Position the window behind the given window
1450 NS_METHOD
nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
1451 nsIWidget
*aWidget
, PRBool aActivate
)
1453 HWND behind
= HWND_TOP
;
1454 if (aPlacement
== eZPlacementBottom
)
1455 behind
= HWND_BOTTOM
;
1456 else if (aPlacement
== eZPlacementBelow
&& aWidget
)
1457 behind
= (HWND
)aWidget
->GetNativeData(NS_NATIVE_WINDOW
);
1458 UINT flags
= SWP_NOMOVE
| SWP_NOREPOSITION
| SWP_NOSIZE
;
1460 flags
|= SWP_NOACTIVATE
;
1462 if (!CanTakeFocus() && behind
== HWND_TOP
)
1464 // Can't place the window to top so place it behind the foreground window
1465 // (as long as it is not topmost)
1466 HWND wndAfter
= ::GetForegroundWindow();
1468 behind
= HWND_BOTTOM
;
1469 else if (!(GetWindowLongPtrW(wndAfter
, GWL_EXSTYLE
) & WS_EX_TOPMOST
))
1471 flags
|= SWP_NOACTIVATE
;
1474 ::SetWindowPos(mWnd
, behind
, 0, 0, 0, 0, flags
);
1478 // Maximize, minimize or restore the window.
1479 #if !defined(WINCE) // implemented in nsWindowCE.cpp
1480 NS_IMETHODIMP
nsWindow::SetSizeMode(PRInt32 aMode
) {
1484 // Let's not try and do anything if we're already in that state.
1485 // (This is needed to prevent problems when calling window.minimize(), which
1486 // calls us directly, and then the OS triggers another call to us.)
1487 if (aMode
== mSizeMode
)
1490 // save the requested state
1491 rv
= nsBaseWidget::SetSizeMode(aMode
);
1492 if (NS_SUCCEEDED(rv
) && mIsVisible
) {
1496 case nsSizeMode_Fullscreen
:
1500 case nsSizeMode_Maximized
:
1504 case nsSizeMode_Minimized
:
1505 // Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
1506 // keeps the window active in the tray. So after the window is minimized,
1507 // windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
1508 // we will do some additional processing to get the active window set right.
1509 // If sTrimOnMinimize is set, we let windows handle minimization normally
1510 // using SW_MINIMIZE.
1511 mode
= sTrimOnMinimize
? SW_MINIMIZE
: SW_SHOWMINIMIZED
;
1517 ::ShowWindow(mWnd
, mode
);
1518 // we dispatch an activate event here to ensure that the right child window
1520 if (mode
== SW_RESTORE
|| mode
== SW_MAXIMIZE
)
1521 DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
1525 #endif // !defined(WINCE)
1527 // Constrain a potential move to fit onscreen
1528 NS_METHOD
nsWindow::ConstrainPosition(PRBool aAllowSlop
,
1529 PRInt32
*aX
, PRInt32
*aY
)
1531 if (!mIsTopWidgetWindow
) // only a problem for top-level windows
1534 PRBool doConstrain
= PR_FALSE
; // whether we have enough info to do anything
1536 /* get our playing field. use the current screen, or failing that
1537 for any reason, use device caps for the default screen. */
1540 nsCOMPtr
<nsIScreenManager
> screenmgr
= do_GetService(sScreenManagerContractID
);
1542 nsCOMPtr
<nsIScreen
> screen
;
1543 PRInt32 left
, top
, width
, height
;
1545 // zero size rects confuse the screen manager
1546 width
= mBounds
.width
> 0 ? mBounds
.width
: 1;
1547 height
= mBounds
.height
> 0 ? mBounds
.height
: 1;
1548 screenmgr
->ScreenForRect(*aX
, *aY
, width
, height
,
1549 getter_AddRefs(screen
));
1551 screen
->GetAvailRect(&left
, &top
, &width
, &height
);
1552 screenRect
.left
= left
;
1553 screenRect
.right
= left
+width
;
1554 screenRect
.top
= top
;
1555 screenRect
.bottom
= top
+height
;
1556 doConstrain
= PR_TRUE
;
1560 HDC dc
= ::GetDC(mWnd
);
1562 if (::GetDeviceCaps(dc
, TECHNOLOGY
) == DT_RASDISPLAY
) {
1563 ::SystemParametersInfo(SPI_GETWORKAREA
, 0, &screenRect
, 0);
1564 doConstrain
= PR_TRUE
;
1566 ::ReleaseDC(mWnd
, dc
);
1572 if (*aX
< screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
)
1573 *aX
= screenRect
.left
- mBounds
.width
+ kWindowPositionSlop
;
1574 else if (*aX
>= screenRect
.right
- kWindowPositionSlop
)
1575 *aX
= screenRect
.right
- kWindowPositionSlop
;
1577 if (*aY
< screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
)
1578 *aY
= screenRect
.top
- mBounds
.height
+ kWindowPositionSlop
;
1579 else if (*aY
>= screenRect
.bottom
- kWindowPositionSlop
)
1580 *aY
= screenRect
.bottom
- kWindowPositionSlop
;
1584 if (*aX
< screenRect
.left
)
1585 *aX
= screenRect
.left
;
1586 else if (*aX
>= screenRect
.right
- mBounds
.width
)
1587 *aX
= screenRect
.right
- mBounds
.width
;
1589 if (*aY
< screenRect
.top
)
1590 *aY
= screenRect
.top
;
1591 else if (*aY
>= screenRect
.bottom
- mBounds
.height
)
1592 *aY
= screenRect
.bottom
- mBounds
.height
;
1598 /**************************************************************
1600 * SECTION: nsIWidget::Enable, nsIWidget::IsEnabled
1602 * Enabling and disabling the widget.
1604 **************************************************************/
1606 // Enable/disable this component
1607 NS_METHOD
nsWindow::Enable(PRBool bState
)
1610 ::EnableWindow(mWnd
, bState
);
1615 // Return the current enable state
1616 NS_METHOD
nsWindow::IsEnabled(PRBool
*aState
)
1618 NS_ENSURE_ARG_POINTER(aState
);
1621 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(::GetAncestor(mWnd
, GA_ROOT
)));
1623 *aState
= !mWnd
|| (::IsWindowEnabled(mWnd
) && ::IsWindowEnabled(mWnd
));
1630 /**************************************************************
1632 * SECTION: nsIWidget::SetFocus
1634 * Give the focus to this widget.
1636 **************************************************************/
1638 NS_METHOD
nsWindow::SetFocus(PRBool aRaise
)
1641 #ifdef WINSTATE_DEBUG_OUTPUT
1642 if (mWnd
== GetTopLevelHWND(mWnd
))
1643 printf("*** SetFocus: [ top] raise=%d\n", aRaise
);
1645 printf("*** SetFocus: [child] raise=%d\n", aRaise
);
1647 // Uniconify, if necessary
1648 HWND toplevelWnd
= GetTopLevelHWND(mWnd
);
1649 if (aRaise
&& ::IsIconic(toplevelWnd
)) {
1650 ::ShowWindow(toplevelWnd
, SW_RESTORE
);
1658 /**************************************************************
1662 * nsIWidget::GetBounds, nsIWidget::GetScreenBounds,
1663 * nsIWidget::GetClientBounds
1665 * Bound calculations.
1667 **************************************************************/
1669 // Get this component dimension
1670 NS_METHOD
nsWindow::GetBounds(nsIntRect
&aRect
)
1674 VERIFY(::GetWindowRect(mWnd
, &r
));
1677 aRect
.width
= r
.right
- r
.left
;
1678 aRect
.height
= r
.bottom
- r
.top
;
1680 // convert coordinates if parent exists
1681 HWND parent
= ::GetParent(mWnd
);
1684 VERIFY(::GetWindowRect(parent
, &pr
));
1697 // Get this component dimension
1698 NS_METHOD
nsWindow::GetClientBounds(nsIntRect
&aRect
)
1702 VERIFY(::GetClientRect(mWnd
, &r
));
1707 aRect
.width
= r
.right
- r
.left
;
1708 aRect
.height
= r
.bottom
- r
.top
;
1711 aRect
.SetRect(0,0,0,0);
1716 // Get the bounds, but don't take into account the client size
1717 void nsWindow::GetNonClientBounds(nsIntRect
&aRect
)
1721 VERIFY(::GetWindowRect(mWnd
, &r
));
1724 aRect
.width
= r
.right
- r
.left
;
1725 aRect
.height
= r
.bottom
- r
.top
;
1727 // convert coordinates if parent exists
1728 HWND parent
= ::GetParent(mWnd
);
1731 VERIFY(::GetWindowRect(parent
, &pr
));
1738 aRect
.SetRect(0,0,0,0);
1742 // Like GetBounds, but don't offset by the parent
1743 NS_METHOD
nsWindow::GetScreenBounds(nsIntRect
&aRect
)
1747 VERIFY(::GetWindowRect(mWnd
, &r
));
1749 aRect
.width
= r
.right
- r
.left
;
1750 aRect
.height
= r
.bottom
- r
.top
;
1759 /**************************************************************
1761 * SECTION: nsIWidget::SetBackgroundColor
1763 * Sets the window background paint color.
1765 **************************************************************/
1767 NS_METHOD
nsWindow::SetBackgroundColor(const nscolor
&aColor
)
1769 nsBaseWidget::SetBackgroundColor(aColor
);
1772 ::DeleteObject(mBrush
);
1774 mBrush
= ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground
));
1777 ::SetClassLongPtrW(mWnd
, GCLP_HBRBACKGROUND
, (LONG_PTR
)mBrush
);
1783 /**************************************************************
1785 * SECTION: nsIWidget::SetCursor
1787 * SetCursor and related utilities for manging cursor state.
1789 **************************************************************/
1791 // Set this component cursor
1792 NS_METHOD
nsWindow::SetCursor(nsCursor aCursor
)
1794 // Only change cursor if it's changing
1796 //XXX mCursor isn't always right. Scrollbars and others change it, too.
1797 //XXX If we want this optimization we need a better way to do it.
1798 //if (aCursor != mCursor) {
1799 HCURSOR newCursor
= NULL
;
1802 case eCursor_select
:
1803 newCursor
= ::LoadCursor(NULL
, IDC_IBEAM
);
1807 newCursor
= ::LoadCursor(NULL
, IDC_WAIT
);
1810 case eCursor_hyperlink
:
1812 newCursor
= ::LoadCursor(NULL
, IDC_HAND
);
1816 case eCursor_standard
:
1817 newCursor
= ::LoadCursor(NULL
, IDC_ARROW
);
1820 case eCursor_n_resize
:
1821 case eCursor_s_resize
:
1822 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
1825 case eCursor_w_resize
:
1826 case eCursor_e_resize
:
1827 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
1830 case eCursor_nw_resize
:
1831 case eCursor_se_resize
:
1832 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
1835 case eCursor_ne_resize
:
1836 case eCursor_sw_resize
:
1837 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
1840 case eCursor_crosshair
:
1841 newCursor
= ::LoadCursor(NULL
, IDC_CROSS
);
1845 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
1849 newCursor
= ::LoadCursor(NULL
, IDC_HELP
);
1852 case eCursor_copy
: // CSS3
1853 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COPY
));
1857 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ALIAS
));
1861 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_CELL
));
1865 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRAB
));
1868 case eCursor_grabbing
:
1869 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_GRABBING
));
1872 case eCursor_spinning
:
1873 newCursor
= ::LoadCursor(NULL
, IDC_APPSTARTING
);
1876 case eCursor_context_menu
:
1877 // XXX this CSS3 cursor needs to be implemented
1880 case eCursor_zoom_in
:
1881 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMIN
));
1884 case eCursor_zoom_out
:
1885 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ZOOMOUT
));
1888 case eCursor_not_allowed
:
1889 case eCursor_no_drop
:
1890 newCursor
= ::LoadCursor(NULL
, IDC_NO
);
1893 case eCursor_col_resize
:
1894 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_COLRESIZE
));
1897 case eCursor_row_resize
:
1898 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_ROWRESIZE
));
1901 case eCursor_vertical_text
:
1902 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_VERTICALTEXT
));
1905 case eCursor_all_scroll
:
1906 // XXX not 100% appropriate perhaps
1907 newCursor
= ::LoadCursor(NULL
, IDC_SIZEALL
);
1910 case eCursor_nesw_resize
:
1911 newCursor
= ::LoadCursor(NULL
, IDC_SIZENESW
);
1914 case eCursor_nwse_resize
:
1915 newCursor
= ::LoadCursor(NULL
, IDC_SIZENWSE
);
1918 case eCursor_ns_resize
:
1919 newCursor
= ::LoadCursor(NULL
, IDC_SIZENS
);
1922 case eCursor_ew_resize
:
1923 newCursor
= ::LoadCursor(NULL
, IDC_SIZEWE
);
1927 newCursor
= ::LoadCursor(nsToolkit::mDllInstance
, MAKEINTRESOURCE(IDC_NONE
));
1931 NS_ERROR("Invalid cursor type");
1935 if (NULL
!= newCursor
) {
1937 HCURSOR oldCursor
= ::SetCursor(newCursor
);
1939 if (sHCursor
== oldCursor
) {
1940 NS_IF_RELEASE(sCursorImgContainer
);
1941 if (sHCursor
!= NULL
)
1942 ::DestroyIcon(sHCursor
);
1950 // Setting the actual cursor
1951 NS_IMETHODIMP
nsWindow::SetCursor(imgIContainer
* aCursor
,
1952 PRUint32 aHotspotX
, PRUint32 aHotspotY
)
1954 if (sCursorImgContainer
== aCursor
&& sHCursor
) {
1955 ::SetCursor(sHCursor
);
1963 rv
= aCursor
->GetWidth(&width
);
1964 NS_ENSURE_SUCCESS(rv
, rv
);
1965 rv
= aCursor
->GetHeight(&height
);
1966 NS_ENSURE_SUCCESS(rv
, rv
);
1968 // Reject cursors greater than 128 pixels in either direction, to prevent
1970 // XXX ideally we should rescale. Also, we could modify the API to
1971 // allow trusted content to set larger cursors.
1972 if (width
> 128 || height
> 128)
1973 return NS_ERROR_NOT_AVAILABLE
;
1976 rv
= nsWindowGfx::CreateIcon(aCursor
, PR_TRUE
, aHotspotX
, aHotspotY
, &cursor
);
1977 NS_ENSURE_SUCCESS(rv
, rv
);
1979 mCursor
= nsCursor(-1);
1980 ::SetCursor(cursor
);
1982 NS_IF_RELEASE(sCursorImgContainer
);
1983 sCursorImgContainer
= aCursor
;
1984 NS_ADDREF(sCursorImgContainer
);
1986 if (sHCursor
!= NULL
)
1987 ::DestroyIcon(sHCursor
);
1993 /**************************************************************
1995 * SECTION: nsIWidget::Get/SetTransparencyMode
1997 * Manage the transparency mode of the top-level window
1998 * containing this widget.
2000 **************************************************************/
2003 nsTransparencyMode
nsWindow::GetTransparencyMode()
2005 return GetTopLevelWindow(PR_TRUE
)->GetWindowTranslucencyInner();
2008 void nsWindow::SetTransparencyMode(nsTransparencyMode aMode
)
2010 GetTopLevelWindow(PR_TRUE
)->SetWindowTranslucencyInner(aMode
);
2014 /**************************************************************
2016 * SECTION: nsIWidget::HideWindowChrome
2018 * Show or hide window chrome.
2020 **************************************************************/
2022 NS_IMETHODIMP
nsWindow::HideWindowChrome(PRBool aShouldHide
)
2024 HWND hwnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
2025 if (!GetNSWindowPtr(hwnd
))
2027 NS_WARNING("Trying to hide window decorations in an embedded context");
2028 return NS_ERROR_FAILURE
;
2031 DWORD_PTR style
, exStyle
;
2033 DWORD_PTR tempStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2034 DWORD_PTR tempExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2036 style
= tempStyle
& ~(WS_CAPTION
| WS_THICKFRAME
);
2037 exStyle
= tempExStyle
& ~(WS_EX_DLGMODALFRAME
| WS_EX_WINDOWEDGE
|
2038 WS_EX_CLIENTEDGE
| WS_EX_STATICEDGE
);
2040 mOldStyle
= tempStyle
;
2041 mOldExStyle
= tempExStyle
;
2044 if (!mOldStyle
|| !mOldExStyle
) {
2045 mOldStyle
= ::GetWindowLongPtrW(hwnd
, GWL_STYLE
);
2046 mOldExStyle
= ::GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
);
2050 exStyle
= mOldExStyle
;
2053 VERIFY_WINDOW_STYLE(style
);
2054 ::SetWindowLongPtrW(hwnd
, GWL_STYLE
, style
);
2055 ::SetWindowLongPtrW(hwnd
, GWL_EXSTYLE
, exStyle
);
2060 /**************************************************************
2062 * SECTION: nsIWidget::Invalidate
2064 * Invalidate an area of the client for painting.
2066 **************************************************************/
2068 #ifdef WINCE_WINDOWS_MOBILE
2069 static inline void AddRECTToRegion(const RECT
& aRect
, nsIRegion
* aRegion
)
2071 aRegion
->Union(aRect
.left
, aRect
.top
, aRect
.right
- aRect
.left
, aRect
.bottom
- aRect
.top
);
2075 // Invalidate this component visible area
2076 NS_METHOD
nsWindow::Invalidate(PRBool aIsSynchronous
)
2080 #ifdef WIDGET_DEBUG_OUTPUT
2081 debug_DumpInvalidate(stdout
,
2085 nsCAutoString("noname"),
2087 #endif // WIDGET_DEBUG_OUTPUT
2088 #ifdef WINCE_WINDOWS_MOBILE
2089 // We need to keep track of our own invalidated region for Windows CE
2091 GetClientRect(mWnd
, &r
);
2092 AddRECTToRegion(r
, mInvalidatedRegion
);
2094 VERIFY(::InvalidateRect(mWnd
, NULL
, FALSE
));
2096 if (aIsSynchronous
) {
2097 VERIFY(::UpdateWindow(mWnd
));
2103 // Invalidate this component visible area
2104 NS_METHOD
nsWindow::Invalidate(const nsIntRect
& aRect
, PRBool aIsSynchronous
)
2108 #ifdef WIDGET_DEBUG_OUTPUT
2109 debug_DumpInvalidate(stdout
,
2113 nsCAutoString("noname"),
2115 #endif // WIDGET_DEBUG_OUTPUT
2119 rect
.left
= aRect
.x
;
2121 rect
.right
= aRect
.x
+ aRect
.width
;
2122 rect
.bottom
= aRect
.y
+ aRect
.height
;
2124 #ifdef WINCE_WINDOWS_MOBILE
2125 // We need to keep track of our own invalidated region for Windows CE
2126 AddRECTToRegion(rect
, mInvalidatedRegion
);
2128 VERIFY(::InvalidateRect(mWnd
, &rect
, FALSE
));
2130 if (aIsSynchronous
) {
2131 VERIFY(::UpdateWindow(mWnd
));
2138 nsWindow::MakeFullScreen(PRBool aFullScreen
)
2140 #if WINCE_WINDOWS_MOBILE
2143 SetForegroundWindow(mWnd
);
2144 SHFullScreen(mWnd
, SHFS_HIDETASKBAR
| SHFS_HIDESTARTICON
);
2145 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2148 SHFullScreen(mWnd
, SHFS_SHOWTASKBAR
| SHFS_SHOWSTARTICON
);
2149 SystemParametersInfo(SPI_GETWORKAREA
, 0, &rc
, FALSE
);
2151 MoveWindow(mWnd
, rc
.left
, rc
.top
, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, TRUE
);
2154 mSizeMode
= nsSizeMode_Fullscreen
;
2157 return nsBaseWidget::MakeFullScreen(aFullScreen
);
2160 /**************************************************************
2162 * SECTION: nsIWidget::Update
2164 * Force a synchronous repaint of the window.
2166 **************************************************************/
2168 NS_IMETHODIMP
nsWindow::Update()
2170 nsresult rv
= NS_OK
;
2172 // updates can come through for windows no longer holding an mWnd during
2173 // deletes triggered by JavaScript in buttons with mouse feedback
2175 VERIFY(::UpdateWindow(mWnd
));
2180 /**************************************************************
2182 * SECTION: nsIWidget::Scroll
2184 * Scroll this widget.
2186 **************************************************************/
2189 ClipRegionContainedInRect(const nsTArray
<nsIntRect
>& aClipRects
,
2190 const nsIntRect
& aRect
)
2192 for (PRUint32 i
= 0; i
< aClipRects
.Length(); ++i
) {
2193 if (!aRect
.Contains(aClipRects
[i
]))
2199 // This function determines whether the given window has a descendant that
2200 // does not intersect the given aScreenRect. If we encounter a window owned
2201 // by another thread (which includes another process, since thread IDs
2202 // are unique system-wide), then we give up and conservatively return true.
2204 HasDescendantWindowOutsideRect(DWORD aThisThreadID
, HWND aWnd
,
2205 const RECT
& aScreenRect
)
2207 // If the window is owned by another thread, give up now, don't try to
2208 // look at its children since they could change asynchronously.
2209 // XXX should we try harder here for out-of-process plugins?
2210 if (GetWindowThreadProcessId(aWnd
, NULL
) != aThisThreadID
) {
2213 for (HWND child
= ::GetWindow(aWnd
, GW_CHILD
); child
;
2214 child
= ::GetWindow(child
, GW_HWNDNEXT
)) {
2215 RECT childScreenRect
;
2216 ::GetWindowRect(child
, &childScreenRect
);
2218 if (!::IntersectRect(&result
, &childScreenRect
, &aScreenRect
)) {
2222 if (HasDescendantWindowOutsideRect(aThisThreadID
, child
, aScreenRect
)) {
2231 nsWindow::Scroll(const nsIntPoint
& aDelta
,
2232 const nsTArray
<nsIntRect
>& aDestRects
,
2233 const nsTArray
<Configuration
>& aConfigurations
)
2235 // We use SW_SCROLLCHILDREN if all the windows that intersect the
2236 // affected area are moving by the scroll amount.
2237 // First, build the set of widgets that are to be moved by the scroll
2239 // At the same time, set the clip region of all changed windows to the
2240 // intersection of the current and new regions.
2241 nsTHashtable
<nsPtrHashKey
<nsWindow
> > scrolledWidgets
;
2242 scrolledWidgets
.Init();
2243 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
2244 const Configuration
& configuration
= aConfigurations
[i
];
2245 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
2246 NS_ASSERTION(w
->GetParent() == this,
2247 "Configured widget is not a child");
2248 if (configuration
.mBounds
== w
->mBounds
+ aDelta
) {
2249 scrolledWidgets
.PutEntry(w
);
2251 w
->SetWindowClipRegion(configuration
.mClipRegion
, PR_TRUE
);
2254 DWORD ourThreadID
= GetWindowThreadProcessId(mWnd
, NULL
);
2256 for (PRUint32 i
= 0; i
< aDestRects
.Length(); ++i
) {
2257 nsIntRect affectedRect
;
2258 affectedRect
.UnionRect(aDestRects
[i
], aDestRects
[i
] - aDelta
);
2259 // We pass SW_INVALIDATE because areas that get scrolled into view
2260 // from offscreen (but inside the scroll area) need to be repainted.
2261 UINT flags
= SW_SCROLLCHILDREN
| SW_INVALIDATE
;
2262 // Now check if any of our children would be affected by
2263 // SW_SCROLLCHILDREN but not supposed to scroll.
2264 for (nsWindow
* w
= static_cast<nsWindow
*>(GetFirstChild()); w
;
2265 w
= static_cast<nsWindow
*>(w
->GetNextSibling())) {
2266 if (w
->mBounds
.Intersects(affectedRect
)) {
2267 // This child will be affected
2268 nsPtrHashKey
<nsWindow
>* entry
= scrolledWidgets
.GetEntry(w
);
2270 // It's supposed to be scrolled, so we can still use
2271 // SW_SCROLLCHILDREN. But don't allow SW_SCROLLCHILDREN to be
2272 // used on it again by a later rectangle in aDestRects, we
2273 // don't want it to move twice!
2274 scrolledWidgets
.RawRemoveEntry(entry
);
2276 nsIntPoint screenOffset
= WidgetToScreenOffset();
2277 RECT screenAffectedRect
= {
2278 screenOffset
.x
+ affectedRect
.x
,
2279 screenOffset
.y
+ affectedRect
.y
,
2280 screenOffset
.x
+ affectedRect
.XMost(),
2281 screenOffset
.y
+ affectedRect
.YMost()
2283 if (HasDescendantWindowOutsideRect(ourThreadID
, w
->mWnd
,
2284 screenAffectedRect
)) {
2285 // SW_SCROLLCHILDREN seems to not move descendant windows
2286 // that don't intersect the scrolled rectangle, *even if* the
2287 // immediate child window of the scrolled window *does* intersect
2288 // the scrolled window. So if w has a descendant window
2289 // that would not be moved, SW_SCROLLCHILDREN will hopelessly mess
2290 // things up and we must not use it.
2291 flags
&= ~SW_SCROLLCHILDREN
;
2294 flags
&= ~SW_SCROLLCHILDREN
;
2295 // We may have removed some children from scrolledWidgets even
2296 // though we decide here to not use SW_SCROLLCHILDREN. That's OK,
2297 // it just means that we might not use SW_SCROLLCHILDREN
2298 // for a later rectangle when we could have.
2304 if (flags
& SW_SCROLLCHILDREN
) {
2305 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
2306 const Configuration
& configuration
= aConfigurations
[i
];
2307 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
2308 // Widgets that will be scrolled by SW_SCROLLCHILDREN but which
2309 // will be partly visible outside the scroll area after scrolling
2310 // must be invalidated, because SW_SCROLLCHILDREN doesn't
2311 // update parts of widgets outside the area it scrolled, even
2312 // if it moved them.
2313 if (w
->mBounds
.Intersects(affectedRect
) &&
2314 !ClipRegionContainedInRect(configuration
.mClipRegion
,
2315 affectedRect
- (w
->mBounds
.TopLeft() + aDelta
))) {
2316 w
->Invalidate(PR_FALSE
);
2320 // ScrollWindowEx will send WM_MOVE to each moved window to tell it
2321 // its new position. Unfortunately those messages don't reach our
2322 // WM_MOVE handler for some plugins, so we have to update their
2323 // mBounds here. For windows that do receive WM_MOVE, this is OK,
2324 // they'll just overwrite mBounds again with the correct value.
2325 for (nsWindow
* w
= static_cast<nsWindow
*>(GetFirstChild()); w
;
2326 w
= static_cast<nsWindow
*>(w
->GetNextSibling())) {
2327 if (w
->mBounds
.Intersects(affectedRect
)) {
2328 w
->mBounds
+= aDelta
;
2333 RECT clip
= { affectedRect
.x
, affectedRect
.y
, affectedRect
.XMost(), affectedRect
.YMost() };
2334 ::ScrollWindowEx(mWnd
, aDelta
.x
, aDelta
.y
, &clip
, &clip
, NULL
, NULL
, flags
);
2337 // Now make sure all children actually get positioned, sized and clipped
2338 // correctly. If SW_SCROLLCHILDREN already moved widgets to their correct
2339 // locations, then the SetWindowPos calls this triggers will just be
2341 ConfigureChildren(aConfigurations
);
2344 /**************************************************************
2346 * SECTION: Native data storage
2348 * nsIWidget::GetNativeData
2349 * nsIWidget::FreeNativeData
2351 * Set or clear native data based on a constant.
2353 **************************************************************/
2355 // Return some native data according to aDataType
2356 void* nsWindow::GetNativeData(PRUint32 aDataType
)
2358 switch (aDataType
) {
2359 case NS_NATIVE_PLUGIN_PORT
:
2360 case NS_NATIVE_WIDGET
:
2361 case NS_NATIVE_WINDOW
:
2363 case NS_NATIVE_GRAPHIC
:
2364 // XXX: This is sleezy!! Remember to Release the DC after using it!
2366 return (void*)(eTransparencyTransparent
== mTransparencyMode
) ?
2367 mMemoryDC
: ::GetDC(mWnd
);
2369 return (void*)::GetDC(mWnd
);
2372 #ifdef NS_ENABLE_TSF
2373 case NS_NATIVE_TSF_THREAD_MGR
:
2374 return nsTextStore::GetThreadMgr();
2375 case NS_NATIVE_TSF_CATEGORY_MGR
:
2376 return nsTextStore::GetCategoryMgr();
2377 case NS_NATIVE_TSF_DISPLAY_ATTR_MGR
:
2378 return nsTextStore::GetDisplayAttrMgr();
2379 #endif //NS_ENABLE_TSF
2388 // Free some native data according to aDataType
2389 void nsWindow::FreeNativeData(void * data
, PRUint32 aDataType
)
2393 case NS_NATIVE_GRAPHIC
:
2395 if (eTransparencyTransparent
!= mTransparencyMode
)
2396 ::ReleaseDC(mWnd
, (HDC
)data
);
2398 ::ReleaseDC(mWnd
, (HDC
)data
);
2401 case NS_NATIVE_WIDGET
:
2402 case NS_NATIVE_WINDOW
:
2403 case NS_NATIVE_PLUGIN_PORT
:
2410 /**************************************************************
2412 * SECTION: nsIWidget::SetTitle
2414 * Set the main windows title text.
2416 **************************************************************/
2418 NS_METHOD
nsWindow::SetTitle(const nsAString
& aTitle
)
2420 const nsString
& strTitle
= PromiseFlatString(aTitle
);
2421 ::SendMessageW(mWnd
, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)(LPCWSTR
)strTitle
.get());
2425 /**************************************************************
2427 * SECTION: nsIWidget::SetIcon
2429 * Set the main windows icon.
2431 **************************************************************/
2433 NS_METHOD
nsWindow::SetIcon(const nsAString
& aIconSpec
)
2436 // Assume the given string is a local identifier for an icon file.
2438 nsCOMPtr
<nsILocalFile
> iconFile
;
2439 ResolveIconName(aIconSpec
, NS_LITERAL_STRING(".ico"),
2440 getter_AddRefs(iconFile
));
2442 return NS_OK
; // not an error if icon is not found
2444 nsAutoString iconPath
;
2445 iconFile
->GetPath(iconPath
);
2447 // XXX this should use MZLU (see bug 239279)
2451 HICON bigIcon
= (HICON
)::LoadImageW(NULL
,
2452 (LPCWSTR
)iconPath
.get(),
2454 ::GetSystemMetrics(SM_CXICON
),
2455 ::GetSystemMetrics(SM_CYICON
),
2457 HICON smallIcon
= (HICON
)::LoadImageW(NULL
,
2458 (LPCWSTR
)iconPath
.get(),
2460 ::GetSystemMetrics(SM_CXSMICON
),
2461 ::GetSystemMetrics(SM_CYSMICON
),
2465 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
)bigIcon
);
2467 ::DestroyIcon(icon
);
2469 #ifdef DEBUG_SetIcon
2471 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
2472 printf( "\nIcon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
2476 HICON icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
)smallIcon
);
2478 ::DestroyIcon(icon
);
2480 #ifdef DEBUG_SetIcon
2482 NS_LossyConvertUTF16toASCII
cPath(iconPath
);
2483 printf( "\nSmall icon load error; icon=%s, rc=0x%08X\n\n", cPath
.get(), ::GetLastError() );
2490 /**************************************************************
2492 * SECTION: nsIWidget::WidgetToScreenOffset
2494 * Return this widget's origin in screen coordinates.
2496 **************************************************************/
2498 nsIntPoint
nsWindow::WidgetToScreenOffset()
2503 ::ClientToScreen(mWnd
, &point
);
2504 return nsIntPoint(point
.x
, point
.y
);
2507 /**************************************************************
2509 * SECTION: nsIWidget::EnableDragDrop
2511 * Enables/Disables drag and drop of files on this widget.
2513 **************************************************************/
2515 #if !defined(WINCE) // implemented in nsWindowCE.cpp
2516 NS_METHOD
nsWindow::EnableDragDrop(PRBool aEnable
)
2518 nsresult rv
= NS_ERROR_FAILURE
;
2520 if (nsnull
== mNativeDragTarget
) {
2521 mNativeDragTarget
= new nsNativeDragTarget(this);
2522 if (NULL
!= mNativeDragTarget
) {
2523 mNativeDragTarget
->AddRef();
2524 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
,TRUE
,FALSE
)) {
2525 if (S_OK
== ::RegisterDragDrop(mWnd
, (LPDROPTARGET
)mNativeDragTarget
)) {
2532 if (nsnull
!= mWnd
&& NULL
!= mNativeDragTarget
) {
2533 ::RevokeDragDrop(mWnd
);
2534 if (S_OK
== ::CoLockObjectExternal((LPUNKNOWN
)mNativeDragTarget
, FALSE
, TRUE
)) {
2537 mNativeDragTarget
->mDragCancelled
= PR_TRUE
;
2538 NS_RELEASE(mNativeDragTarget
);
2545 /**************************************************************
2547 * SECTION: nsIWidget::CaptureMouse
2549 * Enables/Disables system mouse capture.
2551 **************************************************************/
2553 NS_METHOD
nsWindow::CaptureMouse(PRBool aCapture
)
2555 if (!nsToolkit::gMouseTrailer
) {
2556 NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
2561 nsToolkit::gMouseTrailer
->SetCaptureWindow(mWnd
);
2564 nsToolkit::gMouseTrailer
->SetCaptureWindow(NULL
);
2567 mIsInMouseCapture
= aCapture
;
2571 /**************************************************************
2573 * SECTION: nsIWidget::CaptureRollupEvents
2575 * Dealing with event rollup on destroy for popups. Enables &
2576 * Disables system capture of any and all events that would
2577 * cause a dropdown to be rolled up.
2579 **************************************************************/
2581 NS_IMETHODIMP
nsWindow::CaptureRollupEvents(nsIRollupListener
* aListener
,
2583 PRBool aConsumeRollupEvent
)
2586 /* we haven't bothered carrying a weak reference to sRollupWidget because
2587 we believe lifespan is properly scoped. this next assertion helps
2588 assure that remains true. */
2589 NS_ASSERTION(!sRollupWidget
, "rollup widget reassigned before release");
2590 sRollupConsumeEvent
= aConsumeRollupEvent
;
2591 NS_IF_RELEASE(sRollupListener
);
2592 NS_IF_RELEASE(sRollupWidget
);
2593 sRollupListener
= aListener
;
2594 NS_ADDREF(aListener
);
2595 sRollupWidget
= this;
2599 if (!sMsgFilterHook
&& !sCallProcHook
&& !sCallMouseHook
) {
2600 RegisterSpecialDropdownHooks();
2602 sProcessHook
= PR_TRUE
;
2606 NS_IF_RELEASE(sRollupListener
);
2607 NS_IF_RELEASE(sRollupWidget
);
2610 sProcessHook
= PR_FALSE
;
2611 UnregisterSpecialDropdownHooks();
2618 /**************************************************************
2620 * SECTION: nsIWidget::GetAttention
2622 * Bring this window to the user's attention.
2624 **************************************************************/
2626 // Draw user's attention to this window until it comes to foreground.
2628 nsWindow::GetAttention(PRInt32 aCycleCount
)
2633 return NS_ERROR_NOT_INITIALIZED
;
2635 // Don't flash if the flash count is 0 or if the
2636 // top level window is already active.
2637 HWND fgWnd
= ::GetForegroundWindow();
2638 if (aCycleCount
== 0 || fgWnd
== GetTopLevelHWND(mWnd
))
2641 HWND flashWnd
= mWnd
;
2642 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
2643 flashWnd
= ownerWnd
;
2646 // Don't flash if the owner window is active either.
2647 if (fgWnd
== flashWnd
)
2650 DWORD defaultCycleCount
= 0;
2651 ::SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT
, 0, &defaultCycleCount
, 0);
2653 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
2654 FLASHW_ALL
, aCycleCount
> 0 ? aCycleCount
: defaultCycleCount
, 0 };
2655 ::FlashWindowEx(&flashInfo
);
2660 void nsWindow::StopFlashing()
2663 HWND flashWnd
= mWnd
;
2664 while (HWND ownerWnd
= ::GetWindow(flashWnd
, GW_OWNER
)) {
2665 flashWnd
= ownerWnd
;
2668 FLASHWINFO flashInfo
= { sizeof(FLASHWINFO
), flashWnd
,
2669 FLASHW_STOP
, 0, 0 };
2670 ::FlashWindowEx(&flashInfo
);
2674 /**************************************************************
2676 * SECTION: nsIWidget::HasPendingInputEvent
2678 * Ask whether there user input events pending. All input events are
2679 * included, including those not targeted at this nsIwidget instance.
2681 **************************************************************/
2684 nsWindow::HasPendingInputEvent()
2686 // If there is pending input or the user is currently
2687 // moving the window then return true.
2688 // Note: When the user is moving the window WIN32 spins
2689 // a separate event loop and input events are not
2690 // reported to the application.
2691 if (HIWORD(GetQueueStatus(QS_INPUT
)))
2696 GUITHREADINFO guiInfo
;
2697 guiInfo
.cbSize
= sizeof(GUITHREADINFO
);
2698 if (!GetGUIThreadInfo(GetCurrentThreadId(), &guiInfo
))
2700 return GUI_INMOVESIZE
== (guiInfo
.flags
& GUI_INMOVESIZE
);
2704 /**************************************************************
2706 * SECTION: nsIWidget::GetThebesSurface
2708 * Get the Thebes surface associated with this widget.
2710 **************************************************************/
2712 gfxASurface
*nsWindow::GetThebesSurface()
2715 return (new gfxWindowsSurface(mPaintDC
));
2717 return (new gfxWindowsSurface(mWnd
));
2720 /**************************************************************
2722 * SECTION: nsIWidget::OnDefaultButtonLoaded
2724 * Called after the dialog is loaded and it has a default button.
2726 **************************************************************/
2729 nsWindow::OnDefaultButtonLoaded(const nsIntRect
&aButtonRect
)
2732 return NS_ERROR_NOT_IMPLEMENTED
;
2734 if (aButtonRect
.IsEmpty())
2737 // Don't snap when we are not active.
2738 HWND activeWnd
= ::GetActiveWindow();
2739 if (activeWnd
!= ::GetForegroundWindow() ||
2740 GetTopLevelHWND(mWnd
, PR_TRUE
) != GetTopLevelHWND(activeWnd
, PR_TRUE
)) {
2744 PRBool isAlwaysSnapCursor
= PR_FALSE
;
2745 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
2747 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
2748 prefs
->GetBranch(nsnull
, getter_AddRefs(prefBranch
));
2750 prefBranch
->GetBoolPref("ui.cursor_snapping.always_enabled",
2751 &isAlwaysSnapCursor
);
2755 if (!isAlwaysSnapCursor
) {
2756 BOOL snapDefaultButton
;
2757 if (!::SystemParametersInfo(SPI_GETSNAPTODEFBUTTON
, 0,
2758 &snapDefaultButton
, 0) || !snapDefaultButton
)
2762 nsIntRect widgetRect
;
2763 nsresult rv
= GetScreenBounds(widgetRect
);
2764 NS_ENSURE_SUCCESS(rv
, rv
);
2765 nsIntRect
buttonRect(aButtonRect
+ widgetRect
.TopLeft());
2767 nsIntPoint
centerOfButton(buttonRect
.x
+ buttonRect
.width
/ 2,
2768 buttonRect
.y
+ buttonRect
.height
/ 2);
2769 // The center of the button can be outside of the widget.
2770 // E.g., it could be hidden by scrolling.
2771 if (!widgetRect
.Contains(centerOfButton
)) {
2775 if (!::SetCursorPos(centerOfButton
.x
, centerOfButton
.y
)) {
2776 NS_ERROR("SetCursorPos failed");
2777 return NS_ERROR_FAILURE
;
2784 nsWindow::OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta
,
2785 PRBool aIsHorizontal
,
2786 PRInt32
&aOverriddenDelta
)
2788 // The default vertical and horizontal scrolling speed is 3, this is defined
2789 // on the document of SystemParametersInfo in MSDN.
2790 const PRInt32 kSystemDefaultScrollingSpeed
= 3;
2792 // Compute the simple overridden speed.
2793 PRInt32 computedOverriddenDelta
;
2795 nsBaseWidget::OverrideSystemMouseScrollSpeed(aOriginalDelta
, aIsHorizontal
,
2796 computedOverriddenDelta
);
2797 NS_ENSURE_SUCCESS(rv
, rv
);
2799 aOverriddenDelta
= aOriginalDelta
;
2801 if (computedOverriddenDelta
== aOriginalDelta
) {
2802 // We don't override now.
2806 // Otherwise, we should check whether the user customized the system settings
2807 // or not. If the user did it, we should respect the will.
2809 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, &systemSpeed
, 0)) {
2810 return NS_ERROR_FAILURE
;
2812 // The default vertical scrolling speed is 3, this is defined on the document
2813 // of SystemParametersInfo in MSDN.
2814 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
2818 // Only Vista and later, Windows has the system setting of horizontal
2819 // scrolling by the mouse wheel.
2820 if (GetWindowsVersion() >= VISTA_VERSION
) {
2821 if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0, &systemSpeed
, 0)) {
2822 return NS_ERROR_FAILURE
;
2824 // The default horizontal scrolling speed is 3, this is defined on the
2825 // document of SystemParametersInfo in MSDN.
2826 if (systemSpeed
!= kSystemDefaultScrollingSpeed
) {
2831 // Limit the overridden delta value from the system settings. The mouse
2832 // driver might accelerate the scrolling speed already. If so, we shouldn't
2833 // override the scrolling speed for preventing the unexpected high speed
2837 nsBaseWidget::OverrideSystemMouseScrollSpeed(kSystemDefaultScrollingSpeed
,
2838 aIsHorizontal
, deltaLimit
);
2839 NS_ENSURE_SUCCESS(rv
, rv
);
2841 aOverriddenDelta
= PR_MIN(computedOverriddenDelta
, deltaLimit
);
2846 /**************************************************************
2847 **************************************************************
2849 ** BLOCK: Moz Events
2851 ** Moz GUI event management.
2853 **************************************************************
2854 **************************************************************/
2856 /**************************************************************
2858 * SECTION: Mozilla event initialization
2860 * Helpers for initializing moz events.
2862 **************************************************************/
2864 // Event intialization
2865 MSG
nsWindow::InitMSG(UINT aMessage
, WPARAM wParam
, LPARAM lParam
)
2868 msg
.message
= aMessage
;
2869 msg
.wParam
= wParam
;
2870 msg
.lParam
= lParam
;
2874 void nsWindow::InitEvent(nsGUIEvent
& event
, nsIntPoint
* aPoint
)
2876 if (nsnull
== aPoint
) { // use the point from the event
2877 // get the message position in client coordinates
2880 DWORD pos
= ::GetMessagePos();
2883 cpos
.x
= GET_X_LPARAM(pos
);
2884 cpos
.y
= GET_Y_LPARAM(pos
);
2886 ::ScreenToClient(mWnd
, &cpos
);
2887 event
.refPoint
.x
= cpos
.x
;
2888 event
.refPoint
.y
= cpos
.y
;
2890 event
.refPoint
.x
= 0;
2891 event
.refPoint
.y
= 0;
2895 // use the point override if provided
2896 event
.refPoint
.x
= aPoint
->x
;
2897 event
.refPoint
.y
= aPoint
->y
;
2901 event
.time
= ::GetMessageTime();
2903 event
.time
= PR_Now() / 1000;
2906 mLastPoint
= event
.refPoint
;
2909 /**************************************************************
2911 * SECTION: Moz event dispatch helpers
2913 * Helpers for dispatching different types of moz events.
2915 **************************************************************/
2917 // Main event dispatch. Invokes callback and ProcessEvent method on
2918 // Event Listener object. Part of nsIWidget.
2919 NS_IMETHODIMP
nsWindow::DispatchEvent(nsGUIEvent
* event
, nsEventStatus
& aStatus
)
2921 #ifdef WIDGET_DEBUG_OUTPUT
2922 debug_DumpEvent(stdout
,
2925 nsCAutoString("something"),
2927 #endif // WIDGET_DEBUG_OUTPUT
2929 aStatus
= nsEventStatus_eIgnore
;
2931 // skip processing of suppressed blur events
2932 if (event
->message
== NS_DEACTIVATE
&& BlurEventsSuppressed())
2935 if (nsnull
!= mEventCallback
) {
2936 aStatus
= (*mEventCallback
)(event
);
2939 // the window can be destroyed during processing of seemingly innocuous events like, say,
2940 // mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
2941 // which causes problems with the deleted window. therefore:
2942 if (mOnDestroyCalled
)
2943 aStatus
= nsEventStatus_eConsumeNoDefault
;
2947 PRBool
nsWindow::DispatchStandardEvent(PRUint32 aMsg
)
2949 nsGUIEvent
event(PR_TRUE
, aMsg
, this);
2952 PRBool result
= DispatchWindowEvent(&event
);
2956 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
)
2958 nsEventStatus status
;
2959 DispatchEvent(event
, status
);
2960 return ConvertStatus(status
);
2963 PRBool
nsWindow::DispatchWindowEvent(nsGUIEvent
* event
, nsEventStatus
&aStatus
) {
2964 DispatchEvent(event
, aStatus
);
2965 return ConvertStatus(aStatus
);
2968 PRBool
nsWindow::DispatchKeyEvent(PRUint32 aEventType
, WORD aCharCode
,
2969 const nsTArray
<nsAlternativeCharCode
>* aAlternativeCharCodes
,
2970 UINT aVirtualCharCode
, const MSG
*aMsg
,
2971 const nsModifierKeyState
&aModKeyState
,
2974 nsKeyEvent
event(PR_TRUE
, aEventType
, this);
2975 nsIntPoint
point(0, 0);
2977 InitEvent(event
, &point
); // this add ref's event.widget
2979 event
.flags
|= aFlags
;
2980 event
.charCode
= aCharCode
;
2981 if (aAlternativeCharCodes
)
2982 event
.alternativeCharCodes
.AppendElements(*aAlternativeCharCodes
);
2983 event
.keyCode
= aVirtualCharCode
;
2987 printf("%d DispatchKE Type: %s charCode %d keyCode %d ", cnt
++,
2988 (NS_KEY_PRESS
== aEventType
) ? "PRESS" : (aEventType
== NS_KEY_UP
? "Up" : "Down"),
2989 event
.charCode
, event
.keyCode
);
2990 printf("Shift: %s Control %s Alt: %s \n",
2991 (mIsShiftDown
? "D" : "U"), (mIsControlDown
? "D" : "U"), (mIsAltDown
? "D" : "U"));
2992 printf("[%c][%c][%c] <== [%c][%c][%c][ space bar ][%c][%c][%c]\n",
2993 IS_VK_DOWN(NS_VK_SHIFT
) ? 'S' : ' ',
2994 IS_VK_DOWN(NS_VK_CONTROL
) ? 'C' : ' ',
2995 IS_VK_DOWN(NS_VK_ALT
) ? 'A' : ' ',
2996 IS_VK_DOWN(VK_LSHIFT
) ? 'S' : ' ',
2997 IS_VK_DOWN(VK_LCONTROL
) ? 'C' : ' ',
2998 IS_VK_DOWN(VK_LMENU
) ? 'A' : ' ',
2999 IS_VK_DOWN(VK_RMENU
) ? 'A' : ' ',
3000 IS_VK_DOWN(VK_RCONTROL
) ? 'C' : ' ',
3001 IS_VK_DOWN(VK_RSHIFT
) ? 'S' : ' ');
3004 event
.isShift
= aModKeyState
.mIsShiftDown
;
3005 event
.isControl
= aModKeyState
.mIsControlDown
;
3006 event
.isMeta
= PR_FALSE
;
3007 event
.isAlt
= aModKeyState
.mIsAltDown
;
3009 NPEvent pluginEvent
;
3010 if (aMsg
&& PluginHasFocus()) {
3011 pluginEvent
.event
= aMsg
->message
;
3012 pluginEvent
.wParam
= aMsg
->wParam
;
3013 pluginEvent
.lParam
= aMsg
->lParam
;
3014 event
.pluginEvent
= (void *)&pluginEvent
;
3017 PRBool result
= DispatchWindowEvent(&event
);
3022 PRBool
nsWindow::DispatchCommandEvent(PRUint32 aEventCommand
)
3024 nsCOMPtr
<nsIAtom
> command
;
3025 switch (aEventCommand
) {
3026 case APPCOMMAND_BROWSER_BACKWARD
:
3027 command
= nsWidgetAtoms::Back
;
3029 case APPCOMMAND_BROWSER_FORWARD
:
3030 command
= nsWidgetAtoms::Forward
;
3032 case APPCOMMAND_BROWSER_REFRESH
:
3033 command
= nsWidgetAtoms::Reload
;
3035 case APPCOMMAND_BROWSER_STOP
:
3036 command
= nsWidgetAtoms::Stop
;
3038 case APPCOMMAND_BROWSER_SEARCH
:
3039 command
= nsWidgetAtoms::Search
;
3041 case APPCOMMAND_BROWSER_FAVORITES
:
3042 command
= nsWidgetAtoms::Bookmarks
;
3044 case APPCOMMAND_BROWSER_HOME
:
3045 command
= nsWidgetAtoms::Home
;
3050 nsCommandEvent
event(PR_TRUE
, nsWidgetAtoms::onAppCommand
, command
, this);
3053 DispatchWindowEvent(&event
);
3058 // Recursively dispatch synchronous paints for nsIWidget
3059 // descendants with invalidated rectangles.
3060 BOOL CALLBACK
nsWindow::DispatchStarvedPaints(HWND aWnd
, LPARAM aMsg
)
3062 LONG_PTR proc
= ::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
3063 if (proc
== (LONG_PTR
)&nsWindow::WindowProc
) {
3064 // its one of our windows so check to see if it has a
3065 // invalidated rect. If it does. Dispatch a synchronous
3067 if (GetUpdateRect(aWnd
, NULL
, FALSE
)) {
3068 VERIFY(::UpdateWindow(aWnd
));
3074 // Check for pending paints and dispatch any pending paint
3075 // messages for any nsIWidget which is a descendant of the
3076 // top-level window that *this* window is embedded within.
3078 // Note: We do not dispatch pending paint messages for non
3079 // nsIWidget managed windows.
3080 void nsWindow::DispatchPendingEvents()
3082 UpdateLastInputEventTime();
3084 // We need to ensure that reflow events do not get starved.
3085 // At the same time, we don't want to recurse through here
3086 // as that would prevent us from dispatching starved paints.
3087 static int recursionBlocker
= 0;
3088 if (recursionBlocker
++ == 0) {
3089 NS_ProcessPendingEvents(nsnull
, PR_MillisecondsToInterval(100));
3093 // Quickly check to see if there are any
3094 // paint events pending.
3095 if (::GetQueueStatus(QS_PAINT
)) {
3096 // Find the top level window.
3097 HWND topWnd
= GetTopLevelHWND(mWnd
);
3099 // Dispatch pending paints for all topWnd's descendant windows.
3100 // Note: EnumChildWindows enumerates all descendant windows not just
3103 ::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, NULL
);
3105 nsWindowCE::EnumChildWindows(topWnd
, nsWindow::DispatchStarvedPaints
, NULL
);
3110 // Deal with plugin events
3111 PRBool
nsWindow::DispatchPluginEvent(const MSG
&aMsg
)
3113 if (!PluginHasFocus())
3116 nsGUIEvent
event(PR_TRUE
, NS_PLUGIN_EVENT
, this);
3117 nsIntPoint
point(0, 0);
3118 InitEvent(event
, &point
);
3119 NPEvent pluginEvent
;
3120 pluginEvent
.event
= aMsg
.message
;
3121 pluginEvent
.wParam
= aMsg
.wParam
;
3122 pluginEvent
.lParam
= aMsg
.lParam
;
3123 event
.pluginEvent
= (void *)&pluginEvent
;
3124 return DispatchWindowEvent(&event
);
3127 void nsWindow::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg
,
3131 ::GetMessageW(&msg
, mWnd
, aFirstMsg
, aLastMsg
);
3132 DispatchPluginEvent(msg
);
3135 // Deal with all sort of mouse event
3136 PRBool
nsWindow::DispatchMouseEvent(PRUint32 aEventType
, WPARAM wParam
,
3137 LPARAM lParam
, PRBool aIsContextMenuKey
,
3140 PRBool result
= PR_FALSE
;
3142 if (!mEventCallback
) {
3146 nsIntPoint eventPoint
;
3147 eventPoint
.x
= GET_X_LPARAM(lParam
);
3148 eventPoint
.y
= GET_Y_LPARAM(lParam
);
3150 nsMouseEvent
event(PR_TRUE
, aEventType
, this, nsMouseEvent::eReal
,
3152 ? nsMouseEvent::eContextMenuKey
3153 : nsMouseEvent::eNormal
);
3154 if (aEventType
== NS_CONTEXTMENU
&& aIsContextMenuKey
) {
3155 nsIntPoint
zero(0, 0);
3156 InitEvent(event
, &zero
);
3158 InitEvent(event
, &eventPoint
);
3161 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
3162 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
3163 event
.isMeta
= PR_FALSE
;
3164 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
3165 event
.button
= aButton
;
3167 nsIntPoint mpScreen
= eventPoint
+ WidgetToScreenOffset();
3169 // Suppress mouse moves caused by widget creation
3170 if (aEventType
== NS_MOUSE_MOVE
)
3172 if ((sLastMouseMovePoint
.x
== mpScreen
.x
) && (sLastMouseMovePoint
.y
== mpScreen
.y
))
3174 sLastMouseMovePoint
.x
= mpScreen
.x
;
3175 sLastMouseMovePoint
.y
= mpScreen
.y
;
3178 PRBool insideMovementThreshold
= (abs(sLastMousePoint
.x
- eventPoint
.x
) < (short)::GetSystemMetrics(SM_CXDOUBLECLK
)) &&
3179 (abs(sLastMousePoint
.y
- eventPoint
.y
) < (short)::GetSystemMetrics(SM_CYDOUBLECLK
));
3183 case nsMouseEvent::eLeftButton
:
3184 eventButton
= VK_LBUTTON
;
3186 case nsMouseEvent::eMiddleButton
:
3187 eventButton
= VK_MBUTTON
;
3189 case nsMouseEvent::eRightButton
:
3190 eventButton
= VK_RBUTTON
;
3197 // Doubleclicks are used to set the click count, then changed to mousedowns
3198 // We're going to time double-clicks from mouse *up* to next mouse *down*
3200 LONG curMsgTime
= ::GetMessageTime();
3202 LONG curMsgTime
= PR_Now() / 1000;
3205 if (aEventType
== NS_MOUSE_DOUBLECLICK
) {
3206 event
.message
= NS_MOUSE_BUTTON_DOWN
;
3207 event
.button
= aButton
;
3208 sLastClickCount
= 2;
3210 else if (aEventType
== NS_MOUSE_BUTTON_UP
) {
3211 // remember when this happened for the next mouse down
3212 sLastMousePoint
.x
= eventPoint
.x
;
3213 sLastMousePoint
.y
= eventPoint
.y
;
3214 sLastMouseButton
= eventButton
;
3216 else if (aEventType
== NS_MOUSE_BUTTON_DOWN
) {
3217 // now look to see if we want to convert this to a double- or triple-click
3218 if (((curMsgTime
- sLastMouseDownTime
) < (LONG
)::GetDoubleClickTime()) && insideMovementThreshold
&&
3219 eventButton
== sLastMouseButton
) {
3222 // reset the click count, to count *this* click
3223 sLastClickCount
= 1;
3225 // Set last Click time on MouseDown only
3226 sLastMouseDownTime
= curMsgTime
;
3228 else if (aEventType
== NS_MOUSE_MOVE
&& !insideMovementThreshold
) {
3229 sLastClickCount
= 0;
3231 else if (aEventType
== NS_MOUSE_EXIT
) {
3232 event
.exit
= IsTopLevelMouseExit(mWnd
) ? nsMouseEvent::eTopLevel
: nsMouseEvent::eChild
;
3234 event
.clickCount
= sLastClickCount
;
3237 printf("Msg Time: %d Click Count: %d\n", curMsgTime
, event
.clickCount
);
3240 NPEvent pluginEvent
;
3244 case NS_MOUSE_BUTTON_DOWN
:
3246 case nsMouseEvent::eLeftButton
:
3247 pluginEvent
.event
= WM_LBUTTONDOWN
;
3249 case nsMouseEvent::eMiddleButton
:
3250 pluginEvent
.event
= WM_MBUTTONDOWN
;
3252 case nsMouseEvent::eRightButton
:
3253 pluginEvent
.event
= WM_RBUTTONDOWN
;
3259 case NS_MOUSE_BUTTON_UP
:
3261 case nsMouseEvent::eLeftButton
:
3262 pluginEvent
.event
= WM_LBUTTONUP
;
3264 case nsMouseEvent::eMiddleButton
:
3265 pluginEvent
.event
= WM_MBUTTONUP
;
3267 case nsMouseEvent::eRightButton
:
3268 pluginEvent
.event
= WM_RBUTTONUP
;
3274 case NS_MOUSE_DOUBLECLICK
:
3276 case nsMouseEvent::eLeftButton
:
3277 pluginEvent
.event
= WM_LBUTTONDBLCLK
;
3279 case nsMouseEvent::eMiddleButton
:
3280 pluginEvent
.event
= WM_MBUTTONDBLCLK
;
3282 case nsMouseEvent::eRightButton
:
3283 pluginEvent
.event
= WM_RBUTTONDBLCLK
;
3290 pluginEvent
.event
= WM_MOUSEMOVE
;
3293 pluginEvent
.event
= WM_NULL
;
3297 pluginEvent
.wParam
= wParam
; // plugins NEED raw OS event flags!
3298 pluginEvent
.lParam
= lParam
;
3300 event
.pluginEvent
= (void *)&pluginEvent
;
3302 // call the event callback
3303 if (nsnull
!= mEventCallback
) {
3304 if (nsToolkit::gMouseTrailer
)
3305 nsToolkit::gMouseTrailer
->Disable();
3306 if (aEventType
== NS_MOUSE_MOVE
) {
3307 if (nsToolkit::gMouseTrailer
&& !mIsInMouseCapture
) {
3308 nsToolkit::gMouseTrailer
->SetMouseTrailerWindow(mWnd
);
3315 if (rect
.Contains(event
.refPoint
)) {
3316 if (sCurrentWindow
== NULL
|| sCurrentWindow
!= this) {
3317 if ((nsnull
!= sCurrentWindow
) && (!sCurrentWindow
->mInDtor
)) {
3318 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
3319 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_EXIT
, wParam
, pos
);
3321 sCurrentWindow
= this;
3323 LPARAM pos
= sCurrentWindow
->lParamToClient(lParamToScreen(lParam
));
3324 sCurrentWindow
->DispatchMouseEvent(NS_MOUSE_ENTER
, wParam
, pos
);
3328 } else if (aEventType
== NS_MOUSE_EXIT
) {
3329 if (sCurrentWindow
== this) {
3330 sCurrentWindow
= nsnull
;
3334 result
= DispatchWindowEvent(&event
);
3336 if (nsToolkit::gMouseTrailer
)
3337 nsToolkit::gMouseTrailer
->Enable();
3339 // Release the widget with NS_IF_RELEASE() just in case
3340 // the context menu key code in nsEventListenerManager::HandleEvent()
3341 // released it already.
3348 // Deal with accessibile event
3349 #ifdef ACCESSIBILITY
3350 PRBool
nsWindow::DispatchAccessibleEvent(PRUint32 aEventType
, nsIAccessible
** aAcc
, nsIntPoint
* aPoint
)
3352 PRBool result
= PR_FALSE
;
3354 if (nsnull
== mEventCallback
) {
3360 nsAccessibleEvent
event(PR_TRUE
, aEventType
, this);
3361 InitEvent(event
, aPoint
);
3363 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
3364 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
3365 event
.isMeta
= PR_FALSE
;
3366 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
3367 event
.accessible
= nsnull
;
3369 result
= DispatchWindowEvent(&event
);
3371 // if the event returned an accesssible get it.
3372 if (event
.accessible
)
3373 *aAcc
= event
.accessible
;
3379 PRBool
nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType
)
3381 if (aEventType
== NS_ACTIVATE
)
3382 sJustGotActivate
= PR_FALSE
;
3383 sJustGotDeactivate
= PR_FALSE
;
3385 // clear the flags, and retrieve the toplevel window. This way, it doesn't
3386 // mattter what child widget received the focus event and it will always be
3387 // fired at the toplevel window.
3388 HWND toplevelWnd
= GetTopLevelHWND(mWnd
);
3390 nsWindow
*win
= GetNSWindowPtr(toplevelWnd
);
3392 return win
->DispatchFocus(aEventType
);
3398 // Deal with focus messages
3399 PRBool
nsWindow::DispatchFocus(PRUint32 aEventType
)
3401 // call the event callback
3402 if (mEventCallback
) {
3403 nsGUIEvent
event(PR_TRUE
, aEventType
, this);
3406 //focus and blur event should go to their base widget loc, not current mouse pos
3407 event
.refPoint
.x
= 0;
3408 event
.refPoint
.y
= 0;
3410 NPEvent pluginEvent
;
3415 pluginEvent
.event
= WM_SETFOCUS
;
3418 pluginEvent
.event
= WM_KILLFOCUS
;
3420 case NS_PLUGIN_ACTIVATE
:
3421 pluginEvent
.event
= WM_KILLFOCUS
;
3427 event
.pluginEvent
= (void *)&pluginEvent
;
3429 return DispatchWindowEvent(&event
);
3434 PRBool
nsWindow::IsTopLevelMouseExit(HWND aWnd
)
3436 DWORD pos
= ::GetMessagePos();
3438 mp
.x
= GET_X_LPARAM(pos
);
3439 mp
.y
= GET_Y_LPARAM(pos
);
3440 HWND mouseWnd
= ::WindowFromPoint(mp
);
3442 // GetTopLevelHWND will return a HWND for the window frame (which includes
3443 // the non-client area). If the mouse has moved into the non-client area,
3444 // we should treat it as a top-level exit.
3445 HWND mouseTopLevel
= nsWindow::GetTopLevelHWND(mouseWnd
);
3446 if (mouseWnd
== mouseTopLevel
)
3449 return nsWindow::GetTopLevelHWND(aWnd
) != mouseTopLevel
;
3452 PRBool
nsWindow::BlurEventsSuppressed()
3454 // are they suppressed in this window?
3455 if (mBlurSuppressLevel
> 0)
3458 // are they suppressed by any container widget?
3459 HWND parentWnd
= ::GetParent(mWnd
);
3461 nsWindow
*parent
= GetNSWindowPtr(parentWnd
);
3463 return parent
->BlurEventsSuppressed();
3468 // In some circumstances (opening dependent windows) it makes more sense
3469 // (and fixes a crash bug) to not blur the parent window. Called from
3471 void nsWindow::SuppressBlurEvents(PRBool aSuppress
)
3474 ++mBlurSuppressLevel
; // for this widget
3476 NS_ASSERTION(mBlurSuppressLevel
> 0, "unbalanced blur event suppression");
3477 if (mBlurSuppressLevel
> 0)
3478 --mBlurSuppressLevel
;
3482 PRBool
nsWindow::ConvertStatus(nsEventStatus aStatus
)
3484 return aStatus
== nsEventStatus_eConsumeNoDefault
;
3487 /**************************************************************
3488 **************************************************************
3490 ** BLOCK: Native events
3492 ** Main Windows message handlers and OnXXX handlers for
3493 ** Windows event handling.
3495 **************************************************************
3496 **************************************************************/
3498 /**************************************************************
3500 * SECTION: Wind proc.
3502 * The main Windows event procedures and associated
3503 * message processing methods.
3505 **************************************************************/
3507 // The WndProc procedure for all nsWindows in this toolkit
3508 LRESULT CALLBACK
nsWindow::WindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
3510 // create this here so that we store the last rolled up popup until after
3511 // the event has been processed.
3512 nsAutoRollup autoRollup
;
3514 LRESULT popupHandlingResult
;
3515 if ( DealWithPopups(hWnd
, msg
, wParam
, lParam
, &popupHandlingResult
) )
3516 return popupHandlingResult
;
3518 // Get the window which caused the event and ask it to process the message
3519 nsWindow
*someWindow
= GetNSWindowPtr(hWnd
);
3521 // XXX This fixes 50208 and we are leaving 51174 open to further investigate
3522 // why we are hitting this assert
3523 if (nsnull
== someWindow
) {
3524 NS_ASSERTION(someWindow
, "someWindow is null, cannot call any CallWindowProc");
3525 return ::DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
3528 // hold on to the window for the life of this method, in case it gets
3529 // deleted during processing. yes, it's a double hack, since someWindow
3530 // is not really an interface.
3531 nsCOMPtr
<nsISupports
> kungFuDeathGrip
;
3532 if (!someWindow
->mInDtor
) // not if we're in the destructor!
3533 kungFuDeathGrip
= do_QueryInterface((nsBaseWidget
*)someWindow
);
3535 // Re-direct a tab change message destined for its parent window to the
3536 // the actual window which generated the event.
3537 if (msg
== WM_NOTIFY
) {
3538 LPNMHDR pnmh
= (LPNMHDR
) lParam
;
3539 if (pnmh
->code
== TCN_SELCHANGE
) {
3540 someWindow
= GetNSWindowPtr(pnmh
->hwndFrom
);
3544 // Call ProcessMessage
3545 if (nsnull
!= someWindow
) {
3547 if (PR_TRUE
== someWindow
->ProcessMessage(msg
, wParam
, lParam
, &retValue
)) {
3552 return ::CallWindowProcW(someWindow
->GetPrevWindowProc(),
3553 hWnd
, msg
, wParam
, lParam
);
3556 // The main windows message processing method for plugins.
3557 // The result means whether this method processed the native
3558 // event for plugin. If false, the native event should be
3559 // processed by the caller self.
3561 nsWindow::ProcessMessageForPlugin(const MSG
&aMsg
,
3563 PRBool
&aCallDefWndProc
)
3565 NS_PRECONDITION(aResult
, "aResult must be non-null.");
3568 aCallDefWndProc
= PR_FALSE
;
3569 PRBool fallBackToNonPluginProcess
= PR_FALSE
;
3570 PRBool eventDispatched
= PR_FALSE
;
3571 PRBool dispatchPendingEvents
= PR_TRUE
;
3572 switch (aMsg
.message
) {
3573 case WM_INPUTLANGCHANGEREQUEST
:
3574 case WM_INPUTLANGCHANGE
:
3575 DispatchPluginEvent(aMsg
);
3576 return PR_FALSE
; // go to non-plug-ins processing
3580 *aResult
= ProcessCharMessage(aMsg
, &eventDispatched
);
3585 *aResult
= ProcessKeyUpMessage(aMsg
, &eventDispatched
);
3590 *aResult
= ProcessKeyDownMessage(aMsg
, &eventDispatched
);
3594 case WM_SYSDEADCHAR
:
3595 case WM_CONTEXTMENU
:
3603 case WM_IME_STARTCOMPOSITION
:
3604 case WM_IME_COMPOSITION
:
3605 case WM_IME_ENDCOMPOSITION
:
3607 case WM_IME_COMPOSITIONFULL
:
3608 case WM_IME_CONTROL
:
3609 case WM_IME_KEYDOWN
:
3612 case WM_IME_REQUEST
:
3616 case WM_IME_SETCONTEXT
:
3617 // Don't synchronously dispatch when we receive WM_IME_SETCONTEXT
3618 // because we get it during plugin destruction. (bug 491848)
3619 dispatchPendingEvents
= PR_FALSE
;
3626 if (!eventDispatched
)
3627 aCallDefWndProc
= !DispatchPluginEvent(aMsg
);
3628 if (dispatchPendingEvents
)
3629 DispatchPendingEvents();
3633 // The main windows message processing method.
3634 PRBool
nsWindow::ProcessMessage(UINT msg
, WPARAM
&wParam
, LPARAM
&lParam
,
3637 // (Large blocks of code should be broken out into OnEvent handlers.)
3638 if (mWindowHook
.Notify(mWnd
, msg
, wParam
, lParam
, aRetValue
))
3642 if (nsIMM32Handler::ProcessMessage(this, msg
, wParam
, lParam
, aRetValue
,
3644 return mWnd
? eatMessage
: PR_TRUE
;
3647 if (PluginHasFocus()) {
3648 PRBool callDefaultWndProc
;
3649 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
3650 if (ProcessMessageForPlugin(nativeMsg
, aRetValue
, callDefaultWndProc
)) {
3651 return mWnd
? !callDefaultWndProc
: PR_TRUE
;
3655 static UINT vkKeyCached
= 0; // caches VK code fon WM_KEYDOWN
3656 PRBool result
= PR_FALSE
; // call the default nsWindow proc
3659 static PRBool getWheelInfo
= PR_TRUE
;
3661 #if defined(EVENT_DEBUG_OUTPUT)
3662 // First param shows all events, second param indicates whether
3663 // to show mouse move events. See nsWindowDbg for details.
3664 PrintEvent(msg
, SHOW_REPEAT_EVENTS
, SHOW_MOUSEMOVE_EVENTS
);
3670 WORD wNotifyCode
= HIWORD(wParam
); // notification code
3671 if ((CBN_SELENDOK
== wNotifyCode
) || (CBN_SELENDCANCEL
== wNotifyCode
)) { // Combo box change
3672 nsGUIEvent
event(PR_TRUE
, NS_CONTROL_CHANGE
, this);
3673 nsIntPoint
point(0,0);
3674 InitEvent(event
, &point
); // this add ref's event.widget
3675 result
= DispatchWindowEvent(&event
);
3676 } else if (wNotifyCode
== 0) { // Menu selection
3677 nsMenuEvent
event(PR_TRUE
, NS_MENU_SELECTED
, this);
3678 event
.mCommand
= LOWORD(wParam
);
3680 result
= DispatchWindowEvent(&event
);
3686 // WM_QUERYENDSESSION must be handled by all windows.
3687 // Otherwise Windows thinks the window can just be killed at will.
3688 case WM_QUERYENDSESSION
:
3689 if (sCanQuit
== TRI_UNKNOWN
)
3691 // Ask if it's ok to quit, and store the answer until we
3692 // get WM_ENDSESSION signaling the round is complete.
3693 nsCOMPtr
<nsIObserverService
> obsServ
=
3694 do_GetService("@mozilla.org/observer-service;1");
3695 nsCOMPtr
<nsISupportsPRBool
> cancelQuit
=
3696 do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID
);
3697 cancelQuit
->SetData(PR_FALSE
);
3698 obsServ
->NotifyObservers(cancelQuit
, "quit-application-requested", nsnull
);
3701 cancelQuit
->GetData(&abortQuit
);
3702 sCanQuit
= abortQuit
? TRI_FALSE
: TRI_TRUE
;
3704 *aRetValue
= sCanQuit
? TRUE
: FALSE
;
3712 case MOZ_WM_APP_QUIT
:
3713 if (msg
== MOZ_WM_APP_QUIT
|| (wParam
== TRUE
&& sCanQuit
== TRI_TRUE
))
3715 // Let's fake a shutdown sequence without actually closing windows etc.
3716 // to avoid Windows killing us in the middle. A proper shutdown would
3717 // require having a chance to pump some messages. Unfortunately
3718 // Windows won't let us do that. Bug 212316.
3719 nsCOMPtr
<nsIObserverService
> obsServ
=
3720 do_GetService("@mozilla.org/observer-service;1");
3721 NS_NAMED_LITERAL_STRING(context
, "shutdown-persist");
3722 obsServ
->NotifyObservers(nsnull
, "quit-application-granted", nsnull
);
3723 obsServ
->NotifyObservers(nsnull
, "quit-application-forced", nsnull
);
3724 obsServ
->NotifyObservers(nsnull
, "quit-application", nsnull
);
3725 obsServ
->NotifyObservers(nsnull
, "profile-change-net-teardown", context
.get());
3726 obsServ
->NotifyObservers(nsnull
, "profile-change-teardown", context
.get());
3727 obsServ
->NotifyObservers(nsnull
, "profile-before-change", context
.get());
3728 // Then a controlled but very quick exit.
3731 sCanQuit
= TRI_UNKNOWN
;
3736 case WM_DISPLAYCHANGE
:
3737 DispatchStandardEvent(NS_DISPLAYCHANGED
);
3741 case WM_SYSCOLORCHANGE
:
3742 // Note: This is sent for child windows as well as top-level windows.
3743 // The Win32 toolkit normally only sends these events to top-level windows.
3744 // But we cycle through all of the childwindows and send it to them as well
3745 // so all presentations get notified properly.
3746 // See nsWindow::GlobalMsgWindowProc.
3747 DispatchStandardEvent(NS_SYSCOLORCHANGED
);
3753 LPNMHDR pnmh
= (LPNMHDR
) lParam
;
3755 switch (pnmh
->code
) {
3758 DispatchStandardEvent(NS_TABCHANGE
);
3766 case WM_XP_THEMECHANGED
:
3768 DispatchStandardEvent(NS_THEMECHANGED
);
3770 // Invalidate the window so that the repaint will
3771 // pick up the new theme.
3772 Invalidate(PR_FALSE
);
3779 PRBool didChange
= PR_FALSE
;
3781 // update the global font list
3782 nsCOMPtr
<nsIFontEnumerator
> fontEnum
= do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv
);
3783 if (NS_SUCCEEDED(rv
)) {
3784 fontEnum
->UpdateFontList(&didChange
);
3785 //didChange is TRUE only if new font langGroup is added to the list.
3787 // update device context font cache
3788 // Dirty but easiest way:
3789 // Changing nsIPrefBranch entry which triggers callbacks
3790 // and flows into calling mDeviceContext->FlushFontCache()
3791 // to update the font cache in all the instance of Browsers
3792 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
3794 nsCOMPtr
<nsIPrefBranch
> fiPrefs
;
3795 prefs
->GetBranch("font.internaluseonly.", getter_AddRefs(fiPrefs
));
3797 PRBool fontInternalChange
= PR_FALSE
;
3798 fiPrefs
->GetBoolPref("changed", &fontInternalChange
);
3799 fiPrefs
->SetBoolPref("changed", !fontInternalChange
);
3803 } //if (NS_SUCCEEDED(rv))
3808 case WM_POWERBROADCAST
:
3809 // only hidden window handle this
3810 // to prevent duplicate notification
3811 if (mWindowType
== eWindowType_invisible
) {
3814 case PBT_APMSUSPEND
:
3815 PostSleepWakeNotification("sleep_notification");
3817 case PBT_APMRESUMEAUTOMATIC
:
3818 case PBT_APMRESUMECRITICAL
:
3819 case PBT_APMRESUMESUSPEND
:
3820 PostSleepWakeNotification("wake_notification");
3827 case WM_MOVE
: // Window moved
3829 PRInt32 x
= GET_X_LPARAM(lParam
); // horizontal position in screen coordinates
3830 PRInt32 y
= GET_Y_LPARAM(lParam
); // vertical position in screen coordinates
3831 result
= OnMove(x
, y
);
3835 case WM_CLOSE
: // close request
3836 DispatchStandardEvent(NS_XUL_CLOSE
);
3837 result
= PR_TRUE
; // abort window closure
3847 *aRetValue
= (int) OnPaint();
3852 case WM_PRINTCLIENT
:
3853 result
= OnPaint((HDC
) wParam
);
3858 result
= OnHotKey(wParam
, lParam
);
3864 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
3865 result
= ProcessCharMessage(nativeMsg
, nsnull
);
3866 DispatchPendingEvents();
3873 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
3874 result
= ProcessKeyUpMessage(nativeMsg
, nsnull
);
3875 DispatchPendingEvents();
3882 MSG nativeMsg
= InitMSG(msg
, wParam
, lParam
);
3883 result
= ProcessKeyDownMessage(nativeMsg
, nsnull
);
3884 DispatchPendingEvents();
3888 // say we've dealt with erase background if widget does
3889 // not need auto-erasing
3891 if (!AutoErase((HDC
)wParam
)) {
3898 *aRetValue
= DLGC_WANTALLKEYS
;
3904 #ifdef WINCE_WINDOWS_MOBILE
3905 // Reset the kill timer so that we can continue at this
3907 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2seconds */, NULL
);
3909 // Suppress dispatch of pending events
3910 // when mouse moves are generated by widget
3911 // creation instead of user input.
3912 LPARAM lParamScreen
= lParamToScreen(lParam
);
3914 mp
.x
= GET_X_LPARAM(lParamScreen
);
3915 mp
.y
= GET_Y_LPARAM(lParamScreen
);
3916 PRBool userMovedMouse
= PR_FALSE
;
3917 if ((sLastMouseMovePoint
.x
!= mp
.x
) || (sLastMouseMovePoint
.y
!= mp
.y
)) {
3918 userMovedMouse
= PR_TRUE
;
3921 result
= DispatchMouseEvent(NS_MOUSE_MOVE
, wParam
, lParam
);
3922 if (userMovedMouse
) {
3923 DispatchPendingEvents();
3928 #ifdef WINCE_WINDOWS_MOBILE
3930 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
3931 KillTimer(mWnd
, KILL_PRIORITY_ID
);
3935 case WM_LBUTTONDOWN
:
3937 #ifdef WINCE_WINDOWS_MOBILE
3938 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
3939 SetTimer(mWnd
, KILL_PRIORITY_ID
, 2000 /* 2 seconds */, NULL
);
3941 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
,
3942 PR_FALSE
, nsMouseEvent::eLeftButton
);
3943 DispatchPendingEvents();
3949 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
,
3950 PR_FALSE
, nsMouseEvent::eLeftButton
);
3951 DispatchPendingEvents();
3953 #ifdef WINCE_WINDOWS_MOBILE
3954 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL
);
3955 KillTimer(mWnd
, KILL_PRIORITY_ID
);
3963 // We need to check mouse button states and put them in for
3965 WPARAM mouseState
= (GetKeyState(VK_LBUTTON
) ? MK_LBUTTON
: 0)
3966 | (GetKeyState(VK_MBUTTON
) ? MK_MBUTTON
: 0)
3967 | (GetKeyState(VK_RBUTTON
) ? MK_RBUTTON
: 0);
3968 // Synthesize an event position because we don't get one from
3970 LPARAM pos
= lParamToClient(::GetMessagePos());
3971 DispatchMouseEvent(NS_MOUSE_EXIT
, mouseState
, pos
);
3976 case WM_CONTEXTMENU
:
3978 // if the context menu is brought up from the keyboard, |lParam|
3981 PRBool contextMenukey
= PR_FALSE
;
3982 if (lParam
== 0xFFFFFFFF)
3984 contextMenukey
= PR_TRUE
;
3985 pos
= lParamToClient(GetMessagePos());
3989 pos
= lParamToClient(lParam
);
3991 result
= DispatchMouseEvent(NS_CONTEXTMENU
, wParam
, pos
, contextMenukey
,
3993 nsMouseEvent::eLeftButton
:
3994 nsMouseEvent::eRightButton
);
3998 case WM_LBUTTONDBLCLK
:
3999 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
4000 nsMouseEvent::eLeftButton
);
4003 case WM_MBUTTONDOWN
:
4005 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4006 nsMouseEvent::eMiddleButton
);
4007 DispatchPendingEvents();
4012 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
4013 nsMouseEvent::eMiddleButton
);
4014 DispatchPendingEvents();
4017 case WM_MBUTTONDBLCLK
:
4018 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4019 nsMouseEvent::eMiddleButton
);
4022 case WM_RBUTTONDOWN
:
4024 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN
, wParam
, lParam
, PR_FALSE
,
4025 nsMouseEvent::eRightButton
);
4026 DispatchPendingEvents();
4031 result
= DispatchMouseEvent(NS_MOUSE_BUTTON_UP
, wParam
, lParam
, PR_FALSE
,
4032 nsMouseEvent::eRightButton
);
4033 DispatchPendingEvents();
4036 case WM_RBUTTONDBLCLK
:
4037 result
= DispatchMouseEvent(NS_MOUSE_DOUBLECLICK
, wParam
, lParam
, PR_FALSE
,
4038 nsMouseEvent::eRightButton
);
4043 PRUint32 appCommand
= GET_APPCOMMAND_LPARAM(lParam
);
4047 case APPCOMMAND_BROWSER_BACKWARD
:
4048 case APPCOMMAND_BROWSER_FORWARD
:
4049 case APPCOMMAND_BROWSER_REFRESH
:
4050 case APPCOMMAND_BROWSER_STOP
:
4051 case APPCOMMAND_BROWSER_SEARCH
:
4052 case APPCOMMAND_BROWSER_FAVORITES
:
4053 case APPCOMMAND_BROWSER_HOME
:
4054 DispatchCommandEvent(appCommand
);
4055 // tell the driver that we handled the event
4060 // default = PR_FALSE - tell the driver that the event was not handled
4066 // check for the incoming nsWindow handle to be null in which case
4067 // we assume the message is coming from a horizontal scrollbar inside
4068 // a listbox and we don't bother processing it (well, we don't have to)
4070 nsWindow
* scrollbar
= GetNSWindowPtr((HWND
)lParam
);
4073 result
= scrollbar
->OnScroll(msg
, wParam
, lParam
);
4078 case WM_CTLCOLORLISTBOX
:
4079 case WM_CTLCOLOREDIT
:
4080 case WM_CTLCOLORBTN
:
4081 //case WM_CTLCOLORSCROLLBAR: //XXX causes the scrollbar to be drawn incorrectly
4082 case WM_CTLCOLORSTATIC
:
4084 nsWindow
* control
= GetNSWindowPtr((HWND
)lParam
);
4086 control
->SetUpForPaint((HDC
)wParam
);
4087 *aRetValue
= (LPARAM
)control
->OnControlColor();
4094 // The WM_ACTIVATE event is fired when a window is raised or lowered,
4095 // and the loword of wParam specifies which. But we don't want to tell
4096 // the focus system about this until the WM_SETFOCUS or WM_KILLFOCUS
4097 // events are fired. Instead, set either the sJustGotActivate or
4098 // gJustGotDeativate flags and fire the NS_ACTIVATE or NS_DEACTIVATE
4099 // events once the focus events arrive.
4101 if (mEventCallback
) {
4102 PRInt32 fActive
= LOWORD(wParam
);
4104 #if defined(WINCE_HAVE_SOFTKB)
4105 if (mIsTopWidgetWindow
&& sSoftKeyboardState
)
4106 nsWindowCE::ToggleSoftKB(fActive
);
4107 if (nsWindowCE::sShowSIPButton
!= TRI_TRUE
&& WA_INACTIVE
!= fActive
) {
4108 HWND hWndSIPB
= FindWindowW(L
"MS_SIPBUTTON", NULL
);
4110 ShowWindow(hWndSIPB
, SW_HIDE
);
4115 if (WA_INACTIVE
== fActive
) {
4116 // when minimizing a window, the deactivation and focus events will
4117 // be fired in the reverse order. Instead, just dispatch
4118 // NS_DEACTIVATE right away.
4120 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
4122 sJustGotDeactivate
= PR_TRUE
;
4124 if (mIsTopWidgetWindow
)
4125 mLastKeyboardLayout
= gKbdLayout
.GetLayout();
4131 sJustGotActivate
= PR_TRUE
;
4132 nsMouseEvent
event(PR_TRUE
, NS_MOUSE_ACTIVATE
, this,
4133 nsMouseEvent::eReal
);
4136 event
.acceptActivation
= PR_TRUE
;
4138 PRBool result
= DispatchWindowEvent(&event
);
4140 if (event
.acceptActivation
)
4141 *aRetValue
= MA_ACTIVATE
;
4143 *aRetValue
= MA_NOACTIVATE
;
4145 if (sSwitchKeyboardLayout
&& mLastKeyboardLayout
)
4146 ActivateKeyboardLayout(mLastKeyboardLayout
, 0);
4150 if (mSizeMode
== nsSizeMode_Fullscreen
)
4151 MakeFullScreen(TRUE
);
4154 #ifdef WINCE_WINDOWS_MOBILE
4155 if (!gCheckForHTCApi
&& gHTCApiNavOpen
== nsnull
) {
4156 gCheckForHTCApi
= PR_TRUE
;
4158 HINSTANCE library
= LoadLibrary(L
"HTCAPI.dll");
4159 gHTCApiNavOpen
= (HTCApiNavOpen
) GetProcAddress(library
, "HTCNavOpen");
4160 gHTCApiNavSetMode
= (HTCApiNavSetMode
) GetProcAddress(library
,"HTCNavSetMode");
4163 if (gHTCApiNavOpen
!= nsnull
) {
4164 gHTCApiNavOpen(mWnd
, 1 /* undocumented value */);
4166 if (gHTCApiNavSetMode
!= nsnull
)
4167 gHTCApiNavSetMode ( mWnd
, 4);
4168 // 4 is Gesture Mode. This will generate WM_HTCNAV events to the window
4174 case WM_MOUSEACTIVATE
:
4175 if (mWindowType
== eWindowType_popup
) {
4176 // a popup with a parent owner should not be activated when clicked
4177 // but should still allow the mouse event to be fired, so the return
4178 // value is set to MA_NOACTIVATE. But if the owner isn't the frontmost
4179 // window, just use default processing so that the window is activated.
4180 HWND owner
= ::GetWindow(mWnd
, GW_OWNER
);
4181 if (owner
&& owner
== ::GetForegroundWindow()) {
4182 *aRetValue
= MA_NOACTIVATE
;
4188 case WM_WINDOWPOSCHANGING
:
4190 LPWINDOWPOS info
= (LPWINDOWPOS
) lParam
;
4191 OnWindowPosChanging(info
);
4197 if (sJustGotActivate
) {
4198 result
= DispatchFocusToTopLevelWindow(NS_ACTIVATE
);
4201 #ifdef ACCESSIBILITY
4202 if (nsWindow::sIsAccessibilityOn
) {
4203 // Create it for the first time so that it can start firing events
4204 nsCOMPtr
<nsIAccessible
> rootAccessible
= GetRootAccessible();
4208 #if defined(WINCE_HAVE_SOFTKB)
4210 // On Windows CE, we have a window that overlaps
4211 // the ISP button. In this case, we should always
4212 // try to hide it when we are activated
4214 nsIMEContext
IMEContext(mWnd
);
4216 ImmSetOpenStatus(IMEContext
.get(), TRUE
);
4222 #if defined(WINCE_HAVE_SOFTKB)
4224 nsIMEContext
IMEContext(mWnd
);
4225 ImmSetOpenStatus(IMEContext
.get(), FALSE
);
4228 if (sJustGotDeactivate
) {
4229 result
= DispatchFocusToTopLevelWindow(NS_DEACTIVATE
);
4233 case WM_WINDOWPOSCHANGED
:
4235 WINDOWPOS
*wp
= (LPWINDOWPOS
)lParam
;
4236 OnWindowPosChanged(wp
, result
);
4240 case WM_SETTINGCHANGE
:
4241 #if !defined (WINCE_WINDOWS_MOBILE)
4242 getWheelInfo
= PR_TRUE
;
4246 case SPI_SETSIPINFO
:
4247 case SPI_SETCURRENTIM
:
4248 nsWindowCE::NotifySoftKbObservers();
4250 case SETTINGCHANGE_RESET
:
4251 if (mWindowType
== eWindowType_invisible
) {
4252 // The OS sees to get confused and think that the invisable window
4253 // is in the foreground after an orientation change. By actually
4254 // setting it to the foreground and hiding it, we set it strait.
4255 // See bug 514007 for details.
4256 SetForegroundWindow(mWnd
);
4257 ShowWindow(mWnd
, SW_HIDE
);
4262 OnSettingsChange(wParam
, lParam
);
4266 case WM_INPUTLANGCHANGEREQUEST
:
4271 case WM_INPUTLANGCHANGE
:
4272 result
= OnInputLangChange((HKL
)lParam
);
4276 case WM_DESTROYCLIPBOARD
:
4278 nsIClipboard
* clipboard
;
4279 nsresult rv
= CallGetService(kCClipboardCID
, &clipboard
);
4280 clipboard
->EmptyClipboard(nsIClipboard::kGlobalClipboard
);
4281 NS_RELEASE(clipboard
);
4285 #ifdef ACCESSIBILITY
4289 if (lParam
== OBJID_CLIENT
) { // oleacc.dll will be loaded dynamically
4290 nsCOMPtr
<nsIAccessible
> rootAccessible
= GetRootAccessible(); // Held by a11y cache
4291 if (rootAccessible
) {
4292 IAccessible
*msaaAccessible
= NULL
;
4293 rootAccessible
->GetNativeInterface((void**)&msaaAccessible
); // does an addref
4294 if (msaaAccessible
) {
4295 *aRetValue
= LresultFromObject(IID_IAccessible
, wParam
, msaaAccessible
); // does an addref
4296 msaaAccessible
->Release(); // release extra addref
4297 result
= PR_TRUE
; // We handled the WM_GETOBJECT message
4306 // prevent Windows from trimming the working set. bug 76831
4307 if (!sTrimOnMinimize
&& wParam
== SC_MINIMIZE
) {
4308 ::ShowWindow(mWnd
, SW_SHOWMINIMIZED
);
4317 nsMemory::HeapMinimize(PR_TRUE
);
4322 case WM_MOUSEHWHEEL
:
4324 // If OnMouseWheel returns true, the event was forwarded directly to another
4325 // mozilla window message handler (ProcessMessage). In this case the return
4326 // value of the forwarded event is in 'result' which we should return immediately.
4327 // If OnMouseWheel returns false, OnMouseWheel processed the event internally.
4328 // 'result' and 'aRetValue' will be set based on what we did with the event, so
4329 // we should fall through.
4330 if (OnMouseWheel(msg
, wParam
, lParam
, getWheelInfo
, result
, aRetValue
))
4336 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
4337 case WM_DWMCOMPOSITIONCHANGED
:
4338 BroadcastMsg(mWnd
, WM_DWMCOMPOSITIONCHANGED
);
4339 DispatchStandardEvent(NS_THEMECHANGED
);
4340 if (nsUXThemeData::CheckForCompositor() && mTransparencyMode
== eTransparencyGlass
) {
4341 MARGINS margins
= { -1, -1, -1, -1 };
4342 nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(mWnd
, &margins
);
4344 Invalidate(PR_FALSE
);
4348 /* Gesture support events */
4349 case WM_TABLET_QUERYSYSTEMGESTURESTATUS
:
4350 // According to MS samples, this must be handled to enable
4351 // rotational support in multi-touch drivers.
4353 *aRetValue
= TABLET_ROTATE_GESTURE_ENABLE
;
4357 result
= OnGesture(wParam
, lParam
);
4360 case WM_GESTURENOTIFY
:
4362 if (mWindowType
!= eWindowType_invisible
&&
4363 mWindowType
!= eWindowType_plugin
&&
4364 mWindowType
!= eWindowType_toplevel
) {
4365 // eWindowType_toplevel is the top level main frame window. Gesture support
4366 // there prevents the user from interacting with the title bar or nc
4367 // areas using a single finger. Java and plugin windows can make their
4369 GESTURENOTIFYSTRUCT
* gestureinfo
= (GESTURENOTIFYSTRUCT
*)lParam
;
4370 nsPointWin touchPoint
;
4371 touchPoint
= gestureinfo
->ptsLocation
;
4372 touchPoint
.ScreenToClient(mWnd
);
4373 nsGestureNotifyEvent
gestureNotifyEvent(PR_TRUE
, NS_GESTURENOTIFY_EVENT_START
, this);
4374 gestureNotifyEvent
.refPoint
= touchPoint
;
4375 nsEventStatus status
;
4376 DispatchEvent(&gestureNotifyEvent
, status
);
4377 mDisplayPanFeedback
= gestureNotifyEvent
.displayPanFeedback
;
4378 mGesture
.SetWinGestureSupport(mWnd
, gestureNotifyEvent
.panDirection
);
4380 result
= PR_FALSE
; //should always bubble to DefWindowProc
4383 #endif // !defined(WINCE)
4387 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_DELETE
, this);
4388 DispatchWindowEvent(&command
);
4395 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_CUT
, this);
4396 DispatchWindowEvent(&command
);
4403 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_COPY
, this);
4404 DispatchWindowEvent(&command
);
4411 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
, this);
4412 DispatchWindowEvent(&command
);
4420 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
, this);
4421 DispatchWindowEvent(&command
);
4422 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
4429 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
, this);
4430 DispatchWindowEvent(&command
);
4431 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
4438 // Support EM_CANPASTE message only when wParam isn't specified or
4439 // is plain text format.
4440 if (wParam
== 0 || wParam
== CF_TEXT
|| wParam
== CF_UNICODETEXT
) {
4441 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_PASTE
,
4443 DispatchWindowEvent(&command
);
4444 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
4452 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_UNDO
,
4454 DispatchWindowEvent(&command
);
4455 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
4462 nsContentCommandEvent
command(PR_TRUE
, NS_CONTENT_COMMAND_REDO
,
4464 DispatchWindowEvent(&command
);
4465 *aRetValue
= (LRESULT
)(command
.mSucceeded
&& command
.mIsEnabled
);
4471 #ifdef WINCE_WINDOWS_MOBILE
4472 //HTC NAVIGATION WHEEL EVENT
4475 int distance
= wParam
& 0x000000FF;
4476 if ( (wParam
& 0x000000100) != 0) // Counter Clockwise
4478 if (OnMouseWheel(WM_MOUSEWHEEL
, MAKEWPARAM(0, distance
),
4479 MAKELPARAM(GetSystemMetrics(SM_CXSCREEN
) / 2,
4480 GetSystemMetrics(SM_CYSCREEN
) / 2),
4481 getWheelInfo
, result
, aRetValue
))
4489 #ifdef NS_ENABLE_TSF
4490 if (msg
== WM_USER_TSF_TEXTCHANGE
) {
4491 nsTextStore::OnTextChangeMsg();
4493 #endif //NS_ENABLE_TSF
4494 #if defined(HEAP_DUMP_EVENT)
4495 if (msg
== GetHeapMsg()) {
4496 HeapDump(msg
, wParam
, lParam
);
4500 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
4501 if (msg
== nsAppShell::GetTaskbarButtonCreatedMessage())
4502 SetHasTaskbarIconBeenCreated();
4508 //*aRetValue = result;
4513 //Events which caused mWnd destruction and aren't consumed
4514 //will crash during the Windows default processing.
4519 /**************************************************************
4521 * SECTION: Broadcast messaging
4523 * Broadcast messages to all windows.
4525 **************************************************************/
4527 // Enumerate all child windows sending aMsg to each of them
4528 BOOL CALLBACK
nsWindow::BroadcastMsgToChildren(HWND aWnd
, LPARAM aMsg
)
4530 WNDPROC winProc
= (WNDPROC
)::GetWindowLongPtrW(aWnd
, GWLP_WNDPROC
);
4531 if (winProc
== &nsWindow::WindowProc
) {
4532 // it's one of our windows so go ahead and send a message to it
4533 ::CallWindowProcW(winProc
, aWnd
, aMsg
, 0, 0);
4538 // Enumerate all top level windows specifying that the children of each
4539 // top level window should be enumerated. Do *not* send the message to
4540 // each top level window since it is assumed that the toolkit will send
4541 // aMsg to them directly.
4542 BOOL CALLBACK
nsWindow::BroadcastMsg(HWND aTopWindow
, LPARAM aMsg
)
4544 // Iterate each of aTopWindows child windows sending the aMsg
4547 ::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
4549 nsWindowCE::EnumChildWindows(aTopWindow
, nsWindow::BroadcastMsgToChildren
, aMsg
);
4554 // This method is called from nsToolkit::WindowProc to forward global
4555 // messages which need to be dispatched to all child windows.
4556 void nsWindow::GlobalMsgWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
4559 case WM_SYSCOLORCHANGE
:
4560 // Code to dispatch WM_SYSCOLORCHANGE message to all child windows.
4561 // WM_SYSCOLORCHANGE is only sent to top-level windows, but the
4562 // cross platform API requires that NS_SYSCOLORCHANGE message be sent to
4563 // all child windows as well. When running in an embedded application
4564 // we may not receive a WM_SYSCOLORCHANGE message because the top
4565 // level window is owned by the embeddor.
4566 // System color changes are posted to top-level windows only.
4567 // The NS_SYSCOLORCHANGE must be dispatched to all child
4570 ::EnumThreadWindows(GetCurrentThreadId(), nsWindow::BroadcastMsg
, msg
);
4576 /**************************************************************
4578 * SECTION: Event processing helpers
4580 * Special processing for certain event types and
4581 * synthesized events.
4583 **************************************************************/
4586 void nsWindow::PostSleepWakeNotification(const char* aNotification
)
4588 nsCOMPtr
<nsIObserverService
> observerService
= do_GetService("@mozilla.org/observer-service;1");
4589 if (observerService
)
4591 observerService
->NotifyObservers(nsnull
, aNotification
, nsnull
);
4596 LRESULT
nsWindow::ProcessCharMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
4598 NS_PRECONDITION(aMsg
.message
== WM_CHAR
|| aMsg
.message
== WM_SYSCHAR
,
4599 "message is not keydown event");
4600 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
4601 ("%s charCode=%d scanCode=%d\n",
4602 aMsg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
4603 aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF));
4605 // These must be checked here too as a lone WM_CHAR could be received
4606 // if a child window didn't handle it (for example Alt+Space in a content window)
4607 nsModifierKeyState modKeyState
;
4608 return OnChar(aMsg
, modKeyState
, aEventDispatched
);
4611 LRESULT
nsWindow::ProcessKeyUpMessage(const MSG
&aMsg
, PRBool
*aEventDispatched
)
4613 NS_PRECONDITION(aMsg
.message
== WM_KEYUP
|| aMsg
.message
== WM_SYSKEYUP
,
4614 "message is not keydown event");
4615 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
4616 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
4617 "WM_SYSKEYUP" : "WM_KEYUP", aMsg
.wParam
));
4619 nsModifierKeyState modKeyState
;
4621 // Note: the original code passed (HIWORD(lParam)) to OnKeyUp as
4622 // scan code. However, this breaks Alt+Num pad input.
4623 // MSDN states the following:
4624 // Typically, ToAscii performs the translation based on the
4625 // virtual-key code. In some cases, however, bit 15 of the
4626 // uScanCode parameter may be used to distinguish between a key
4627 // press and a key release. The scan code is used for
4628 // translating ALT+number key combinations.
4630 // ignore [shift+]alt+space so the OS can handle it
4631 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
4632 IS_VK_DOWN(NS_VK_SPACE
)) {
4636 if (!nsIMM32Handler::IsComposing(this) &&
4637 (aMsg
.message
!= WM_KEYUP
|| aMsg
.message
!= VK_MENU
)) {
4638 // Ignore VK_MENU if it's not a system key release, so that the menu bar does not trigger
4639 // This helps avoid triggering the menu bar for ALT key accelerators used in
4640 // assistive technologies such as Window-Eyes and ZoomText, and when using Alt+Tab
4641 // to switch back to Mozilla in Windows 95 and Windows 98
4642 return OnKeyUp(aMsg
, modKeyState
, aEventDispatched
);
4648 LRESULT
nsWindow::ProcessKeyDownMessage(const MSG
&aMsg
,
4649 PRBool
*aEventDispatched
)
4651 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
4652 ("%s VK=%d\n", aMsg
.message
== WM_SYSKEYDOWN
?
4653 "WM_SYSKEYDOWN" : "WM_KEYDOWN", aMsg
.wParam
));
4654 NS_PRECONDITION(aMsg
.message
== WM_KEYDOWN
|| aMsg
.message
== WM_SYSKEYDOWN
,
4655 "message is not keydown event");
4657 nsModifierKeyState modKeyState
;
4659 // Note: the original code passed (HIWORD(lParam)) to OnKeyDown as
4660 // scan code. However, this breaks Alt+Num pad input.
4661 // MSDN states the following:
4662 // Typically, ToAscii performs the translation based on the
4663 // virtual-key code. In some cases, however, bit 15 of the
4664 // uScanCode parameter may be used to distinguish between a key
4665 // press and a key release. The scan code is used for
4666 // translating ALT+number key combinations.
4668 // ignore [shift+]alt+space so the OS can handle it
4669 if (modKeyState
.mIsAltDown
&& !modKeyState
.mIsControlDown
&&
4670 IS_VK_DOWN(NS_VK_SPACE
))
4674 if (modKeyState
.mIsAltDown
&& nsIMM32Handler::IsStatusChanged()) {
4675 nsIMM32Handler::NotifyEndStatusChange();
4676 } else if (!nsIMM32Handler::IsComposing(this)) {
4677 result
= OnKeyDown(aMsg
, modKeyState
, aEventDispatched
, nsnull
);
4681 if (aMsg
.wParam
== VK_MENU
||
4682 (aMsg
.wParam
== VK_F10
&& !modKeyState
.mIsShiftDown
)) {
4683 // We need to let Windows handle this keypress,
4684 // by returning PR_FALSE, if there's a native menu
4685 // bar somewhere in our containing window hierarchy.
4686 // Otherwise we handle the keypress and don't pass
4687 // it on to Windows, by returning PR_TRUE.
4688 PRBool hasNativeMenu
= PR_FALSE
;
4691 if (::GetMenu(hWnd
)) {
4692 hasNativeMenu
= PR_TRUE
;
4695 hWnd
= ::GetParent(hWnd
);
4697 result
= !hasNativeMenu
;
4705 nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout
,
4706 PRInt32 aNativeKeyCode
,
4707 PRUint32 aModifierFlags
,
4708 const nsAString
& aCharacters
,
4709 const nsAString
& aUnmodifiedCharacters
)
4711 #ifndef WINCE //Win CE doesn't support many of the calls used in this method, perhaps theres another way
4712 nsPrintfCString
layoutName("%08x", aNativeKeyboardLayout
);
4713 HKL loadedLayout
= LoadKeyboardLayoutA(layoutName
.get(), KLF_NOTELLSHELL
);
4714 if (loadedLayout
== NULL
)
4715 return NS_ERROR_NOT_AVAILABLE
;
4717 // Setup clean key state and load desired layout
4718 BYTE originalKbdState
[256];
4719 ::GetKeyboardState(originalKbdState
);
4721 memset(kbdState
, 0, sizeof(kbdState
));
4722 // This changes the state of the keyboard for the current thread only,
4723 // and we'll restore it soon, so this should be OK.
4724 ::SetKeyboardState(kbdState
);
4725 HKL oldLayout
= gKbdLayout
.GetLayout();
4726 gKbdLayout
.LoadLayout(loadedLayout
);
4728 nsAutoTArray
<KeyPair
,10> keySequence
;
4729 SetupKeyModifiersSequence(&keySequence
, aModifierFlags
);
4730 NS_ASSERTION(aNativeKeyCode
>= 0 && aNativeKeyCode
< 256,
4731 "Native VK key code out of range");
4732 keySequence
.AppendElement(KeyPair(aNativeKeyCode
, 0));
4734 // Simulate the pressing of each modifier key and then the real key
4735 for (PRUint32 i
= 0; i
< keySequence
.Length(); ++i
) {
4736 PRUint8 key
= keySequence
[i
].mGeneral
;
4737 PRUint8 keySpecific
= keySequence
[i
].mSpecific
;
4738 kbdState
[key
] = 0x81; // key is down and toggled on if appropriate
4740 kbdState
[keySpecific
] = 0x81;
4742 ::SetKeyboardState(kbdState
);
4743 nsModifierKeyState modKeyState
;
4744 MSG msg
= InitMSG(WM_KEYDOWN
, key
, 0);
4745 if (i
== keySequence
.Length() - 1 && aCharacters
.Length() > 0) {
4746 UINT scanCode
= ::MapVirtualKeyEx(aNativeKeyCode
, MAPVK_VK_TO_VSC
,
4747 gKbdLayout
.GetLayout());
4748 nsFakeCharMessage fakeMsg
= { aCharacters
.CharAt(0), scanCode
};
4749 OnKeyDown(msg
, modKeyState
, nsnull
, &fakeMsg
);
4751 OnKeyDown(msg
, modKeyState
, nsnull
, nsnull
);
4754 for (PRUint32 i
= keySequence
.Length(); i
> 0; --i
) {
4755 PRUint8 key
= keySequence
[i
- 1].mGeneral
;
4756 PRUint8 keySpecific
= keySequence
[i
- 1].mSpecific
;
4757 kbdState
[key
] = 0; // key is up and toggled off if appropriate
4759 kbdState
[keySpecific
] = 0;
4761 ::SetKeyboardState(kbdState
);
4762 nsModifierKeyState modKeyState
;
4763 MSG msg
= InitMSG(WM_KEYUP
, key
, 0);
4764 OnKeyUp(msg
, modKeyState
, nsnull
);
4767 // Restore old key state and layout
4768 ::SetKeyboardState(originalKbdState
);
4769 gKbdLayout
.LoadLayout(oldLayout
);
4771 UnloadKeyboardLayout(loadedLayout
);
4773 #else //XXX: is there another way to do this?
4774 return NS_ERROR_NOT_IMPLEMENTED
;
4779 nsWindow::SynthesizeNativeMouseEvent(nsIntPoint aPoint
,
4780 PRUint32 aNativeMessage
,
4781 PRUint32 aModifierFlags
)
4783 #ifndef WINCE // I don't think WINCE supports SendInput
4785 ::GetWindowRect(mWnd
, &r
);
4786 ::SetCursorPos(r
.left
+ aPoint
.x
, r
.top
+ aPoint
.y
);
4789 memset(&input
, 0, sizeof(input
));
4791 input
.type
= INPUT_MOUSE
;
4792 input
.mi
.dwFlags
= aNativeMessage
;
4793 ::SendInput(1, &input
, sizeof(INPUT
));
4797 return NS_ERROR_NOT_IMPLEMENTED
;
4801 /**************************************************************
4803 * SECTION: OnXXX message handlers
4805 * For message handlers that need to be broken out or
4806 * implemented in specific platform code.
4808 **************************************************************/
4810 BOOL
nsWindow::OnInputLangChange(HKL aHKL
)
4813 printf("OnInputLanguageChange\n");
4817 gKbdLayout
.LoadLayout(aHKL
);
4820 return PR_FALSE
; // always pass to child window
4823 #if !defined(WINCE) // implemented in nsWindowCE.cpp
4824 void nsWindow::OnWindowPosChanged(WINDOWPOS
*wp
, PRBool
& result
)
4829 #ifdef WINSTATE_DEBUG_OUTPUT
4830 if (mWnd
== GetTopLevelHWND(mWnd
))
4831 printf("*** OnWindowPosChanged: [ top] ");
4833 printf("*** OnWindowPosChanged: [child] ");
4834 printf("WINDOWPOS flags:");
4835 if (wp
->flags
& SWP_FRAMECHANGED
)
4836 printf("SWP_FRAMECHANGED ");
4837 if (wp
->flags
& SWP_SHOWWINDOW
)
4838 printf("SWP_SHOWWINDOW ");
4839 if (wp
->flags
& SWP_NOSIZE
)
4840 printf("SWP_NOSIZE ");
4841 if (wp
->flags
& SWP_HIDEWINDOW
)
4842 printf("SWP_HIDEWINDOW ");
4846 // Handle window size mode changes
4847 if (wp
->flags
& SWP_FRAMECHANGED
) {
4848 nsSizeModeEvent
event(PR_TRUE
, NS_SIZEMODE
, this);
4851 pl
.length
= sizeof(pl
);
4852 ::GetWindowPlacement(mWnd
, &pl
);
4854 if (pl
.showCmd
== SW_SHOWMAXIMIZED
)
4855 event
.mSizeMode
= nsSizeMode_Maximized
;
4856 else if (pl
.showCmd
== SW_SHOWMINIMIZED
)
4857 event
.mSizeMode
= nsSizeMode_Minimized
;
4859 event
.mSizeMode
= nsSizeMode_Normal
;
4861 // Windows has just changed the size mode of this window. The following
4862 // NS_SIZEMODE event will trigger a call into SetSizeMode where we will
4863 // set the min/max window state again or for nsSizeMode_Normal, call
4864 // SetWindow with a parameter of SW_RESTORE. There's no need however as
4865 // this window's mode has already changed. Updating mSizeMode here
4866 // insures the SetSizeMode call is a no-op. Addresses a bug on Win7 related
4867 // to window docking. (bug 489258)
4868 mSizeMode
= event
.mSizeMode
;
4870 // If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
4871 // SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
4872 // prevents the working set from being trimmed but keeps the window active.
4873 // After the window is minimized, we need to do some touch up work on the
4874 // active window. (bugs 76831 & 499816)
4875 if (!sTrimOnMinimize
&& nsSizeMode_Minimized
== event
.mSizeMode
)
4876 ActivateOtherWindowHelper(mWnd
);
4878 #ifdef WINSTATE_DEBUG_OUTPUT
4879 switch (mSizeMode
) {
4880 case nsSizeMode_Normal
:
4881 printf("*** mSizeMode: nsSizeMode_Normal\n");
4883 case nsSizeMode_Minimized
:
4884 printf("*** mSizeMode: nsSizeMode_Minimized\n");
4886 case nsSizeMode_Maximized
:
4887 printf("*** mSizeMode: nsSizeMode_Maximized\n");
4890 printf("*** mSizeMode: ??????\n");
4897 result
= DispatchWindowEvent(&event
);
4899 // Skip window size change events below on minimization.
4900 if (mSizeMode
== nsSizeMode_Minimized
)
4904 // Handle window size changes
4905 if (0 == (wp
->flags
& SWP_NOSIZE
)) {
4907 PRInt32 newWidth
, newHeight
;
4909 ::GetWindowRect(mWnd
, &r
);
4911 newWidth
= r
.right
- r
.left
;
4912 newHeight
= r
.bottom
- r
.top
;
4913 nsIntRect
rect(wp
->x
, wp
->y
, newWidth
, newHeight
);
4916 if (eTransparencyTransparent
== mTransparencyMode
)
4917 ResizeTranslucentWindow(newWidth
, newHeight
);
4920 if (newWidth
> mLastSize
.width
)
4925 drect
.left
= wp
->x
+ mLastSize
.width
;
4927 drect
.right
= drect
.left
+ (newWidth
- mLastSize
.width
);
4928 drect
.bottom
= drect
.top
+ newHeight
;
4930 ::RedrawWindow(mWnd
, &drect
, NULL
,
4933 RDW_NOINTERNALPAINT
|
4937 if (newHeight
> mLastSize
.height
)
4943 drect
.top
= wp
->y
+ mLastSize
.height
;
4944 drect
.right
= drect
.left
+ newWidth
;
4945 drect
.bottom
= drect
.top
+ (newHeight
- mLastSize
.height
);
4947 ::RedrawWindow(mWnd
, &drect
, NULL
,
4950 RDW_NOINTERNALPAINT
|
4955 mBounds
.width
= newWidth
;
4956 mBounds
.height
= newHeight
;
4957 mLastSize
.width
= newWidth
;
4958 mLastSize
.height
= newHeight
;
4960 #ifdef WINSTATE_DEBUG_OUTPUT
4961 printf("*** Resize window: %d x %d x %d x %d\n", wp
->x
, wp
->y
, newWidth
, newHeight
);
4964 // Recalculate the width and height based on the client area for gecko events.
4965 if (::GetClientRect(mWnd
, &r
)) {
4966 rect
.width
= r
.right
- r
.left
;
4967 rect
.height
= r
.bottom
- r
.top
;
4970 // Send a gecko resize event
4971 result
= OnResize(rect
);
4976 void nsWindow::ActivateOtherWindowHelper(HWND aWnd
)
4978 // Find the next window that is enabled, visible, and not minimized.
4979 HWND hwndBelow
= ::GetNextWindow(aWnd
, GW_HWNDNEXT
);
4980 while (hwndBelow
&& (!::IsWindowEnabled(hwndBelow
) || !::IsWindowVisible(hwndBelow
) ||
4981 ::IsIconic(hwndBelow
))) {
4982 hwndBelow
= ::GetNextWindow(hwndBelow
, GW_HWNDNEXT
);
4985 // Push ourselves to the bottom of the stack, then activate the
4987 ::SetWindowPos(aWnd
, HWND_BOTTOM
, 0, 0, 0, 0,
4988 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
);
4990 ::SetForegroundWindow(hwndBelow
);
4992 // Play the minimize sound while we're here, since that is also
4993 // forgotten when we use SW_SHOWMINIMIZED.
4994 ::PlaySoundW(L
"Minimize", nsnull
, SND_ALIAS
| SND_NODEFAULT
| SND_ASYNC
);
4996 #endif // !defined(WINCE)
4999 void nsWindow::OnWindowPosChanging(LPWINDOWPOS
& info
)
5001 // enforce local z-order rules
5002 if (!(info
->flags
& SWP_NOZORDER
)) {
5003 HWND hwndAfter
= info
->hwndInsertAfter
;
5005 nsZLevelEvent
event(PR_TRUE
, NS_SETZLEVEL
, this);
5006 nsWindow
*aboveWindow
= 0;
5010 if (hwndAfter
== HWND_BOTTOM
)
5011 event
.mPlacement
= nsWindowZBottom
;
5012 else if (hwndAfter
== HWND_TOP
|| hwndAfter
== HWND_TOPMOST
|| hwndAfter
== HWND_NOTOPMOST
)
5013 event
.mPlacement
= nsWindowZTop
;
5015 event
.mPlacement
= nsWindowZRelative
;
5016 aboveWindow
= GetNSWindowPtr(hwndAfter
);
5018 event
.mReqBelow
= aboveWindow
;
5019 event
.mActualBelow
= nsnull
;
5021 event
.mImmediate
= PR_FALSE
;
5022 event
.mAdjusted
= PR_FALSE
;
5023 DispatchWindowEvent(&event
);
5025 if (event
.mAdjusted
) {
5026 if (event
.mPlacement
== nsWindowZBottom
)
5027 info
->hwndInsertAfter
= HWND_BOTTOM
;
5028 else if (event
.mPlacement
== nsWindowZTop
)
5029 info
->hwndInsertAfter
= HWND_TOP
;
5031 info
->hwndInsertAfter
= (HWND
)event
.mActualBelow
->GetNativeData(NS_NATIVE_WINDOW
);
5034 NS_IF_RELEASE(event
.mActualBelow
);
5036 // prevent rude external programs from making hidden window visible
5037 if (mWindowType
== eWindowType_invisible
)
5038 info
->flags
&= ~SWP_SHOWWINDOW
;
5042 // Gesture event processing. Handles WM_GESTURE events.
5044 PRBool
nsWindow::OnGesture(WPARAM wParam
, LPARAM lParam
)
5046 // Treatment for pan events which translate into scroll events:
5047 if (mGesture
.IsPanEvent(lParam
)) {
5048 nsMouseScrollEvent
event(PR_TRUE
, NS_MOUSE_PIXEL_SCROLL
, this);
5050 if ( !mGesture
.ProcessPanMessage(mWnd
, wParam
, lParam
) )
5051 return PR_FALSE
; // ignore
5053 nsEventStatus status
;
5055 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
5056 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
5057 event
.isMeta
= PR_FALSE
;
5058 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
5060 event
.time
= ::GetMessageTime();
5062 PRBool endFeedback
= PR_TRUE
;
5064 PRInt32 scrollOverflowX
= 0;
5065 PRInt32 scrollOverflowY
= 0;
5067 if (mGesture
.PanDeltaToPixelScrollX(event
)) {
5068 DispatchEvent(&event
, status
);
5069 scrollOverflowX
= event
.scrollOverflow
;
5072 if (mGesture
.PanDeltaToPixelScrollY(event
)) {
5073 DispatchEvent(&event
, status
);
5074 scrollOverflowY
= event
.scrollOverflow
;
5077 if (mDisplayPanFeedback
) {
5078 mGesture
.UpdatePanFeedbackX(mWnd
, scrollOverflowX
, endFeedback
);
5079 mGesture
.UpdatePanFeedbackY(mWnd
, scrollOverflowY
, endFeedback
);
5080 mGesture
.PanFeedbackFinalize(mWnd
, endFeedback
);
5083 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
5088 // Other gestures translate into simple gesture events:
5089 nsSimpleGestureEvent
event(PR_TRUE
, 0, this, 0, 0.0);
5090 if ( !mGesture
.ProcessGestureMessage(mWnd
, wParam
, lParam
, event
) ) {
5091 return PR_FALSE
; // fall through to DefWndProc
5094 // Polish up and send off the new event
5095 event
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
5096 event
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
5097 event
.isMeta
= PR_FALSE
;
5098 event
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
5100 event
.time
= ::GetMessageTime();
5102 nsEventStatus status
;
5103 DispatchEvent(&event
, status
);
5104 if (status
== nsEventStatus_eIgnore
) {
5105 return PR_FALSE
; // Ignored, fall through
5108 // Only close this if we process and return true.
5109 mGesture
.CloseGestureInfoHandle((HGESTUREINFO
)lParam
);
5111 return PR_TRUE
; // Handled
5113 #endif // !defined(WINCE)
5116 * OnMouseWheel - mouse wheele event processing. This was originally embedded
5117 * within the message case block. If returning true result should be returned
5118 * immediately (no more processing).
5120 PRBool
nsWindow::OnMouseWheel(UINT msg
, WPARAM wParam
, LPARAM lParam
, PRBool
& getWheelInfo
, PRBool
& result
, LRESULT
*aRetValue
)
5122 // Handle both flavors of mouse wheel events.
5123 static int iDeltaPerLine
, iDeltaPerChar
;
5124 static ULONG ulScrollLines
, ulScrollChars
= 1;
5125 static int currentVDelta
, currentHDelta
;
5126 static HWND currentWindow
= 0;
5128 PRBool isVertical
= msg
== WM_MOUSEWHEEL
;
5130 // Get mouse wheel metrics (but only once).
5132 getWheelInfo
= PR_FALSE
;
5134 SystemParametersInfo (SPI_GETWHEELSCROLLLINES
, 0, &ulScrollLines
, 0);
5136 // ulScrollLines usually equals 3 or 0 (for no scrolling)
5137 // WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
5139 // However, if ulScrollLines > WHEEL_DELTA, we assume that
5140 // the mouse driver wants a page scroll. The docs state that
5141 // ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
5142 // since some mouse drivers use an arbitrary large number instead,
5143 // we have to handle that as well.
5146 if (ulScrollLines
) {
5147 if (ulScrollLines
<= WHEEL_DELTA
) {
5148 iDeltaPerLine
= WHEEL_DELTA
/ ulScrollLines
;
5150 ulScrollLines
= WHEEL_PAGESCROLL
;
5154 if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS
, 0,
5155 &ulScrollChars
, 0)) {
5156 // Note that we may always fail to get the value before Win Vista.
5161 if (ulScrollChars
) {
5162 if (ulScrollChars
<= WHEEL_DELTA
) {
5163 iDeltaPerChar
= WHEEL_DELTA
/ ulScrollChars
;
5165 ulScrollChars
= WHEEL_PAGESCROLL
;
5170 if ((isVertical
&& ulScrollLines
!= WHEEL_PAGESCROLL
&& !iDeltaPerLine
) ||
5171 (!isVertical
&& ulScrollChars
!= WHEEL_PAGESCROLL
&& !iDeltaPerChar
))
5172 return PR_FALSE
; // break
5174 // The mousewheel event will be dispatched to the toplevel
5175 // window. We need to give it to the child window
5176 if (!HandleScrollingPlugins(msg
, wParam
, lParam
, result
))
5177 return result
; // return immediately if its not our window
5179 // We should cancel the surplus delta if the current window is not
5180 // same as previous.
5181 if (currentWindow
!= mWnd
) {
5184 currentWindow
= mWnd
;
5187 nsMouseScrollEvent
scrollEvent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
5188 scrollEvent
.delta
= 0;
5190 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsVertical
;
5191 if (ulScrollLines
== WHEEL_PAGESCROLL
) {
5192 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
5193 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? -1 : 1;
5195 currentVDelta
-= (short) HIWORD (wParam
);
5196 if (PR_ABS(currentVDelta
) >= iDeltaPerLine
) {
5197 scrollEvent
.delta
= currentVDelta
/ iDeltaPerLine
;
5198 currentVDelta
%= iDeltaPerLine
;
5202 scrollEvent
.scrollFlags
= nsMouseScrollEvent::kIsHorizontal
;
5203 if (ulScrollChars
== WHEEL_PAGESCROLL
) {
5204 scrollEvent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
5205 scrollEvent
.delta
= (((short) HIWORD (wParam
)) > 0) ? 1 : -1;
5207 currentHDelta
+= (short) HIWORD (wParam
);
5208 if (PR_ABS(currentHDelta
) >= iDeltaPerChar
) {
5209 scrollEvent
.delta
= currentHDelta
/ iDeltaPerChar
;
5210 currentHDelta
%= iDeltaPerChar
;
5215 if (!scrollEvent
.delta
)
5216 return PR_FALSE
; // break
5218 scrollEvent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
5219 scrollEvent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
5220 scrollEvent
.isMeta
= PR_FALSE
;
5221 scrollEvent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
5222 InitEvent(scrollEvent
);
5223 if (nsnull
!= mEventCallback
) {
5224 result
= DispatchWindowEvent(&scrollEvent
);
5226 // Note that we should return zero if we process WM_MOUSEWHEEL.
5227 // But if we process WM_MOUSEHWHEEL, we should return non-zero.
5230 *aRetValue
= isVertical
? 0 : TRUE
;
5232 return PR_FALSE
; // break;
5236 StringCaseInsensitiveEquals(const PRUnichar
* aChars1
, const PRUint32 aNumChars1
,
5237 const PRUnichar
* aChars2
, const PRUint32 aNumChars2
)
5239 if (aNumChars1
!= aNumChars2
)
5242 nsCaseInsensitiveStringComparator comp
;
5243 return comp(aChars1
, aChars2
, aNumChars1
) == 0;
5246 UINT
nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode
)
5249 switch (aNativeKeyCode
) {
5250 case VK_OEM_1
: return NS_VK_SEMICOLON
; // 0xBA, For the US standard keyboard, the ';:' key
5251 case VK_OEM_PLUS
: return NS_VK_ADD
; // 0xBB, For any country/region, the '+' key
5252 case VK_OEM_MINUS
: return NS_VK_SUBTRACT
; // 0xBD, For any country/region, the '-' key
5256 return aNativeKeyCode
;
5260 * nsWindow::OnKeyDown peeks into the message queue and pulls out
5261 * WM_CHAR messages for processing. During testing we don't want to
5262 * mess with the real message queue. Instead we pass a
5263 * pseudo-WM_CHAR-message using this structure, and OnKeyDown will use
5264 * that as if it was in the message queue, and refrain from actually
5265 * looking at or touching the message queue.
5267 LRESULT
nsWindow::OnKeyDown(const MSG
&aMsg
,
5268 nsModifierKeyState
&aModKeyState
,
5269 PRBool
*aEventDispatched
,
5270 nsFakeCharMessage
* aFakeCharMessage
)
5272 UINT virtualKeyCode
= aMsg
.wParam
;
5275 gKbdLayout
.OnKeyDown (virtualKeyCode
);
5278 // Use only DOMKeyCode for XP processing.
5279 // Use aVirtualKeyCode for gKbdLayout and native processing.
5280 UINT DOMKeyCode
= nsIMM32Handler::IsComposing(this) ?
5281 virtualKeyCode
: MapFromNativeToDOM(virtualKeyCode
);
5284 //printf("In OnKeyDown virt: %d\n", DOMKeyCode);
5288 DispatchKeyEvent(NS_KEY_DOWN
, 0, nsnull
, DOMKeyCode
, &aMsg
, aModKeyState
);
5289 if (aEventDispatched
)
5290 *aEventDispatched
= PR_TRUE
;
5292 // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
5293 // for almost all keys
5294 switch (DOMKeyCode
) {
5298 case NS_VK_CAPS_LOCK
:
5299 case NS_VK_NUM_LOCK
:
5300 case NS_VK_SCROLL_LOCK
: return noDefault
;
5303 PRUint32 extraFlags
= (noDefault
? NS_EVENT_FLAG_NO_DEFAULT
: 0);
5305 BOOL gotMsg
= aFakeCharMessage
||
5306 ::PeekMessageW(&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
5307 // Enter and backspace are always handled here to avoid for example the
5308 // confusion between ctrl-enter and ctrl-J.
5309 if (DOMKeyCode
== NS_VK_RETURN
|| DOMKeyCode
== NS_VK_BACK
||
5310 ((aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)
5314 && !gKbdLayout
.IsDeadKey() && KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)))
5317 // Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
5318 // They can be more than one because of:
5319 // * Dead-keys not pairing with base character
5320 // * Some keyboard layouts may map up to 4 characters to the single key
5321 PRBool anyCharMessagesRemoved
= PR_FALSE
;
5323 if (aFakeCharMessage
) {
5324 anyCharMessagesRemoved
= PR_TRUE
;
5326 while (gotMsg
&& (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
))
5328 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5329 ("%s charCode=%d scanCode=%d\n", msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
5330 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
5331 RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST
, WM_KEYLAST
);
5332 anyCharMessagesRemoved
= PR_TRUE
;
5334 gotMsg
= ::PeekMessageW (&msg
, mWnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_NOREMOVE
| PM_NOYIELD
);
5338 if (!anyCharMessagesRemoved
&& DOMKeyCode
== NS_VK_BACK
&&
5339 nsIMM32Handler::IsDoingKakuteiUndo(mWnd
)) {
5340 NS_ASSERTION(!aFakeCharMessage
,
5341 "We shouldn't be touching the real msg queue");
5342 RemoveMessageAndDispatchPluginEvent(WM_CHAR
, WM_CHAR
);
5346 (aFakeCharMessage
||
5347 msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
|| msg
.message
== WM_DEADCHAR
)) {
5348 if (aFakeCharMessage
)
5349 return OnCharRaw(aFakeCharMessage
->mCharCode
,
5350 aFakeCharMessage
->mScanCode
, aModKeyState
, extraFlags
);
5352 // If prevent default set for keydown, do same for keypress
5353 ::GetMessageW(&msg
, mWnd
, msg
.message
, msg
.message
);
5355 if (msg
.message
== WM_DEADCHAR
) {
5356 if (!PluginHasFocus())
5359 // We need to send the removed message to focused plug-in.
5360 DispatchPluginEvent(msg
);
5364 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5365 ("%s charCode=%d scanCode=%d\n",
5366 msg
.message
== WM_SYSCHAR
? "WM_SYSCHAR" : "WM_CHAR",
5367 msg
.wParam
, HIWORD(msg
.lParam
) & 0xFF));
5369 BOOL result
= OnChar(msg
, aModKeyState
, nsnull
, extraFlags
);
5370 // If a syschar keypress wasn't processed, Windows may want to
5371 // handle it to activate a native menu.
5372 if (!result
&& msg
.message
== WM_SYSCHAR
)
5373 ::DefWindowProcW(mWnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
5377 else if (!aModKeyState
.mIsControlDown
&& !aModKeyState
.mIsAltDown
&&
5378 (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
) ||
5379 KeyboardLayout::IsNumpadKey(virtualKeyCode
)))
5381 // If this is simple KeyDown event but next message is not WM_CHAR,
5382 // this event may not input text, so we should ignore this event.
5384 return PluginHasFocus() && noDefault
;
5387 if (gKbdLayout
.IsDeadKey ())
5388 return PluginHasFocus() && noDefault
;
5390 PRUint8 shiftStates
[5];
5391 PRUnichar uniChars
[5];
5392 PRUnichar shiftedChars
[5] = {0, 0, 0, 0, 0};
5393 PRUnichar unshiftedChars
[5] = {0, 0, 0, 0, 0};
5394 PRUnichar shiftedLatinChar
= 0;
5395 PRUnichar unshiftedLatinChar
= 0;
5396 PRUint32 numOfUniChars
= 0;
5397 PRUint32 numOfShiftedChars
= 0;
5398 PRUint32 numOfUnshiftedChars
= 0;
5399 PRUint32 numOfShiftStates
= 0;
5401 switch (virtualKeyCode
) {
5402 // keys to be sent as characters
5403 case VK_ADD
: uniChars
[0] = '+'; numOfUniChars
= 1; break;
5404 case VK_SUBTRACT
: uniChars
[0] = '-'; numOfUniChars
= 1; break;
5405 case VK_DIVIDE
: uniChars
[0] = '/'; numOfUniChars
= 1; break;
5406 case VK_MULTIPLY
: uniChars
[0] = '*'; numOfUniChars
= 1; break;
5417 uniChars
[0] = virtualKeyCode
- VK_NUMPAD0
+ '0';
5421 if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode
)) {
5422 numOfUniChars
= numOfShiftStates
=
5423 gKbdLayout
.GetUniChars(uniChars
, shiftStates
,
5424 NS_ARRAY_LENGTH(uniChars
));
5427 if (aModKeyState
.mIsControlDown
^ aModKeyState
.mIsAltDown
) {
5428 PRUint8 capsLockState
= (::GetKeyState(VK_CAPITAL
) & 1) ? eCapsLock
: 0;
5429 numOfUnshiftedChars
=
5430 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
, capsLockState
,
5431 unshiftedChars
, NS_ARRAY_LENGTH(unshiftedChars
));
5433 gKbdLayout
.GetUniCharsWithShiftState(virtualKeyCode
,
5434 capsLockState
| eShift
,
5435 shiftedChars
, NS_ARRAY_LENGTH(shiftedChars
));
5437 // The current keyboard cannot input alphabets or numerics,
5438 // we should append them for Shortcut/Access keys.
5439 // E.g., for Cyrillic keyboard layout.
5440 if (NS_VK_A
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_Z
) {
5441 shiftedLatinChar
= unshiftedLatinChar
= DOMKeyCode
;
5443 shiftedLatinChar
+= 0x20;
5445 unshiftedLatinChar
+= 0x20;
5446 if (unshiftedLatinChar
== unshiftedChars
[0] &&
5447 shiftedLatinChar
== shiftedChars
[0]) {
5448 shiftedLatinChar
= unshiftedLatinChar
= 0;
5452 if (NS_VK_0
<= DOMKeyCode
&& DOMKeyCode
<= NS_VK_9
) {
5455 switch (virtualKeyCode
) {
5456 case VK_OEM_PLUS
: ch
= '+'; break;
5457 case VK_OEM_MINUS
: ch
= '-'; break;
5460 if (ch
&& unshiftedChars
[0] != ch
&& shiftedChars
[0] != ch
) {
5461 // Windows has assigned a virtual key code to the key even though
5462 // the character can't be produced with this key. That probably
5463 // means the character can't be produced with any key in the
5464 // current layout and so the assignment is based on a QWERTY
5465 // layout. Append this code so that users can access the shortcut.
5466 unshiftedLatinChar
= ch
;
5470 // If the charCode is not ASCII character, we should replace the
5471 // charCode with ASCII character only when Ctrl is pressed.
5472 // But don't replace the charCode when the charCode is not same as
5473 // unmodified characters. In such case, Ctrl is sometimes used for a
5474 // part of character inputting key combination like Shift.
5475 if (aModKeyState
.mIsControlDown
) {
5476 PRUint8 currentState
= eCtrl
;
5477 if (aModKeyState
.mIsShiftDown
)
5478 currentState
|= eShift
;
5481 aModKeyState
.mIsShiftDown
? shiftedLatinChar
: unshiftedLatinChar
;
5483 (numOfUniChars
== 0 ||
5484 StringCaseInsensitiveEquals(uniChars
, numOfUniChars
,
5485 aModKeyState
.mIsShiftDown
? shiftedChars
: unshiftedChars
,
5486 aModKeyState
.mIsShiftDown
? numOfShiftedChars
:
5487 numOfUnshiftedChars
))) {
5488 numOfUniChars
= numOfShiftStates
= 1;
5490 shiftStates
[0] = currentState
;
5496 if (numOfUniChars
> 0 || numOfShiftedChars
> 0 || numOfUnshiftedChars
> 0) {
5497 PRUint32 num
= PR_MAX(numOfUniChars
,
5498 PR_MAX(numOfShiftedChars
, numOfUnshiftedChars
));
5499 PRUint32 skipUniChars
= num
- numOfUniChars
;
5500 PRUint32 skipShiftedChars
= num
- numOfShiftedChars
;
5501 PRUint32 skipUnshiftedChars
= num
- numOfUnshiftedChars
;
5502 UINT keyCode
= numOfUniChars
== 0 ? DOMKeyCode
: 0;
5503 for (PRUint32 cnt
= 0; cnt
< num
; cnt
++) {
5504 PRUint16 uniChar
, shiftedChar
, unshiftedChar
;
5505 uniChar
= shiftedChar
= unshiftedChar
= 0;
5506 if (skipUniChars
<= cnt
) {
5507 if (cnt
- skipUniChars
< numOfShiftStates
) {
5508 // If key in combination with Alt and/or Ctrl produces a different
5509 // character than without them then do not report these flags
5510 // because it is separate keyboard layout shift state. If dead-key
5511 // and base character does not produce a valid composite character
5512 // then both produced dead-key character and following base
5513 // character may have different modifier flags, too.
5514 aModKeyState
.mIsShiftDown
=
5515 (shiftStates
[cnt
- skipUniChars
] & eShift
) != 0;
5516 aModKeyState
.mIsControlDown
=
5517 (shiftStates
[cnt
- skipUniChars
] & eCtrl
) != 0;
5518 aModKeyState
.mIsAltDown
=
5519 (shiftStates
[cnt
- skipUniChars
] & eAlt
) != 0;
5521 uniChar
= uniChars
[cnt
- skipUniChars
];
5523 if (skipShiftedChars
<= cnt
)
5524 shiftedChar
= shiftedChars
[cnt
- skipShiftedChars
];
5525 if (skipUnshiftedChars
<= cnt
)
5526 unshiftedChar
= unshiftedChars
[cnt
- skipUnshiftedChars
];
5527 nsAutoTArray
<nsAlternativeCharCode
, 5> altArray
;
5529 if (shiftedChar
|| unshiftedChar
) {
5530 nsAlternativeCharCode
chars(unshiftedChar
, shiftedChar
);
5531 altArray
.AppendElement(chars
);
5533 if (cnt
== num
- 1 && (unshiftedLatinChar
|| shiftedLatinChar
)) {
5534 nsAlternativeCharCode
chars(unshiftedLatinChar
, shiftedLatinChar
);
5535 altArray
.AppendElement(chars
);
5538 DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, &altArray
,
5539 keyCode
, nsnull
, aModKeyState
, extraFlags
);
5542 DispatchKeyEvent(NS_KEY_PRESS
, 0, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
5547 UINT unichar
= ::MapVirtualKey(virtualKeyCode
, MAPVK_VK_TO_CHAR
);
5548 // Check for dead characters or no mapping
5549 if (unichar
& 0x80) {
5552 DispatchKeyEvent(NS_KEY_PRESS
, unichar
, nsnull
, DOMKeyCode
, nsnull
, aModKeyState
,
5561 LRESULT
nsWindow::OnKeyUp(const MSG
&aMsg
,
5562 nsModifierKeyState
&aModKeyState
,
5563 PRBool
*aEventDispatched
)
5565 UINT virtualKeyCode
= aMsg
.wParam
;
5567 PR_LOG(gWindowsLog
, PR_LOG_ALWAYS
,
5568 ("nsWindow::OnKeyUp VK=%d\n", virtualKeyCode
));
5570 if (!nsIMM32Handler::IsComposing(this)) {
5571 virtualKeyCode
= MapFromNativeToDOM(virtualKeyCode
);
5574 if (aEventDispatched
)
5575 *aEventDispatched
= PR_TRUE
;
5576 return DispatchKeyEvent(NS_KEY_UP
, 0, nsnull
, virtualKeyCode
, &aMsg
,
5581 LRESULT
nsWindow::OnChar(const MSG
&aMsg
, nsModifierKeyState
&aModKeyState
,
5582 PRBool
*aEventDispatched
, PRUint32 aFlags
)
5584 return OnCharRaw(aMsg
.wParam
, HIWORD(aMsg
.lParam
) & 0xFF, aModKeyState
,
5585 aFlags
, &aMsg
, aEventDispatched
);
5589 LRESULT
nsWindow::OnCharRaw(UINT charCode
, UINT aScanCode
,
5590 nsModifierKeyState
&aModKeyState
, PRUint32 aFlags
,
5591 const MSG
*aMsg
, PRBool
*aEventDispatched
)
5593 // ignore [shift+]alt+space so the OS can handle it
5594 if (aModKeyState
.mIsAltDown
&& !aModKeyState
.mIsControlDown
&&
5595 IS_VK_DOWN(NS_VK_SPACE
)) {
5599 // Ignore Ctrl+Enter (bug 318235)
5600 if (aModKeyState
.mIsControlDown
&& charCode
== 0xA) {
5604 // WM_CHAR with Control and Alt (== AltGr) down really means a normal character
5605 PRBool saveIsAltDown
= aModKeyState
.mIsAltDown
;
5606 PRBool saveIsControlDown
= aModKeyState
.mIsControlDown
;
5607 if (aModKeyState
.mIsAltDown
&& aModKeyState
.mIsControlDown
)
5608 aModKeyState
.mIsAltDown
= aModKeyState
.mIsControlDown
= PR_FALSE
;
5612 if (nsIMM32Handler::IsComposing(this)) {
5616 if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1A) { // Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
5617 // need to account for shift here. bug 16486
5618 if (aModKeyState
.mIsShiftDown
)
5619 uniChar
= charCode
- 1 + 'A';
5621 uniChar
= charCode
- 1 + 'a';
5624 else if (aModKeyState
.mIsControlDown
&& charCode
<= 0x1F) {
5625 // Fix for 50255 - <ctrl><[> and <ctrl><]> are not being processed.
5626 // also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
5627 // for some reason the keypress handler need to have the uniChar code set
5628 // with the addition of a upper case A not the lower case.
5629 uniChar
= charCode
- 1 + 'A';
5631 } else { // 0x20 - SPACE, 0x3D - EQUALS
5632 if (charCode
< 0x20 || (charCode
== 0x3D && aModKeyState
.mIsControlDown
)) {
5640 // Keep the characters unshifted for shortcuts and accesskeys and make sure
5641 // that numbers are always passed as such (among others: bugs 50255 and 351310)
5642 if (uniChar
&& (aModKeyState
.mIsControlDown
|| aModKeyState
.mIsAltDown
)) {
5643 UINT virtualKeyCode
= ::MapVirtualKeyEx(aScanCode
, MAPVK_VSC_TO_VK
,
5644 gKbdLayout
.GetLayout());
5645 UINT unshiftedCharCode
=
5646 virtualKeyCode
>= '0' && virtualKeyCode
<= '9' ? virtualKeyCode
:
5647 aModKeyState
.mIsShiftDown
? ::MapVirtualKeyEx(virtualKeyCode
,
5649 gKbdLayout
.GetLayout()) : 0;
5650 // ignore diacritics (top bit set) and key mapping errors (char code 0)
5651 if ((INT
)unshiftedCharCode
> 0)
5652 uniChar
= unshiftedCharCode
;
5655 // Fix for bug 285161 (and 295095) which was caused by the initial fix for bug 178110.
5656 // When pressing (alt|ctrl)+char, the char must be lowercase unless shift is
5658 if (!aModKeyState
.mIsShiftDown
&& (saveIsAltDown
|| saveIsControlDown
)) {
5659 uniChar
= towlower(uniChar
);
5662 PRBool result
= DispatchKeyEvent(NS_KEY_PRESS
, uniChar
, nsnull
,
5663 charCode
, aMsg
, aModKeyState
, aFlags
);
5664 if (aEventDispatched
)
5665 *aEventDispatched
= PR_TRUE
;
5666 aModKeyState
.mIsAltDown
= saveIsAltDown
;
5667 aModKeyState
.mIsControlDown
= saveIsControlDown
;
5672 nsWindow::SetupKeyModifiersSequence(nsTArray
<KeyPair
>* aArray
, PRUint32 aModifiers
)
5674 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(sModifierKeyMap
); ++i
) {
5675 const PRUint32
* map
= sModifierKeyMap
[i
];
5676 if (aModifiers
& map
[0]) {
5677 aArray
->AppendElement(KeyPair(map
[1], map
[2]));
5683 nsWindow::ConfigureChildren(const nsTArray
<Configuration
>& aConfigurations
)
5685 // XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos
5686 // here, if that helps in some situations. So far I haven't seen a
5688 for (PRUint32 i
= 0; i
< aConfigurations
.Length(); ++i
) {
5689 const Configuration
& configuration
= aConfigurations
[i
];
5690 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
5691 NS_ASSERTION(w
->GetParent() == this,
5692 "Configured widget is not a child");
5694 // MSDN says we should do on WinCE this before moving or resizing the window
5695 // See http://msdn.microsoft.com/en-us/library/aa930600.aspx
5696 // We put the region back just below, anyway.
5697 ::SetWindowRgn(w
->mWnd
, NULL
, TRUE
);
5700 w
->GetBounds(bounds
);
5701 if (bounds
.Size() != configuration
.mBounds
.Size()) {
5702 w
->Resize(configuration
.mBounds
.x
, configuration
.mBounds
.y
,
5703 configuration
.mBounds
.width
, configuration
.mBounds
.height
,
5705 } else if (bounds
.TopLeft() != configuration
.mBounds
.TopLeft()) {
5706 w
->Move(configuration
.mBounds
.x
, configuration
.mBounds
.y
);
5708 nsresult rv
= w
->SetWindowClipRegion(configuration
.mClipRegion
, PR_FALSE
);
5709 NS_ENSURE_SUCCESS(rv
, rv
);
5715 CreateHRGNFromArray(const nsTArray
<nsIntRect
>& aRects
)
5717 PRInt32 size
= sizeof(RGNDATAHEADER
) + sizeof(RECT
)*aRects
.Length();
5718 nsAutoTArray
<PRUint8
,100> buf
;
5719 if (!buf
.SetLength(size
))
5721 RGNDATA
* data
= reinterpret_cast<RGNDATA
*>(buf
.Elements());
5722 RECT
* rects
= reinterpret_cast<RECT
*>(data
->Buffer
);
5723 data
->rdh
.dwSize
= sizeof(data
->rdh
);
5724 data
->rdh
.iType
= RDH_RECTANGLES
;
5725 data
->rdh
.nCount
= aRects
.Length();
5727 for (PRUint32 i
= 0; i
< aRects
.Length(); ++i
) {
5728 const nsIntRect
& r
= aRects
[i
];
5729 bounds
.UnionRect(bounds
, r
);
5730 ::SetRect(&rects
[i
], r
.x
, r
.y
, r
.XMost(), r
.YMost());
5732 ::SetRect(&data
->rdh
.rcBound
, bounds
.x
, bounds
.y
, bounds
.XMost(), bounds
.YMost());
5733 return ::ExtCreateRegion(NULL
, buf
.Length(), data
);
5737 nsWindow::SetWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
,
5738 PRBool aIntersectWithExisting
)
5740 if (!aIntersectWithExisting
) {
5741 if (!StoreWindowClipRegion(aRects
))
5745 HRGN dest
= CreateHRGNFromArray(aRects
);
5747 return NS_ERROR_OUT_OF_MEMORY
;
5749 if (aIntersectWithExisting
) {
5750 HRGN current
= ::CreateRectRgn(0, 0, 0, 0);
5752 if (::GetWindowRgn(mWnd
, current
) != 0 /*ERROR*/) {
5753 ::CombineRgn(dest
, dest
, current
, RGN_AND
);
5755 ::DeleteObject(current
);
5759 if (!::SetWindowRgn(mWnd
, dest
, TRUE
)) {
5760 ::DeleteObject(dest
);
5761 return NS_ERROR_FAILURE
;
5766 // WM_DESTROY event handler
5767 void nsWindow::OnDestroy()
5769 mOnDestroyCalled
= PR_TRUE
;
5771 // Make sure we don't get destroyed in the process of tearing down.
5772 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
5774 // Dispatch the NS_DESTROY event. Must be called before mEventCallback is cleared.
5776 DispatchStandardEvent(NS_DESTROY
);
5778 // Prevent the widget from sending additional events.
5779 mEventCallback
= nsnull
;
5781 // Free our subclass and clear |this| stored in the window props. We will no longer
5782 // receive events from Windows after this point.
5783 SubclassWindow(FALSE
);
5785 // Once mEventCallback is cleared and the subclass is reset, sCurrentWindow can be
5786 // cleared. (It's used in tracking windows for mouse events.)
5787 if (sCurrentWindow
== this)
5788 sCurrentWindow
= nsnull
;
5790 // Disconnects us from our parent, will call our GetParent().
5791 nsBaseWidget::Destroy();
5793 // Release references to children, device context, toolkit, and app shell.
5794 nsBaseWidget::OnDestroy();
5796 // Clear our native parent handle.
5797 // XXX Windows will take care of this in the proper order, and SetParent(nsnull)'s
5798 // remove child on the parent already took place in nsBaseWidget's Destroy call above.
5799 //SetParent(nsnull);
5801 // We have to destroy the native drag target before we null out our window pointer.
5802 EnableDragDrop(PR_FALSE
);
5804 // If we're going away and for some reason we're still the rollup widget, rollup and
5805 // turn off capture.
5806 if ( this == sRollupWidget
) {
5807 if ( sRollupListener
)
5808 sRollupListener
->Rollup(nsnull
, nsnull
);
5809 CaptureRollupEvents(nsnull
, PR_FALSE
, PR_TRUE
);
5812 // If IME is disabled, restore it.
5814 mOldIMC
= ::ImmAssociateContext(mWnd
, mOldIMC
);
5815 NS_ASSERTION(!mOldIMC
, "Another IMC was associated");
5818 // Turn off mouse trails if enabled.
5819 MouseTrailer
* mtrailer
= nsToolkit::gMouseTrailer
;
5821 if (mtrailer
->GetMouseTrailerWindow() == mWnd
)
5822 mtrailer
->DestroyTimer();
5824 if (mtrailer
->GetCaptureWindow() == mWnd
)
5825 mtrailer
->SetCaptureWindow(nsnull
);
5828 // Free GDI window class objects
5830 VERIFY(::DeleteObject(mBrush
));
5834 // Free app icon resources.
5836 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_BIG
, (LPARAM
) 0);
5838 ::DestroyIcon(icon
);
5840 icon
= (HICON
) ::SendMessageW(mWnd
, WM_SETICON
, (WPARAM
)ICON_SMALL
, (LPARAM
) 0);
5842 ::DestroyIcon(icon
);
5844 // Destroy any custom cursor resources.
5846 SetCursor(eCursor_standard
);
5849 // Reset transparency
5850 if (eTransparencyTransparent
== mTransparencyMode
)
5851 SetupTranslucentWindowMemoryBitmap(eTransparencyOpaque
);
5854 // Clear the main HWND.
5859 PRBool
nsWindow::OnMove(PRInt32 aX
, PRInt32 aY
)
5864 nsGUIEvent
event(PR_TRUE
, NS_MOVE
, this);
5866 event
.refPoint
.x
= aX
;
5867 event
.refPoint
.y
= aY
;
5869 return DispatchWindowEvent(&event
);
5872 // Send a resize message to the listener
5873 PRBool
nsWindow::OnResize(nsIntRect
&aWindowRect
)
5875 // call the event callback
5876 if (mEventCallback
) {
5877 nsSizeEvent
event(PR_TRUE
, NS_SIZE
, this);
5879 event
.windowSize
= &aWindowRect
;
5881 if (::GetWindowRect(mWnd
, &r
)) {
5882 event
.mWinWidth
= PRInt32(r
.right
- r
.left
);
5883 event
.mWinHeight
= PRInt32(r
.bottom
- r
.top
);
5885 event
.mWinWidth
= 0;
5886 event
.mWinHeight
= 0;
5888 return DispatchWindowEvent(&event
);
5894 #if !defined(WINCE) // implemented in nsWindowCE.cpp
5895 PRBool
nsWindow::OnHotKey(WPARAM wParam
, LPARAM lParam
)
5899 #endif // !defined(WINCE)
5901 void nsWindow::OnSettingsChange(WPARAM wParam
, LPARAM lParam
)
5903 if (mWindowType
== eWindowType_dialog
||
5904 mWindowType
== eWindowType_toplevel
)
5905 nsWindowGfx::OnSettingsChangeGfx(wParam
);
5908 // Scrolling helper function for handling plugins.
5909 // Return value indicates whether the calling function should handle this
5910 // result indicates whether this was handled at all
5911 PRBool
nsWindow::HandleScrollingPlugins(UINT aMsg
, WPARAM aWParam
,
5912 LPARAM aLParam
, PRBool
& aHandled
)
5914 // The scroll event will be dispatched to the toplevel
5915 // window. We need to give it to the child window
5916 aHandled
= PR_FALSE
; // default is to have not handled
5918 DWORD dwPoints
= ::GetMessagePos();
5919 point
.x
= GET_X_LPARAM(dwPoints
);
5920 point
.y
= GET_Y_LPARAM(dwPoints
);
5922 static PRBool sMayBeUsingLogitechMouse
= PR_FALSE
;
5923 if (aMsg
== WM_MOUSEHWHEEL
) {
5924 // Logitech (Logicool) mouse driver (confirmed with 4.82.11 and MX-1100)
5925 // always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs one
5926 // message at first time, this time, ::GetMessagePos works fine.
5927 // Then, we will return 0 (0 means we process it) to the message. Then, the
5928 // driver will POST the same messages continuously during the wheel tilted.
5929 // But ::GetMessagePos API always returns (0, 0), even if the actual mouse
5930 // cursor isn't 0,0. Therefore, we cannot trust the result of
5931 // ::GetMessagePos API if the sender is the driver.
5932 if (!sMayBeUsingLogitechMouse
&& aLParam
== 0 && aLParam
!= dwPoints
&&
5933 ::InSendMessage()) {
5934 sMayBeUsingLogitechMouse
= PR_TRUE
;
5935 } else if (sMayBeUsingLogitechMouse
&& aLParam
!= 0 && ::InSendMessage()) {
5936 // The user has changed the mouse from Logitech's to another one (e.g.,
5937 // the user has changed to the touchpad of the notebook.
5938 sMayBeUsingLogitechMouse
= PR_FALSE
;
5940 // If the WM_MOUSEHWHEEL comes from Logitech's mouse driver, and the
5941 // ::GetMessagePos isn't correct, probably, we should use ::GetCursorPos
5943 if (sMayBeUsingLogitechMouse
&& aLParam
== 0 && dwPoints
== 0) {
5944 ::GetCursorPos(&point
);
5948 HWND destWnd
= ::WindowFromPoint(point
);
5949 // Since we receive scroll events for as long as
5950 // we are focused, it's entirely possible that there
5951 // is another app's window or no window under the
5955 // No window is under the pointer
5956 return PR_FALSE
; // break
5958 // We don't care about windows belonging to other processes.
5959 DWORD processId
= 0;
5960 GetWindowThreadProcessId(destWnd
, &processId
);
5961 if (processId
!= GetCurrentProcessId())
5963 // Somebody elses window
5964 return PR_FALSE
; // break
5966 nsWindow
* destWindow
= GetNSWindowPtr(destWnd
);
5967 if (!destWindow
|| destWindow
->mWindowType
== eWindowType_plugin
) {
5968 // Some other app, or a plugin window.
5969 // Windows directs scrolling messages to the focused window.
5970 // However, Mozilla does not like plugins having focus, so a
5971 // Mozilla window (ie, the plugin's parent (us!) has focus.)
5972 // Therefore, plugins etc _should_ get first grab at the
5973 // message, but this focus vaguary means the plugin misses
5974 // out. If the window is a child of ours, forward it on.
5975 // Determine if a child by walking the parent list until
5976 // we find a parent matching our wndproc.
5977 HWND parentWnd
= ::GetParent(destWnd
);
5979 nsWindow
* parentWindow
= GetNSWindowPtr(parentWnd
);
5981 // We have a child window - quite possibly a plugin window.
5982 // However, not all plugins are created equal - some will handle this
5983 // message themselves, some will forward directly back to us, while
5984 // others will call DefWndProc, which itself still forwards back to us.
5985 // So if we have sent it once, we need to handle it ourself.
5986 if (mInScrollProcessing
) {
5987 destWnd
= parentWnd
;
5988 destWindow
= parentWindow
;
5990 // First time we have seen this message.
5991 // Call the child - either it will consume it, or
5992 // it will wind it's way back to us,triggering the destWnd case above
5993 // either way,when the call returns,we are all done with the message,
5994 mInScrollProcessing
= PR_TRUE
;
5995 if (0 == ::SendMessageW(destWnd
, aMsg
, aWParam
, aLParam
))
5998 mInScrollProcessing
= PR_FALSE
;
6000 return PR_FALSE
; // break; // stop parent search
6002 parentWnd
= ::GetParent(parentWnd
);
6003 } // while parentWnd
6005 if (destWnd
== nsnull
)
6007 if (destWnd
!= mWnd
) {
6010 destWindow
->ProcessMessage(aMsg
, aWParam
, aLParam
, &aRetValue
);
6012 return PR_FALSE
; // return result immediately
6016 printf("WARNING: couldn't get child window for SCROLL event\n");
6019 return PR_TRUE
; // caller should handle this
6022 PRBool
nsWindow::OnScroll(UINT aMsg
, WPARAM aWParam
, LPARAM aLParam
)
6026 // Scroll message generated by Thinkpad Trackpoint Driver or similar
6027 // Treat as a mousewheel message and scroll appropriately
6030 if (!HandleScrollingPlugins(aMsg
, aWParam
, aLParam
, result
))
6031 return result
; // Return if it's not our message or has been dispatched
6033 nsMouseScrollEvent
scrollevent(PR_TRUE
, NS_MOUSE_SCROLL
, this);
6034 scrollevent
.scrollFlags
= (aMsg
== WM_VSCROLL
)
6035 ? nsMouseScrollEvent::kIsVertical
6036 : nsMouseScrollEvent::kIsHorizontal
;
6037 switch (LOWORD(aWParam
))
6040 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6042 scrollevent
.delta
= 1;
6045 scrollevent
.scrollFlags
|= nsMouseScrollEvent::kIsFullPage
;
6047 scrollevent
.delta
= -1;
6052 scrollevent
.isShift
= IS_VK_DOWN(NS_VK_SHIFT
);
6053 scrollevent
.isControl
= IS_VK_DOWN(NS_VK_CONTROL
);
6054 scrollevent
.isMeta
= PR_FALSE
;
6055 scrollevent
.isAlt
= IS_VK_DOWN(NS_VK_ALT
);
6056 InitEvent(scrollevent
);
6057 if (nsnull
!= mEventCallback
)
6059 DispatchWindowEvent(&scrollevent
);
6063 // Scroll message generated by external application
6064 // XXX Handle by scrolling the window in the desired manner (Bug 315727)
6068 // Return the brush used to paint the background of this control
6069 HBRUSH
nsWindow::OnControlColor()
6074 // Can be overriden. Controls auto-erase of background.
6075 PRBool
nsWindow::AutoErase(HDC dc
)
6077 #ifdef WINCE_WINDOWS_MOBILE
6079 GetClipBox(dc
, &wrect
);
6080 AddRECTToRegion(wrect
, mInvalidatedRegion
);
6085 /**************************************************************
6086 **************************************************************
6088 ** BLOCK: IME management and accessibility
6090 ** Handles managing IME input and accessibility.
6092 **************************************************************
6093 **************************************************************/
6095 NS_IMETHODIMP
nsWindow::ResetInputState()
6097 #ifdef DEBUG_KBSTATE
6098 printf("ResetInputState\n");
6101 #ifdef NS_ENABLE_TSF
6102 nsTextStore::CommitComposition(PR_FALSE
);
6103 #endif //NS_ENABLE_TSF
6105 nsIMEContext
IMEContext(mWnd
);
6106 if (IMEContext
.IsValid()) {
6107 ::ImmNotifyIME(IMEContext
.get(), NI_COMPOSITIONSTR
, CPS_COMPLETE
, NULL
);
6108 ::ImmNotifyIME(IMEContext
.get(), NI_COMPOSITIONSTR
, CPS_CANCEL
, NULL
);
6113 NS_IMETHODIMP
nsWindow::SetIMEOpenState(PRBool aState
)
6115 #ifdef DEBUG_KBSTATE
6116 printf("SetIMEOpenState %s\n", (aState
? "Open" : "Close"));
6119 #ifdef NS_ENABLE_TSF
6120 nsTextStore::SetIMEOpenState(aState
);
6121 #endif //NS_ENABLE_TSF
6123 nsIMEContext
IMEContext(mWnd
);
6124 if (IMEContext
.IsValid()) {
6125 ::ImmSetOpenStatus(IMEContext
.get(), aState
? TRUE
: FALSE
);
6130 NS_IMETHODIMP
nsWindow::GetIMEOpenState(PRBool
* aState
)
6132 nsIMEContext
IMEContext(mWnd
);
6133 if (IMEContext
.IsValid()) {
6134 BOOL isOpen
= ::ImmGetOpenStatus(IMEContext
.get());
6135 *aState
= isOpen
? PR_TRUE
: PR_FALSE
;
6139 #ifdef NS_ENABLE_TSF
6140 *aState
|= nsTextStore::GetIMEOpenState();
6141 #endif //NS_ENABLE_TSF
6146 NS_IMETHODIMP
nsWindow::SetIMEEnabled(PRUint32 aState
)
6148 #ifdef NS_ENABLE_TSF
6149 nsTextStore::SetIMEEnabled(aState
);
6150 #endif //NS_ENABLE_TSF
6151 #ifdef DEBUG_KBSTATE
6152 printf("SetIMEEnabled: %s\n", (aState
== nsIWidget::IME_STATUS_ENABLED
||
6153 aState
== nsIWidget::IME_STATUS_PLUGIN
)?
6154 "Enabled": "Disabled");
6156 if (nsIMM32Handler::IsComposing(this))
6158 mIMEEnabled
= aState
;
6159 PRBool enable
= (aState
== nsIWidget::IME_STATUS_ENABLED
||
6160 aState
== nsIWidget::IME_STATUS_PLUGIN
);
6162 #if defined(WINCE_HAVE_SOFTKB)
6163 sSoftKeyboardState
= (aState
!= nsIWidget::IME_STATUS_DISABLED
);
6164 nsWindowCE::ToggleSoftKB(sSoftKeyboardState
);
6167 if (!enable
!= !mOldIMC
)
6169 mOldIMC
= ::ImmAssociateContext(mWnd
, enable
? mOldIMC
: NULL
);
6170 NS_ASSERTION(!enable
|| !mOldIMC
, "Another IMC was associated");
6175 NS_IMETHODIMP
nsWindow::GetIMEEnabled(PRUint32
* aState
)
6177 #ifdef DEBUG_KBSTATE
6178 printf("GetIMEEnabled: %s\n", mIMEEnabled
? "Enabled": "Disabled");
6180 *aState
= mIMEEnabled
;
6184 NS_IMETHODIMP
nsWindow::CancelIMEComposition()
6186 #ifdef DEBUG_KBSTATE
6187 printf("CancelIMEComposition\n");
6190 #ifdef NS_ENABLE_TSF
6191 nsTextStore::CommitComposition(PR_TRUE
);
6192 #endif //NS_ENABLE_TSF
6194 nsIMEContext
IMEContext(mWnd
);
6195 if (IMEContext
.IsValid()) {
6196 ::ImmNotifyIME(IMEContext
.get(), NI_COMPOSITIONSTR
, CPS_CANCEL
, NULL
);
6202 nsWindow::GetToggledKeyState(PRUint32 aKeyCode
, PRBool
* aLEDState
)
6204 #ifdef DEBUG_KBSTATE
6205 printf("GetToggledKeyState\n");
6207 NS_ENSURE_ARG_POINTER(aLEDState
);
6208 *aLEDState
= (::GetKeyState(aKeyCode
) & 1) != 0;
6212 #ifdef NS_ENABLE_TSF
6214 nsWindow::OnIMEFocusChange(PRBool aFocus
)
6216 nsresult rv
= nsTextStore::OnFocusChange(aFocus
, this, mIMEEnabled
);
6217 if (rv
== NS_ERROR_NOT_AVAILABLE
)
6218 rv
= NS_ERROR_NOT_IMPLEMENTED
; // TSF is not enabled, maybe.
6223 nsWindow::OnIMETextChange(PRUint32 aStart
,
6227 return nsTextStore::OnTextChange(aStart
, aOldEnd
, aNewEnd
);
6231 nsWindow::OnIMESelectionChange(void)
6233 return nsTextStore::OnSelectionChange();
6235 #endif //NS_ENABLE_TSF
6237 #ifdef ACCESSIBILITY
6238 already_AddRefed
<nsIAccessible
> nsWindow::GetRootAccessible()
6240 nsWindow::sIsAccessibilityOn
= TRUE
;
6242 if (mInDtor
|| mOnDestroyCalled
|| mWindowType
== eWindowType_invisible
) {
6246 nsIAccessible
*rootAccessible
= nsnull
;
6248 // If accessibility is turned on, we create this even before it is requested
6249 // when the window gets focused. We need it to be created early so it can
6250 // generate accessibility events right away
6251 nsWindow
* accessibleWindow
= nsnull
;
6252 if (mContentType
!= eContentTypeInherit
) {
6253 // We're on a MozillaContentWindowClass or MozillaUIWindowClass window.
6254 // Search for the correct visible child window to get an accessible
6255 // document from. Make sure to use an active child window
6256 HWND accessibleWnd
= ::GetTopWindow(mWnd
);
6257 while (accessibleWnd
) {
6258 // Loop through windows and find the first one with accessibility info
6259 accessibleWindow
= GetNSWindowPtr(accessibleWnd
);
6260 if (accessibleWindow
) {
6261 accessibleWindow
->DispatchAccessibleEvent(NS_GETACCESSIBLE
, &rootAccessible
);
6262 if (rootAccessible
) {
6263 break; // Success, one of the child windows was active
6266 accessibleWnd
= ::GetNextWindow(accessibleWnd
, GW_HWNDNEXT
);
6270 DispatchAccessibleEvent(NS_GETACCESSIBLE
, &rootAccessible
);
6272 return rootAccessible
;
6275 STDMETHODIMP_(LRESULT
)
6276 nsWindow::LresultFromObject(REFIID riid
, WPARAM wParam
, LPUNKNOWN pAcc
)
6278 // open the dll dynamically
6280 sAccLib
=::LoadLibraryW(L
"OLEACC.DLL");
6283 if (!sLresultFromObject
)
6284 sLresultFromObject
= (LPFNLRESULTFROMOBJECT
)GetProcAddress(sAccLib
,"LresultFromObject");
6286 if (sLresultFromObject
)
6287 return sLresultFromObject(riid
,wParam
,pAcc
);
6294 /**************************************************************
6295 **************************************************************
6297 ** BLOCK: Transparency
6299 ** Window transparency helpers.
6301 **************************************************************
6302 **************************************************************/
6306 void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth
, PRInt32 aNewHeight
, PRBool force
)
6308 if (!force
&& aNewWidth
== mBounds
.width
&& aNewHeight
== mBounds
.height
)
6311 mTransparentSurface
= new gfxWindowsSurface(gfxIntSize(aNewWidth
, aNewHeight
), gfxASurface::ImageFormatARGB32
);
6312 mMemoryDC
= mTransparentSurface
->GetDC();
6315 void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode
)
6319 if (aMode
== mTransparencyMode
)
6322 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
6323 nsWindow
* topWindow
= GetNSWindowPtr(hWnd
);
6327 NS_WARNING("Trying to use transparent chrome in an embedded context");
6331 LONG_PTR style
= 0, exStyle
= 0;
6333 case eTransparencyTransparent
:
6334 exStyle
|= WS_EX_LAYERED
;
6335 case eTransparencyOpaque
:
6336 case eTransparencyGlass
:
6337 topWindow
->mTransparencyMode
= aMode
;
6341 style
|= topWindow
->WindowStyle();
6342 exStyle
|= topWindow
->WindowExStyle();
6344 if (aMode
== eTransparencyTransparent
) {
6345 style
&= ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
);
6346 exStyle
&= ~(WS_EX_DLGMODALFRAME
| WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
| WS_EX_STATICEDGE
);
6349 VERIFY_WINDOW_STYLE(style
);
6350 ::SetWindowLongPtrW(hWnd
, GWL_STYLE
, style
);
6351 ::SetWindowLongPtrW(hWnd
, GWL_EXSTYLE
, exStyle
);
6353 mTransparencyMode
= aMode
;
6355 SetupTranslucentWindowMemoryBitmap(aMode
);
6356 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
6357 MARGINS margins
= { 0, 0, 0, 0 };
6358 DWMNCRENDERINGPOLICY policy
= DWMNCRP_USEWINDOWSTYLE
;
6359 if(eTransparencyGlass
== aMode
) {
6360 margins
.cxLeftWidth
= -1;
6361 policy
= DWMNCRP_ENABLED
;
6363 if(nsUXThemeData::sHaveCompositor
) {
6364 nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd
, &margins
);
6365 nsUXThemeData::dwmSetWindowAttributePtr(hWnd
, DWMWA_NCRENDERING_POLICY
, &policy
, sizeof policy
);
6367 #endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
6368 #endif // #ifndef WINCE
6371 void nsWindow::SetupTranslucentWindowMemoryBitmap(nsTransparencyMode aMode
)
6373 if (eTransparencyTransparent
== aMode
) {
6374 ResizeTranslucentWindow(mBounds
.width
, mBounds
.height
, PR_TRUE
);
6376 mTransparentSurface
= nsnull
;
6381 nsresult
nsWindow::UpdateTranslucentWindow()
6384 if (mBounds
.IsEmpty())
6389 BLENDFUNCTION bf
= { AC_SRC_OVER
, 0, 255, AC_SRC_ALPHA
};
6390 SIZE winSize
= { mBounds
.width
, mBounds
.height
};
6391 POINT srcPos
= { 0, 0 };
6392 HWND hWnd
= GetTopLevelHWND(mWnd
, PR_TRUE
);
6394 ::GetWindowRect(hWnd
, &winRect
);
6396 // perform the alpha blend
6397 if (!::UpdateLayeredWindow(hWnd
, NULL
, (POINT
*)&winRect
, &winSize
, mMemoryDC
, &srcPos
, 0, &bf
, ULW_ALPHA
))
6398 return NS_ERROR_FAILURE
;
6406 /**************************************************************
6407 **************************************************************
6409 ** BLOCK: Popup rollup hooks
6411 ** Deals with CaptureRollup on popup windows.
6413 **************************************************************
6414 **************************************************************/
6417 // Schedules a timer for a window, so we can rollup after processing the hook event
6418 void nsWindow::ScheduleHookTimer(HWND aWnd
, UINT aMsgId
)
6420 // In some cases multiple hooks may be scheduled
6421 // so ignore any other requests once one timer is scheduled
6422 if (sHookTimerId
== 0) {
6423 // Remember the window handle and the message ID to be used later
6424 sRollupMsgId
= aMsgId
;
6425 sRollupMsgWnd
= aWnd
;
6426 // Schedule native timer for doing the rollup after
6427 // this event is done being processed
6428 sHookTimerId
= ::SetTimer(NULL
, 0, 0, (TIMERPROC
)HookTimerForPopups
);
6429 NS_ASSERTION(sHookTimerId
, "Timer couldn't be created.");
6433 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
6434 int gLastMsgCode
= 0;
6435 extern MSGFEventMsgInfo gMSGFEvents
[];
6438 // Process Menu messages, rollup when popup is clicked.
6439 LRESULT CALLBACK
nsWindow::MozSpecialMsgFilter(int code
, WPARAM wParam
, LPARAM lParam
)
6441 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
6443 MSG
* pMsg
= (MSG
*)lParam
;
6446 while (gMSGFEvents
[inx
].mId
!= code
&& gMSGFEvents
[inx
].mStr
!= NULL
) {
6449 if (code
!= gLastMsgCode
) {
6450 if (gMSGFEvents
[inx
].mId
== code
) {
6452 printf("MozSpecialMessageProc - code: 0x%X - %s hw: %p\n", code
, gMSGFEvents
[inx
].mStr
, pMsg
->hwnd
);
6456 printf("MozSpecialMessageProc - code: 0x%X - %d hw: %p\n", code
, gMSGFEvents
[inx
].mId
, pMsg
->hwnd
);
6459 gLastMsgCode
= code
;
6461 PrintEvent(pMsg
->message
, FALSE
, FALSE
);
6463 #endif // #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
6465 if (sProcessHook
&& code
== MSGF_MENU
) {
6466 MSG
* pMsg
= (MSG
*)lParam
;
6467 ScheduleHookTimer( pMsg
->hwnd
, pMsg
->message
);
6470 return ::CallNextHookEx(sMsgFilterHook
, code
, wParam
, lParam
);
6473 // Process all mouse messages. Roll up when a click is in a native window
6474 // that doesn't have an nsIWidget.
6475 LRESULT CALLBACK
nsWindow::MozSpecialMouseProc(int code
, WPARAM wParam
, LPARAM lParam
)
6479 case WM_LBUTTONDOWN
:
6480 case WM_RBUTTONDOWN
:
6481 case WM_MBUTTONDOWN
:
6483 case WM_MOUSEHWHEEL
:
6485 MOUSEHOOKSTRUCT
* ms
= (MOUSEHOOKSTRUCT
*)lParam
;
6486 nsIWidget
* mozWin
= (nsIWidget
*)GetNSWindowPtr(ms
->hwnd
);
6488 // If this window is windowed plugin window, the mouse events are not
6490 if (static_cast<nsWindow
*>(mozWin
)->mWindowType
== eWindowType_plugin
)
6491 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
6493 ScheduleHookTimer(ms
->hwnd
, (UINT
)wParam
);
6499 return ::CallNextHookEx(sCallMouseHook
, code
, wParam
, lParam
);
6502 // Process all messages. Roll up when the window is moving, or
6503 // is resizing or when maximized or mininized.
6504 LRESULT CALLBACK
nsWindow::MozSpecialWndProc(int code
, WPARAM wParam
, LPARAM lParam
)
6506 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
6508 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
6509 PrintEvent(cwpt
->message
, FALSE
, FALSE
);
6514 CWPSTRUCT
* cwpt
= (CWPSTRUCT
*)lParam
;
6515 if (cwpt
->message
== WM_MOVING
||
6516 cwpt
->message
== WM_SIZING
||
6517 cwpt
->message
== WM_GETMINMAXINFO
) {
6518 ScheduleHookTimer(cwpt
->hwnd
, (UINT
)cwpt
->message
);
6522 return ::CallNextHookEx(sCallProcHook
, code
, wParam
, lParam
);
6525 // Register the special "hooks" for dropdown processing.
6526 void nsWindow::RegisterSpecialDropdownHooks()
6528 NS_ASSERTION(!sMsgFilterHook
, "sMsgFilterHook must be NULL!");
6529 NS_ASSERTION(!sCallProcHook
, "sCallProcHook must be NULL!");
6531 DISPLAY_NMM_PRT("***************** Installing Msg Hooks ***************\n");
6533 //HMODULE hMod = GetModuleHandle("gkwidget.dll");
6535 // Install msg hook for moving the window and resizing
6536 if (!sMsgFilterHook
) {
6537 DISPLAY_NMM_PRT("***** Hooking sMsgFilterHook!\n");
6538 sMsgFilterHook
= SetWindowsHookEx(WH_MSGFILTER
, MozSpecialMsgFilter
, NULL
, GetCurrentThreadId());
6539 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
6540 if (!sMsgFilterHook
) {
6541 printf("***** SetWindowsHookEx is NOT installed for WH_MSGFILTER!\n");
6546 // Install msg hook for menus
6547 if (!sCallProcHook
) {
6548 DISPLAY_NMM_PRT("***** Hooking sCallProcHook!\n");
6549 sCallProcHook
= SetWindowsHookEx(WH_CALLWNDPROC
, MozSpecialWndProc
, NULL
, GetCurrentThreadId());
6550 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
6551 if (!sCallProcHook
) {
6552 printf("***** SetWindowsHookEx is NOT installed for WH_CALLWNDPROC!\n");
6557 // Install msg hook for the mouse
6558 if (!sCallMouseHook
) {
6559 DISPLAY_NMM_PRT("***** Hooking sCallMouseHook!\n");
6560 sCallMouseHook
= SetWindowsHookEx(WH_MOUSE
, MozSpecialMouseProc
, NULL
, GetCurrentThreadId());
6561 #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
6562 if (!sCallMouseHook
) {
6563 printf("***** SetWindowsHookEx is NOT installed for WH_MOUSE!\n");
6569 // Unhook special message hooks for dropdowns.
6570 void nsWindow::UnregisterSpecialDropdownHooks()
6572 DISPLAY_NMM_PRT("***************** De-installing Msg Hooks ***************\n");
6574 if (sCallProcHook
) {
6575 DISPLAY_NMM_PRT("***** Unhooking sCallProcHook!\n");
6576 if (!::UnhookWindowsHookEx(sCallProcHook
)) {
6577 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallProcHook!\n");
6579 sCallProcHook
= NULL
;
6582 if (sMsgFilterHook
) {
6583 DISPLAY_NMM_PRT("***** Unhooking sMsgFilterHook!\n");
6584 if (!::UnhookWindowsHookEx(sMsgFilterHook
)) {
6585 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sMsgFilterHook!\n");
6587 sMsgFilterHook
= NULL
;
6590 if (sCallMouseHook
) {
6591 DISPLAY_NMM_PRT("***** Unhooking sCallMouseHook!\n");
6592 if (!::UnhookWindowsHookEx(sCallMouseHook
)) {
6593 DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallMouseHook!\n");
6595 sCallMouseHook
= NULL
;
6599 // This timer is designed to only fire one time at most each time a "hook" function
6600 // is used to rollup the dropdown. In some cases, the timer may be scheduled from the
6601 // hook, but that hook event or a subsequent event may roll up the dropdown before
6602 // this timer function is executed.
6604 // For example, if an MFC control takes focus, the combobox will lose focus and rollup
6605 // before this function fires.
6606 VOID CALLBACK
nsWindow::HookTimerForPopups(HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
6608 if (sHookTimerId
!= 0) {
6609 // if the window is NULL then we need to use the ID to kill the timer
6610 BOOL status
= ::KillTimer(NULL
, sHookTimerId
);
6611 NS_ASSERTION(status
, "Hook Timer was not killed.");
6615 if (sRollupMsgId
!= 0) {
6616 // Note: DealWithPopups does the check to make sure that
6617 // sRollupListener and sRollupWidget are not NULL
6618 LRESULT popupHandlingResult
;
6619 nsAutoRollup autoRollup
;
6620 DealWithPopups(sRollupMsgWnd
, sRollupMsgId
, 0, 0, &popupHandlingResult
);
6622 sRollupMsgWnd
= NULL
;
6627 static PRBool
IsDifferentThreadWindow(HWND aWnd
)
6629 return ::GetCurrentThreadId() != ::GetWindowThreadProcessId(aWnd
, NULL
);
6633 nsWindow::EventIsInsideWindow(UINT Msg
, nsWindow
* aWindow
)
6638 if (Msg
== WM_ACTIVATEAPP
)
6639 // don't care about activation/deactivation
6642 if (Msg
== WM_ACTIVATE
)
6643 // but on Windows CE we do care about
6644 // activation/deactivation because there doesn't exist
6645 // cancelable Mouse Activation events
6649 ::GetWindowRect(aWindow
->mWnd
, &r
);
6650 DWORD pos
= ::GetMessagePos();
6652 mp
.x
= GET_X_LPARAM(pos
);
6653 mp
.y
= GET_Y_LPARAM(pos
);
6655 // was the event inside this window?
6656 return (PRBool
) PtInRect(&r
, mp
);
6659 // Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
6661 nsWindow::DealWithPopups(HWND inWnd
, UINT inMsg
, WPARAM inWParam
, LPARAM inLParam
, LRESULT
* outResult
)
6663 if (sRollupListener
&& sRollupWidget
&& ::IsWindowVisible(inWnd
)) {
6665 if (inMsg
== WM_LBUTTONDOWN
|| inMsg
== WM_RBUTTONDOWN
|| inMsg
== WM_MBUTTONDOWN
||
6666 inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
|| inMsg
== WM_ACTIVATE
||
6667 (inMsg
== WM_KILLFOCUS
&& IsDifferentThreadWindow((HWND
)inWParam
))
6670 inMsg
== WM_NCRBUTTONDOWN
||
6671 inMsg
== WM_MOVING
||
6672 inMsg
== WM_SIZING
||
6673 inMsg
== WM_NCLBUTTONDOWN
||
6674 inMsg
== WM_NCMBUTTONDOWN
||
6675 inMsg
== WM_MOUSEACTIVATE
||
6676 inMsg
== WM_ACTIVATEAPP
||
6677 inMsg
== WM_MENUSELECT
6681 // Rollup if the event is outside the popup.
6682 PRBool rollup
= !nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)sRollupWidget
);
6684 if (rollup
&& (inMsg
== WM_MOUSEWHEEL
|| inMsg
== WM_MOUSEHWHEEL
))
6686 sRollupListener
->ShouldRollupOnMouseWheelEvent(&rollup
);
6687 *outResult
= PR_TRUE
;
6690 // If we're dealing with menus, we probably have submenus and we don't
6691 // want to rollup if the click is in a parent menu of the current submenu.
6692 PRUint32 popupsToRollup
= PR_UINT32_MAX
;
6694 nsCOMPtr
<nsIMenuRollup
> menuRollup ( do_QueryInterface(sRollupListener
) );
6696 nsAutoTArray
<nsIWidget
*, 5> widgetChain
;
6697 PRUint32 sameTypeCount
= menuRollup
->GetSubmenuWidgetChain(&widgetChain
);
6698 for ( PRUint32 i
= 0; i
< widgetChain
.Length(); ++i
) {
6699 nsIWidget
* widget
= widgetChain
[i
];
6700 if ( nsWindow::EventIsInsideWindow(inMsg
, (nsWindow
*)widget
) ) {
6701 // don't roll up if the mouse event occured within a menu of the
6702 // same type. If the mouse event occured in a menu higher than
6703 // that, roll up, but pass the number of popups to Rollup so
6704 // that only those of the same type close up.
6705 if (i
< sameTypeCount
) {
6709 popupsToRollup
= sameTypeCount
;
6713 } // foreach parent menu widget
6714 } // if rollup listener knows about menus
6718 if (inMsg
== WM_MOUSEACTIVATE
&& popupsToRollup
== PR_UINT32_MAX
) {
6719 // Prevent the click inside the popup from causing a change in window
6720 // activation. Since the popup is shown non-activated, we need to eat
6721 // any requests to activate the window while it is displayed. Windows
6722 // will automatically activate the popup on the mousedown otherwise.
6724 *outResult
= MA_NOACTIVATE
;
6729 UINT uMsg
= HIWORD(inLParam
);
6730 if (uMsg
== WM_MOUSEMOVE
)
6732 // WM_MOUSEACTIVATE cause by moving the mouse - X-mouse (eg. TweakUI)
6733 // must be enabled in Windows.
6734 sRollupListener
->ShouldRollupOnMouseActivate(&rollup
);
6737 *outResult
= MA_NOACTIVATE
;
6743 // if we've still determined that we should still rollup everything, do it.
6747 // sRollupConsumeEvent may be modified by
6748 // nsIRollupListener::Rollup.
6749 PRBool consumeRollupEvent
= sRollupConsumeEvent
;
6750 // only need to deal with the last rollup for left mouse down events.
6751 sRollupListener
->Rollup(popupsToRollup
, inMsg
== WM_LBUTTONDOWN
? &mLastRollup
: nsnull
);
6753 // Tell hook to stop processing messages
6754 sProcessHook
= PR_FALSE
;
6756 sRollupMsgWnd
= NULL
;
6758 // return TRUE tells Windows that the event is consumed,
6759 // false allows the event to be dispatched
6761 // So if we are NOT supposed to be consuming events, let it go through
6762 if (consumeRollupEvent
&& inMsg
!= WM_RBUTTONDOWN
) {
6767 // if we are only rolling up some popups, don't activate and don't let
6768 // the event go through. This prevents clicks menus higher in the
6769 // chain from opening when a context menu is open
6770 if (popupsToRollup
!= PR_UINT32_MAX
&& inMsg
== WM_MOUSEACTIVATE
) {
6771 *outResult
= MA_NOACTIVATEANDEAT
;
6776 } // if event that might trigger a popup to rollup
6777 } // if rollup listeners registered
6782 /**************************************************************
6783 **************************************************************
6785 ** BLOCK: Misc. utility methods and functions.
6789 **************************************************************
6790 **************************************************************/
6792 // nsModifierKeyState used in various character processing.
6793 nsModifierKeyState::nsModifierKeyState()
6795 mIsShiftDown
= IS_VK_DOWN(NS_VK_SHIFT
);
6796 mIsControlDown
= IS_VK_DOWN(NS_VK_CONTROL
);
6797 mIsAltDown
= IS_VK_DOWN(NS_VK_ALT
);
6801 PRInt32
nsWindow::GetWindowsVersion()
6806 static PRInt32 version
= 0;
6807 static PRBool didCheck
= PR_FALSE
;
6812 OSVERSIONINFOEX osInfo
;
6813 osInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
6814 // This cast is safe and supposed to be here, don't worry
6815 ::GetVersionEx((OSVERSIONINFO
*)&osInfo
);
6816 version
= (osInfo
.dwMajorVersion
& 0xff) << 8 | (osInfo
.dwMinorVersion
& 0xff);
6822 // Note that the result of GetTopLevelWindow method can be different from the
6823 // result of GetTopLevelHWND method. The result can be non-floating window.
6824 // Because our top level window may be contained in another window which is
6825 // not managed by us.
6826 nsWindow
* nsWindow::GetTopLevelWindow(PRBool aStopOnDialogOrPopup
)
6828 nsWindow
* curWindow
= this;
6831 if (aStopOnDialogOrPopup
) {
6832 switch (curWindow
->mWindowType
) {
6833 case eWindowType_dialog
:
6834 case eWindowType_popup
:
6839 // Retrieve the top level parent or owner window
6840 nsWindow
* parentWindow
= curWindow
->GetParentWindow(PR_TRUE
);
6845 curWindow
= parentWindow
;
6849 // Note that the result of GetTopLevelHWND can be different from the result
6850 // of GetTopLevelWindow method. Because this is checking whether the window
6851 // is top level only in Win32 window system. Therefore, the result window
6852 // may not be managed by us.
6853 HWND
nsWindow::GetTopLevelHWND(HWND aWnd
, PRBool aStopOnDialogOrPopup
)
6862 if (aStopOnDialogOrPopup
) {
6863 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
6865 VERIFY_WINDOW_STYLE(style
);
6867 if (!(style
& WS_CHILD
)) // first top-level window
6871 upWnd
= ::GetParent(curWnd
); // Parent or owner (if has no parent)
6874 // For dialog windows, we want just the parent, not the owner.
6875 // For other/popup windows, we want to find the first owner/parent
6876 // that's a dialog and/or has an owner.
6877 if (upWnd
&& ::GetWindow(curWnd
, GW_OWNER
) == upWnd
) {
6878 DWORD_PTR style
= ::GetWindowLongPtrW(curWnd
, GWL_STYLE
);
6879 if ((style
& WS_DLGFRAME
) != 0)
6890 static BOOL CALLBACK
gEnumWindowsProc(HWND hwnd
, LPARAM lParam
)
6893 ::GetWindowThreadProcessId(hwnd
, &pid
);
6894 if (pid
== GetCurrentProcessId() && ::IsWindowVisible(hwnd
))
6896 gWindowsVisible
= PR_TRUE
;
6902 PRBool
nsWindow::CanTakeFocus()
6904 gWindowsVisible
= PR_FALSE
;
6905 EnumWindows(gEnumWindowsProc
, 0);
6906 if (!gWindowsVisible
) {
6909 HWND fgWnd
= ::GetForegroundWindow();
6914 GetWindowThreadProcessId(fgWnd
, &pid
);
6915 if (pid
== GetCurrentProcessId()) {
6923 void nsWindow::InitTrackPointHack()
6925 // Init Trackpoint Hack
6929 const WCHAR wstrKeys
[][40] = {L
"Software\\Lenovo\\TrackPoint",
6930 L
"Software\\Lenovo\\UltraNav",
6931 L
"Software\\Synaptics\\SynTPEnh\\UltraNavPS2"};
6932 // If anything fails turn the hack off
6933 sTrackPointHack
= false;
6934 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
));
6935 if(NS_SUCCEEDED(rv
) && prefs
) {
6936 prefs
->GetIntPref("ui.trackpoint_hack.enabled", &lHackValue
);
6937 switch (lHackValue
) {
6938 // 0 means hack disabled
6941 // 1 means hack enabled
6943 sTrackPointHack
= true;
6945 // -1 means autodetect
6947 for(int i
= 0; i
< NS_ARRAY_LENGTH(wstrKeys
); i
++) {
6949 lResult
= ::RegOpenKeyExW(HKEY_CURRENT_USER
, (LPCWSTR
)&wstrKeys
[i
],
6950 0, KEY_READ
, &hKey
);
6951 ::RegCloseKey(hKey
);
6952 if(lResult
== ERROR_SUCCESS
) {
6953 // If we detected a registry key belonging to a TrackPoint driver
6955 sTrackPointHack
= true;
6960 // Shouldn't be any other values, but treat them as disabled
6967 #endif // #if !defined(WINCE)
6969 LPARAM
nsWindow::lParamToScreen(LPARAM lParam
)
6972 pt
.x
= GET_X_LPARAM(lParam
);
6973 pt
.y
= GET_Y_LPARAM(lParam
);
6974 ::ClientToScreen(mWnd
, &pt
);
6975 return MAKELPARAM(pt
.x
, pt
.y
);
6978 LPARAM
nsWindow::lParamToClient(LPARAM lParam
)
6981 pt
.x
= GET_X_LPARAM(lParam
);
6982 pt
.y
= GET_Y_LPARAM(lParam
);
6983 ::ScreenToClient(mWnd
, &pt
);
6984 return MAKELPARAM(pt
.x
, pt
.y
);
6987 /**************************************************************
6988 **************************************************************
6990 ** BLOCK: ChildWindow impl.
6992 ** Child window overrides.
6994 **************************************************************
6995 **************************************************************/
6997 // Deal with all sort of mouse event
6998 PRBool
ChildWindow::DispatchMouseEvent(PRUint32 aEventType
, WPARAM wParam
, LPARAM lParam
,
6999 PRBool aIsContextMenuKey
, PRInt16 aButton
)
7001 PRBool result
= PR_FALSE
;
7003 if (nsnull
== mEventCallback
) {
7007 switch (aEventType
) {
7008 case NS_MOUSE_BUTTON_DOWN
:
7009 CaptureMouse(PR_TRUE
);
7012 // NS_MOUSE_MOVE and NS_MOUSE_EXIT are here because we need to make sure capture flag
7013 // isn't left on after a drag where we wouldn't see a button up message (see bug 324131).
7014 case NS_MOUSE_BUTTON_UP
:
7017 if (!(wParam
& (MK_LBUTTON
| MK_MBUTTON
| MK_RBUTTON
)) && mIsInMouseCapture
)
7018 CaptureMouse(PR_FALSE
);
7026 return nsWindow::DispatchMouseEvent(aEventType
, wParam
, lParam
,
7027 aIsContextMenuKey
, aButton
);
7030 // return the style for a child nsWindow
7031 DWORD
ChildWindow::WindowStyle()
7033 DWORD style
= WS_CLIPCHILDREN
| nsWindow::WindowStyle();
7034 if (!(style
& WS_POPUP
))
7035 style
|= WS_CHILD
; // WS_POPUP and WS_CHILD are mutually exclusive.
7036 VERIFY_WINDOW_STYLE(style
);