2004-01-12 08:25:18 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2005-03-15 22:13:12 +00:00
|
|
|
/* vim:set ts=2 sts=2 sw=2 et cin: */
|
2001-09-28 20:14:13 +00:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
2004-04-18 22:01:16 +00:00
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
1998-04-13 20:24:54 +00:00
|
|
|
*
|
2004-04-18 22:01:16 +00:00
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
1998-04-13 20:24:54 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
1998-04-13 20:24:54 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2004-04-18 22:01:16 +00:00
|
|
|
* The Initial Developer of the Original Code is
|
2001-09-28 20:14:13 +00:00
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 03:40:37 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Contributor(s):
|
2002-02-27 01:30:40 +00:00
|
|
|
* Dean Tessman <dean_tessman@hotmail.com>
|
2009-03-27 01:10:52 +00:00
|
|
|
* Ere Maijala <emaijala@kolumbus.fi>
|
2002-02-27 01:30:40 +00:00
|
|
|
* Mark Hammond <markh@activestate.com>
|
2000-02-04 00:39:15 +00:00
|
|
|
* Michael Lowe <michael.lowe@bigfoot.com>
|
2000-12-19 03:01:31 +00:00
|
|
|
* Peter Bajusz <hyp-x@inf.bme.hu>
|
2000-12-20 01:43:38 +00:00
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
2000-03-21 03:42:00 +00:00
|
|
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
2002-07-03 00:55:47 +00:00
|
|
|
* Roy Yokoyama <yokoyama@netscape.com>
|
2002-12-06 03:41:43 +00:00
|
|
|
* Makoto Kato <m_kato@ga2.so-net.ne.jp>
|
2004-07-15 20:38:00 +00:00
|
|
|
* Masayuki Nakano <masayuki@d-toybox.com>
|
2004-07-27 19:14:44 +00:00
|
|
|
* Dainis Jonitis <Dainis_Jonitis@swh-t.lv>
|
2005-03-15 22:13:12 +00:00
|
|
|
* Christian Biesinger <cbiesinger@web.de>
|
2010-06-02 13:02:05 +00:00
|
|
|
* Mats Palmgren <matspal@gmail.com>
|
2009-02-10 20:56:51 +00:00
|
|
|
* Ningjie Chen <chenn@email.uc.edu>
|
2009-06-29 19:36:16 +00:00
|
|
|
* Jim Mathies <jmathies@mozilla.com>
|
2009-08-31 22:19:06 +00:00
|
|
|
* Kyle Huey <me@kylehuey.com>
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
2004-04-18 22:01:16 +00:00
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
2001-09-28 20:14:13 +00:00
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
2004-04-18 22:01:16 +00:00
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
2001-09-28 20:14:13 +00:00
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
2004-04-18 22:01:16 +00:00
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/*
|
2009-06-30 06:00:16 +00:00
|
|
|
* nsWindow - Native window management and event handling.
|
|
|
|
*
|
2009-06-29 19:36:16 +00:00
|
|
|
* nsWindow is organized into a set of major blocks and
|
|
|
|
* block subsections. The layout is as follows:
|
|
|
|
*
|
|
|
|
* Includes
|
|
|
|
* Variables
|
|
|
|
* nsIWidget impl.
|
|
|
|
* nsIWidget methods and utilities
|
|
|
|
* nsSwitchToUIThread impl.
|
|
|
|
* nsSwitchToUIThread methods and utilities
|
|
|
|
* Moz events
|
|
|
|
* Event initialization
|
|
|
|
* Event dispatching
|
|
|
|
* Native events
|
|
|
|
* Wndproc(s)
|
|
|
|
* Event processing
|
|
|
|
* OnEvent event handlers
|
|
|
|
* IME management and accessibility
|
|
|
|
* Transparency
|
|
|
|
* Popup hook handling
|
|
|
|
* Misc. utilities
|
|
|
|
* Child window impl.
|
|
|
|
*
|
|
|
|
* Search for "BLOCK:" to find major blocks.
|
|
|
|
* Search for "SECTION:" to find specific sections.
|
|
|
|
*
|
|
|
|
* Blocks should be split out into separate files if they
|
|
|
|
* become unmanageable.
|
|
|
|
*
|
|
|
|
* Related source:
|
|
|
|
*
|
|
|
|
* nsWindowDefs.h - Definitions, macros, structs, enums
|
|
|
|
* and general setup.
|
|
|
|
* nsWindowDbg.h/.cpp - Debug related code and directives.
|
|
|
|
* nsWindowGfx.h/.cpp - Graphics and painting.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Includes
|
|
|
|
**
|
|
|
|
** Include headers.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
2010-02-09 22:34:38 +00:00
|
|
|
#include "mozilla/ipc/RPCChannel.h"
|
2009-11-06 22:33:12 +00:00
|
|
|
|
2011-10-11 05:50:08 +00:00
|
|
|
/* This must occur *after* ipc/RPCChannel.h to avoid typedefs conflicts. */
|
|
|
|
#include "mozilla/Util.h"
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsWindow.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
#include <process.h>
|
|
|
|
#include <commctrl.h>
|
|
|
|
#include <unknwn.h>
|
|
|
|
|
|
|
|
#include "prlog.h"
|
|
|
|
#include "prtime.h"
|
|
|
|
#include "prprf.h"
|
|
|
|
#include "prmem.h"
|
|
|
|
|
2011-03-03 16:20:02 +00:00
|
|
|
#include "mozilla/WidgetTraceEvent.h"
|
1998-07-29 18:51:45 +00:00
|
|
|
#include "nsIAppShell.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsISupportsPrimitives.h"
|
2011-08-26 07:43:56 +00:00
|
|
|
#include "nsIDOMMouseEvent.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsITheme.h"
|
2006-02-23 17:02:45 +00:00
|
|
|
#include "nsIObserverService.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsIScreenManager.h"
|
2005-03-15 22:13:12 +00:00
|
|
|
#include "imgIContainer.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsIFile.h"
|
|
|
|
#include "nsIRollupListener.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIClipboard.h"
|
|
|
|
#include "nsIMM32Handler.h"
|
|
|
|
#include "nsILocalFile.h"
|
2011-04-08 01:05:49 +00:00
|
|
|
#include "nsFontMetrics.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsIFontEnumerator.h"
|
|
|
|
#include "nsGUIEvent.h"
|
|
|
|
#include "nsFont.h"
|
|
|
|
#include "nsRect.h"
|
|
|
|
#include "nsThreadUtils.h"
|
2005-02-01 19:24:59 +00:00
|
|
|
#include "nsNativeCharsetUtils.h"
|
2011-10-14 18:11:22 +00:00
|
|
|
#include "nsGkAtoms.h"
|
2008-04-30 04:12:15 +00:00
|
|
|
#include "nsUnicharUtils.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
|
|
#include "nsXPIDLString.h"
|
|
|
|
#include "nsWidgetsCID.h"
|
2009-07-22 00:45:13 +00:00
|
|
|
#include "nsTHashtable.h"
|
|
|
|
#include "nsHashKeys.h"
|
2009-08-31 22:19:06 +00:00
|
|
|
#include "nsString.h"
|
Bug 560095 - Use mozilla::services::GetObserverService(). r=biesi,dveditz,gavin,josh,jst,mrbkap,roc,sdwilsh,shaver,sicking,smontagu,surkov
2010-04-29 16:59:13 +00:00
|
|
|
#include "mozilla/Services.h"
|
2010-08-10 01:49:35 +00:00
|
|
|
#include "nsNativeThemeWin.h"
|
2010-11-12 02:39:05 +00:00
|
|
|
#include "nsWindowsDllInterceptor.h"
|
2010-12-07 02:06:31 +00:00
|
|
|
#include "nsIWindowMediator.h"
|
|
|
|
#include "nsIServiceManager.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsWindowGfx.h"
|
2010-02-26 06:36:07 +00:00
|
|
|
#include "gfxWindowsPlatform.h"
|
2010-03-31 03:02:58 +00:00
|
|
|
#include "Layers.h"
|
2011-08-25 08:46:01 +00:00
|
|
|
#include "nsPrintfCString.h"
|
2011-05-28 07:03:00 +00:00
|
|
|
#include "mozilla/Preferences.h"
|
2011-09-08 15:24:43 +00:00
|
|
|
#include "nsISound.h"
|
2011-11-03 14:39:50 +00:00
|
|
|
#include "WinTaskbar.h"
|
2012-01-04 10:21:44 +00:00
|
|
|
#include "WinUtils.h"
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2010-06-06 10:37:44 +00:00
|
|
|
#ifdef MOZ_ENABLE_D3D9_LAYER
|
2010-05-24 15:28:54 +00:00
|
|
|
#include "LayerManagerD3D9.h"
|
2010-06-06 10:37:44 +00:00
|
|
|
#endif
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2010-09-30 22:53:53 +00:00
|
|
|
#ifdef MOZ_ENABLE_D3D10_LAYER
|
|
|
|
#include "LayerManagerD3D10.h"
|
|
|
|
#endif
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2010-05-24 15:28:54 +00:00
|
|
|
#include "LayerManagerOGL.h"
|
2011-01-18 20:11:19 +00:00
|
|
|
#include "nsIGfxInfo.h"
|
2010-08-14 06:34:13 +00:00
|
|
|
#include "BasicLayers.h"
|
2009-03-25 00:51:57 +00:00
|
|
|
#include "nsUXThemeConstants.h"
|
2010-07-27 12:47:42 +00:00
|
|
|
#include "KeyboardLayout.h"
|
2009-01-05 18:17:44 +00:00
|
|
|
#include "nsNativeDragTarget.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
|
2009-01-05 18:17:44 +00:00
|
|
|
#include <zmouse.h>
|
2009-08-10 09:14:01 +00:00
|
|
|
#include <richedit.h>
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#if defined(ACCESSIBILITY)
|
2009-08-10 09:14:01 +00:00
|
|
|
#include "oleidl.h"
|
2007-11-09 18:38:07 +00:00
|
|
|
#include <winuser.h>
|
2010-07-21 04:12:08 +00:00
|
|
|
#include "nsIAccessibleDocument.h"
|
2009-06-29 19:36:16 +00:00
|
|
|
#if !defined(WINABLEAPI)
|
2007-11-09 18:38:07 +00:00
|
|
|
#include <winable.h>
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif // !defined(WINABLEAPI)
|
|
|
|
#endif // defined(ACCESSIBILITY)
|
2001-04-01 01:38:35 +00:00
|
|
|
|
2009-10-06 02:26:54 +00:00
|
|
|
#include "nsIWinTaskbar.h"
|
2011-09-01 14:15:09 +00:00
|
|
|
#define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
|
2009-10-06 02:26:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#if defined(NS_ENABLE_TSF)
|
|
|
|
#include "nsTextStore.h"
|
|
|
|
#endif // defined(NS_ENABLE_TSF)
|
|
|
|
|
|
|
|
// Windowless plugin support
|
2009-09-17 01:30:26 +00:00
|
|
|
#include "npapi.h"
|
1999-06-11 22:48:50 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#include "nsWindowDefs.h"
|
1999-07-09 19:41:46 +00:00
|
|
|
|
2010-05-19 23:22:19 +00:00
|
|
|
#include "mozilla/FunctionTimer.h"
|
2011-02-12 01:56:11 +00:00
|
|
|
#include "nsCrashOnException.h"
|
2010-08-28 02:44:37 +00:00
|
|
|
#include "nsIXULRuntime.h"
|
|
|
|
|
2011-11-09 21:49:21 +00:00
|
|
|
#include "nsIContent.h"
|
|
|
|
|
2010-07-27 12:47:42 +00:00
|
|
|
using namespace mozilla::widget;
|
2010-12-05 15:02:17 +00:00
|
|
|
using namespace mozilla::layers;
|
2011-05-28 07:03:00 +00:00
|
|
|
using namespace mozilla;
|
2010-07-27 12:47:42 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Variables
|
|
|
|
**
|
|
|
|
** nsWindow Class static initializations and global variables.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2000-01-21 21:56:09 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsWindow statics
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sDropShadowEnabled = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
PRUint32 nsWindow::sInstanceCount = 0;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sSwitchKeyboardLayout = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
BOOL nsWindow::sIsOleInitialized = FALSE;
|
|
|
|
HCURSOR nsWindow::sHCursor = NULL;
|
|
|
|
imgIContainer* nsWindow::sCursorImgContainer = nsnull;
|
|
|
|
nsWindow* nsWindow::sCurrentWindow = nsnull;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sJustGotDeactivate = false;
|
|
|
|
bool nsWindow::sJustGotActivate = false;
|
|
|
|
bool nsWindow::sIsInMouseCapture = false;
|
2001-12-17 22:51:39 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// imported in nsWidgetFactory.cpp
|
|
|
|
TriStateBool nsWindow::sCanQuit = TRI_UNKNOWN;
|
|
|
|
|
|
|
|
// Hook Data Memebers for Dropdowns. sProcessHook Tells the
|
|
|
|
// hook methods whether they should be processing the hook
|
|
|
|
// messages.
|
|
|
|
HHOOK nsWindow::sMsgFilterHook = NULL;
|
|
|
|
HHOOK nsWindow::sCallProcHook = NULL;
|
|
|
|
HHOOK nsWindow::sCallMouseHook = NULL;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sProcessHook = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
UINT nsWindow::sRollupMsgId = 0;
|
|
|
|
HWND nsWindow::sRollupMsgWnd = NULL;
|
|
|
|
UINT nsWindow::sHookTimerId = 0;
|
|
|
|
|
|
|
|
// Rollup Listener
|
|
|
|
nsIRollupListener* nsWindow::sRollupListener = nsnull;
|
|
|
|
nsIWidget* nsWindow::sRollupWidget = nsnull;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sRollupConsumeEvent = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
// Mouse Clicks - static variable definitions for figuring
|
|
|
|
// out 1 - 3 Clicks.
|
|
|
|
POINT nsWindow::sLastMousePoint = {0};
|
|
|
|
POINT nsWindow::sLastMouseMovePoint = {0};
|
|
|
|
LONG nsWindow::sLastMouseDownTime = 0L;
|
|
|
|
LONG nsWindow::sLastClickCount = 0L;
|
|
|
|
BYTE nsWindow::sLastMouseButton = 0;
|
|
|
|
|
|
|
|
// Trim heap on minimize. (initialized, but still true.)
|
|
|
|
int nsWindow::sTrimOnMinimize = 2;
|
2001-04-14 00:57:30 +00:00
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
// Default value for Trackpoint hack (used when the pref is set to -1).
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sDefaultTrackPointHack = false;
|
2010-11-08 09:06:13 +00:00
|
|
|
// Default value for general window class (used when the pref is the empty string).
|
|
|
|
const char* nsWindow::sDefaultMainWindowClass = kClassNameGeneral;
|
2011-06-22 20:48:24 +00:00
|
|
|
// Whether to enable the Elantech swipe gesture hack.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sUseElantechSwipeHack = false;
|
2011-06-22 20:48:24 +00:00
|
|
|
// Whether to enable the Elantech pinch-to-zoom gesture hack.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sUseElantechPinchHack = false;
|
2010-11-08 09:06:13 +00:00
|
|
|
|
2010-12-07 02:06:31 +00:00
|
|
|
// If we're using D3D9, this will not be allowed during initial 5 seconds.
|
|
|
|
bool nsWindow::sAllowD3D9 = false;
|
2009-10-07 04:19:04 +00:00
|
|
|
|
2011-03-02 11:53:55 +00:00
|
|
|
TriStateBool nsWindow::sHasBogusPopupsDropShadowOnMultiMonitor = TRI_UNKNOWN;
|
|
|
|
|
2010-01-26 21:40:15 +00:00
|
|
|
// Used in OOPP plugin focus processing.
|
|
|
|
const PRUnichar* kOOPPPluginFocusEventId = L"OOPP Plugin Focus Widget Event";
|
|
|
|
PRUint32 nsWindow::sOOPPPluginFocusEvent =
|
|
|
|
RegisterWindowMessageW(kOOPPPluginFocusEventId);
|
|
|
|
|
2011-01-14 13:38:57 +00:00
|
|
|
MSG nsWindow::sRedirectedKeyDown;
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sEnablePixelScrolling = true;
|
|
|
|
bool nsWindow::sNeedsToInitMouseWheelSettings = true;
|
2011-05-17 00:23:23 +00:00
|
|
|
ULONG nsWindow::sMouseWheelScrollLines = 0;
|
|
|
|
ULONG nsWindow::sMouseWheelScrollChars = 0;
|
|
|
|
|
|
|
|
HWND nsWindow::sLastMouseWheelWnd = NULL;
|
|
|
|
PRInt32 nsWindow::sRemainingDeltaForScroll = 0;
|
|
|
|
PRInt32 nsWindow::sRemainingDeltaForPixel = 0;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::sLastMouseWheelDeltaIsPositive = false;
|
|
|
|
bool nsWindow::sLastMouseWheelOrientationIsVertical = false;
|
|
|
|
bool nsWindow::sLastMouseWheelUnitIsPage = false;
|
2011-05-17 00:23:23 +00:00
|
|
|
PRUint32 nsWindow::sLastMouseWheelTime = 0;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: globals variables
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2002-02-27 02:18:12 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
|
|
|
|
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
PRLogModuleInfo* gWindowsLog = nsnull;
|
|
|
|
#endif
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Kbd layout. Used throughout character processing.
|
2010-07-22 02:11:34 +00:00
|
|
|
static KeyboardLayout gKbdLayout;
|
2009-08-26 16:07:15 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Global user preference for disabling native theme. Used
|
|
|
|
// in NativeWindowTheme.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool gDisableNativeTheme = false;
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Global used in Show window enumerations.
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool gWindowsVisible = false;
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2011-11-08 19:59:09 +00:00
|
|
|
// True if we have sent a notification that we are suspending/sleeping.
|
|
|
|
static bool gIsSleepMode = false;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2010-11-12 02:39:05 +00:00
|
|
|
// General purpose user32.dll hook object
|
|
|
|
static WindowsDllInterceptor sUser32Intercept;
|
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
// 2 pixel offset for eTransparencyBorderlessGlass which equals the size of
|
|
|
|
// the default window border Windows paints. Glass will be extended inward
|
|
|
|
// this distance to remove the border.
|
2011-01-27 22:58:58 +00:00
|
|
|
static const PRInt32 kGlassMarginAdjustment = 2;
|
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
// When the client area is extended out into the default window frame area,
|
|
|
|
// this is the minimum amount of space along the edge of resizable windows
|
|
|
|
// we will always display a resize cursor in, regardless of the underlying
|
|
|
|
// content.
|
|
|
|
static const PRInt32 kResizableBorderMinSize = 3;
|
2011-10-04 01:20:43 +00:00
|
|
|
|
|
|
|
// We should never really try to accelerate windows bigger than this. In some
|
|
|
|
// cases this might lead to no D3D9 acceleration where we could have had it
|
|
|
|
// but D3D9 does not reliably report when it supports bigger windows. 8192
|
|
|
|
// is as safe as we can get, we know at least D3D10 hardware always supports
|
|
|
|
// this, other hardware we expect to report correctly in D3D9.
|
|
|
|
#define MAX_ACCELERATED_DIMENSION 8192
|
|
|
|
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: nsIWidget impl.
|
|
|
|
**
|
|
|
|
** nsIWidget interface implementation, broken down into
|
|
|
|
** sections.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsWindow construction and destruction
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsWindow::nsWindow() : nsBaseWidget()
|
2009-04-23 00:48:30 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef PR_LOGGING
|
2011-08-16 19:30:44 +00:00
|
|
|
if (!gWindowsLog) {
|
|
|
|
gWindowsLog = PR_NewLogModule("nsWindow");
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
mWnd = nsnull;
|
|
|
|
mPaintDC = nsnull;
|
|
|
|
mPrevWndProc = nsnull;
|
|
|
|
mNativeDragTarget = nsnull;
|
2011-10-02 02:16:19 +00:00
|
|
|
mInDtor = false;
|
|
|
|
mIsVisible = false;
|
|
|
|
mIsTopWidgetWindow = false;
|
|
|
|
mUnicodeWidget = true;
|
|
|
|
mDisplayPanFeedback = false;
|
|
|
|
mTouchWindow = false;
|
|
|
|
mCustomNonClient = false;
|
|
|
|
mHideChrome = false;
|
|
|
|
mFullscreenMode = false;
|
|
|
|
mMousePresent = false;
|
2011-12-07 19:01:48 +00:00
|
|
|
mDestroyCalled = false;
|
|
|
|
mPickerDisplayCount = 0;
|
2009-06-29 19:36:16 +00:00
|
|
|
mWindowType = eWindowType_child;
|
|
|
|
mBorderStyle = eBorderStyle_default;
|
|
|
|
mPopupType = ePopupTypeAny;
|
2010-06-28 06:04:20 +00:00
|
|
|
mOldSizeMode = nsSizeMode_Normal;
|
2009-06-29 19:36:16 +00:00
|
|
|
mLastPoint.x = 0;
|
|
|
|
mLastPoint.y = 0;
|
|
|
|
mLastSize.width = 0;
|
|
|
|
mLastSize.height = 0;
|
|
|
|
mOldStyle = 0;
|
|
|
|
mOldExStyle = 0;
|
|
|
|
mPainting = 0;
|
|
|
|
mLastKeyboardLayout = 0;
|
2011-02-12 01:56:13 +00:00
|
|
|
mAssumeWheelIsZoomUntil = 0;
|
2009-06-29 19:36:16 +00:00
|
|
|
mBlurSuppressLevel = 0;
|
2012-02-06 10:24:29 +00:00
|
|
|
mLastPaintEndTime = TimeStamp::Now();
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
mTransparentSurface = nsnull;
|
|
|
|
mMemoryDC = nsnull;
|
|
|
|
mTransparencyMode = eTransparencyOpaque;
|
2010-03-17 22:56:00 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
|
|
|
memset(&mGlassMargins, 0, sizeof mGlassMargins);
|
|
|
|
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif
|
|
|
|
mBackground = ::GetSysColor(COLOR_BTNFACE);
|
|
|
|
mBrush = ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground));
|
|
|
|
mForeground = ::GetSysColor(COLOR_WINDOWTEXT);
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-10-06 02:26:54 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
|
|
|
mTaskbarPreview = nsnull;
|
2011-10-02 02:16:19 +00:00
|
|
|
mHasTaskbarIconBeenCreated = false;
|
2009-10-06 02:26:54 +00:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Global initialization
|
|
|
|
if (!sInstanceCount) {
|
2011-11-03 14:39:50 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
|
|
|
// Global app registration id for Win7 and up. See
|
|
|
|
// WinTaskbar.cpp for details.
|
|
|
|
mozilla::widget::WinTaskbar::RegisterAppUserModelID();
|
|
|
|
#endif
|
|
|
|
|
2010-08-10 01:49:35 +00:00
|
|
|
gKbdLayout.LoadLayout(::GetKeyboardLayout(0));
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2010-08-10 01:49:35 +00:00
|
|
|
// Init IME handler
|
|
|
|
nsIMM32Handler::Initialize();
|
2009-02-16 01:09:11 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef NS_ENABLE_TSF
|
2010-08-10 01:49:35 +00:00
|
|
|
nsTextStore::Initialize();
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif
|
2009-03-09 05:08:41 +00:00
|
|
|
|
2010-08-10 01:49:35 +00:00
|
|
|
if (SUCCEEDED(::OleInitialize(NULL)))
|
|
|
|
sIsOleInitialized = TRUE;
|
|
|
|
NS_ASSERTION(sIsOleInitialized, "***** OLE is not initialized!\n");
|
2009-01-05 18:17:44 +00:00
|
|
|
|
2011-01-24 21:38:41 +00:00
|
|
|
InitInputWorkaroundPrefDefaults();
|
2010-08-10 01:49:35 +00:00
|
|
|
|
|
|
|
// Init titlebar button info for custom frames.
|
2010-08-10 01:49:35 +00:00
|
|
|
nsUXThemeData::InitTitlebarInfo();
|
2010-10-09 20:53:44 +00:00
|
|
|
// Init theme data
|
|
|
|
nsUXThemeData::UpdateNativeThemeInfo();
|
2011-01-14 13:38:57 +00:00
|
|
|
|
|
|
|
ForgetRedirectedKeyDownMessage();
|
2009-06-29 19:36:16 +00:00
|
|
|
} // !sInstanceCount
|
2009-03-24 01:10:36 +00:00
|
|
|
|
2010-04-16 17:37:16 +00:00
|
|
|
mIdleService = nsnull;
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
sInstanceCount++;
|
2009-04-14 05:27:39 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsWindow::~nsWindow()
|
2009-03-24 01:10:36 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
mInDtor = true;
|
2006-03-17 21:42:28 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// If the widget was released without calling Destroy() then the native window still
|
|
|
|
// exists, and we need to destroy it. This will also result in a call to OnDestroy.
|
|
|
|
//
|
|
|
|
// XXX How could this happen???
|
|
|
|
if (NULL != mWnd)
|
2009-06-29 19:36:16 +00:00
|
|
|
Destroy();
|
2009-01-05 18:17:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
sInstanceCount--;
|
2009-01-05 18:17:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Global shutdown
|
2009-06-30 06:00:16 +00:00
|
|
|
if (sInstanceCount == 0) {
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::Terminate();
|
|
|
|
#endif
|
|
|
|
NS_IF_RELEASE(sCursorImgContainer);
|
|
|
|
if (sIsOleInitialized) {
|
|
|
|
::OleFlushClipboard();
|
|
|
|
::OleUninitialize();
|
|
|
|
sIsOleInitialized = FALSE;
|
|
|
|
}
|
|
|
|
// delete any of the IME structures that we allocated
|
|
|
|
nsIMM32Handler::Terminate();
|
2009-01-05 18:17:44 +00:00
|
|
|
}
|
2009-06-30 06:00:16 +00:00
|
|
|
|
|
|
|
NS_IF_RELEASE(mNativeDragTarget);
|
2009-01-05 18:17:44 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Create, nsIWidget::Destroy
|
|
|
|
*
|
|
|
|
* Creating and destroying windows for this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Allow Derived classes to modify the height that is passed
|
2011-04-25 03:10:12 +00:00
|
|
|
// when the window is created or resized.
|
2009-06-29 19:36:16 +00:00
|
|
|
PRInt32 nsWindow::GetHeight(PRInt32 aProposedHeight)
|
2007-08-06 17:45:57 +00:00
|
|
|
{
|
2011-04-25 03:10:12 +00:00
|
|
|
return aProposedHeight;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1999-03-23 21:26:20 +00:00
|
|
|
|
2009-09-24 06:18:10 +00:00
|
|
|
// Create the proper widget
|
2009-06-29 19:36:16 +00:00
|
|
|
nsresult
|
2009-09-24 06:18:10 +00:00
|
|
|
nsWindow::Create(nsIWidget *aParent,
|
|
|
|
nsNativeWidget aNativeParent,
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
EVENT_CALLBACK aHandleEventFunction,
|
2011-04-17 01:22:44 +00:00
|
|
|
nsDeviceContext *aContext,
|
2009-09-24 06:18:10 +00:00
|
|
|
nsWidgetInitData *aInitData)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2010-08-20 19:29:01 +00:00
|
|
|
nsWidgetInitData defaultInitData;
|
|
|
|
if (!aInitData)
|
|
|
|
aInitData = &defaultInitData;
|
2009-09-24 06:18:10 +00:00
|
|
|
|
2010-08-20 19:29:01 +00:00
|
|
|
mUnicodeWidget = aInitData->mUnicode;
|
|
|
|
|
|
|
|
nsIWidget *baseParent = aInitData->mWindowType == eWindowType_dialog ||
|
2009-06-29 19:36:16 +00:00
|
|
|
aInitData->mWindowType == eWindowType_toplevel ||
|
2010-08-20 19:29:01 +00:00
|
|
|
aInitData->mWindowType == eWindowType_invisible ?
|
|
|
|
nsnull : aParent;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
mIsTopWidgetWindow = (nsnull == baseParent);
|
2010-10-08 18:51:50 +00:00
|
|
|
mBounds = aRect;
|
2004-09-08 19:30:22 +00:00
|
|
|
|
2011-10-25 15:05:32 +00:00
|
|
|
// Ensure that the toolkit is created.
|
|
|
|
nsToolkit::GetToolkit();
|
|
|
|
|
|
|
|
BaseCreate(baseParent, aRect, aHandleEventFunction, aContext, aInitData);
|
2008-12-06 09:27:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
HWND parent;
|
2010-06-02 13:02:05 +00:00
|
|
|
if (aParent) { // has a nsIWidget parent
|
|
|
|
parent = aParent ? (HWND)aParent->GetNativeData(NS_NATIVE_WINDOW) : NULL;
|
|
|
|
mParent = aParent;
|
2009-06-29 19:36:16 +00:00
|
|
|
} else { // has a nsNative parent
|
|
|
|
parent = (HWND)aNativeParent;
|
2012-01-04 10:21:44 +00:00
|
|
|
mParent = aNativeParent ?
|
|
|
|
WinUtils::GetNSWindowPtr((HWND)aNativeParent) : nsnull;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2010-08-20 19:29:01 +00:00
|
|
|
mPopupType = aInitData->mPopupHint;
|
2010-09-02 18:20:56 +00:00
|
|
|
mIsRTL = aInitData->mRTL;
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
DWORD style = WindowStyle();
|
|
|
|
DWORD extendedStyle = WindowExStyle();
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWindowType == eWindowType_popup) {
|
2010-07-27 13:38:03 +00:00
|
|
|
if (!aParent)
|
2009-06-29 19:36:16 +00:00
|
|
|
parent = NULL;
|
2011-04-26 01:37:20 +00:00
|
|
|
|
|
|
|
if (aInitData->mIsDragPopup) {
|
|
|
|
// This flag makes the window transparent to mouse events
|
|
|
|
extendedStyle |= WS_EX_TRANSPARENT;
|
|
|
|
}
|
2009-08-25 19:00:46 +00:00
|
|
|
} else if (mWindowType == eWindowType_invisible) {
|
|
|
|
// Make sure CreateWindowEx succeeds at creating a toplevel window
|
2009-08-25 20:13:23 +00:00
|
|
|
style &= ~0x40000000; // WS_CHILDWINDOW
|
2010-08-20 19:29:01 +00:00
|
|
|
} else {
|
2009-06-29 19:36:16 +00:00
|
|
|
// See if the caller wants to explictly set clip children and clip siblings
|
|
|
|
if (aInitData->clipChildren) {
|
|
|
|
style |= WS_CLIPCHILDREN;
|
|
|
|
} else {
|
|
|
|
style &= ~WS_CLIPCHILDREN;
|
|
|
|
}
|
|
|
|
if (aInitData->clipSiblings) {
|
|
|
|
style |= WS_CLIPSIBLINGS;
|
|
|
|
}
|
|
|
|
}
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
nsAutoString className;
|
|
|
|
if (aInitData->mDropShadow) {
|
|
|
|
GetWindowPopupClass(className);
|
|
|
|
} else {
|
|
|
|
GetWindowClass(className);
|
|
|
|
}
|
2011-08-31 19:19:03 +00:00
|
|
|
// Plugins are created in the disabled state so that they can't
|
|
|
|
// steal focus away from our main window. This is especially
|
|
|
|
// important if the plugin has loaded in a background tab.
|
|
|
|
if(aInitData->mWindowType == eWindowType_plugin) {
|
|
|
|
style |= WS_DISABLED;
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
mWnd = ::CreateWindowExW(extendedStyle,
|
2010-11-08 09:06:13 +00:00
|
|
|
className.get(),
|
2009-06-29 19:36:16 +00:00
|
|
|
L"",
|
|
|
|
style,
|
|
|
|
aRect.x,
|
|
|
|
aRect.y,
|
|
|
|
aRect.width,
|
|
|
|
GetHeight(aRect.height),
|
|
|
|
parent,
|
|
|
|
NULL,
|
|
|
|
nsToolkit::mDllInstance,
|
|
|
|
NULL);
|
2008-12-06 09:27:30 +00:00
|
|
|
|
2010-06-25 02:01:06 +00:00
|
|
|
if (!mWnd) {
|
|
|
|
NS_WARNING("nsWindow CreateWindowEx failed.");
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2010-06-25 02:01:06 +00:00
|
|
|
}
|
2007-08-10 19:01:48 +00:00
|
|
|
|
2010-09-07 21:40:05 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2010-09-07 21:25:30 +00:00
|
|
|
if (mIsRTL && nsUXThemeData::dwmSetWindowAttributePtr) {
|
|
|
|
DWORD dwAttribute = TRUE;
|
|
|
|
nsUXThemeData::dwmSetWindowAttributePtr(mWnd, DWMWA_NONCLIENT_RTL_LAYOUT, &dwAttribute, sizeof dwAttribute);
|
|
|
|
}
|
2010-09-07 21:40:05 +00:00
|
|
|
#endif
|
2010-09-07 21:25:30 +00:00
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
if (mWindowType != eWindowType_plugin &&
|
|
|
|
mWindowType != eWindowType_invisible &&
|
|
|
|
UseTrackPointHack()) {
|
2010-12-28 10:16:43 +00:00
|
|
|
// Ugly Thinkpad Driver Hack (Bugs 507222 and 594977)
|
|
|
|
//
|
|
|
|
// We create two zero-sized windows as descendants of the top-level window,
|
|
|
|
// like so:
|
|
|
|
//
|
|
|
|
// Top-level window (MozillaWindowClass)
|
|
|
|
// FAKETRACKPOINTSCROLLCONTAINER (MozillaWindowClass)
|
|
|
|
// FAKETRACKPOINTSCROLLABLE (MozillaWindowClass)
|
|
|
|
//
|
|
|
|
// We need to have the middle window, otherwise the Trackpoint driver
|
|
|
|
// will fail to deliver scroll messages. WM_MOUSEWHEEL messages are
|
|
|
|
// sent to the FAKETRACKPOINTSCROLLABLE, which then propagate up the
|
|
|
|
// window hierarchy until they are handled by nsWindow::WindowProc.
|
|
|
|
// WM_HSCROLL messages are also sent to the FAKETRACKPOINTSCROLLABLE,
|
|
|
|
// but these do not propagate automatically, so we have the window
|
|
|
|
// procedure pretend that they were dispatched to the top-level window
|
|
|
|
// instead.
|
|
|
|
//
|
|
|
|
// The FAKETRACKPOINTSCROLLABLE needs to have the specific window styles it
|
|
|
|
// is given below so that it catches the Trackpoint driver's heuristics.
|
|
|
|
HWND scrollContainerWnd = ::CreateWindowW
|
|
|
|
(className.get(), L"FAKETRACKPOINTSCROLLCONTAINER",
|
|
|
|
WS_CHILD | WS_VISIBLE,
|
|
|
|
0, 0, 0, 0, mWnd, NULL, nsToolkit::mDllInstance, NULL);
|
|
|
|
HWND scrollableWnd = ::CreateWindowW
|
|
|
|
(className.get(), L"FAKETRACKPOINTSCROLLABLE",
|
|
|
|
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | 0x30,
|
|
|
|
0, 0, 0, 0, scrollContainerWnd, NULL, nsToolkit::mDllInstance, NULL);
|
|
|
|
|
|
|
|
// Give the FAKETRACKPOINTSCROLLABLE window a specific ID so that
|
|
|
|
// WindowProcInternal can distinguish it from the top-level window
|
|
|
|
// easily.
|
|
|
|
::SetWindowLongPtrW(scrollableWnd, GWLP_ID, eFakeTrackPointScrollableID);
|
|
|
|
|
|
|
|
// Make FAKETRACKPOINTSCROLLABLE use nsWindow::WindowProc, and store the
|
|
|
|
// old window procedure in its "user data".
|
|
|
|
WNDPROC oldWndProc;
|
|
|
|
if (mUnicodeWidget)
|
|
|
|
oldWndProc = (WNDPROC)::SetWindowLongPtrW(scrollableWnd, GWLP_WNDPROC,
|
|
|
|
(LONG_PTR)nsWindow::WindowProc);
|
|
|
|
else
|
|
|
|
oldWndProc = (WNDPROC)::SetWindowLongPtrA(scrollableWnd, GWLP_WNDPROC,
|
|
|
|
(LONG_PTR)nsWindow::WindowProc);
|
|
|
|
::SetWindowLongPtrW(scrollableWnd, GWLP_USERDATA, (LONG_PTR)oldWndProc);
|
2009-09-24 09:32:20 +00:00
|
|
|
}
|
2009-08-31 22:19:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// call the event callback to notify about creation
|
2002-02-16 01:44:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchStandardEvent(NS_CREATE);
|
|
|
|
SubclassWindow(TRUE);
|
2005-04-13 05:52:02 +00:00
|
|
|
|
2011-05-27 22:35:42 +00:00
|
|
|
// If the internal variable set by the config.trim_on_minimize pref has not
|
|
|
|
// been initialized, and if this is the hidden window (conveniently created
|
|
|
|
// before any visible windows, and after the profile has been initialized),
|
|
|
|
// do some initialization work.
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sTrimOnMinimize == 2 && mWindowType == eWindowType_invisible) {
|
2011-05-27 22:35:42 +00:00
|
|
|
// Our internal trim prevention logic is effective on 2K/XP at maintaining
|
|
|
|
// the working set when windows are minimized, but on Vista and up it has
|
|
|
|
// little to no effect. Since this feature has been the source of numerous
|
|
|
|
// bugs over the years, disable it (sTrimOnMinimize=1) on Vista and up.
|
2011-05-28 07:03:00 +00:00
|
|
|
sTrimOnMinimize =
|
|
|
|
Preferences::GetBool("config.trim_on_minimize",
|
2012-01-04 10:21:44 +00:00
|
|
|
(WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION)) ? 1 : 0;
|
2011-05-28 07:03:00 +00:00
|
|
|
sSwitchKeyboardLayout =
|
2011-09-29 06:19:26 +00:00
|
|
|
Preferences::GetBool("intl.keyboard.per_window_layout", false);
|
2011-05-28 07:03:00 +00:00
|
|
|
gDisableNativeTheme =
|
2011-09-29 06:19:26 +00:00
|
|
|
Preferences::GetBool("mozilla.widget.disable-native-theme", false);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
landing keyEvent_19991004_BRANCH
bugs # see the log of the check in into branch
author/reviewer:
mozilla/layout/base/src/nsRangeList.cpp brade/mjudge
mozilla/layout/html/forms/src/nsGfxTextControlFrame.cpp brade/ftang
mozilla/layout/events/src/nsDOMEvent.cpp brade/joki
mozilla/layout/events/src/nsEventStateManager.cpp brade/joki
mozilla/widget/public/nsGUIEvent.h akkana/ftang
mozilla/widget/src/windows/nsWindow.cpp ftang/mjudge
mozilla/widget/src/windows/nsWindow.h ftang/mjudge
mozilla/widget/src/mac/nsTextAreaWidget.cpp brade/ftang
mozilla/widget/src/mac/nsMacEventHandler.cpp brade/simon
mozilla/widget/src/xpwidgets/nsKeyBindMgr.cpp brade/ftang
mozilla/widget/src/gtk/nsGtkEventHandler.cpp akkana/?
mozilla/widget/src/gtk/nsWidget.cpp erik/ftang
mozilla/layout/xul/base/src/nsTreeCellFrame.cpp brade/ftang
mozilla/editor/base/nsEditorEventListeners.cpp brade/akkana
mozilla/editor/base/nsHTMLEditor.cpp brade/akkana
mozilla/rdf/content/src/nsXULKeyListener.cpp ftang/saari
fix the master bug- 15693
fix at least, but not limited to, the following bugs
10158,11956,6053,9333,10901,14348,6449,11845,13016,14410,15657,15307,15842,13856
1999-10-14 18:27:01 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-12-06 03:41:43 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// Close this nsWindow
|
|
|
|
NS_METHOD nsWindow::Destroy()
|
|
|
|
{
|
2011-08-25 15:19:56 +00:00
|
|
|
// WM_DESTROY has already fired, avoid calling it twice
|
|
|
|
if (mOnDestroyCalled)
|
2009-07-13 15:58:19 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
2011-12-07 19:01:48 +00:00
|
|
|
// Don't destroy windows that have file pickers open, we'll tear these down
|
|
|
|
// later once the picker is closed.
|
|
|
|
mDestroyCalled = true;
|
|
|
|
if (mPickerDisplayCount)
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// During the destruction of all of our children, make sure we don't get deleted.
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
|
|
|
|
2010-03-31 03:02:58 +00:00
|
|
|
/**
|
|
|
|
* On windows the LayerManagerOGL destructor wants the widget to be around for
|
|
|
|
* cleanup. It also would like to have the HWND intact, so we NULL it here.
|
|
|
|
*/
|
2010-08-07 05:09:18 +00:00
|
|
|
if (mLayerManager) {
|
|
|
|
mLayerManager->Destroy();
|
|
|
|
}
|
|
|
|
mLayerManager = nsnull;
|
2010-03-31 03:02:58 +00:00
|
|
|
|
2010-08-20 03:40:51 +00:00
|
|
|
/* We should clear our cached resources now and not wait for the GC to
|
2010-08-18 03:43:49 +00:00
|
|
|
* delete the nsWindow. */
|
2010-08-20 03:40:51 +00:00
|
|
|
ClearCachedResources();
|
2010-08-18 03:43:49 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
|
|
|
|
// and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
|
|
|
|
// from it. The function also destroys the window's menu, flushes the thread message queue,
|
|
|
|
// destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if
|
|
|
|
// the window is at the top of the viewer chain).
|
|
|
|
//
|
|
|
|
// If the specified window is a parent or owner window, DestroyWindow automatically destroys
|
|
|
|
// the associated child or owned windows when it destroys the parent or owner window. The
|
|
|
|
// function first destroys child or owned windows, and then it destroys the parent or owner
|
|
|
|
// window.
|
|
|
|
VERIFY(::DestroyWindow(mWnd));
|
|
|
|
|
|
|
|
// Our windows can be subclassed which may prevent us receiving WM_DESTROY. If OnDestroy()
|
|
|
|
// didn't get called, call it now.
|
2011-10-02 02:16:19 +00:00
|
|
|
if (false == mOnDestroyCalled) {
|
2010-11-23 14:58:38 +00:00
|
|
|
LRESULT result;
|
|
|
|
mWindowHook.Notify(mWnd, WM_DESTROY, 0, 0, &result);
|
2009-07-13 15:58:19 +00:00
|
|
|
OnDestroy();
|
2010-11-23 14:58:38 +00:00
|
|
|
}
|
2009-07-13 15:58:19 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window class utilities
|
|
|
|
*
|
|
|
|
* Utilities for calculating the proper window class name for
|
|
|
|
* Create window.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2008-09-09 17:22:12 +00:00
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
void nsWindow::RegisterWindowClass(const nsString& aClassName, UINT aExtraStyle,
|
|
|
|
LPWSTR aIconID)
|
2005-08-13 18:00:33 +00:00
|
|
|
{
|
2010-11-08 09:06:13 +00:00
|
|
|
WNDCLASSW wc;
|
|
|
|
if (::GetClassInfoW(nsToolkit::mDllInstance, aClassName.get(), &wc)) {
|
|
|
|
// already registered
|
|
|
|
return;
|
|
|
|
}
|
2008-09-09 17:22:12 +00:00
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
wc.style = CS_DBLCLKS | aExtraStyle;
|
|
|
|
wc.lpfnWndProc = ::DefWindowProcW;
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hInstance = nsToolkit::mDllInstance;
|
|
|
|
wc.hIcon = aIconID ? ::LoadIconW(::GetModuleHandleW(NULL), aIconID) : NULL;
|
|
|
|
wc.hCursor = NULL;
|
|
|
|
wc.hbrBackground = mBrush;
|
|
|
|
wc.lpszMenuName = NULL;
|
|
|
|
wc.lpszClassName = aClassName.get();
|
2002-06-04 17:47:54 +00:00
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
if (!::RegisterClassW(&wc)) {
|
|
|
|
// For older versions of Win32 (i.e., not XP), the registration may
|
|
|
|
// fail with aExtraStyle, so we have to re-register without it.
|
|
|
|
wc.style = CS_DBLCLKS;
|
|
|
|
::RegisterClassW(&wc);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2010-11-08 09:06:13 +00:00
|
|
|
}
|
2002-06-04 17:47:54 +00:00
|
|
|
|
2010-11-08 10:47:12 +00:00
|
|
|
static LPWSTR const gStockApplicationIcon = MAKEINTRESOURCEW(32512);
|
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
// Return the proper window class for everything except popups.
|
|
|
|
void nsWindow::GetWindowClass(nsString& aWindowClass)
|
|
|
|
{
|
|
|
|
switch (mWindowType) {
|
|
|
|
case eWindowType_invisible:
|
|
|
|
aWindowClass.AssignLiteral(kClassNameHidden);
|
2010-11-08 10:47:12 +00:00
|
|
|
RegisterWindowClass(aWindowClass, 0, gStockApplicationIcon);
|
2010-11-08 09:06:13 +00:00
|
|
|
break;
|
|
|
|
case eWindowType_dialog:
|
|
|
|
aWindowClass.AssignLiteral(kClassNameDialog);
|
|
|
|
RegisterWindowClass(aWindowClass, 0, 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GetMainWindowClass(aWindowClass);
|
2010-11-08 10:47:12 +00:00
|
|
|
RegisterWindowClass(aWindowClass, 0, gStockApplicationIcon);
|
2010-11-08 09:06:13 +00:00
|
|
|
break;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2002-06-04 17:47:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Return the proper popup window class
|
2010-11-08 09:06:13 +00:00
|
|
|
void nsWindow::GetWindowPopupClass(nsString& aWindowClass)
|
2002-06-04 17:47:54 +00:00
|
|
|
{
|
2010-11-08 09:06:13 +00:00
|
|
|
aWindowClass.AssignLiteral(kClassNameDropShadow);
|
2010-11-08 10:47:12 +00:00
|
|
|
RegisterWindowClass(aWindowClass, CS_XP_DROPSHADOW, gStockApplicationIcon);
|
2002-06-04 17:47:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window styles utilities
|
|
|
|
*
|
|
|
|
* Return the proper windows styles and extended styles.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2002-06-04 17:47:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Return nsWindow styles
|
|
|
|
DWORD nsWindow::WindowStyle()
|
1998-11-04 21:43:47 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
DWORD style;
|
2008-05-05 23:01:07 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (mWindowType) {
|
2009-09-24 09:32:20 +00:00
|
|
|
case eWindowType_plugin:
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_child:
|
|
|
|
style = WS_OVERLAPPED;
|
|
|
|
break;
|
1999-03-19 23:36:20 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_dialog:
|
2010-06-26 04:32:13 +00:00
|
|
|
style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_3DLOOK |
|
|
|
|
DS_MODALFRAME | WS_CLIPCHILDREN;
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mBorderStyle != eBorderStyle_default)
|
|
|
|
style |= WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
|
|
|
|
break;
|
2003-03-14 23:35:18 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_popup:
|
|
|
|
style = WS_POPUP;
|
2010-08-18 03:07:10 +00:00
|
|
|
if (!HasGlass()) {
|
2009-06-29 19:36:16 +00:00
|
|
|
style |= WS_OVERLAPPED;
|
|
|
|
}
|
|
|
|
break;
|
2009-02-10 20:56:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
default:
|
2009-08-14 14:09:00 +00:00
|
|
|
NS_ERROR("unknown border style");
|
2009-06-29 19:36:16 +00:00
|
|
|
// fall through
|
2009-02-07 17:13:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_toplevel:
|
|
|
|
case eWindowType_invisible:
|
|
|
|
style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU |
|
2010-06-26 04:32:13 +00:00
|
|
|
WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-04-14 18:23:01 +00:00
|
|
|
|
2009-08-16 10:54:26 +00:00
|
|
|
if (mBorderStyle != eBorderStyle_default && mBorderStyle != eBorderStyle_all) {
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_border))
|
|
|
|
style &= ~WS_BORDER;
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_title)) {
|
|
|
|
style &= ~WS_DLGFRAME;
|
|
|
|
style |= WS_POPUP;
|
|
|
|
style &= ~WS_CHILD;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_close))
|
|
|
|
style &= ~0;
|
|
|
|
// XXX The close box can only be removed by changing the window class,
|
|
|
|
// as far as I know --- roc+moz@cs.cmu.edu
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none ||
|
|
|
|
!(mBorderStyle & (eBorderStyle_menu | eBorderStyle_close)))
|
|
|
|
style &= ~WS_SYSMENU;
|
|
|
|
// Looks like getting rid of the system menu also does away with the
|
|
|
|
// close box. So, we only get rid of the system menu if you want neither it
|
|
|
|
// nor the close box. How does the Windows "Dialog" window class get just
|
|
|
|
// closebox and no sysmenu? Who knows.
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_resizeh))
|
|
|
|
style &= ~WS_THICKFRAME;
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_minimize))
|
|
|
|
style &= ~WS_MINIMIZEBOX;
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_maximize))
|
|
|
|
style &= ~WS_MAXIMIZEBOX;
|
2010-07-27 13:38:03 +00:00
|
|
|
|
|
|
|
if (IsPopupWithTitleBar()) {
|
|
|
|
style |= WS_CAPTION;
|
2010-07-27 13:38:04 +00:00
|
|
|
if (mBorderStyle & eBorderStyle_close) {
|
|
|
|
style |= WS_SYSMENU;
|
|
|
|
}
|
2010-07-27 13:38:03 +00:00
|
|
|
}
|
2009-08-16 10:54:26 +00:00
|
|
|
}
|
2010-07-27 13:38:03 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
VERIFY_WINDOW_STYLE(style);
|
|
|
|
return style;
|
2009-01-05 18:17:44 +00:00
|
|
|
}
|
2004-09-08 19:30:22 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Return nsWindow extended styles
|
|
|
|
DWORD nsWindow::WindowExStyle()
|
1998-11-04 21:43:47 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (mWindowType)
|
|
|
|
{
|
2009-09-24 09:32:20 +00:00
|
|
|
case eWindowType_plugin:
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_child:
|
|
|
|
return 0;
|
1998-11-04 21:43:47 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_dialog:
|
|
|
|
return WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME;
|
2006-02-22 21:08:40 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_popup:
|
2010-07-27 13:38:03 +00:00
|
|
|
{
|
2011-04-25 03:10:12 +00:00
|
|
|
DWORD extendedStyle = WS_EX_TOOLWINDOW;
|
2010-07-27 13:38:03 +00:00
|
|
|
if (mPopupLevel == ePopupLevelTop)
|
|
|
|
extendedStyle |= WS_EX_TOPMOST;
|
|
|
|
return extendedStyle;
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
default:
|
2009-08-14 14:09:00 +00:00
|
|
|
NS_ERROR("unknown border style");
|
2009-06-29 19:36:16 +00:00
|
|
|
// fall through
|
1998-11-04 21:43:47 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eWindowType_toplevel:
|
|
|
|
case eWindowType_invisible:
|
|
|
|
return WS_EX_WINDOWEDGE;
|
2005-04-13 05:52:02 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2005-04-13 05:52:02 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window subclassing utilities
|
|
|
|
*
|
|
|
|
* Set or clear window subclasses on native windows. Used in
|
|
|
|
* Create and Destroy.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2009-02-10 20:56:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Subclass (or remove the subclass from) this component's nsWindow
|
|
|
|
void nsWindow::SubclassWindow(BOOL bState)
|
|
|
|
{
|
|
|
|
if (NULL != mWnd) {
|
2009-10-06 02:26:54 +00:00
|
|
|
//NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
|
|
|
|
if (!::IsWindow(mWnd)) {
|
|
|
|
NS_ERROR("Invalid window handle");
|
|
|
|
}
|
2007-10-31 18:55:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (bState) {
|
|
|
|
// change the nsWindow proc
|
|
|
|
if (mUnicodeWidget)
|
|
|
|
mPrevWndProc = (WNDPROC)::SetWindowLongPtrW(mWnd, GWLP_WNDPROC,
|
|
|
|
(LONG_PTR)nsWindow::WindowProc);
|
|
|
|
else
|
|
|
|
mPrevWndProc = (WNDPROC)::SetWindowLongPtrA(mWnd, GWLP_WNDPROC,
|
|
|
|
(LONG_PTR)nsWindow::WindowProc);
|
|
|
|
NS_ASSERTION(mPrevWndProc, "Null standard window procedure");
|
|
|
|
// connect the this pointer to the nsWindow handle
|
2012-01-04 10:21:44 +00:00
|
|
|
WinUtils::SetNSWindowPtr(mWnd, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (mUnicodeWidget)
|
|
|
|
::SetWindowLongPtrW(mWnd, GWLP_WNDPROC, (LONG_PTR)mPrevWndProc);
|
|
|
|
else
|
|
|
|
::SetWindowLongPtrA(mWnd, GWLP_WNDPROC, (LONG_PTR)mPrevWndProc);
|
2012-01-04 10:21:44 +00:00
|
|
|
WinUtils::SetNSWindowPtr(mWnd, NULL);
|
2009-06-29 19:36:16 +00:00
|
|
|
mPrevWndProc = NULL;
|
2007-10-31 18:55:57 +00:00
|
|
|
}
|
2004-09-08 19:30:22 +00:00
|
|
|
}
|
1998-11-04 21:43:47 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetParent, nsIWidget::GetParent
|
|
|
|
*
|
|
|
|
* Set or clear the parent widgets using window properties, and
|
|
|
|
* handles calculating native parent handles.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-05-04 19:25:25 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Get and set parent widgets
|
|
|
|
NS_IMETHODIMP nsWindow::SetParent(nsIWidget *aNewParent)
|
2005-12-02 12:08:32 +00:00
|
|
|
{
|
2010-06-02 13:02:05 +00:00
|
|
|
mParent = aNewParent;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
|
|
|
nsIWidget* parent = GetParent();
|
|
|
|
if (parent) {
|
|
|
|
parent->RemoveChild(this);
|
2003-02-24 20:15:59 +00:00
|
|
|
}
|
2010-09-18 11:28:50 +00:00
|
|
|
if (aNewParent) {
|
|
|
|
ReparentNativeWidget(aNewParent);
|
|
|
|
aNewParent->AddChild(this);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
2009-07-13 15:58:19 +00:00
|
|
|
// If we have no parent, SetParent should return the desktop.
|
|
|
|
VERIFY(::SetParent(mWnd, nsnull));
|
2003-02-24 20:15:59 +00:00
|
|
|
}
|
2010-09-18 11:28:50 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2003-02-24 20:15:59 +00:00
|
|
|
|
2010-09-18 11:28:50 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::ReparentNativeWidget(nsIWidget* aNewParent)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aNewParent, "");
|
|
|
|
|
|
|
|
mParent = aNewParent;
|
|
|
|
if (mWindowType == eWindowType_popup) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
HWND newParent = (HWND)aNewParent->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
NS_ASSERTION(newParent, "Parent widget has a null native window handle");
|
|
|
|
if (newParent && mWnd) {
|
|
|
|
::SetParent(mWnd, newParent);
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-24 23:09:11 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsIWidget* nsWindow::GetParent(void)
|
1998-04-24 23:09:11 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
return GetParentWindow(false);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2003-02-24 20:15:59 +00:00
|
|
|
|
2010-08-13 09:57:55 +00:00
|
|
|
float nsWindow::GetDPI()
|
|
|
|
{
|
|
|
|
HDC dc = ::GetDC(mWnd);
|
|
|
|
if (!dc)
|
|
|
|
return 96.0f;
|
|
|
|
|
2010-08-13 09:57:57 +00:00
|
|
|
double heightInches = ::GetDeviceCaps(dc, VERTSIZE)/MM_PER_INCH_FLOAT;
|
2010-08-13 09:57:55 +00:00
|
|
|
int heightPx = ::GetDeviceCaps(dc, VERTRES);
|
|
|
|
::ReleaseDC(mWnd, dc);
|
|
|
|
if (heightInches < 0.25) {
|
|
|
|
// Something's broken
|
|
|
|
return 96.0f;
|
|
|
|
}
|
|
|
|
return float(heightPx/heightInches);
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
nsWindow* nsWindow::GetParentWindow(bool aIncludeOwner)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (mIsTopWidgetWindow) {
|
|
|
|
// Must use a flag instead of mWindowType to tell if the window is the
|
|
|
|
// owned by the topmost widget, because a child window can be embedded inside
|
|
|
|
// a HWND which is not associated with a nsIWidget.
|
|
|
|
return nsnull;
|
1998-04-24 23:09:11 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// If this widget has already been destroyed, pretend we have no parent.
|
|
|
|
// This corresponds to code in Destroy which removes the destroyed
|
|
|
|
// widget from its parent's child list.
|
2009-07-13 15:58:19 +00:00
|
|
|
if (mInDtor || mOnDestroyCalled)
|
2009-06-29 19:36:16 +00:00
|
|
|
return nsnull;
|
1999-04-06 00:11:43 +00:00
|
|
|
|
1998-10-07 22:11:37 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// aIncludeOwner set to true implies walking the parent chain to retrieve the
|
|
|
|
// root owner. aIncludeOwner set to false implies the search will stop at the
|
|
|
|
// true parent (default).
|
|
|
|
nsWindow* widget = nsnull;
|
|
|
|
if (mWnd) {
|
|
|
|
HWND parent = nsnull;
|
|
|
|
if (aIncludeOwner)
|
|
|
|
parent = ::GetParent(mWnd);
|
|
|
|
else
|
|
|
|
parent = ::GetAncestor(mWnd, GA_PARENT);
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (parent) {
|
2012-01-04 10:21:44 +00:00
|
|
|
widget = WinUtils::GetNSWindowPtr(parent);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (widget) {
|
|
|
|
// If the widget is in the process of being destroyed then
|
|
|
|
// do NOT return it
|
2009-07-13 15:58:19 +00:00
|
|
|
if (widget->mInDtor) {
|
2009-06-29 19:36:16 +00:00
|
|
|
widget = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-04-24 23:09:11 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return widget;
|
1999-11-12 02:06:52 +00:00
|
|
|
}
|
2010-12-07 02:05:48 +00:00
|
|
|
|
|
|
|
BOOL CALLBACK
|
|
|
|
nsWindow::EnumAllChildWindProc(HWND aWnd, LPARAM aParam)
|
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow *wnd = WinUtils::GetNSWindowPtr(aWnd);
|
2010-12-07 02:05:48 +00:00
|
|
|
if (wnd) {
|
|
|
|
((nsWindow::WindowEnumCallback*)aParam)(wnd);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CALLBACK
|
|
|
|
nsWindow::EnumAllThreadWindowProc(HWND aWnd, LPARAM aParam)
|
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow *wnd = WinUtils::GetNSWindowPtr(aWnd);
|
2010-12-07 02:05:48 +00:00
|
|
|
if (wnd) {
|
|
|
|
((nsWindow::WindowEnumCallback*)aParam)(wnd);
|
|
|
|
}
|
|
|
|
EnumChildWindows(aWnd, EnumAllChildWindProc, aParam);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsWindow::EnumAllWindows(WindowEnumCallback aCallback)
|
|
|
|
{
|
|
|
|
EnumThreadWindows(GetCurrentThreadId(),
|
|
|
|
EnumAllThreadWindowProc,
|
2011-01-28 10:31:26 +00:00
|
|
|
(LPARAM)aCallback);
|
2010-12-07 02:05:48 +00:00
|
|
|
}
|
1999-11-12 02:06:52 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Show
|
|
|
|
*
|
|
|
|
* Hide or show this component.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-05-04 19:25:25 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::Show(bool bState)
|
1998-05-04 19:25:25 +00:00
|
|
|
{
|
2011-02-19 03:49:11 +00:00
|
|
|
if (mWindowType == eWindowType_popup) {
|
2011-03-02 11:53:55 +00:00
|
|
|
// See bug 603793. When we try to draw D3D9/10 windows with a drop shadow
|
2011-02-19 03:49:11 +00:00
|
|
|
// without the DWM on a secondary monitor, windows fails to composite
|
|
|
|
// our windows correctly. We therefor switch off the drop shadow for
|
|
|
|
// pop-up windows when the DWM is disabled and two monitors are
|
|
|
|
// connected.
|
2011-03-02 11:53:55 +00:00
|
|
|
if (HasBogusPopupsDropShadowOnMultiMonitor() &&
|
2012-01-04 10:21:44 +00:00
|
|
|
WinUtils::GetMonitorCount() > 1 &&
|
2011-02-19 03:49:11 +00:00
|
|
|
!nsUXThemeData::CheckForCompositor())
|
|
|
|
{
|
|
|
|
if (sDropShadowEnabled) {
|
|
|
|
::SetClassLongA(mWnd, GCL_STYLE, 0);
|
2011-10-02 02:16:19 +00:00
|
|
|
sDropShadowEnabled = false;
|
2011-02-19 03:49:11 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!sDropShadowEnabled) {
|
|
|
|
::SetClassLongA(mWnd, GCL_STYLE, CS_DROPSHADOW);
|
2011-10-02 02:16:19 +00:00
|
|
|
sDropShadowEnabled = true;
|
2011-02-19 03:49:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-26 18:13:03 +00:00
|
|
|
#ifdef NS_FUNCTION_TIMER
|
|
|
|
static bool firstShow = true;
|
|
|
|
if (firstShow &&
|
|
|
|
(mWindowType == eWindowType_toplevel ||
|
|
|
|
mWindowType == eWindowType_dialog ||
|
|
|
|
mWindowType == eWindowType_popup))
|
|
|
|
{
|
|
|
|
firstShow = false;
|
2010-05-19 23:22:19 +00:00
|
|
|
mozilla::FunctionTimer::LogMessage("@ First toplevel/dialog/popup showing");
|
2010-04-26 18:13:03 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool syncInvalidate = false;
|
2011-02-09 22:37:58 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool wasVisible = mIsVisible;
|
2009-06-29 19:36:16 +00:00
|
|
|
// Set the status now so that anyone asking during ShowWindow or
|
|
|
|
// SetWindowPos would get the correct answer.
|
|
|
|
mIsVisible = bState;
|
1998-04-24 23:09:11 +00:00
|
|
|
|
2011-02-15 21:31:34 +00:00
|
|
|
// We may have cached an out of date visible state. This can happen
|
|
|
|
// when session restore sets the full screen mode.
|
|
|
|
if (mIsVisible)
|
|
|
|
mOldStyle |= WS_VISIBLE;
|
|
|
|
else
|
|
|
|
mOldStyle &= ~WS_VISIBLE;
|
|
|
|
|
2010-08-14 06:34:13 +00:00
|
|
|
if (!mIsVisible && wasVisible) {
|
2010-08-20 03:40:51 +00:00
|
|
|
ClearCachedResources();
|
2010-08-14 06:34:13 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
|
|
|
if (bState) {
|
|
|
|
if (!wasVisible && mWindowType == eWindowType_toplevel) {
|
2011-02-09 22:37:58 +00:00
|
|
|
// speed up the initial paint after show for
|
|
|
|
// top level windows:
|
2011-10-02 02:16:19 +00:00
|
|
|
syncInvalidate = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (mSizeMode) {
|
2011-03-29 21:49:45 +00:00
|
|
|
case nsSizeMode_Fullscreen:
|
|
|
|
::ShowWindow(mWnd, SW_SHOW);
|
|
|
|
break;
|
2009-06-29 19:36:16 +00:00
|
|
|
case nsSizeMode_Maximized :
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMAXIMIZED);
|
|
|
|
break;
|
|
|
|
case nsSizeMode_Minimized :
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMINIMIZED);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (CanTakeFocus()) {
|
|
|
|
::ShowWindow(mWnd, SW_SHOWNORMAL);
|
|
|
|
} else {
|
|
|
|
// Place the window behind the foreground window
|
|
|
|
// (as long as it is not topmost)
|
|
|
|
HWND wndAfter = ::GetForegroundWindow();
|
|
|
|
if (!wndAfter)
|
|
|
|
wndAfter = HWND_BOTTOM;
|
|
|
|
else if (GetWindowLongPtrW(wndAfter, GWL_EXSTYLE) & WS_EX_TOPMOST)
|
|
|
|
wndAfter = HWND_TOP;
|
|
|
|
::SetWindowPos(mWnd, wndAfter, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE |
|
|
|
|
SWP_NOMOVE | SWP_NOACTIVATE);
|
|
|
|
GetAttention(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW;
|
|
|
|
if (wasVisible)
|
|
|
|
flags |= SWP_NOZORDER;
|
2001-05-25 10:53:32 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWindowType == eWindowType_popup) {
|
|
|
|
// ensure popups are the topmost of the TOPMOST
|
|
|
|
// layer. Remember not to set the SWP_NOZORDER
|
|
|
|
// flag as that might allow the taskbar to overlap
|
2011-04-25 03:10:12 +00:00
|
|
|
// the popup.
|
2009-06-29 19:36:16 +00:00
|
|
|
flags |= SWP_NOACTIVATE;
|
|
|
|
HWND owner = ::GetWindow(mWnd, GW_OWNER);
|
|
|
|
::SetWindowPos(mWnd, owner ? 0 : HWND_TOPMOST, 0, 0, 0, 0, flags);
|
|
|
|
} else {
|
|
|
|
if (mWindowType == eWindowType_dialog && !CanTakeFocus())
|
|
|
|
flags |= SWP_NOACTIVATE;
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
::SetWindowPos(mWnd, HWND_TOP, 0, 0, 0, 0, flags);
|
|
|
|
}
|
|
|
|
}
|
2010-04-21 14:53:42 +00:00
|
|
|
|
|
|
|
if (!wasVisible && (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)) {
|
|
|
|
// when a toplevel window or dialog is shown, initialize the UI state
|
|
|
|
::SendMessageW(mWnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0);
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
} else {
|
|
|
|
if (mWindowType != eWindowType_dialog) {
|
|
|
|
::ShowWindow(mWnd, SW_HIDE);
|
|
|
|
} else {
|
|
|
|
::SetWindowPos(mWnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
|
|
|
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
}
|
|
|
|
}
|
1999-09-21 11:22:21 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
2011-12-24 03:52:21 +00:00
|
|
|
if (!wasVisible && bState) {
|
|
|
|
Invalidate();
|
|
|
|
if (syncInvalidate) {
|
|
|
|
::UpdateWindow(mWnd);
|
|
|
|
}
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif
|
1999-09-21 11:22:21 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::IsVisible
|
|
|
|
*
|
|
|
|
* Returns the visibility state.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
// Return true if the whether the component is visible, false otherwise
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::IsVisible(bool & bState)
|
1999-10-02 00:13:23 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
bState = mIsVisible;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window clipping utilities
|
|
|
|
*
|
|
|
|
* Used in Size and Move operations for setting the proper
|
|
|
|
* window clipping regions for window transparency.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2001-03-14 02:34:46 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// XP and Vista visual styles sometimes require window clipping regions to be applied for proper
|
|
|
|
// transparency. These routines are called on size and move operations.
|
|
|
|
void nsWindow::ClearThemeRegion()
|
|
|
|
{
|
2012-02-08 21:04:21 +00:00
|
|
|
if (nsUXThemeData::sIsVistaOrLater && !HasGlass() &&
|
2010-09-07 17:30:28 +00:00
|
|
|
(mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
|
|
|
|
(mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
|
2009-06-29 19:36:16 +00:00
|
|
|
SetWindowRgn(mWnd, NULL, false);
|
|
|
|
}
|
1999-10-02 00:13:23 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::SetThemeRegion()
|
|
|
|
{
|
|
|
|
// Popup types that have a visual styles region applied (bug 376408). This can be expanded
|
|
|
|
// for other window types as needed. The regions are applied generically to the base window
|
|
|
|
// so default constants are used for part and state. At some point we might need part and
|
|
|
|
// state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
|
|
|
|
// change shape based on state haven't come up.
|
2012-02-08 21:04:21 +00:00
|
|
|
if (nsUXThemeData::sIsVistaOrLater && !HasGlass() &&
|
2010-09-07 17:30:28 +00:00
|
|
|
(mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
|
|
|
|
(mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
|
2009-06-29 19:36:16 +00:00
|
|
|
HRGN hRgn = nsnull;
|
|
|
|
RECT rect = {0,0,mBounds.width,mBounds.height};
|
|
|
|
|
2010-01-05 18:52:07 +00:00
|
|
|
HDC dc = ::GetDC(mWnd);
|
2012-02-08 21:04:21 +00:00
|
|
|
nsUXThemeData::getThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip), dc, TTP_STANDARD, TS_NORMAL, &rect, &hRgn);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (hRgn) {
|
|
|
|
if (!SetWindowRgn(mWnd, hRgn, false)) // do not delete or alter hRgn if accepted.
|
|
|
|
DeleteObject(hRgn);
|
|
|
|
}
|
2010-01-05 18:52:07 +00:00
|
|
|
::ReleaseDC(mWnd, dc);
|
2005-08-22 04:18:47 +00:00
|
|
|
}
|
2000-04-27 00:23:18 +00:00
|
|
|
}
|
|
|
|
|
2010-08-02 13:34:54 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::RegisterTouchWindow,
|
|
|
|
* nsIWidget::UnregisterTouchWindow, and helper functions
|
|
|
|
*
|
|
|
|
* Used to register the native window to receive touch events
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
NS_METHOD nsWindow::RegisterTouchWindow() {
|
2011-10-02 02:16:19 +00:00
|
|
|
mTouchWindow = true;
|
2010-08-02 13:34:54 +00:00
|
|
|
mGesture.RegisterTouchWindow(mWnd);
|
2010-08-20 18:19:38 +00:00
|
|
|
::EnumChildWindows(mWnd, nsWindow::RegisterTouchForDescendants, 0);
|
2010-08-02 13:34:54 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD nsWindow::UnregisterTouchWindow() {
|
2011-10-02 02:16:19 +00:00
|
|
|
mTouchWindow = false;
|
2010-08-02 13:34:54 +00:00
|
|
|
mGesture.UnregisterTouchWindow(mWnd);
|
2010-08-20 18:19:38 +00:00
|
|
|
::EnumChildWindows(mWnd, nsWindow::UnregisterTouchForDescendants, 0);
|
2010-08-02 13:34:54 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CALLBACK nsWindow::RegisterTouchForDescendants(HWND aWnd, LPARAM aMsg) {
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow* win = WinUtils::GetNSWindowPtr(aWnd);
|
2010-08-02 13:34:54 +00:00
|
|
|
if (win)
|
|
|
|
win->mGesture.RegisterTouchWindow(aWnd);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CALLBACK nsWindow::UnregisterTouchForDescendants(HWND aWnd, LPARAM aMsg) {
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow* win = WinUtils::GetNSWindowPtr(aWnd);
|
2010-08-02 13:34:54 +00:00
|
|
|
if (win)
|
|
|
|
win->mGesture.UnregisterTouchWindow(aWnd);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
2009-10-06 16:11:59 +00:00
|
|
|
* SECTION: nsIWidget::Move, nsIWidget::Resize,
|
|
|
|
* nsIWidget::Size, nsIWidget::BeginResizeDrag
|
2009-06-29 19:36:16 +00:00
|
|
|
*
|
|
|
|
* Repositioning and sizing a window.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1999-10-02 00:13:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Move this component
|
|
|
|
NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
|
2000-04-13 20:15:40 +00:00
|
|
|
{
|
2009-11-02 19:10:07 +00:00
|
|
|
if (mWindowType == eWindowType_toplevel ||
|
|
|
|
mWindowType == eWindowType_dialog) {
|
|
|
|
SetSizeMode(nsSizeMode_Normal);
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
// Check to see if window needs to be moved first
|
|
|
|
// to avoid a costly call to SetWindowPos. This check
|
|
|
|
// can not be moved to the calling code in nsView, because
|
|
|
|
// some platforms do not position child windows correctly
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Only perform this check for non-popup windows, since the positioning can
|
|
|
|
// in fact change even when the x/y do not. We always need to perform the
|
|
|
|
// check. See bug #97805 for details.
|
|
|
|
if (mWindowType != eWindowType_popup && (mBounds.x == aX) && (mBounds.y == aY))
|
|
|
|
{
|
|
|
|
// Nothing to do, since it is already positioned correctly.
|
|
|
|
return NS_OK;
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
1998-04-17 00:16:11 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
// complain if a window is moved offscreen (legal, but potentially worrisome)
|
|
|
|
if (mIsTopWidgetWindow) { // only a problem for top-level windows
|
|
|
|
// Make sure this window is actually on the screen before we move it
|
|
|
|
// XXX: Needs multiple monitor support
|
|
|
|
HDC dc = ::GetDC(mWnd);
|
|
|
|
if (dc) {
|
|
|
|
if (::GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
|
|
|
|
RECT workArea;
|
|
|
|
::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
|
|
|
|
// no annoying assertions. just mention the issue.
|
2011-08-16 19:30:44 +00:00
|
|
|
if (aX < 0 || aX >= workArea.right || aY < 0 || aY >= workArea.bottom) {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("window moved to offscreen position\n"));
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
::ReleaseDC(mWnd, dc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2009-07-27 17:27:35 +00:00
|
|
|
ClearThemeRegion();
|
2010-12-05 15:02:17 +00:00
|
|
|
|
|
|
|
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE;
|
|
|
|
// Workaround SetWindowPos bug with D3D9. If our window has a clip
|
|
|
|
// region, some drivers or OSes may incorrectly copy into the clipped-out
|
|
|
|
// area.
|
|
|
|
if (mWindowType == eWindowType_plugin &&
|
|
|
|
(!mLayerManager || mLayerManager->GetBackendType() == LayerManager::LAYERS_D3D9) &&
|
|
|
|
mClipRects &&
|
2011-04-19 03:07:23 +00:00
|
|
|
(mClipRectCount != 1 || !mClipRects[0].IsEqualInterior(nsIntRect(0, 0, mBounds.width, mBounds.height)))) {
|
2010-12-05 15:02:17 +00:00
|
|
|
flags |= SWP_NOCOPYBITS;
|
|
|
|
}
|
|
|
|
VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, 0, 0, flags));
|
|
|
|
|
2009-07-27 17:27:35 +00:00
|
|
|
SetThemeRegion();
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-05-04 12:39:42 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Resize this component
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
NS_ASSERTION((aWidth >=0 ) , "Negative width passed to nsWindow::Resize");
|
|
|
|
NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
|
1998-08-19 23:11:41 +00:00
|
|
|
|
2010-06-25 02:01:06 +00:00
|
|
|
// Avoid unnecessary resizing calls
|
2010-06-25 17:56:39 +00:00
|
|
|
if (mBounds.width == aWidth && mBounds.height == aHeight && !aRepaint)
|
2010-06-25 02:01:06 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
ResizeTranslucentWindow(aWidth, aHeight);
|
|
|
|
#endif
|
1999-05-27 21:09:49 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Set cached value for lightweight and printing
|
|
|
|
mBounds.width = aWidth;
|
|
|
|
mBounds.height = aHeight;
|
2004-05-04 12:39:42 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
|
|
|
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
|
2009-07-27 17:27:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!aRepaint) {
|
|
|
|
flags |= SWP_NOREDRAW;
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-07-27 17:27:35 +00:00
|
|
|
ClearThemeRegion();
|
|
|
|
VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, aWidth, GetHeight(aHeight), flags));
|
|
|
|
SetThemeRegion();
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aRepaint)
|
2011-12-24 03:52:21 +00:00
|
|
|
Invalidate();
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Resize this component
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
NS_ASSERTION((aWidth >=0 ), "Negative width passed to nsWindow::Resize");
|
|
|
|
NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
|
2005-06-15 00:20:12 +00:00
|
|
|
|
2010-06-25 02:01:06 +00:00
|
|
|
// Avoid unnecessary resizing calls
|
|
|
|
if (mBounds.x == aX && mBounds.y == aY &&
|
2010-06-25 17:56:39 +00:00
|
|
|
mBounds.width == aWidth && mBounds.height == aHeight && !aRepaint)
|
2010-06-25 02:01:06 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
ResizeTranslucentWindow(aWidth, aHeight);
|
|
|
|
#endif
|
2009-01-28 23:39:13 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Set cached value for lightweight and printing
|
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
|
|
|
mBounds.width = aWidth;
|
|
|
|
mBounds.height = aHeight;
|
2004-12-09 19:01:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
|
|
|
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
|
|
|
|
if (!aRepaint) {
|
|
|
|
flags |= SWP_NOREDRAW;
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
2006-03-17 21:42:28 +00:00
|
|
|
|
2009-07-27 17:27:35 +00:00
|
|
|
ClearThemeRegion();
|
|
|
|
VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, aWidth, GetHeight(aHeight), flags));
|
|
|
|
SetThemeRegion();
|
2009-04-02 19:34:31 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aRepaint)
|
2011-12-24 03:52:21 +00:00
|
|
|
Invalidate();
|
2009-06-29 19:36:16 +00:00
|
|
|
|
2004-09-03 08:44:23 +00:00
|
|
|
return NS_OK;
|
1998-09-29 21:34:58 +00:00
|
|
|
}
|
|
|
|
|
2009-10-06 16:11:59 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aEvent);
|
|
|
|
|
|
|
|
if (aEvent->eventStructType != NS_MOUSE_EVENT) {
|
|
|
|
// you can only begin a resize drag with a mouse event
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aEvent);
|
|
|
|
if (mouseEvent->button != nsMouseEvent::eLeftButton) {
|
|
|
|
// you can only begin a resize drag with the left mouse button
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// work out what sizemode we're talking about
|
|
|
|
WPARAM syscommand;
|
|
|
|
if (aVertical < 0) {
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_TOPLEFT;
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_TOP;
|
|
|
|
} else {
|
|
|
|
syscommand = SC_SIZE | WMSZ_TOPRIGHT;
|
|
|
|
}
|
|
|
|
} else if (aVertical == 0) {
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_LEFT;
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
} else {
|
|
|
|
syscommand = SC_SIZE | WMSZ_RIGHT;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_BOTTOMLEFT;
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_BOTTOM;
|
|
|
|
} else {
|
|
|
|
syscommand = SC_SIZE | WMSZ_BOTTOMRIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// resizing doesn't work if the mouse is already captured
|
2011-10-02 02:16:19 +00:00
|
|
|
CaptureMouse(false);
|
2009-10-06 16:11:59 +00:00
|
|
|
|
|
|
|
// find the top-level window
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND toplevelWnd = WinUtils::GetTopLevelHWND(mWnd, true);
|
2009-10-06 16:11:59 +00:00
|
|
|
|
|
|
|
// tell Windows to start the resize
|
|
|
|
::PostMessage(toplevelWnd, WM_SYSCOMMAND, syscommand,
|
|
|
|
POINTTOPOINTS(aEvent->refPoint));
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window Z-order and state.
|
|
|
|
*
|
|
|
|
* nsIWidget::PlaceBehind, nsIWidget::SetSizeMode,
|
|
|
|
* nsIWidget::ConstrainPosition
|
|
|
|
*
|
|
|
|
* Z-order, positioning, restore, minimize, and maximize.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-09-29 21:34:58 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Position the window behind the given window
|
|
|
|
NS_METHOD nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
|
2011-09-29 06:19:26 +00:00
|
|
|
nsIWidget *aWidget, bool aActivate)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
HWND behind = HWND_TOP;
|
|
|
|
if (aPlacement == eZPlacementBottom)
|
|
|
|
behind = HWND_BOTTOM;
|
|
|
|
else if (aPlacement == eZPlacementBelow && aWidget)
|
|
|
|
behind = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
UINT flags = SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOSIZE;
|
|
|
|
if (!aActivate)
|
|
|
|
flags |= SWP_NOACTIVATE;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!CanTakeFocus() && behind == HWND_TOP)
|
|
|
|
{
|
|
|
|
// Can't place the window to top so place it behind the foreground window
|
|
|
|
// (as long as it is not topmost)
|
|
|
|
HWND wndAfter = ::GetForegroundWindow();
|
|
|
|
if (!wndAfter)
|
|
|
|
behind = HWND_BOTTOM;
|
|
|
|
else if (!(GetWindowLongPtrW(wndAfter, GWL_EXSTYLE) & WS_EX_TOPMOST))
|
|
|
|
behind = wndAfter;
|
|
|
|
flags |= SWP_NOACTIVATE;
|
1998-08-09 01:37:30 +00:00
|
|
|
}
|
1998-05-04 19:25:25 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
::SetWindowPos(mWnd, behind, 0, 0, 0, 0, flags);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Maximize, minimize or restore the window.
|
|
|
|
NS_IMETHODIMP nsWindow::SetSizeMode(PRInt32 aMode) {
|
1999-04-06 20:23:55 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsresult rv;
|
2002-05-03 18:52:04 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Let's not try and do anything if we're already in that state.
|
|
|
|
// (This is needed to prevent problems when calling window.minimize(), which
|
|
|
|
// calls us directly, and then the OS triggers another call to us.)
|
|
|
|
if (aMode == mSizeMode)
|
|
|
|
return NS_OK;
|
2005-11-17 16:33:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// save the requested state
|
|
|
|
rv = nsBaseWidget::SetSizeMode(aMode);
|
|
|
|
if (NS_SUCCEEDED(rv) && mIsVisible) {
|
|
|
|
int mode;
|
2003-10-30 01:35:14 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (aMode) {
|
2009-07-08 16:13:13 +00:00
|
|
|
case nsSizeMode_Fullscreen :
|
2010-07-16 02:07:27 +00:00
|
|
|
mode = SW_SHOW;
|
2009-07-08 16:13:13 +00:00
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case nsSizeMode_Maximized :
|
|
|
|
mode = SW_MAXIMIZE;
|
|
|
|
break;
|
2009-11-12 01:11:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case nsSizeMode_Minimized :
|
2009-11-12 01:11:57 +00:00
|
|
|
// Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
|
|
|
|
// keeps the window active in the tray. So after the window is minimized,
|
|
|
|
// windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
|
|
|
|
// we will do some additional processing to get the active window set right.
|
|
|
|
// If sTrimOnMinimize is set, we let windows handle minimization normally
|
|
|
|
// using SW_MINIMIZE.
|
2009-06-29 19:36:16 +00:00
|
|
|
mode = sTrimOnMinimize ? SW_MINIMIZE : SW_SHOWMINIMIZED;
|
|
|
|
break;
|
2009-11-12 01:11:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
default :
|
|
|
|
mode = SW_RESTORE;
|
2004-07-27 19:14:44 +00:00
|
|
|
}
|
2011-07-28 22:47:47 +00:00
|
|
|
|
|
|
|
WINDOWPLACEMENT pl;
|
|
|
|
pl.length = sizeof(pl);
|
|
|
|
::GetWindowPlacement(mWnd, &pl);
|
|
|
|
// Don't call ::ShowWindow if we're trying to "restore" a window that is
|
|
|
|
// already in a normal state. Prevents a bug where snapping to one side
|
|
|
|
// of the screen and then minimizing would cause Windows to forget our
|
|
|
|
// window's correct restored position/size.
|
|
|
|
if( !(pl.showCmd == SW_SHOWNORMAL && mode == SW_RESTORE) ) {
|
|
|
|
::ShowWindow(mWnd, mode);
|
|
|
|
}
|
2009-08-12 14:03:34 +00:00
|
|
|
// we dispatch an activate event here to ensure that the right child window
|
|
|
|
// is focused
|
2011-05-09 18:52:59 +00:00
|
|
|
if (mode == SW_RESTORE || mode == SW_MAXIMIZE || mode == SW_SHOW)
|
2009-08-12 14:03:34 +00:00
|
|
|
DispatchFocusToTopLevelWindow(NS_ACTIVATE);
|
1998-08-09 01:37:30 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return rv;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Constrain a potential move to fit onscreen
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::ConstrainPosition(bool aAllowSlop,
|
2009-06-29 19:36:16 +00:00
|
|
|
PRInt32 *aX, PRInt32 *aY)
|
2002-09-12 03:59:15 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!mIsTopWidgetWindow) // only a problem for top-level windows
|
|
|
|
return NS_OK;
|
2007-07-12 23:19:47 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool doConstrain = false; // whether we have enough info to do anything
|
2007-07-12 23:19:47 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/* get our playing field. use the current screen, or failing that
|
|
|
|
for any reason, use device caps for the default screen. */
|
|
|
|
RECT screenRect;
|
2007-07-12 23:19:47 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
|
|
|
|
if (screenmgr) {
|
|
|
|
nsCOMPtr<nsIScreen> screen;
|
|
|
|
PRInt32 left, top, width, height;
|
2003-03-06 23:07:00 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// zero size rects confuse the screen manager
|
|
|
|
width = mBounds.width > 0 ? mBounds.width : 1;
|
|
|
|
height = mBounds.height > 0 ? mBounds.height : 1;
|
|
|
|
screenmgr->ScreenForRect(*aX, *aY, width, height,
|
|
|
|
getter_AddRefs(screen));
|
|
|
|
if (screen) {
|
2010-07-20 04:19:48 +00:00
|
|
|
if (mSizeMode != nsSizeMode_Fullscreen) {
|
|
|
|
// For normalized windows, use the desktop work area.
|
|
|
|
screen->GetAvailRect(&left, &top, &width, &height);
|
|
|
|
} else {
|
|
|
|
// For full screen windows, use the desktop.
|
|
|
|
screen->GetRect(&left, &top, &width, &height);
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
screenRect.left = left;
|
|
|
|
screenRect.right = left+width;
|
|
|
|
screenRect.top = top;
|
|
|
|
screenRect.bottom = top+height;
|
2011-10-02 02:16:19 +00:00
|
|
|
doConstrain = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (mWnd) {
|
|
|
|
HDC dc = ::GetDC(mWnd);
|
|
|
|
if (dc) {
|
|
|
|
if (::GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
|
2010-07-20 04:19:48 +00:00
|
|
|
if (mSizeMode != nsSizeMode_Fullscreen) {
|
|
|
|
::SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
|
|
|
|
} else {
|
|
|
|
screenRect.left = screenRect.top = 0;
|
|
|
|
screenRect.right = GetSystemMetrics(SM_CXFULLSCREEN);
|
|
|
|
screenRect.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
doConstrain = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
::ReleaseDC(mWnd, dc);
|
|
|
|
}
|
|
|
|
}
|
2002-09-12 03:59:15 +00:00
|
|
|
}
|
2007-08-13 20:47:04 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aAllowSlop) {
|
|
|
|
if (*aX < screenRect.left - mBounds.width + kWindowPositionSlop)
|
|
|
|
*aX = screenRect.left - mBounds.width + kWindowPositionSlop;
|
|
|
|
else if (*aX >= screenRect.right - kWindowPositionSlop)
|
|
|
|
*aX = screenRect.right - kWindowPositionSlop;
|
2007-08-13 20:47:04 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (*aY < screenRect.top - mBounds.height + kWindowPositionSlop)
|
|
|
|
*aY = screenRect.top - mBounds.height + kWindowPositionSlop;
|
|
|
|
else if (*aY >= screenRect.bottom - kWindowPositionSlop)
|
|
|
|
*aY = screenRect.bottom - kWindowPositionSlop;
|
2007-08-13 20:47:04 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
} else {
|
2007-08-13 20:47:04 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (*aX < screenRect.left)
|
|
|
|
*aX = screenRect.left;
|
|
|
|
else if (*aX >= screenRect.right - mBounds.width)
|
|
|
|
*aX = screenRect.right - mBounds.width;
|
|
|
|
|
|
|
|
if (*aY < screenRect.top)
|
|
|
|
*aY = screenRect.top;
|
|
|
|
else if (*aY >= screenRect.bottom - mBounds.height)
|
|
|
|
*aY = screenRect.bottom - mBounds.height;
|
2007-08-13 20:47:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2002-09-12 03:59:15 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Enable, nsIWidget::IsEnabled
|
|
|
|
*
|
|
|
|
* Enabling and disabling the widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Enable/disable this component
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::Enable(bool bState)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
|
|
|
::EnableWindow(mWnd, bState);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2004-12-09 17:56:46 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Return the current enable state
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::IsEnabled(bool *aState)
|
2004-12-09 17:56:46 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aState);
|
|
|
|
*aState = !mWnd || (::IsWindowEnabled(mWnd) && ::IsWindowEnabled(::GetAncestor(mWnd, GA_ROOT)));
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetFocus
|
|
|
|
*
|
|
|
|
* Give the focus to this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2006-06-19 05:58:00 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::SetFocus(bool aRaise)
|
2006-06-19 05:58:00 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
2009-11-10 16:24:10 +00:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
2012-01-04 10:21:44 +00:00
|
|
|
if (mWnd == WinUtils::GetTopLevelHWND(mWnd)) {
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("*** SetFocus: [ top] raise=%d\n", aRaise));
|
|
|
|
} else {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("*** SetFocus: [child] raise=%d\n", aRaise));
|
|
|
|
}
|
2009-11-10 16:24:10 +00:00
|
|
|
#endif
|
2009-06-29 19:36:16 +00:00
|
|
|
// Uniconify, if necessary
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND toplevelWnd = WinUtils::GetTopLevelHWND(mWnd);
|
2009-09-27 02:07:43 +00:00
|
|
|
if (aRaise && ::IsIconic(toplevelWnd)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
::ShowWindow(toplevelWnd, SW_RESTORE);
|
2009-09-27 02:07:43 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
::SetFocus(mWnd);
|
2006-07-20 04:01:52 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
2006-07-20 04:01:52 +00:00
|
|
|
}
|
|
|
|
|
2009-06-16 18:59:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Bounds
|
|
|
|
*
|
2010-06-25 02:01:07 +00:00
|
|
|
* GetBounds, GetClientBounds, GetScreenBounds, GetClientOffset
|
|
|
|
* SetDrawsInTitlebar, GetNonClientMargins, SetNonClientMargins
|
2009-06-29 19:36:16 +00:00
|
|
|
*
|
|
|
|
* Bound calculations.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2008-08-01 17:32:32 +00:00
|
|
|
|
2010-06-25 02:01:06 +00:00
|
|
|
// Return the window's full dimensions in screen coordinates.
|
|
|
|
// If the window has a parent, converts the origin to an offset
|
|
|
|
// of the parent's screen origin.
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_METHOD nsWindow::GetBounds(nsIntRect &aRect)
|
|
|
|
{
|
2000-12-20 01:43:38 +00:00
|
|
|
if (mWnd) {
|
2009-06-29 19:36:16 +00:00
|
|
|
RECT r;
|
|
|
|
VERIFY(::GetWindowRect(mWnd, &r));
|
2000-12-20 01:43:38 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// assign size
|
|
|
|
aRect.width = r.right - r.left;
|
|
|
|
aRect.height = r.bottom - r.top;
|
|
|
|
|
2011-04-01 05:20:40 +00:00
|
|
|
// popup window bounds' are in screen coordinates, not relative to parent
|
|
|
|
// window
|
|
|
|
if (mWindowType == eWindowType_popup) {
|
|
|
|
aRect.x = r.left;
|
|
|
|
aRect.y = r.top;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-25 02:01:06 +00:00
|
|
|
// chrome on parent:
|
|
|
|
// ___ 5,5 (chrome start)
|
|
|
|
// | ____ 10,10 (client start)
|
|
|
|
// | | ____ 20,20 (child start)
|
|
|
|
// | | |
|
|
|
|
// 20,20 - 5,5 = 15,15 (??)
|
|
|
|
// minus GetClientOffset:
|
|
|
|
// 15,15 - 5,5 = 10,10
|
|
|
|
//
|
|
|
|
// no chrome on parent:
|
|
|
|
// ______ 10,10 (win start)
|
|
|
|
// | ____ 20,20 (child start)
|
|
|
|
// | |
|
|
|
|
// 20,20 - 10,10 = 10,10
|
|
|
|
//
|
|
|
|
// walking the chain:
|
|
|
|
// ___ 5,5 (chrome start)
|
|
|
|
// | ___ 10,10 (client start)
|
|
|
|
// | | ___ 20,20 (child start)
|
|
|
|
// | | | __ 30,30 (child start)
|
|
|
|
// | | | |
|
|
|
|
// 30,30 - 20,20 = 10,10 (offset from second child to first)
|
|
|
|
// 20,20 - 5,5 = 15,15 + 10,10 = 25,25 (??)
|
|
|
|
// minus GetClientOffset:
|
|
|
|
// 25,25 - 5,5 = 20,20 (offset from second child to parent client)
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// convert coordinates if parent exists
|
|
|
|
HWND parent = ::GetParent(mWnd);
|
|
|
|
if (parent) {
|
|
|
|
RECT pr;
|
|
|
|
VERIFY(::GetWindowRect(parent, &pr));
|
|
|
|
r.left -= pr.left;
|
|
|
|
r.top -= pr.top;
|
2010-06-25 02:01:06 +00:00
|
|
|
// adjust for chrome
|
|
|
|
nsWindow* pWidget = static_cast<nsWindow*>(GetParent());
|
|
|
|
if (pWidget && pWidget->IsTopLevelWidget()) {
|
2010-07-27 13:38:03 +00:00
|
|
|
nsIntPoint clientOffset = pWidget->GetClientOffset();
|
2010-06-25 02:01:06 +00:00
|
|
|
r.left -= clientOffset.x;
|
|
|
|
r.top -= clientOffset.y;
|
|
|
|
}
|
2003-04-01 20:04:36 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
aRect.x = r.left;
|
|
|
|
aRect.y = r.top;
|
|
|
|
} else {
|
|
|
|
aRect = mBounds;
|
2000-12-20 01:43:38 +00:00
|
|
|
}
|
2006-06-16 02:27:37 +00:00
|
|
|
|
2000-12-20 01:43:38 +00:00
|
|
|
return NS_OK;
|
1998-09-28 22:32:48 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Get this component dimension
|
|
|
|
NS_METHOD nsWindow::GetClientBounds(nsIntRect &aRect)
|
1998-09-28 22:32:48 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mWnd) {
|
|
|
|
RECT r;
|
|
|
|
VERIFY(::GetClientRect(mWnd, &r));
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-12-01 21:35:42 +00:00
|
|
|
nsIntRect bounds;
|
|
|
|
GetBounds(bounds);
|
|
|
|
aRect.MoveTo(bounds.TopLeft() + GetClientOffset());
|
2009-06-29 19:36:16 +00:00
|
|
|
aRect.width = r.right - r.left;
|
|
|
|
aRect.height = r.bottom - r.top;
|
2000-08-30 21:21:39 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
} else {
|
|
|
|
aRect.SetRect(0,0,0,0);
|
2006-07-20 04:01:52 +00:00
|
|
|
}
|
2000-04-01 22:16:43 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Like GetBounds, but don't offset by the parent
|
|
|
|
NS_METHOD nsWindow::GetScreenBounds(nsIntRect &aRect)
|
|
|
|
{
|
|
|
|
if (mWnd) {
|
|
|
|
RECT r;
|
|
|
|
VERIFY(::GetWindowRect(mWnd, &r));
|
2000-12-14 22:37:08 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
aRect.width = r.right - r.left;
|
|
|
|
aRect.height = r.bottom - r.top;
|
|
|
|
aRect.x = r.left;
|
|
|
|
aRect.y = r.top;
|
|
|
|
} else
|
|
|
|
aRect = mBounds;
|
2006-08-12 11:39:05 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-05-02 09:24:52 +00:00
|
|
|
|
2010-06-25 02:01:06 +00:00
|
|
|
// return the x,y offset of the client area from the origin
|
|
|
|
// of the window. If the window is borderless returns (0,0).
|
2010-07-27 13:38:03 +00:00
|
|
|
nsIntPoint nsWindow::GetClientOffset()
|
2010-06-25 02:01:06 +00:00
|
|
|
{
|
|
|
|
if (!mWnd) {
|
2010-07-27 13:38:03 +00:00
|
|
|
return nsIntPoint(0, 0);
|
2010-06-25 02:01:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RECT r1;
|
|
|
|
GetWindowRect(mWnd, &r1);
|
|
|
|
nsIntPoint pt = WidgetToScreenOffset();
|
2010-07-27 13:38:03 +00:00
|
|
|
return nsIntPoint(pt.x - r1.left, pt.y - r1.top);
|
2010-06-25 02:01:06 +00:00
|
|
|
}
|
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
void
|
2011-09-29 06:19:26 +00:00
|
|
|
nsWindow::SetDrawsInTitlebar(bool aState)
|
2010-06-25 02:01:07 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsWindow * window = GetTopLevelWindow(true);
|
2010-06-25 02:01:07 +00:00
|
|
|
if (window && window != this) {
|
|
|
|
return window->SetDrawsInTitlebar(aState);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aState) {
|
|
|
|
// left, top, right, bottom for nsIntMargin
|
|
|
|
nsIntMargin margins(-1, 0, -1, -1);
|
|
|
|
SetNonClientMargins(margins);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsIntMargin margins(-1, -1, -1, -1);
|
|
|
|
SetNonClientMargins(margins);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::GetNonClientMargins(nsIntMargin &margins)
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsWindow * window = GetTopLevelWindow(true);
|
2010-06-25 02:01:07 +00:00
|
|
|
if (window && window != this) {
|
|
|
|
return window->GetNonClientMargins(margins);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCustomNonClient) {
|
|
|
|
margins = mNonClientMargins;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-28 05:57:07 +00:00
|
|
|
margins.top = GetSystemMetrics(SM_CYCAPTION);
|
|
|
|
margins.bottom = GetSystemMetrics(SM_CYFRAME);
|
|
|
|
margins.top += margins.bottom;
|
|
|
|
margins.left = margins.right = GetSystemMetrics(SM_CYFRAME);
|
2010-06-25 02:01:07 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-07-16 06:20:02 +00:00
|
|
|
void
|
|
|
|
nsWindow::ResetLayout()
|
|
|
|
{
|
|
|
|
// This will trigger a frame changed event, triggering
|
|
|
|
// nc calc size and a sizemode gecko event.
|
|
|
|
SetWindowPos(mWnd, 0, 0, 0, 0, 0,
|
|
|
|
SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|
|
|
|
|
SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
|
|
|
|
|
|
|
|
// If hidden, just send the frame changed event for now.
|
|
|
|
if (!mIsVisible)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Send a gecko size event to trigger reflow.
|
|
|
|
RECT clientRc = {0};
|
|
|
|
GetClientRect(mWnd, &clientRc);
|
|
|
|
nsIntRect evRect(nsWindowGfx::ToIntRect(clientRc));
|
|
|
|
OnResize(evRect);
|
|
|
|
|
|
|
|
// Invalidate and update
|
2011-12-24 03:52:21 +00:00
|
|
|
Invalidate();
|
2010-07-16 06:20:02 +00:00
|
|
|
}
|
|
|
|
|
2010-11-12 02:39:05 +00:00
|
|
|
// Internally track the caption status via a window property. Required
|
|
|
|
// due to our internal handling of WM_NCACTIVATE when custom client
|
|
|
|
// margins are set.
|
|
|
|
static const PRUnichar kManageWindowInfoProperty[] = L"ManageWindowInfoProperty";
|
|
|
|
typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
|
|
|
|
static GetWindowInfoPtr sGetWindowInfoPtrStub = NULL;
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
GetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
|
|
|
|
{
|
|
|
|
if (!sGetWindowInfoPtrStub) {
|
|
|
|
NS_ASSERTION(FALSE, "Something is horribly wrong in GetWindowInfoHook!");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
int windowStatus =
|
2011-01-28 10:33:47 +00:00
|
|
|
reinterpret_cast<LONG_PTR>(GetPropW(hWnd, kManageWindowInfoProperty));
|
2010-11-12 02:39:05 +00:00
|
|
|
// No property set, return the default data.
|
|
|
|
if (!windowStatus)
|
|
|
|
return sGetWindowInfoPtrStub(hWnd, pwi);
|
|
|
|
// Call GetWindowInfo and update dwWindowStatus with our
|
|
|
|
// internally tracked value.
|
|
|
|
BOOL result = sGetWindowInfoPtrStub(hWnd, pwi);
|
|
|
|
if (result && pwi)
|
|
|
|
pwi->dwWindowStatus = (windowStatus == 1 ? 0 : WS_ACTIVECAPTION);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-09-29 06:19:26 +00:00
|
|
|
nsWindow::UpdateGetWindowInfoCaptionStatus(bool aActiveCaption)
|
2010-11-12 02:39:05 +00:00
|
|
|
{
|
|
|
|
if (!mWnd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!sGetWindowInfoPtrStub) {
|
|
|
|
sUser32Intercept.Init("user32.dll");
|
2011-05-02 12:34:14 +00:00
|
|
|
if (!sUser32Intercept.AddHook("GetWindowInfo", reinterpret_cast<intptr_t>(GetWindowInfoHook),
|
2010-11-12 02:39:05 +00:00
|
|
|
(void**) &sGetWindowInfoPtrStub))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Update our internally tracked caption status
|
|
|
|
SetPropW(mWnd, kManageWindowInfoProperty,
|
|
|
|
reinterpret_cast<HANDLE>(static_cast<int>(aActiveCaption) + 1));
|
|
|
|
}
|
|
|
|
|
2010-07-16 06:20:02 +00:00
|
|
|
// Called when the window layout changes: full screen mode transitions,
|
|
|
|
// theme changes, and composition changes. Calculates the new non-client
|
|
|
|
// margins and fires off a frame changed event, which triggers an nc calc
|
|
|
|
// size windows event, kicking the changes in.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
|
|
|
nsWindow::UpdateNonClientMargins(PRInt32 aSizeMode, bool aReflowWindow)
|
2010-06-25 02:01:07 +00:00
|
|
|
{
|
|
|
|
if (!mCustomNonClient)
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2010-06-25 02:01:07 +00:00
|
|
|
|
|
|
|
mNonClientOffset.top = mNonClientOffset.bottom =
|
|
|
|
mNonClientOffset.left = mNonClientOffset.right = 0;
|
2012-01-13 15:10:05 +00:00
|
|
|
mCaptionHeight = mVertResizeMargin = mHorResizeMargin = 0;
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2010-06-28 05:57:07 +00:00
|
|
|
if (aSizeMode == -1)
|
|
|
|
aSizeMode = mSizeMode;
|
|
|
|
|
|
|
|
if (aSizeMode == nsSizeMode_Minimized ||
|
|
|
|
aSizeMode == nsSizeMode_Fullscreen) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-06-25 02:01:07 +00:00
|
|
|
}
|
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
bool hasCaption = (mBorderStyle & (eBorderStyle_all |
|
|
|
|
eBorderStyle_title |
|
|
|
|
eBorderStyle_menu |
|
|
|
|
eBorderStyle_default)) > 0 ? true : false;
|
|
|
|
|
|
|
|
if (hasCaption)
|
|
|
|
mCaptionHeight = GetSystemMetrics(SM_CYCAPTION);
|
2010-06-28 05:57:07 +00:00
|
|
|
mHorResizeMargin = GetSystemMetrics(SM_CXFRAME);
|
|
|
|
mVertResizeMargin = GetSystemMetrics(SM_CYFRAME);
|
|
|
|
mCaptionHeight += mVertResizeMargin;
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
// Custom margin offset calculations for the chrome margin attribute on a
|
|
|
|
// window. The offsets calculated here are added to the client area in the
|
|
|
|
// WM_NCCALCSIZE event:
|
|
|
|
// -1 - leave the default frame in place
|
|
|
|
// 0 - remove the frame, our frame offset equals the default frame size
|
|
|
|
// >0 - frame size equals (default frame size - margin value) with the
|
|
|
|
// restriction that the offset <= default frame size.
|
2010-06-25 02:01:07 +00:00
|
|
|
if (!mNonClientMargins.top)
|
|
|
|
mNonClientOffset.top = mCaptionHeight;
|
|
|
|
else if (mNonClientMargins.top > 0)
|
2012-01-13 15:10:05 +00:00
|
|
|
mNonClientOffset.top = NS_MIN(mCaptionHeight, mNonClientMargins.top);
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2010-07-30 19:24:36 +00:00
|
|
|
if (!mNonClientMargins.left)
|
2010-06-28 05:57:07 +00:00
|
|
|
mNonClientOffset.left = mHorResizeMargin;
|
2010-07-30 19:24:36 +00:00
|
|
|
else if (mNonClientMargins.left > 0)
|
2012-01-13 15:10:05 +00:00
|
|
|
mNonClientOffset.left = NS_MIN(mHorResizeMargin, mNonClientMargins.left);
|
2010-06-28 05:57:07 +00:00
|
|
|
|
2010-07-30 19:24:36 +00:00
|
|
|
if (!mNonClientMargins.right)
|
2010-06-28 05:57:07 +00:00
|
|
|
mNonClientOffset.right = mHorResizeMargin;
|
2010-07-30 19:24:36 +00:00
|
|
|
else if (mNonClientMargins.right > 0)
|
2012-01-13 15:10:05 +00:00
|
|
|
mNonClientOffset.right = NS_MIN(mHorResizeMargin, mNonClientMargins.right);
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2010-07-30 19:24:36 +00:00
|
|
|
if (!mNonClientMargins.bottom)
|
2010-06-28 05:57:07 +00:00
|
|
|
mNonClientOffset.bottom = mVertResizeMargin;
|
2010-07-30 19:24:36 +00:00
|
|
|
else if (mNonClientMargins.bottom > 0)
|
2012-01-13 15:10:05 +00:00
|
|
|
mNonClientOffset.bottom = NS_MIN(mVertResizeMargin, mNonClientMargins.bottom);
|
|
|
|
|
|
|
|
// Disable chrome margins > 0 in two cases:
|
|
|
|
// - For non-glass desktops: The window frame is painted with textures that
|
|
|
|
// require the entire space of the default frame. We allow a full frame or
|
|
|
|
// no frame at all.
|
|
|
|
// - For maximized windows: Windows positions maximized windows such that the
|
|
|
|
// outer bounds sit off screen a distance equal to the standard frame size.
|
|
|
|
if(!nsUXThemeData::CheckForCompositor() || aSizeMode == nsSizeMode_Maximized) {
|
|
|
|
if (mNonClientMargins.top > 0)
|
|
|
|
mNonClientOffset.top = 0;
|
|
|
|
if (mNonClientMargins.bottom > 0)
|
|
|
|
mNonClientOffset.bottom = 0;
|
|
|
|
if (mNonClientMargins.left > 0)
|
|
|
|
mNonClientOffset.left = 0;
|
|
|
|
if (mNonClientMargins.right > 0)
|
|
|
|
mNonClientOffset.right = 0;
|
|
|
|
}
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2010-07-30 19:24:36 +00:00
|
|
|
if (aSizeMode == nsSizeMode_Maximized) {
|
2012-01-13 15:10:05 +00:00
|
|
|
// For chrome margins = 0 on maximized windows, Windows places the bounds
|
|
|
|
// off screen a distance equal to the standard frame size. Remove this
|
|
|
|
// area from our expanded client area.
|
|
|
|
if (!mNonClientMargins.bottom)
|
|
|
|
mNonClientOffset.bottom = 0;
|
|
|
|
if (!mNonClientMargins.left)
|
|
|
|
mNonClientOffset.left = 0;
|
|
|
|
if (!mNonClientMargins.right)
|
|
|
|
mNonClientOffset.right = 0;
|
|
|
|
|
|
|
|
// This should be (mCaptionHeight - mVertResizeMargin). But if we offset
|
|
|
|
// the client area by just SM_CYCAPTION (placing the top of the client
|
|
|
|
// area level with the visible screen) Windows dwm def proc fails to pick
|
|
|
|
// up mouse hover and clicks on the glass control buttons. To compensate,
|
|
|
|
// we position the client area off screen by mVertResizeMargin, and add
|
|
|
|
// widget padding in nsNativeThemeWin::GetWidgetPadding().
|
|
|
|
if (!mNonClientMargins.top)
|
|
|
|
mNonClientOffset.top = mCaptionHeight;
|
|
|
|
|
2010-07-30 19:24:36 +00:00
|
|
|
// Address an issue with auto-hide taskbars which fall behind the window.
|
|
|
|
// Ensure a 1 pixel margin at the bottom of the monitor so that unhiding
|
|
|
|
// the taskbar works properly.
|
|
|
|
MONITORINFO info = {sizeof(MONITORINFO)};
|
|
|
|
if (::GetMonitorInfo(::MonitorFromWindow(mWnd, MONITOR_DEFAULTTOPRIMARY),
|
|
|
|
&info)) {
|
|
|
|
RECT r;
|
|
|
|
if (::GetWindowRect(mWnd, &r)) {
|
|
|
|
// Adjust window rect to account for non-client margins.
|
|
|
|
r.top += mVertResizeMargin - mNonClientOffset.top;
|
|
|
|
r.left += mHorResizeMargin - mNonClientOffset.left;
|
|
|
|
r.bottom -= mVertResizeMargin - mNonClientOffset.bottom;
|
|
|
|
r.right -= mHorResizeMargin - mNonClientOffset.right;
|
|
|
|
// Leave the 1 pixel margin if the window covers the monitor.
|
|
|
|
if (r.top <= info.rcMonitor.top &&
|
|
|
|
r.left <= info.rcMonitor.left &&
|
|
|
|
r.right >= info.rcMonitor.right &&
|
|
|
|
r.bottom >= info.rcMonitor.bottom)
|
|
|
|
mNonClientOffset.bottom -= r.bottom - info.rcMonitor.bottom + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2010-07-16 06:20:02 +00:00
|
|
|
if (aReflowWindow) {
|
|
|
|
// Force a reflow of content based on the new client
|
|
|
|
// dimensions.
|
|
|
|
ResetLayout();
|
2010-06-28 05:57:07 +00:00
|
|
|
}
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-06-25 02:01:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::SetNonClientMargins(nsIntMargin &margins)
|
|
|
|
{
|
|
|
|
if (!mIsTopWidgetWindow ||
|
|
|
|
mBorderStyle & eBorderStyle_none ||
|
|
|
|
mHideChrome)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
// Request for a reset
|
|
|
|
if (margins.top == -1 && margins.left == -1 &&
|
|
|
|
margins.right == -1 && margins.bottom == -1) {
|
2011-10-02 02:16:19 +00:00
|
|
|
mCustomNonClient = false;
|
2010-06-25 02:01:07 +00:00
|
|
|
mNonClientMargins = margins;
|
2010-11-12 07:50:38 +00:00
|
|
|
RemovePropW(mWnd, kManageWindowInfoProperty);
|
2010-07-16 06:20:02 +00:00
|
|
|
// Force a reflow of content based on the new client
|
|
|
|
// dimensions.
|
|
|
|
ResetLayout();
|
2010-06-25 02:01:07 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (margins.top < -1 || margins.bottom < -1 ||
|
|
|
|
margins.left < -1 || margins.right < -1)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
mNonClientMargins = margins;
|
2011-10-02 02:16:19 +00:00
|
|
|
mCustomNonClient = true;
|
2010-06-25 02:01:07 +00:00
|
|
|
if (!UpdateNonClientMargins()) {
|
|
|
|
NS_WARNING("UpdateNonClientMargins failed!");
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2010-06-25 02:01:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-10 01:49:35 +00:00
|
|
|
void
|
|
|
|
nsWindow::InvalidateNonClientRegion()
|
|
|
|
{
|
|
|
|
// +-+-----------------------+-+
|
|
|
|
// | | app non-client chrome | |
|
|
|
|
// | +-----------------------+ |
|
|
|
|
// | | app client chrome | | }
|
|
|
|
// | +-----------------------+ | }
|
|
|
|
// | | app content | | } area we don't want to invalidate
|
|
|
|
// | +-----------------------+ | }
|
|
|
|
// | | app client chrome | | }
|
|
|
|
// | +-----------------------+ |
|
|
|
|
// +---------------------------+ <
|
|
|
|
// ^ ^ windows non-client chrome
|
|
|
|
// client area = app *
|
|
|
|
RECT rect;
|
|
|
|
GetWindowRect(mWnd, &rect);
|
|
|
|
MapWindowPoints(NULL, mWnd, (LPPOINT)&rect, 2);
|
|
|
|
HRGN winRgn = CreateRectRgnIndirect(&rect);
|
|
|
|
|
|
|
|
// Subtract app client chrome and app content leaving
|
|
|
|
// windows non-client chrome and app non-client chrome
|
|
|
|
// in winRgn.
|
|
|
|
GetWindowRect(mWnd, &rect);
|
|
|
|
rect.top += mCaptionHeight;
|
|
|
|
rect.right -= mHorResizeMargin;
|
|
|
|
rect.bottom -= mHorResizeMargin;
|
|
|
|
rect.left += mVertResizeMargin;
|
|
|
|
MapWindowPoints(NULL, mWnd, (LPPOINT)&rect, 2);
|
|
|
|
HRGN clientRgn = CreateRectRgnIndirect(&rect);
|
|
|
|
CombineRgn(winRgn, winRgn, clientRgn, RGN_DIFF);
|
|
|
|
DeleteObject(clientRgn);
|
|
|
|
|
|
|
|
// triggers ncpaint and paint events for the two areas
|
|
|
|
RedrawWindow(mWnd, NULL, winRgn, RDW_FRAME|RDW_INVALIDATE);
|
|
|
|
DeleteObject(winRgn);
|
|
|
|
}
|
|
|
|
|
|
|
|
HRGN
|
|
|
|
nsWindow::ExcludeNonClientFromPaintRegion(HRGN aRegion)
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
HRGN rgn = NULL;
|
|
|
|
if (aRegion == (HRGN)1) { // undocumented value indicating a full refresh
|
|
|
|
GetWindowRect(mWnd, &rect);
|
|
|
|
rgn = CreateRectRgnIndirect(&rect);
|
|
|
|
} else {
|
|
|
|
rgn = aRegion;
|
|
|
|
}
|
|
|
|
GetClientRect(mWnd, &rect);
|
|
|
|
MapWindowPoints(mWnd, NULL, (LPPOINT)&rect, 2);
|
|
|
|
HRGN nonClientRgn = CreateRectRgnIndirect(&rect);
|
|
|
|
CombineRgn(rgn, rgn, nonClientRgn, RGN_DIFF);
|
|
|
|
DeleteObject(nonClientRgn);
|
|
|
|
return rgn;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetBackgroundColor
|
|
|
|
*
|
|
|
|
* Sets the window background paint color.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
NS_METHOD nsWindow::SetBackgroundColor(const nscolor &aColor)
|
|
|
|
{
|
|
|
|
nsBaseWidget::SetBackgroundColor(aColor);
|
|
|
|
|
|
|
|
if (mBrush)
|
|
|
|
::DeleteObject(mBrush);
|
|
|
|
|
|
|
|
mBrush = ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground));
|
|
|
|
if (mWnd != NULL) {
|
|
|
|
::SetClassLongPtrW(mWnd, GCLP_HBRBACKGROUND, (LONG_PTR)mBrush);
|
2000-12-14 22:37:08 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
2000-12-14 22:37:08 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetCursor
|
|
|
|
*
|
|
|
|
* SetCursor and related utilities for manging cursor state.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Set this component cursor
|
|
|
|
NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
|
2000-08-04 14:48:33 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
// Only change cursor if it's changing
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
//XXX mCursor isn't always right. Scrollbars and others change it, too.
|
|
|
|
//XXX If we want this optimization we need a better way to do it.
|
|
|
|
//if (aCursor != mCursor) {
|
|
|
|
HCURSOR newCursor = NULL;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (aCursor) {
|
|
|
|
case eCursor_select:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_IBEAM);
|
|
|
|
break;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_wait:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_WAIT);
|
|
|
|
break;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_hyperlink:
|
|
|
|
{
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_HAND);
|
|
|
|
break;
|
2000-08-04 14:48:33 +00:00
|
|
|
}
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_standard:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_ARROW);
|
|
|
|
break;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_n_resize:
|
|
|
|
case eCursor_s_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENS);
|
|
|
|
break;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_w_resize:
|
|
|
|
case eCursor_e_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEWE);
|
|
|
|
break;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_nw_resize:
|
|
|
|
case eCursor_se_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENWSE);
|
|
|
|
break;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_ne_resize:
|
|
|
|
case eCursor_sw_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENESW);
|
|
|
|
break;
|
2002-01-09 01:30:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_crosshair:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_CROSS);
|
|
|
|
break;
|
2000-08-04 14:48:33 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_move:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEALL);
|
|
|
|
break;
|
2009-03-25 00:51:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_help:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_HELP);
|
|
|
|
break;
|
2009-03-25 00:51:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_copy: // CSS3
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_COPY));
|
|
|
|
break;
|
2009-03-25 00:51:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_alias:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ALIAS));
|
|
|
|
break;
|
2003-03-06 10:38:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_cell:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_CELL));
|
|
|
|
break;
|
2003-03-06 10:38:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_grab:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_GRAB));
|
|
|
|
break;
|
1998-11-24 14:57:09 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_grabbing:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_GRABBING));
|
|
|
|
break;
|
2004-07-27 19:14:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_spinning:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_APPSTARTING);
|
|
|
|
break;
|
2004-07-27 19:14:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_context_menu:
|
|
|
|
// XXX this CSS3 cursor needs to be implemented
|
|
|
|
break;
|
1998-11-24 14:57:09 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_zoom_in:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ZOOMIN));
|
|
|
|
break;
|
1998-05-13 03:39:08 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_zoom_out:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ZOOMOUT));
|
|
|
|
break;
|
1998-06-01 20:26:50 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_not_allowed:
|
|
|
|
case eCursor_no_drop:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_NO);
|
|
|
|
break;
|
1998-06-16 17:16:59 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_col_resize:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_COLRESIZE));
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_row_resize:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ROWRESIZE));
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_vertical_text:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_VERTICALTEXT));
|
|
|
|
break;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_all_scroll:
|
|
|
|
// XXX not 100% appropriate perhaps
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEALL);
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_nesw_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENESW);
|
|
|
|
break;
|
1999-07-27 23:26:36 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_nwse_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENWSE);
|
|
|
|
break;
|
2004-07-27 19:14:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_ns_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENS);
|
|
|
|
break;
|
1998-11-24 14:57:09 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_ew_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEWE);
|
|
|
|
break;
|
1998-05-13 03:39:08 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case eCursor_none:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_NONE));
|
|
|
|
break;
|
1998-06-01 20:26:50 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
default:
|
|
|
|
NS_ERROR("Invalid cursor type");
|
|
|
|
break;
|
|
|
|
}
|
2009-03-25 00:51:57 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (NULL != newCursor) {
|
|
|
|
mCursor = aCursor;
|
|
|
|
HCURSOR oldCursor = ::SetCursor(newCursor);
|
|
|
|
|
|
|
|
if (sHCursor == oldCursor) {
|
|
|
|
NS_IF_RELEASE(sCursorImgContainer);
|
|
|
|
if (sHCursor != NULL)
|
|
|
|
::DestroyIcon(sHCursor);
|
|
|
|
sHCursor = NULL;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Setting the actual cursor
|
|
|
|
NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
|
|
|
|
PRUint32 aHotspotX, PRUint32 aHotspotY)
|
2004-03-03 16:42:51 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sCursorImgContainer == aCursor && sHCursor) {
|
|
|
|
::SetCursor(sHCursor);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-03-03 16:42:51 +00:00
|
|
|
|
2009-07-28 18:52:40 +00:00
|
|
|
PRInt32 width;
|
|
|
|
PRInt32 height;
|
2004-03-03 16:42:51 +00:00
|
|
|
|
2009-07-28 18:52:40 +00:00
|
|
|
nsresult rv;
|
|
|
|
rv = aCursor->GetWidth(&width);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aCursor->GetHeight(&height);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2004-03-03 16:42:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Reject cursors greater than 128 pixels in either direction, to prevent
|
|
|
|
// spoofing.
|
|
|
|
// XXX ideally we should rescale. Also, we could modify the API to
|
|
|
|
// allow trusted content to set larger cursors.
|
|
|
|
if (width > 128 || height > 128)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
1998-07-21 18:04:18 +00:00
|
|
|
|
2009-07-28 18:52:40 +00:00
|
|
|
HCURSOR cursor;
|
2011-09-28 18:36:43 +00:00
|
|
|
// No scaling
|
|
|
|
gfxIntSize size(0, 0);
|
2011-10-02 02:16:19 +00:00
|
|
|
rv = nsWindowGfx::CreateIcon(aCursor, true, aHotspotX, aHotspotY, size, &cursor);
|
2009-07-28 18:52:40 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
mCursor = nsCursor(-1);
|
|
|
|
::SetCursor(cursor);
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_IF_RELEASE(sCursorImgContainer);
|
|
|
|
sCursorImgContainer = aCursor;
|
|
|
|
NS_ADDREF(sCursorImgContainer);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sHCursor != NULL)
|
|
|
|
::DestroyIcon(sHCursor);
|
|
|
|
sHCursor = cursor;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Get/SetTransparencyMode
|
|
|
|
*
|
|
|
|
* Manage the transparency mode of the top-level window
|
|
|
|
* containing this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-07-30 21:25:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
nsTransparencyMode nsWindow::GetTransparencyMode()
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
return GetTopLevelWindow(true)->GetWindowTranslucencyInner();
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1998-07-30 21:25:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
GetTopLevelWindow(true)->SetWindowTranslucencyInner(aMode);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2010-03-17 22:56:00 +00:00
|
|
|
|
2011-01-27 22:58:58 +00:00
|
|
|
static const nsIntRegion
|
|
|
|
RegionFromArray(const nsTArray<nsIntRect>& aRects)
|
|
|
|
{
|
|
|
|
nsIntRegion region;
|
|
|
|
for (PRUint32 i = 0; i < aRects.Length(); ++i) {
|
|
|
|
region.Or(region, aRects[i]);
|
|
|
|
}
|
|
|
|
return region;
|
|
|
|
}
|
2011-01-04 03:56:57 +00:00
|
|
|
|
2011-05-13 16:40:46 +00:00
|
|
|
void nsWindow::UpdateOpaqueRegion(const nsIntRegion &aOpaqueRegion)
|
2011-01-27 22:58:58 +00:00
|
|
|
{
|
2010-03-17 22:56:00 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2011-01-27 22:58:58 +00:00
|
|
|
if (!HasGlass() || GetParent())
|
2010-03-26 03:30:00 +00:00
|
|
|
return;
|
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
// If there is no opaque region or hidechrome=true, set margins
|
2011-01-27 22:58:58 +00:00
|
|
|
// to support a full sheet of glass. Comments in MSDN indicate
|
|
|
|
// all values must be set to -1 to get a full sheet of glass.
|
|
|
|
MARGINS margins = { -1, -1, -1, -1 };
|
2011-05-13 16:40:46 +00:00
|
|
|
if (!aOpaqueRegion.IsEmpty()) {
|
2011-01-04 03:56:57 +00:00
|
|
|
nsIntRect pluginBounds;
|
|
|
|
for (nsIWidget* child = GetFirstChild(); child; child = child->GetNextSibling()) {
|
|
|
|
nsWindowType type;
|
|
|
|
child->GetWindowType(type);
|
|
|
|
if (type == eWindowType_plugin) {
|
2011-01-27 22:58:58 +00:00
|
|
|
// Collect the bounds of all plugins for GetLargestRectangle.
|
2011-01-04 03:56:57 +00:00
|
|
|
nsIntRect childBounds;
|
|
|
|
child->GetBounds(childBounds);
|
|
|
|
pluginBounds.UnionRect(pluginBounds, childBounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-13 16:40:46 +00:00
|
|
|
nsIntRect clientBounds;
|
|
|
|
GetClientBounds(clientBounds);
|
|
|
|
|
2011-01-04 03:56:57 +00:00
|
|
|
// Find the largest rectangle and use that to calculate the inset. Our top
|
|
|
|
// priority is to include the bounds of all plugins.
|
2011-05-13 16:40:46 +00:00
|
|
|
nsIntRect largest = aOpaqueRegion.GetLargestRectangle(pluginBounds);
|
2011-05-13 16:40:46 +00:00
|
|
|
margins.cxLeftWidth = largest.x;
|
|
|
|
margins.cxRightWidth = clientBounds.width - largest.XMost();
|
|
|
|
margins.cyBottomHeight = clientBounds.height - largest.YMost();
|
|
|
|
if (mCustomNonClient) {
|
|
|
|
// The minimum glass height must be the caption buttons height,
|
|
|
|
// otherwise the buttons are drawn incorrectly.
|
2011-06-25 14:06:02 +00:00
|
|
|
largest.y = NS_MAX<PRUint32>(largest.y,
|
2011-05-13 16:40:46 +00:00
|
|
|
nsUXThemeData::sCommandButtons[CMDBUTTONIDX_BUTTONBOX].cy);
|
2010-11-13 06:34:57 +00:00
|
|
|
}
|
2011-05-13 16:40:46 +00:00
|
|
|
margins.cyTopHeight = largest.y;
|
2010-03-17 22:56:00 +00:00
|
|
|
}
|
2010-06-25 02:01:07 +00:00
|
|
|
|
|
|
|
// Only update glass area if there are changes
|
2010-03-17 22:56:00 +00:00
|
|
|
if (memcmp(&mGlassMargins, &margins, sizeof mGlassMargins)) {
|
|
|
|
mGlassMargins = margins;
|
|
|
|
UpdateGlass();
|
|
|
|
}
|
|
|
|
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
|
|
|
}
|
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
void nsWindow::UpdateGlass()
|
|
|
|
{
|
2010-03-17 22:56:00 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2010-08-18 03:07:10 +00:00
|
|
|
MARGINS margins = mGlassMargins;
|
2010-06-25 02:01:07 +00:00
|
|
|
|
|
|
|
// DWMNCRP_USEWINDOWSTYLE - The non-client rendering area is
|
|
|
|
// rendered based on the window style.
|
|
|
|
// DWMNCRP_ENABLED - The non-client area rendering is
|
|
|
|
// enabled; the window style is ignored.
|
2010-03-17 22:56:00 +00:00
|
|
|
DWMNCRENDERINGPOLICY policy = DWMNCRP_USEWINDOWSTYLE;
|
2010-08-18 03:07:10 +00:00
|
|
|
switch (mTransparencyMode) {
|
|
|
|
case eTransparencyBorderlessGlass:
|
2011-02-04 19:52:03 +00:00
|
|
|
// Only adjust if there is some opaque rectangle
|
2010-08-21 00:11:57 +00:00
|
|
|
if (margins.cxLeftWidth >= 0) {
|
2011-02-04 19:52:03 +00:00
|
|
|
margins.cxLeftWidth += kGlassMarginAdjustment;
|
|
|
|
margins.cyTopHeight += kGlassMarginAdjustment;
|
|
|
|
margins.cxRightWidth += kGlassMarginAdjustment;
|
|
|
|
margins.cyBottomHeight += kGlassMarginAdjustment;
|
2010-08-18 03:07:10 +00:00
|
|
|
}
|
|
|
|
// Fall through
|
|
|
|
case eTransparencyGlass:
|
2010-03-17 22:56:00 +00:00
|
|
|
policy = DWMNCRP_ENABLED;
|
2010-08-18 03:07:10 +00:00
|
|
|
break;
|
2010-03-17 22:56:00 +00:00
|
|
|
}
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2011-01-27 22:58:55 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("glass margins: left:%d top:%d right:%d bottom:%d\n",
|
|
|
|
margins.cxLeftWidth, margins.cyTopHeight,
|
|
|
|
margins.cxRightWidth, margins.cyBottomHeight));
|
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
// Extends the window frame behind the client area
|
2010-03-17 22:56:00 +00:00
|
|
|
if(nsUXThemeData::CheckForCompositor()) {
|
2011-01-27 22:58:58 +00:00
|
|
|
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(mWnd, &margins);
|
|
|
|
nsUXThemeData::dwmSetWindowAttributePtr(mWnd, DWMWA_NCRENDERING_POLICY, &policy, sizeof policy);
|
2010-03-17 22:56:00 +00:00
|
|
|
}
|
|
|
|
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif
|
2000-04-30 15:29:32 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::HideWindowChrome
|
|
|
|
*
|
|
|
|
* Show or hide window chrome.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_IMETHODIMP nsWindow::HideWindowChrome(bool aShouldHide)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND hwnd = WinUtils::GetTopLevelHWND(mWnd, true);
|
|
|
|
if (!WinUtils::GetNSWindowPtr(hwnd))
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
NS_WARNING("Trying to hide window decorations in an embedded context");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2000-03-21 22:06:29 +00:00
|
|
|
|
2010-06-28 06:04:20 +00:00
|
|
|
if (mHideChrome == aShouldHide)
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
DWORD_PTR style, exStyle;
|
2010-06-25 02:01:07 +00:00
|
|
|
mHideChrome = aShouldHide;
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aShouldHide) {
|
|
|
|
DWORD_PTR tempStyle = ::GetWindowLongPtrW(hwnd, GWL_STYLE);
|
|
|
|
DWORD_PTR tempExStyle = ::GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
2000-03-21 22:06:29 +00:00
|
|
|
|
2010-06-25 22:50:36 +00:00
|
|
|
style = tempStyle & ~(WS_CAPTION | WS_THICKFRAME);
|
2009-06-29 19:36:16 +00:00
|
|
|
exStyle = tempExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE |
|
|
|
|
WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
2000-05-07 05:14:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
mOldStyle = tempStyle;
|
|
|
|
mOldExStyle = tempExStyle;
|
|
|
|
}
|
|
|
|
else {
|
2010-06-25 22:50:36 +00:00
|
|
|
if (!mOldStyle || !mOldExStyle) {
|
2009-06-29 19:36:16 +00:00
|
|
|
mOldStyle = ::GetWindowLongPtrW(hwnd, GWL_STYLE);
|
|
|
|
mOldExStyle = ::GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
2010-06-25 17:56:39 +00:00
|
|
|
}
|
2000-05-07 05:14:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
style = mOldStyle;
|
|
|
|
exStyle = mOldExStyle;
|
|
|
|
}
|
2000-05-07 05:14:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
VERIFY_WINDOW_STYLE(style);
|
|
|
|
::SetWindowLongPtrW(hwnd, GWL_STYLE, style);
|
|
|
|
::SetWindowLongPtrW(hwnd, GWL_EXSTYLE, exStyle);
|
2000-05-07 05:14:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-05-07 05:14:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
2011-10-08 01:52:09 +00:00
|
|
|
* SECTION: nsWindow::Invalidate
|
2009-06-29 19:36:16 +00:00
|
|
|
*
|
2009-09-07 21:48:23 +00:00
|
|
|
* Invalidate an area of the client for painting.
|
2009-06-29 19:36:16 +00:00
|
|
|
*
|
|
|
|
**************************************************************/
|
2000-05-07 05:14:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Invalidate this component visible area
|
2011-12-24 03:52:21 +00:00
|
|
|
NS_METHOD nsWindow::Invalidate(bool aEraseBackground,
|
2011-10-08 01:52:09 +00:00
|
|
|
bool aUpdateNCArea,
|
|
|
|
bool aIncludeChildren)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2011-10-08 01:52:09 +00:00
|
|
|
if (!mWnd) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef WIDGET_DEBUG_OUTPUT
|
2011-10-08 01:52:09 +00:00
|
|
|
debug_DumpInvalidate(stdout,
|
|
|
|
this,
|
|
|
|
nsnull,
|
|
|
|
nsCAutoString("noname"),
|
|
|
|
(PRInt32) mWnd);
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif // WIDGET_DEBUG_OUTPUT
|
2010-01-29 04:02:12 +00:00
|
|
|
|
2011-10-08 01:52:09 +00:00
|
|
|
DWORD flags = RDW_INVALIDATE;
|
|
|
|
if (aEraseBackground) {
|
|
|
|
flags |= RDW_ERASE;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2011-10-08 01:52:09 +00:00
|
|
|
if (aUpdateNCArea) {
|
|
|
|
flags |= RDW_FRAME;
|
|
|
|
}
|
|
|
|
if (aIncludeChildren) {
|
|
|
|
flags |= RDW_ALLCHILDREN;
|
|
|
|
}
|
|
|
|
|
|
|
|
VERIFY(::RedrawWindow(mWnd, NULL, NULL, flags));
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-09-11 23:24:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Invalidate this component visible area
|
2011-12-24 03:52:21 +00:00
|
|
|
NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (mWnd)
|
|
|
|
{
|
|
|
|
#ifdef WIDGET_DEBUG_OUTPUT
|
|
|
|
debug_DumpInvalidate(stdout,
|
|
|
|
this,
|
|
|
|
&aRect,
|
|
|
|
nsCAutoString("noname"),
|
|
|
|
(PRInt32) mWnd);
|
|
|
|
#endif // WIDGET_DEBUG_OUTPUT
|
2004-09-11 23:24:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
RECT rect;
|
2004-09-11 23:24:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
rect.left = aRect.x;
|
|
|
|
rect.top = aRect.y;
|
|
|
|
rect.right = aRect.x + aRect.width;
|
|
|
|
rect.bottom = aRect.y + aRect.height;
|
2004-09-11 23:24:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
VERIFY(::InvalidateRect(mWnd, &rect, FALSE));
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-09-11 23:24:30 +00:00
|
|
|
|
2009-07-08 16:13:13 +00:00
|
|
|
NS_IMETHODIMP
|
2011-09-29 06:19:26 +00:00
|
|
|
nsWindow::MakeFullScreen(bool aFullScreen)
|
2009-07-08 16:13:13 +00:00
|
|
|
{
|
2011-09-01 14:15:09 +00:00
|
|
|
// taskbarInfo will be NULL pre Windows 7 until Bug 680227 is resolved.
|
|
|
|
nsCOMPtr<nsIWinTaskbar> taskbarInfo =
|
|
|
|
do_GetService(NS_TASKBAR_CONTRACTID);
|
|
|
|
|
2010-09-07 14:58:26 +00:00
|
|
|
mFullscreenMode = aFullScreen;
|
2010-06-28 06:04:20 +00:00
|
|
|
if (aFullScreen) {
|
2010-08-27 04:44:01 +00:00
|
|
|
if (mSizeMode == nsSizeMode_Fullscreen)
|
|
|
|
return NS_OK;
|
|
|
|
mOldSizeMode = mSizeMode;
|
2010-06-28 06:04:20 +00:00
|
|
|
SetSizeMode(nsSizeMode_Fullscreen);
|
2011-09-01 14:15:09 +00:00
|
|
|
|
|
|
|
// Notify the taskbar that we will be entering full screen mode.
|
|
|
|
if (taskbarInfo) {
|
|
|
|
taskbarInfo->PrepareFullScreenHWND(mWnd, TRUE);
|
|
|
|
}
|
2010-06-28 06:04:20 +00:00
|
|
|
} else {
|
|
|
|
SetSizeMode(mOldSizeMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateNonClientMargins();
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool visible = mIsVisible;
|
2011-04-11 17:46:18 +00:00
|
|
|
if (mOldSizeMode == nsSizeMode_Normal)
|
2011-10-02 02:16:19 +00:00
|
|
|
Show(false);
|
2011-03-28 21:54:05 +00:00
|
|
|
|
2010-06-28 06:04:20 +00:00
|
|
|
// Will call hide chrome, reposition window. Note this will
|
|
|
|
// also cache dimensions for restoration, so it should only
|
|
|
|
// be called once per fullscreen request.
|
2010-08-27 04:44:01 +00:00
|
|
|
nsresult rv = nsBaseWidget::MakeFullScreen(aFullScreen);
|
|
|
|
|
2011-03-28 21:54:05 +00:00
|
|
|
if (visible) {
|
2011-10-02 02:16:19 +00:00
|
|
|
Show(true);
|
2011-12-24 03:52:21 +00:00
|
|
|
Invalidate();
|
2010-09-16 00:39:40 +00:00
|
|
|
}
|
|
|
|
|
2011-09-01 14:15:09 +00:00
|
|
|
// Notify the taskbar that we have exited full screen mode.
|
|
|
|
if (!aFullScreen && taskbarInfo) {
|
|
|
|
taskbarInfo->PrepareFullScreenHWND(mWnd, FALSE);
|
|
|
|
}
|
|
|
|
|
2010-08-27 04:44:01 +00:00
|
|
|
// Let the dom know via web shell window
|
2011-10-02 02:16:19 +00:00
|
|
|
nsSizeModeEvent event(true, NS_SIZEMODE, this);
|
2010-08-27 04:44:01 +00:00
|
|
|
event.mSizeMode = mSizeMode;
|
|
|
|
InitEvent(event);
|
|
|
|
DispatchWindowEvent(&event);
|
|
|
|
|
|
|
|
return rv;
|
2009-07-08 16:13:13 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
2007-09-27 16:38:26 +00:00
|
|
|
*
|
2009-06-29 19:36:16 +00:00
|
|
|
* SECTION: Native data storage
|
2007-09-27 16:38:26 +00:00
|
|
|
*
|
2009-06-29 19:36:16 +00:00
|
|
|
* nsIWidget::GetNativeData
|
|
|
|
* nsIWidget::FreeNativeData
|
|
|
|
*
|
|
|
|
* Set or clear native data based on a constant.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2005-04-13 05:52:02 +00:00
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Return some native data according to aDataType
|
|
|
|
void* nsWindow::GetNativeData(PRUint32 aDataType)
|
|
|
|
{
|
2010-11-08 09:06:13 +00:00
|
|
|
nsAutoString className;
|
2004-09-03 08:44:23 +00:00
|
|
|
switch (aDataType) {
|
2010-09-06 14:09:19 +00:00
|
|
|
case NS_NATIVE_TMP_WINDOW:
|
2010-11-08 09:06:13 +00:00
|
|
|
GetWindowClass(className);
|
2010-09-20 09:40:41 +00:00
|
|
|
return (void*)::CreateWindowExW(mIsRTL ? WS_EX_LAYOUTRTL : 0,
|
2010-11-08 09:06:13 +00:00
|
|
|
className.get(),
|
2010-09-06 14:09:19 +00:00
|
|
|
L"",
|
|
|
|
WS_CHILD,
|
|
|
|
CW_USEDEFAULT,
|
|
|
|
CW_USEDEFAULT,
|
|
|
|
CW_USEDEFAULT,
|
|
|
|
CW_USEDEFAULT,
|
|
|
|
mWnd,
|
|
|
|
NULL,
|
|
|
|
nsToolkit::mDllInstance,
|
|
|
|
NULL);
|
2008-11-27 05:42:18 +00:00
|
|
|
case NS_NATIVE_PLUGIN_PORT:
|
2004-09-03 08:44:23 +00:00
|
|
|
case NS_NATIVE_WIDGET:
|
|
|
|
case NS_NATIVE_WINDOW:
|
2011-08-31 19:01:38 +00:00
|
|
|
case NS_NATIVE_SHAREABLE_WINDOW:
|
2004-09-03 08:44:23 +00:00
|
|
|
return (void*)mWnd;
|
|
|
|
case NS_NATIVE_GRAPHIC:
|
|
|
|
// XXX: This is sleezy!! Remember to Release the DC after using it!
|
2004-07-27 19:14:44 +00:00
|
|
|
#ifdef MOZ_XUL
|
2008-08-13 00:44:14 +00:00
|
|
|
return (void*)(eTransparencyTransparent == mTransparencyMode) ?
|
2006-04-04 20:57:13 +00:00
|
|
|
mMemoryDC : ::GetDC(mWnd);
|
2004-07-27 19:14:44 +00:00
|
|
|
#else
|
2004-09-03 08:44:23 +00:00
|
|
|
return (void*)::GetDC(mWnd);
|
2004-07-27 19:14:44 +00:00
|
|
|
#endif
|
2009-02-10 20:56:51 +00:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
2009-02-23 08:56:33 +00:00
|
|
|
case NS_NATIVE_TSF_THREAD_MGR:
|
|
|
|
return nsTextStore::GetThreadMgr();
|
|
|
|
case NS_NATIVE_TSF_CATEGORY_MGR:
|
|
|
|
return nsTextStore::GetCategoryMgr();
|
|
|
|
case NS_NATIVE_TSF_DISPLAY_ATTR_MGR:
|
|
|
|
return nsTextStore::GetDisplayAttrMgr();
|
2009-02-10 20:56:51 +00:00
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2004-09-03 08:44:23 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2004-09-03 08:44:23 +00:00
|
|
|
return NULL;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Free some native data according to aDataType
|
1999-05-27 23:20:09 +00:00
|
|
|
void nsWindow::FreeNativeData(void * data, PRUint32 aDataType)
|
|
|
|
{
|
2004-09-03 08:44:23 +00:00
|
|
|
switch (aDataType)
|
1999-05-27 23:20:09 +00:00
|
|
|
{
|
|
|
|
case NS_NATIVE_GRAPHIC:
|
2004-07-27 19:14:44 +00:00
|
|
|
#ifdef MOZ_XUL
|
2008-08-13 00:44:14 +00:00
|
|
|
if (eTransparencyTransparent != mTransparencyMode)
|
2004-09-03 08:44:23 +00:00
|
|
|
::ReleaseDC(mWnd, (HDC)data);
|
2004-07-27 19:14:44 +00:00
|
|
|
#else
|
|
|
|
::ReleaseDC(mWnd, (HDC)data);
|
|
|
|
#endif
|
|
|
|
break;
|
1999-05-27 23:20:09 +00:00
|
|
|
case NS_NATIVE_WIDGET:
|
|
|
|
case NS_NATIVE_WINDOW:
|
|
|
|
case NS_NATIVE_PLUGIN_PORT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetTitle
|
|
|
|
*
|
|
|
|
* Set the main windows title text.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_METHOD nsWindow::SetTitle(const nsAString& aTitle)
|
2007-11-07 08:54:06 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
const nsString& strTitle = PromiseFlatString(aTitle);
|
|
|
|
::SendMessageW(mWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)(LPCWSTR)strTitle.get());
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-11-07 08:54:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetIcon
|
|
|
|
*
|
|
|
|
* Set the main windows icon.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
NS_METHOD nsWindow::SetIcon(const nsAString& aIconSpec)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
// Assume the given string is a local identifier for an icon file.
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsCOMPtr<nsILocalFile> iconFile;
|
|
|
|
ResolveIconName(aIconSpec, NS_LITERAL_STRING(".ico"),
|
|
|
|
getter_AddRefs(iconFile));
|
|
|
|
if (!iconFile)
|
|
|
|
return NS_OK; // not an error if icon is not found
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsAutoString iconPath;
|
|
|
|
iconFile->GetPath(iconPath);
|
|
|
|
|
|
|
|
// XXX this should use MZLU (see bug 239279)
|
|
|
|
|
|
|
|
::SetLastError(0);
|
|
|
|
|
|
|
|
HICON bigIcon = (HICON)::LoadImageW(NULL,
|
|
|
|
(LPCWSTR)iconPath.get(),
|
|
|
|
IMAGE_ICON,
|
|
|
|
::GetSystemMetrics(SM_CXICON),
|
|
|
|
::GetSystemMetrics(SM_CYICON),
|
|
|
|
LR_LOADFROMFILE );
|
|
|
|
HICON smallIcon = (HICON)::LoadImageW(NULL,
|
|
|
|
(LPCWSTR)iconPath.get(),
|
|
|
|
IMAGE_ICON,
|
|
|
|
::GetSystemMetrics(SM_CXSMICON),
|
|
|
|
::GetSystemMetrics(SM_CYSMICON),
|
|
|
|
LR_LOADFROMFILE );
|
|
|
|
|
|
|
|
if (bigIcon) {
|
|
|
|
HICON icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)bigIcon);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
|
|
|
}
|
|
|
|
#ifdef DEBUG_SetIcon
|
|
|
|
else {
|
|
|
|
NS_LossyConvertUTF16toASCII cPath(iconPath);
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("\nIcon load error; icon=%s, rc=0x%08X\n\n",
|
|
|
|
cPath.get(), ::GetLastError()));
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (smallIcon) {
|
|
|
|
HICON icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)smallIcon);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
|
|
|
}
|
|
|
|
#ifdef DEBUG_SetIcon
|
|
|
|
else {
|
|
|
|
NS_LossyConvertUTF16toASCII cPath(iconPath);
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("\nSmall icon load error; icon=%s, rc=0x%08X\n\n",
|
|
|
|
cPath.get(), ::GetLastError()));
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
#endif
|
1998-09-28 22:32:48 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::WidgetToScreenOffset
|
|
|
|
*
|
|
|
|
* Return this widget's origin in screen coordinates.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsIntPoint nsWindow::WidgetToScreenOffset()
|
|
|
|
{
|
|
|
|
POINT point;
|
|
|
|
point.x = 0;
|
|
|
|
point.y = 0;
|
|
|
|
::ClientToScreen(mWnd, &point);
|
|
|
|
return nsIntPoint(point.x, point.y);
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2010-07-27 13:38:03 +00:00
|
|
|
nsIntSize nsWindow::ClientToWindowSize(const nsIntSize& aClientSize)
|
|
|
|
{
|
|
|
|
if (!IsPopupWithTitleBar())
|
|
|
|
return aClientSize;
|
|
|
|
|
|
|
|
// just use (200, 200) as the position
|
|
|
|
RECT r;
|
|
|
|
r.left = 200;
|
|
|
|
r.top = 200;
|
|
|
|
r.right = 200 + aClientSize.width;
|
|
|
|
r.bottom = 200 + aClientSize.height;
|
2011-10-02 02:16:19 +00:00
|
|
|
::AdjustWindowRectEx(&r, WindowStyle(), false, WindowExStyle());
|
2010-07-27 13:38:03 +00:00
|
|
|
|
|
|
|
return nsIntSize(r.right - r.left, r.bottom - r.top);
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::EnableDragDrop
|
|
|
|
*
|
|
|
|
* Enables/Disables drag and drop of files on this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::EnableDragDrop(bool aEnable)
|
1999-03-09 23:48:58 +00:00
|
|
|
{
|
2010-06-02 13:02:05 +00:00
|
|
|
NS_ASSERTION(mWnd, "nsWindow::EnableDragDrop() called after Destroy()");
|
|
|
|
|
1999-08-26 14:41:17 +00:00
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
if (aEnable) {
|
|
|
|
if (nsnull == mNativeDragTarget) {
|
|
|
|
mNativeDragTarget = new nsNativeDragTarget(this);
|
|
|
|
if (NULL != mNativeDragTarget) {
|
|
|
|
mNativeDragTarget->AddRef();
|
|
|
|
if (S_OK == ::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget,TRUE,FALSE)) {
|
|
|
|
if (S_OK == ::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget)) {
|
|
|
|
rv = NS_OK;
|
|
|
|
}
|
|
|
|
}
|
1999-04-17 13:45:10 +00:00
|
|
|
}
|
1999-08-26 14:41:17 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (nsnull != mWnd && NULL != mNativeDragTarget) {
|
|
|
|
::RevokeDragDrop(mWnd);
|
|
|
|
if (S_OK == ::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget, FALSE, TRUE)) {
|
|
|
|
rv = NS_OK;
|
|
|
|
}
|
2010-06-02 13:02:05 +00:00
|
|
|
mNativeDragTarget->DragCancel();
|
1999-08-26 14:41:17 +00:00
|
|
|
NS_RELEASE(mNativeDragTarget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
1999-03-09 23:48:58 +00:00
|
|
|
}
|
1999-03-01 16:22:40 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::CaptureMouse
|
|
|
|
*
|
|
|
|
* Enables/Disables system mouse capture.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
NS_METHOD nsWindow::CaptureMouse(bool aCapture)
|
2000-02-02 15:00:59 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!nsToolkit::gMouseTrailer) {
|
|
|
|
NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
|
|
|
|
return NS_OK;
|
2000-02-02 15:00:59 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aCapture) {
|
|
|
|
nsToolkit::gMouseTrailer->SetCaptureWindow(mWnd);
|
|
|
|
::SetCapture(mWnd);
|
|
|
|
} else {
|
|
|
|
nsToolkit::gMouseTrailer->SetCaptureWindow(NULL);
|
|
|
|
::ReleaseCapture();
|
|
|
|
}
|
2011-01-20 03:21:50 +00:00
|
|
|
sIsInMouseCapture = aCapture;
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
2000-02-02 15:00:59 +00:00
|
|
|
}
|
1999-04-23 14:30:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::CaptureRollupEvents
|
|
|
|
*
|
|
|
|
* Dealing with event rollup on destroy for popups. Enables &
|
|
|
|
* Disables system capture of any and all events that would
|
|
|
|
* cause a dropdown to be rolled up.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1999-04-23 14:30:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool aDoCapture,
|
|
|
|
bool aConsumeRollupEvent)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (aDoCapture) {
|
|
|
|
/* we haven't bothered carrying a weak reference to sRollupWidget because
|
|
|
|
we believe lifespan is properly scoped. this next assertion helps
|
|
|
|
assure that remains true. */
|
|
|
|
NS_ASSERTION(!sRollupWidget, "rollup widget reassigned before release");
|
|
|
|
sRollupConsumeEvent = aConsumeRollupEvent;
|
|
|
|
NS_IF_RELEASE(sRollupWidget);
|
|
|
|
sRollupListener = aListener;
|
|
|
|
sRollupWidget = this;
|
|
|
|
NS_ADDREF(this);
|
|
|
|
if (!sMsgFilterHook && !sCallProcHook && !sCallMouseHook) {
|
|
|
|
RegisterSpecialDropdownHooks();
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
sProcessHook = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
} else {
|
2009-12-22 23:49:33 +00:00
|
|
|
sRollupListener = nsnull;
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_IF_RELEASE(sRollupWidget);
|
2011-10-02 02:16:19 +00:00
|
|
|
sProcessHook = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
UnregisterSpecialDropdownHooks();
|
2001-12-29 22:21:31 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-04-23 14:30:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::GetAttention
|
|
|
|
*
|
|
|
|
* Bring this window to the user's attention.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Draw user's attention to this window until it comes to foreground.
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::GetAttention(PRInt32 aCycleCount)
|
|
|
|
{
|
|
|
|
// Got window?
|
|
|
|
if (!mWnd)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND flashWnd = WinUtils::GetTopLevelHWND(mWnd, false, false);
|
2009-06-29 19:36:16 +00:00
|
|
|
HWND fgWnd = ::GetForegroundWindow();
|
2011-10-09 14:19:24 +00:00
|
|
|
// Don't flash if the flash count is 0 or if the foreground window is our
|
|
|
|
// window handle or that of our owned-most window.
|
|
|
|
if (aCycleCount == 0 ||
|
|
|
|
flashWnd == fgWnd ||
|
2012-01-04 10:21:44 +00:00
|
|
|
flashWnd == WinUtils::GetTopLevelHWND(fgWnd, false, false)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD defaultCycleCount = 0;
|
|
|
|
::SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &defaultCycleCount, 0);
|
|
|
|
|
|
|
|
FLASHWINFO flashInfo = { sizeof(FLASHWINFO), flashWnd,
|
|
|
|
FLASHW_ALL, aCycleCount > 0 ? aCycleCount : defaultCycleCount, 0 };
|
|
|
|
::FlashWindowEx(&flashInfo);
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
1999-04-23 14:30:51 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::StopFlashing()
|
2008-12-15 03:54:54 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
HWND flashWnd = mWnd;
|
|
|
|
while (HWND ownerWnd = ::GetWindow(flashWnd, GW_OWNER)) {
|
|
|
|
flashWnd = ownerWnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
FLASHWINFO flashInfo = { sizeof(FLASHWINFO), flashWnd,
|
|
|
|
FLASHW_STOP, 0, 0 };
|
|
|
|
::FlashWindowEx(&flashInfo);
|
2008-12-15 03:54:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::HasPendingInputEvent
|
|
|
|
*
|
|
|
|
* Ask whether there user input events pending. All input events are
|
|
|
|
* included, including those not targeted at this nsIwidget instance.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2009-06-29 19:36:16 +00:00
|
|
|
nsWindow::HasPendingInputEvent()
|
2008-04-30 04:12:15 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
// If there is pending input or the user is currently
|
|
|
|
// moving the window then return true.
|
|
|
|
// Note: When the user is moving the window WIN32 spins
|
|
|
|
// a separate event loop and input events are not
|
|
|
|
// reported to the application.
|
2009-07-21 22:53:04 +00:00
|
|
|
if (HIWORD(GetQueueStatus(QS_INPUT)))
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-07-21 22:53:04 +00:00
|
|
|
GUITHREADINFO guiInfo;
|
|
|
|
guiInfo.cbSize = sizeof(GUITHREADINFO);
|
|
|
|
if (!GetGUIThreadInfo(GetCurrentThreadId(), &guiInfo))
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-07-21 22:53:04 +00:00
|
|
|
return GUI_INMOVESIZE == (guiInfo.flags & GUI_INMOVESIZE);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2008-04-30 04:12:15 +00:00
|
|
|
|
2010-03-31 03:02:58 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::GetLayerManager
|
|
|
|
*
|
|
|
|
* Get the layer manager associated with this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
2011-01-12 20:13:41 +00:00
|
|
|
struct LayerManagerPrefs {
|
|
|
|
LayerManagerPrefs()
|
2011-10-02 02:16:19 +00:00
|
|
|
: mAccelerateByDefault(true)
|
|
|
|
, mDisableAcceleration(false)
|
|
|
|
, mPreferOpenGL(false)
|
|
|
|
, mPreferD3D9(false)
|
2011-01-12 20:13:41 +00:00
|
|
|
{}
|
2011-09-29 06:19:26 +00:00
|
|
|
bool mAccelerateByDefault;
|
|
|
|
bool mDisableAcceleration;
|
|
|
|
bool mForceAcceleration;
|
|
|
|
bool mPreferOpenGL;
|
|
|
|
bool mPreferD3D9;
|
2011-01-12 20:13:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
GetLayerManagerPrefs(LayerManagerPrefs* aManagerPrefs)
|
|
|
|
{
|
2011-05-28 07:03:00 +00:00
|
|
|
Preferences::GetBool("layers.acceleration.disabled",
|
2011-01-12 20:13:41 +00:00
|
|
|
&aManagerPrefs->mDisableAcceleration);
|
2011-05-28 07:03:00 +00:00
|
|
|
Preferences::GetBool("layers.acceleration.force-enabled",
|
2011-01-18 20:11:19 +00:00
|
|
|
&aManagerPrefs->mForceAcceleration);
|
2011-05-28 07:03:00 +00:00
|
|
|
Preferences::GetBool("layers.prefer-opengl",
|
2011-01-12 20:13:41 +00:00
|
|
|
&aManagerPrefs->mPreferOpenGL);
|
2011-05-28 07:03:00 +00:00
|
|
|
Preferences::GetBool("layers.prefer-d3d9",
|
2011-01-12 20:13:41 +00:00
|
|
|
&aManagerPrefs->mPreferD3D9);
|
|
|
|
|
|
|
|
const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
|
|
|
|
aManagerPrefs->mAccelerateByDefault =
|
|
|
|
aManagerPrefs->mAccelerateByDefault ||
|
|
|
|
(acceleratedEnv && (*acceleratedEnv != '0'));
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool safeMode = false;
|
2011-01-12 20:13:41 +00:00
|
|
|
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
|
|
|
|
if (xr)
|
|
|
|
xr->GetInSafeMode(&safeMode);
|
|
|
|
aManagerPrefs->mDisableAcceleration =
|
|
|
|
aManagerPrefs->mDisableAcceleration || safeMode;
|
|
|
|
}
|
|
|
|
|
2011-08-09 19:38:26 +00:00
|
|
|
LayerManager*
|
|
|
|
nsWindow::GetLayerManager(PLayersChild* aShadowManager,
|
|
|
|
LayersBackend aBackendHint,
|
|
|
|
LayerManagerPersistence aPersistence,
|
|
|
|
bool* aAllowRetaining)
|
2010-03-31 03:02:58 +00:00
|
|
|
{
|
2010-10-15 10:34:29 +00:00
|
|
|
if (aAllowRetaining) {
|
|
|
|
*aAllowRetaining = true;
|
|
|
|
}
|
|
|
|
|
2010-11-19 18:50:45 +00:00
|
|
|
#ifdef MOZ_ENABLE_D3D10_LAYER
|
|
|
|
if (mLayerManager) {
|
|
|
|
if (mLayerManager->GetBackendType() ==
|
|
|
|
mozilla::layers::LayerManager::LAYERS_D3D10)
|
|
|
|
{
|
|
|
|
mozilla::layers::LayerManagerD3D10 *layerManagerD3D10 =
|
|
|
|
static_cast<mozilla::layers::LayerManagerD3D10*>(mLayerManager.get());
|
|
|
|
if (layerManagerD3D10->device() !=
|
|
|
|
gfxWindowsPlatform::GetPlatform()->GetD3D10Device())
|
|
|
|
{
|
2010-12-07 02:05:25 +00:00
|
|
|
mLayerManager->Destroy();
|
2010-11-19 18:50:45 +00:00
|
|
|
mLayerManager = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-10-04 01:20:43 +00:00
|
|
|
RECT windowRect;
|
|
|
|
::GetClientRect(mWnd, &windowRect);
|
|
|
|
|
2010-12-07 02:06:31 +00:00
|
|
|
if (!mLayerManager ||
|
|
|
|
(!sAllowD3D9 && aPersistence == LAYER_MANAGER_PERSISTENT &&
|
|
|
|
mLayerManager->GetBackendType() ==
|
|
|
|
mozilla::layers::LayerManager::LAYERS_BASIC)) {
|
|
|
|
// If D3D9 is not currently allowed but the permanent manager is required,
|
|
|
|
// -and- we're currently using basic layers, run through this check.
|
2011-01-12 20:13:41 +00:00
|
|
|
LayerManagerPrefs prefs;
|
|
|
|
GetLayerManagerPrefs(&prefs);
|
2010-09-03 18:08:23 +00:00
|
|
|
|
2010-09-04 03:21:26 +00:00
|
|
|
/* We don't currently support using an accelerated layer manager with
|
|
|
|
* transparent windows so don't even try. I'm also not sure if we even
|
|
|
|
* want to support this case. See bug #593471 */
|
2011-01-12 20:13:41 +00:00
|
|
|
if (eTransparencyTransparent == mTransparencyMode ||
|
2011-10-04 01:20:43 +00:00
|
|
|
prefs.mDisableAcceleration ||
|
|
|
|
windowRect.right - windowRect.left > MAX_ACCELERATED_DIMENSION ||
|
|
|
|
windowRect.bottom - windowRect.top > MAX_ACCELERATED_DIMENSION)
|
2011-10-02 02:16:19 +00:00
|
|
|
mUseAcceleratedRendering = false;
|
2011-01-12 20:13:41 +00:00
|
|
|
else if (prefs.mAccelerateByDefault)
|
2011-10-02 02:16:19 +00:00
|
|
|
mUseAcceleratedRendering = true;
|
2010-08-28 02:44:37 +00:00
|
|
|
|
2010-05-24 15:28:54 +00:00
|
|
|
if (mUseAcceleratedRendering) {
|
2010-12-07 02:06:31 +00:00
|
|
|
if (aPersistence == LAYER_MANAGER_PERSISTENT && !sAllowD3D9) {
|
|
|
|
// This will clear out our existing layer manager if we have one since
|
|
|
|
// if we hit this with a LayerManager we're always using BasicLayers.
|
|
|
|
nsToolkit::StartAllowingD3D9();
|
|
|
|
}
|
|
|
|
|
2010-09-30 22:53:53 +00:00
|
|
|
#ifdef MOZ_ENABLE_D3D10_LAYER
|
2011-11-07 20:11:44 +00:00
|
|
|
if (!prefs.mPreferD3D9 && !prefs.mPreferOpenGL) {
|
2010-09-30 22:53:53 +00:00
|
|
|
nsRefPtr<mozilla::layers::LayerManagerD3D10> layerManager =
|
|
|
|
new mozilla::layers::LayerManagerD3D10(this);
|
|
|
|
if (layerManager->Initialize()) {
|
|
|
|
mLayerManager = layerManager;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2010-06-06 10:37:44 +00:00
|
|
|
#ifdef MOZ_ENABLE_D3D9_LAYER
|
2011-01-12 20:13:41 +00:00
|
|
|
if (!prefs.mPreferOpenGL && !mLayerManager && sAllowD3D9) {
|
2010-08-28 02:44:37 +00:00
|
|
|
nsRefPtr<mozilla::layers::LayerManagerD3D9> layerManager =
|
|
|
|
new mozilla::layers::LayerManagerD3D9(this);
|
|
|
|
if (layerManager->Initialize()) {
|
|
|
|
mLayerManager = layerManager;
|
2010-05-24 15:28:54 +00:00
|
|
|
}
|
2010-08-28 02:44:37 +00:00
|
|
|
}
|
2010-06-06 10:37:44 +00:00
|
|
|
#endif
|
2011-01-12 20:13:41 +00:00
|
|
|
if (!mLayerManager && prefs.mPreferOpenGL) {
|
2011-01-18 20:11:19 +00:00
|
|
|
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
|
|
|
PRInt32 status = nsIGfxInfo::FEATURE_NO_INFO;
|
|
|
|
|
|
|
|
if (gfxInfo && !prefs.mForceAcceleration) {
|
|
|
|
gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == nsIGfxInfo::FEATURE_NO_INFO) {
|
|
|
|
nsRefPtr<mozilla::layers::LayerManagerOGL> layerManager =
|
|
|
|
new mozilla::layers::LayerManagerOGL(this);
|
|
|
|
if (layerManager->Initialize()) {
|
|
|
|
mLayerManager = layerManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
NS_WARNING("OpenGL accelerated layers are not supported on this system.");
|
2010-05-24 15:28:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-09-04 03:21:26 +00:00
|
|
|
|
|
|
|
// Fall back to software if we couldn't use any hardware backends.
|
|
|
|
if (!mLayerManager)
|
2010-09-14 23:40:23 +00:00
|
|
|
mLayerManager = CreateBasicLayerManager();
|
2010-05-24 15:28:54 +00:00
|
|
|
}
|
|
|
|
|
2011-10-02 19:11:19 +00:00
|
|
|
NS_ASSERTION(mLayerManager, "Couldn't provide a valid layer manager.");
|
|
|
|
|
2010-09-04 03:21:26 +00:00
|
|
|
return mLayerManager;
|
2010-03-31 03:02:58 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::GetThebesSurface
|
|
|
|
*
|
|
|
|
* Get the Thebes surface associated with this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
gfxASurface *nsWindow::GetThebesSurface()
|
|
|
|
{
|
2010-02-26 06:36:07 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
|
|
|
if (mD2DWindowSurface) {
|
|
|
|
return mD2DWindowSurface;
|
|
|
|
}
|
|
|
|
#endif
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mPaintDC)
|
|
|
|
return (new gfxWindowsSurface(mPaintDC));
|
|
|
|
|
2010-02-26 06:36:07 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
|
|
|
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
|
|
|
gfxWindowsPlatform::RENDER_DIRECT2D) {
|
2010-06-09 15:50:03 +00:00
|
|
|
gfxASurface::gfxContentType content = gfxASurface::CONTENT_COLOR;
|
|
|
|
#if defined(MOZ_XUL)
|
|
|
|
if (mTransparencyMode != eTransparencyOpaque) {
|
|
|
|
content = gfxASurface::CONTENT_COLOR_ALPHA;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return (new gfxD2DSurface(mWnd, content));
|
2010-02-26 06:36:07 +00:00
|
|
|
} else {
|
|
|
|
#endif
|
2010-07-15 21:08:10 +00:00
|
|
|
PRUint32 flags = gfxWindowsSurface::FLAG_TAKE_DC;
|
|
|
|
if (mTransparencyMode != eTransparencyOpaque) {
|
|
|
|
flags |= gfxWindowsSurface::FLAG_IS_TRANSPARENT;
|
|
|
|
}
|
|
|
|
return (new gfxWindowsSurface(mWnd, flags));
|
2010-02-26 06:36:07 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
|
|
|
}
|
|
|
|
#endif
|
2008-04-30 04:12:15 +00:00
|
|
|
}
|
1999-04-23 14:30:51 +00:00
|
|
|
|
2009-07-15 09:54:30 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::OnDefaultButtonLoaded
|
|
|
|
*
|
|
|
|
* Called after the dialog is loaded and it has a default button.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::OnDefaultButtonLoaded(const nsIntRect &aButtonRect)
|
|
|
|
{
|
|
|
|
if (aButtonRect.IsEmpty())
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// Don't snap when we are not active.
|
|
|
|
HWND activeWnd = ::GetActiveWindow();
|
|
|
|
if (activeWnd != ::GetForegroundWindow() ||
|
2012-01-04 10:21:44 +00:00
|
|
|
WinUtils::GetTopLevelHWND(mWnd, true) !=
|
|
|
|
WinUtils::GetTopLevelHWND(activeWnd, true)) {
|
2009-07-15 09:54:30 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool isAlwaysSnapCursor =
|
|
|
|
Preferences::GetBool("ui.cursor_snapping.always_enabled", false);
|
2009-07-15 09:54:30 +00:00
|
|
|
|
|
|
|
if (!isAlwaysSnapCursor) {
|
|
|
|
BOOL snapDefaultButton;
|
|
|
|
if (!::SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0,
|
|
|
|
&snapDefaultButton, 0) || !snapDefaultButton)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntRect widgetRect;
|
|
|
|
nsresult rv = GetScreenBounds(widgetRect);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsIntRect buttonRect(aButtonRect + widgetRect.TopLeft());
|
|
|
|
|
|
|
|
nsIntPoint centerOfButton(buttonRect.x + buttonRect.width / 2,
|
|
|
|
buttonRect.y + buttonRect.height / 2);
|
|
|
|
// The center of the button can be outside of the widget.
|
|
|
|
// E.g., it could be hidden by scrolling.
|
|
|
|
if (!widgetRect.Contains(centerOfButton)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!::SetCursorPos(centerOfButton.x, centerOfButton.y)) {
|
|
|
|
NS_ERROR("SetCursorPos failed");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-24 10:58:04 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool aIsHorizontal,
|
2009-09-24 10:58:04 +00:00
|
|
|
PRInt32 &aOverriddenDelta)
|
|
|
|
{
|
|
|
|
// The default vertical and horizontal scrolling speed is 3, this is defined
|
|
|
|
// on the document of SystemParametersInfo in MSDN.
|
2010-08-20 18:19:38 +00:00
|
|
|
const PRUint32 kSystemDefaultScrollingSpeed = 3;
|
2009-09-24 10:58:04 +00:00
|
|
|
|
2011-06-25 14:06:02 +00:00
|
|
|
PRInt32 absOriginDelta = NS_ABS(aOriginalDelta);
|
2010-02-08 13:42:22 +00:00
|
|
|
|
2009-09-24 10:58:04 +00:00
|
|
|
// Compute the simple overridden speed.
|
2010-02-08 13:42:22 +00:00
|
|
|
PRInt32 absComputedOverriddenDelta;
|
2009-09-24 10:58:04 +00:00
|
|
|
nsresult rv =
|
2010-02-08 13:42:22 +00:00
|
|
|
nsBaseWidget::OverrideSystemMouseScrollSpeed(absOriginDelta, aIsHorizontal,
|
|
|
|
absComputedOverriddenDelta);
|
2009-09-24 10:58:04 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
aOverriddenDelta = aOriginalDelta;
|
|
|
|
|
2010-02-08 13:42:22 +00:00
|
|
|
if (absComputedOverriddenDelta == absOriginDelta) {
|
2009-09-24 10:58:04 +00:00
|
|
|
// We don't override now.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we should check whether the user customized the system settings
|
|
|
|
// or not. If the user did it, we should respect the will.
|
|
|
|
UINT systemSpeed;
|
|
|
|
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &systemSpeed, 0)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
// The default vertical scrolling speed is 3, this is defined on the document
|
|
|
|
// of SystemParametersInfo in MSDN.
|
|
|
|
if (systemSpeed != kSystemDefaultScrollingSpeed) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only Vista and later, Windows has the system setting of horizontal
|
|
|
|
// scrolling by the mouse wheel.
|
2012-01-04 10:21:44 +00:00
|
|
|
if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
|
2009-09-24 10:58:04 +00:00
|
|
|
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &systemSpeed, 0)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
// The default horizontal scrolling speed is 3, this is defined on the
|
|
|
|
// document of SystemParametersInfo in MSDN.
|
|
|
|
if (systemSpeed != kSystemDefaultScrollingSpeed) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Limit the overridden delta value from the system settings. The mouse
|
|
|
|
// driver might accelerate the scrolling speed already. If so, we shouldn't
|
|
|
|
// override the scrolling speed for preventing the unexpected high speed
|
|
|
|
// scrolling.
|
2010-02-08 13:42:22 +00:00
|
|
|
PRInt32 absDeltaLimit;
|
2009-09-24 10:58:04 +00:00
|
|
|
rv =
|
|
|
|
nsBaseWidget::OverrideSystemMouseScrollSpeed(kSystemDefaultScrollingSpeed,
|
2010-02-08 13:42:22 +00:00
|
|
|
aIsHorizontal, absDeltaLimit);
|
2009-09-24 10:58:04 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2010-02-08 13:42:22 +00:00
|
|
|
// If the given delta is larger than our computed limitation value, the delta
|
|
|
|
// was accelerated by the mouse driver. So, we should do nothing here.
|
|
|
|
if (absDeltaLimit <= absOriginDelta) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
absComputedOverriddenDelta =
|
2011-06-25 14:06:02 +00:00
|
|
|
NS_MIN(absComputedOverriddenDelta, absDeltaLimit);
|
2009-09-24 10:58:04 +00:00
|
|
|
|
2010-02-08 13:42:22 +00:00
|
|
|
aOverriddenDelta = (aOriginalDelta > 0) ? absComputedOverriddenDelta :
|
|
|
|
-absComputedOverriddenDelta;
|
2009-09-24 10:58:04 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Moz Events
|
|
|
|
**
|
|
|
|
** Moz GUI event management.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Mozilla event initialization
|
|
|
|
*
|
|
|
|
* Helpers for initializing moz events.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Event intialization
|
|
|
|
void nsWindow::InitEvent(nsGUIEvent& event, nsIntPoint* aPoint)
|
|
|
|
{
|
|
|
|
if (nsnull == aPoint) { // use the point from the event
|
|
|
|
// get the message position in client coordinates
|
|
|
|
if (mWnd != NULL) {
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
DWORD pos = ::GetMessagePos();
|
|
|
|
POINT cpos;
|
|
|
|
|
|
|
|
cpos.x = GET_X_LPARAM(pos);
|
|
|
|
cpos.y = GET_Y_LPARAM(pos);
|
2006-03-16 21:02:22 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
::ScreenToClient(mWnd, &cpos);
|
|
|
|
event.refPoint.x = cpos.x;
|
|
|
|
event.refPoint.y = cpos.y;
|
|
|
|
} else {
|
|
|
|
event.refPoint.x = 0;
|
|
|
|
event.refPoint.y = 0;
|
2004-04-18 11:03:51 +00:00
|
|
|
}
|
2001-10-22 22:43:52 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
else {
|
|
|
|
// use the point override if provided
|
|
|
|
event.refPoint.x = aPoint->x;
|
|
|
|
event.refPoint.y = aPoint->y;
|
|
|
|
}
|
2006-03-16 21:02:22 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
event.time = ::GetMessageTime();
|
|
|
|
mLastPoint = event.refPoint;
|
|
|
|
}
|
2006-03-16 21:02:22 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Moz event dispatch helpers
|
|
|
|
*
|
|
|
|
* Helpers for dispatching different types of moz events.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2008-05-05 23:01:07 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Main event dispatch. Invokes callback and ProcessEvent method on
|
|
|
|
// Event Listener object. Part of nsIWidget.
|
|
|
|
NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus)
|
2002-09-20 01:24:36 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef WIDGET_DEBUG_OUTPUT
|
|
|
|
debug_DumpEvent(stdout,
|
|
|
|
event->widget,
|
|
|
|
event,
|
|
|
|
nsCAutoString("something"),
|
|
|
|
(PRInt32) mWnd);
|
|
|
|
#endif // WIDGET_DEBUG_OUTPUT
|
2002-09-20 01:24:36 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
aStatus = nsEventStatus_eIgnore;
|
2002-09-20 01:24:36 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// skip processing of suppressed blur events
|
|
|
|
if (event->message == NS_DEACTIVATE && BlurEventsSuppressed())
|
|
|
|
return NS_OK;
|
2002-10-01 03:04:22 +00:00
|
|
|
|
2010-06-25 02:01:06 +00:00
|
|
|
// Top level windows can have a view attached which requires events be sent
|
|
|
|
// to the underlying base window and the view. Added when we combined the
|
|
|
|
// base chrome window with the main content child for nc client area (title
|
|
|
|
// bar) rendering.
|
|
|
|
if (mViewCallback) {
|
|
|
|
// A subset of events are sent to the base xul window first
|
|
|
|
switch(event->message) {
|
|
|
|
// send to the base window (view mgr ignores these for the view)
|
|
|
|
case NS_UISTATECHANGED:
|
|
|
|
case NS_DESTROY:
|
|
|
|
case NS_SETZLEVEL:
|
|
|
|
case NS_XUL_CLOSE:
|
|
|
|
case NS_MOVE:
|
|
|
|
(*mEventCallback)(event); // web shell / xul window
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// sent to the base window, then to the view
|
|
|
|
case NS_SIZE:
|
|
|
|
case NS_DEACTIVATE:
|
|
|
|
case NS_ACTIVATE:
|
|
|
|
case NS_SIZEMODE:
|
|
|
|
(*mEventCallback)(event); // web shell / xul window
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
// attached view events
|
|
|
|
aStatus = (*mViewCallback)(event);
|
|
|
|
}
|
|
|
|
else if (mEventCallback) {
|
2009-06-29 19:36:16 +00:00
|
|
|
aStatus = (*mEventCallback)(event);
|
2002-09-28 15:04:47 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// the window can be destroyed during processing of seemingly innocuous events like, say,
|
|
|
|
// mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
|
|
|
|
// which causes problems with the deleted window. therefore:
|
|
|
|
if (mOnDestroyCalled)
|
|
|
|
aStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
return NS_OK;
|
2006-02-23 17:02:45 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchStandardEvent(PRUint32 aMsg)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsGUIEvent event(true, aMsg, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
InitEvent(event);
|
1998-04-17 00:16:11 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool result = DispatchWindowEvent(&event);
|
2009-06-29 19:36:16 +00:00
|
|
|
return result;
|
|
|
|
}
|
2006-02-23 17:02:45 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(event, status);
|
|
|
|
return ConvertStatus(status);
|
|
|
|
}
|
1999-12-01 22:38:06 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchWindowEvent(nsGUIEvent* event, nsEventStatus &aStatus) {
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchEvent(event, aStatus);
|
|
|
|
return ConvertStatus(aStatus);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode,
|
2009-06-29 19:36:16 +00:00
|
|
|
const nsTArray<nsAlternativeCharCode>* aAlternativeCharCodes,
|
|
|
|
UINT aVirtualCharCode, const MSG *aMsg,
|
|
|
|
const nsModifierKeyState &aModKeyState,
|
|
|
|
PRUint32 aFlags)
|
|
|
|
{
|
2010-04-16 17:37:16 +00:00
|
|
|
UserActivity();
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsKeyEvent event(true, aEventType, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
nsIntPoint point(0, 0);
|
2003-04-14 22:56:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
InitEvent(event, &point); // this add ref's event.widget
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
event.flags |= aFlags;
|
|
|
|
event.charCode = aCharCode;
|
|
|
|
if (aAlternativeCharCodes)
|
|
|
|
event.alternativeCharCodes.AppendElements(*aAlternativeCharCodes);
|
|
|
|
event.keyCode = aVirtualCharCode;
|
|
|
|
|
|
|
|
#ifdef KE_DEBUG
|
|
|
|
static cnt=0;
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("%d DispatchKE Type: %s charCode %d keyCode %d ", cnt++,
|
|
|
|
NS_KEY_PRESS == aEventType ? "PRESS :
|
|
|
|
(aEventType == NS_KEY_UP ? "Up" : "Down"),
|
|
|
|
event.charCode, event.keyCode));
|
|
|
|
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("Shift: %s Control %s Alt: %s \n", (mIsShiftDown ? "D" : "U"),
|
|
|
|
(mIsControlDown ? "D" : "U"), (mIsAltDown ? "D" : "U")));
|
|
|
|
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("[%c][%c][%c] <== [%c][%c][%c][ space bar ][%c][%c][%c]\n",
|
|
|
|
IS_VK_DOWN(NS_VK_SHIFT) ? 'S' : ' ',
|
|
|
|
IS_VK_DOWN(NS_VK_CONTROL) ? 'C' : ' ',
|
|
|
|
IS_VK_DOWN(NS_VK_ALT) ? 'A' : ' ',
|
|
|
|
IS_VK_DOWN(VK_LSHIFT) ? 'S' : ' ',
|
|
|
|
IS_VK_DOWN(VK_LCONTROL) ? 'C' : ' ',
|
|
|
|
IS_VK_DOWN(VK_LMENU) ? 'A' : ' ',
|
|
|
|
IS_VK_DOWN(VK_RMENU) ? 'A' : ' ',
|
|
|
|
IS_VK_DOWN(VK_RCONTROL) ? 'C' : ' ',
|
|
|
|
IS_VK_DOWN(VK_RSHIFT) ? 'S' : ' '));
|
2005-02-23 07:07:51 +00:00
|
|
|
#endif
|
2005-08-22 15:17:53 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isShift = aModKeyState.mIsShiftDown;
|
|
|
|
event.isControl = aModKeyState.mIsControlDown;
|
2011-10-02 02:16:19 +00:00
|
|
|
event.isMeta = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isAlt = aModKeyState.mIsAltDown;
|
2005-10-13 15:07:56 +00:00
|
|
|
|
2009-09-17 01:30:26 +00:00
|
|
|
NPEvent pluginEvent;
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aMsg && PluginHasFocus()) {
|
|
|
|
pluginEvent.event = aMsg->message;
|
|
|
|
pluginEvent.wParam = aMsg->wParam;
|
|
|
|
pluginEvent.lParam = aMsg->lParam;
|
2009-11-10 21:55:38 +00:00
|
|
|
event.pluginEvent = (void *)&pluginEvent;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2005-07-24 19:36:18 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool result = DispatchWindowEvent(&event);
|
2005-07-24 19:36:18 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return result;
|
|
|
|
}
|
2005-07-24 19:36:18 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchCommandEvent(PRUint32 aEventCommand)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> command;
|
|
|
|
switch (aEventCommand) {
|
|
|
|
case APPCOMMAND_BROWSER_BACKWARD:
|
2011-10-14 18:11:22 +00:00
|
|
|
command = nsGkAtoms::Back;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_FORWARD:
|
2011-10-14 18:11:22 +00:00
|
|
|
command = nsGkAtoms::Forward;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_REFRESH:
|
2011-10-14 18:11:22 +00:00
|
|
|
command = nsGkAtoms::Reload;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_STOP:
|
2011-10-14 18:11:22 +00:00
|
|
|
command = nsGkAtoms::Stop;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_SEARCH:
|
2011-10-14 18:11:22 +00:00
|
|
|
command = nsGkAtoms::Search;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_FAVORITES:
|
2011-10-14 18:11:22 +00:00
|
|
|
command = nsGkAtoms::Bookmarks;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_HOME:
|
2011-10-14 18:11:22 +00:00
|
|
|
command = nsGkAtoms::Home;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
default:
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2011-10-14 18:11:22 +00:00
|
|
|
nsCommandEvent event(true, nsGkAtoms::onAppCommand, command, this);
|
2005-07-24 19:36:18 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
InitEvent(event);
|
|
|
|
DispatchWindowEvent(&event);
|
2005-07-24 19:36:18 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2005-07-24 19:36:18 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Recursively dispatch synchronous paints for nsIWidget
|
|
|
|
// descendants with invalidated rectangles.
|
|
|
|
BOOL CALLBACK nsWindow::DispatchStarvedPaints(HWND aWnd, LPARAM aMsg)
|
|
|
|
{
|
|
|
|
LONG_PTR proc = ::GetWindowLongPtrW(aWnd, GWLP_WNDPROC);
|
|
|
|
if (proc == (LONG_PTR)&nsWindow::WindowProc) {
|
|
|
|
// its one of our windows so check to see if it has a
|
|
|
|
// invalidated rect. If it does. Dispatch a synchronous
|
|
|
|
// paint.
|
2010-01-28 19:32:41 +00:00
|
|
|
if (GetUpdateRect(aWnd, NULL, FALSE))
|
|
|
|
VERIFY(::UpdateWindow(aWnd));
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
2001-05-01 13:29:14 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Check for pending paints and dispatch any pending paint
|
|
|
|
// messages for any nsIWidget which is a descendant of the
|
|
|
|
// top-level window that *this* window is embedded within.
|
|
|
|
//
|
|
|
|
// Note: We do not dispatch pending paint messages for non
|
|
|
|
// nsIWidget managed windows.
|
|
|
|
void nsWindow::DispatchPendingEvents()
|
|
|
|
{
|
2009-11-30 23:14:04 +00:00
|
|
|
if (mPainting) {
|
|
|
|
NS_WARNING("We were asked to dispatch pending events during painting, "
|
|
|
|
"denying since that's unsafe.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// We need to ensure that reflow events do not get starved.
|
|
|
|
// At the same time, we don't want to recurse through here
|
|
|
|
// as that would prevent us from dispatching starved paints.
|
|
|
|
static int recursionBlocker = 0;
|
|
|
|
if (recursionBlocker++ == 0) {
|
|
|
|
NS_ProcessPendingEvents(nsnull, PR_MillisecondsToInterval(100));
|
|
|
|
--recursionBlocker;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2012-01-14 01:29:22 +00:00
|
|
|
// Quickly check to see if there are any paint events pending,
|
|
|
|
// but only dispatch them if it has been long enough since the
|
|
|
|
// last paint completed.
|
|
|
|
if (::GetQueueStatus(QS_PAINT) &&
|
|
|
|
((TimeStamp::Now() - mLastPaintEndTime).ToMilliseconds() >= 50)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
// Find the top level window.
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND topWnd = WinUtils::GetTopLevelHWND(mWnd);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2010-10-08 18:58:45 +00:00
|
|
|
// Dispatch pending paints for topWnd and all its descendant windows.
|
2009-06-29 19:36:16 +00:00
|
|
|
// Note: EnumChildWindows enumerates all descendant windows not just
|
2010-10-08 18:58:45 +00:00
|
|
|
// the children (but not the window itself).
|
|
|
|
nsWindow::DispatchStarvedPaints(topWnd, 0);
|
2010-08-20 18:19:38 +00:00
|
|
|
::EnumChildWindows(topWnd, nsWindow::DispatchStarvedPaints, 0);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
2001-09-27 11:10:17 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Deal with plugin events
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchPluginEvent(const MSG &aMsg)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (!PluginHasFocus())
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2002-09-20 01:24:36 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsPluginEvent event(true, NS_PLUGIN_INPUT_EVENT, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
nsIntPoint point(0, 0);
|
|
|
|
InitEvent(event, &point);
|
2009-09-17 01:30:26 +00:00
|
|
|
NPEvent pluginEvent;
|
2009-06-29 19:36:16 +00:00
|
|
|
pluginEvent.event = aMsg.message;
|
|
|
|
pluginEvent.wParam = aMsg.wParam;
|
|
|
|
pluginEvent.lParam = aMsg.lParam;
|
2009-11-10 21:55:38 +00:00
|
|
|
event.pluginEvent = (void *)&pluginEvent;
|
2011-10-02 02:16:19 +00:00
|
|
|
event.retargetToFocusedDocument = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
return DispatchWindowEvent(&event);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchPluginEvent(UINT aMessage,
|
2010-08-08 09:23:25 +00:00
|
|
|
WPARAM aWParam,
|
|
|
|
LPARAM aLParam,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool aDispatchPendingEvents)
|
2010-08-08 09:23:25 +00:00
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
bool ret = DispatchPluginEvent(WinUtils::InitMSG(aMessage, aWParam, aLParam));
|
2010-08-08 09:23:25 +00:00
|
|
|
if (aDispatchPendingEvents) {
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg,
|
2011-04-20 23:54:43 +00:00
|
|
|
UINT aLastMsg, nsFakeCharMessage* aFakeCharMessage)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
MSG msg;
|
2011-04-20 23:54:43 +00:00
|
|
|
if (aFakeCharMessage) {
|
|
|
|
if (aFirstMsg > WM_CHAR || aLastMsg < WM_CHAR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
msg = aFakeCharMessage->GetCharMessage(mWnd);
|
|
|
|
} else {
|
|
|
|
::GetMessageW(&msg, mWnd, aFirstMsg, aLastMsg);
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchPluginEvent(msg);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Deal with all sort of mouse event
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam,
|
|
|
|
LPARAM lParam, bool aIsContextMenuKey,
|
2010-04-06 12:59:24 +00:00
|
|
|
PRInt16 aButton, PRUint16 aInputSource)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2011-09-29 06:19:26 +00:00
|
|
|
bool result = false;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2010-04-16 17:37:16 +00:00
|
|
|
UserActivity();
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!mEventCallback) {
|
|
|
|
return result;
|
|
|
|
}
|
2005-12-02 12:08:32 +00:00
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
switch (aEventType) {
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
2011-10-02 02:16:19 +00:00
|
|
|
CaptureMouse(true);
|
2010-06-25 02:01:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// NS_MOUSE_MOVE and NS_MOUSE_EXIT are here because we need to make sure capture flag
|
|
|
|
// isn't left on after a drag where we wouldn't see a button up message (see bug 324131).
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
case NS_MOUSE_EXIT:
|
2011-01-20 03:21:50 +00:00
|
|
|
if (!(wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) && sIsInMouseCapture)
|
2011-10-02 02:16:19 +00:00
|
|
|
CaptureMouse(false);
|
2010-06-25 02:01:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
} // switch
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsIntPoint eventPoint;
|
|
|
|
eventPoint.x = GET_X_LPARAM(lParam);
|
|
|
|
eventPoint.y = GET_Y_LPARAM(lParam);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsMouseEvent event(true, aEventType, this, nsMouseEvent::eReal,
|
2009-06-29 19:36:16 +00:00
|
|
|
aIsContextMenuKey
|
|
|
|
? nsMouseEvent::eContextMenuKey
|
|
|
|
: nsMouseEvent::eNormal);
|
|
|
|
if (aEventType == NS_CONTEXTMENU && aIsContextMenuKey) {
|
|
|
|
nsIntPoint zero(0, 0);
|
|
|
|
InitEvent(event, &zero);
|
|
|
|
} else {
|
|
|
|
InitEvent(event, &eventPoint);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
2011-10-02 02:16:19 +00:00
|
|
|
event.isMeta = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
event.button = aButton;
|
2010-04-06 12:59:24 +00:00
|
|
|
event.inputSource = aInputSource;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsIntPoint mpScreen = eventPoint + WidgetToScreenOffset();
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Suppress mouse moves caused by widget creation
|
|
|
|
if (aEventType == NS_MOUSE_MOVE)
|
|
|
|
{
|
|
|
|
if ((sLastMouseMovePoint.x == mpScreen.x) && (sLastMouseMovePoint.y == mpScreen.y))
|
|
|
|
return result;
|
|
|
|
sLastMouseMovePoint.x = mpScreen.x;
|
|
|
|
sLastMouseMovePoint.y = mpScreen.y;
|
|
|
|
}
|
2002-12-06 03:41:43 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool insideMovementThreshold = (abs(sLastMousePoint.x - eventPoint.x) < (short)::GetSystemMetrics(SM_CXDOUBLECLK)) &&
|
2009-06-29 19:36:16 +00:00
|
|
|
(abs(sLastMousePoint.y - eventPoint.y) < (short)::GetSystemMetrics(SM_CYDOUBLECLK));
|
2002-12-06 03:41:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
BYTE eventButton;
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
eventButton = VK_LBUTTON;
|
2004-09-03 08:44:23 +00:00
|
|
|
break;
|
2009-06-29 19:36:16 +00:00
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
eventButton = VK_MBUTTON;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
eventButton = VK_RBUTTON;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
eventButton = 0;
|
2004-09-03 08:44:23 +00:00
|
|
|
break;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Doubleclicks are used to set the click count, then changed to mousedowns
|
|
|
|
// We're going to time double-clicks from mouse *up* to next mouse *down*
|
|
|
|
LONG curMsgTime = ::GetMessageTime();
|
2000-04-01 22:16:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aEventType == NS_MOUSE_DOUBLECLICK) {
|
|
|
|
event.message = NS_MOUSE_BUTTON_DOWN;
|
|
|
|
event.button = aButton;
|
|
|
|
sLastClickCount = 2;
|
|
|
|
}
|
|
|
|
else if (aEventType == NS_MOUSE_BUTTON_UP) {
|
|
|
|
// remember when this happened for the next mouse down
|
|
|
|
sLastMousePoint.x = eventPoint.x;
|
|
|
|
sLastMousePoint.y = eventPoint.y;
|
|
|
|
sLastMouseButton = eventButton;
|
|
|
|
}
|
|
|
|
else if (aEventType == NS_MOUSE_BUTTON_DOWN) {
|
|
|
|
// now look to see if we want to convert this to a double- or triple-click
|
|
|
|
if (((curMsgTime - sLastMouseDownTime) < (LONG)::GetDoubleClickTime()) && insideMovementThreshold &&
|
|
|
|
eventButton == sLastMouseButton) {
|
|
|
|
sLastClickCount ++;
|
|
|
|
} else {
|
|
|
|
// reset the click count, to count *this* click
|
|
|
|
sLastClickCount = 1;
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
// Set last Click time on MouseDown only
|
|
|
|
sLastMouseDownTime = curMsgTime;
|
|
|
|
}
|
|
|
|
else if (aEventType == NS_MOUSE_MOVE && !insideMovementThreshold) {
|
|
|
|
sLastClickCount = 0;
|
|
|
|
}
|
|
|
|
else if (aEventType == NS_MOUSE_EXIT) {
|
|
|
|
event.exit = IsTopLevelMouseExit(mWnd) ? nsMouseEvent::eTopLevel : nsMouseEvent::eChild;
|
|
|
|
}
|
2010-06-28 06:04:05 +00:00
|
|
|
else if (aEventType == NS_MOUSE_MOZHITTEST)
|
|
|
|
{
|
|
|
|
event.flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH;
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
event.clickCount = sLastClickCount;
|
2000-04-01 22:16:43 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef NS_DEBUG_XX
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("Msg Time: %d Click Count: %d\n", curMsgTime, event.clickCount));
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif
|
2000-04-01 22:16:43 +00:00
|
|
|
|
2009-09-17 01:30:26 +00:00
|
|
|
NPEvent pluginEvent;
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
switch (aEventType)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
pluginEvent.event = WM_LBUTTONDOWN;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
pluginEvent.event = WM_MBUTTONDOWN;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
pluginEvent.event = WM_RBUTTONDOWN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
pluginEvent.event = WM_LBUTTONUP;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
pluginEvent.event = WM_MBUTTONUP;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
pluginEvent.event = WM_RBUTTONUP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_DOUBLECLICK:
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
pluginEvent.event = WM_LBUTTONDBLCLK;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
pluginEvent.event = WM_MBUTTONDBLCLK;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
pluginEvent.event = WM_RBUTTONDBLCLK;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-06-29 19:36:16 +00:00
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
pluginEvent.event = WM_MOUSEMOVE;
|
2004-09-03 08:44:23 +00:00
|
|
|
break;
|
2010-01-14 01:46:44 +00:00
|
|
|
case NS_MOUSE_EXIT:
|
|
|
|
pluginEvent.event = WM_MOUSELEAVE;
|
|
|
|
break;
|
2009-06-29 19:36:16 +00:00
|
|
|
default:
|
|
|
|
pluginEvent.event = WM_NULL;
|
|
|
|
break;
|
|
|
|
}
|
2000-08-24 04:53:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
pluginEvent.wParam = wParam; // plugins NEED raw OS event flags!
|
|
|
|
pluginEvent.lParam = lParam;
|
2009-03-24 01:10:36 +00:00
|
|
|
|
2009-11-10 21:55:38 +00:00
|
|
|
event.pluginEvent = (void *)&pluginEvent;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// call the event callback
|
|
|
|
if (nsnull != mEventCallback) {
|
|
|
|
if (nsToolkit::gMouseTrailer)
|
|
|
|
nsToolkit::gMouseTrailer->Disable();
|
|
|
|
if (aEventType == NS_MOUSE_MOVE) {
|
2011-01-20 03:21:50 +00:00
|
|
|
if (nsToolkit::gMouseTrailer && !sIsInMouseCapture) {
|
2009-06-29 19:36:16 +00:00
|
|
|
nsToolkit::gMouseTrailer->SetMouseTrailerWindow(mWnd);
|
|
|
|
}
|
|
|
|
nsIntRect rect;
|
|
|
|
GetBounds(rect);
|
|
|
|
rect.x = 0;
|
|
|
|
rect.y = 0;
|
2004-12-09 19:01:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (rect.Contains(event.refPoint)) {
|
|
|
|
if (sCurrentWindow == NULL || sCurrentWindow != this) {
|
2009-07-13 15:58:19 +00:00
|
|
|
if ((nsnull != sCurrentWindow) && (!sCurrentWindow->mInDtor)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
LPARAM pos = sCurrentWindow->lParamToClient(lParamToScreen(lParam));
|
2011-10-02 02:16:19 +00:00
|
|
|
sCurrentWindow->DispatchMouseEvent(NS_MOUSE_EXIT, wParam, pos, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eLeftButton, aInputSource);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
sCurrentWindow = this;
|
2009-07-13 15:58:19 +00:00
|
|
|
if (!mInDtor) {
|
2009-06-29 19:36:16 +00:00
|
|
|
LPARAM pos = sCurrentWindow->lParamToClient(lParamToScreen(lParam));
|
2011-10-02 02:16:19 +00:00
|
|
|
sCurrentWindow->DispatchMouseEvent(NS_MOUSE_ENTER, wParam, pos, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eLeftButton, aInputSource);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2000-04-01 22:16:43 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
} else if (aEventType == NS_MOUSE_EXIT) {
|
|
|
|
if (sCurrentWindow == this) {
|
|
|
|
sCurrentWindow = nsnull;
|
|
|
|
}
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
result = DispatchWindowEvent(&event);
|
2008-09-23 23:16:11 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (nsToolkit::gMouseTrailer)
|
|
|
|
nsToolkit::gMouseTrailer->Enable();
|
2008-04-09 01:51:00 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Release the widget with NS_IF_RELEASE() just in case
|
|
|
|
// the context menu key code in nsEventListenerManager::HandleEvent()
|
|
|
|
// released it already.
|
|
|
|
return result;
|
|
|
|
}
|
2005-02-23 07:07:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return result;
|
|
|
|
}
|
2007-02-20 19:45:17 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Deal with accessibile event
|
2008-02-06 20:34:35 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2010-05-12 06:47:35 +00:00
|
|
|
nsAccessible*
|
|
|
|
nsWindow::DispatchAccessibleEvent(PRUint32 aEventType)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (nsnull == mEventCallback) {
|
2010-05-12 06:47:35 +00:00
|
|
|
return nsnull;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsAccessibleEvent event(true, aEventType, this);
|
2010-05-12 06:47:35 +00:00
|
|
|
InitEvent(event, nsnull);
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
2011-10-02 02:16:19 +00:00
|
|
|
event.isMeta = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
2010-05-12 09:14:50 +00:00
|
|
|
|
2010-05-12 06:47:35 +00:00
|
|
|
DispatchWindowEvent(&event);
|
2009-06-29 19:36:16 +00:00
|
|
|
|
2010-05-12 06:47:35 +00:00
|
|
|
return event.mAccessible;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2005-12-19 03:00:41 +00:00
|
|
|
#endif
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (aEventType == NS_ACTIVATE)
|
2011-10-02 02:16:19 +00:00
|
|
|
sJustGotActivate = false;
|
|
|
|
sJustGotDeactivate = false;
|
2005-12-19 03:00:41 +00:00
|
|
|
|
2009-12-09 16:34:14 +00:00
|
|
|
// retrive the toplevel window or dialog
|
|
|
|
HWND curWnd = mWnd;
|
|
|
|
HWND toplevelWnd = NULL;
|
|
|
|
while (curWnd) {
|
|
|
|
toplevelWnd = curWnd;
|
|
|
|
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow *win = WinUtils::GetNSWindowPtr(curWnd);
|
2009-12-09 16:34:14 +00:00
|
|
|
if (win) {
|
|
|
|
nsWindowType wintype;
|
|
|
|
win->GetWindowType(wintype);
|
|
|
|
if (wintype == eWindowType_toplevel || wintype == eWindowType_dialog)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
curWnd = ::GetParent(curWnd); // Parent or owner (if has no parent)
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (toplevelWnd) {
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow *win = WinUtils::GetNSWindowPtr(toplevelWnd);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (win)
|
|
|
|
return win->DispatchFocus(aEventType);
|
|
|
|
}
|
2005-12-19 03:00:41 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1998-06-19 02:46:25 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Deal with focus messages
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::DispatchFocus(PRUint32 aEventType)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
// call the event callback
|
|
|
|
if (mEventCallback) {
|
2011-10-02 02:16:19 +00:00
|
|
|
nsGUIEvent event(true, aEventType, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
InitEvent(event);
|
1998-06-19 02:46:25 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
//focus and blur event should go to their base widget loc, not current mouse pos
|
|
|
|
event.refPoint.x = 0;
|
|
|
|
event.refPoint.y = 0;
|
2004-07-27 19:14:44 +00:00
|
|
|
|
2009-09-17 01:30:26 +00:00
|
|
|
NPEvent pluginEvent;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (aEventType)
|
|
|
|
{
|
|
|
|
case NS_ACTIVATE:
|
|
|
|
pluginEvent.event = WM_SETFOCUS;
|
|
|
|
break;
|
|
|
|
case NS_DEACTIVATE:
|
|
|
|
pluginEvent.event = WM_KILLFOCUS;
|
|
|
|
break;
|
|
|
|
case NS_PLUGIN_ACTIVATE:
|
|
|
|
pluginEvent.event = WM_KILLFOCUS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2000-12-19 03:01:31 +00:00
|
|
|
|
2009-11-10 21:55:38 +00:00
|
|
|
event.pluginEvent = (void *)&pluginEvent;
|
2002-06-20 04:55:13 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return DispatchWindowEvent(&event);
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::IsTopLevelMouseExit(HWND aWnd)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
DWORD pos = ::GetMessagePos();
|
|
|
|
POINT mp;
|
|
|
|
mp.x = GET_X_LPARAM(pos);
|
|
|
|
mp.y = GET_Y_LPARAM(pos);
|
|
|
|
HWND mouseWnd = ::WindowFromPoint(mp);
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2012-01-04 10:21:44 +00:00
|
|
|
// WinUtils::GetTopLevelHWND() will return a HWND for the window frame
|
|
|
|
// (which includes the non-client area). If the mouse has moved into
|
|
|
|
// the non-client area, we should treat it as a top-level exit.
|
|
|
|
HWND mouseTopLevel = WinUtils::GetTopLevelHWND(mouseWnd);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mouseWnd == mouseTopLevel)
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2012-01-04 10:21:44 +00:00
|
|
|
return WinUtils::GetTopLevelHWND(aWnd) != mouseTopLevel;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::BlurEventsSuppressed()
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
// are they suppressed in this window?
|
|
|
|
if (mBlurSuppressLevel > 0)
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// are they suppressed by any container widget?
|
|
|
|
HWND parentWnd = ::GetParent(mWnd);
|
|
|
|
if (parentWnd) {
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow *parent = WinUtils::GetNSWindowPtr(parentWnd);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (parent)
|
|
|
|
return parent->BlurEventsSuppressed();
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1998-08-19 00:57:02 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// In some circumstances (opening dependent windows) it makes more sense
|
|
|
|
// (and fixes a crash bug) to not blur the parent window. Called from
|
|
|
|
// nsFilePicker.
|
2011-09-29 06:19:26 +00:00
|
|
|
void nsWindow::SuppressBlurEvents(bool aSuppress)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (aSuppress)
|
|
|
|
++mBlurSuppressLevel; // for this widget
|
|
|
|
else {
|
|
|
|
NS_ASSERTION(mBlurSuppressLevel > 0, "unbalanced blur event suppression");
|
|
|
|
if (mBlurSuppressLevel > 0)
|
|
|
|
--mBlurSuppressLevel;
|
|
|
|
}
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::ConvertStatus(nsEventStatus aStatus)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
return aStatus == nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
2000-02-11 14:35:01 +00:00
|
|
|
|
2010-02-09 22:34:38 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: IPC
|
|
|
|
*
|
|
|
|
* IPC related helpers.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// static
|
|
|
|
bool
|
|
|
|
nsWindow::IsAsyncResponseEvent(UINT aMsg, LRESULT& aResult)
|
|
|
|
{
|
|
|
|
switch(aMsg) {
|
|
|
|
case WM_SETFOCUS:
|
|
|
|
case WM_KILLFOCUS:
|
|
|
|
case WM_ENABLE:
|
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
|
|
case WM_PARENTNOTIFY:
|
|
|
|
case WM_ACTIVATEAPP:
|
|
|
|
case WM_NCACTIVATE:
|
|
|
|
case WM_ACTIVATE:
|
|
|
|
case WM_CHILDACTIVATE:
|
|
|
|
case WM_IME_SETCONTEXT:
|
|
|
|
case WM_IME_NOTIFY:
|
|
|
|
case WM_SHOWWINDOW:
|
|
|
|
case WM_CANCELMODE:
|
|
|
|
case WM_MOUSEACTIVATE:
|
2010-03-23 03:06:35 +00:00
|
|
|
case WM_CONTEXTMENU:
|
2010-02-09 22:34:38 +00:00
|
|
|
aResult = 0;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case WM_SETTINGCHANGE:
|
|
|
|
case WM_SETCURSOR:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
char szBuf[200];
|
|
|
|
sprintf(szBuf,
|
|
|
|
"An unhandled ISMEX_SEND message was received during spin loop! (%X)", aMsg);
|
|
|
|
NS_WARNING(szBuf);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-02-23 01:09:27 +00:00
|
|
|
nsWindow::IPCWindowProcHandler(UINT& msg, WPARAM& wParam, LPARAM& lParam)
|
2010-02-09 22:34:38 +00:00
|
|
|
{
|
|
|
|
NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
|
|
|
|
"Failed to prevent a nonqueued message from running!");
|
2010-02-23 01:09:27 +00:00
|
|
|
|
|
|
|
// Modal UI being displayed in windowless plugins.
|
2010-02-09 22:34:38 +00:00
|
|
|
if (mozilla::ipc::RPCChannel::IsSpinLoopActive() &&
|
2010-03-11 01:16:44 +00:00
|
|
|
(InSendMessageEx(NULL)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
|
2010-02-09 22:34:38 +00:00
|
|
|
LRESULT res;
|
|
|
|
if (IsAsyncResponseEvent(msg, res)) {
|
2010-03-11 01:16:44 +00:00
|
|
|
ReplyMessage(res);
|
2010-02-09 22:34:38 +00:00
|
|
|
}
|
2010-03-11 01:16:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle certain sync plugin events sent to the parent which
|
|
|
|
// trigger ipc calls that result in deadlocks.
|
|
|
|
|
2010-04-17 21:11:47 +00:00
|
|
|
DWORD dwResult = 0;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool handled = false;
|
2010-03-06 18:33:40 +00:00
|
|
|
|
2010-04-17 21:11:47 +00:00
|
|
|
switch(msg) {
|
|
|
|
// Windowless flash sending WM_ACTIVATE events to the main window
|
|
|
|
// via calls to ShowWindow.
|
|
|
|
case WM_ACTIVATE:
|
|
|
|
if (lParam != 0 && LOWORD(wParam) == WA_ACTIVE &&
|
2011-03-25 23:17:35 +00:00
|
|
|
IsWindow((HWND)lParam)) {
|
|
|
|
// Check for Adobe Reader X sync activate message from their
|
|
|
|
// helper window and ignore. Fixes an annoying focus problem.
|
|
|
|
if ((InSendMessageEx(NULL)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
|
|
|
|
PRUnichar szClass[10];
|
|
|
|
HWND focusWnd = (HWND)lParam;
|
|
|
|
if (IsWindowVisible(focusWnd) &&
|
|
|
|
GetClassNameW(focusWnd, szClass,
|
|
|
|
sizeof(szClass)/sizeof(PRUnichar)) &&
|
|
|
|
!wcscmp(szClass, L"Edit") &&
|
2012-01-04 10:21:44 +00:00
|
|
|
!WinUtils::IsOurProcessWindow(focusWnd)) {
|
2011-03-25 23:17:35 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
handled = true;
|
2011-03-25 23:17:35 +00:00
|
|
|
}
|
2010-04-17 21:11:47 +00:00
|
|
|
break;
|
|
|
|
// Plugins taking or losing focus triggering focus app messages.
|
|
|
|
case WM_SETFOCUS:
|
|
|
|
case WM_KILLFOCUS:
|
|
|
|
// Windowed plugins that pass sys key events to defwndproc generate
|
|
|
|
// WM_SYSCOMMAND events to the main window.
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
// Windowed plugins that fire context menu selection events to parent
|
|
|
|
// windows.
|
|
|
|
case WM_CONTEXTMENU:
|
2010-05-17 16:33:34 +00:00
|
|
|
// IME events fired as a result of synchronous focus changes
|
|
|
|
case WM_IME_SETCONTEXT:
|
2011-10-02 02:16:19 +00:00
|
|
|
handled = true;
|
2010-04-17 21:11:47 +00:00
|
|
|
break;
|
2010-03-11 01:16:44 +00:00
|
|
|
}
|
|
|
|
|
2010-04-17 21:11:47 +00:00
|
|
|
if (handled &&
|
2010-03-11 01:16:44 +00:00
|
|
|
(InSendMessageEx(NULL)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
|
2010-04-17 21:11:47 +00:00
|
|
|
ReplyMessage(dwResult);
|
2010-03-06 18:33:40 +00:00
|
|
|
}
|
2010-02-09 22:34:38 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Native events
|
|
|
|
**
|
|
|
|
** Main Windows message handlers and OnXXX handlers for
|
|
|
|
** Windows event handling.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Wind proc.
|
|
|
|
*
|
|
|
|
* The main Windows event procedures and associated
|
|
|
|
* message processing methods.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool
|
|
|
|
DisplaySystemMenu(HWND hWnd, nsSizeMode sizeMode, bool isRtl, PRInt32 x, PRInt32 y)
|
2010-10-22 22:38:18 +00:00
|
|
|
{
|
|
|
|
HMENU hMenu = GetSystemMenu(hWnd, FALSE);
|
|
|
|
if (hMenu) {
|
2011-05-11 07:16:10 +00:00
|
|
|
MENUITEMINFO mii;
|
|
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
|
|
mii.fMask = MIIM_STATE;
|
|
|
|
mii.fType = 0;
|
|
|
|
|
2010-10-22 22:38:18 +00:00
|
|
|
// update the options
|
2011-05-11 07:16:10 +00:00
|
|
|
mii.fState = MF_ENABLED;
|
|
|
|
SetMenuItemInfo(hMenu, SC_RESTORE, FALSE, &mii);
|
|
|
|
SetMenuItemInfo(hMenu, SC_SIZE, FALSE, &mii);
|
|
|
|
SetMenuItemInfo(hMenu, SC_MOVE, FALSE, &mii);
|
|
|
|
SetMenuItemInfo(hMenu, SC_MAXIMIZE, FALSE, &mii);
|
|
|
|
SetMenuItemInfo(hMenu, SC_MINIMIZE, FALSE, &mii);
|
|
|
|
|
|
|
|
mii.fState = MF_GRAYED;
|
2010-10-22 22:38:18 +00:00
|
|
|
switch(sizeMode) {
|
|
|
|
case nsSizeMode_Fullscreen:
|
2011-06-21 15:33:03 +00:00
|
|
|
SetMenuItemInfo(hMenu, SC_RESTORE, FALSE, &mii);
|
2010-10-22 22:38:18 +00:00
|
|
|
// intentional fall through
|
|
|
|
case nsSizeMode_Maximized:
|
2011-05-11 07:16:10 +00:00
|
|
|
SetMenuItemInfo(hMenu, SC_SIZE, FALSE, &mii);
|
|
|
|
SetMenuItemInfo(hMenu, SC_MOVE, FALSE, &mii);
|
|
|
|
SetMenuItemInfo(hMenu, SC_MAXIMIZE, FALSE, &mii);
|
2010-10-22 22:38:18 +00:00
|
|
|
break;
|
|
|
|
case nsSizeMode_Minimized:
|
2011-05-11 07:16:10 +00:00
|
|
|
SetMenuItemInfo(hMenu, SC_MINIMIZE, FALSE, &mii);
|
2010-10-22 22:38:18 +00:00
|
|
|
break;
|
|
|
|
case nsSizeMode_Normal:
|
2011-05-11 07:16:10 +00:00
|
|
|
SetMenuItemInfo(hMenu, SC_RESTORE, FALSE, &mii);
|
2010-10-22 22:38:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
LPARAM cmd =
|
|
|
|
TrackPopupMenu(hMenu,
|
|
|
|
(TPM_LEFTBUTTON|TPM_RIGHTBUTTON|
|
|
|
|
TPM_RETURNCMD|TPM_TOPALIGN|
|
|
|
|
(isRtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN)),
|
|
|
|
x, y, 0, hWnd, NULL);
|
|
|
|
if (cmd) {
|
|
|
|
PostMessage(hWnd, WM_SYSCOMMAND, cmd, 0);
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-10-22 22:38:18 +00:00
|
|
|
}
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2010-10-22 22:38:18 +00:00
|
|
|
}
|
|
|
|
|
2010-08-16 19:25:13 +00:00
|
|
|
// The WndProc procedure for all nsWindows in this toolkit. This merely catches
|
2010-08-16 19:28:18 +00:00
|
|
|
// exceptions and passes the real work to WindowProcInternal. See bug 587406
|
|
|
|
// and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx
|
2009-06-29 19:36:16 +00:00
|
|
|
LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
2010-08-16 19:25:13 +00:00
|
|
|
{
|
2011-02-12 01:56:11 +00:00
|
|
|
return mozilla::CallWindowProcCrashProtected(WindowProcInternal, hWnd, msg, wParam, lParam);
|
2010-08-16 19:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LRESULT CALLBACK nsWindow::WindowProcInternal(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2010-05-19 23:22:19 +00:00
|
|
|
NS_TIME_FUNCTION_MIN_FMT(5.0, "%s (line %d) (hWnd: %p, msg: %p, wParam: %p, lParam: %p",
|
|
|
|
MOZ_FUNCTION_NAME, __LINE__, hWnd, msg,
|
|
|
|
wParam, lParam);
|
|
|
|
|
2010-12-28 10:16:43 +00:00
|
|
|
if (::GetWindowLongPtrW(hWnd, GWLP_ID) == eFakeTrackPointScrollableID) {
|
|
|
|
// This message was sent to the FAKETRACKPOINTSCROLLABLE.
|
|
|
|
if (msg == WM_HSCROLL) {
|
|
|
|
// Route WM_HSCROLL messages to the main window.
|
|
|
|
hWnd = ::GetParent(::GetParent(hWnd));
|
|
|
|
} else {
|
|
|
|
// Handle all other messages with its original window procedure.
|
|
|
|
WNDPROC prevWindowProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
|
|
|
return ::CallWindowProcW(prevWindowProc, hWnd, msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-03 16:20:02 +00:00
|
|
|
if (msg == MOZ_WM_TRACE) {
|
|
|
|
// This is a tracer event for measuring event loop latency.
|
|
|
|
// See WidgetTraceEvent.cpp for more details.
|
|
|
|
mozilla::SignalTracerThread();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-23 01:09:27 +00:00
|
|
|
// Get the window which caused the event and ask it to process the message
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow *someWindow = WinUtils::GetNSWindowPtr(hWnd);
|
2010-02-23 01:09:27 +00:00
|
|
|
|
|
|
|
if (someWindow)
|
|
|
|
someWindow->IPCWindowProcHandler(msg, wParam, lParam);
|
2009-11-06 22:33:12 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// create this here so that we store the last rolled up popup until after
|
|
|
|
// the event has been processed.
|
|
|
|
nsAutoRollup autoRollup;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
LRESULT popupHandlingResult;
|
2010-02-23 01:10:08 +00:00
|
|
|
if (DealWithPopups(hWnd, msg, wParam, lParam, &popupHandlingResult))
|
2009-06-29 19:36:16 +00:00
|
|
|
return popupHandlingResult;
|
1999-03-09 23:48:58 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// XXX This fixes 50208 and we are leaving 51174 open to further investigate
|
|
|
|
// why we are hitting this assert
|
|
|
|
if (nsnull == someWindow) {
|
|
|
|
NS_ASSERTION(someWindow, "someWindow is null, cannot call any CallWindowProc");
|
|
|
|
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
|
|
|
|
}
|
1999-03-23 21:26:20 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// hold on to the window for the life of this method, in case it gets
|
|
|
|
// deleted during processing. yes, it's a double hack, since someWindow
|
|
|
|
// is not really an interface.
|
|
|
|
nsCOMPtr<nsISupports> kungFuDeathGrip;
|
2009-07-13 15:58:19 +00:00
|
|
|
if (!someWindow->mInDtor) // not if we're in the destructor!
|
2009-06-29 19:36:16 +00:00
|
|
|
kungFuDeathGrip = do_QueryInterface((nsBaseWidget*)someWindow);
|
2004-04-01 22:51:46 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Call ProcessMessage
|
2010-02-23 01:10:08 +00:00
|
|
|
LRESULT retValue;
|
2011-10-02 02:16:19 +00:00
|
|
|
if (true == someWindow->ProcessMessage(msg, wParam, lParam, &retValue)) {
|
2010-02-23 01:10:08 +00:00
|
|
|
return retValue;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2006-04-17 17:42:20 +00:00
|
|
|
|
2010-02-23 01:10:08 +00:00
|
|
|
LRESULT res = ::CallWindowProcW(someWindow->GetPrevWindowProc(),
|
|
|
|
hWnd, msg, wParam, lParam);
|
|
|
|
|
|
|
|
return res;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2006-09-08 06:04:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// The main windows message processing method for plugins.
|
|
|
|
// The result means whether this method processed the native
|
|
|
|
// event for plugin. If false, the native event should be
|
|
|
|
// processed by the caller self.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2009-06-29 19:36:16 +00:00
|
|
|
nsWindow::ProcessMessageForPlugin(const MSG &aMsg,
|
|
|
|
LRESULT *aResult,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool &aCallDefWndProc)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aResult, "aResult must be non-null.");
|
|
|
|
*aResult = 0;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
aCallDefWndProc = false;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool eventDispatched = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (aMsg.message) {
|
|
|
|
case WM_CHAR:
|
|
|
|
case WM_SYSCHAR:
|
|
|
|
*aResult = ProcessCharMessage(aMsg, &eventDispatched);
|
|
|
|
break;
|
2002-04-29 14:50:58 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_KEYUP:
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
*aResult = ProcessKeyUpMessage(aMsg, &eventDispatched);
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_KEYDOWN:
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
*aResult = ProcessKeyDownMessage(aMsg, &eventDispatched);
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_DEADCHAR:
|
|
|
|
case WM_SYSDEADCHAR:
|
2006-09-08 06:04:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_CUT:
|
|
|
|
case WM_COPY:
|
|
|
|
case WM_PASTE:
|
|
|
|
case WM_CLEAR:
|
|
|
|
case WM_UNDO:
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
default:
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!eventDispatched)
|
|
|
|
aCallDefWndProc = !DispatchPluginEvent(aMsg);
|
2010-08-08 09:23:25 +00:00
|
|
|
DispatchPendingEvents();
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-06-09 07:13:05 +00:00
|
|
|
static void ForceFontUpdate()
|
|
|
|
{
|
|
|
|
// update device context font cache
|
|
|
|
// Dirty but easiest way:
|
|
|
|
// Changing nsIPrefBranch entry which triggers callbacks
|
|
|
|
// and flows into calling mDeviceContext->FlushFontCache()
|
|
|
|
// to update the font cache in all the instance of Browsers
|
|
|
|
static const char kPrefName[] = "font.internaluseonly.changed";
|
2011-09-29 06:19:26 +00:00
|
|
|
bool fontInternalChange =
|
|
|
|
Preferences::GetBool(kPrefName, false);
|
2011-06-09 07:13:05 +00:00
|
|
|
Preferences::SetBool(kPrefName, !fontInternalChange);
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool CleartypeSettingChanged()
|
2011-06-09 07:13:05 +00:00
|
|
|
{
|
|
|
|
static int currentQuality = -1;
|
|
|
|
BYTE quality = cairo_win32_get_system_text_quality();
|
|
|
|
|
|
|
|
if (currentQuality == quality)
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2011-06-09 07:13:05 +00:00
|
|
|
|
|
|
|
if (currentQuality < 0) {
|
|
|
|
currentQuality = quality;
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2011-06-09 07:13:05 +00:00
|
|
|
}
|
|
|
|
currentQuality = quality;
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2011-06-09 07:13:05 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// The main windows message processing method.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
2009-06-29 19:36:16 +00:00
|
|
|
LRESULT *aRetValue)
|
|
|
|
{
|
2011-02-12 01:56:13 +00:00
|
|
|
// For the Elantech Touchpad Zoom Gesture Hack, we should check that the
|
|
|
|
// system time (32-bit milliseconds) hasn't wrapped around. Otherwise we
|
|
|
|
// might get into the situation where wheel events for the next 50 days of
|
|
|
|
// system uptime are assumed to be Ctrl+Wheel events. (It is unlikely that
|
|
|
|
// we would get into that state, because the system would already need to be
|
|
|
|
// up for 50 days and the Control key message would need to be processed just
|
|
|
|
// before the system time overflow and the wheel message just after.)
|
|
|
|
//
|
|
|
|
// We also take the chance to reset mAssumeWheelIsZoomUntil if we simply have
|
|
|
|
// passed that time.
|
|
|
|
if (mAssumeWheelIsZoomUntil) {
|
|
|
|
LONG msgTime = ::GetMessageTime();
|
|
|
|
if ((mAssumeWheelIsZoomUntil >= 0x3fffffffu && DWORD(msgTime) < 0x40000000u) ||
|
|
|
|
(mAssumeWheelIsZoomUntil < DWORD(msgTime))) {
|
|
|
|
mAssumeWheelIsZoomUntil = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// (Large blocks of code should be broken out into OnEvent handlers.)
|
2009-08-13 23:04:39 +00:00
|
|
|
if (mWindowHook.Notify(mWnd, msg, wParam, lParam, aRetValue))
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-03-24 21:49:05 +00:00
|
|
|
|
2010-02-09 22:34:38 +00:00
|
|
|
#if defined(EVENT_DEBUG_OUTPUT)
|
|
|
|
// First param shows all events, second param indicates whether
|
|
|
|
// to show mouse move events. See nsWindowDbg for details.
|
|
|
|
PrintEvent(msg, SHOW_REPEAT_EVENTS, SHOW_MOUSEMOVE_EVENTS);
|
|
|
|
#endif
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool eatMessage;
|
2009-06-29 19:36:16 +00:00
|
|
|
if (nsIMM32Handler::ProcessMessage(this, msg, wParam, lParam, aRetValue,
|
|
|
|
eatMessage)) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return mWnd ? eatMessage : true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (PluginHasFocus()) {
|
2011-09-29 06:19:26 +00:00
|
|
|
bool callDefaultWndProc;
|
2012-01-04 10:21:44 +00:00
|
|
|
MSG nativeMsg = WinUtils::InitMSG(msg, wParam, lParam);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (ProcessMessageForPlugin(nativeMsg, aRetValue, callDefaultWndProc)) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return mWnd ? !callDefaultWndProc : true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool result = false; // call the default nsWindow proc
|
2009-06-29 19:36:16 +00:00
|
|
|
*aRetValue = 0;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2010-06-28 09:41:01 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2010-06-25 02:01:07 +00:00
|
|
|
// Glass hit testing w/custom transparent margins
|
|
|
|
LRESULT dwmHitResult;
|
|
|
|
if (mCustomNonClient &&
|
|
|
|
nsUXThemeData::CheckForCompositor() &&
|
|
|
|
nsUXThemeData::dwmDwmDefWindowProcPtr(mWnd, msg, wParam, lParam, &dwmHitResult)) {
|
|
|
|
*aRetValue = dwmHitResult;
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-06-25 02:01:07 +00:00
|
|
|
}
|
2010-06-28 09:41:01 +00:00
|
|
|
#endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (msg) {
|
|
|
|
// WM_QUERYENDSESSION must be handled by all windows.
|
|
|
|
// Otherwise Windows thinks the window can just be killed at will.
|
|
|
|
case WM_QUERYENDSESSION:
|
|
|
|
if (sCanQuit == TRI_UNKNOWN)
|
|
|
|
{
|
|
|
|
// Ask if it's ok to quit, and store the answer until we
|
|
|
|
// get WM_ENDSESSION signaling the round is complete.
|
|
|
|
nsCOMPtr<nsIObserverService> obsServ =
|
Bug 560095 - Use mozilla::services::GetObserverService(). r=biesi,dveditz,gavin,josh,jst,mrbkap,roc,sdwilsh,shaver,sicking,smontagu,surkov
2010-04-29 16:59:13 +00:00
|
|
|
mozilla::services::GetObserverService();
|
2009-06-29 19:36:16 +00:00
|
|
|
nsCOMPtr<nsISupportsPRBool> cancelQuit =
|
|
|
|
do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID);
|
2011-10-02 02:16:19 +00:00
|
|
|
cancelQuit->SetData(false);
|
2009-06-29 19:36:16 +00:00
|
|
|
obsServ->NotifyObservers(cancelQuit, "quit-application-requested", nsnull);
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool abortQuit;
|
2009-06-29 19:36:16 +00:00
|
|
|
cancelQuit->GetData(&abortQuit);
|
|
|
|
sCanQuit = abortQuit ? TRI_FALSE : TRI_TRUE;
|
|
|
|
}
|
|
|
|
*aRetValue = sCanQuit ? TRUE : FALSE;
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-04-02 19:34:31 +00:00
|
|
|
break;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_ENDSESSION:
|
2009-11-05 19:58:21 +00:00
|
|
|
case MOZ_WM_APP_QUIT:
|
|
|
|
if (msg == MOZ_WM_APP_QUIT || (wParam == TRUE && sCanQuit == TRI_TRUE))
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
// Let's fake a shutdown sequence without actually closing windows etc.
|
|
|
|
// to avoid Windows killing us in the middle. A proper shutdown would
|
|
|
|
// require having a chance to pump some messages. Unfortunately
|
|
|
|
// Windows won't let us do that. Bug 212316.
|
|
|
|
nsCOMPtr<nsIObserverService> obsServ =
|
Bug 560095 - Use mozilla::services::GetObserverService(). r=biesi,dveditz,gavin,josh,jst,mrbkap,roc,sdwilsh,shaver,sicking,smontagu,surkov
2010-04-29 16:59:13 +00:00
|
|
|
mozilla::services::GetObserverService();
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
|
|
|
|
obsServ->NotifyObservers(nsnull, "quit-application-granted", nsnull);
|
|
|
|
obsServ->NotifyObservers(nsnull, "quit-application-forced", nsnull);
|
|
|
|
obsServ->NotifyObservers(nsnull, "quit-application", nsnull);
|
|
|
|
obsServ->NotifyObservers(nsnull, "profile-change-net-teardown", context.get());
|
|
|
|
obsServ->NotifyObservers(nsnull, "profile-change-teardown", context.get());
|
|
|
|
obsServ->NotifyObservers(nsnull, "profile-before-change", context.get());
|
|
|
|
// Then a controlled but very quick exit.
|
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
sCanQuit = TRI_UNKNOWN;
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_DISPLAYCHANGE:
|
|
|
|
DispatchStandardEvent(NS_DISPLAYCHANGED);
|
|
|
|
break;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_SYSCOLORCHANGE:
|
2011-11-21 17:53:20 +00:00
|
|
|
OnSysColorChanged();
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_NOTIFY:
|
|
|
|
// TAB change
|
|
|
|
{
|
|
|
|
LPNMHDR pnmh = (LPNMHDR) lParam;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (pnmh->code) {
|
|
|
|
case TCN_SELCHANGE:
|
|
|
|
{
|
|
|
|
DispatchStandardEvent(NS_TABCHANGE);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-04-02 19:34:31 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2010-11-29 16:19:17 +00:00
|
|
|
case WM_THEMECHANGED:
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2010-06-25 02:01:07 +00:00
|
|
|
// Update non-client margin offsets
|
|
|
|
UpdateNonClientMargins();
|
2010-11-29 16:19:17 +00:00
|
|
|
nsUXThemeData::InitTitlebarInfo();
|
2010-10-09 20:53:44 +00:00
|
|
|
nsUXThemeData::UpdateNativeThemeInfo();
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchStandardEvent(NS_THEMECHANGED);
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Invalidate the window so that the repaint will
|
|
|
|
// pick up the new theme.
|
2011-12-24 03:52:21 +00:00
|
|
|
Invalidate(true, true, true);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_FONTCHANGE:
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool didChange = false;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// update the global font list
|
|
|
|
nsCOMPtr<nsIFontEnumerator> fontEnum = do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
fontEnum->UpdateFontList(&didChange);
|
|
|
|
//didChange is TRUE only if new font langGroup is added to the list.
|
|
|
|
if (didChange) {
|
2011-06-09 07:13:05 +00:00
|
|
|
ForceFontUpdate();
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
} //if (NS_SUCCEEDED(rv))
|
|
|
|
}
|
|
|
|
break;
|
2009-04-02 19:34:31 +00:00
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
case WM_NCCALCSIZE:
|
|
|
|
{
|
|
|
|
// If wParam is TRUE, it specifies that the application should indicate
|
|
|
|
// which part of the client area contains valid information. The system
|
|
|
|
// copies the valid information to the specified area within the new
|
|
|
|
// client area. If the wParam parameter is FALSE, the application should
|
|
|
|
// return zero.
|
2010-08-25 03:03:37 +00:00
|
|
|
if (mCustomNonClient) {
|
2010-06-25 02:01:07 +00:00
|
|
|
if (!wParam) {
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2010-06-25 02:01:07 +00:00
|
|
|
*aRetValue = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// before:
|
|
|
|
// rgrc[0]: the proposed window
|
|
|
|
// rgrc[1]: the current window
|
|
|
|
// rgrc[2]: the source client area
|
|
|
|
// pncsp->lppos: move/size data
|
|
|
|
// after:
|
|
|
|
// rgrc[0]: the new client area
|
|
|
|
// rgrc[1]: the destination window
|
|
|
|
// rgrc[2]: the source client area
|
|
|
|
// (all values in screen coordiantes)
|
|
|
|
NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
|
|
|
|
LRESULT res = CallWindowProcW(GetPrevWindowProc(), mWnd, msg, wParam, lParam);
|
|
|
|
pncsp->rgrc[0].top -= mNonClientOffset.top;
|
|
|
|
pncsp->rgrc[0].left -= mNonClientOffset.left;
|
|
|
|
pncsp->rgrc[0].right += mNonClientOffset.right;
|
|
|
|
pncsp->rgrc[0].bottom += mNonClientOffset.bottom;
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2010-06-25 02:01:07 +00:00
|
|
|
*aRetValue = res;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_NCHITTEST:
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If an nc client area margin has been moved, we are responsible
|
|
|
|
* for calculating where the resize margins are and returning the
|
|
|
|
* appropriate set of hit test constants. DwmDefWindowProc (above)
|
|
|
|
* will handle hit testing on it's command buttons if we are on a
|
|
|
|
* composited desktop.
|
|
|
|
*/
|
|
|
|
|
2010-08-25 03:03:37 +00:00
|
|
|
if (!mCustomNonClient)
|
2010-06-25 02:01:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
*aRetValue =
|
|
|
|
ClientMarginHitTestPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2010-06-25 02:01:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-08-10 01:49:35 +00:00
|
|
|
case WM_SETTEXT:
|
|
|
|
/*
|
|
|
|
* WM_SETTEXT paints the titlebar area. Avoid this if we have a
|
|
|
|
* custom titlebar we paint ourselves.
|
|
|
|
*/
|
|
|
|
|
2010-08-12 21:54:48 +00:00
|
|
|
if (!mCustomNonClient || mNonClientMargins.top == -1)
|
2010-08-10 01:49:35 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
{
|
|
|
|
// From msdn, the way around this is to disable the visible state
|
|
|
|
// temporarily. We need the text to be set but we don't want the
|
|
|
|
// redraw to occur.
|
|
|
|
DWORD style = GetWindowLong(mWnd, GWL_STYLE);
|
|
|
|
SetWindowLong(mWnd, GWL_STYLE, style & ~WS_VISIBLE);
|
|
|
|
*aRetValue = CallWindowProcW(GetPrevWindowProc(), mWnd,
|
|
|
|
msg, wParam, lParam);
|
|
|
|
SetWindowLong(mWnd, GWL_STYLE, style);
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-08-10 01:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case WM_NCACTIVATE:
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* WM_NCACTIVATE paints nc areas. Avoid this and re-route painting
|
|
|
|
* through WM_NCPAINT via InvalidateNonClientRegion.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!mCustomNonClient)
|
|
|
|
break;
|
|
|
|
|
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
|
|
|
// let the dwm handle nc painting on glass
|
|
|
|
if(nsUXThemeData::CheckForCompositor())
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (wParam == TRUE) {
|
|
|
|
// going active
|
|
|
|
*aRetValue = FALSE; // ignored
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
|
|
|
UpdateGetWindowInfoCaptionStatus(true);
|
2010-08-10 01:49:35 +00:00
|
|
|
// invalidate to trigger a paint
|
|
|
|
InvalidateNonClientRegion();
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
// going inactive
|
|
|
|
*aRetValue = TRUE; // go ahead and deactive
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
|
|
|
UpdateGetWindowInfoCaptionStatus(false);
|
2010-08-10 01:49:35 +00:00
|
|
|
// invalidate to trigger a paint
|
|
|
|
InvalidateNonClientRegion();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_NCPAINT:
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Reset the non-client paint region so that it excludes the
|
|
|
|
* non-client areas we paint manually. Then call defwndproc
|
|
|
|
* to do the actual painting.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!mCustomNonClient)
|
|
|
|
break;
|
|
|
|
|
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
|
|
|
// let the dwm handle nc painting on glass
|
|
|
|
if(nsUXThemeData::CheckForCompositor())
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
HRGN paintRgn = ExcludeNonClientFromPaintRegion((HRGN)wParam);
|
|
|
|
LRESULT res = CallWindowProcW(GetPrevWindowProc(), mWnd,
|
|
|
|
msg, (WPARAM)paintRgn, lParam);
|
|
|
|
if (paintRgn != (HRGN)wParam)
|
|
|
|
DeleteObject(paintRgn);
|
|
|
|
*aRetValue = res;
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2010-08-10 01:49:35 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_POWERBROADCAST:
|
2011-11-08 19:59:09 +00:00
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case PBT_APMSUSPEND:
|
|
|
|
PostSleepWakeNotification(true);
|
|
|
|
break;
|
|
|
|
case PBT_APMRESUMEAUTOMATIC:
|
|
|
|
case PBT_APMRESUMECRITICAL:
|
|
|
|
case PBT_APMRESUMESUSPEND:
|
|
|
|
PostSleepWakeNotification(false);
|
|
|
|
break;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MOVE: // Window moved
|
|
|
|
{
|
2010-07-27 13:38:03 +00:00
|
|
|
RECT rect;
|
|
|
|
::GetWindowRect(mWnd, &rect);
|
|
|
|
result = OnMove(rect.left, rect.top);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_CLOSE: // close request
|
|
|
|
DispatchStandardEvent(NS_XUL_CLOSE);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true; // abort window closure
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_DESTROY:
|
|
|
|
// clean up.
|
|
|
|
OnDestroy();
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_PAINT:
|
2011-06-09 07:13:05 +00:00
|
|
|
if (CleartypeSettingChanged()) {
|
|
|
|
ForceFontUpdate();
|
|
|
|
gfxFontCache *fc = gfxFontCache::GetCache();
|
|
|
|
if (fc) {
|
|
|
|
fc->Flush();
|
|
|
|
}
|
|
|
|
}
|
2010-07-15 21:08:08 +00:00
|
|
|
*aRetValue = (int) OnPaint(NULL, 0);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_PRINTCLIENT:
|
2010-07-15 21:08:08 +00:00
|
|
|
result = OnPaint((HDC) wParam, 0);
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_HOTKEY:
|
|
|
|
result = OnHotKey(wParam, lParam);
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_SYSCHAR:
|
|
|
|
case WM_CHAR:
|
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
MSG nativeMsg = WinUtils::InitMSG(msg, wParam, lParam);
|
2009-06-29 19:36:16 +00:00
|
|
|
result = ProcessCharMessage(nativeMsg, nsnull);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_SYSKEYUP:
|
|
|
|
case WM_KEYUP:
|
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
MSG nativeMsg = WinUtils::InitMSG(msg, wParam, lParam);
|
2011-02-12 01:56:13 +00:00
|
|
|
nativeMsg.time = ::GetMessageTime();
|
2009-06-29 19:36:16 +00:00
|
|
|
result = ProcessKeyUpMessage(nativeMsg, nsnull);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
MSG nativeMsg = WinUtils::InitMSG(msg, wParam, lParam);
|
2009-06-29 19:36:16 +00:00
|
|
|
result = ProcessKeyDownMessage(nativeMsg, nsnull);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// say we've dealt with erase background if widget does
|
|
|
|
// not need auto-erasing
|
|
|
|
case WM_ERASEBKGND:
|
2009-09-03 00:40:10 +00:00
|
|
|
if (!AutoErase((HDC)wParam)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
*aRetValue = 1;
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
mMousePresent = true;
|
2010-12-15 17:01:52 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Suppress dispatch of pending events
|
|
|
|
// when mouse moves are generated by widget
|
|
|
|
// creation instead of user input.
|
|
|
|
LPARAM lParamScreen = lParamToScreen(lParam);
|
|
|
|
POINT mp;
|
|
|
|
mp.x = GET_X_LPARAM(lParamScreen);
|
|
|
|
mp.y = GET_Y_LPARAM(lParamScreen);
|
2011-09-29 06:19:26 +00:00
|
|
|
bool userMovedMouse = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
if ((sLastMouseMovePoint.x != mp.x) || (sLastMouseMovePoint.y != mp.y)) {
|
2011-10-02 02:16:19 +00:00
|
|
|
userMovedMouse = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2010-04-06 12:59:24 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_MOVE, wParam, lParam,
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
if (userMovedMouse) {
|
|
|
|
DispatchPendingEvents();
|
2008-12-15 03:54:54 +00:00
|
|
|
}
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2010-12-15 17:01:52 +00:00
|
|
|
case WM_NCMOUSEMOVE:
|
|
|
|
// If we receive a mouse move event on non-client chrome, make sure and
|
|
|
|
// send an NS_MOUSE_EXIT event as well.
|
2011-01-20 03:21:50 +00:00
|
|
|
if (mMousePresent && !sIsInMouseCapture)
|
2010-12-15 17:01:52 +00:00
|
|
|
SendMessage(mWnd, WM_MOUSELEAVE, 0, 0);
|
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
{
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam,
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_LBUTTONUP:
|
|
|
|
{
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, wParam, lParam,
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MOUSELEAVE:
|
|
|
|
{
|
2010-12-15 17:01:52 +00:00
|
|
|
if (!mMousePresent)
|
|
|
|
break;
|
2011-10-02 02:16:19 +00:00
|
|
|
mMousePresent = false;
|
2010-12-15 17:01:52 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// We need to check mouse button states and put them in for
|
|
|
|
// wParam.
|
|
|
|
WPARAM mouseState = (GetKeyState(VK_LBUTTON) ? MK_LBUTTON : 0)
|
|
|
|
| (GetKeyState(VK_MBUTTON) ? MK_MBUTTON : 0)
|
|
|
|
| (GetKeyState(VK_RBUTTON) ? MK_RBUTTON : 0);
|
|
|
|
// Synthesize an event position because we don't get one from
|
|
|
|
// WM_MOUSELEAVE.
|
|
|
|
LPARAM pos = lParamToClient(::GetMessagePos());
|
2011-10-02 02:16:19 +00:00
|
|
|
DispatchMouseEvent(NS_MOUSE_EXIT, mouseState, pos, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_CONTEXTMENU:
|
|
|
|
{
|
|
|
|
// if the context menu is brought up from the keyboard, |lParam|
|
2010-08-05 12:36:11 +00:00
|
|
|
// will be -1.
|
2009-06-29 19:36:16 +00:00
|
|
|
LPARAM pos;
|
2011-09-29 06:19:26 +00:00
|
|
|
bool contextMenukey = false;
|
2010-08-05 12:36:11 +00:00
|
|
|
if (lParam == -1)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
contextMenukey = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
pos = lParamToClient(GetMessagePos());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pos = lParamToClient(lParam);
|
|
|
|
}
|
2010-04-06 12:59:24 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
result = DispatchMouseEvent(NS_CONTEXTMENU, wParam, pos, contextMenukey,
|
|
|
|
contextMenukey ?
|
|
|
|
nsMouseEvent::eLeftButton :
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eRightButton, MOUSE_INPUT_SOURCE());
|
2010-10-07 21:51:05 +00:00
|
|
|
if (lParam != -1 && !result && mCustomNonClient &&
|
|
|
|
DispatchMouseEvent(NS_MOUSE_MOZHITTEST, wParam, pos,
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eLeftButton,
|
2010-10-07 21:51:05 +00:00
|
|
|
MOUSE_INPUT_SOURCE())) {
|
|
|
|
// Blank area hit, throw up the system menu.
|
2010-10-22 22:38:18 +00:00
|
|
|
DisplaySystemMenu(mWnd, mSizeMode, mIsRTL, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2010-10-07 21:51:05 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_LBUTTONDBLCLK:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, wParam, lParam, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
|
2010-10-07 21:51:05 +00:00
|
|
|
DispatchPendingEvents();
|
2008-12-15 03:54:54 +00:00
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MBUTTONDOWN:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchPendingEvents();
|
2010-10-07 21:51:05 +00:00
|
|
|
break;
|
2008-12-15 03:54:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MBUTTONUP:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, wParam, lParam, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchPendingEvents();
|
2009-05-15 03:08:41 +00:00
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MBUTTONDBLCLK:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, wParam, lParam, false,
|
2010-09-02 21:50:26 +00:00
|
|
|
nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE());
|
2010-10-07 21:51:05 +00:00
|
|
|
DispatchPendingEvents();
|
2010-09-02 21:50:26 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_NCMBUTTONDOWN:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, 0, lParamToClient(lParam), false,
|
2010-09-02 21:50:26 +00:00
|
|
|
nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE());
|
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_NCMBUTTONUP:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, 0, lParamToClient(lParam), false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE());
|
2010-09-02 21:50:26 +00:00
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_NCMBUTTONDBLCLK:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, 0, lParamToClient(lParam), false,
|
2010-09-02 21:50:26 +00:00
|
|
|
nsMouseEvent::eMiddleButton, MOUSE_INPUT_SOURCE());
|
|
|
|
DispatchPendingEvents();
|
2008-12-15 03:54:54 +00:00
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_RBUTTONDOWN:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eRightButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchPendingEvents();
|
2010-10-07 21:51:05 +00:00
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_RBUTTONUP:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, wParam, lParam, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eRightButton, MOUSE_INPUT_SOURCE());
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_RBUTTONDBLCLK:
|
2011-10-02 02:16:19 +00:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, wParam, lParam, false,
|
2010-04-06 12:59:24 +00:00
|
|
|
nsMouseEvent::eRightButton, MOUSE_INPUT_SOURCE());
|
2010-10-07 21:51:05 +00:00
|
|
|
DispatchPendingEvents();
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2005-02-18 14:24:43 +00:00
|
|
|
|
2010-06-28 06:04:05 +00:00
|
|
|
case WM_NCRBUTTONDOWN:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, 0, lParamToClient(lParam),
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eRightButton,
|
2010-06-28 06:04:05 +00:00
|
|
|
MOUSE_INPUT_SOURCE());
|
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_NCRBUTTONUP:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, 0, lParamToClient(lParam),
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eRightButton,
|
2010-06-28 06:04:05 +00:00
|
|
|
MOUSE_INPUT_SOURCE());
|
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_NCRBUTTONDBLCLK:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, 0, lParamToClient(lParam),
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eRightButton,
|
2010-06-28 06:04:05 +00:00
|
|
|
MOUSE_INPUT_SOURCE());
|
2010-10-07 21:51:05 +00:00
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
2010-06-28 06:04:05 +00:00
|
|
|
|
2011-03-25 23:17:35 +00:00
|
|
|
case WM_EXITSIZEMOVE:
|
|
|
|
if (!sIsInMouseCapture) {
|
|
|
|
DispatchStandardEvent(NS_DONESIZEMOVE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-06-15 22:46:12 +00:00
|
|
|
case WM_NCLBUTTONDBLCLK:
|
|
|
|
DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, 0, lParamToClient(lParam),
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eLeftButton,
|
2011-06-15 22:46:12 +00:00
|
|
|
MOUSE_INPUT_SOURCE());
|
|
|
|
result =
|
|
|
|
DispatchMouseEvent(NS_MOUSE_BUTTON_UP, 0, lParamToClient(lParam),
|
2011-10-02 02:16:19 +00:00
|
|
|
false, nsMouseEvent::eLeftButton,
|
2011-06-15 22:46:12 +00:00
|
|
|
MOUSE_INPUT_SOURCE());
|
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_APPCOMMAND:
|
|
|
|
{
|
|
|
|
PRUint32 appCommand = GET_APPCOMMAND_LPARAM(lParam);
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (appCommand)
|
|
|
|
{
|
|
|
|
case APPCOMMAND_BROWSER_BACKWARD:
|
|
|
|
case APPCOMMAND_BROWSER_FORWARD:
|
|
|
|
case APPCOMMAND_BROWSER_REFRESH:
|
|
|
|
case APPCOMMAND_BROWSER_STOP:
|
|
|
|
case APPCOMMAND_BROWSER_SEARCH:
|
|
|
|
case APPCOMMAND_BROWSER_FAVORITES:
|
|
|
|
case APPCOMMAND_BROWSER_HOME:
|
|
|
|
DispatchCommandEvent(appCommand);
|
|
|
|
// tell the driver that we handled the event
|
|
|
|
*aRetValue = 1;
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
// default = false - tell the driver that the event was not handled
|
2004-05-04 12:39:42 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_HSCROLL:
|
|
|
|
case WM_VSCROLL:
|
2010-03-11 05:25:29 +00:00
|
|
|
*aRetValue = 0;
|
|
|
|
result = OnScroll(msg, wParam, lParam);
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
case MOZ_WM_HSCROLL:
|
|
|
|
case MOZ_WM_VSCROLL:
|
|
|
|
*aRetValue = 0;
|
2012-01-04 10:21:44 +00:00
|
|
|
OnScrollInternal(WinUtils::GetNativeMessage(msg), wParam, lParam);
|
2011-08-02 03:03:15 +00:00
|
|
|
// Doesn't need to call next wndproc for internal message.
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2011-08-02 03:03:15 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// The WM_ACTIVATE event is fired when a window is raised or lowered,
|
|
|
|
// and the loword of wParam specifies which. But we don't want to tell
|
|
|
|
// the focus system about this until the WM_SETFOCUS or WM_KILLFOCUS
|
|
|
|
// events are fired. Instead, set either the sJustGotActivate or
|
|
|
|
// gJustGotDeativate flags and fire the NS_ACTIVATE or NS_DEACTIVATE
|
|
|
|
// events once the focus events arrive.
|
|
|
|
case WM_ACTIVATE:
|
|
|
|
if (mEventCallback) {
|
|
|
|
PRInt32 fActive = LOWORD(wParam);
|
2006-04-17 17:42:20 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (WA_INACTIVE == fActive) {
|
|
|
|
// when minimizing a window, the deactivation and focus events will
|
|
|
|
// be fired in the reverse order. Instead, just dispatch
|
|
|
|
// NS_DEACTIVATE right away.
|
|
|
|
if (HIWORD(wParam))
|
|
|
|
result = DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
|
|
|
|
else
|
2011-10-02 02:16:19 +00:00
|
|
|
sJustGotDeactivate = true;
|
2011-04-25 03:10:12 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mIsTopWidgetWindow)
|
|
|
|
mLastKeyboardLayout = gKbdLayout.GetLayout();
|
2002-07-03 00:55:47 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
} else {
|
|
|
|
StopFlashing();
|
2002-07-03 00:55:47 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
sJustGotActivate = true;
|
|
|
|
nsMouseEvent event(true, NS_MOUSE_ACTIVATE, this,
|
2009-06-29 19:36:16 +00:00
|
|
|
nsMouseEvent::eReal);
|
|
|
|
InitEvent(event);
|
2010-08-20 18:19:38 +00:00
|
|
|
DispatchWindowEvent(&event);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sSwitchKeyboardLayout && mLastKeyboardLayout)
|
|
|
|
ActivateKeyboardLayout(mLastKeyboardLayout, 0);
|
|
|
|
}
|
|
|
|
}
|
2009-02-13 02:26:02 +00:00
|
|
|
break;
|
2009-08-26 16:07:15 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MOUSEACTIVATE:
|
|
|
|
if (mWindowType == eWindowType_popup) {
|
|
|
|
// a popup with a parent owner should not be activated when clicked
|
|
|
|
// but should still allow the mouse event to be fired, so the return
|
|
|
|
// value is set to MA_NOACTIVATE. But if the owner isn't the frontmost
|
|
|
|
// window, just use default processing so that the window is activated.
|
|
|
|
HWND owner = ::GetWindow(mWnd, GW_OWNER);
|
|
|
|
if (owner && owner == ::GetForegroundWindow()) {
|
|
|
|
*aRetValue = MA_NOACTIVATE;
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
2005-08-22 15:17:53 +00:00
|
|
|
break;
|
2005-07-18 16:04:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
|
|
{
|
|
|
|
LPWINDOWPOS info = (LPWINDOWPOS) lParam;
|
|
|
|
OnWindowPosChanging(info);
|
|
|
|
}
|
|
|
|
break;
|
2005-07-18 16:04:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_SETFOCUS:
|
2011-01-14 13:38:57 +00:00
|
|
|
// If previous focused window isn't ours, it must have received the
|
|
|
|
// redirected message. So, we should forget it.
|
2012-01-04 10:21:44 +00:00
|
|
|
if (!WinUtils::IsOurProcessWindow(HWND(wParam))) {
|
2011-01-14 13:38:57 +00:00
|
|
|
ForgetRedirectedKeyDownMessage();
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sJustGotActivate) {
|
|
|
|
result = DispatchFocusToTopLevelWindow(NS_ACTIVATE);
|
|
|
|
}
|
2000-03-21 03:42:00 +00:00
|
|
|
break;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_KILLFOCUS:
|
2012-02-08 04:10:11 +00:00
|
|
|
if (sJustGotDeactivate) {
|
2009-06-29 19:36:16 +00:00
|
|
|
result = DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
|
2008-09-13 21:52:17 +00:00
|
|
|
}
|
2009-02-13 08:34:42 +00:00
|
|
|
break;
|
2000-03-21 03:42:00 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
|
|
{
|
|
|
|
WINDOWPOS *wp = (LPWINDOWPOS)lParam;
|
2009-08-11 17:29:53 +00:00
|
|
|
OnWindowPosChanged(wp, result);
|
2009-08-11 17:45:42 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
1998-09-15 03:45:06 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_SETTINGCHANGE:
|
2011-05-17 00:23:23 +00:00
|
|
|
switch (wParam) {
|
|
|
|
case SPI_SETWHEELSCROLLLINES:
|
|
|
|
case SPI_SETWHEELSCROLLCHARS:
|
2011-10-02 02:16:19 +00:00
|
|
|
sNeedsToInitMouseWheelSettings = true;
|
2011-05-17 00:23:23 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2007-08-02 20:55:25 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_INPUTLANGCHANGEREQUEST:
|
|
|
|
*aRetValue = TRUE;
|
2011-10-02 02:16:19 +00:00
|
|
|
result = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2003-11-14 21:58:08 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_INPUTLANGCHANGE:
|
|
|
|
result = OnInputLangChange((HKL)lParam);
|
|
|
|
break;
|
1998-10-08 00:04:21 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_DESTROYCLIPBOARD:
|
|
|
|
{
|
|
|
|
nsIClipboard* clipboard;
|
|
|
|
nsresult rv = CallGetService(kCClipboardCID, &clipboard);
|
2010-08-20 18:19:38 +00:00
|
|
|
if(NS_SUCCEEDED(rv)) {
|
|
|
|
clipboard->EmptyClipboard(nsIClipboard::kGlobalClipboard);
|
|
|
|
NS_RELEASE(clipboard);
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
case WM_GETOBJECT:
|
|
|
|
{
|
|
|
|
*aRetValue = 0;
|
2011-07-14 08:08:25 +00:00
|
|
|
// Do explicit casting to make it working on 64bit systems (see bug 649236
|
|
|
|
// for details).
|
|
|
|
DWORD objId = static_cast<DWORD>(lParam);
|
|
|
|
if (objId == OBJID_CLIENT) { // oleacc.dll will be loaded dynamically
|
2010-05-12 06:47:35 +00:00
|
|
|
nsAccessible *rootAccessible = GetRootAccessible(); // Held by a11y cache
|
2009-06-29 19:36:16 +00:00
|
|
|
if (rootAccessible) {
|
|
|
|
IAccessible *msaaAccessible = NULL;
|
|
|
|
rootAccessible->GetNativeInterface((void**)&msaaAccessible); // does an addref
|
|
|
|
if (msaaAccessible) {
|
|
|
|
*aRetValue = LresultFromObject(IID_IAccessible, wParam, msaaAccessible); // does an addref
|
|
|
|
msaaAccessible->Release(); // release extra addref
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true; // We handled the WM_GETOBJECT message
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2008-04-03 11:55:14 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_SYSCOMMAND:
|
2010-11-29 16:19:17 +00:00
|
|
|
{
|
|
|
|
WPARAM filteredWParam = (wParam &0xFFF0);
|
2009-06-29 19:36:16 +00:00
|
|
|
// prevent Windows from trimming the working set. bug 76831
|
2010-11-29 16:19:17 +00:00
|
|
|
if (!sTrimOnMinimize && filteredWParam == SC_MINIMIZE) {
|
2009-06-29 19:36:16 +00:00
|
|
|
::ShowWindow(mWnd, SW_SHOWMINIMIZED);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2010-10-22 22:38:18 +00:00
|
|
|
|
|
|
|
// Handle the system menu manually when we're in full screen mode
|
|
|
|
// so we can set the appropriate options.
|
2010-11-29 16:19:17 +00:00
|
|
|
if (filteredWParam == SC_KEYMENU && lParam == VK_SPACE &&
|
2010-10-22 22:38:18 +00:00
|
|
|
mSizeMode == nsSizeMode_Fullscreen) {
|
|
|
|
DisplaySystemMenu(mWnd, mSizeMode, mIsRTL,
|
|
|
|
MOZ_SYSCONTEXT_X_POS,
|
|
|
|
MOZ_SYSCONTEXT_Y_POS);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2010-10-22 22:38:18 +00:00
|
|
|
}
|
2010-11-29 16:19:17 +00:00
|
|
|
}
|
|
|
|
break;
|
2008-04-03 11:55:14 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
case WM_MOUSEHWHEEL:
|
2011-08-02 03:03:15 +00:00
|
|
|
OnMouseWheel(msg, wParam, lParam, aRetValue);
|
|
|
|
// We don't need to call next wndproc WM_MOUSEWHEEL and WM_MOUSEHWHEEL.
|
|
|
|
// We should consume them always. If the messages would be handled by
|
|
|
|
// our window again, it causes making infinite message loop.
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2011-08-02 03:03:15 +00:00
|
|
|
|
|
|
|
case MOZ_WM_MOUSEVWHEEL:
|
|
|
|
case MOZ_WM_MOUSEHWHEEL:
|
2009-06-30 18:19:15 +00:00
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
UINT nativeMessage = WinUtils::GetNativeMessage(msg);
|
2009-06-30 18:19:15 +00:00
|
|
|
// If OnMouseWheel returns true, the event was forwarded directly to another
|
|
|
|
// mozilla window message handler (ProcessMessage). In this case the return
|
|
|
|
// value of the forwarded event is in 'result' which we should return immediately.
|
|
|
|
// If OnMouseWheel returns false, OnMouseWheel processed the event internally.
|
|
|
|
// 'result' and 'aRetValue' will be set based on what we did with the event, so
|
|
|
|
// we should fall through.
|
2011-08-02 03:03:15 +00:00
|
|
|
OnMouseWheelInternal(nativeMessage, wParam, lParam, aRetValue);
|
|
|
|
// Doesn't need to call next wndproc for internal message.
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-06-30 18:19:15 +00:00
|
|
|
}
|
2008-04-03 11:55:14 +00:00
|
|
|
|
2009-09-26 22:42:14 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_DWMCOMPOSITIONCHANGED:
|
2010-11-18 02:31:22 +00:00
|
|
|
// First, update the compositor state to latest one. All other methods
|
|
|
|
// should use same state as here for consistency painting.
|
2011-10-02 02:16:19 +00:00
|
|
|
nsUXThemeData::CheckForCompositor(true);
|
2010-11-18 02:31:22 +00:00
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
UpdateNonClientMargins();
|
2010-11-12 07:50:38 +00:00
|
|
|
RemovePropW(mWnd, kManageWindowInfoProperty);
|
2009-06-29 19:36:16 +00:00
|
|
|
BroadcastMsg(mWnd, WM_DWMCOMPOSITIONCHANGED);
|
|
|
|
DispatchStandardEvent(NS_THEMECHANGED);
|
2010-03-17 22:56:00 +00:00
|
|
|
UpdateGlass();
|
2011-12-24 03:52:21 +00:00
|
|
|
Invalidate(true, true, true);
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
|
|
|
#endif
|
2008-04-03 11:55:14 +00:00
|
|
|
|
2010-04-21 14:53:42 +00:00
|
|
|
case WM_UPDATEUISTATE:
|
|
|
|
{
|
|
|
|
// If the UI state has changed, fire an event so the UI updates the
|
|
|
|
// keyboard cues based on the system setting and how the window was
|
|
|
|
// opened. For example, a dialog opened via a keyboard press on a button
|
|
|
|
// should enable cues, whereas the same dialog opened via a mouse click of
|
|
|
|
// the button should not.
|
|
|
|
PRInt32 action = LOWORD(wParam);
|
|
|
|
if (action == UIS_SET || action == UIS_CLEAR) {
|
2011-10-02 02:16:19 +00:00
|
|
|
nsUIStateChangeEvent event(true, NS_UISTATECHANGED, this);
|
2010-04-21 14:53:42 +00:00
|
|
|
PRInt32 flags = HIWORD(wParam);
|
|
|
|
if (flags & UISF_HIDEACCEL)
|
|
|
|
event.showAccelerators = (action == UIS_SET) ? UIStateChangeType_Clear : UIStateChangeType_Set;
|
|
|
|
if (flags & UISF_HIDEFOCUS)
|
|
|
|
event.showFocusRings = (action == UIS_SET) ? UIStateChangeType_Clear : UIStateChangeType_Set;
|
|
|
|
DispatchWindowEvent(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/* Gesture support events */
|
|
|
|
case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
|
|
|
|
// According to MS samples, this must be handled to enable
|
|
|
|
// rotational support in multi-touch drivers.
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
*aRetValue = TABLET_ROTATE_GESTURE_ENABLE;
|
|
|
|
break;
|
2010-08-02 13:34:54 +00:00
|
|
|
|
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
|
|
|
case WM_TOUCH:
|
|
|
|
result = OnTouch(wParam, lParam);
|
|
|
|
if (result) {
|
|
|
|
*aRetValue = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
case WM_GESTURE:
|
|
|
|
result = OnGesture(wParam, lParam);
|
|
|
|
break;
|
2009-08-13 20:54:09 +00:00
|
|
|
|
|
|
|
case WM_GESTURENOTIFY:
|
|
|
|
{
|
|
|
|
if (mWindowType != eWindowType_invisible &&
|
2010-08-27 21:26:17 +00:00
|
|
|
mWindowType != eWindowType_plugin) {
|
|
|
|
// A GestureNotify event is dispatched to decide which single-finger panning
|
|
|
|
// direction should be active (including none) and if pan feedback should
|
|
|
|
// be displayed. Java and plugin windows can make their own calls.
|
2009-08-13 20:54:09 +00:00
|
|
|
GESTURENOTIFYSTRUCT * gestureinfo = (GESTURENOTIFYSTRUCT*)lParam;
|
|
|
|
nsPointWin touchPoint;
|
|
|
|
touchPoint = gestureinfo->ptsLocation;
|
|
|
|
touchPoint.ScreenToClient(mWnd);
|
2011-10-02 02:16:19 +00:00
|
|
|
nsGestureNotifyEvent gestureNotifyEvent(true, NS_GESTURENOTIFY_EVENT_START, this);
|
2009-08-13 20:54:09 +00:00
|
|
|
gestureNotifyEvent.refPoint = touchPoint;
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(&gestureNotifyEvent, status);
|
|
|
|
mDisplayPanFeedback = gestureNotifyEvent.displayPanFeedback;
|
2010-08-02 13:34:54 +00:00
|
|
|
if (!mTouchWindow)
|
|
|
|
mGesture.SetWinGestureSupport(mWnd, gestureNotifyEvent.panDirection);
|
2009-08-13 20:54:09 +00:00
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
result = false; //should always bubble to DefWindowProc
|
2009-08-13 20:54:09 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-02-16 01:09:11 +00:00
|
|
|
|
2009-08-07 15:11:17 +00:00
|
|
|
case WM_CLEAR:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_DELETE, this);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CUT:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_CUT, this);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COPY:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_COPY, this);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_PASTE:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_PASTE, this);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_UNDO:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_UNDO, this);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_REDO:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_REDO, this);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_CANPASTE:
|
|
|
|
{
|
|
|
|
// Support EM_CANPASTE message only when wParam isn't specified or
|
|
|
|
// is plain text format.
|
|
|
|
if (wParam == 0 || wParam == CF_TEXT || wParam == CF_UNICODETEXT) {
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_PASTE,
|
|
|
|
this, true);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_CANUNDO:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_UNDO,
|
|
|
|
this, true);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_CANREDO:
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_REDO,
|
|
|
|
this, true);
|
2009-08-07 15:11:17 +00:00
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2009-08-07 15:11:17 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-08-26 16:07:15 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
if (msg == WM_USER_TSF_TEXTCHANGE) {
|
|
|
|
nsTextStore::OnTextChangeMsg();
|
|
|
|
}
|
|
|
|
#endif //NS_ENABLE_TSF
|
2009-10-06 02:26:54 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
|
|
|
if (msg == nsAppShell::GetTaskbarButtonCreatedMessage())
|
|
|
|
SetHasTaskbarIconBeenCreated();
|
2010-01-26 21:40:15 +00:00
|
|
|
#endif
|
2010-02-23 01:10:08 +00:00
|
|
|
if (msg == sOOPPPluginFocusEvent) {
|
2010-06-23 17:08:56 +00:00
|
|
|
if (wParam == 1) {
|
|
|
|
// With OOPP, the plugin window exists in another process and is a child of
|
|
|
|
// this window. This window is a placeholder plugin window for the dom. We
|
|
|
|
// receive this event when the child window receives focus. (sent from
|
|
|
|
// PluginInstanceParent.cpp)
|
|
|
|
::SendMessage(mWnd, WM_MOUSEACTIVATE, 0, 0); // See nsPluginNativeWindowWin.cpp
|
|
|
|
} else {
|
|
|
|
// WM_KILLFOCUS was received by the child process.
|
|
|
|
if (sJustGotDeactivate) {
|
|
|
|
DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
|
|
|
|
}
|
|
|
|
}
|
2010-02-23 01:10:08 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-02-16 01:09:11 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
//*aRetValue = result;
|
|
|
|
if (mWnd) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//Events which caused mWnd destruction and aren't consumed
|
|
|
|
//will crash during the Windows default processing.
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2008-04-03 11:55:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Broadcast messaging
|
|
|
|
*
|
|
|
|
* Broadcast messages to all windows.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Enumerate all child windows sending aMsg to each of them
|
|
|
|
BOOL CALLBACK nsWindow::BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg)
|
2009-04-23 00:48:30 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
WNDPROC winProc = (WNDPROC)::GetWindowLongPtrW(aWnd, GWLP_WNDPROC);
|
|
|
|
if (winProc == &nsWindow::WindowProc) {
|
|
|
|
// it's one of our windows so go ahead and send a message to it
|
|
|
|
::CallWindowProcW(winProc, aWnd, aMsg, 0, 0);
|
2009-04-23 00:48:30 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return TRUE;
|
2009-04-23 00:48:30 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Enumerate all top level windows specifying that the children of each
|
|
|
|
// top level window should be enumerated. Do *not* send the message to
|
|
|
|
// each top level window since it is assumed that the toolkit will send
|
|
|
|
// aMsg to them directly.
|
|
|
|
BOOL CALLBACK nsWindow::BroadcastMsg(HWND aTopWindow, LPARAM aMsg)
|
|
|
|
{
|
|
|
|
// Iterate each of aTopWindows child windows sending the aMsg
|
|
|
|
// to each of them.
|
|
|
|
::EnumChildWindows(aTopWindow, nsWindow::BroadcastMsgToChildren, aMsg);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Event processing helpers
|
|
|
|
*
|
|
|
|
* Special processing for certain event types and
|
|
|
|
* synthesized events.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
1998-12-15 05:44:21 +00:00
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
PRInt32
|
|
|
|
nsWindow::ClientMarginHitTestPoint(PRInt32 mx, PRInt32 my)
|
|
|
|
{
|
2012-01-13 15:10:05 +00:00
|
|
|
if (mSizeMode == nsSizeMode_Minimized ||
|
|
|
|
mSizeMode == nsSizeMode_Fullscreen) {
|
|
|
|
return HTCLIENT;
|
|
|
|
}
|
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
// Calculations are done in screen coords
|
|
|
|
RECT winRect;
|
|
|
|
GetWindowRect(mWnd, &winRect);
|
|
|
|
|
|
|
|
// hit return constants:
|
|
|
|
// HTBORDER - non-resizable border
|
|
|
|
// HTBOTTOM, HTLEFT, HTRIGHT, HTTOP - resizable border
|
|
|
|
// HTBOTTOMLEFT, HTBOTTOMRIGHT - resizable corner
|
|
|
|
// HTTOPLEFT, HTTOPRIGHT - resizable corner
|
|
|
|
// HTCAPTION - general title bar area
|
|
|
|
// HTCLIENT - area considered the client
|
|
|
|
// HTCLOSE - hovering over the close button
|
|
|
|
// HTMAXBUTTON - maximize button
|
|
|
|
// HTMINBUTTON - minimize button
|
|
|
|
|
|
|
|
PRInt32 testResult = HTCLIENT;
|
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
bool isResizable = (mBorderStyle & (eBorderStyle_all |
|
|
|
|
eBorderStyle_resizeh |
|
|
|
|
eBorderStyle_default)) > 0 ? true : false;
|
|
|
|
if (mSizeMode == nsSizeMode_Maximized)
|
|
|
|
isResizable = false;
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool top = false;
|
|
|
|
bool bottom = false;
|
|
|
|
bool left = false;
|
|
|
|
bool right = false;
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
int topOffset = NS_MAX(mCaptionHeight - mNonClientOffset.top,
|
|
|
|
kResizableBorderMinSize);
|
|
|
|
int bottomOffset = NS_MAX(mVertResizeMargin - mNonClientOffset.bottom,
|
|
|
|
kResizableBorderMinSize);
|
|
|
|
int topBounds = winRect.top + topOffset;
|
|
|
|
int bottomBounds = winRect.bottom - bottomOffset;
|
|
|
|
|
|
|
|
if (my >= winRect.top && my < topBounds)
|
2011-10-02 02:16:19 +00:00
|
|
|
top = true;
|
2012-01-13 15:10:05 +00:00
|
|
|
else if (my <= winRect.bottom && my > bottomBounds)
|
2011-10-02 02:16:19 +00:00
|
|
|
bottom = true;
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
int leftOffset = NS_MAX(mHorResizeMargin - mNonClientOffset.left,
|
|
|
|
kResizableBorderMinSize);
|
|
|
|
int rightOffset = NS_MAX(mHorResizeMargin - mNonClientOffset.right,
|
|
|
|
kResizableBorderMinSize);
|
|
|
|
// (the 2x case here doubles the resize area for corners)
|
|
|
|
int leftBounds = winRect.left +
|
|
|
|
(bottom ? (2*leftOffset) : leftOffset);
|
|
|
|
int rightBounds = winRect.right -
|
|
|
|
(bottom ? (2*rightOffset) : rightOffset);
|
|
|
|
|
|
|
|
if (mx >= winRect.left && mx < leftBounds)
|
2011-10-02 02:16:19 +00:00
|
|
|
left = true;
|
2012-01-13 15:10:05 +00:00
|
|
|
else if (mx <= winRect.right && mx > rightBounds)
|
2011-10-02 02:16:19 +00:00
|
|
|
right = true;
|
2010-06-25 02:01:07 +00:00
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
if (isResizable) {
|
|
|
|
if (top) {
|
|
|
|
testResult = HTTOP;
|
|
|
|
if (left)
|
|
|
|
testResult = HTTOPLEFT;
|
|
|
|
else if (right)
|
|
|
|
testResult = HTTOPRIGHT;
|
|
|
|
} else if (bottom) {
|
|
|
|
testResult = HTBOTTOM;
|
|
|
|
if (left)
|
|
|
|
testResult = HTBOTTOMLEFT;
|
|
|
|
else if (right)
|
|
|
|
testResult = HTBOTTOMRIGHT;
|
|
|
|
} else {
|
|
|
|
if (left)
|
|
|
|
testResult = HTLEFT;
|
|
|
|
if (right)
|
|
|
|
testResult = HTRIGHT;
|
|
|
|
}
|
2010-06-25 02:01:07 +00:00
|
|
|
} else {
|
2012-01-13 15:10:05 +00:00
|
|
|
if (top)
|
|
|
|
testResult = HTCAPTION;
|
|
|
|
else if (bottom || left || right)
|
|
|
|
testResult = HTBORDER;
|
2010-06-25 02:01:07 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool contentOverlap = true;
|
2010-07-22 06:58:06 +00:00
|
|
|
|
2012-01-13 15:10:05 +00:00
|
|
|
if (mSizeMode != nsSizeMode_Maximized) {
|
|
|
|
contentOverlap = mx >= winRect.left + leftOffset &&
|
|
|
|
mx <= winRect.right - rightOffset &&
|
|
|
|
my >= winRect.top + topOffset &&
|
|
|
|
my <= winRect.bottom - bottomOffset;
|
2010-07-22 06:58:06 +00:00
|
|
|
}
|
2010-06-30 22:59:33 +00:00
|
|
|
|
2011-01-20 03:21:50 +00:00
|
|
|
if (!sIsInMouseCapture &&
|
2010-07-22 06:58:06 +00:00
|
|
|
contentOverlap &&
|
2010-06-30 22:59:33 +00:00
|
|
|
(testResult == HTCLIENT ||
|
|
|
|
testResult == HTTOP ||
|
2012-01-13 15:10:05 +00:00
|
|
|
testResult == HTBORDER ||
|
2010-06-30 22:59:33 +00:00
|
|
|
testResult == HTTOPLEFT ||
|
|
|
|
testResult == HTCAPTION)) {
|
2010-06-28 06:04:05 +00:00
|
|
|
LPARAM lParam = MAKELPARAM(mx, my);
|
|
|
|
LPARAM lParamClient = lParamToClient(lParam);
|
2011-09-29 06:19:26 +00:00
|
|
|
bool result = DispatchMouseEvent(NS_MOUSE_MOZHITTEST, 0, lParamClient,
|
2012-01-13 15:10:05 +00:00
|
|
|
false, nsMouseEvent::eLeftButton, MOUSE_INPUT_SOURCE());
|
2010-06-28 06:04:05 +00:00
|
|
|
if (result) {
|
|
|
|
// The mouse is over a blank area
|
|
|
|
testResult = testResult == HTCLIENT ? HTCAPTION : testResult;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// There's content over the mouse pointer. Set HTCLIENT
|
|
|
|
// to possibly override a resizer border.
|
|
|
|
testResult = HTCLIENT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
return testResult;
|
|
|
|
}
|
|
|
|
|
2011-11-08 19:59:09 +00:00
|
|
|
void nsWindow::PostSleepWakeNotification(const bool aIsSleepMode)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2011-11-08 19:59:09 +00:00
|
|
|
if (aIsSleepMode == gIsSleepMode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gIsSleepMode = aIsSleepMode;
|
|
|
|
|
Bug 560095 - Use mozilla::services::GetObserverService(). r=biesi,dveditz,gavin,josh,jst,mrbkap,roc,sdwilsh,shaver,sicking,smontagu,surkov
2010-04-29 16:59:13 +00:00
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
|
|
mozilla::services::GetObserverService();
|
2009-06-29 19:36:16 +00:00
|
|
|
if (observerService)
|
2011-11-08 19:59:09 +00:00
|
|
|
observerService->NotifyObservers(nsnull,
|
|
|
|
aIsSleepMode ? "sleep_notification" : "wake_notification", nsnull);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2005-12-19 03:00:41 +00:00
|
|
|
|
2011-01-14 13:38:57 +00:00
|
|
|
// RemoveNextCharMessage() should be called by WM_KEYDOWN or WM_SYSKEYDOWM
|
|
|
|
// message handler. If there is no WM_(SYS)CHAR message for it, this
|
|
|
|
// method does nothing.
|
|
|
|
// NOTE: WM_(SYS)CHAR message is posted by TranslateMessage() API which is
|
|
|
|
// called in message loop. So, WM_(SYS)KEYDOWN message should have
|
|
|
|
// WM_(SYS)CHAR message in the queue if the keydown event causes character
|
|
|
|
// input.
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void nsWindow::RemoveNextCharMessage(HWND aWnd)
|
|
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
if (::PeekMessageW(&msg, aWnd,
|
|
|
|
WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD) &&
|
|
|
|
(msg.message == WM_CHAR || msg.message == WM_SYSCHAR)) {
|
|
|
|
::GetMessageW(&msg, aWnd, msg.message, msg.message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
LRESULT nsWindow::ProcessCharMessage(const MSG &aMsg, bool *aEventDispatched)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aMsg.message == WM_CHAR || aMsg.message == WM_SYSCHAR,
|
|
|
|
"message is not keydown event");
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("%s charCode=%d scanCode=%d\n",
|
2011-08-16 19:30:44 +00:00
|
|
|
aMsg.message == WM_SYSCHAR ? "WM_SYSCHAR" : "WM_CHAR",
|
|
|
|
aMsg.wParam, HIWORD(aMsg.lParam) & 0xFF));
|
1998-12-15 05:44:21 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// These must be checked here too as a lone WM_CHAR could be received
|
|
|
|
// if a child window didn't handle it (for example Alt+Space in a content window)
|
|
|
|
nsModifierKeyState modKeyState;
|
|
|
|
return OnChar(aMsg, modKeyState, aEventDispatched);
|
|
|
|
}
|
2004-12-09 17:56:46 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
LRESULT nsWindow::ProcessKeyUpMessage(const MSG &aMsg, bool *aEventDispatched)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aMsg.message == WM_KEYUP || aMsg.message == WM_SYSKEYUP,
|
|
|
|
"message is not keydown event");
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("%s VK=%d\n", aMsg.message == WM_SYSKEYDOWN ?
|
2011-08-16 19:30:44 +00:00
|
|
|
"WM_SYSKEYUP" : "WM_KEYUP", aMsg.wParam));
|
2008-09-27 22:40:34 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsModifierKeyState modKeyState;
|
1999-09-09 03:47:26 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Note: the original code passed (HIWORD(lParam)) to OnKeyUp as
|
|
|
|
// scan code. However, this breaks Alt+Num pad input.
|
|
|
|
// MSDN states the following:
|
|
|
|
// Typically, ToAscii performs the translation based on the
|
|
|
|
// virtual-key code. In some cases, however, bit 15 of the
|
|
|
|
// uScanCode parameter may be used to distinguish between a key
|
|
|
|
// press and a key release. The scan code is used for
|
|
|
|
// translating ALT+number key combinations.
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// ignore [shift+]alt+space so the OS can handle it
|
|
|
|
if (modKeyState.mIsAltDown && !modKeyState.mIsControlDown &&
|
|
|
|
IS_VK_DOWN(NS_VK_SPACE)) {
|
|
|
|
return FALSE;
|
2008-04-03 11:55:14 +00:00
|
|
|
}
|
|
|
|
|
2010-08-08 09:23:25 +00:00
|
|
|
if (!nsIMM32Handler::IsComposingOn(this) &&
|
2010-03-26 08:27:27 +00:00
|
|
|
(aMsg.message != WM_KEYUP || aMsg.wParam != VK_MENU)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
// Ignore VK_MENU if it's not a system key release, so that the menu bar does not trigger
|
|
|
|
// This helps avoid triggering the menu bar for ALT key accelerators used in
|
|
|
|
// assistive technologies such as Window-Eyes and ZoomText, and when using Alt+Tab
|
|
|
|
// to switch back to Mozilla in Windows 95 and Windows 98
|
|
|
|
return OnKeyUp(aMsg, modKeyState, aEventDispatched);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return 0;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
LRESULT nsWindow::ProcessKeyDownMessage(const MSG &aMsg,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool *aEventDispatched)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("%s VK=%d\n", aMsg.message == WM_SYSKEYDOWN ?
|
2011-08-16 19:30:44 +00:00
|
|
|
"WM_SYSKEYDOWN" : "WM_KEYDOWN", aMsg.wParam));
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_PRECONDITION(aMsg.message == WM_KEYDOWN || aMsg.message == WM_SYSKEYDOWN,
|
|
|
|
"message is not keydown event");
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-01-14 13:38:57 +00:00
|
|
|
// If this method doesn't call OnKeyDown(), this method must clean up the
|
|
|
|
// redirected message information itself. For more information, see above
|
|
|
|
// comment of AutoForgetRedirectedKeyDownMessage struct definition in
|
|
|
|
// nsWindow.h.
|
|
|
|
AutoForgetRedirectedKeyDownMessage forgetRedirectedMessage(this, aMsg);
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsModifierKeyState modKeyState;
|
1998-12-15 05:44:21 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Note: the original code passed (HIWORD(lParam)) to OnKeyDown as
|
|
|
|
// scan code. However, this breaks Alt+Num pad input.
|
|
|
|
// MSDN states the following:
|
|
|
|
// Typically, ToAscii performs the translation based on the
|
|
|
|
// virtual-key code. In some cases, however, bit 15 of the
|
|
|
|
// uScanCode parameter may be used to distinguish between a key
|
|
|
|
// press and a key release. The scan code is used for
|
|
|
|
// translating ALT+number key combinations.
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// ignore [shift+]alt+space so the OS can handle it
|
|
|
|
if (modKeyState.mIsAltDown && !modKeyState.mIsControlDown &&
|
|
|
|
IS_VK_DOWN(NS_VK_SPACE))
|
|
|
|
return FALSE;
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
LRESULT result = 0;
|
|
|
|
if (modKeyState.mIsAltDown && nsIMM32Handler::IsStatusChanged()) {
|
|
|
|
nsIMM32Handler::NotifyEndStatusChange();
|
2010-08-08 09:23:25 +00:00
|
|
|
} else if (!nsIMM32Handler::IsComposingOn(this)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
result = OnKeyDown(aMsg, modKeyState, aEventDispatched, nsnull);
|
2011-01-14 13:38:57 +00:00
|
|
|
// OnKeyDown cleaned up the redirected message information itself, so,
|
|
|
|
// we should do nothing.
|
2011-10-02 02:16:19 +00:00
|
|
|
forgetRedirectedMessage.mCancel = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aMsg.wParam == VK_MENU ||
|
|
|
|
(aMsg.wParam == VK_F10 && !modKeyState.mIsShiftDown)) {
|
|
|
|
// We need to let Windows handle this keypress,
|
2011-10-02 02:16:19 +00:00
|
|
|
// by returning false, if there's a native menu
|
2009-06-29 19:36:16 +00:00
|
|
|
// bar somewhere in our containing window hierarchy.
|
|
|
|
// Otherwise we handle the keypress and don't pass
|
2011-10-02 02:16:19 +00:00
|
|
|
// it on to Windows, by returning true.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool hasNativeMenu = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
HWND hWnd = mWnd;
|
|
|
|
while (hWnd) {
|
|
|
|
if (::GetMenu(hWnd)) {
|
2011-10-02 02:16:19 +00:00
|
|
|
hasNativeMenu = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
break;
|
2009-04-23 00:48:30 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
hWnd = ::GetParent(hWnd);
|
2009-04-23 00:48:30 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
result = !hasNativeMenu;
|
|
|
|
}
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return result;
|
|
|
|
}
|
2009-03-09 05:08:41 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsresult
|
|
|
|
nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
|
|
|
PRInt32 aNativeKeyCode,
|
|
|
|
PRUint32 aModifierFlags,
|
|
|
|
const nsAString& aCharacters,
|
|
|
|
const nsAString& aUnmodifiedCharacters)
|
|
|
|
{
|
|
|
|
nsPrintfCString layoutName("%08x", aNativeKeyboardLayout);
|
|
|
|
HKL loadedLayout = LoadKeyboardLayoutA(layoutName.get(), KLF_NOTELLSHELL);
|
|
|
|
if (loadedLayout == NULL)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2009-03-09 05:08:41 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Setup clean key state and load desired layout
|
|
|
|
BYTE originalKbdState[256];
|
|
|
|
::GetKeyboardState(originalKbdState);
|
|
|
|
BYTE kbdState[256];
|
|
|
|
memset(kbdState, 0, sizeof(kbdState));
|
|
|
|
// This changes the state of the keyboard for the current thread only,
|
|
|
|
// and we'll restore it soon, so this should be OK.
|
|
|
|
::SetKeyboardState(kbdState);
|
|
|
|
HKL oldLayout = gKbdLayout.GetLayout();
|
|
|
|
gKbdLayout.LoadLayout(loadedLayout);
|
2009-03-09 05:08:41 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsAutoTArray<KeyPair,10> keySequence;
|
|
|
|
SetupKeyModifiersSequence(&keySequence, aModifierFlags);
|
|
|
|
NS_ASSERTION(aNativeKeyCode >= 0 && aNativeKeyCode < 256,
|
|
|
|
"Native VK key code out of range");
|
|
|
|
keySequence.AppendElement(KeyPair(aNativeKeyCode, 0));
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Simulate the pressing of each modifier key and then the real key
|
|
|
|
for (PRUint32 i = 0; i < keySequence.Length(); ++i) {
|
|
|
|
PRUint8 key = keySequence[i].mGeneral;
|
|
|
|
PRUint8 keySpecific = keySequence[i].mSpecific;
|
|
|
|
kbdState[key] = 0x81; // key is down and toggled on if appropriate
|
|
|
|
if (keySpecific) {
|
|
|
|
kbdState[keySpecific] = 0x81;
|
2009-04-23 00:48:30 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
::SetKeyboardState(kbdState);
|
|
|
|
nsModifierKeyState modKeyState;
|
2012-01-04 10:21:44 +00:00
|
|
|
MSG msg = WinUtils::InitMSG(WM_KEYDOWN, key, 0);
|
2009-06-29 19:36:16 +00:00
|
|
|
if (i == keySequence.Length() - 1 && aCharacters.Length() > 0) {
|
|
|
|
UINT scanCode = ::MapVirtualKeyEx(aNativeKeyCode, MAPVK_VK_TO_VSC,
|
|
|
|
gKbdLayout.GetLayout());
|
|
|
|
nsFakeCharMessage fakeMsg = { aCharacters.CharAt(0), scanCode };
|
|
|
|
OnKeyDown(msg, modKeyState, nsnull, &fakeMsg);
|
|
|
|
} else {
|
|
|
|
OnKeyDown(msg, modKeyState, nsnull, nsnull);
|
2009-04-23 00:48:30 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
for (PRUint32 i = keySequence.Length(); i > 0; --i) {
|
|
|
|
PRUint8 key = keySequence[i - 1].mGeneral;
|
|
|
|
PRUint8 keySpecific = keySequence[i - 1].mSpecific;
|
|
|
|
kbdState[key] = 0; // key is up and toggled off if appropriate
|
|
|
|
if (keySpecific) {
|
|
|
|
kbdState[keySpecific] = 0;
|
2009-04-23 00:48:30 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
::SetKeyboardState(kbdState);
|
|
|
|
nsModifierKeyState modKeyState;
|
2012-01-04 10:21:44 +00:00
|
|
|
MSG msg = WinUtils::InitMSG(WM_KEYUP, key, 0);
|
2009-06-29 19:36:16 +00:00
|
|
|
OnKeyUp(msg, modKeyState, nsnull);
|
|
|
|
}
|
2006-02-15 23:35:53 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Restore old key state and layout
|
|
|
|
::SetKeyboardState(originalKbdState);
|
|
|
|
gKbdLayout.LoadLayout(oldLayout);
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
UnloadKeyboardLayout(loadedLayout);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-10-07 11:14:12 +00:00
|
|
|
nsresult
|
|
|
|
nsWindow::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
|
|
|
|
PRUint32 aNativeMessage,
|
|
|
|
PRUint32 aModifierFlags)
|
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
::GetWindowRect(mWnd, &r);
|
|
|
|
::SetCursorPos(r.left + aPoint.x, r.top + aPoint.y);
|
|
|
|
|
|
|
|
INPUT input;
|
|
|
|
memset(&input, 0, sizeof(input));
|
|
|
|
|
|
|
|
input.type = INPUT_MOUSE;
|
|
|
|
input.mi.dwFlags = aNativeMessage;
|
|
|
|
::SendInput(1, &input, sizeof(INPUT));
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: OnXXX message handlers
|
|
|
|
*
|
|
|
|
* For message handlers that need to be broken out or
|
|
|
|
* implemented in specific platform code.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2006-02-15 23:35:53 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
BOOL nsWindow::OnInputLangChange(HKL aHKL)
|
|
|
|
{
|
|
|
|
#ifdef KE_DEBUG
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("OnInputLanguageChange\n"));
|
2009-04-23 00:48:30 +00:00
|
|
|
#endif
|
2009-06-29 19:36:16 +00:00
|
|
|
gKbdLayout.LoadLayout(aHKL);
|
2011-10-02 02:16:19 +00:00
|
|
|
return false; // always pass to child window
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-04-14 22:12:38 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
void nsWindow::OnWindowPosChanged(WINDOWPOS *wp, bool& result)
|
2009-08-11 17:29:53 +00:00
|
|
|
{
|
|
|
|
if (wp == nsnull)
|
|
|
|
return;
|
|
|
|
|
2009-11-10 16:24:10 +00:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
2012-01-04 10:21:44 +00:00
|
|
|
if (mWnd == WinUtils::GetTopLevelHWND(mWnd)) {
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("*** OnWindowPosChanged: [ top] "));
|
|
|
|
} else {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("*** OnWindowPosChanged: [child] "));
|
|
|
|
}
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("WINDOWPOS flags:"));
|
|
|
|
if (wp->flags & SWP_FRAMECHANGED) {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("SWP_FRAMECHANGED "));
|
|
|
|
}
|
|
|
|
if (wp->flags & SWP_SHOWWINDOW) {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("SWP_SHOWWINDOW "));
|
|
|
|
}
|
|
|
|
if (wp->flags & SWP_NOSIZE) {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("SWP_NOSIZE "));
|
|
|
|
}
|
|
|
|
if (wp->flags & SWP_HIDEWINDOW) {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("SWP_HIDEWINDOW "));
|
|
|
|
}
|
|
|
|
if (wp->flags & SWP_NOZORDER) {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("SWP_NOZORDER "));
|
|
|
|
}
|
|
|
|
if (wp->flags & SWP_NOACTIVATE) {
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("SWP_NOACTIVATE "));
|
|
|
|
}
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("\n"));
|
2009-11-10 16:24:10 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Handle window size mode changes
|
2010-06-28 06:04:20 +00:00
|
|
|
if (wp->flags & SWP_FRAMECHANGED && mSizeMode != nsSizeMode_Fullscreen) {
|
2010-10-22 18:43:40 +00:00
|
|
|
|
|
|
|
// Bug 566135 - Windows theme code calls show window on SW_SHOWMINIMIZED
|
|
|
|
// windows when fullscreen games disable desktop composition. If we're
|
|
|
|
// minimized and not being activated, ignore the event and let windows
|
|
|
|
// handle it.
|
|
|
|
if (mSizeMode == nsSizeMode_Minimized && (wp->flags & SWP_NOACTIVATE))
|
|
|
|
return;
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsSizeModeEvent event(true, NS_SIZEMODE, this);
|
2009-11-10 16:24:10 +00:00
|
|
|
|
|
|
|
WINDOWPLACEMENT pl;
|
|
|
|
pl.length = sizeof(pl);
|
|
|
|
::GetWindowPlacement(mWnd, &pl);
|
|
|
|
|
|
|
|
if (pl.showCmd == SW_SHOWMAXIMIZED)
|
2011-02-08 01:52:08 +00:00
|
|
|
event.mSizeMode = (mFullscreenMode ? nsSizeMode_Fullscreen : nsSizeMode_Maximized);
|
2009-11-10 16:24:10 +00:00
|
|
|
else if (pl.showCmd == SW_SHOWMINIMIZED)
|
|
|
|
event.mSizeMode = nsSizeMode_Minimized;
|
2011-02-25 21:29:41 +00:00
|
|
|
else if (mFullscreenMode)
|
|
|
|
event.mSizeMode = nsSizeMode_Fullscreen;
|
2009-11-10 16:24:10 +00:00
|
|
|
else
|
|
|
|
event.mSizeMode = nsSizeMode_Normal;
|
|
|
|
|
|
|
|
// Windows has just changed the size mode of this window. The following
|
|
|
|
// NS_SIZEMODE event will trigger a call into SetSizeMode where we will
|
|
|
|
// set the min/max window state again or for nsSizeMode_Normal, call
|
|
|
|
// SetWindow with a parameter of SW_RESTORE. There's no need however as
|
|
|
|
// this window's mode has already changed. Updating mSizeMode here
|
|
|
|
// insures the SetSizeMode call is a no-op. Addresses a bug on Win7 related
|
|
|
|
// to window docking. (bug 489258)
|
|
|
|
mSizeMode = event.mSizeMode;
|
|
|
|
|
2009-11-12 01:11:57 +00:00
|
|
|
// If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
|
|
|
|
// SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
|
|
|
|
// prevents the working set from being trimmed but keeps the window active.
|
|
|
|
// After the window is minimized, we need to do some touch up work on the
|
|
|
|
// active window. (bugs 76831 & 499816)
|
|
|
|
if (!sTrimOnMinimize && nsSizeMode_Minimized == event.mSizeMode)
|
|
|
|
ActivateOtherWindowHelper(mWnd);
|
|
|
|
|
2009-11-10 16:24:10 +00:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
|
|
|
switch (mSizeMode) {
|
|
|
|
case nsSizeMode_Normal:
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("*** mSizeMode: nsSizeMode_Normal\n"));
|
2009-11-10 16:24:10 +00:00
|
|
|
break;
|
|
|
|
case nsSizeMode_Minimized:
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("*** mSizeMode: nsSizeMode_Minimized\n"));
|
2009-11-10 16:24:10 +00:00
|
|
|
break;
|
|
|
|
case nsSizeMode_Maximized:
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("*** mSizeMode: nsSizeMode_Maximized\n");
|
2009-11-10 16:24:10 +00:00
|
|
|
break;
|
|
|
|
default:
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("*** mSizeMode: ??????\n");
|
2009-11-10 16:24:10 +00:00
|
|
|
break;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
InitEvent(event);
|
|
|
|
|
|
|
|
result = DispatchWindowEvent(&event);
|
|
|
|
|
|
|
|
// Skip window size change events below on minimization.
|
|
|
|
if (mSizeMode == nsSizeMode_Minimized)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle window size changes
|
2010-11-05 15:19:05 +00:00
|
|
|
if (!(wp->flags & SWP_NOSIZE)) {
|
2009-08-11 17:29:53 +00:00
|
|
|
RECT r;
|
|
|
|
PRInt32 newWidth, newHeight;
|
2009-11-10 16:24:10 +00:00
|
|
|
|
|
|
|
::GetWindowRect(mWnd, &r);
|
|
|
|
|
|
|
|
newWidth = r.right - r.left;
|
|
|
|
newHeight = r.bottom - r.top;
|
2009-08-11 17:29:53 +00:00
|
|
|
nsIntRect rect(wp->x, wp->y, newWidth, newHeight);
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
ResizeTranslucentWindow(newWidth, newHeight);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (newWidth > mLastSize.width)
|
|
|
|
{
|
|
|
|
RECT drect;
|
|
|
|
|
2009-11-10 16:24:10 +00:00
|
|
|
// getting wider
|
|
|
|
drect.left = wp->x + mLastSize.width;
|
|
|
|
drect.top = wp->y;
|
|
|
|
drect.right = drect.left + (newWidth - mLastSize.width);
|
2009-08-11 17:29:53 +00:00
|
|
|
drect.bottom = drect.top + newHeight;
|
|
|
|
|
|
|
|
::RedrawWindow(mWnd, &drect, NULL,
|
2009-11-10 16:24:10 +00:00
|
|
|
RDW_INVALIDATE |
|
|
|
|
RDW_NOERASE |
|
|
|
|
RDW_NOINTERNALPAINT |
|
|
|
|
RDW_ERASENOW |
|
|
|
|
RDW_ALLCHILDREN);
|
2009-08-11 17:29:53 +00:00
|
|
|
}
|
|
|
|
if (newHeight > mLastSize.height)
|
|
|
|
{
|
|
|
|
RECT drect;
|
|
|
|
|
2009-11-10 16:24:10 +00:00
|
|
|
// getting taller
|
|
|
|
drect.left = wp->x;
|
|
|
|
drect.top = wp->y + mLastSize.height;
|
|
|
|
drect.right = drect.left + newWidth;
|
2009-08-11 17:29:53 +00:00
|
|
|
drect.bottom = drect.top + (newHeight - mLastSize.height);
|
|
|
|
|
|
|
|
::RedrawWindow(mWnd, &drect, NULL,
|
2009-11-10 16:24:10 +00:00
|
|
|
RDW_INVALIDATE |
|
|
|
|
RDW_NOERASE |
|
|
|
|
RDW_NOINTERNALPAINT |
|
|
|
|
RDW_ERASENOW |
|
|
|
|
RDW_ALLCHILDREN);
|
2009-08-11 17:29:53 +00:00
|
|
|
}
|
|
|
|
|
2009-11-10 16:24:10 +00:00
|
|
|
mBounds.width = newWidth;
|
|
|
|
mBounds.height = newHeight;
|
|
|
|
mLastSize.width = newWidth;
|
2009-08-11 17:29:53 +00:00
|
|
|
mLastSize.height = newHeight;
|
|
|
|
|
2009-11-10 16:24:10 +00:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("*** Resize window: %d x %d x %d x %d\n", wp->x, wp->y,
|
|
|
|
newWidth, newHeight));
|
2009-11-10 16:24:10 +00:00
|
|
|
#endif
|
2010-07-30 19:24:36 +00:00
|
|
|
|
|
|
|
// If a maximized window is resized, recalculate the non-client margins and
|
|
|
|
// ensure a 1 pixel margin at screen bottom to allow taskbar unhiding to
|
|
|
|
// work properly.
|
|
|
|
if (mSizeMode == nsSizeMode_Maximized) {
|
2011-10-02 02:16:19 +00:00
|
|
|
if (UpdateNonClientMargins(nsSizeMode_Maximized, true)) {
|
2010-07-30 19:24:36 +00:00
|
|
|
// gecko resize event already sent by UpdateNonClientMargins.
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2010-07-30 19:24:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-08-11 17:29:53 +00:00
|
|
|
|
2009-11-10 16:24:10 +00:00
|
|
|
// Recalculate the width and height based on the client area for gecko events.
|
2009-08-11 17:29:53 +00:00
|
|
|
if (::GetClientRect(mWnd, &r)) {
|
2009-11-10 16:24:10 +00:00
|
|
|
rect.width = r.right - r.left;
|
|
|
|
rect.height = r.bottom - r.top;
|
2009-08-11 17:29:53 +00:00
|
|
|
}
|
2009-11-10 16:24:10 +00:00
|
|
|
|
|
|
|
// Send a gecko resize event
|
2009-08-11 17:29:53 +00:00
|
|
|
result = OnResize(rect);
|
|
|
|
}
|
|
|
|
}
|
2009-11-12 01:11:57 +00:00
|
|
|
|
|
|
|
// static
|
|
|
|
void nsWindow::ActivateOtherWindowHelper(HWND aWnd)
|
|
|
|
{
|
|
|
|
// Find the next window that is enabled, visible, and not minimized.
|
|
|
|
HWND hwndBelow = ::GetNextWindow(aWnd, GW_HWNDNEXT);
|
|
|
|
while (hwndBelow && (!::IsWindowEnabled(hwndBelow) || !::IsWindowVisible(hwndBelow) ||
|
|
|
|
::IsIconic(hwndBelow))) {
|
|
|
|
hwndBelow = ::GetNextWindow(hwndBelow, GW_HWNDNEXT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Push ourselves to the bottom of the stack, then activate the
|
|
|
|
// next window.
|
|
|
|
::SetWindowPos(aWnd, HWND_BOTTOM, 0, 0, 0, 0,
|
|
|
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
|
|
if (hwndBelow)
|
|
|
|
::SetForegroundWindow(hwndBelow);
|
|
|
|
|
|
|
|
// Play the minimize sound while we're here, since that is also
|
|
|
|
// forgotten when we use SW_SHOWMINIMIZED.
|
2011-09-08 15:24:43 +00:00
|
|
|
nsCOMPtr<nsISound> sound(do_CreateInstance("@mozilla.org/sound;1"));
|
|
|
|
if (sound) {
|
|
|
|
sound->PlaySystemSound(NS_LITERAL_STRING("Minimize"));
|
|
|
|
}
|
2009-11-12 01:11:57 +00:00
|
|
|
}
|
2009-08-11 17:29:53 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::OnWindowPosChanging(LPWINDOWPOS& info)
|
|
|
|
{
|
2010-06-28 05:57:07 +00:00
|
|
|
// Update non-client margins if the frame size is changing, and let the
|
|
|
|
// browser know we are changing size modes, so alternative css can kick in.
|
2010-06-28 06:04:20 +00:00
|
|
|
// If we're going into fullscreen mode, ignore this, since it'll reset
|
|
|
|
// margins to normal mode.
|
2010-10-22 18:43:40 +00:00
|
|
|
if ((info->flags & SWP_FRAMECHANGED && !(info->flags & SWP_NOSIZE)) &&
|
|
|
|
mSizeMode != nsSizeMode_Fullscreen) {
|
2010-06-28 05:57:07 +00:00
|
|
|
WINDOWPLACEMENT pl;
|
|
|
|
pl.length = sizeof(pl);
|
|
|
|
::GetWindowPlacement(mWnd, &pl);
|
|
|
|
PRInt32 sizeMode;
|
|
|
|
if (pl.showCmd == SW_SHOWMAXIMIZED)
|
2011-02-08 01:52:08 +00:00
|
|
|
sizeMode = (mFullscreenMode ? nsSizeMode_Fullscreen : nsSizeMode_Maximized);
|
2010-06-28 05:57:07 +00:00
|
|
|
else if (pl.showCmd == SW_SHOWMINIMIZED)
|
|
|
|
sizeMode = nsSizeMode_Minimized;
|
2011-02-25 21:29:41 +00:00
|
|
|
else if (mFullscreenMode)
|
|
|
|
sizeMode = nsSizeMode_Fullscreen;
|
2010-06-28 05:57:07 +00:00
|
|
|
else
|
|
|
|
sizeMode = nsSizeMode_Normal;
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsSizeModeEvent event(true, NS_SIZEMODE, this);
|
2010-06-28 05:57:07 +00:00
|
|
|
|
|
|
|
InitEvent(event);
|
|
|
|
event.mSizeMode = static_cast<nsSizeMode>(sizeMode);
|
|
|
|
DispatchWindowEvent(&event);
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
UpdateNonClientMargins(sizeMode, false);
|
2010-06-28 05:57:07 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// enforce local z-order rules
|
|
|
|
if (!(info->flags & SWP_NOZORDER)) {
|
|
|
|
HWND hwndAfter = info->hwndInsertAfter;
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsZLevelEvent event(true, NS_SETZLEVEL, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
nsWindow *aboveWindow = 0;
|
2009-04-14 22:12:38 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
InitEvent(event);
|
2009-04-23 00:48:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (hwndAfter == HWND_BOTTOM)
|
|
|
|
event.mPlacement = nsWindowZBottom;
|
|
|
|
else if (hwndAfter == HWND_TOP || hwndAfter == HWND_TOPMOST || hwndAfter == HWND_NOTOPMOST)
|
|
|
|
event.mPlacement = nsWindowZTop;
|
|
|
|
else {
|
|
|
|
event.mPlacement = nsWindowZRelative;
|
2012-01-04 10:21:44 +00:00
|
|
|
aboveWindow = WinUtils::GetNSWindowPtr(hwndAfter);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
event.mReqBelow = aboveWindow;
|
|
|
|
event.mActualBelow = nsnull;
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
event.mImmediate = false;
|
|
|
|
event.mAdjusted = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchWindowEvent(&event);
|
|
|
|
|
|
|
|
if (event.mAdjusted) {
|
|
|
|
if (event.mPlacement == nsWindowZBottom)
|
|
|
|
info->hwndInsertAfter = HWND_BOTTOM;
|
|
|
|
else if (event.mPlacement == nsWindowZTop)
|
|
|
|
info->hwndInsertAfter = HWND_TOP;
|
|
|
|
else {
|
|
|
|
info->hwndInsertAfter = (HWND)event.mActualBelow->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
}
|
1999-09-09 03:47:26 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_IF_RELEASE(event.mActualBelow);
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
// prevent rude external programs from making hidden window visible
|
|
|
|
if (mWindowType == eWindowType_invisible)
|
|
|
|
info->flags &= ~SWP_SHOWWINDOW;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2010-04-16 17:37:16 +00:00
|
|
|
void nsWindow::UserActivity()
|
|
|
|
{
|
|
|
|
// Check if we have the idle service, if not we try to get it.
|
|
|
|
if (!mIdleService) {
|
|
|
|
mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that we now have the idle service.
|
|
|
|
if (mIdleService) {
|
|
|
|
mIdleService->ResetIdleTimeOut();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-02 13:34:54 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::OnTouch(WPARAM wParam, LPARAM lParam)
|
2010-08-02 13:34:54 +00:00
|
|
|
{
|
|
|
|
PRUint32 cInputs = LOWORD(wParam);
|
|
|
|
PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs];
|
|
|
|
|
|
|
|
if (mGesture.GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs)) {
|
|
|
|
for (PRUint32 i = 0; i < cInputs; i++) {
|
|
|
|
PRUint32 msg;
|
|
|
|
if (pInputs[i].dwFlags & TOUCHEVENTF_MOVE) {
|
|
|
|
msg = NS_MOZTOUCH_MOVE;
|
|
|
|
} else if (pInputs[i].dwFlags & TOUCHEVENTF_DOWN) {
|
|
|
|
msg = NS_MOZTOUCH_DOWN;
|
|
|
|
} else if (pInputs[i].dwFlags & TOUCHEVENTF_UP) {
|
|
|
|
msg = NS_MOZTOUCH_UP;
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPointWin touchPoint;
|
|
|
|
touchPoint.x = TOUCH_COORD_TO_PIXEL(pInputs[i].x);
|
|
|
|
touchPoint.y = TOUCH_COORD_TO_PIXEL(pInputs[i].y);
|
|
|
|
touchPoint.ScreenToClient(mWnd);
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsMozTouchEvent touchEvent(true, msg, this, pInputs[i].dwID);
|
2011-08-26 07:43:56 +00:00
|
|
|
touchEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
2010-08-02 13:34:54 +00:00
|
|
|
touchEvent.refPoint = touchPoint;
|
|
|
|
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(&touchEvent, status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete [] pInputs;
|
|
|
|
mGesture.CloseTouchInputHandle((HTOUCHINPUT)lParam);
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-08-02 13:34:54 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Gesture event processing. Handles WM_GESTURE events.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::OnGesture(WPARAM wParam, LPARAM lParam)
|
2009-06-23 20:57:45 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
// Treatment for pan events which translate into scroll events:
|
|
|
|
if (mGesture.IsPanEvent(lParam)) {
|
2011-10-02 02:16:19 +00:00
|
|
|
nsMouseScrollEvent event(true, NS_MOUSE_PIXEL_SCROLL, this);
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if ( !mGesture.ProcessPanMessage(mWnd, wParam, lParam) )
|
2011-10-02 02:16:19 +00:00
|
|
|
return false; // ignore
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsEventStatus status;
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
2011-10-02 02:16:19 +00:00
|
|
|
event.isMeta = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
event.button = 0;
|
|
|
|
event.time = ::GetMessageTime();
|
2011-08-26 07:43:56 +00:00
|
|
|
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool endFeedback = true;
|
2009-07-30 06:01:27 +00:00
|
|
|
|
|
|
|
PRInt32 scrollOverflowX = 0;
|
|
|
|
PRInt32 scrollOverflowY = 0;
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mGesture.PanDeltaToPixelScrollX(event)) {
|
|
|
|
DispatchEvent(&event, status);
|
2009-07-30 06:01:27 +00:00
|
|
|
scrollOverflowX = event.scrollOverflow;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-07-30 06:01:27 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (mGesture.PanDeltaToPixelScrollY(event)) {
|
|
|
|
DispatchEvent(&event, status);
|
2009-07-30 06:01:27 +00:00
|
|
|
scrollOverflowY = event.scrollOverflow;
|
|
|
|
}
|
|
|
|
|
2009-08-13 20:54:09 +00:00
|
|
|
if (mDisplayPanFeedback) {
|
2009-07-30 06:01:27 +00:00
|
|
|
mGesture.UpdatePanFeedbackX(mWnd, scrollOverflowX, endFeedback);
|
|
|
|
mGesture.UpdatePanFeedbackY(mWnd, scrollOverflowY, endFeedback);
|
|
|
|
mGesture.PanFeedbackFinalize(mWnd, endFeedback);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-07-30 06:01:27 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
mGesture.CloseGestureInfoHandle((HGESTUREINFO)lParam);
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-06-23 20:57:45 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Other gestures translate into simple gesture events:
|
2011-10-02 02:16:19 +00:00
|
|
|
nsSimpleGestureEvent event(true, 0, this, 0, 0.0);
|
2009-06-29 19:36:16 +00:00
|
|
|
if ( !mGesture.ProcessGestureMessage(mWnd, wParam, lParam, event) ) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return false; // fall through to DefWndProc
|
2009-06-23 20:57:45 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Polish up and send off the new event
|
|
|
|
event.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
2011-10-02 02:16:19 +00:00
|
|
|
event.isMeta = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
event.button = 0;
|
|
|
|
event.time = ::GetMessageTime();
|
2011-08-26 07:43:56 +00:00
|
|
|
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
if (status == nsEventStatus_eIgnore) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return false; // Ignored, fall through
|
2009-06-23 20:57:45 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Only close this if we process and return true.
|
|
|
|
mGesture.CloseGestureInfoHandle((HGESTUREINFO)lParam);
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
return true; // Handled
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
|
2011-05-17 00:23:23 +00:00
|
|
|
/* static */ void
|
|
|
|
nsWindow::InitMouseWheelScrollData()
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
2011-05-17 00:23:23 +00:00
|
|
|
if (!sNeedsToInitMouseWheelSettings) {
|
|
|
|
return;
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
sNeedsToInitMouseWheelSettings = false;
|
2011-05-17 00:23:23 +00:00
|
|
|
ResetRemainingWheelDelta();
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2011-05-17 00:23:23 +00:00
|
|
|
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
|
|
|
|
&sMouseWheelScrollLines, 0)) {
|
|
|
|
NS_WARNING("Failed to get SPI_GETWHEELSCROLLLINES");
|
|
|
|
sMouseWheelScrollLines = 3;
|
|
|
|
} else if (sMouseWheelScrollLines > WHEEL_DELTA) {
|
|
|
|
// sMouseWheelScrollLines usually equals 3 or 0 (for no scrolling)
|
|
|
|
// However, if sMouseWheelScrollLines > WHEEL_DELTA, we assume that
|
2009-06-29 19:36:16 +00:00
|
|
|
// the mouse driver wants a page scroll. The docs state that
|
2011-05-17 00:23:23 +00:00
|
|
|
// sMouseWheelScrollLines should explicitly equal WHEEL_PAGESCROLL, but
|
2009-06-29 19:36:16 +00:00
|
|
|
// since some mouse drivers use an arbitrary large number instead,
|
|
|
|
// we have to handle that as well.
|
2011-05-17 00:23:23 +00:00
|
|
|
sMouseWheelScrollLines = WHEEL_PAGESCROLL;
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
|
2011-05-17 00:23:23 +00:00
|
|
|
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
|
|
|
|
&sMouseWheelScrollChars, 0)) {
|
2012-02-08 21:04:21 +00:00
|
|
|
NS_ASSERTION(!nsUXThemeData::sIsVistaOrLater,
|
2011-05-17 00:23:23 +00:00
|
|
|
"Failed to get SPI_GETWHEELSCROLLCHARS");
|
|
|
|
sMouseWheelScrollChars = 1;
|
|
|
|
} else if (sMouseWheelScrollChars > WHEEL_DELTA) {
|
|
|
|
// See the comments for the case sMouseWheelScrollLines > WHEEL_DELTA.
|
|
|
|
sMouseWheelScrollChars = WHEEL_PAGESCROLL;
|
|
|
|
}
|
2011-05-28 07:03:00 +00:00
|
|
|
|
|
|
|
sEnablePixelScrolling =
|
2011-09-29 06:19:26 +00:00
|
|
|
Preferences::GetBool("mousewheel.enable_pixel_scrolling", true);
|
2011-05-17 00:23:23 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
|
2011-05-17 00:23:23 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsWindow::ResetRemainingWheelDelta()
|
|
|
|
{
|
|
|
|
sRemainingDeltaForPixel = 0;
|
|
|
|
sRemainingDeltaForScroll = 0;
|
|
|
|
sLastMouseWheelWnd = NULL;
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
|
2011-05-17 00:23:23 +00:00
|
|
|
static PRInt32 RoundDelta(double aDelta)
|
|
|
|
{
|
2011-05-30 19:08:55 +00:00
|
|
|
return aDelta >= 0 ? (PRInt32)floor(aDelta) : (PRInt32)ceil(aDelta);
|
2011-05-17 00:23:23 +00:00
|
|
|
}
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
/**
|
|
|
|
* OnMouseWheelInternal - mouse wheel event processing.
|
|
|
|
* aMessage may be WM_MOUSEWHEEL or WM_MOUSEHWHEEL but this is called when
|
|
|
|
* ProcessMessage() handles MOZ_WM_MOUSEVWHEEL or MOZ_WM_MOUSEHWHEEL.
|
2011-05-17 00:23:23 +00:00
|
|
|
*/
|
2011-08-02 03:03:15 +00:00
|
|
|
void
|
|
|
|
nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
|
|
|
|
LRESULT *aRetValue)
|
2011-05-17 00:23:23 +00:00
|
|
|
{
|
|
|
|
InitMouseWheelScrollData();
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool isVertical = (aMessage == WM_MOUSEWHEEL);
|
2011-05-17 00:23:23 +00:00
|
|
|
if ((isVertical && sMouseWheelScrollLines == 0) ||
|
|
|
|
(!isVertical && sMouseWheelScrollChars == 0)) {
|
|
|
|
// XXX I think that we should dispatch mouse wheel events even if the
|
|
|
|
// operation will not scroll because the wheel operation really happened
|
|
|
|
// and web application may want to handle the event for non-scroll action.
|
|
|
|
ResetRemainingWheelDelta();
|
|
|
|
*aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
|
2011-08-02 03:03:15 +00:00
|
|
|
return;
|
2011-05-17 00:23:23 +00:00
|
|
|
}
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2011-05-17 00:23:23 +00:00
|
|
|
PRInt32 nativeDelta = (short)HIWORD(aWParam);
|
|
|
|
if (!nativeDelta) {
|
|
|
|
*aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
|
|
|
|
ResetRemainingWheelDelta();
|
2011-08-02 03:03:15 +00:00
|
|
|
return; // We cannot process this message
|
2009-06-23 20:57:45 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool isPageScroll =
|
2011-05-17 00:23:23 +00:00
|
|
|
((isVertical && sMouseWheelScrollLines == WHEEL_PAGESCROLL) ||
|
|
|
|
(!isVertical && sMouseWheelScrollChars == WHEEL_PAGESCROLL));
|
|
|
|
|
|
|
|
// Discard the remaining delta if current wheel message and last one are
|
|
|
|
// received by different window or to scroll different direction or
|
|
|
|
// different unit scroll. Furthermore, if the last event was too old.
|
|
|
|
PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
|
|
|
|
if (sLastMouseWheelWnd &&
|
|
|
|
(sLastMouseWheelWnd != mWnd ||
|
|
|
|
sLastMouseWheelDeltaIsPositive != (nativeDelta > 0) ||
|
|
|
|
sLastMouseWheelOrientationIsVertical != isVertical ||
|
|
|
|
sLastMouseWheelUnitIsPage != isPageScroll ||
|
|
|
|
now - sLastMouseWheelTime > 1500)) {
|
|
|
|
ResetRemainingWheelDelta();
|
|
|
|
}
|
|
|
|
sLastMouseWheelWnd = mWnd;
|
|
|
|
sLastMouseWheelDeltaIsPositive = (nativeDelta > 0);
|
|
|
|
sLastMouseWheelOrientationIsVertical = isVertical;
|
|
|
|
sLastMouseWheelUnitIsPage = isPageScroll;
|
|
|
|
sLastMouseWheelTime = now;
|
|
|
|
|
2011-05-22 05:39:16 +00:00
|
|
|
*aRetValue = isVertical ? FALSE : TRUE; // means we process this message
|
|
|
|
nsModifierKeyState modKeyState;
|
|
|
|
|
|
|
|
// Our positive delta value means to bottom or right.
|
|
|
|
// But positive nativeDelta value means to top or right.
|
2011-05-23 14:56:59 +00:00
|
|
|
// Use orienter for computing our delta value with native delta value.
|
2011-05-22 05:39:16 +00:00
|
|
|
PRInt32 orienter = isVertical ? -1 : 1;
|
|
|
|
|
|
|
|
// Assume the Control key is down if the Elantech touchpad has sent the
|
|
|
|
// mis-ordered WM_KEYDOWN/WM_MOUSEWHEEL messages. (See the comment in
|
|
|
|
// OnKeyUp.)
|
2011-09-29 06:19:26 +00:00
|
|
|
bool isControl;
|
2011-05-22 05:39:16 +00:00
|
|
|
if (mAssumeWheelIsZoomUntil &&
|
|
|
|
static_cast<DWORD>(::GetMessageTime()) < mAssumeWheelIsZoomUntil) {
|
2011-10-02 02:16:19 +00:00
|
|
|
isControl = true;
|
2011-05-22 05:39:16 +00:00
|
|
|
} else {
|
|
|
|
isControl = modKeyState.mIsControlDown;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create line (or page) scroll event.
|
2011-10-02 02:16:19 +00:00
|
|
|
nsMouseScrollEvent scrollEvent(true, NS_MOUSE_SCROLL, this);
|
2011-05-22 05:39:16 +00:00
|
|
|
|
|
|
|
// Initialize common members on line scroll event, pixel scroll event and
|
|
|
|
// test event.
|
|
|
|
InitEvent(scrollEvent);
|
|
|
|
scrollEvent.isShift = modKeyState.mIsShiftDown;
|
|
|
|
scrollEvent.isControl = isControl;
|
2011-10-02 02:16:19 +00:00
|
|
|
scrollEvent.isMeta = false;
|
2011-05-22 05:39:16 +00:00
|
|
|
scrollEvent.isAlt = modKeyState.mIsAltDown;
|
|
|
|
|
|
|
|
// Before dispatching line scroll event, we should get the current scroll
|
|
|
|
// event target information for pixel scroll.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool dispatchPixelScrollEvent = false;
|
|
|
|
bool reversePixelScrollDirection = false;
|
2011-07-14 22:12:20 +00:00
|
|
|
PRInt32 actualScrollAction = nsQueryContentEvent::SCROLL_ACTION_NONE;
|
2011-05-18 23:12:16 +00:00
|
|
|
PRInt32 pixelsPerUnit = 0;
|
2011-05-23 14:56:59 +00:00
|
|
|
// the amount is the number of lines (or pages) per WHEEL_DELTA
|
|
|
|
PRInt32 computedScrollAmount = isPageScroll ? 1 :
|
|
|
|
(isVertical ? sMouseWheelScrollLines : sMouseWheelScrollChars);
|
2011-05-18 23:12:16 +00:00
|
|
|
|
|
|
|
if (sEnablePixelScrolling) {
|
2011-10-02 02:16:19 +00:00
|
|
|
nsMouseScrollEvent testEvent(true, NS_MOUSE_SCROLL, this);
|
2011-05-18 23:12:16 +00:00
|
|
|
InitEvent(testEvent);
|
|
|
|
testEvent.scrollFlags = isPageScroll ? nsMouseScrollEvent::kIsFullPage : 0;
|
|
|
|
testEvent.scrollFlags |= isVertical ? nsMouseScrollEvent::kIsVertical :
|
|
|
|
nsMouseScrollEvent::kIsHorizontal;
|
2011-05-22 05:39:16 +00:00
|
|
|
testEvent.isShift = scrollEvent.isShift;
|
|
|
|
testEvent.isControl = scrollEvent.isControl;
|
|
|
|
testEvent.isMeta = scrollEvent.isMeta;
|
|
|
|
testEvent.isAlt = scrollEvent.isAlt;
|
2011-05-23 14:56:59 +00:00
|
|
|
|
|
|
|
testEvent.delta = computedScrollAmount;
|
|
|
|
if ((isVertical && sLastMouseWheelDeltaIsPositive) ||
|
|
|
|
(!isVertical && !sLastMouseWheelDeltaIsPositive)) {
|
|
|
|
testEvent.delta *= -1;
|
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
nsQueryContentEvent queryEvent(true, NS_QUERY_SCROLL_TARGET_INFO, this);
|
2011-05-18 23:12:16 +00:00
|
|
|
InitEvent(queryEvent);
|
|
|
|
queryEvent.InitForQueryScrollTargetInfo(&testEvent);
|
|
|
|
DispatchWindowEvent(&queryEvent);
|
|
|
|
// If the necessary interger isn't larger than 0, we should assume that
|
|
|
|
// the event failed for us.
|
|
|
|
if (queryEvent.mSucceeded) {
|
2011-07-14 22:12:20 +00:00
|
|
|
actualScrollAction = queryEvent.mReply.mComputedScrollAction;
|
|
|
|
if (actualScrollAction == nsQueryContentEvent::SCROLL_ACTION_PAGE) {
|
2011-05-18 23:12:16 +00:00
|
|
|
if (isVertical) {
|
|
|
|
pixelsPerUnit = queryEvent.mReply.mPageHeight;
|
|
|
|
} else {
|
|
|
|
pixelsPerUnit = queryEvent.mReply.mPageWidth;
|
|
|
|
}
|
2011-05-17 00:23:23 +00:00
|
|
|
} else {
|
2011-05-18 23:12:16 +00:00
|
|
|
pixelsPerUnit = queryEvent.mReply.mLineHeight;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2011-05-23 14:56:59 +00:00
|
|
|
computedScrollAmount = queryEvent.mReply.mComputedScrollAmount;
|
2011-07-14 22:12:20 +00:00
|
|
|
if (pixelsPerUnit > 0 && computedScrollAmount != 0 &&
|
|
|
|
actualScrollAction != nsQueryContentEvent::SCROLL_ACTION_NONE) {
|
2011-10-02 02:16:19 +00:00
|
|
|
dispatchPixelScrollEvent = true;
|
2011-07-14 22:12:20 +00:00
|
|
|
// If original delta's sign and computed delta's one are different,
|
|
|
|
// we need to reverse the pixel scroll direction at dispatching it.
|
|
|
|
reversePixelScrollDirection =
|
|
|
|
(testEvent.delta > 0 && computedScrollAmount < 0) ||
|
|
|
|
(testEvent.delta < 0 && computedScrollAmount > 0);
|
|
|
|
// scroll amount must be positive.
|
|
|
|
computedScrollAmount = NS_ABS(computedScrollAmount);
|
2011-05-23 14:56:59 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-06-23 20:57:45 +00:00
|
|
|
}
|
|
|
|
|
2011-05-22 05:39:16 +00:00
|
|
|
// If we dispatch pixel scroll event after the line scroll event,
|
|
|
|
// we should set kHasPixels flag to the line scroll event.
|
2011-05-17 00:23:23 +00:00
|
|
|
scrollEvent.scrollFlags =
|
2011-05-18 23:12:16 +00:00
|
|
|
dispatchPixelScrollEvent ? nsMouseScrollEvent::kHasPixels : 0;
|
2011-05-17 00:23:23 +00:00
|
|
|
|
|
|
|
PRInt32 nativeDeltaForScroll = nativeDelta + sRemainingDeltaForScroll;
|
|
|
|
|
2011-05-23 14:56:59 +00:00
|
|
|
// NOTE: Don't use computedScrollAmount for computing the delta value of
|
|
|
|
// line/page scroll event. The value will be recomputed in ESM.
|
2011-05-17 00:23:23 +00:00
|
|
|
if (isPageScroll) {
|
|
|
|
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
if (isVertical) {
|
|
|
|
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
|
|
|
|
} else {
|
|
|
|
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
|
|
|
|
}
|
|
|
|
scrollEvent.delta = nativeDeltaForScroll * orienter / WHEEL_DELTA;
|
|
|
|
PRInt32 recomputedNativeDelta = scrollEvent.delta * orienter / WHEEL_DELTA;
|
|
|
|
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
|
|
|
|
} else {
|
|
|
|
double deltaPerUnit;
|
|
|
|
if (isVertical) {
|
|
|
|
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
|
|
|
|
deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollLines;
|
|
|
|
} else {
|
|
|
|
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
|
|
|
|
deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollChars;
|
|
|
|
}
|
|
|
|
scrollEvent.delta =
|
|
|
|
RoundDelta((double)nativeDeltaForScroll * orienter / deltaPerUnit);
|
|
|
|
PRInt32 recomputedNativeDelta =
|
|
|
|
(PRInt32)(scrollEvent.delta * orienter * deltaPerUnit);
|
|
|
|
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-06-23 20:57:45 +00:00
|
|
|
|
2011-05-17 00:23:23 +00:00
|
|
|
if (scrollEvent.delta) {
|
2011-08-02 03:03:15 +00:00
|
|
|
DispatchWindowEvent(&scrollEvent);
|
2011-05-17 00:23:23 +00:00
|
|
|
if (mOnDestroyCalled) {
|
|
|
|
ResetRemainingWheelDelta();
|
2011-08-02 03:03:15 +00:00
|
|
|
return;
|
2011-05-17 00:23:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the query event failed, we cannot send pixel events.
|
2011-05-18 23:12:16 +00:00
|
|
|
if (!dispatchPixelScrollEvent) {
|
2011-05-17 00:23:23 +00:00
|
|
|
sRemainingDeltaForPixel = 0;
|
2011-08-02 03:03:15 +00:00
|
|
|
return;
|
2011-05-17 00:23:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsMouseScrollEvent pixelEvent(true, NS_MOUSE_PIXEL_SCROLL, this);
|
2011-05-17 00:23:23 +00:00
|
|
|
InitEvent(pixelEvent);
|
2011-07-14 22:12:20 +00:00
|
|
|
pixelEvent.scrollFlags = nsMouseScrollEvent::kAllowSmoothScroll;
|
|
|
|
pixelEvent.scrollFlags |= isVertical ?
|
|
|
|
nsMouseScrollEvent::kIsVertical : nsMouseScrollEvent::kIsHorizontal;
|
|
|
|
if (actualScrollAction == nsQueryContentEvent::SCROLL_ACTION_PAGE) {
|
|
|
|
pixelEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
}
|
2011-05-22 05:39:16 +00:00
|
|
|
// Use same modifier state for pixel scroll event.
|
|
|
|
pixelEvent.isShift = scrollEvent.isShift;
|
|
|
|
pixelEvent.isControl = scrollEvent.isControl;
|
|
|
|
pixelEvent.isMeta = scrollEvent.isMeta;
|
|
|
|
pixelEvent.isAlt = scrollEvent.isAlt;
|
2011-05-17 00:23:23 +00:00
|
|
|
|
|
|
|
PRInt32 nativeDeltaForPixel = nativeDelta + sRemainingDeltaForPixel;
|
2011-07-14 22:12:20 +00:00
|
|
|
// Pixel scroll event won't be recomputed the scroll amout and direction by
|
|
|
|
// ESM. Therefore, we need to set the computed amout and direction here.
|
|
|
|
PRInt32 orienterForPixel = reversePixelScrollDirection ? -orienter : orienter;
|
2011-05-17 00:23:23 +00:00
|
|
|
|
2011-05-23 14:56:59 +00:00
|
|
|
double deltaPerPixel =
|
|
|
|
(double)WHEEL_DELTA / computedScrollAmount / pixelsPerUnit;
|
2011-05-17 00:23:23 +00:00
|
|
|
pixelEvent.delta =
|
2011-07-14 22:12:20 +00:00
|
|
|
RoundDelta((double)nativeDeltaForPixel * orienterForPixel / deltaPerPixel);
|
2011-05-17 00:23:23 +00:00
|
|
|
PRInt32 recomputedNativeDelta =
|
2011-07-14 22:12:20 +00:00
|
|
|
(PRInt32)(pixelEvent.delta * orienterForPixel * deltaPerPixel);
|
2011-05-17 00:23:23 +00:00
|
|
|
sRemainingDeltaForPixel = nativeDeltaForPixel - recomputedNativeDelta;
|
|
|
|
if (pixelEvent.delta != 0) {
|
2011-08-02 03:03:15 +00:00
|
|
|
DispatchWindowEvent(&pixelEvent);
|
2011-05-17 00:23:23 +00:00
|
|
|
}
|
2011-08-02 03:03:15 +00:00
|
|
|
return;
|
2011-05-17 00:23:23 +00:00
|
|
|
}
|
2009-08-04 21:28:17 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool
|
2009-06-29 19:36:16 +00:00
|
|
|
StringCaseInsensitiveEquals(const PRUnichar* aChars1, const PRUint32 aNumChars1,
|
|
|
|
const PRUnichar* aChars2, const PRUint32 aNumChars2)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aNumChars1 != aNumChars2)
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsCaseInsensitiveStringComparator comp;
|
2010-09-01 01:03:40 +00:00
|
|
|
return comp(aChars1, aChars2, aNumChars1, aNumChars2) == 0;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
UINT nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode)
|
2008-03-12 22:44:45 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (aNativeKeyCode) {
|
|
|
|
case VK_OEM_1: return NS_VK_SEMICOLON; // 0xBA, For the US standard keyboard, the ';:' key
|
|
|
|
case VK_OEM_PLUS: return NS_VK_ADD; // 0xBB, For any country/region, the '+' key
|
|
|
|
case VK_OEM_MINUS: return NS_VK_SUBTRACT; // 0xBD, For any country/region, the '-' key
|
|
|
|
}
|
|
|
|
return aNativeKeyCode;
|
2008-03-12 22:44:45 +00:00
|
|
|
}
|
|
|
|
|
2011-01-14 13:38:57 +00:00
|
|
|
/* static */
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::IsRedirectedKeyDownMessage(const MSG &aMsg)
|
2011-01-14 13:38:57 +00:00
|
|
|
{
|
|
|
|
return (aMsg.message == WM_KEYDOWN || aMsg.message == WM_SYSKEYDOWN) &&
|
|
|
|
(sRedirectedKeyDown.message == aMsg.message &&
|
2012-01-04 10:21:44 +00:00
|
|
|
WinUtils::GetScanCode(sRedirectedKeyDown.lParam) ==
|
|
|
|
WinUtils::GetScanCode(aMsg.lParam));
|
2011-01-14 13:38:57 +00:00
|
|
|
}
|
|
|
|
|
2011-01-24 21:38:41 +00:00
|
|
|
void
|
|
|
|
nsWindow::PerformElantechSwipeGestureHack(UINT& aVirtualKeyCode,
|
|
|
|
nsModifierKeyState& aModKeyState)
|
|
|
|
{
|
|
|
|
// The Elantech touchpad driver understands three-finger swipe left and
|
|
|
|
// right gestures, and translates them into Page Up and Page Down key
|
|
|
|
// events for most applications. For Firefox 3.6, it instead sends
|
|
|
|
// Alt+Left and Alt+Right to trigger browser back/forward actions. As
|
|
|
|
// with the Thinkpad Driver hack in nsWindow::Create, the change in
|
|
|
|
// HWND structure makes Firefox not trigger the driver's heuristics
|
|
|
|
// any longer.
|
|
|
|
//
|
|
|
|
// The Elantech driver actually sends these messages for a three-finger
|
|
|
|
// swipe right:
|
|
|
|
//
|
|
|
|
// WM_KEYDOWN virtual_key = 0xCC or 0xFF (depending on driver version)
|
|
|
|
// WM_KEYDOWN virtual_key = VK_NEXT
|
|
|
|
// WM_KEYUP virtual_key = VK_NEXT
|
|
|
|
// WM_KEYUP virtual_key = 0xCC or 0xFF
|
|
|
|
//
|
|
|
|
// so we use the 0xCC or 0xFF key modifier to detect whether the Page Down
|
|
|
|
// is due to the gesture rather than a regular Page Down keypress. We then
|
|
|
|
// pretend that we were went an Alt+Right keystroke instead. Similarly
|
|
|
|
// for VK_PRIOR and Alt+Left.
|
|
|
|
if ((aVirtualKeyCode == VK_NEXT || aVirtualKeyCode == VK_PRIOR) &&
|
|
|
|
(IS_VK_DOWN(0xFF) || IS_VK_DOWN(0xCC))) {
|
|
|
|
aModKeyState.mIsAltDown = true;
|
|
|
|
aVirtualKeyCode = aVirtualKeyCode == VK_NEXT ? VK_RIGHT : VK_LEFT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**
|
|
|
|
* nsWindow::OnKeyDown peeks into the message queue and pulls out
|
|
|
|
* WM_CHAR messages for processing. During testing we don't want to
|
|
|
|
* mess with the real message queue. Instead we pass a
|
|
|
|
* pseudo-WM_CHAR-message using this structure, and OnKeyDown will use
|
|
|
|
* that as if it was in the message queue, and refrain from actually
|
|
|
|
* looking at or touching the message queue.
|
|
|
|
*/
|
|
|
|
LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
|
|
|
|
nsModifierKeyState &aModKeyState,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool *aEventDispatched,
|
2009-06-29 19:36:16 +00:00
|
|
|
nsFakeCharMessage* aFakeCharMessage)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2011-01-14 13:38:57 +00:00
|
|
|
UINT virtualKeyCode =
|
|
|
|
aMsg.wParam != VK_PROCESSKEY ? aMsg.wParam : ::ImmGetVirtualKey(mWnd);
|
|
|
|
gKbdLayout.OnKeyDown(virtualKeyCode);
|
2005-12-02 12:08:32 +00:00
|
|
|
|
2011-06-22 20:48:24 +00:00
|
|
|
if (sUseElantechSwipeHack) {
|
2011-01-24 21:38:41 +00:00
|
|
|
PerformElantechSwipeGestureHack(virtualKeyCode, aModKeyState);
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Use only DOMKeyCode for XP processing.
|
2011-01-14 13:38:57 +00:00
|
|
|
// Use virtualKeyCode for gKbdLayout and native processing.
|
2010-08-08 09:23:25 +00:00
|
|
|
UINT DOMKeyCode = nsIMM32Handler::IsComposingOn(this) ?
|
2009-06-29 19:36:16 +00:00
|
|
|
virtualKeyCode : MapFromNativeToDOM(virtualKeyCode);
|
2003-05-15 00:12:03 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef DEBUG
|
2011-08-16 19:30:44 +00:00
|
|
|
//PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("In OnKeyDown virt: %d\n", DOMKeyCode));
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif
|
1998-05-08 14:54:09 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool sRedirectedKeyDownEventPreventedDefault = false;
|
|
|
|
bool noDefault;
|
2011-01-14 13:38:57 +00:00
|
|
|
if (aFakeCharMessage || !IsRedirectedKeyDownMessage(aMsg)) {
|
2011-07-07 12:02:07 +00:00
|
|
|
nsIMEContext IMEContext(mWnd);
|
2011-01-14 13:38:57 +00:00
|
|
|
noDefault =
|
|
|
|
DispatchKeyEvent(NS_KEY_DOWN, 0, nsnull, DOMKeyCode, &aMsg, aModKeyState);
|
|
|
|
if (aEventDispatched) {
|
2011-10-02 02:16:19 +00:00
|
|
|
*aEventDispatched = true;
|
2011-01-14 13:38:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If IMC wasn't associated to the window but is associated it now (i.e.,
|
|
|
|
// focus is moved from a non-editable editor to an editor by keydown
|
|
|
|
// event handler), WM_CHAR and WM_SYSCHAR shouldn't cause first character
|
|
|
|
// inputting if IME is opened. But then, we should redirect the native
|
|
|
|
// keydown message to IME.
|
|
|
|
// However, note that if focus has been already moved to another
|
|
|
|
// application, we shouldn't redirect the message to it because the keydown
|
|
|
|
// message is processed by us, so, nobody shouldn't process it.
|
|
|
|
HWND focusedWnd = ::GetFocus();
|
2011-07-07 12:02:07 +00:00
|
|
|
nsIMEContext newIMEContext(mWnd);
|
|
|
|
if (!noDefault && !aFakeCharMessage && focusedWnd && !PluginHasFocus() &&
|
|
|
|
!IMEContext.get() && newIMEContext.get()) {
|
2011-01-14 13:38:57 +00:00
|
|
|
RemoveNextCharMessage(focusedWnd);
|
|
|
|
|
|
|
|
INPUT keyinput;
|
|
|
|
keyinput.type = INPUT_KEYBOARD;
|
|
|
|
keyinput.ki.wVk = aMsg.wParam;
|
2012-01-04 10:21:44 +00:00
|
|
|
keyinput.ki.wScan = WinUtils::GetScanCode(aMsg.lParam);
|
2011-01-14 13:38:57 +00:00
|
|
|
keyinput.ki.dwFlags = KEYEVENTF_SCANCODE;
|
2012-01-04 10:21:44 +00:00
|
|
|
if (WinUtils::IsExtendedScanCode(aMsg.lParam)) {
|
2011-01-14 13:38:57 +00:00
|
|
|
keyinput.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
|
|
|
|
}
|
|
|
|
keyinput.ki.time = 0;
|
|
|
|
keyinput.ki.dwExtraInfo = NULL;
|
|
|
|
|
|
|
|
sRedirectedKeyDownEventPreventedDefault = noDefault;
|
|
|
|
sRedirectedKeyDown = aMsg;
|
|
|
|
|
|
|
|
::SendInput(1, &keyinput, sizeof(keyinput));
|
|
|
|
|
|
|
|
// Return here. We shouldn't dispatch keypress event for this WM_KEYDOWN.
|
|
|
|
// If it's needed, it will be dispatched after next (redirected)
|
|
|
|
// WM_KEYDOWN.
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2011-01-14 13:38:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mOnDestroyCalled) {
|
|
|
|
// If this was destroyed by the keydown event handler, we shouldn't
|
|
|
|
// dispatch keypress event on this window.
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2011-01-14 13:38:57 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
noDefault = sRedirectedKeyDownEventPreventedDefault;
|
|
|
|
// If this is redirected keydown message, we have dispatched the keydown
|
|
|
|
// event already.
|
|
|
|
if (aEventDispatched) {
|
2011-10-02 02:16:19 +00:00
|
|
|
*aEventDispatched = true;
|
2011-01-14 13:38:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ForgetRedirectedKeyDownMessage();
|
|
|
|
|
|
|
|
// If the key was processed by IME, we shouldn't dispatch keypress event.
|
|
|
|
if (aMsg.wParam == VK_PROCESSKEY) {
|
|
|
|
return noDefault;
|
|
|
|
}
|
2000-04-28 20:27:18 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
|
|
|
|
// for almost all keys
|
|
|
|
switch (DOMKeyCode) {
|
|
|
|
case NS_VK_SHIFT:
|
|
|
|
case NS_VK_CONTROL:
|
|
|
|
case NS_VK_ALT:
|
|
|
|
case NS_VK_CAPS_LOCK:
|
|
|
|
case NS_VK_NUM_LOCK:
|
|
|
|
case NS_VK_SCROLL_LOCK: return noDefault;
|
2001-12-06 02:55:06 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
PRUint32 extraFlags = (noDefault ? NS_EVENT_FLAG_NO_DEFAULT : 0);
|
|
|
|
MSG msg;
|
|
|
|
BOOL gotMsg = aFakeCharMessage ||
|
|
|
|
::PeekMessageW(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
|
|
|
|
// Enter and backspace are always handled here to avoid for example the
|
|
|
|
// confusion between ctrl-enter and ctrl-J.
|
|
|
|
if (DOMKeyCode == NS_VK_RETURN || DOMKeyCode == NS_VK_BACK ||
|
|
|
|
((aModKeyState.mIsControlDown || aModKeyState.mIsAltDown)
|
2010-07-22 02:11:34 +00:00
|
|
|
&& !gKbdLayout.IsDeadKey() && KeyboardLayout::IsPrintableCharKey(virtualKeyCode)))
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
// Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
|
|
|
|
// They can be more than one because of:
|
|
|
|
// * Dead-keys not pairing with base character
|
|
|
|
// * Some keyboard layouts may map up to 4 characters to the single key
|
2011-09-29 06:19:26 +00:00
|
|
|
bool anyCharMessagesRemoved = false;
|
2005-12-29 10:18:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aFakeCharMessage) {
|
2011-04-20 23:54:43 +00:00
|
|
|
RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST,
|
|
|
|
aFakeCharMessage);
|
2011-10-02 02:16:19 +00:00
|
|
|
anyCharMessagesRemoved = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
} else {
|
|
|
|
while (gotMsg && (msg.message == WM_CHAR || msg.message == WM_SYSCHAR))
|
|
|
|
{
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
2011-08-16 19:30:44 +00:00
|
|
|
("%s charCode=%d scanCode=%d\n", msg.message == WM_SYSCHAR ?
|
|
|
|
"WM_SYSCHAR" : "WM_CHAR",
|
2009-06-29 19:36:16 +00:00
|
|
|
msg.wParam, HIWORD(msg.lParam) & 0xFF));
|
|
|
|
RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST);
|
2011-10-02 02:16:19 +00:00
|
|
|
anyCharMessagesRemoved = true;
|
2004-07-09 21:39:16 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
gotMsg = ::PeekMessageW (&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
|
|
|
|
}
|
|
|
|
}
|
2005-12-29 10:18:31 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!anyCharMessagesRemoved && DOMKeyCode == NS_VK_BACK &&
|
|
|
|
nsIMM32Handler::IsDoingKakuteiUndo(mWnd)) {
|
|
|
|
NS_ASSERTION(!aFakeCharMessage,
|
|
|
|
"We shouldn't be touching the real msg queue");
|
|
|
|
RemoveMessageAndDispatchPluginEvent(WM_CHAR, WM_CHAR);
|
|
|
|
}
|
2001-02-23 00:40:19 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
else if (gotMsg &&
|
|
|
|
(aFakeCharMessage ||
|
|
|
|
msg.message == WM_CHAR || msg.message == WM_SYSCHAR || msg.message == WM_DEADCHAR)) {
|
2011-04-20 23:54:43 +00:00
|
|
|
if (aFakeCharMessage) {
|
|
|
|
MSG msg = aFakeCharMessage->GetCharMessage(mWnd);
|
2009-06-29 19:36:16 +00:00
|
|
|
return OnCharRaw(aFakeCharMessage->mCharCode,
|
2011-04-20 23:54:43 +00:00
|
|
|
aFakeCharMessage->mScanCode,
|
|
|
|
aModKeyState, extraFlags, &msg);
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// If prevent default set for keydown, do same for keypress
|
|
|
|
::GetMessageW(&msg, mWnd, msg.message, msg.message);
|
|
|
|
|
|
|
|
if (msg.message == WM_DEADCHAR) {
|
|
|
|
if (!PluginHasFocus())
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
// We need to send the removed message to focused plug-in.
|
|
|
|
DispatchPluginEvent(msg);
|
|
|
|
return noDefault;
|
2000-04-28 20:27:18 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("%s charCode=%d scanCode=%d\n",
|
|
|
|
msg.message == WM_SYSCHAR ? "WM_SYSCHAR" : "WM_CHAR",
|
|
|
|
msg.wParam, HIWORD(msg.lParam) & 0xFF));
|
|
|
|
|
|
|
|
BOOL result = OnChar(msg, aModKeyState, nsnull, extraFlags);
|
|
|
|
// If a syschar keypress wasn't processed, Windows may want to
|
|
|
|
// handle it to activate a native menu.
|
|
|
|
if (!result && msg.message == WM_SYSCHAR)
|
|
|
|
::DefWindowProcW(mWnd, msg.message, msg.wParam, msg.lParam);
|
|
|
|
return result;
|
2000-04-28 20:27:18 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
else if (!aModKeyState.mIsControlDown && !aModKeyState.mIsAltDown &&
|
2010-07-22 02:11:34 +00:00
|
|
|
(KeyboardLayout::IsPrintableCharKey(virtualKeyCode) ||
|
|
|
|
KeyboardLayout::IsNumpadKey(virtualKeyCode)))
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
// If this is simple KeyDown event but next message is not WM_CHAR,
|
|
|
|
// this event may not input text, so we should ignore this event.
|
|
|
|
// See bug 314130.
|
|
|
|
return PluginHasFocus() && noDefault;
|
2008-03-12 22:44:45 +00:00
|
|
|
}
|
2000-04-28 20:27:18 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (gKbdLayout.IsDeadKey ())
|
|
|
|
return PluginHasFocus() && noDefault;
|
2000-04-28 20:27:18 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
PRUint8 shiftStates[5];
|
|
|
|
PRUnichar uniChars[5];
|
|
|
|
PRUnichar shiftedChars[5] = {0, 0, 0, 0, 0};
|
|
|
|
PRUnichar unshiftedChars[5] = {0, 0, 0, 0, 0};
|
|
|
|
PRUnichar shiftedLatinChar = 0;
|
|
|
|
PRUnichar unshiftedLatinChar = 0;
|
|
|
|
PRUint32 numOfUniChars = 0;
|
|
|
|
PRUint32 numOfShiftedChars = 0;
|
|
|
|
PRUint32 numOfUnshiftedChars = 0;
|
|
|
|
PRUint32 numOfShiftStates = 0;
|
1999-06-25 21:17:52 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
switch (virtualKeyCode) {
|
|
|
|
// keys to be sent as characters
|
|
|
|
case VK_ADD: uniChars [0] = '+'; numOfUniChars = 1; break;
|
|
|
|
case VK_SUBTRACT: uniChars [0] = '-'; numOfUniChars = 1; break;
|
|
|
|
case VK_DIVIDE: uniChars [0] = '/'; numOfUniChars = 1; break;
|
|
|
|
case VK_MULTIPLY: uniChars [0] = '*'; numOfUniChars = 1; break;
|
|
|
|
case VK_NUMPAD0:
|
|
|
|
case VK_NUMPAD1:
|
|
|
|
case VK_NUMPAD2:
|
|
|
|
case VK_NUMPAD3:
|
|
|
|
case VK_NUMPAD4:
|
|
|
|
case VK_NUMPAD5:
|
|
|
|
case VK_NUMPAD6:
|
|
|
|
case VK_NUMPAD7:
|
|
|
|
case VK_NUMPAD8:
|
|
|
|
case VK_NUMPAD9:
|
|
|
|
uniChars [0] = virtualKeyCode - VK_NUMPAD0 + '0';
|
|
|
|
numOfUniChars = 1;
|
1999-06-25 21:17:52 +00:00
|
|
|
break;
|
|
|
|
default:
|
2010-07-22 02:11:34 +00:00
|
|
|
if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
numOfUniChars = numOfShiftStates =
|
|
|
|
gKbdLayout.GetUniChars(uniChars, shiftStates,
|
2011-10-11 05:50:08 +00:00
|
|
|
ArrayLength(uniChars));
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1999-06-25 21:17:52 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aModKeyState.mIsControlDown ^ aModKeyState.mIsAltDown) {
|
|
|
|
PRUint8 capsLockState = (::GetKeyState(VK_CAPITAL) & 1) ? eCapsLock : 0;
|
|
|
|
numOfUnshiftedChars =
|
|
|
|
gKbdLayout.GetUniCharsWithShiftState(virtualKeyCode, capsLockState,
|
2011-10-11 05:50:08 +00:00
|
|
|
unshiftedChars, ArrayLength(unshiftedChars));
|
2009-06-29 19:36:16 +00:00
|
|
|
numOfShiftedChars =
|
|
|
|
gKbdLayout.GetUniCharsWithShiftState(virtualKeyCode,
|
|
|
|
capsLockState | eShift,
|
2011-10-11 05:50:08 +00:00
|
|
|
shiftedChars, ArrayLength(shiftedChars));
|
1999-06-25 21:17:52 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// The current keyboard cannot input alphabets or numerics,
|
|
|
|
// we should append them for Shortcut/Access keys.
|
|
|
|
// E.g., for Cyrillic keyboard layout.
|
|
|
|
if (NS_VK_A <= DOMKeyCode && DOMKeyCode <= NS_VK_Z) {
|
|
|
|
shiftedLatinChar = unshiftedLatinChar = DOMKeyCode;
|
|
|
|
if (capsLockState)
|
|
|
|
shiftedLatinChar += 0x20;
|
|
|
|
else
|
|
|
|
unshiftedLatinChar += 0x20;
|
|
|
|
if (unshiftedLatinChar == unshiftedChars[0] &&
|
|
|
|
shiftedLatinChar == shiftedChars[0]) {
|
|
|
|
shiftedLatinChar = unshiftedLatinChar = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PRUint16 ch = 0;
|
|
|
|
if (NS_VK_0 <= DOMKeyCode && DOMKeyCode <= NS_VK_9) {
|
|
|
|
ch = DOMKeyCode;
|
|
|
|
} else {
|
|
|
|
switch (virtualKeyCode) {
|
|
|
|
case VK_OEM_PLUS: ch = '+'; break;
|
|
|
|
case VK_OEM_MINUS: ch = '-'; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ch && unshiftedChars[0] != ch && shiftedChars[0] != ch) {
|
|
|
|
// Windows has assigned a virtual key code to the key even though
|
|
|
|
// the character can't be produced with this key. That probably
|
|
|
|
// means the character can't be produced with any key in the
|
|
|
|
// current layout and so the assignment is based on a QWERTY
|
|
|
|
// layout. Append this code so that users can access the shortcut.
|
|
|
|
unshiftedLatinChar = ch;
|
|
|
|
}
|
|
|
|
}
|
1999-06-25 21:17:52 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// If the charCode is not ASCII character, we should replace the
|
|
|
|
// charCode with ASCII character only when Ctrl is pressed.
|
|
|
|
// But don't replace the charCode when the charCode is not same as
|
|
|
|
// unmodified characters. In such case, Ctrl is sometimes used for a
|
|
|
|
// part of character inputting key combination like Shift.
|
|
|
|
if (aModKeyState.mIsControlDown) {
|
|
|
|
PRUint8 currentState = eCtrl;
|
|
|
|
if (aModKeyState.mIsShiftDown)
|
|
|
|
currentState |= eShift;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
PRUint32 ch =
|
|
|
|
aModKeyState.mIsShiftDown ? shiftedLatinChar : unshiftedLatinChar;
|
|
|
|
if (ch &&
|
|
|
|
(numOfUniChars == 0 ||
|
|
|
|
StringCaseInsensitiveEquals(uniChars, numOfUniChars,
|
|
|
|
aModKeyState.mIsShiftDown ? shiftedChars : unshiftedChars,
|
|
|
|
aModKeyState.mIsShiftDown ? numOfShiftedChars :
|
|
|
|
numOfUnshiftedChars))) {
|
|
|
|
numOfUniChars = numOfShiftStates = 1;
|
|
|
|
uniChars[0] = ch;
|
|
|
|
shiftStates[0] = currentState;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (numOfUniChars > 0 || numOfShiftedChars > 0 || numOfUnshiftedChars > 0) {
|
2011-06-25 14:06:02 +00:00
|
|
|
PRUint32 num = NS_MAX(numOfUniChars,
|
|
|
|
NS_MAX(numOfShiftedChars, numOfUnshiftedChars));
|
2009-06-29 19:36:16 +00:00
|
|
|
PRUint32 skipUniChars = num - numOfUniChars;
|
|
|
|
PRUint32 skipShiftedChars = num - numOfShiftedChars;
|
|
|
|
PRUint32 skipUnshiftedChars = num - numOfUnshiftedChars;
|
|
|
|
UINT keyCode = numOfUniChars == 0 ? DOMKeyCode : 0;
|
|
|
|
for (PRUint32 cnt = 0; cnt < num; cnt++) {
|
|
|
|
PRUint16 uniChar, shiftedChar, unshiftedChar;
|
|
|
|
uniChar = shiftedChar = unshiftedChar = 0;
|
|
|
|
if (skipUniChars <= cnt) {
|
|
|
|
if (cnt - skipUniChars < numOfShiftStates) {
|
|
|
|
// If key in combination with Alt and/or Ctrl produces a different
|
|
|
|
// character than without them then do not report these flags
|
|
|
|
// because it is separate keyboard layout shift state. If dead-key
|
|
|
|
// and base character does not produce a valid composite character
|
|
|
|
// then both produced dead-key character and following base
|
|
|
|
// character may have different modifier flags, too.
|
|
|
|
aModKeyState.mIsShiftDown =
|
|
|
|
(shiftStates[cnt - skipUniChars] & eShift) != 0;
|
|
|
|
aModKeyState.mIsControlDown =
|
|
|
|
(shiftStates[cnt - skipUniChars] & eCtrl) != 0;
|
|
|
|
aModKeyState.mIsAltDown =
|
|
|
|
(shiftStates[cnt - skipUniChars] & eAlt) != 0;
|
|
|
|
}
|
|
|
|
uniChar = uniChars[cnt - skipUniChars];
|
|
|
|
}
|
|
|
|
if (skipShiftedChars <= cnt)
|
|
|
|
shiftedChar = shiftedChars[cnt - skipShiftedChars];
|
|
|
|
if (skipUnshiftedChars <= cnt)
|
|
|
|
unshiftedChar = unshiftedChars[cnt - skipUnshiftedChars];
|
|
|
|
nsAutoTArray<nsAlternativeCharCode, 5> altArray;
|
|
|
|
|
|
|
|
if (shiftedChar || unshiftedChar) {
|
|
|
|
nsAlternativeCharCode chars(unshiftedChar, shiftedChar);
|
|
|
|
altArray.AppendElement(chars);
|
|
|
|
}
|
|
|
|
if (cnt == num - 1 && (unshiftedLatinChar || shiftedLatinChar)) {
|
|
|
|
nsAlternativeCharCode chars(unshiftedLatinChar, shiftedLatinChar);
|
|
|
|
altArray.AppendElement(chars);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
DispatchKeyEvent(NS_KEY_PRESS, uniChar, &altArray,
|
|
|
|
keyCode, nsnull, aModKeyState, extraFlags);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
2009-07-17 23:03:54 +00:00
|
|
|
} else {
|
2009-06-29 19:36:16 +00:00
|
|
|
DispatchKeyEvent(NS_KEY_PRESS, 0, nsnull, DOMKeyCode, nsnull, aModKeyState,
|
|
|
|
extraFlags);
|
2009-07-17 23:03:54 +00:00
|
|
|
}
|
2002-04-02 21:08:29 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return noDefault;
|
|
|
|
}
|
|
|
|
|
|
|
|
// OnKeyUp
|
|
|
|
LRESULT nsWindow::OnKeyUp(const MSG &aMsg,
|
|
|
|
nsModifierKeyState &aModKeyState,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool *aEventDispatched)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
UINT virtualKeyCode = aMsg.wParam;
|
2006-01-09 17:23:20 +00:00
|
|
|
|
2011-06-22 20:48:24 +00:00
|
|
|
if (sUseElantechSwipeHack) {
|
2011-01-24 21:38:41 +00:00
|
|
|
PerformElantechSwipeGestureHack(virtualKeyCode, aModKeyState);
|
2011-06-22 20:48:24 +00:00
|
|
|
}
|
2011-02-12 01:56:13 +00:00
|
|
|
|
2011-06-22 20:48:24 +00:00
|
|
|
if (sUseElantechPinchHack) {
|
2011-02-12 01:56:13 +00:00
|
|
|
// Version 8 of the Elantech touchpad driver sends these messages for
|
|
|
|
// zoom gestures:
|
|
|
|
//
|
|
|
|
// WM_KEYDOWN virtual_key = 0xCC time = 10
|
|
|
|
// WM_KEYDOWN virtual_key = VK_CONTROL time = 10
|
|
|
|
// WM_MOUSEWHEEL time = ::GetTickCount()
|
|
|
|
// WM_KEYUP virtual_key = VK_CONTROL time = 10
|
|
|
|
// WM_KEYUP virtual_key = 0xCC time = 10
|
|
|
|
//
|
|
|
|
// The result of this is that we process all of the WM_KEYDOWN/WM_KEYUP
|
|
|
|
// messages first because their timestamps make them appear to have
|
|
|
|
// been sent before the WM_MOUSEWHEEL message. To work around this,
|
|
|
|
// we store the current time when we process the WM_KEYUP message and
|
|
|
|
// assume that any WM_MOUSEWHEEL message with a timestamp before that
|
|
|
|
// time is one that should be processed as if the Control key was down.
|
|
|
|
if (virtualKeyCode == VK_CONTROL && aMsg.time == 10) {
|
|
|
|
// We look only at the bottom 31 bits of the system tick count since
|
|
|
|
// GetMessageTime returns a LONG, which is signed, so we want values
|
|
|
|
// that are more easily comparable.
|
|
|
|
mAssumeWheelIsZoomUntil = ::GetTickCount() & 0x7FFFFFFF;
|
|
|
|
}
|
2011-01-24 21:38:41 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("nsWindow::OnKeyUp VK=%d\n", virtualKeyCode));
|
2006-01-22 12:00:55 +00:00
|
|
|
|
2010-08-08 09:23:25 +00:00
|
|
|
if (!nsIMM32Handler::IsComposingOn(this)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
virtualKeyCode = MapFromNativeToDOM(virtualKeyCode);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aEventDispatched)
|
2011-10-02 02:16:19 +00:00
|
|
|
*aEventDispatched = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
return DispatchKeyEvent(NS_KEY_UP, 0, nsnull, virtualKeyCode, &aMsg,
|
|
|
|
aModKeyState);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// OnChar
|
|
|
|
LRESULT nsWindow::OnChar(const MSG &aMsg, nsModifierKeyState &aModKeyState,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool *aEventDispatched, PRUint32 aFlags)
|
2001-04-01 01:38:35 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
return OnCharRaw(aMsg.wParam, HIWORD(aMsg.lParam) & 0xFF, aModKeyState,
|
|
|
|
aFlags, &aMsg, aEventDispatched);
|
|
|
|
}
|
2001-04-01 01:38:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// OnCharRaw
|
|
|
|
LRESULT nsWindow::OnCharRaw(UINT charCode, UINT aScanCode,
|
|
|
|
nsModifierKeyState &aModKeyState, PRUint32 aFlags,
|
2011-09-29 06:19:26 +00:00
|
|
|
const MSG *aMsg, bool *aEventDispatched)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
// ignore [shift+]alt+space so the OS can handle it
|
|
|
|
if (aModKeyState.mIsAltDown && !aModKeyState.mIsControlDown &&
|
|
|
|
IS_VK_DOWN(NS_VK_SPACE)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ignore Ctrl+Enter (bug 318235)
|
|
|
|
if (aModKeyState.mIsControlDown && charCode == 0xA) {
|
|
|
|
return FALSE;
|
2001-04-01 01:38:35 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// WM_CHAR with Control and Alt (== AltGr) down really means a normal character
|
2011-09-29 06:19:26 +00:00
|
|
|
bool saveIsAltDown = aModKeyState.mIsAltDown;
|
|
|
|
bool saveIsControlDown = aModKeyState.mIsControlDown;
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aModKeyState.mIsAltDown && aModKeyState.mIsControlDown)
|
2011-10-02 02:16:19 +00:00
|
|
|
aModKeyState.mIsAltDown = aModKeyState.mIsControlDown = false;
|
2001-04-01 01:38:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
wchar_t uniChar;
|
2001-04-01 01:38:35 +00:00
|
|
|
|
2010-08-08 09:23:25 +00:00
|
|
|
if (nsIMM32Handler::IsComposingOn(this)) {
|
2009-06-29 19:36:16 +00:00
|
|
|
ResetInputState();
|
|
|
|
}
|
2001-04-01 01:38:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aModKeyState.mIsControlDown && charCode <= 0x1A) { // Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
|
|
|
|
// need to account for shift here. bug 16486
|
|
|
|
if (aModKeyState.mIsShiftDown)
|
|
|
|
uniChar = charCode - 1 + 'A';
|
|
|
|
else
|
|
|
|
uniChar = charCode - 1 + 'a';
|
|
|
|
charCode = 0;
|
|
|
|
}
|
|
|
|
else if (aModKeyState.mIsControlDown && charCode <= 0x1F) {
|
|
|
|
// Fix for 50255 - <ctrl><[> and <ctrl><]> are not being processed.
|
|
|
|
// also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
|
|
|
|
// for some reason the keypress handler need to have the uniChar code set
|
|
|
|
// with the addition of a upper case A not the lower case.
|
|
|
|
uniChar = charCode - 1 + 'A';
|
|
|
|
charCode = 0;
|
|
|
|
} else { // 0x20 - SPACE, 0x3D - EQUALS
|
|
|
|
if (charCode < 0x20 || (charCode == 0x3D && aModKeyState.mIsControlDown)) {
|
|
|
|
uniChar = 0;
|
|
|
|
} else {
|
|
|
|
uniChar = charCode;
|
|
|
|
charCode = 0;
|
|
|
|
}
|
|
|
|
}
|
2001-04-01 01:38:35 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Keep the characters unshifted for shortcuts and accesskeys and make sure
|
|
|
|
// that numbers are always passed as such (among others: bugs 50255 and 351310)
|
|
|
|
if (uniChar && (aModKeyState.mIsControlDown || aModKeyState.mIsAltDown)) {
|
|
|
|
UINT virtualKeyCode = ::MapVirtualKeyEx(aScanCode, MAPVK_VSC_TO_VK,
|
|
|
|
gKbdLayout.GetLayout());
|
|
|
|
UINT unshiftedCharCode =
|
|
|
|
virtualKeyCode >= '0' && virtualKeyCode <= '9' ? virtualKeyCode :
|
|
|
|
aModKeyState.mIsShiftDown ? ::MapVirtualKeyEx(virtualKeyCode,
|
|
|
|
MAPVK_VK_TO_CHAR,
|
|
|
|
gKbdLayout.GetLayout()) : 0;
|
|
|
|
// ignore diacritics (top bit set) and key mapping errors (char code 0)
|
|
|
|
if ((INT)unshiftedCharCode > 0)
|
|
|
|
uniChar = unshiftedCharCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix for bug 285161 (and 295095) which was caused by the initial fix for bug 178110.
|
|
|
|
// When pressing (alt|ctrl)+char, the char must be lowercase unless shift is
|
|
|
|
// pressed too.
|
|
|
|
if (!aModKeyState.mIsShiftDown && (saveIsAltDown || saveIsControlDown)) {
|
|
|
|
uniChar = towlower(uniChar);
|
|
|
|
}
|
2001-04-01 01:38:35 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool result = DispatchKeyEvent(NS_KEY_PRESS, uniChar, nsnull,
|
2009-06-29 19:36:16 +00:00
|
|
|
charCode, aMsg, aModKeyState, aFlags);
|
|
|
|
if (aEventDispatched)
|
2011-10-02 02:16:19 +00:00
|
|
|
*aEventDispatched = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
aModKeyState.mIsAltDown = saveIsAltDown;
|
|
|
|
aModKeyState.mIsControlDown = saveIsControlDown;
|
2001-04-01 01:38:35 +00:00
|
|
|
return result;
|
|
|
|
}
|
2001-08-17 03:13:07 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void
|
|
|
|
nsWindow::SetupKeyModifiersSequence(nsTArray<KeyPair>* aArray, PRUint32 aModifiers)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
{
|
2011-10-11 05:50:08 +00:00
|
|
|
for (PRUint32 i = 0; i < ArrayLength(sModifierKeyMap); ++i) {
|
2009-06-29 19:36:16 +00:00
|
|
|
const PRUint32* map = sModifierKeyMap[i];
|
|
|
|
if (aModifiers & map[0]) {
|
|
|
|
aArray->AppendElement(KeyPair(map[1], map[2]));
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-22 00:44:55 +00:00
|
|
|
nsresult
|
|
|
|
nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
|
|
|
{
|
|
|
|
// XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos
|
|
|
|
// here, if that helps in some situations. So far I haven't seen a
|
|
|
|
// need.
|
|
|
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
|
|
|
const Configuration& configuration = aConfigurations[i];
|
|
|
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
|
|
|
NS_ASSERTION(w->GetParent() == this,
|
|
|
|
"Configured widget is not a child");
|
2011-10-02 02:16:19 +00:00
|
|
|
nsresult rv = w->SetWindowClipRegion(configuration.mClipRegion, true);
|
2010-08-28 07:51:13 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2009-07-26 21:19:15 +00:00
|
|
|
nsIntRect bounds;
|
|
|
|
w->GetBounds(bounds);
|
|
|
|
if (bounds.Size() != configuration.mBounds.Size()) {
|
|
|
|
w->Resize(configuration.mBounds.x, configuration.mBounds.y,
|
|
|
|
configuration.mBounds.width, configuration.mBounds.height,
|
2011-10-02 02:16:19 +00:00
|
|
|
true);
|
2009-07-26 21:19:15 +00:00
|
|
|
} else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
|
|
|
|
w->Move(configuration.mBounds.x, configuration.mBounds.y);
|
2010-12-05 21:52:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
|
|
|
gfxWindowsPlatform::RENDER_DIRECT2D ||
|
|
|
|
GetLayerManager()->GetBackendType() != LayerManager::LAYERS_BASIC) {
|
|
|
|
// XXX - Workaround for Bug 587508. This will invalidate the part of the
|
|
|
|
// plugin window that might be touched by moving content somehow. The
|
|
|
|
// underlying problem should be found and fixed!
|
|
|
|
nsIntRegion r;
|
|
|
|
r.Sub(bounds, configuration.mBounds);
|
|
|
|
r.MoveBy(-bounds.x,
|
|
|
|
-bounds.y);
|
2011-12-24 03:52:21 +00:00
|
|
|
w->Invalidate(r.GetBounds());
|
2010-12-05 21:52:56 +00:00
|
|
|
}
|
2009-07-26 21:19:15 +00:00
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
rv = w->SetWindowClipRegion(configuration.mClipRegion, false);
|
2009-07-22 00:44:55 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRGN
|
|
|
|
CreateHRGNFromArray(const nsTArray<nsIntRect>& aRects)
|
|
|
|
{
|
|
|
|
PRInt32 size = sizeof(RGNDATAHEADER) + sizeof(RECT)*aRects.Length();
|
|
|
|
nsAutoTArray<PRUint8,100> buf;
|
|
|
|
if (!buf.SetLength(size))
|
|
|
|
return NULL;
|
|
|
|
RGNDATA* data = reinterpret_cast<RGNDATA*>(buf.Elements());
|
|
|
|
RECT* rects = reinterpret_cast<RECT*>(data->Buffer);
|
|
|
|
data->rdh.dwSize = sizeof(data->rdh);
|
|
|
|
data->rdh.iType = RDH_RECTANGLES;
|
|
|
|
data->rdh.nCount = aRects.Length();
|
|
|
|
nsIntRect bounds;
|
|
|
|
for (PRUint32 i = 0; i < aRects.Length(); ++i) {
|
|
|
|
const nsIntRect& r = aRects[i];
|
|
|
|
bounds.UnionRect(bounds, r);
|
|
|
|
::SetRect(&rects[i], r.x, r.y, r.XMost(), r.YMost());
|
|
|
|
}
|
|
|
|
::SetRect(&data->rdh.rcBound, bounds.x, bounds.y, bounds.XMost(), bounds.YMost());
|
|
|
|
return ::ExtCreateRegion(NULL, buf.Length(), data);
|
|
|
|
}
|
|
|
|
|
2010-12-31 20:16:35 +00:00
|
|
|
static const nsTArray<nsIntRect>
|
|
|
|
ArrayFromRegion(const nsIntRegion& aRegion)
|
|
|
|
{
|
|
|
|
nsTArray<nsIntRect> rects;
|
|
|
|
const nsIntRect* r;
|
|
|
|
for (nsIntRegionRectIterator iter(aRegion); (r = iter.Next());) {
|
|
|
|
rects.AppendElement(*r);
|
|
|
|
}
|
|
|
|
return rects;
|
|
|
|
}
|
|
|
|
|
2009-07-22 00:44:55 +00:00
|
|
|
nsresult
|
|
|
|
nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool aIntersectWithExisting)
|
2009-07-22 00:44:55 +00:00
|
|
|
{
|
2009-07-26 21:19:15 +00:00
|
|
|
if (!aIntersectWithExisting) {
|
|
|
|
if (!StoreWindowClipRegion(aRects))
|
|
|
|
return NS_OK;
|
2010-08-28 07:51:13 +00:00
|
|
|
} else {
|
|
|
|
// In this case still early return if nothing changed.
|
|
|
|
if (mClipRects && mClipRectCount == aRects.Length() &&
|
|
|
|
memcmp(mClipRects,
|
|
|
|
aRects.Elements(),
|
|
|
|
sizeof(nsIntRect)*mClipRectCount) == 0) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-12-31 20:16:35 +00:00
|
|
|
|
|
|
|
// get current rects
|
|
|
|
nsTArray<nsIntRect> currentRects;
|
|
|
|
GetWindowClipRegion(¤tRects);
|
|
|
|
// create region from them
|
|
|
|
nsIntRegion currentRegion = RegionFromArray(currentRects);
|
|
|
|
// create region from new rects
|
|
|
|
nsIntRegion newRegion = RegionFromArray(aRects);
|
|
|
|
// intersect regions
|
|
|
|
nsIntRegion intersection;
|
|
|
|
intersection.And(currentRegion, newRegion);
|
|
|
|
// create int rect array from intersection
|
|
|
|
nsTArray<nsIntRect> rects = ArrayFromRegion(intersection);
|
|
|
|
// store
|
|
|
|
if (!StoreWindowClipRegion(rects))
|
|
|
|
return NS_OK;
|
2009-07-26 21:19:15 +00:00
|
|
|
}
|
|
|
|
|
2009-07-22 00:44:55 +00:00
|
|
|
HRGN dest = CreateHRGNFromArray(aRects);
|
|
|
|
if (!dest)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
if (aIntersectWithExisting) {
|
|
|
|
HRGN current = ::CreateRectRgn(0, 0, 0, 0);
|
|
|
|
if (current) {
|
|
|
|
if (::GetWindowRgn(mWnd, current) != 0 /*ERROR*/) {
|
|
|
|
::CombineRgn(dest, dest, current, RGN_AND);
|
|
|
|
}
|
|
|
|
::DeleteObject(current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-31 19:19:03 +00:00
|
|
|
// If a plugin is not visibile, especially if it is in a background tab,
|
|
|
|
// it should not be able to steal keyboard focus. This code checks whether
|
|
|
|
// the region that the plugin is being clipped to is NULLREGION. If it is,
|
|
|
|
// the plugin window gets disabled.
|
|
|
|
if(mWindowType == eWindowType_plugin) {
|
|
|
|
if(NULLREGION == ::CombineRgn(dest, dest, dest, RGN_OR)) {
|
|
|
|
::EnableWindow(mWnd, FALSE);
|
|
|
|
} else {
|
|
|
|
::EnableWindow(mWnd, TRUE);
|
|
|
|
}
|
|
|
|
}
|
2009-07-22 00:44:55 +00:00
|
|
|
if (!::SetWindowRgn(mWnd, dest, TRUE)) {
|
|
|
|
::DeleteObject(dest);
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// WM_DESTROY event handler
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::OnDestroy()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
mOnDestroyCalled = true;
|
1999-07-27 20:50:05 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// Make sure we don't get destroyed in the process of tearing down.
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
|
|
|
|
|
|
|
// Dispatch the NS_DESTROY event. Must be called before mEventCallback is cleared.
|
|
|
|
if (!mInDtor)
|
|
|
|
DispatchStandardEvent(NS_DESTROY);
|
|
|
|
|
|
|
|
// Prevent the widget from sending additional events.
|
|
|
|
mEventCallback = nsnull;
|
|
|
|
|
|
|
|
// Free our subclass and clear |this| stored in the window props. We will no longer
|
|
|
|
// receive events from Windows after this point.
|
2009-06-29 19:36:16 +00:00
|
|
|
SubclassWindow(FALSE);
|
1999-07-27 20:50:05 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// Once mEventCallback is cleared and the subclass is reset, sCurrentWindow can be
|
|
|
|
// cleared. (It's used in tracking windows for mouse events.)
|
|
|
|
if (sCurrentWindow == this)
|
|
|
|
sCurrentWindow = nsnull;
|
|
|
|
|
|
|
|
// Disconnects us from our parent, will call our GetParent().
|
|
|
|
nsBaseWidget::Destroy();
|
|
|
|
|
|
|
|
// Release references to children, device context, toolkit, and app shell.
|
|
|
|
nsBaseWidget::OnDestroy();
|
|
|
|
|
|
|
|
// Clear our native parent handle.
|
|
|
|
// XXX Windows will take care of this in the proper order, and SetParent(nsnull)'s
|
|
|
|
// remove child on the parent already took place in nsBaseWidget's Destroy call above.
|
|
|
|
//SetParent(nsnull);
|
2010-06-02 13:02:05 +00:00
|
|
|
mParent = nsnull;
|
2009-07-13 15:58:19 +00:00
|
|
|
|
|
|
|
// We have to destroy the native drag target before we null out our window pointer.
|
2011-10-02 02:16:19 +00:00
|
|
|
EnableDragDrop(false);
|
1999-07-27 20:50:05 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// If we're going away and for some reason we're still the rollup widget, rollup and
|
|
|
|
// turn off capture.
|
|
|
|
if ( this == sRollupWidget ) {
|
|
|
|
if ( sRollupListener )
|
2011-11-08 19:59:07 +00:00
|
|
|
sRollupListener->Rollup(0);
|
|
|
|
CaptureRollupEvents(nsnull, false, true);
|
2009-07-13 15:58:19 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-07-07 12:02:07 +00:00
|
|
|
// Restore the IM context.
|
2011-10-02 02:16:19 +00:00
|
|
|
AssociateDefaultIMC(true);
|
2009-07-13 15:58:19 +00:00
|
|
|
|
|
|
|
// Turn off mouse trails if enabled.
|
|
|
|
MouseTrailer* mtrailer = nsToolkit::gMouseTrailer;
|
|
|
|
if (mtrailer) {
|
|
|
|
if (mtrailer->GetMouseTrailerWindow() == mWnd)
|
|
|
|
mtrailer->DestroyTimer();
|
|
|
|
|
|
|
|
if (mtrailer->GetCaptureWindow() == mWnd)
|
|
|
|
mtrailer->SetCaptureWindow(nsnull);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
1999-07-27 20:50:05 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// Free GDI window class objects
|
|
|
|
if (mBrush) {
|
|
|
|
VERIFY(::DeleteObject(mBrush));
|
|
|
|
mBrush = NULL;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-07-13 15:58:19 +00:00
|
|
|
|
|
|
|
// Free app icon resources.
|
|
|
|
HICON icon;
|
|
|
|
icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM) 0);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
|
|
|
|
|
|
|
icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM) 0);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
|
|
|
|
|
|
|
// Destroy any custom cursor resources.
|
|
|
|
if (mCursor == -1)
|
|
|
|
SetCursor(eCursor_standard);
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
// Reset transparency
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
SetupTranslucentWindowMemoryBitmap(eTransparencyOpaque);
|
|
|
|
#endif
|
|
|
|
|
2010-05-26 18:53:00 +00:00
|
|
|
// Finalize panning feedback to possibly restore window displacement
|
2011-10-02 02:16:19 +00:00
|
|
|
mGesture.PanFeedbackFinalize(mWnd, true);
|
2010-05-26 18:53:00 +00:00
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
// Clear the main HWND.
|
|
|
|
mWnd = NULL;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// OnMove
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::OnMove(PRInt32 aX, PRInt32 aY)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
nsGUIEvent event(true, NS_MOVE, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
InitEvent(event);
|
|
|
|
event.refPoint.x = aX;
|
|
|
|
event.refPoint.y = aY;
|
|
|
|
|
|
|
|
return DispatchWindowEvent(&event);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Send a resize message to the listener
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::OnResize(nsIntRect &aWindowRect)
|
1998-07-21 18:04:18 +00:00
|
|
|
{
|
2010-02-26 06:36:07 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
|
|
|
if (mD2DWindowSurface) {
|
|
|
|
mD2DWindowSurface = NULL;
|
2011-12-24 03:52:21 +00:00
|
|
|
Invalidate();
|
2010-02-26 06:36:07 +00:00
|
|
|
}
|
|
|
|
#endif
|
2010-08-27 21:26:30 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// call the event callback
|
|
|
|
if (mEventCallback) {
|
2011-10-02 02:16:19 +00:00
|
|
|
nsSizeEvent event(true, NS_SIZE, this);
|
2009-06-29 19:36:16 +00:00
|
|
|
InitEvent(event);
|
|
|
|
event.windowSize = &aWindowRect;
|
|
|
|
RECT r;
|
|
|
|
if (::GetWindowRect(mWnd, &r)) {
|
|
|
|
event.mWinWidth = PRInt32(r.right - r.left);
|
|
|
|
event.mWinHeight = PRInt32(r.bottom - r.top);
|
|
|
|
} else {
|
|
|
|
event.mWinWidth = 0;
|
|
|
|
event.mWinHeight = 0;
|
|
|
|
}
|
2010-06-25 02:01:06 +00:00
|
|
|
|
|
|
|
#if 0
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("[%X] OnResize: client:(%d x %d x %d x %d) window:(%d x %d)\n", this,
|
|
|
|
aWindowRect.x, aWindowRect.y, aWindowRect.width, aWindowRect.height,
|
|
|
|
event.mWinWidth, event.mWinHeight));
|
2010-06-25 02:01:06 +00:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return DispatchWindowEvent(&event);
|
1998-07-21 18:04:18 +00:00
|
|
|
}
|
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
1998-07-21 18:04:18 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::OnHotKey(WPARAM wParam, LPARAM lParam)
|
1999-07-27 04:27:17 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
1999-07-27 04:27:17 +00:00
|
|
|
}
|
|
|
|
|
2012-02-08 21:04:21 +00:00
|
|
|
typedef DWORD (WINAPI *GetProcessImageFileNameProc)(HANDLE, LPWSTR, DWORD);
|
|
|
|
|
2011-01-27 06:54:30 +00:00
|
|
|
// Determine whether the given HWND is the handle for the Elantech helper
|
|
|
|
// window. The helper window cannot be distinguished based on its
|
|
|
|
// window class, so we need to check if it is owned by the helper process,
|
|
|
|
// ETDCtrl.exe.
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool IsElantechHelperWindow(HWND aHWND)
|
2011-01-27 06:54:30 +00:00
|
|
|
{
|
2012-02-08 21:04:21 +00:00
|
|
|
static HMODULE hPSAPI = ::LoadLibraryW(L"psapi.dll");
|
|
|
|
static GetProcessImageFileNameProc pGetProcessImageFileName =
|
|
|
|
reinterpret_cast<GetProcessImageFileNameProc>(::GetProcAddress(hPSAPI, "GetProcessImageFileNameW"));
|
|
|
|
|
|
|
|
if (!pGetProcessImageFileName) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-27 06:54:30 +00:00
|
|
|
const PRUnichar* filenameSuffix = L"\\etdctrl.exe";
|
|
|
|
const int filenameSuffixLength = 12;
|
|
|
|
|
|
|
|
DWORD pid;
|
|
|
|
::GetWindowThreadProcessId(aHWND, &pid);
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool result = false;
|
2011-01-27 06:54:30 +00:00
|
|
|
|
|
|
|
HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
|
|
|
if (hProcess) {
|
|
|
|
PRUnichar path[256] = {L'\0'};
|
2012-02-08 21:04:21 +00:00
|
|
|
if (pGetProcessImageFileName(hProcess, path, ArrayLength(path))) {
|
2011-01-27 06:54:30 +00:00
|
|
|
int pathLength = lstrlenW(path);
|
|
|
|
if (pathLength >= filenameSuffixLength) {
|
|
|
|
if (lstrcmpiW(path + pathLength - filenameSuffixLength, filenameSuffix) == 0) {
|
2011-10-02 02:16:19 +00:00
|
|
|
result = true;
|
2011-01-27 06:54:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
::CloseHandle(hProcess);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
/**
|
|
|
|
* OnMouseWheel() is called when ProcessMessage() handles WM_MOUSEWHEEL,
|
|
|
|
* WM_MOUSEHWHEEL and also OnScroll() tries to emulate mouse wheel action for
|
|
|
|
* WM_VSCROLL or WM_HSCROLL.
|
|
|
|
* So, aMsg may be WM_MOUSEWHEEL, WM_MOUSEHWHEEL, WM_VSCROLL or WM_HSCROLL.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
nsWindow::OnMouseWheel(UINT aMsg, WPARAM aWParam, LPARAM aLParam,
|
|
|
|
LRESULT *aRetValue)
|
2001-04-14 00:57:30 +00:00
|
|
|
{
|
2011-08-02 03:03:15 +00:00
|
|
|
*aRetValue = (aMsg != WM_MOUSEHWHEEL) ? TRUE : FALSE;
|
|
|
|
|
2009-08-31 22:19:06 +00:00
|
|
|
POINT point;
|
2009-09-23 17:13:55 +00:00
|
|
|
DWORD dwPoints = ::GetMessagePos();
|
2009-08-31 22:19:06 +00:00
|
|
|
point.x = GET_X_LPARAM(dwPoints);
|
|
|
|
point.y = GET_Y_LPARAM(dwPoints);
|
2009-09-23 17:13:55 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool sMayBeUsingLogitechMouse = false;
|
2009-09-23 17:13:55 +00:00
|
|
|
if (aMsg == WM_MOUSEHWHEEL) {
|
|
|
|
// Logitech (Logicool) mouse driver (confirmed with 4.82.11 and MX-1100)
|
|
|
|
// always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs one
|
|
|
|
// message at first time, this time, ::GetMessagePos works fine.
|
|
|
|
// Then, we will return 0 (0 means we process it) to the message. Then, the
|
|
|
|
// driver will POST the same messages continuously during the wheel tilted.
|
|
|
|
// But ::GetMessagePos API always returns (0, 0), even if the actual mouse
|
|
|
|
// cursor isn't 0,0. Therefore, we cannot trust the result of
|
|
|
|
// ::GetMessagePos API if the sender is the driver.
|
2010-08-20 18:19:38 +00:00
|
|
|
if (!sMayBeUsingLogitechMouse && aLParam == 0 && (DWORD)aLParam != dwPoints &&
|
2009-09-23 17:13:55 +00:00
|
|
|
::InSendMessage()) {
|
2011-10-02 02:16:19 +00:00
|
|
|
sMayBeUsingLogitechMouse = true;
|
2009-09-23 17:13:55 +00:00
|
|
|
} else if (sMayBeUsingLogitechMouse && aLParam != 0 && ::InSendMessage()) {
|
|
|
|
// The user has changed the mouse from Logitech's to another one (e.g.,
|
|
|
|
// the user has changed to the touchpad of the notebook.
|
2011-10-02 02:16:19 +00:00
|
|
|
sMayBeUsingLogitechMouse = false;
|
2009-09-23 17:13:55 +00:00
|
|
|
}
|
|
|
|
// If the WM_MOUSEHWHEEL comes from Logitech's mouse driver, and the
|
|
|
|
// ::GetMessagePos isn't correct, probably, we should use ::GetCursorPos
|
|
|
|
// instead.
|
|
|
|
if (sMayBeUsingLogitechMouse && aLParam == 0 && dwPoints == 0) {
|
|
|
|
::GetCursorPos(&point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
HWND underCursorWnd = ::WindowFromPoint(point);
|
|
|
|
if (!underCursorWnd) {
|
|
|
|
return;
|
|
|
|
}
|
2009-08-31 22:19:06 +00:00
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
if (sUseElantechPinchHack && IsElantechHelperWindow(underCursorWnd)) {
|
2011-01-27 06:54:30 +00:00
|
|
|
// The Elantech driver places a window right underneath the cursor
|
|
|
|
// when sending a WM_MOUSEWHEEL event to us as part of a pinch-to-zoom
|
|
|
|
// gesture. We detect that here, and search for our window that would
|
|
|
|
// be beneath the cursor if that window wasn't there.
|
2012-01-04 10:21:44 +00:00
|
|
|
underCursorWnd = WinUtils::FindOurWindowAtPoint(point);
|
2011-08-02 03:03:15 +00:00
|
|
|
if (!underCursorWnd) {
|
|
|
|
return;
|
|
|
|
}
|
2009-08-31 22:19:06 +00:00
|
|
|
}
|
2010-04-12 07:40:37 +00:00
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
// Handle most cases first. If the window under mouse cursor is our window
|
|
|
|
// except plugin window (MozillaWindowClass), we should handle the message
|
|
|
|
// on the window.
|
2012-01-04 10:21:44 +00:00
|
|
|
if (WinUtils::IsOurProcessWindow(underCursorWnd)) {
|
|
|
|
nsWindow* destWindow = WinUtils::GetNSWindowPtr(underCursorWnd);
|
2011-08-02 03:03:15 +00:00
|
|
|
if (!destWindow) {
|
|
|
|
NS_WARNING("We're not sure what cause this is.");
|
|
|
|
HWND wnd = ::GetParent(underCursorWnd);
|
|
|
|
for (; wnd; wnd = ::GetParent(wnd)) {
|
2012-01-04 10:21:44 +00:00
|
|
|
destWindow = WinUtils::GetNSWindowPtr(wnd);
|
2011-08-02 03:03:15 +00:00
|
|
|
if (destWindow) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!wnd) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-04-12 07:40:37 +00:00
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
NS_ASSERTION(destWindow, "destWindow must not be NULL");
|
|
|
|
// If the found window is our plugin window, it means that the message
|
|
|
|
// has been handled by the plugin but not consumed. We should handle the
|
2011-08-09 01:12:03 +00:00
|
|
|
// message on its parent window. However, note that the DOM event may
|
|
|
|
// cause accessing the plugin. Therefore, we should unlock the plugin
|
|
|
|
// process by using PostMessage().
|
2011-08-02 03:03:15 +00:00
|
|
|
if (destWindow->mWindowType == eWindowType_plugin) {
|
2011-10-02 02:16:19 +00:00
|
|
|
destWindow = destWindow->GetParentWindow(false);
|
2011-08-02 03:03:15 +00:00
|
|
|
NS_ENSURE_TRUE(destWindow, );
|
2010-04-12 07:40:37 +00:00
|
|
|
}
|
2012-01-04 10:21:44 +00:00
|
|
|
UINT internalMessage = WinUtils::GetInternalMessage(aMsg);
|
2011-08-09 01:12:03 +00:00
|
|
|
::PostMessage(destWindow->mWnd, internalMessage, aWParam, aLParam);
|
2011-08-02 03:03:15 +00:00
|
|
|
return;
|
2009-08-31 22:19:06 +00:00
|
|
|
}
|
2011-08-02 03:03:15 +00:00
|
|
|
|
|
|
|
// If the window under cursor is not in our process, it means:
|
|
|
|
// 1. The window may be a plugin window (GeckoPluginWindow or its descendant).
|
|
|
|
// 2. The window may be another application's window.
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND pluginWnd = WinUtils::FindOurProcessWindow(underCursorWnd);
|
2011-08-02 03:03:15 +00:00
|
|
|
if (!pluginWnd) {
|
|
|
|
// If there is no plugin window in ancestors of the window under cursor,
|
|
|
|
// the window is for another applications (case 2).
|
|
|
|
// We don't need to handle this message.
|
|
|
|
return;
|
2009-08-31 22:19:06 +00:00
|
|
|
}
|
2011-08-02 03:03:15 +00:00
|
|
|
|
|
|
|
// If we're a plugin window (MozillaWindowClass) and cursor in this window,
|
|
|
|
// the message shouldn't go to plugin's wndproc again. So, we should handle
|
2011-08-09 01:12:03 +00:00
|
|
|
// it on parent window. However, note that the DOM event may cause accessing
|
|
|
|
// the plugin. Therefore, we should unlock the plugin process by using
|
|
|
|
// PostMessage().
|
2011-08-02 03:03:15 +00:00
|
|
|
if (mWindowType == eWindowType_plugin && pluginWnd == mWnd) {
|
2011-10-02 02:16:19 +00:00
|
|
|
nsWindow* destWindow = GetParentWindow(false);
|
2011-08-02 03:03:15 +00:00
|
|
|
NS_ENSURE_TRUE(destWindow, );
|
2012-01-04 10:21:44 +00:00
|
|
|
UINT internalMessage = WinUtils::GetInternalMessage(aMsg);
|
2011-08-09 01:12:03 +00:00
|
|
|
::PostMessage(destWindow->mWnd, internalMessage, aWParam, aLParam);
|
2011-08-02 03:03:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the window is a part of plugin, we should post the message to it.
|
|
|
|
::PostMessage(underCursorWnd, aMsg, aWParam, aLParam);
|
2009-08-31 22:19:06 +00:00
|
|
|
}
|
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
/**
|
|
|
|
* OnScroll() is called when ProcessMessage() handles WM_VSCROLL or WM_HSCROLL.
|
|
|
|
* aMsg may be WM_VSCROLL or WM_HSCROLL.
|
|
|
|
*/
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2011-08-02 03:03:15 +00:00
|
|
|
nsWindow::OnScroll(UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
2009-08-31 22:19:06 +00:00
|
|
|
{
|
2010-03-11 05:25:29 +00:00
|
|
|
static PRInt8 sMouseWheelEmulation = -1;
|
|
|
|
if (sMouseWheelEmulation < 0) {
|
2011-09-29 06:19:26 +00:00
|
|
|
bool emulate =
|
|
|
|
Preferences::GetBool("mousewheel.emulate_at_wm_scroll", false);
|
2010-03-11 05:25:29 +00:00
|
|
|
sMouseWheelEmulation = PRInt8(emulate);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aLParam || sMouseWheelEmulation) {
|
2009-08-31 22:19:06 +00:00
|
|
|
// Scroll message generated by Thinkpad Trackpoint Driver or similar
|
|
|
|
// Treat as a mousewheel message and scroll appropriately
|
2009-11-19 23:43:34 +00:00
|
|
|
LRESULT retVal;
|
2011-08-02 03:03:15 +00:00
|
|
|
OnMouseWheel(aMsg, aWParam, aLParam, &retVal);
|
|
|
|
// Always consume the scroll message if we try to emulate mouse wheel
|
|
|
|
// action.
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-08-31 22:19:06 +00:00
|
|
|
}
|
2010-03-11 05:25:29 +00:00
|
|
|
|
2009-08-31 22:19:06 +00:00
|
|
|
// Scroll message generated by external application
|
2011-10-02 02:16:19 +00:00
|
|
|
nsContentCommandEvent command(true, NS_CONTENT_COMMAND_SCROLL, this);
|
2010-03-11 05:25:29 +00:00
|
|
|
|
|
|
|
command.mScroll.mIsHorizontal = (aMsg == WM_HSCROLL);
|
|
|
|
|
|
|
|
switch (LOWORD(aWParam))
|
|
|
|
{
|
|
|
|
case SB_LINEUP: // SB_LINELEFT
|
|
|
|
command.mScroll.mUnit = nsContentCommandEvent::eCmdScrollUnit_Line;
|
|
|
|
command.mScroll.mAmount = -1;
|
|
|
|
break;
|
|
|
|
case SB_LINEDOWN: // SB_LINERIGHT
|
|
|
|
command.mScroll.mUnit = nsContentCommandEvent::eCmdScrollUnit_Line;
|
|
|
|
command.mScroll.mAmount = 1;
|
|
|
|
break;
|
|
|
|
case SB_PAGEUP: // SB_PAGELEFT
|
|
|
|
command.mScroll.mUnit = nsContentCommandEvent::eCmdScrollUnit_Page;
|
|
|
|
command.mScroll.mAmount = -1;
|
|
|
|
break;
|
|
|
|
case SB_PAGEDOWN: // SB_PAGERIGHT
|
|
|
|
command.mScroll.mUnit = nsContentCommandEvent::eCmdScrollUnit_Page;
|
|
|
|
command.mScroll.mAmount = 1;
|
|
|
|
break;
|
|
|
|
case SB_TOP: // SB_LEFT
|
|
|
|
command.mScroll.mUnit = nsContentCommandEvent::eCmdScrollUnit_Whole;
|
|
|
|
command.mScroll.mAmount = -1;
|
|
|
|
break;
|
|
|
|
case SB_BOTTOM: // SB_RIGHT
|
|
|
|
command.mScroll.mUnit = nsContentCommandEvent::eCmdScrollUnit_Whole;
|
|
|
|
command.mScroll.mAmount = 1;
|
|
|
|
break;
|
|
|
|
default:
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2010-03-11 05:25:29 +00:00
|
|
|
}
|
2011-08-02 03:03:15 +00:00
|
|
|
// XXX If this is a plugin window, we should dispatch the event from
|
|
|
|
// parent window.
|
2010-03-11 05:25:29 +00:00
|
|
|
DispatchWindowEvent(&command);
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2004-09-03 08:44:23 +00:00
|
|
|
}
|
2001-04-14 00:57:30 +00:00
|
|
|
|
2011-08-02 03:03:15 +00:00
|
|
|
/**
|
|
|
|
* OnScrollInternal() is called when ProcessMessage() handles MOZ_WM_VSCROLL or
|
|
|
|
* MOZ_WM_HSCROLL but aMsg may be WM_VSCROLL or WM_HSCROLL.
|
|
|
|
* These internal messages used only when OnScroll() tries to emulate mouse
|
|
|
|
* wheel action for the WM_VSCROLL or WM_HSCROLL message.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
nsWindow::OnScrollInternal(UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
nsMouseScrollEvent scrollevent(true, NS_MOUSE_SCROLL, this);
|
2011-08-02 03:03:15 +00:00
|
|
|
scrollevent.scrollFlags = (aMsg == WM_VSCROLL)
|
|
|
|
? nsMouseScrollEvent::kIsVertical
|
|
|
|
: nsMouseScrollEvent::kIsHorizontal;
|
|
|
|
switch (LOWORD(aWParam)) {
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
scrollevent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
scrollevent.delta = 1;
|
|
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
|
|
scrollevent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
case SB_LINEUP:
|
|
|
|
scrollevent.delta = -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
scrollevent.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
scrollevent.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
2011-10-02 02:16:19 +00:00
|
|
|
scrollevent.isMeta = false;
|
2011-08-02 03:03:15 +00:00
|
|
|
scrollevent.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
InitEvent(scrollevent);
|
|
|
|
if (mEventCallback) {
|
|
|
|
DispatchWindowEvent(&scrollevent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-03 00:40:10 +00:00
|
|
|
// Can be overriden. Controls auto-erase of background.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::AutoErase(HDC dc)
|
1998-04-28 19:24:52 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
1998-04-28 19:24:52 +00:00
|
|
|
}
|
|
|
|
|
2010-12-07 02:06:31 +00:00
|
|
|
void
|
|
|
|
nsWindow::AllowD3D9Callback(nsWindow *aWindow)
|
|
|
|
{
|
|
|
|
if (aWindow->mLayerManager) {
|
|
|
|
aWindow->mLayerManager->Destroy();
|
|
|
|
aWindow->mLayerManager = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsWindow::AllowD3D9WithReinitializeCallback(nsWindow *aWindow)
|
|
|
|
{
|
|
|
|
if (aWindow->mLayerManager) {
|
|
|
|
aWindow->mLayerManager->Destroy();
|
|
|
|
aWindow->mLayerManager = NULL;
|
|
|
|
(void) aWindow->GetLayerManager();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsWindow::StartAllowingD3D9(bool aReinitialize)
|
|
|
|
{
|
|
|
|
sAllowD3D9 = true;
|
|
|
|
|
2011-01-12 20:13:41 +00:00
|
|
|
LayerManagerPrefs prefs;
|
|
|
|
GetLayerManagerPrefs(&prefs);
|
|
|
|
if (prefs.mDisableAcceleration) {
|
|
|
|
// The guarantee here is, if there's *any* chance that after we
|
|
|
|
// throw out our layer managers we'd create at least one new,
|
|
|
|
// accelerated one, we *will* throw out all the current layer
|
|
|
|
// managers. We early-return here because currently, if
|
|
|
|
// |disableAcceleration|, we will always use basic managers and
|
|
|
|
// it's a waste to recreate them.
|
|
|
|
//
|
|
|
|
// NB: the above implies that it's eminently possible for us to
|
|
|
|
// skip this early return but still recreate basic managers.
|
|
|
|
// That's OK. It's *not* OK to take this early return when we
|
|
|
|
// *might* have created an accelerated manager.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-07 02:06:31 +00:00
|
|
|
if (aReinitialize) {
|
|
|
|
EnumAllWindows(AllowD3D9WithReinitializeCallback);
|
|
|
|
} else {
|
|
|
|
EnumAllWindows(AllowD3D9Callback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-02 11:53:55 +00:00
|
|
|
bool
|
|
|
|
nsWindow::HasBogusPopupsDropShadowOnMultiMonitor() {
|
|
|
|
if (sHasBogusPopupsDropShadowOnMultiMonitor == TRI_UNKNOWN) {
|
|
|
|
// Since any change in the preferences requires a restart, this can be
|
|
|
|
// done just once.
|
|
|
|
// Check for Direct2D first.
|
|
|
|
sHasBogusPopupsDropShadowOnMultiMonitor =
|
|
|
|
gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
|
|
|
gfxWindowsPlatform::RENDER_DIRECT2D ? TRI_TRUE : TRI_FALSE;
|
|
|
|
if (!sHasBogusPopupsDropShadowOnMultiMonitor) {
|
|
|
|
// Otherwise check if Direct3D 9 may be used.
|
|
|
|
LayerManagerPrefs prefs;
|
|
|
|
GetLayerManagerPrefs(&prefs);
|
|
|
|
if (!prefs.mDisableAcceleration && !prefs.mPreferOpenGL) {
|
|
|
|
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
|
|
|
if (gfxInfo) {
|
|
|
|
PRInt32 status;
|
|
|
|
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
|
|
|
|
if (status == nsIGfxInfo::FEATURE_NO_INFO || prefs.mForceAcceleration)
|
|
|
|
{
|
|
|
|
sHasBogusPopupsDropShadowOnMultiMonitor = TRI_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !!sHasBogusPopupsDropShadowOnMultiMonitor;
|
|
|
|
}
|
|
|
|
|
2011-11-21 17:53:20 +00:00
|
|
|
void
|
|
|
|
nsWindow::OnSysColorChanged()
|
|
|
|
{
|
|
|
|
if (mWindowType == eWindowType_invisible) {
|
|
|
|
::EnumThreadWindows(GetCurrentThreadId(), nsWindow::BroadcastMsg, WM_SYSCOLORCHANGE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Note: This is sent for child windows as well as top-level windows.
|
|
|
|
// The Win32 toolkit normally only sends these events to top-level windows.
|
|
|
|
// But we cycle through all of the childwindows and send it to them as well
|
|
|
|
// so all presentations get notified properly.
|
|
|
|
// See nsWindow::GlobalMsgWindowProc.
|
|
|
|
DispatchStandardEvent(NS_SYSCOLORCHANGED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: IME management and accessibility
|
|
|
|
**
|
|
|
|
** Handles managing IME input and accessibility.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2009-03-04 09:09:09 +00:00
|
|
|
|
1999-11-15 20:57:41 +00:00
|
|
|
NS_IMETHODIMP nsWindow::ResetInputState()
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_KBSTATE
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("ResetInputState\n"));
|
2004-09-03 08:44:23 +00:00
|
|
|
#endif
|
2009-02-10 20:56:51 +00:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
2011-10-02 02:16:19 +00:00
|
|
|
nsTextStore::CommitComposition(false);
|
2009-02-10 20:56:51 +00:00
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2010-08-08 09:23:25 +00:00
|
|
|
nsIMM32Handler::CommitComposition(this);
|
2004-09-03 08:44:23 +00:00
|
|
|
return NS_OK;
|
1999-11-15 20:57:41 +00:00
|
|
|
}
|
2000-08-04 21:43:29 +00:00
|
|
|
|
2011-11-27 11:51:52 +00:00
|
|
|
NS_IMETHODIMP_(void)
|
|
|
|
nsWindow::SetInputContext(const InputContext& aContext,
|
|
|
|
const InputContextAction& aAction)
|
2005-08-23 14:32:09 +00:00
|
|
|
{
|
2009-02-10 20:56:51 +00:00
|
|
|
#ifdef NS_ENABLE_TSF
|
2011-11-27 11:51:52 +00:00
|
|
|
nsTextStore::SetInputContext(aContext);
|
2009-02-10 20:56:51 +00:00
|
|
|
#endif //NS_ENABLE_TSF
|
2010-08-08 09:23:25 +00:00
|
|
|
if (nsIMM32Handler::IsComposing()) {
|
2005-08-23 14:32:09 +00:00
|
|
|
ResetInputState();
|
2010-08-08 09:23:25 +00:00
|
|
|
}
|
2011-11-27 11:51:52 +00:00
|
|
|
mInputContext = aContext;
|
2011-11-27 11:51:53 +00:00
|
|
|
bool enable = (mInputContext.mIMEState.mEnabled == IMEState::ENABLED ||
|
|
|
|
mInputContext.mIMEState.mEnabled == IMEState::PLUGIN);
|
2009-02-20 07:03:46 +00:00
|
|
|
|
2011-07-07 12:02:07 +00:00
|
|
|
AssociateDefaultIMC(enable);
|
2011-11-27 11:51:53 +00:00
|
|
|
|
|
|
|
if (enable &&
|
|
|
|
mInputContext.mIMEState.mOpen != IMEState::DONT_CHANGE_OPEN_STATE) {
|
|
|
|
bool open = (mInputContext.mIMEState.mOpen == IMEState::OPEN);
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::SetIMEOpenState(open);
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
if (IMEContext.IsValid()) {
|
|
|
|
::ImmSetOpenStatus(IMEContext.get(), open);
|
|
|
|
}
|
|
|
|
}
|
2005-08-23 14:32:09 +00:00
|
|
|
}
|
|
|
|
|
2011-11-27 11:51:52 +00:00
|
|
|
NS_IMETHODIMP_(InputContext)
|
|
|
|
nsWindow::GetInputContext()
|
2005-08-23 14:32:09 +00:00
|
|
|
{
|
2011-11-27 11:51:53 +00:00
|
|
|
mInputContext.mIMEState.mOpen = IMEState::CLOSED;
|
|
|
|
switch (mInputContext.mIMEState.mEnabled) {
|
|
|
|
case IMEState::ENABLED:
|
|
|
|
case IMEState::PLUGIN: {
|
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
if (IMEContext.IsValid()) {
|
|
|
|
mInputContext.mIMEState.mOpen =
|
|
|
|
::ImmGetOpenStatus(IMEContext.get()) ? IMEState::OPEN :
|
|
|
|
IMEState::CLOSED;
|
|
|
|
}
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
if (mInputContext.mIMEState.mOpen == IMEState::CLOSED &&
|
|
|
|
nsTextStore::GetIMEOpenState()) {
|
|
|
|
mInputContext.mIMEState.mOpen = IMEState::OPEN;
|
|
|
|
}
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
}
|
|
|
|
}
|
2011-11-27 11:51:52 +00:00
|
|
|
return mInputContext;
|
2005-08-23 14:32:09 +00:00
|
|
|
}
|
|
|
|
|
2004-11-13 11:27:09 +00:00
|
|
|
NS_IMETHODIMP nsWindow::CancelIMEComposition()
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_KBSTATE
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("CancelIMEComposition\n"));
|
2004-11-13 11:27:09 +00:00
|
|
|
#endif
|
2009-02-10 20:56:51 +00:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
2011-10-02 02:16:19 +00:00
|
|
|
nsTextStore::CommitComposition(true);
|
2009-02-10 20:56:51 +00:00
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2010-08-08 09:23:25 +00:00
|
|
|
nsIMM32Handler::CancelComposition(this);
|
2004-11-13 11:27:09 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-06-16 19:19:46 +00:00
|
|
|
NS_IMETHODIMP
|
2011-09-29 06:19:26 +00:00
|
|
|
nsWindow::GetToggledKeyState(PRUint32 aKeyCode, bool* aLEDState)
|
2007-06-16 19:19:46 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_KBSTATE
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("GetToggledKeyState\n"));
|
2007-06-16 19:19:46 +00:00
|
|
|
#endif
|
|
|
|
NS_ENSURE_ARG_POINTER(aLEDState);
|
|
|
|
*aLEDState = (::GetKeyState(aKeyCode) & 1) != 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-08-04 21:43:29 +00:00
|
|
|
|
2009-02-10 20:56:51 +00:00
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 06:19:26 +00:00
|
|
|
nsWindow::OnIMEFocusChange(bool aFocus)
|
2009-02-10 20:56:51 +00:00
|
|
|
{
|
2011-11-27 11:51:52 +00:00
|
|
|
nsresult rv = nsTextStore::OnFocusChange(aFocus, this,
|
2011-11-27 11:51:53 +00:00
|
|
|
mInputContext.mIMEState.mEnabled);
|
2009-05-05 06:15:23 +00:00
|
|
|
if (rv == NS_ERROR_NOT_AVAILABLE)
|
2009-10-05 01:45:43 +00:00
|
|
|
rv = NS_ERROR_NOT_IMPLEMENTED; // TSF is not enabled, maybe.
|
2009-05-05 06:15:23 +00:00
|
|
|
return rv;
|
2009-02-10 20:56:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::OnIMETextChange(PRUint32 aStart,
|
|
|
|
PRUint32 aOldEnd,
|
|
|
|
PRUint32 aNewEnd)
|
|
|
|
{
|
|
|
|
return nsTextStore::OnTextChange(aStart, aOldEnd, aNewEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::OnIMESelectionChange(void)
|
|
|
|
{
|
|
|
|
return nsTextStore::OnSelectionChange();
|
|
|
|
}
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::AssociateDefaultIMC(bool aAssociate)
|
2011-07-07 12:02:07 +00:00
|
|
|
{
|
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
|
|
|
|
if (aAssociate) {
|
|
|
|
BOOL ret = ::ImmAssociateContextEx(mWnd, NULL, IACE_DEFAULT);
|
|
|
|
#ifdef DEBUG
|
|
|
|
// Note that if IME isn't available with current keyboard layout,
|
|
|
|
// IMM might not be installed on the system such as English Windows.
|
|
|
|
// On such system, IMM APIs always fail.
|
|
|
|
NS_ASSERTION(ret || !nsIMM32Handler::IsIMEAvailable(),
|
|
|
|
"ImmAssociateContextEx failed to restore default IMC");
|
|
|
|
if (ret) {
|
|
|
|
nsIMEContext newIMEContext(mWnd);
|
|
|
|
NS_ASSERTION(!IMEContext.get() || newIMEContext.get() == IMEContext.get(),
|
|
|
|
"Unknown IMC had been associated");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return ret && !IMEContext.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mOnDestroyCalled) {
|
|
|
|
// If OnDestroy() has been called, we shouldn't disassociate the default
|
|
|
|
// IMC at destroying the window.
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2011-07-07 12:02:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!IMEContext.get()) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return false; // already disassociated
|
2011-07-07 12:02:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ret = ::ImmAssociateContextEx(mWnd, NULL, 0);
|
|
|
|
NS_ASSERTION(ret, "ImmAssociateContextEx failed to disassociate the IMC");
|
|
|
|
return ret != FALSE;
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2010-07-21 04:12:08 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_WMGETOBJECT
|
|
|
|
#define NS_LOG_WMGETOBJECT_WNDACC(aWnd) \
|
|
|
|
nsAccessible* acc = aWnd ? \
|
|
|
|
aWnd->DispatchAccessibleEvent(NS_GETACCESSIBLE) : nsnull; \
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, (" acc: %p", acc)); \
|
2010-07-21 04:12:08 +00:00
|
|
|
if (acc) { \
|
|
|
|
nsAutoString name; \
|
|
|
|
acc->GetName(name); \
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, \
|
|
|
|
(", accname: %s", NS_ConvertUTF16toUTF8(name).get())); \
|
2010-07-21 04:12:08 +00:00
|
|
|
nsCOMPtr<nsIAccessibleDocument> doc = do_QueryObject(acc); \
|
|
|
|
void *hwnd = nsnull; \
|
|
|
|
doc->GetWindowHandle(&hwnd); \
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, (", acc hwnd: %d", hwnd)); \
|
2010-07-21 04:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define NS_LOG_WMGETOBJECT_THISWND \
|
|
|
|
{ \
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, \
|
|
|
|
("\n*******Get Doc Accessible*******\nOrig Window: ")); \
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, \
|
|
|
|
("\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n", \
|
|
|
|
mWnd, ::GetParent(mWnd), this)); \
|
2010-07-21 04:12:08 +00:00
|
|
|
NS_LOG_WMGETOBJECT_WNDACC(this) \
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("\n }\n")); \
|
2010-07-21 04:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd) \
|
|
|
|
{ \
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow* wnd = WinUtils::GetNSWindowPtr(aHwnd); \
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, \
|
|
|
|
("Get " aMsg ":\n {\n HWND: %d, parent HWND: %d, wndobj: %p,\n", \
|
|
|
|
aHwnd, ::GetParent(aHwnd), wnd)); \
|
2010-07-21 04:12:08 +00:00
|
|
|
NS_LOG_WMGETOBJECT_WNDACC(wnd); \
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("\n }\n")); \
|
2010-07-21 04:12:08 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define NS_LOG_WMGETOBJECT_THISWND
|
|
|
|
#define NS_LOG_WMGETOBJECT_WND(aMsg, aHwnd)
|
|
|
|
#endif // DEBUG_WMGETOBJECT
|
|
|
|
|
2010-05-12 06:47:35 +00:00
|
|
|
nsAccessible*
|
|
|
|
nsWindow::GetRootAccessible()
|
2004-09-03 08:44:23 +00:00
|
|
|
{
|
2010-03-09 21:02:25 +00:00
|
|
|
// We want the ability to forcibly disable a11y on windows, because
|
|
|
|
// some non-a11y-related components attempt to bring it up. See bug
|
|
|
|
// 538530 for details; we have a pref here that allows it to be disabled
|
|
|
|
// for performance and testing resons.
|
|
|
|
//
|
|
|
|
// This pref is checked only once, and the browser needs a restart to
|
|
|
|
// pick up any changes.
|
|
|
|
static int accForceDisable = -1;
|
|
|
|
|
|
|
|
if (accForceDisable == -1) {
|
2011-05-28 07:03:00 +00:00
|
|
|
const char* kPrefName = "accessibility.win32.force_disabled";
|
2011-09-29 06:19:26 +00:00
|
|
|
if (Preferences::GetBool(kPrefName, false)) {
|
2010-03-09 21:02:25 +00:00
|
|
|
accForceDisable = 1;
|
|
|
|
} else {
|
|
|
|
accForceDisable = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the pref was true, return null here, disabling a11y.
|
|
|
|
if (accForceDisable)
|
|
|
|
return nsnull;
|
|
|
|
|
2009-07-13 15:58:19 +00:00
|
|
|
if (mInDtor || mOnDestroyCalled || mWindowType == eWindowType_invisible) {
|
2009-06-29 19:36:16 +00:00
|
|
|
return nsnull;
|
|
|
|
}
|
2004-02-11 03:46:30 +00:00
|
|
|
|
2010-07-21 04:12:08 +00:00
|
|
|
NS_LOG_WMGETOBJECT_THISWND
|
2010-09-15 20:55:51 +00:00
|
|
|
NS_LOG_WMGETOBJECT_WND("This Window", mWnd);
|
2010-07-21 04:12:08 +00:00
|
|
|
|
2010-09-23 03:35:39 +00:00
|
|
|
return DispatchAccessibleEvent(NS_GETACCESSIBLE);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2009-03-27 01:10:52 +00:00
|
|
|
#endif
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Transparency
|
|
|
|
**
|
|
|
|
** Window transparency helpers.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight, bool force)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
if (!force && aNewWidth == mBounds.width && aNewHeight == mBounds.height)
|
|
|
|
return;
|
|
|
|
|
2010-06-22 06:40:00 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
2010-06-22 01:10:36 +00:00
|
|
|
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
|
|
|
gfxWindowsPlatform::RENDER_DIRECT2D) {
|
|
|
|
nsRefPtr<gfxD2DSurface> newSurface =
|
|
|
|
new gfxD2DSurface(gfxIntSize(aNewWidth, aNewHeight), gfxASurface::ImageFormatARGB32);
|
|
|
|
mTransparentSurface = newSurface;
|
|
|
|
mMemoryDC = nsnull;
|
2010-06-22 06:40:00 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2010-06-22 01:10:36 +00:00
|
|
|
nsRefPtr<gfxWindowsSurface> newSurface =
|
|
|
|
new gfxWindowsSurface(gfxIntSize(aNewWidth, aNewHeight), gfxASurface::ImageFormatARGB32);
|
|
|
|
mTransparentSurface = newSurface;
|
|
|
|
mMemoryDC = newSurface->GetDC();
|
|
|
|
}
|
1999-12-10 07:20:51 +00:00
|
|
|
}
|
2001-05-25 10:53:32 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode)
|
2009-03-27 00:15:41 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (aMode == mTransparencyMode)
|
|
|
|
return;
|
|
|
|
|
2010-06-28 06:04:20 +00:00
|
|
|
// stop on dialogs and popups!
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND hWnd = WinUtils::GetTopLevelHWND(mWnd, true);
|
|
|
|
nsWindow* parent = WinUtils::GetNSWindowPtr(hWnd);
|
2009-06-29 19:36:16 +00:00
|
|
|
|
2010-06-28 06:04:20 +00:00
|
|
|
if (!parent)
|
2009-06-29 19:36:16 +00:00
|
|
|
{
|
|
|
|
NS_WARNING("Trying to use transparent chrome in an embedded context");
|
|
|
|
return;
|
2009-03-27 00:15:41 +00:00
|
|
|
}
|
|
|
|
|
2010-06-28 06:04:20 +00:00
|
|
|
if (parent != this) {
|
|
|
|
NS_WARNING("Setting SetWindowTranslucencyInner on a parent this is not us!");
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
|
2010-06-25 17:56:39 +00:00
|
|
|
if (aMode == eTransparencyTransparent) {
|
2010-06-28 06:04:20 +00:00
|
|
|
// If we're switching to the use of a transparent window, hide the chrome
|
|
|
|
// on our parent.
|
2011-10-02 02:16:19 +00:00
|
|
|
HideWindowChrome(true);
|
2010-06-28 06:04:20 +00:00
|
|
|
} else if (mHideChrome && mTransparencyMode == eTransparencyTransparent) {
|
|
|
|
// if we're switching out of transparent, re-enable our parent's chrome.
|
2011-10-02 02:16:19 +00:00
|
|
|
HideWindowChrome(false);
|
2010-06-25 17:56:39 +00:00
|
|
|
}
|
|
|
|
|
2010-06-28 06:04:20 +00:00
|
|
|
LONG_PTR style = ::GetWindowLongPtrW(hWnd, GWL_STYLE),
|
|
|
|
exStyle = ::GetWindowLongPtr(hWnd, GWL_EXSTYLE);
|
|
|
|
|
|
|
|
if (parent->mIsVisible)
|
|
|
|
style |= WS_VISIBLE;
|
|
|
|
if (parent->mSizeMode == nsSizeMode_Maximized)
|
|
|
|
style |= WS_MAXIMIZE;
|
|
|
|
else if (parent->mSizeMode == nsSizeMode_Minimized)
|
|
|
|
style |= WS_MINIMIZE;
|
|
|
|
|
|
|
|
if (aMode == eTransparencyTransparent)
|
|
|
|
exStyle |= WS_EX_LAYERED;
|
|
|
|
else
|
|
|
|
exStyle &= ~WS_EX_LAYERED;
|
2010-06-25 17:56:39 +00:00
|
|
|
|
|
|
|
VERIFY_WINDOW_STYLE(style);
|
|
|
|
::SetWindowLongPtrW(hWnd, GWL_STYLE, style);
|
|
|
|
::SetWindowLongPtrW(hWnd, GWL_EXSTYLE, exStyle);
|
2009-06-29 19:36:16 +00:00
|
|
|
|
2010-06-17 11:25:11 +00:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2010-08-18 03:07:10 +00:00
|
|
|
if (HasGlass())
|
2010-05-27 09:00:04 +00:00
|
|
|
memset(&mGlassMargins, 0, sizeof mGlassMargins);
|
2010-06-17 11:25:11 +00:00
|
|
|
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2009-06-29 19:36:16 +00:00
|
|
|
mTransparencyMode = aMode;
|
|
|
|
|
|
|
|
SetupTranslucentWindowMemoryBitmap(aMode);
|
2010-03-17 22:56:00 +00:00
|
|
|
UpdateGlass();
|
2009-03-27 00:15:41 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
void nsWindow::SetupTranslucentWindowMemoryBitmap(nsTransparencyMode aMode)
|
2009-04-21 23:53:52 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (eTransparencyTransparent == aMode) {
|
2011-10-02 02:16:19 +00:00
|
|
|
ResizeTranslucentWindow(mBounds.width, mBounds.height, true);
|
2009-06-29 19:36:16 +00:00
|
|
|
} else {
|
|
|
|
mTransparentSurface = nsnull;
|
|
|
|
mMemoryDC = NULL;
|
|
|
|
}
|
2009-04-21 23:53:52 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
nsresult nsWindow::UpdateTranslucentWindow()
|
|
|
|
{
|
|
|
|
if (mBounds.IsEmpty())
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
::GdiFlush();
|
|
|
|
|
|
|
|
BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
|
|
|
|
SIZE winSize = { mBounds.width, mBounds.height };
|
|
|
|
POINT srcPos = { 0, 0 };
|
2012-01-04 10:21:44 +00:00
|
|
|
HWND hWnd = WinUtils::GetTopLevelHWND(mWnd, true);
|
2009-06-29 19:36:16 +00:00
|
|
|
RECT winRect;
|
|
|
|
::GetWindowRect(hWnd, &winRect);
|
|
|
|
|
2010-06-22 06:40:00 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
2010-06-22 01:10:36 +00:00
|
|
|
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
|
|
|
gfxWindowsPlatform::RENDER_DIRECT2D) {
|
|
|
|
mMemoryDC = static_cast<gfxD2DSurface*>(mTransparentSurface.get())->
|
2011-10-02 02:16:19 +00:00
|
|
|
GetDC(true);
|
2010-06-22 01:10:36 +00:00
|
|
|
}
|
2010-06-22 06:40:00 +00:00
|
|
|
#endif
|
2009-06-29 19:36:16 +00:00
|
|
|
// perform the alpha blend
|
2011-09-29 06:19:26 +00:00
|
|
|
bool updateSuccesful =
|
2010-06-22 01:10:36 +00:00
|
|
|
::UpdateLayeredWindow(hWnd, NULL, (POINT*)&winRect, &winSize, mMemoryDC, &srcPos, 0, &bf, ULW_ALPHA);
|
|
|
|
|
2010-06-22 06:40:00 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
2010-06-22 01:10:36 +00:00
|
|
|
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
|
|
|
|
gfxWindowsPlatform::RENDER_DIRECT2D) {
|
|
|
|
nsIntRect r(0, 0, 0, 0);
|
|
|
|
static_cast<gfxD2DSurface*>(mTransparentSurface.get())->ReleaseDC(&r);
|
|
|
|
}
|
2010-06-22 06:40:00 +00:00
|
|
|
#endif
|
2010-06-22 01:10:36 +00:00
|
|
|
|
|
|
|
if (!updateSuccesful) {
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2010-06-22 01:10:36 +00:00
|
|
|
}
|
2001-05-25 10:53:32 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //MOZ_XUL
|
2001-05-25 10:53:32 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Popup rollup hooks
|
|
|
|
**
|
|
|
|
** Deals with CaptureRollup on popup windows.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2005-02-23 07:07:51 +00:00
|
|
|
|
2004-09-03 08:44:23 +00:00
|
|
|
// Schedules a timer for a window, so we can rollup after processing the hook event
|
2001-06-14 02:08:39 +00:00
|
|
|
void nsWindow::ScheduleHookTimer(HWND aWnd, UINT aMsgId)
|
|
|
|
{
|
2004-09-03 08:44:23 +00:00
|
|
|
// In some cases multiple hooks may be scheduled
|
2001-06-14 02:08:39 +00:00
|
|
|
// so ignore any other requests once one timer is scheduled
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sHookTimerId == 0) {
|
2005-01-14 19:23:06 +00:00
|
|
|
// Remember the window handle and the message ID to be used later
|
2009-06-29 19:36:16 +00:00
|
|
|
sRollupMsgId = aMsgId;
|
|
|
|
sRollupMsgWnd = aWnd;
|
2004-09-03 08:44:23 +00:00
|
|
|
// Schedule native timer for doing the rollup after
|
2001-06-14 02:08:39 +00:00
|
|
|
// this event is done being processed
|
2009-06-29 19:36:16 +00:00
|
|
|
sHookTimerId = ::SetTimer(NULL, 0, 0, (TIMERPROC)HookTimerForPopups);
|
|
|
|
NS_ASSERTION(sHookTimerId, "Timer couldn't be created.");
|
2001-06-14 02:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
int gLastMsgCode = 0;
|
|
|
|
extern MSGFEventMsgInfo gMSGFEvents[];
|
|
|
|
#endif
|
2005-02-23 07:07:51 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Process Menu messages, rollup when popup is clicked.
|
2001-05-25 10:53:32 +00:00
|
|
|
LRESULT CALLBACK nsWindow::MozSpecialMsgFilter(int code, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (sProcessHook) {
|
2001-05-25 10:53:32 +00:00
|
|
|
MSG* pMsg = (MSG*)lParam;
|
|
|
|
|
|
|
|
int inx = 0;
|
|
|
|
while (gMSGFEvents[inx].mId != code && gMSGFEvents[inx].mStr != NULL) {
|
|
|
|
inx++;
|
|
|
|
}
|
|
|
|
if (code != gLastMsgCode) {
|
|
|
|
if (gMSGFEvents[inx].mId == code) {
|
2001-06-20 05:48:45 +00:00
|
|
|
#ifdef DEBUG
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("MozSpecialMessageProc - code: 0x%X - %s hw: %p\n",
|
|
|
|
code, gMSGFEvents[inx].mStr, pMsg->hwnd));
|
2001-06-20 05:48:45 +00:00
|
|
|
#endif
|
2001-05-25 10:53:32 +00:00
|
|
|
} else {
|
2001-06-20 05:48:45 +00:00
|
|
|
#ifdef DEBUG
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("MozSpecialMessageProc - code: 0x%X - %d hw: %p\n",
|
|
|
|
code, gMSGFEvents[inx].mId, pMsg->hwnd));
|
2001-06-20 05:48:45 +00:00
|
|
|
#endif
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
gLastMsgCode = code;
|
|
|
|
}
|
|
|
|
PrintEvent(pMsg->message, FALSE, FALSE);
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
#endif // #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
2001-05-25 10:53:32 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sProcessHook && code == MSGF_MENU) {
|
2001-05-25 10:53:32 +00:00
|
|
|
MSG* pMsg = (MSG*)lParam;
|
2001-06-14 02:08:39 +00:00
|
|
|
ScheduleHookTimer( pMsg->hwnd, pMsg->message);
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return ::CallNextHookEx(sMsgFilterHook, code, wParam, lParam);
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Process all mouse messages. Roll up when a click is in a native window
|
|
|
|
// that doesn't have an nsIWidget.
|
2001-05-25 10:53:32 +00:00
|
|
|
LRESULT CALLBACK nsWindow::MozSpecialMouseProc(int code, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sProcessHook) {
|
2012-01-04 10:21:44 +00:00
|
|
|
switch (WinUtils::GetNativeMessage(wParam)) {
|
2008-11-27 05:42:18 +00:00
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
case WM_MOUSEHWHEEL:
|
|
|
|
{
|
|
|
|
MOUSEHOOKSTRUCT* ms = (MOUSEHOOKSTRUCT*)lParam;
|
2012-01-04 10:21:44 +00:00
|
|
|
nsIWidget* mozWin = WinUtils::GetNSWindowPtr(ms->hwnd);
|
2008-11-27 05:42:18 +00:00
|
|
|
if (mozWin) {
|
|
|
|
// If this window is windowed plugin window, the mouse events are not
|
|
|
|
// sent to us.
|
2009-09-24 09:32:20 +00:00
|
|
|
if (static_cast<nsWindow*>(mozWin)->mWindowType == eWindowType_plugin)
|
2008-11-27 05:42:18 +00:00
|
|
|
ScheduleHookTimer(ms->hwnd, (UINT)wParam);
|
|
|
|
} else {
|
|
|
|
ScheduleHookTimer(ms->hwnd, (UINT)wParam);
|
|
|
|
}
|
|
|
|
break;
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return ::CallNextHookEx(sCallMouseHook, code, wParam, lParam);
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Process all messages. Roll up when the window is moving, or
|
|
|
|
// is resizing or when maximized or mininized.
|
2001-05-25 10:53:32 +00:00
|
|
|
LRESULT CALLBACK nsWindow::MozSpecialWndProc(int code, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (sProcessHook) {
|
2001-05-25 10:53:32 +00:00
|
|
|
CWPSTRUCT* cwpt = (CWPSTRUCT*)lParam;
|
|
|
|
PrintEvent(cwpt->message, FALSE, FALSE);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sProcessHook) {
|
2001-05-25 10:53:32 +00:00
|
|
|
CWPSTRUCT* cwpt = (CWPSTRUCT*)lParam;
|
2004-09-03 08:44:23 +00:00
|
|
|
if (cwpt->message == WM_MOVING ||
|
|
|
|
cwpt->message == WM_SIZING ||
|
2001-05-25 10:53:32 +00:00
|
|
|
cwpt->message == WM_GETMINMAXINFO) {
|
2004-09-03 08:44:23 +00:00
|
|
|
ScheduleHookTimer(cwpt->hwnd, (UINT)cwpt->message);
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
return ::CallNextHookEx(sCallProcHook, code, wParam, lParam);
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Register the special "hooks" for dropdown processing.
|
2001-05-25 10:53:32 +00:00
|
|
|
void nsWindow::RegisterSpecialDropdownHooks()
|
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
NS_ASSERTION(!sMsgFilterHook, "sMsgFilterHook must be NULL!");
|
|
|
|
NS_ASSERTION(!sCallProcHook, "sCallProcHook must be NULL!");
|
2001-05-25 10:53:32 +00:00
|
|
|
|
|
|
|
DISPLAY_NMM_PRT("***************** Installing Msg Hooks ***************\n");
|
|
|
|
|
|
|
|
// Install msg hook for moving the window and resizing
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!sMsgFilterHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Hooking sMsgFilterHook!\n");
|
|
|
|
sMsgFilterHook = SetWindowsHookEx(WH_MSGFILTER, MozSpecialMsgFilter, NULL, GetCurrentThreadId());
|
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (!sMsgFilterHook) {
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("***** SetWindowsHookEx is NOT installed for WH_MSGFILTER!\n"));
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Install msg hook for menus
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!sCallProcHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Hooking sCallProcHook!\n");
|
|
|
|
sCallProcHook = SetWindowsHookEx(WH_CALLWNDPROC, MozSpecialWndProc, NULL, GetCurrentThreadId());
|
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (!sCallProcHook) {
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("***** SetWindowsHookEx is NOT installed for WH_CALLWNDPROC!\n"));
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Install msg hook for the mouse
|
2009-06-29 19:36:16 +00:00
|
|
|
if (!sCallMouseHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Hooking sCallMouseHook!\n");
|
|
|
|
sCallMouseHook = SetWindowsHookEx(WH_MOUSE, MozSpecialMouseProc, NULL, GetCurrentThreadId());
|
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (!sCallMouseHook) {
|
2011-08-16 19:30:44 +00:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("***** SetWindowsHookEx is NOT installed for WH_MOUSE!\n"));
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Unhook special message hooks for dropdowns.
|
2001-05-25 10:53:32 +00:00
|
|
|
void nsWindow::UnregisterSpecialDropdownHooks()
|
|
|
|
{
|
|
|
|
DISPLAY_NMM_PRT("***************** De-installing Msg Hooks ***************\n");
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sCallProcHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Unhooking sCallProcHook!\n");
|
|
|
|
if (!::UnhookWindowsHookEx(sCallProcHook)) {
|
|
|
|
DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallProcHook!\n");
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
sCallProcHook = NULL;
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sMsgFilterHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Unhooking sMsgFilterHook!\n");
|
|
|
|
if (!::UnhookWindowsHookEx(sMsgFilterHook)) {
|
|
|
|
DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sMsgFilterHook!\n");
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
sMsgFilterHook = NULL;
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sCallMouseHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Unhooking sCallMouseHook!\n");
|
|
|
|
if (!::UnhookWindowsHookEx(sCallMouseHook)) {
|
|
|
|
DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallMouseHook!\n");
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
sCallMouseHook = NULL;
|
2001-05-25 10:53:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-14 02:08:39 +00:00
|
|
|
// This timer is designed to only fire one time at most each time a "hook" function
|
2009-06-29 19:36:16 +00:00
|
|
|
// is used to rollup the dropdown. In some cases, the timer may be scheduled from the
|
|
|
|
// hook, but that hook event or a subsequent event may roll up the dropdown before
|
|
|
|
// this timer function is executed.
|
2001-06-14 02:08:39 +00:00
|
|
|
//
|
|
|
|
// For example, if an MFC control takes focus, the combobox will lose focus and rollup
|
|
|
|
// before this function fires.
|
2004-09-03 08:44:23 +00:00
|
|
|
VOID CALLBACK nsWindow::HookTimerForPopups(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
|
2001-06-14 02:08:39 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sHookTimerId != 0) {
|
2001-06-14 02:08:39 +00:00
|
|
|
// if the window is NULL then we need to use the ID to kill the timer
|
2009-06-29 19:36:16 +00:00
|
|
|
BOOL status = ::KillTimer(NULL, sHookTimerId);
|
2001-06-14 02:08:39 +00:00
|
|
|
NS_ASSERTION(status, "Hook Timer was not killed.");
|
2009-06-29 19:36:16 +00:00
|
|
|
sHookTimerId = 0;
|
2001-06-14 02:08:39 +00:00
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sRollupMsgId != 0) {
|
2004-09-03 08:44:23 +00:00
|
|
|
// Note: DealWithPopups does the check to make sure that
|
2009-06-29 19:36:16 +00:00
|
|
|
// sRollupListener and sRollupWidget are not NULL
|
2001-06-14 02:08:39 +00:00
|
|
|
LRESULT popupHandlingResult;
|
2007-12-03 16:33:42 +00:00
|
|
|
nsAutoRollup autoRollup;
|
2009-06-29 19:36:16 +00:00
|
|
|
DealWithPopups(sRollupMsgWnd, sRollupMsgId, 0, 0, &popupHandlingResult);
|
|
|
|
sRollupMsgId = 0;
|
|
|
|
sRollupMsgWnd = NULL;
|
2001-06-14 02:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
2005-06-29 18:52:08 +00:00
|
|
|
|
2010-08-20 03:40:51 +00:00
|
|
|
BOOL CALLBACK nsWindow::ClearResourcesCallback(HWND aWnd, LPARAM aMsg)
|
2010-08-14 06:34:13 +00:00
|
|
|
{
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow *window = WinUtils::GetNSWindowPtr(aWnd);
|
2010-08-14 06:34:13 +00:00
|
|
|
if (window) {
|
2010-08-20 03:40:51 +00:00
|
|
|
window->ClearCachedResources();
|
2010-08-14 06:34:13 +00:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-08-20 03:40:51 +00:00
|
|
|
nsWindow::ClearCachedResources()
|
2010-08-14 06:34:13 +00:00
|
|
|
{
|
2010-08-20 03:40:51 +00:00
|
|
|
#ifdef CAIRO_HAS_D2D_SURFACE
|
2010-08-14 06:34:13 +00:00
|
|
|
mD2DWindowSurface = nsnull;
|
2010-08-20 03:40:51 +00:00
|
|
|
#endif
|
|
|
|
if (mLayerManager &&
|
|
|
|
mLayerManager->GetBackendType() == LayerManager::LAYERS_BASIC) {
|
|
|
|
static_cast<BasicLayerManager*>(mLayerManager.get())->
|
|
|
|
ClearCachedResources();
|
2010-08-14 06:34:13 +00:00
|
|
|
}
|
2011-01-28 10:33:47 +00:00
|
|
|
::EnumChildWindows(mWnd, nsWindow::ClearResourcesCallback, 0);
|
2010-08-14 06:34:13 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool IsDifferentThreadWindow(HWND aWnd)
|
2008-11-27 05:42:18 +00:00
|
|
|
{
|
|
|
|
return ::GetCurrentThreadId() != ::GetWindowThreadProcessId(aWnd, NULL);
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2009-06-29 19:36:16 +00:00
|
|
|
nsWindow::EventIsInsideWindow(UINT Msg, nsWindow* aWindow)
|
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
|
|
|
|
if (Msg == WM_ACTIVATEAPP)
|
|
|
|
// don't care about activation/deactivation
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2009-06-29 19:36:16 +00:00
|
|
|
|
|
|
|
::GetWindowRect(aWindow->mWnd, &r);
|
|
|
|
DWORD pos = ::GetMessagePos();
|
|
|
|
POINT mp;
|
|
|
|
mp.x = GET_X_LPARAM(pos);
|
|
|
|
mp.y = GET_Y_LPARAM(pos);
|
|
|
|
|
|
|
|
// was the event inside this window?
|
2011-09-29 06:19:26 +00:00
|
|
|
return (bool) PtInRect(&r, mp);
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2005-06-08 16:48:44 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
|
2005-06-08 16:48:44 +00:00
|
|
|
BOOL
|
2009-06-29 19:36:16 +00:00
|
|
|
nsWindow::DealWithPopups(HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inLParam, LRESULT* outResult)
|
2005-06-08 16:48:44 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
if (sRollupListener && sRollupWidget && ::IsWindowVisible(inWnd)) {
|
2005-06-08 16:48:44 +00:00
|
|
|
|
2012-01-04 10:21:44 +00:00
|
|
|
inMsg = WinUtils::GetNativeMessage(inMsg);
|
2005-08-16 19:15:06 +00:00
|
|
|
if (inMsg == WM_LBUTTONDOWN || inMsg == WM_RBUTTONDOWN || inMsg == WM_MBUTTONDOWN ||
|
2008-11-27 05:42:18 +00:00
|
|
|
inMsg == WM_MOUSEWHEEL || inMsg == WM_MOUSEHWHEEL || inMsg == WM_ACTIVATE ||
|
2011-04-25 03:10:12 +00:00
|
|
|
(inMsg == WM_KILLFOCUS && IsDifferentThreadWindow((HWND)inWParam)) ||
|
2009-06-29 19:36:16 +00:00
|
|
|
inMsg == WM_NCRBUTTONDOWN ||
|
|
|
|
inMsg == WM_MOVING ||
|
|
|
|
inMsg == WM_SIZING ||
|
|
|
|
inMsg == WM_NCLBUTTONDOWN ||
|
2005-06-08 16:48:44 +00:00
|
|
|
inMsg == WM_NCMBUTTONDOWN ||
|
|
|
|
inMsg == WM_MOUSEACTIVATE ||
|
|
|
|
inMsg == WM_ACTIVATEAPP ||
|
2011-04-25 03:10:12 +00:00
|
|
|
inMsg == WM_MENUSELECT)
|
2005-06-08 16:48:44 +00:00
|
|
|
{
|
|
|
|
// Rollup if the event is outside the popup.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool rollup = !nsWindow::EventIsInsideWindow(inMsg, (nsWindow*)sRollupWidget);
|
2005-06-08 16:48:44 +00:00
|
|
|
|
2006-09-08 06:04:44 +00:00
|
|
|
if (rollup && (inMsg == WM_MOUSEWHEEL || inMsg == WM_MOUSEHWHEEL))
|
2005-06-08 16:48:44 +00:00
|
|
|
{
|
2011-11-08 19:59:07 +00:00
|
|
|
rollup = sRollupListener->ShouldRollupOnMouseWheelEvent();
|
2011-10-02 02:16:19 +00:00
|
|
|
*outResult = true;
|
2005-06-08 16:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we're dealing with menus, we probably have submenus and we don't
|
|
|
|
// want to rollup if the click is in a parent menu of the current submenu.
|
2009-06-12 18:23:16 +00:00
|
|
|
PRUint32 popupsToRollup = PR_UINT32_MAX;
|
2005-06-08 16:48:44 +00:00
|
|
|
if (rollup) {
|
2011-11-08 19:59:07 +00:00
|
|
|
if ( sRollupListener ) {
|
2008-01-17 06:57:13 +00:00
|
|
|
nsAutoTArray<nsIWidget*, 5> widgetChain;
|
2011-11-08 19:59:07 +00:00
|
|
|
PRUint32 sameTypeCount = sRollupListener->GetSubmenuWidgetChain(&widgetChain);
|
2008-01-17 06:57:13 +00:00
|
|
|
for ( PRUint32 i = 0; i < widgetChain.Length(); ++i ) {
|
|
|
|
nsIWidget* widget = widgetChain[i];
|
|
|
|
if ( nsWindow::EventIsInsideWindow(inMsg, (nsWindow*)widget) ) {
|
2010-05-13 12:19:50 +00:00
|
|
|
// don't roll up if the mouse event occurred within a menu of the
|
|
|
|
// same type. If the mouse event occurred in a menu higher than
|
2009-06-12 18:23:16 +00:00
|
|
|
// that, roll up, but pass the number of popups to Rollup so
|
|
|
|
// that only those of the same type close up.
|
|
|
|
if (i < sameTypeCount) {
|
2011-10-02 02:16:19 +00:00
|
|
|
rollup = false;
|
2009-06-12 18:23:16 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
popupsToRollup = sameTypeCount;
|
|
|
|
}
|
2008-01-17 06:57:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} // foreach parent menu widget
|
2005-06-08 16:48:44 +00:00
|
|
|
} // if rollup listener knows about menus
|
|
|
|
}
|
|
|
|
|
2009-06-12 18:23:16 +00:00
|
|
|
if (inMsg == WM_MOUSEACTIVATE && popupsToRollup == PR_UINT32_MAX) {
|
2005-06-08 16:48:44 +00:00
|
|
|
// Prevent the click inside the popup from causing a change in window
|
|
|
|
// activation. Since the popup is shown non-activated, we need to eat
|
|
|
|
// any requests to activate the window while it is displayed. Windows
|
|
|
|
// will automatically activate the popup on the mousedown otherwise.
|
|
|
|
if (!rollup) {
|
|
|
|
*outResult = MA_NOACTIVATE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UINT uMsg = HIWORD(inLParam);
|
|
|
|
if (uMsg == WM_MOUSEMOVE)
|
|
|
|
{
|
|
|
|
// WM_MOUSEACTIVATE cause by moving the mouse - X-mouse (eg. TweakUI)
|
|
|
|
// must be enabled in Windows.
|
2011-11-08 19:59:07 +00:00
|
|
|
rollup = sRollupListener->ShouldRollupOnMouseActivate();
|
2005-06-08 16:48:44 +00:00
|
|
|
if (!rollup)
|
|
|
|
{
|
|
|
|
*outResult = MA_NOACTIVATE;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if we've still determined that we should still rollup everything, do it.
|
2011-04-25 03:10:12 +00:00
|
|
|
else if (rollup) {
|
2009-06-29 19:36:16 +00:00
|
|
|
// sRollupConsumeEvent may be modified by
|
2008-11-18 06:15:24 +00:00
|
|
|
// nsIRollupListener::Rollup.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool consumeRollupEvent = sRollupConsumeEvent;
|
2007-12-03 16:33:42 +00:00
|
|
|
// only need to deal with the last rollup for left mouse down events.
|
2011-11-08 19:59:07 +00:00
|
|
|
NS_ASSERTION(!mLastRollup, "mLastRollup is null");
|
|
|
|
mLastRollup = sRollupListener->Rollup(popupsToRollup, inMsg == WM_LBUTTONDOWN);
|
|
|
|
NS_IF_ADDREF(mLastRollup);
|
2005-06-08 16:48:44 +00:00
|
|
|
|
|
|
|
// Tell hook to stop processing messages
|
2011-10-02 02:16:19 +00:00
|
|
|
sProcessHook = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
sRollupMsgId = 0;
|
|
|
|
sRollupMsgWnd = NULL;
|
2005-06-08 16:48:44 +00:00
|
|
|
|
|
|
|
// return TRUE tells Windows that the event is consumed,
|
|
|
|
// false allows the event to be dispatched
|
|
|
|
//
|
|
|
|
// So if we are NOT supposed to be consuming events, let it go through
|
2008-11-18 06:15:24 +00:00
|
|
|
if (consumeRollupEvent && inMsg != WM_RBUTTONDOWN) {
|
2010-11-24 18:31:24 +00:00
|
|
|
*outResult = MA_ACTIVATE;
|
|
|
|
|
|
|
|
// However, don't activate panels
|
|
|
|
if (inMsg == WM_MOUSEACTIVATE) {
|
2012-01-04 10:21:44 +00:00
|
|
|
nsWindow* activateWindow = WinUtils::GetNSWindowPtr(inWnd);
|
2010-11-24 18:31:24 +00:00
|
|
|
if (activateWindow) {
|
|
|
|
nsWindowType wintype;
|
|
|
|
activateWindow->GetWindowType(wintype);
|
|
|
|
if (wintype == eWindowType_popup && activateWindow->PopupType() == ePopupTypePanel) {
|
|
|
|
*outResult = MA_NOACTIVATE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-06-08 16:48:44 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2009-06-12 18:23:16 +00:00
|
|
|
// if we are only rolling up some popups, don't activate and don't let
|
|
|
|
// the event go through. This prevents clicks menus higher in the
|
|
|
|
// chain from opening when a context menu is open
|
|
|
|
if (popupsToRollup != PR_UINT32_MAX && inMsg == WM_MOUSEACTIVATE) {
|
|
|
|
*outResult = MA_NOACTIVATEANDEAT;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2005-06-08 16:48:44 +00:00
|
|
|
}
|
|
|
|
} // if event that might trigger a popup to rollup
|
|
|
|
} // if rollup listeners registered
|
|
|
|
|
|
|
|
return FALSE;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2001-09-25 08:34:42 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Misc. utility methods and functions.
|
|
|
|
**
|
|
|
|
** General use.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2001-09-25 08:34:42 +00:00
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// nsModifierKeyState used in various character processing.
|
|
|
|
nsModifierKeyState::nsModifierKeyState()
|
2001-09-25 08:34:42 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
mIsShiftDown = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
mIsControlDown = IS_VK_DOWN(NS_VK_CONTROL);
|
|
|
|
mIsAltDown = IS_VK_DOWN(NS_VK_ALT);
|
2001-09-25 08:34:42 +00:00
|
|
|
}
|
2003-04-01 20:02:51 +00:00
|
|
|
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
// Note that the result of GetTopLevelWindow method can be different from the
|
2012-01-04 10:21:44 +00:00
|
|
|
// result of WinUtils::GetTopLevelHWND(). The result can be non-floating
|
|
|
|
// window. Because our top level window may be contained in another window
|
|
|
|
// which is not managed by us.
|
2011-09-29 06:19:26 +00:00
|
|
|
nsWindow* nsWindow::GetTopLevelWindow(bool aStopOnDialogOrPopup)
|
2004-07-27 19:14:44 +00:00
|
|
|
{
|
2004-12-09 17:56:46 +00:00
|
|
|
nsWindow* curWindow = this;
|
2004-07-27 19:14:44 +00:00
|
|
|
|
2011-10-02 02:16:19 +00:00
|
|
|
while (true) {
|
2008-09-09 17:22:12 +00:00
|
|
|
if (aStopOnDialogOrPopup) {
|
|
|
|
switch (curWindow->mWindowType) {
|
|
|
|
case eWindowType_dialog:
|
|
|
|
case eWindowType_popup:
|
|
|
|
return curWindow;
|
2010-08-20 18:19:38 +00:00
|
|
|
default:
|
|
|
|
break;
|
2008-09-09 17:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
2004-07-27 19:14:44 +00:00
|
|
|
|
2009-04-19 19:15:25 +00:00
|
|
|
// Retrieve the top level parent or owner window
|
2011-10-02 02:16:19 +00:00
|
|
|
nsWindow* parentWindow = curWindow->GetParentWindow(true);
|
2008-09-09 17:22:12 +00:00
|
|
|
|
|
|
|
if (!parentWindow)
|
2004-12-09 17:56:46 +00:00
|
|
|
return curWindow;
|
2008-09-09 17:22:12 +00:00
|
|
|
|
|
|
|
curWindow = parentWindow;
|
2004-07-27 19:14:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
static BOOL CALLBACK gEnumWindowsProc(HWND hwnd, LPARAM lParam)
|
2004-07-27 19:14:44 +00:00
|
|
|
{
|
2009-06-29 19:36:16 +00:00
|
|
|
DWORD pid;
|
|
|
|
::GetWindowThreadProcessId(hwnd, &pid);
|
|
|
|
if (pid == GetCurrentProcessId() && ::IsWindowVisible(hwnd))
|
2004-08-02 20:08:43 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
gWindowsVisible = true;
|
2009-06-29 19:36:16 +00:00
|
|
|
return FALSE;
|
2009-02-24 16:53:32 +00:00
|
|
|
}
|
2009-06-29 19:36:16 +00:00
|
|
|
return TRUE;
|
2004-12-09 17:56:46 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::CanTakeFocus()
|
2004-12-09 17:56:46 +00:00
|
|
|
{
|
2011-10-02 02:16:19 +00:00
|
|
|
gWindowsVisible = false;
|
2009-06-29 19:36:16 +00:00
|
|
|
EnumWindows(gEnumWindowsProc, 0);
|
|
|
|
if (!gWindowsVisible) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2006-02-15 23:35:53 +00:00
|
|
|
} else {
|
2009-06-29 19:36:16 +00:00
|
|
|
HWND fgWnd = ::GetForegroundWindow();
|
|
|
|
if (!fgWnd) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
|
|
|
DWORD pid;
|
|
|
|
GetWindowThreadProcessId(fgWnd, &pid);
|
|
|
|
if (pid == GetCurrentProcessId()) {
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2009-06-29 19:36:16 +00:00
|
|
|
}
|
2004-07-27 19:14:44 +00:00
|
|
|
}
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2004-07-27 19:14:44 +00:00
|
|
|
}
|
|
|
|
|
2010-11-08 09:06:13 +00:00
|
|
|
void nsWindow::GetMainWindowClass(nsAString& aClass)
|
|
|
|
{
|
2011-05-28 07:03:00 +00:00
|
|
|
NS_PRECONDITION(aClass.IsEmpty(), "aClass should be empty string");
|
|
|
|
nsresult rv = Preferences::GetString("ui.window_class_override", &aClass);
|
|
|
|
if (NS_FAILED(rv) || aClass.IsEmpty()) {
|
|
|
|
aClass.AssignASCII(sDefaultMainWindowClass);
|
2010-11-08 09:06:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-24 21:38:41 +00:00
|
|
|
/**
|
|
|
|
* Gets the Boolean value of a pref used to enable or disable an input
|
|
|
|
* workaround (like the Trackpoint hack). The pref can take values 0 (for
|
|
|
|
* disabled), 1 (for enabled) or -1 (to automatically detect whether to
|
|
|
|
* enable the workaround).
|
|
|
|
*
|
|
|
|
* @param aPrefName The name of the pref.
|
|
|
|
* @param aValueIfAutomatic Whether the given input workaround should be
|
|
|
|
* enabled by default.
|
|
|
|
*/
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::GetInputWorkaroundPref(const char* aPrefName,
|
|
|
|
bool aValueIfAutomatic)
|
2010-11-08 09:06:13 +00:00
|
|
|
{
|
2011-01-24 21:38:41 +00:00
|
|
|
if (!aPrefName) {
|
|
|
|
return aValueIfAutomatic;
|
|
|
|
}
|
|
|
|
|
2011-05-28 07:03:00 +00:00
|
|
|
PRInt32 lHackValue = 0;
|
|
|
|
if (NS_SUCCEEDED(Preferences::GetInt(aPrefName, &lHackValue))) {
|
|
|
|
switch (lHackValue) {
|
|
|
|
case 0: // disabled
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2011-05-28 07:03:00 +00:00
|
|
|
case 1: // enabled
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2011-05-28 07:03:00 +00:00
|
|
|
default: // -1: autodetect
|
|
|
|
break;
|
2010-11-08 09:06:13 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-24 21:38:41 +00:00
|
|
|
return aValueIfAutomatic;
|
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nsWindow::UseTrackPointHack()
|
2011-01-24 21:38:41 +00:00
|
|
|
{
|
|
|
|
return GetInputWorkaroundPref("ui.trackpoint_hack.enabled",
|
|
|
|
sDefaultTrackPointHack);
|
2010-11-08 09:06:13 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool
|
2011-01-24 21:38:41 +00:00
|
|
|
HasRegistryKey(HKEY aRoot, PRUnichar* aName)
|
2010-11-08 09:06:14 +00:00
|
|
|
{
|
|
|
|
HKEY key;
|
2011-08-15 21:19:34 +00:00
|
|
|
LONG result = ::RegOpenKeyExW(aRoot, aName, 0, KEY_READ | KEY_WOW64_32KEY, &key);
|
|
|
|
if (result != ERROR_SUCCESS) {
|
|
|
|
result = ::RegOpenKeyExW(aRoot, aName, 0, KEY_READ | KEY_WOW64_64KEY, &key);
|
|
|
|
if (result != ERROR_SUCCESS)
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2011-08-15 21:19:34 +00:00
|
|
|
}
|
2010-11-08 09:06:14 +00:00
|
|
|
::RegCloseKey(key);
|
2011-10-02 02:16:19 +00:00
|
|
|
return true;
|
2010-11-08 09:06:14 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
static bool
|
2011-01-24 21:38:41 +00:00
|
|
|
IsObsoleteSynapticsDriver()
|
|
|
|
{
|
|
|
|
PRUnichar buf[40];
|
2012-01-04 10:21:44 +00:00
|
|
|
bool foundKey = WinUtils::GetRegistryKey(HKEY_LOCAL_MACHINE,
|
2011-11-03 14:39:50 +00:00
|
|
|
L"Software\\Synaptics\\SynTP\\Install",
|
|
|
|
L"DriverVersion",
|
|
|
|
buf,
|
|
|
|
sizeof buf);
|
2011-01-24 21:38:41 +00:00
|
|
|
if (!foundKey)
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2010-11-08 09:06:14 +00:00
|
|
|
|
|
|
|
int majorVersion = wcstol(buf, NULL, 10);
|
2011-08-15 21:19:34 +00:00
|
|
|
int minorVersion = 0;
|
|
|
|
PRUnichar* p = wcschr(buf, L'.');
|
|
|
|
if (p) {
|
|
|
|
minorVersion = wcstol(p + 1, NULL, 10);
|
|
|
|
}
|
|
|
|
return majorVersion < 15 || majorVersion == 15 && minorVersion == 0;
|
2010-11-08 09:06:14 +00:00
|
|
|
}
|
|
|
|
|
2011-06-22 20:48:24 +00:00
|
|
|
static PRInt32
|
|
|
|
GetElantechDriverMajorVersion()
|
2011-01-24 21:38:41 +00:00
|
|
|
{
|
|
|
|
PRUnichar buf[40];
|
|
|
|
// The driver version is found in one of these two registry keys.
|
2012-01-04 10:21:44 +00:00
|
|
|
bool foundKey = WinUtils::GetRegistryKey(HKEY_CURRENT_USER,
|
2011-11-03 14:39:50 +00:00
|
|
|
L"Software\\Elantech\\MainOption",
|
|
|
|
L"DriverVersion",
|
|
|
|
buf,
|
|
|
|
sizeof buf);
|
2011-01-24 21:38:41 +00:00
|
|
|
if (!foundKey)
|
2012-01-04 10:21:44 +00:00
|
|
|
foundKey = WinUtils::GetRegistryKey(HKEY_CURRENT_USER,
|
2011-11-03 14:39:50 +00:00
|
|
|
L"Software\\Elantech",
|
|
|
|
L"DriverVersion",
|
|
|
|
buf,
|
|
|
|
sizeof buf);
|
2011-01-24 21:38:41 +00:00
|
|
|
|
|
|
|
if (!foundKey)
|
2011-10-02 02:16:19 +00:00
|
|
|
return false;
|
2011-01-24 21:38:41 +00:00
|
|
|
|
|
|
|
// Assume that the major version number can be found just after a space
|
|
|
|
// or at the start of the string.
|
|
|
|
for (PRUnichar* p = buf; *p; p++) {
|
|
|
|
if (*p >= L'0' && *p <= L'9' && (p == buf || *(p - 1) == L' ')) {
|
2011-06-22 20:48:24 +00:00
|
|
|
return wcstol(p, NULL, 10);
|
2011-01-24 21:38:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-22 20:48:24 +00:00
|
|
|
return 0;
|
2011-01-24 21:38:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsWindow::InitInputWorkaroundPrefDefaults()
|
2009-10-07 04:19:04 +00:00
|
|
|
{
|
2011-06-22 20:48:24 +00:00
|
|
|
PRUint32 elantechDriverVersion = GetElantechDriverMajorVersion();
|
|
|
|
|
2010-11-08 09:06:14 +00:00
|
|
|
if (HasRegistryKey(HKEY_CURRENT_USER, L"Software\\Lenovo\\TrackPoint")) {
|
2011-10-02 02:16:19 +00:00
|
|
|
sDefaultTrackPointHack = true;
|
2010-11-08 09:06:14 +00:00
|
|
|
} else if (HasRegistryKey(HKEY_CURRENT_USER, L"Software\\Lenovo\\UltraNav")) {
|
2011-10-02 02:16:19 +00:00
|
|
|
sDefaultTrackPointHack = true;
|
2010-11-08 09:06:14 +00:00
|
|
|
} else if (HasRegistryKey(HKEY_CURRENT_USER, L"Software\\Alps\\Apoint\\TrackPoint")) {
|
2011-10-02 02:16:19 +00:00
|
|
|
sDefaultTrackPointHack = true;
|
2010-11-08 09:06:14 +00:00
|
|
|
} else if ((HasRegistryKey(HKEY_CURRENT_USER, L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB") ||
|
|
|
|
HasRegistryKey(HKEY_CURRENT_USER, L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2")) &&
|
2011-08-01 22:05:13 +00:00
|
|
|
IsObsoleteSynapticsDriver()) {
|
2011-10-02 02:16:19 +00:00
|
|
|
sDefaultTrackPointHack = true;
|
2009-10-07 04:19:04 +00:00
|
|
|
}
|
2011-01-24 21:38:41 +00:00
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool useElantechGestureHacks =
|
2011-01-24 21:38:41 +00:00
|
|
|
GetInputWorkaroundPref("ui.elantech_gesture_hacks.enabled",
|
2011-06-22 20:48:24 +00:00
|
|
|
elantechDriverVersion != 0);
|
|
|
|
sUseElantechSwipeHack = useElantechGestureHacks && elantechDriverVersion <= 7;
|
|
|
|
sUseElantechPinchHack = useElantechGestureHacks && elantechDriverVersion <= 8;
|
2009-10-07 04:19:04 +00:00
|
|
|
}
|
|
|
|
|
2009-07-27 17:27:35 +00:00
|
|
|
LPARAM nsWindow::lParamToScreen(LPARAM lParam)
|
|
|
|
{
|
|
|
|
POINT pt;
|
|
|
|
pt.x = GET_X_LPARAM(lParam);
|
|
|
|
pt.y = GET_Y_LPARAM(lParam);
|
|
|
|
::ClientToScreen(mWnd, &pt);
|
|
|
|
return MAKELPARAM(pt.x, pt.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
LPARAM nsWindow::lParamToClient(LPARAM lParam)
|
|
|
|
{
|
|
|
|
POINT pt;
|
|
|
|
pt.x = GET_X_LPARAM(lParam);
|
|
|
|
pt.y = GET_Y_LPARAM(lParam);
|
|
|
|
::ScreenToClient(mWnd, &pt);
|
|
|
|
return MAKELPARAM(pt.x, pt.y);
|
|
|
|
}
|
|
|
|
|
2011-12-07 19:01:48 +00:00
|
|
|
void nsWindow::PickerOpen()
|
|
|
|
{
|
|
|
|
mPickerDisplayCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsWindow::PickerClosed()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mPickerDisplayCount > 0, "mPickerDisplayCount out of sync!");
|
|
|
|
if (!mPickerDisplayCount)
|
|
|
|
return;
|
|
|
|
mPickerDisplayCount--;
|
|
|
|
if (!mPickerDisplayCount && mDestroyCalled) {
|
|
|
|
Destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 19:36:16 +00:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: ChildWindow impl.
|
|
|
|
**
|
|
|
|
** Child window overrides.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// return the style for a child nsWindow
|
|
|
|
DWORD ChildWindow::WindowStyle()
|
|
|
|
{
|
|
|
|
DWORD style = WS_CLIPCHILDREN | nsWindow::WindowStyle();
|
|
|
|
if (!(style & WS_POPUP))
|
|
|
|
style |= WS_CHILD; // WS_POPUP and WS_CHILD are mutually exclusive.
|
|
|
|
VERIFY_WINDOW_STYLE(style);
|
|
|
|
return style;
|
2009-08-02 00:30:23 +00:00
|
|
|
}
|