2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sts=2 sw=2 et cin: */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* 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/
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Dean Tessman <dean_tessman@hotmail.com>
|
2009-03-26 18:10:52 -07:00
|
|
|
* Ere Maijala <emaijala@kolumbus.fi>
|
2007-03-22 10:30:00 -07:00
|
|
|
* Mark Hammond <markh@activestate.com>
|
|
|
|
* Michael Lowe <michael.lowe@bigfoot.com>
|
|
|
|
* Peter Bajusz <hyp-x@inf.bme.hu>
|
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
|
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
|
|
|
* Roy Yokoyama <yokoyama@netscape.com>
|
|
|
|
* Makoto Kato <m_kato@ga2.so-net.ne.jp>
|
|
|
|
* Masayuki Nakano <masayuki@d-toybox.com>
|
|
|
|
* Dainis Jonitis <Dainis_Jonitis@swh-t.lv>
|
|
|
|
* Christian Biesinger <cbiesinger@web.de>
|
|
|
|
* Mats Palmgren <mats.palmgren@bredband.net>
|
2009-02-10 12:56:51 -08:00
|
|
|
* Ningjie Chen <chenn@email.uc.edu>
|
2009-06-29 12:36:16 -07:00
|
|
|
* Jim Mathies <jmathies@mozilla.com>
|
2007-03-22 10:30:00 -07:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* 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
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* 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
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/*
|
2009-06-29 23:00:16 -07:00
|
|
|
* nsWindow - Native window management and event handling.
|
|
|
|
*
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
* nsWindowCE.h/.cpp - WINCE specific code that can be
|
|
|
|
* split out from nsWindow.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Includes
|
|
|
|
**
|
|
|
|
** Include headers.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsWindow.h"
|
2009-06-29 12:36:16 -07: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"
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIAppShell.h"
|
2009-06-29 12:36:16 -07:00
|
|
|
#include "nsISupportsPrimitives.h"
|
|
|
|
#include "nsIDOMNSUIEvent.h"
|
|
|
|
#include "nsITheme.h"
|
|
|
|
#include "nsIImage.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIPrefBranch.h"
|
|
|
|
#include "nsIPrefService.h"
|
|
|
|
#include "nsIObserverService.h"
|
2009-06-29 12:36:16 -07:00
|
|
|
#include "nsIScreenManager.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "imgIContainer.h"
|
|
|
|
#include "gfxIImageFrame.h"
|
2009-06-29 12:36:16 -07:00
|
|
|
#include "nsIFile.h"
|
|
|
|
#include "nsIRollupListener.h"
|
|
|
|
#include "nsIMenuRollup.h"
|
|
|
|
#include "nsIRegion.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIClipboard.h"
|
|
|
|
#include "nsIMM32Handler.h"
|
|
|
|
#include "nsILocalFile.h"
|
|
|
|
#include "nsIFontMetrics.h"
|
|
|
|
#include "nsIFontEnumerator.h"
|
|
|
|
#include "nsIDeviceContext.h"
|
|
|
|
|
|
|
|
#include "nsGUIEvent.h"
|
|
|
|
#include "nsFont.h"
|
|
|
|
#include "nsRect.h"
|
|
|
|
#include "nsThreadUtils.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsNativeCharsetUtils.h"
|
|
|
|
#include "nsWidgetAtoms.h"
|
2008-04-29 21:12:15 -07:00
|
|
|
#include "nsUnicharUtils.h"
|
2009-06-29 12:36:16 -07:00
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
|
|
#include "nsXPIDLString.h"
|
|
|
|
#include "nsWidgetsCID.h"
|
2009-02-12 18:26:02 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(WINCE)
|
|
|
|
#include "nsWindowCE.h"
|
2009-02-12 18:26:02 -08:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#include "nsWindowGfx.h"
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE)
|
2009-01-05 10:17:44 -08:00
|
|
|
#include "nsUXThemeData.h"
|
2009-03-24 17:51:57 -07:00
|
|
|
#include "nsUXThemeConstants.h"
|
2009-01-05 10:17:44 -08:00
|
|
|
#include "nsKeyboardLayout.h"
|
|
|
|
#include "nsNativeDragTarget.h"
|
2009-06-29 12:36:16 -07:00
|
|
|
#include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
|
2009-01-05 10:17:44 -08:00
|
|
|
#include <zmouse.h>
|
2009-06-29 12:36:16 -07:00
|
|
|
#include <pbt.h>
|
|
|
|
#endif // !defined(WINCE)
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(ACCESSIBILITY)
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "OLEIDL.H"
|
2007-11-09 10:38:07 -08:00
|
|
|
#include <winuser.h>
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINABLEAPI)
|
2007-11-09 10:38:07 -08:00
|
|
|
#include <winable.h>
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // !defined(WINABLEAPI)
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIAccessible.h"
|
|
|
|
#include "nsIAccessibleDocument.h"
|
|
|
|
#include "nsIAccessNode.h"
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // defined(ACCESSIBILITY)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(NS_ENABLE_TSF)
|
|
|
|
#include "nsTextStore.h"
|
|
|
|
#endif // defined(NS_ENABLE_TSF)
|
|
|
|
|
|
|
|
#if defined(MOZ_SPLASHSCREEN)
|
|
|
|
#include "nsSplashScreen.h"
|
|
|
|
#endif // defined(MOZ_SPLASHSCREEN)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Windowless plugin support
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsplugindefs.h"
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#include "nsWindowDefs.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Variables
|
|
|
|
**
|
|
|
|
** nsWindow Class static initializations and global variables.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsWindow statics
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
PRUint32 nsWindow::sInstanceCount = 0;
|
|
|
|
PRBool nsWindow::sSwitchKeyboardLayout = PR_FALSE;
|
|
|
|
BOOL nsWindow::sIsRegistered = FALSE;
|
|
|
|
BOOL nsWindow::sIsPopupClassRegistered = FALSE;
|
|
|
|
BOOL nsWindow::sIsOleInitialized = FALSE;
|
|
|
|
HCURSOR nsWindow::sHCursor = NULL;
|
|
|
|
imgIContainer* nsWindow::sCursorImgContainer = nsnull;
|
|
|
|
nsWindow* nsWindow::sCurrentWindow = nsnull;
|
|
|
|
PRBool nsWindow::sJustGotDeactivate = PR_FALSE;
|
|
|
|
PRBool nsWindow::sJustGotActivate = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
PRPackedBool nsWindow::sProcessHook = PR_FALSE;
|
|
|
|
UINT nsWindow::sRollupMsgId = 0;
|
|
|
|
HWND nsWindow::sRollupMsgWnd = NULL;
|
|
|
|
UINT nsWindow::sHookTimerId = 0;
|
|
|
|
|
|
|
|
// Rollup Listener
|
|
|
|
nsIRollupListener* nsWindow::sRollupListener = nsnull;
|
|
|
|
nsIWidget* nsWindow::sRollupWidget = nsnull;
|
|
|
|
PRBool nsWindow::sRollupConsumeEvent = PR_FALSE;
|
|
|
|
|
|
|
|
// 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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
BOOL nsWindow::sIsAccessibilityOn = FALSE;
|
|
|
|
// Accessibility wm_getobject handler
|
|
|
|
HINSTANCE nsWindow::sAccLib = 0;
|
|
|
|
LPFNLRESULTFROMOBJECT
|
|
|
|
nsWindow::sLresultFromObject = 0;
|
|
|
|
#endif // ACCESSIBILITY
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: globals variables
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
|
|
|
|
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
PRLogModuleInfo* gWindowsLog = nsnull;
|
|
|
|
#endif
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
// Kbd layout. Used throughout character processing.
|
|
|
|
static KeyboardLayout gKbdLayout;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// The last user input event time in microseconds. If
|
|
|
|
// there are any pending native toolkit input events
|
|
|
|
// it returns the current time. The value is compatible
|
|
|
|
// with PR_IntervalToMicroseconds(PR_IntervalNow()).
|
|
|
|
#if !defined(WINCE)
|
|
|
|
static PRUint32 gLastInputEventTime = 0;
|
|
|
|
#else
|
|
|
|
PRUint32 gLastInputEventTime = 0;
|
|
|
|
#endif
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Global user preference for disabling native theme. Used
|
|
|
|
// in NativeWindowTheme.
|
|
|
|
PRBool gDisableNativeTheme = PR_FALSE;
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Global used in Show window enumerations.
|
|
|
|
static PRBool gWindowsVisible = PR_FALSE;
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: nsIWidget impl.
|
|
|
|
**
|
|
|
|
** nsIWidget interface implementation, broken down into
|
|
|
|
** sections.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsWindow construction and destruction
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsWindow::nsWindow() : nsBaseWidget()
|
2009-04-22 17:48:30 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef PR_LOGGING
|
|
|
|
if (!gWindowsLog)
|
|
|
|
gWindowsLog = PR_NewLogModule("nsWindowsWidgets");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mWnd = nsnull;
|
|
|
|
mPaintDC = nsnull;
|
|
|
|
mPrevWndProc = nsnull;
|
|
|
|
mDeferredPositioner = nsnull;
|
|
|
|
mOldIMC = nsnull;
|
|
|
|
mNativeDragTarget = nsnull;
|
|
|
|
mIsDestroying = PR_FALSE;
|
|
|
|
mIsVisible = PR_FALSE;
|
|
|
|
mHas3DBorder = PR_FALSE;
|
|
|
|
mIsInMouseCapture = PR_FALSE;
|
|
|
|
mIsPluginWindow = PR_FALSE;
|
|
|
|
mIsTopWidgetWindow = PR_FALSE;
|
|
|
|
mInWheelProcessing = PR_FALSE;
|
|
|
|
mUnicodeWidget = PR_TRUE;
|
|
|
|
mWindowType = eWindowType_child;
|
|
|
|
mBorderStyle = eBorderStyle_default;
|
|
|
|
mPopupType = ePopupTypeAny;
|
|
|
|
mLastPoint.x = 0;
|
|
|
|
mLastPoint.y = 0;
|
|
|
|
mLastSize.width = 0;
|
|
|
|
mLastSize.height = 0;
|
|
|
|
mOldStyle = 0;
|
|
|
|
mOldExStyle = 0;
|
|
|
|
mPainting = 0;
|
|
|
|
mLastKeyboardLayout = 0;
|
|
|
|
mBlurSuppressLevel = 0;
|
|
|
|
mIMEEnabled = nsIWidget::IME_STATUS_ENABLED;
|
|
|
|
mLeadByte = '\0';
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
mTransparentSurface = nsnull;
|
|
|
|
mMemoryDC = nsnull;
|
|
|
|
mTransparencyMode = eTransparencyOpaque;
|
|
|
|
#endif
|
|
|
|
mBackground = ::GetSysColor(COLOR_BTNFACE);
|
|
|
|
mBrush = ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground));
|
|
|
|
mForeground = ::GetSysColor(COLOR_WINDOWTEXT);
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Global initialization
|
|
|
|
if (!sInstanceCount) {
|
|
|
|
#if !defined(WINCE)
|
|
|
|
gKbdLayout.LoadLayout(::GetKeyboardLayout(0));
|
2009-04-22 17:48:30 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Init IME handler
|
|
|
|
nsIMM32Handler::Initialize();
|
2009-02-15 17:09:11 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::Initialize();
|
|
|
|
#endif
|
2009-03-08 22:08:41 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
if (SUCCEEDED(::OleInitialize(NULL)))
|
|
|
|
sIsOleInitialized = TRUE;
|
|
|
|
NS_ASSERTION(sIsOleInitialized, "***** OLE is not initialized!\n");
|
|
|
|
#endif
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(HEAP_DUMP_EVENT)
|
|
|
|
InitHeapDump();
|
|
|
|
#endif
|
|
|
|
} // !sInstanceCount
|
2009-03-23 18:10:36 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Set gLastInputEventTime to some valid number
|
|
|
|
gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
|
|
|
|
|
|
|
sInstanceCount++;
|
2009-04-13 22:27:39 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsWindow::~nsWindow()
|
2009-03-23 18:10:36 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
mIsDestroying = PR_TRUE;
|
|
|
|
if (sCurrentWindow == this) {
|
|
|
|
sCurrentWindow = nsnull;
|
|
|
|
}
|
2009-03-23 18:10:36 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
MouseTrailer* mtrailer = nsToolkit::gMouseTrailer;
|
|
|
|
if (mtrailer) {
|
|
|
|
if (mtrailer->GetMouseTrailerWindow() == mWnd)
|
|
|
|
mtrailer->DestroyTimer();
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mtrailer->GetCaptureWindow() == mWnd)
|
|
|
|
mtrailer->SetCaptureWindow(nsnull);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// If the widget was released without calling Destroy() then the native
|
|
|
|
// window still exists, and we need to destroy it
|
|
|
|
if (NULL != mWnd) {
|
|
|
|
Destroy();
|
|
|
|
}
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mCursor == -1) {
|
|
|
|
// A successfull SetCursor call will destroy the custom cursor, if it's ours
|
|
|
|
SetCursor(eCursor_standard);
|
|
|
|
}
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
sInstanceCount--;
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Global shutdown
|
2009-06-29 23:00:16 -07:00
|
|
|
if (sInstanceCount == 0) {
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::Terminate();
|
|
|
|
#endif
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
NS_IF_RELEASE(sCursorImgContainer);
|
|
|
|
if (sIsOleInitialized) {
|
|
|
|
::OleFlushClipboard();
|
|
|
|
::OleUninitialize();
|
|
|
|
sIsOleInitialized = FALSE;
|
|
|
|
}
|
|
|
|
// delete any of the IME structures that we allocated
|
|
|
|
nsIMM32Handler::Terminate();
|
|
|
|
#endif // !defined(WINCE)
|
2009-01-05 10:17:44 -08:00
|
|
|
}
|
2009-06-29 23:00:16 -07:00
|
|
|
|
|
|
|
#if !defined(WINCE)
|
|
|
|
NS_IF_RELEASE(mNativeDragTarget);
|
|
|
|
#endif // !defined(WINCE)
|
2009-01-05 10:17:44 -08:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Create, nsIWidget::Destroy
|
|
|
|
*
|
|
|
|
* Creating and destroying windows for this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Create the proper widget
|
|
|
|
NS_METHOD nsWindow::Create(nsIWidget *aParent,
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
EVENT_CALLBACK aHandleEventFunction,
|
|
|
|
nsIDeviceContext *aContext,
|
|
|
|
nsIAppShell *aAppShell,
|
|
|
|
nsIToolkit *aToolkit,
|
|
|
|
nsWidgetInitData *aInitData)
|
2009-01-05 10:17:44 -08:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aInitData)
|
|
|
|
mUnicodeWidget = aInitData->mUnicode;
|
|
|
|
return(StandardWindowCreate(aParent, aRect, aHandleEventFunction,
|
|
|
|
aContext, aAppShell, aToolkit, aInitData,
|
|
|
|
nsnull));
|
2009-01-05 10:17:44 -08:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
// Create with a native parent
|
|
|
|
NS_METHOD nsWindow::Create(nsNativeWidget aParent,
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
EVENT_CALLBACK aHandleEventFunction,
|
|
|
|
nsIDeviceContext *aContext,
|
|
|
|
nsIAppShell *aAppShell,
|
|
|
|
nsIToolkit *aToolkit,
|
|
|
|
nsWidgetInitData *aInitData)
|
2009-01-05 10:17:44 -08:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aInitData)
|
|
|
|
mUnicodeWidget = aInitData->mUnicode;
|
|
|
|
return(StandardWindowCreate(nsnull, aRect, aHandleEventFunction,
|
|
|
|
aContext, aAppShell, aToolkit, aInitData,
|
|
|
|
aParent));
|
2009-01-05 10:17:44 -08:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Close this nsWindow
|
|
|
|
NS_METHOD nsWindow::Destroy()
|
|
|
|
{
|
|
|
|
// Switch to the "main gui thread" if necessary... This method must
|
|
|
|
// be executed on the "gui thread"...
|
|
|
|
nsToolkit* toolkit = (nsToolkit *)mToolkit;
|
|
|
|
if (toolkit != nsnull && !toolkit->IsGuiThread()) {
|
|
|
|
MethodInfo info(this, nsWindow::DESTROY);
|
|
|
|
toolkit->CallMethod(&info);
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// disconnect from the parent
|
|
|
|
if (!mIsDestroying) {
|
|
|
|
nsBaseWidget::Destroy();
|
|
|
|
}
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// just to be safe. 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 )
|
|
|
|
sRollupListener->Rollup(nsnull, nsnull);
|
|
|
|
CaptureRollupEvents(nsnull, PR_FALSE, PR_TRUE);
|
|
|
|
}
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
EnableDragDrop(PR_FALSE);
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// destroy the HWND
|
|
|
|
if (mWnd) {
|
|
|
|
// prevent the widget from causing additional events
|
|
|
|
mEventCallback = nsnull;
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// if IME is disabled, restore it.
|
|
|
|
if (mOldIMC) {
|
|
|
|
mOldIMC = ::ImmAssociateContext(mWnd, mOldIMC);
|
|
|
|
NS_ASSERTION(!mOldIMC, "Another IMC was associated");
|
|
|
|
}
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
HICON icon;
|
|
|
|
icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM) 0);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM) 0);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
{
|
|
|
|
SetupTranslucentWindowMemoryBitmap(eTransparencyOpaque);
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2009-01-05 10:17:44 -08:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
VERIFY(::DestroyWindow(mWnd));
|
|
|
|
|
|
|
|
mWnd = NULL;
|
|
|
|
//our windows can be subclassed by
|
|
|
|
//others and these nameless, faceless others
|
|
|
|
//may not let us know about WM_DESTROY. so,
|
|
|
|
//if OnDestroy() didn't get called, just call
|
|
|
|
//it now. MMP
|
|
|
|
if (PR_FALSE == mOnDestroyCalled)
|
|
|
|
OnDestroy();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Allow Derived classes to modify the height that is passed
|
|
|
|
// when the window is created or resized. Also add extra height
|
|
|
|
// if needed (on Windows CE)
|
|
|
|
PRInt32 nsWindow::GetHeight(PRInt32 aProposedHeight)
|
2007-08-06 10:45:57 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
PRInt32 extra = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
|
|
|
|
DWORD style = WindowStyle();
|
|
|
|
if ((style & WS_SYSMENU) && (style & WS_POPUP)) {
|
|
|
|
extra = GetSystemMetrics(SM_CYCAPTION);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif
|
2008-08-20 13:28:15 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return aProposedHeight + extra;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Utility methods for creating windows.
|
|
|
|
nsresult
|
|
|
|
nsWindow::StandardWindowCreate(nsIWidget *aParent,
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
EVENT_CALLBACK aHandleEventFunction,
|
|
|
|
nsIDeviceContext *aContext,
|
|
|
|
nsIAppShell *aAppShell,
|
|
|
|
nsIToolkit *aToolkit,
|
|
|
|
nsWidgetInitData *aInitData,
|
|
|
|
nsNativeWidget aNativeParent)
|
|
|
|
{
|
|
|
|
nsIWidget *baseParent = aInitData &&
|
|
|
|
(aInitData->mWindowType == eWindowType_dialog ||
|
|
|
|
aInitData->mWindowType == eWindowType_toplevel ||
|
|
|
|
aInitData->mWindowType == eWindowType_invisible) ?
|
|
|
|
nsnull : aParent;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mIsTopWidgetWindow = (nsnull == baseParent);
|
|
|
|
mBounds.width = aRect.width;
|
|
|
|
mBounds.height = aRect.height;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
|
|
|
|
aAppShell, aToolkit, aInitData);
|
2008-12-06 01:27:30 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Switch to the "main gui thread" if necessary... This method must
|
|
|
|
// be executed on the "gui thread"...
|
2009-01-28 15:39:13 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsToolkit* toolkit = (nsToolkit *)mToolkit;
|
|
|
|
if (toolkit && !toolkit->IsGuiThread()) {
|
|
|
|
DWORD_PTR args[7];
|
|
|
|
args[0] = (DWORD_PTR)aParent;
|
|
|
|
args[1] = (DWORD_PTR)&aRect;
|
|
|
|
args[2] = (DWORD_PTR)aHandleEventFunction;
|
|
|
|
args[3] = (DWORD_PTR)aContext;
|
|
|
|
args[4] = (DWORD_PTR)aAppShell;
|
|
|
|
args[5] = (DWORD_PTR)aToolkit;
|
|
|
|
args[6] = (DWORD_PTR)aInitData;
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull != aParent) {
|
|
|
|
// nsIWidget parent dispatch
|
|
|
|
MethodInfo info(this, nsWindow::CREATE, 7, args);
|
|
|
|
toolkit->CallMethod(&info);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Native parent dispatch
|
|
|
|
MethodInfo info(this, nsWindow::CREATE_NATIVE, 5, args);
|
|
|
|
toolkit->CallMethod(&info);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
HWND parent;
|
|
|
|
if (nsnull != aParent) { // has a nsIWidget parent
|
|
|
|
parent = ((aParent) ? (HWND)aParent->GetNativeData(NS_NATIVE_WINDOW) : nsnull);
|
|
|
|
} else { // has a nsNative parent
|
|
|
|
parent = (HWND)aNativeParent;
|
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull != aInitData) {
|
|
|
|
SetWindowType(aInitData->mWindowType);
|
|
|
|
SetBorderStyle(aInitData->mBorderStyle);
|
|
|
|
mPopupType = aInitData->mPopupHint;
|
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mContentType = aInitData ? aInitData->mContentType : eContentTypeInherit;
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
DWORD style = WindowStyle();
|
|
|
|
DWORD extendedStyle = WindowExStyle();
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWindowType == eWindowType_popup) {
|
|
|
|
// if a parent was specified, don't use WS_EX_TOPMOST so that the popup
|
|
|
|
// only appears above the parent, instead of all windows
|
|
|
|
if (aParent)
|
|
|
|
extendedStyle = WS_EX_TOOLWINDOW;
|
|
|
|
else
|
|
|
|
parent = NULL;
|
|
|
|
} else if (nsnull != aInitData) {
|
|
|
|
// 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-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mHas3DBorder = (extendedStyle & WS_EX_CLIENTEDGE) > 0;
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mWnd = ::CreateWindowExW(extendedStyle,
|
|
|
|
aInitData && aInitData->mDropShadow ?
|
|
|
|
WindowPopupClass() : WindowClass(),
|
|
|
|
L"",
|
|
|
|
style,
|
|
|
|
aRect.x,
|
|
|
|
aRect.y,
|
|
|
|
aRect.width,
|
|
|
|
GetHeight(aRect.height),
|
|
|
|
parent,
|
|
|
|
NULL,
|
|
|
|
nsToolkit::mDllInstance,
|
|
|
|
NULL);
|
2008-12-06 01:27:30 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!mWnd)
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-08-10 12:01:48 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// call the event callback to notify about creation
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
DispatchStandardEvent(NS_CREATE);
|
|
|
|
SubclassWindow(TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sTrimOnMinimize == 2 && mWindowType == eWindowType_invisible) {
|
|
|
|
/* The internal variable set by the config.trim_on_minimize pref
|
|
|
|
has not yet been initialized, and this is the hidden window
|
|
|
|
(conveniently created before any visible windows, and after
|
|
|
|
the profile has been initialized).
|
|
|
|
|
|
|
|
Default config.trim_on_minimize to false, to fix bug 76831
|
|
|
|
for good. If anyone complains about this new default, saying
|
|
|
|
that a Mozilla app hogs too much memory while minimized, they
|
|
|
|
will have that entire bug tattooed on their backside. */
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
sTrimOnMinimize = 0;
|
|
|
|
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
|
|
if (prefs) {
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch;
|
|
|
|
prefs->GetBranch(0, getter_AddRefs(prefBranch));
|
|
|
|
if (prefBranch) {
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool temp;
|
|
|
|
if (NS_SUCCEEDED(prefBranch->GetBoolPref("config.trim_on_minimize",
|
|
|
|
&temp))
|
|
|
|
&& temp)
|
|
|
|
sTrimOnMinimize = 1;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (NS_SUCCEEDED(prefBranch->GetBoolPref("intl.keyboard.per_window_layout",
|
|
|
|
&temp)))
|
|
|
|
sSwitchKeyboardLayout = temp;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (NS_SUCCEEDED(prefBranch->GetBoolPref("mozilla.widget.disable-native-theme",
|
|
|
|
&temp)))
|
|
|
|
gDisableNativeTheme = temp;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRInt32 tempint;
|
|
|
|
if (NS_SUCCEEDED(prefBranch->GetIntPref("mozilla.widget.render-mode",
|
|
|
|
&tempint)))
|
|
|
|
{
|
|
|
|
if (tempint > 0 && tempint < RENDER_MODE_MAX) {
|
|
|
|
#ifndef CAIRO_HAS_DDRAW_SURFACE
|
|
|
|
if (tempint == RENDER_DDRAW)
|
|
|
|
tempint = RENDER_IMAGE_STRETCH24;
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
sRenderMode = (WinRenderMode) tempint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if defined(WINCE_HAVE_SOFTKB)
|
|
|
|
if (mWindowType == eWindowType_dialog || mWindowType == eWindowType_toplevel )
|
|
|
|
nsWindowCE::CreateSoftKeyMenuBar(mWnd);
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
// Enable gesture support for this window.
|
|
|
|
if (mWindowType != eWindowType_invisible &&
|
|
|
|
mWindowType != eWindowType_plugin &&
|
|
|
|
mWindowType != eWindowType_java &&
|
|
|
|
mWindowType != eWindowType_toplevel) {
|
|
|
|
// eWindowType_toplevel is the top level main frame window. Gesture support
|
|
|
|
// there prevents the user from interacting with the title bar or nc
|
|
|
|
// areas using a single finger. Java and plugin windows can make their
|
|
|
|
// own calls.
|
|
|
|
mGesture.InitWinGestureSupport(mWnd);
|
|
|
|
}
|
|
|
|
#endif // !defined(WINCE)
|
2009-05-03 15:20:11 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window class utilities
|
|
|
|
*
|
|
|
|
* Utilities for calculating the proper window class name for
|
|
|
|
* Create window.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2008-09-09 10:22:12 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Return the proper window class for everything except popups.
|
|
|
|
LPCWSTR nsWindow::WindowClass()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!nsWindow::sIsRegistered) {
|
|
|
|
WNDCLASSW wc;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
|
|
|
wc.style = CS_DBLCLKS;
|
|
|
|
wc.lpfnWndProc = ::DefWindowProcW;
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hInstance = nsToolkit::mDllInstance;
|
|
|
|
wc.hIcon = ::LoadIconW(::GetModuleHandleW(NULL), (LPWSTR)IDI_APPLICATION);
|
|
|
|
wc.hCursor = NULL;
|
|
|
|
wc.hbrBackground = mBrush;
|
|
|
|
wc.lpszMenuName = NULL;
|
|
|
|
wc.lpszClassName = kClassNameHidden;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
BOOL succeeded = ::RegisterClassW(&wc) != 0 &&
|
|
|
|
ERROR_CLASS_ALREADY_EXISTS != GetLastError();
|
|
|
|
nsWindow::sIsRegistered = succeeded;
|
2008-09-09 10:22:12 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
wc.lpszClassName = kClassNameContentFrame;
|
|
|
|
if (!::RegisterClassW(&wc) &&
|
|
|
|
ERROR_CLASS_ALREADY_EXISTS != GetLastError()) {
|
|
|
|
nsWindow::sIsRegistered = FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
wc.lpszClassName = kClassNameContent;
|
|
|
|
if (!::RegisterClassW(&wc) &&
|
|
|
|
ERROR_CLASS_ALREADY_EXISTS != GetLastError()) {
|
|
|
|
nsWindow::sIsRegistered = FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
wc.lpszClassName = kClassNameUI;
|
|
|
|
if (!::RegisterClassW(&wc) &&
|
|
|
|
ERROR_CLASS_ALREADY_EXISTS != GetLastError()) {
|
|
|
|
nsWindow::sIsRegistered = FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
wc.lpszClassName = kClassNameGeneral;
|
|
|
|
ATOM generalClassAtom = ::RegisterClassW(&wc);
|
|
|
|
if (!generalClassAtom &&
|
|
|
|
ERROR_CLASS_ALREADY_EXISTS != GetLastError()) {
|
|
|
|
nsWindow::sIsRegistered = FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
wc.lpszClassName = kClassNameDialog;
|
|
|
|
wc.hIcon = 0;
|
|
|
|
if (!::RegisterClassW(&wc) &&
|
|
|
|
ERROR_CLASS_ALREADY_EXISTS != GetLastError()) {
|
|
|
|
nsWindow::sIsRegistered = FALSE;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWindowType == eWindowType_invisible) {
|
|
|
|
return kClassNameHidden;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWindowType == eWindowType_dialog) {
|
|
|
|
return kClassNameDialog;
|
|
|
|
}
|
|
|
|
if (mContentType == eContentTypeContent) {
|
|
|
|
return kClassNameContent;
|
|
|
|
}
|
|
|
|
if (mContentType == eContentTypeContentFrame) {
|
|
|
|
return kClassNameContentFrame;
|
|
|
|
}
|
|
|
|
if (mContentType == eContentTypeUI) {
|
|
|
|
return kClassNameUI;
|
|
|
|
}
|
|
|
|
return kClassNameGeneral;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Return the proper popup window class
|
|
|
|
LPCWSTR nsWindow::WindowPopupClass()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
const LPCWSTR className = L"MozillaDropShadowWindowClass";
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!nsWindow::sIsPopupClassRegistered) {
|
|
|
|
WNDCLASSW wc;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
wc.style = CS_DBLCLKS | CS_XP_DROPSHADOW;
|
|
|
|
wc.lpfnWndProc = ::DefWindowProcW;
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hInstance = nsToolkit::mDllInstance;
|
|
|
|
wc.hIcon = ::LoadIconW(::GetModuleHandleW(NULL), (LPWSTR)IDI_APPLICATION);
|
|
|
|
wc.hCursor = NULL;
|
|
|
|
wc.hbrBackground = mBrush;
|
|
|
|
wc.lpszMenuName = NULL;
|
|
|
|
wc.lpszClassName = className;
|
|
|
|
|
|
|
|
nsWindow::sIsPopupClassRegistered = ::RegisterClassW(&wc);
|
|
|
|
if (!nsWindow::sIsPopupClassRegistered) {
|
|
|
|
// For older versions of Win32 (i.e., not XP), the registration will
|
|
|
|
// fail, so we have to re-register without the CS_XP_DROPSHADOW flag.
|
|
|
|
wc.style = CS_DBLCLKS;
|
|
|
|
nsWindow::sIsPopupClassRegistered = ::RegisterClassW(&wc);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
return className;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window styles utilities
|
|
|
|
*
|
|
|
|
* Return the proper windows styles and extended styles.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Return nsWindow styles
|
|
|
|
#if !defined(WINCE) // implemented in nsWindowCE.cpp
|
|
|
|
DWORD nsWindow::WindowStyle()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
DWORD style;
|
2008-05-05 16:01:07 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (mWindowType) {
|
|
|
|
case eWindowType_child:
|
|
|
|
style = WS_OVERLAPPED;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eWindowType_dialog:
|
|
|
|
style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_3DLOOK | DS_MODALFRAME;
|
|
|
|
if (mBorderStyle != eBorderStyle_default)
|
|
|
|
style |= WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eWindowType_popup:
|
|
|
|
style = WS_POPUP;
|
|
|
|
if (mTransparencyMode == eTransparencyGlass) {
|
|
|
|
/* Glass seems to need WS_CAPTION or WS_THICKFRAME to work.
|
|
|
|
WS_THICKFRAME has issues with autohiding popups but looks better */
|
|
|
|
style |= WS_THICKFRAME;
|
|
|
|
} else {
|
|
|
|
style |= WS_OVERLAPPED;
|
|
|
|
}
|
|
|
|
break;
|
2009-02-10 12:56:51 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
NS_ASSERTION(0, "unknown border style");
|
|
|
|
// fall through
|
2009-02-07 09:13:30 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eWindowType_toplevel:
|
|
|
|
case eWindowType_invisible:
|
|
|
|
style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU |
|
|
|
|
WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
|
|
|
|
break;
|
|
|
|
}
|
2009-04-14 11:23:01 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
VERIFY_WINDOW_STYLE(style);
|
|
|
|
return style;
|
2009-01-05 10:17:44 -08:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // !defined(WINCE)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Return nsWindow extended styles
|
|
|
|
DWORD nsWindow::WindowExStyle()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (mWindowType)
|
|
|
|
{
|
|
|
|
case eWindowType_child:
|
|
|
|
return 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eWindowType_dialog:
|
|
|
|
return WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eWindowType_popup:
|
|
|
|
return
|
|
|
|
#if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
|
|
|
|
WS_EX_NOACTIVATE |
|
|
|
|
#endif
|
|
|
|
WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
NS_ASSERTION(0, "unknown border style");
|
|
|
|
// fall through
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eWindowType_toplevel:
|
|
|
|
case eWindowType_invisible:
|
|
|
|
return WS_EX_WINDOWEDGE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window subclassing utilities
|
|
|
|
*
|
|
|
|
* Set or clear window subclasses on native windows. Used in
|
|
|
|
* Create and Destroy.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2009-02-10 12:56:51 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Subclass (or remove the subclass from) this component's nsWindow
|
|
|
|
void nsWindow::SubclassWindow(BOOL bState)
|
|
|
|
{
|
|
|
|
if (NULL != mWnd) {
|
|
|
|
NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
|
2007-10-31 11:55:57 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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
|
|
|
|
SetNSWindowPtr(mWnd, this);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (mUnicodeWidget)
|
|
|
|
::SetWindowLongPtrW(mWnd, GWLP_WNDPROC, (LONG_PTR)mPrevWndProc);
|
|
|
|
else
|
|
|
|
::SetWindowLongPtrA(mWnd, GWLP_WNDPROC, (LONG_PTR)mPrevWndProc);
|
|
|
|
SetNSWindowPtr(mWnd, NULL);
|
|
|
|
mPrevWndProc = NULL;
|
2007-10-31 11:55:57 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window properties
|
|
|
|
*
|
|
|
|
* Set and clear native window properties.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
static PRUnichar sPropName[40] = L"";
|
|
|
|
static PRUnichar* GetNSWindowPropName()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!*sPropName)
|
|
|
|
{
|
|
|
|
_snwprintf(sPropName, 39, L"MozillansIWidgetPtr%p", GetCurrentProcessId());
|
|
|
|
sPropName[39] = '\0';
|
2009-06-16 11:55:06 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return sPropName;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsWindow * nsWindow::GetNSWindowPtr(HWND aWnd)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
return (nsWindow *) ::GetPropW(aWnd, GetNSWindowPropName());
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
BOOL nsWindow::SetNSWindowPtr(HWND aWnd, nsWindow * ptr)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (ptr == NULL) {
|
|
|
|
::RemovePropW(aWnd, GetNSWindowPropName());
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
return ::SetPropW(aWnd, GetNSWindowPropName(), (HANDLE)ptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetParent, nsIWidget::GetParent
|
|
|
|
*
|
|
|
|
* Set or clear the parent widgets using window properties, and
|
|
|
|
* handles calculating native parent handles.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Get and set parent widgets
|
|
|
|
NS_IMETHODIMP nsWindow::SetParent(nsIWidget *aNewParent)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aNewParent) {
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIWidget* parent = GetParent();
|
|
|
|
if (parent) {
|
|
|
|
parent->RemoveChild(this);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
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);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
aNewParent->AddChild(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIWidget* parent = GetParent();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (parent) {
|
|
|
|
parent->RemoveChild(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWnd) {
|
|
|
|
::SetParent(mWnd, nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIWidget* nsWindow::GetParent(void)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
return GetParentWindow(PR_FALSE);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsWindow* nsWindow::GetParentWindow(PRBool aIncludeOwner)
|
|
|
|
{
|
|
|
|
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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
if (mIsDestroying || mOnDestroyCalled)
|
|
|
|
return nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
|
2009-06-29 12:36:16 -07: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) {
|
|
|
|
#ifdef WINCE
|
|
|
|
HWND parent = ::GetParent(mWnd);
|
|
|
|
#else
|
|
|
|
HWND parent = nsnull;
|
|
|
|
if (aIncludeOwner)
|
|
|
|
parent = ::GetParent(mWnd);
|
|
|
|
else
|
|
|
|
parent = ::GetAncestor(mWnd, GA_PARENT);
|
|
|
|
#endif
|
|
|
|
if (parent) {
|
|
|
|
widget = GetNSWindowPtr(parent);
|
|
|
|
if (widget) {
|
|
|
|
// If the widget is in the process of being destroyed then
|
|
|
|
// do NOT return it
|
|
|
|
if (widget->mIsDestroying) {
|
|
|
|
widget = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return widget;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Show
|
|
|
|
*
|
|
|
|
* Hide or show this component.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_METHOD nsWindow::Show(PRBool bState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(MOZ_SPLASHSCREEN)
|
|
|
|
// we're about to show the first toplevel window,
|
|
|
|
// so kill off any splash screen if we had one
|
|
|
|
nsSplashScreen *splash = nsSplashScreen::Get();
|
|
|
|
if (splash && splash->IsOpen() && mWnd && bState &&
|
|
|
|
(mWindowType == eWindowType_toplevel ||
|
|
|
|
mWindowType == eWindowType_dialog ||
|
|
|
|
mWindowType == eWindowType_popup))
|
|
|
|
{
|
|
|
|
splash->Close();
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool wasVisible = mIsVisible;
|
|
|
|
// Set the status now so that anyone asking during ShowWindow or
|
|
|
|
// SetWindowPos would get the correct answer.
|
|
|
|
mIsVisible = bState;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWnd) {
|
|
|
|
if (bState) {
|
|
|
|
if (!wasVisible && mWindowType == eWindowType_toplevel) {
|
|
|
|
switch (mSizeMode) {
|
|
|
|
#ifdef WINCE
|
|
|
|
case nsSizeMode_Maximized :
|
|
|
|
::SetForegroundWindow(mWnd);
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMAXIMIZED);
|
|
|
|
break;
|
|
|
|
// use default for nsSizeMode_Minimized on Windows CE
|
|
|
|
#else
|
|
|
|
case nsSizeMode_Maximized :
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMAXIMIZED);
|
|
|
|
break;
|
|
|
|
case nsSizeMode_Minimized :
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMINIMIZED);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
if (CanTakeFocus()) {
|
|
|
|
#ifdef WINCE
|
|
|
|
::SetForegroundWindow(mWnd);
|
|
|
|
#endif
|
|
|
|
::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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWindowType == eWindowType_popup) {
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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
|
|
|
|
// the popup. However on windows ce, we need to
|
|
|
|
// activate the popup or clicks will not be sent.
|
|
|
|
flags |= SWP_NOACTIVATE;
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
HWND owner = ::GetWindow(mWnd, GW_OWNER);
|
|
|
|
::SetWindowPos(mWnd, owner ? 0 : HWND_TOPMOST, 0, 0, 0, 0, flags);
|
|
|
|
} else {
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWindowType == eWindowType_dialog && !CanTakeFocus())
|
|
|
|
flags |= SWP_NOACTIVATE;
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
::SetWindowPos(mWnd, HWND_TOP, 0, 0, 0, 0, flags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} 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);
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (!wasVisible && bState)
|
|
|
|
Invalidate(PR_FALSE);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::IsVisible
|
|
|
|
*
|
|
|
|
* Returns the visibility state.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
|
|
|
|
NS_METHOD nsWindow::IsVisible(PRBool & bState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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()
|
|
|
|
{
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsUXThemeData::sIsVistaOrLater && mTransparencyMode != eTransparencyGlass &&
|
|
|
|
mWindowType == eWindowType_popup && (mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel)) {
|
|
|
|
SetWindowRgn(mWnd, NULL, false);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
void nsWindow::SetThemeRegion()
|
|
|
|
{
|
|
|
|
#ifndef WINCE
|
|
|
|
// 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.
|
|
|
|
if (nsUXThemeData::sIsVistaOrLater && mTransparencyMode != eTransparencyGlass &&
|
|
|
|
mWindowType == eWindowType_popup && (mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel)) {
|
|
|
|
HRGN hRgn = nsnull;
|
|
|
|
RECT rect = {0,0,mBounds.width,mBounds.height};
|
|
|
|
|
|
|
|
nsUXThemeData::getThemeBackgroundRegion(nsUXThemeData::GetTheme(eUXTooltip), GetDC(mWnd), TTP_STANDARD, TS_NORMAL, &rect, &hRgn);
|
|
|
|
if (hRgn) {
|
|
|
|
if (!SetWindowRgn(mWnd, hRgn, false)) // do not delete or alter hRgn if accepted.
|
|
|
|
DeleteObject(hRgn);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Move, nsIWidget::Resize, nsIWidget::Size
|
|
|
|
*
|
|
|
|
* Repositioning and sizing a window.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Move this component
|
|
|
|
NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07: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
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
if (aX < 0 || aX >= workArea.right || aY < 0 || aY >= workArea.bottom)
|
|
|
|
printf("window moved to offscreen position\n");
|
|
|
|
}
|
|
|
|
::ReleaseDC(mWnd, dc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIWidget *par = GetParent();
|
|
|
|
HDWP deferrer = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull != par) {
|
|
|
|
deferrer = ((nsWindow *)par)->mDeferredPositioner;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (NULL != deferrer) {
|
|
|
|
VERIFY(((nsWindow *)par)->mDeferredPositioner = ::DeferWindowPos(deferrer,
|
|
|
|
mWnd, NULL, aX, aY, 0, 0,
|
|
|
|
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
else {
|
2009-06-29 12:36:16 -07:00
|
|
|
ClearThemeRegion();
|
|
|
|
VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, 0, 0,
|
|
|
|
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
|
|
|
|
SetThemeRegion();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Resize this component
|
|
|
|
NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
|
|
|
|
{
|
|
|
|
NS_ASSERTION((aWidth >=0 ) , "Negative width passed to nsWindow::Resize");
|
|
|
|
NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
ResizeTranslucentWindow(aWidth, aHeight);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Set cached value for lightweight and printing
|
|
|
|
mBounds.width = aWidth;
|
|
|
|
mBounds.height = aHeight;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWnd) {
|
|
|
|
nsIWidget *par = GetParent();
|
|
|
|
HDWP deferrer = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull != par) {
|
|
|
|
deferrer = ((nsWindow *)par)->mDeferredPositioner;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
|
|
|
|
#ifndef WINCE
|
|
|
|
if (!aRepaint) {
|
|
|
|
flags |= SWP_NOREDRAW;
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (NULL != deferrer) {
|
|
|
|
VERIFY(((nsWindow *)par)->mDeferredPositioner = ::DeferWindowPos(deferrer,
|
|
|
|
mWnd, NULL, 0, 0, aWidth, GetHeight(aHeight), flags));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ClearThemeRegion();
|
|
|
|
VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, aWidth, GetHeight(aHeight), flags));
|
|
|
|
SetThemeRegion();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aRepaint)
|
|
|
|
Invalidate(PR_FALSE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Resize this component
|
|
|
|
NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
|
|
|
|
{
|
|
|
|
NS_ASSERTION((aWidth >=0 ), "Negative width passed to nsWindow::Resize");
|
|
|
|
NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
ResizeTranslucentWindow(aWidth, aHeight);
|
|
|
|
#endif
|
2009-01-28 15:39:13 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Set cached value for lightweight and printing
|
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
|
|
|
mBounds.width = aWidth;
|
|
|
|
mBounds.height = aHeight;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWnd) {
|
|
|
|
nsIWidget *par = GetParent();
|
|
|
|
HDWP deferrer = NULL;
|
2009-01-28 15:39:13 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull != par) {
|
|
|
|
deferrer = ((nsWindow *)par)->mDeferredPositioner;
|
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
|
|
|
|
#ifndef WINCE
|
|
|
|
if (!aRepaint) {
|
|
|
|
flags |= SWP_NOREDRAW;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (NULL != deferrer) {
|
|
|
|
VERIFY(((nsWindow *)par)->mDeferredPositioner = ::DeferWindowPos(deferrer,
|
|
|
|
mWnd, NULL, aX, aY, aWidth, GetHeight(aHeight), flags));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ClearThemeRegion();
|
|
|
|
VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, aWidth, GetHeight(aHeight), flags));
|
|
|
|
SetThemeRegion();
|
|
|
|
}
|
2009-04-02 12:34:31 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aRepaint)
|
|
|
|
Invalidate(PR_FALSE);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Window Z-order and state.
|
|
|
|
*
|
|
|
|
* nsIWidget::PlaceBehind, nsIWidget::SetSizeMode,
|
|
|
|
* nsIWidget::ConstrainPosition
|
|
|
|
*
|
|
|
|
* Z-order, positioning, restore, minimize, and maximize.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Position the window behind the given window
|
|
|
|
NS_METHOD nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
|
|
|
|
nsIWidget *aWidget, PRBool aActivate)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
::SetWindowPos(mWnd, behind, 0, 0, 0, 0, flags);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Maximize, minimize or restore the window.
|
|
|
|
#if !defined(WINCE) // implemented in nsWindowCE.cpp
|
|
|
|
NS_IMETHODIMP nsWindow::SetSizeMode(PRInt32 aMode) {
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsresult rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// save the requested state
|
|
|
|
rv = nsBaseWidget::SetSizeMode(aMode);
|
|
|
|
if (NS_SUCCEEDED(rv) && mIsVisible) {
|
|
|
|
int mode;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (aMode) {
|
|
|
|
case nsSizeMode_Maximized :
|
|
|
|
mode = SW_MAXIMIZE;
|
|
|
|
break;
|
|
|
|
case nsSizeMode_Minimized :
|
|
|
|
mode = sTrimOnMinimize ? SW_MINIMIZE : SW_SHOWMINIMIZED;
|
|
|
|
if (!sTrimOnMinimize) {
|
|
|
|
// Find the next window that is visible and not minimized.
|
|
|
|
HWND hwndBelow = ::GetNextWindow(mWnd, GW_HWNDNEXT);
|
|
|
|
while (hwndBelow && (!::IsWindowVisible(hwndBelow) ||
|
|
|
|
::IsIconic(hwndBelow))) {
|
|
|
|
hwndBelow = ::GetNextWindow(hwndBelow, GW_HWNDNEXT);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Push ourselves to the bottom of the stack, then activate the
|
|
|
|
// next window.
|
|
|
|
::SetWindowPos(mWnd, HWND_BOTTOM, 0, 0, 0, 0,
|
|
|
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
|
|
if (hwndBelow)
|
|
|
|
::SetForegroundWindow(hwndBelow);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Play the minimize sound while we're here, since that is also
|
|
|
|
// forgotten when we use SW_SHOWMINIMIZED.
|
|
|
|
::PlaySoundW(L"Minimize", nsnull, SND_ALIAS | SND_NODEFAULT | SND_ASYNC);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
mode = SW_RESTORE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
::ShowWindow(mWnd, mode);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // !defined(WINCE)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Constrain a potential move to fit onscreen
|
|
|
|
NS_METHOD nsWindow::ConstrainPosition(PRBool aAllowSlop,
|
|
|
|
PRInt32 *aX, PRInt32 *aY)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!mIsTopWidgetWindow) // only a problem for top-level windows
|
|
|
|
return NS_OK;
|
2007-07-12 16:19:47 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool doConstrain = PR_FALSE; // whether we have enough info to do anything
|
2007-07-12 16:19:47 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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 16:19:47 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
|
|
|
|
if (screenmgr) {
|
|
|
|
nsCOMPtr<nsIScreen> screen;
|
|
|
|
PRInt32 left, top, width, height;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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) {
|
|
|
|
screen->GetAvailRect(&left, &top, &width, &height);
|
|
|
|
screenRect.left = left;
|
|
|
|
screenRect.right = left+width;
|
|
|
|
screenRect.top = top;
|
|
|
|
screenRect.bottom = top+height;
|
|
|
|
doConstrain = PR_TRUE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (mWnd) {
|
|
|
|
HDC dc = ::GetDC(mWnd);
|
|
|
|
if (dc) {
|
|
|
|
if (::GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
|
|
|
|
::SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
|
|
|
|
doConstrain = PR_TRUE;
|
|
|
|
}
|
|
|
|
::ReleaseDC(mWnd, dc);
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-08-13 13:47:04 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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 13:47:04 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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 13:47:04 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
} else {
|
2007-08-13 13:47:04 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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 13:47:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Enable, nsIWidget::IsEnabled
|
|
|
|
*
|
|
|
|
* Enabling and disabling the widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Enable/disable this component
|
|
|
|
NS_METHOD nsWindow::Enable(PRBool bState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWnd) {
|
|
|
|
::EnableWindow(mWnd, bState);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Return the current enable state
|
|
|
|
NS_METHOD nsWindow::IsEnabled(PRBool *aState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aState);
|
2008-09-09 10:22:12 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
*aState = !mWnd || (::IsWindowEnabled(mWnd) && ::IsWindowEnabled(::GetAncestor(mWnd, GA_ROOT)));
|
2009-04-19 12:39:37 -07:00
|
|
|
#else
|
2009-06-29 12:36:16 -07:00
|
|
|
*aState = !mWnd || (::IsWindowEnabled(mWnd) && ::IsWindowEnabled(mWnd));
|
2009-04-19 12:39:37 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetFocus
|
|
|
|
*
|
|
|
|
* Give the focus to this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_METHOD nsWindow::SetFocus(PRBool aRaise)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
// Switch to the "main gui thread" if necessary... This method must
|
|
|
|
// be executed on the "gui thread"...
|
|
|
|
nsToolkit* toolkit = (nsToolkit *)mToolkit;
|
|
|
|
NS_ASSERTION(toolkit != nsnull, "This should never be null!"); // Bug 57044
|
|
|
|
if (toolkit != nsnull && !toolkit->IsGuiThread()) {
|
|
|
|
MethodInfo info(this, nsWindow::SET_FOCUS);
|
|
|
|
toolkit->CallMethod(&info);
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWnd) {
|
|
|
|
// Uniconify, if necessary
|
|
|
|
HWND toplevelWnd = GetTopLevelHWND(mWnd);
|
|
|
|
if (::IsIconic(toplevelWnd))
|
|
|
|
::ShowWindow(toplevelWnd, SW_RESTORE);
|
|
|
|
::SetFocus(mWnd);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-16 11:59:35 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Bounds
|
|
|
|
*
|
|
|
|
* nsIWidget::GetBounds, nsIWidget::GetScreenBounds,
|
|
|
|
* nsIWidget::GetClientBounds
|
|
|
|
*
|
|
|
|
* Bound calculations.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2008-08-01 10:32:32 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Get this component dimension
|
|
|
|
NS_METHOD nsWindow::GetBounds(nsIntRect &aRect)
|
|
|
|
{
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mWnd) {
|
2009-06-29 12:36:16 -07:00
|
|
|
RECT r;
|
|
|
|
VERIFY(::GetWindowRect(mWnd, &r));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// assign size
|
|
|
|
aRect.width = r.right - r.left;
|
|
|
|
aRect.height = r.bottom - r.top;
|
|
|
|
|
|
|
|
// 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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
aRect.x = r.left;
|
|
|
|
aRect.y = r.top;
|
|
|
|
} else {
|
|
|
|
aRect = mBounds;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Get this component dimension
|
|
|
|
NS_METHOD nsWindow::GetClientBounds(nsIntRect &aRect)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mWnd) {
|
|
|
|
RECT r;
|
|
|
|
VERIFY(::GetClientRect(mWnd, &r));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// assign size
|
|
|
|
aRect.x = 0;
|
|
|
|
aRect.y = 0;
|
|
|
|
aRect.width = r.right - r.left;
|
|
|
|
aRect.height = r.bottom - r.top;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
} else {
|
|
|
|
aRect.SetRect(0,0,0,0);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Get the bounds, but don't take into account the client size
|
|
|
|
void nsWindow::GetNonClientBounds(nsIntRect &aRect)
|
|
|
|
{
|
|
|
|
if (mWnd) {
|
|
|
|
RECT r;
|
|
|
|
VERIFY(::GetWindowRect(mWnd, &r));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// assign size
|
|
|
|
aRect.width = r.right - r.left;
|
|
|
|
aRect.height = r.bottom - r.top;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
}
|
|
|
|
aRect.x = r.left;
|
|
|
|
aRect.y = r.top;
|
|
|
|
} else {
|
|
|
|
aRect.SetRect(0,0,0,0);
|
2009-02-09 12:07:14 -08:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2009-02-09 12:07:14 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Like GetBounds, but don't offset by the parent
|
|
|
|
NS_METHOD nsWindow::GetScreenBounds(nsIntRect &aRect)
|
|
|
|
{
|
|
|
|
if (mWnd) {
|
|
|
|
RECT r;
|
|
|
|
VERIFY(::GetWindowRect(mWnd, &r));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
aRect.width = r.right - r.left;
|
|
|
|
aRect.height = r.bottom - r.top;
|
|
|
|
aRect.x = r.left;
|
|
|
|
aRect.y = r.top;
|
|
|
|
} else
|
|
|
|
aRect = mBounds;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-05-02 02:24:52 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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));
|
|
|
|
#ifndef WINCE
|
|
|
|
if (mWnd != NULL) {
|
|
|
|
::SetClassLongPtrW(mWnd, GCLP_HBRBACKGROUND, (LONG_PTR)mBrush);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetCursor
|
|
|
|
*
|
|
|
|
* SetCursor and related utilities for manging cursor state.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Set this component cursor
|
|
|
|
NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
// Only change cursor if it's changing
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (aCursor) {
|
|
|
|
case eCursor_select:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_IBEAM);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_wait:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_WAIT);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_hyperlink:
|
|
|
|
{
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_HAND);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_standard:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_ARROW);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_n_resize:
|
|
|
|
case eCursor_s_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENS);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_w_resize:
|
|
|
|
case eCursor_e_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEWE);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_nw_resize:
|
|
|
|
case eCursor_se_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENWSE);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_ne_resize:
|
|
|
|
case eCursor_sw_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENESW);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_crosshair:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_CROSS);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_move:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEALL);
|
|
|
|
break;
|
2009-03-24 17:51:57 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_help:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_HELP);
|
|
|
|
break;
|
2009-03-24 17:51:57 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_copy: // CSS3
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_COPY));
|
|
|
|
break;
|
2009-03-24 17:51:57 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_alias:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ALIAS));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_cell:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_CELL));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_grab:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_GRAB));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_grabbing:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_GRABBING));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_spinning:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_APPSTARTING);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_context_menu:
|
|
|
|
// XXX this CSS3 cursor needs to be implemented
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_zoom_in:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ZOOMIN));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_zoom_out:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ZOOMOUT));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_not_allowed:
|
|
|
|
case eCursor_no_drop:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_NO);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_col_resize:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_COLRESIZE));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_row_resize:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ROWRESIZE));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_vertical_text:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_VERTICALTEXT));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_all_scroll:
|
|
|
|
// XXX not 100% appropriate perhaps
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEALL);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_nesw_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENESW);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_nwse_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENWSE);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_ns_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZENS);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_ew_resize:
|
|
|
|
newCursor = ::LoadCursor(NULL, IDC_SIZEWE);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case eCursor_none:
|
|
|
|
newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_NONE));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
NS_ERROR("Invalid cursor type");
|
|
|
|
break;
|
|
|
|
}
|
2009-03-24 17:51:57 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (NULL != newCursor) {
|
|
|
|
mCursor = aCursor;
|
|
|
|
HCURSOR oldCursor = ::SetCursor(newCursor);
|
|
|
|
|
|
|
|
if (sHCursor == oldCursor) {
|
|
|
|
NS_IF_RELEASE(sCursorImgContainer);
|
|
|
|
if (sHCursor != NULL)
|
|
|
|
::DestroyIcon(sHCursor);
|
|
|
|
sHCursor = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Adjust cursor image data
|
|
|
|
PRUint8* nsWindow::Data32BitTo1Bit(PRUint8* aImageData,
|
|
|
|
PRUint32 aWidth, PRUint32 aHeight)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
// We need (aWidth + 7) / 8 bytes plus zero-padding up to a multiple of
|
|
|
|
// 4 bytes for each row (HBITMAP requirement). Bug 353553.
|
|
|
|
PRUint32 outBpr = ((aWidth + 31) / 8) & ~3;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Allocate and clear mask buffer
|
|
|
|
PRUint8* outData = (PRUint8*)PR_Calloc(outBpr, aHeight);
|
|
|
|
if (!outData)
|
|
|
|
return NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRInt32 *imageRow = (PRInt32*)aImageData;
|
|
|
|
for (PRUint32 curRow = 0; curRow < aHeight; curRow++) {
|
|
|
|
PRUint8 *outRow = outData + curRow * outBpr;
|
|
|
|
PRUint8 mask = 0x80;
|
|
|
|
for (PRUint32 curCol = 0; curCol < aWidth; curCol++) {
|
|
|
|
// Use sign bit to test for transparency, as alpha byte is highest byte
|
|
|
|
if (*imageRow++ < 0)
|
|
|
|
*outRow |= mask;
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mask >>= 1;
|
|
|
|
if (!mask) {
|
|
|
|
outRow ++;
|
|
|
|
mask = 0x80;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-05 10:17:44 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return outData;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::IsCursorTranslucencySupported()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef WINCE
|
|
|
|
return PR_FALSE;
|
|
|
|
#else
|
|
|
|
static PRBool didCheck = PR_FALSE;
|
|
|
|
static PRBool isSupported = PR_FALSE;
|
|
|
|
if (!didCheck) {
|
|
|
|
didCheck = PR_TRUE;
|
|
|
|
// Cursor translucency is supported on Windows XP and newer
|
|
|
|
isSupported = nsWindow::GetWindowsVersion() >= 0x501;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return isSupported;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**
|
|
|
|
* Convert the given image data to a HBITMAP. If the requested depth is
|
|
|
|
* 32 bit and the OS supports translucency, a bitmap with an alpha channel
|
|
|
|
* will be returned.
|
|
|
|
*
|
|
|
|
* @param aImageData The image data to convert. Must use the format accepted
|
|
|
|
* by CreateDIBitmap.
|
|
|
|
* @param aWidth With of the bitmap, in pixels.
|
|
|
|
* @param aHeight Height of the image, in pixels.
|
|
|
|
* @param aDepth Image depth, in bits. Should be one of 1, 24 and 32.
|
|
|
|
*
|
|
|
|
* @return The HBITMAP representing the image. Caller should call
|
|
|
|
* DeleteObject when done with the bitmap.
|
|
|
|
* On failure, NULL will be returned.
|
|
|
|
*/
|
|
|
|
HBITMAP nsWindow::DataToBitmap(PRUint8* aImageData,
|
|
|
|
PRUint32 aWidth,
|
|
|
|
PRUint32 aHeight,
|
|
|
|
PRUint32 aDepth)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
HDC dc = ::GetDC(NULL);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aDepth == 32 && IsCursorTranslucencySupported()) {
|
|
|
|
// Alpha channel. We need the new header.
|
|
|
|
BITMAPV4HEADER head = { 0 };
|
|
|
|
head.bV4Size = sizeof(head);
|
|
|
|
head.bV4Width = aWidth;
|
|
|
|
head.bV4Height = aHeight;
|
|
|
|
head.bV4Planes = 1;
|
|
|
|
head.bV4BitCount = aDepth;
|
|
|
|
head.bV4V4Compression = BI_BITFIELDS;
|
|
|
|
head.bV4SizeImage = 0; // Uncompressed
|
|
|
|
head.bV4XPelsPerMeter = 0;
|
|
|
|
head.bV4YPelsPerMeter = 0;
|
|
|
|
head.bV4ClrUsed = 0;
|
|
|
|
head.bV4ClrImportant = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
head.bV4RedMask = 0x00FF0000;
|
|
|
|
head.bV4GreenMask = 0x0000FF00;
|
|
|
|
head.bV4BlueMask = 0x000000FF;
|
|
|
|
head.bV4AlphaMask = 0xFF000000;
|
|
|
|
|
|
|
|
HBITMAP bmp = ::CreateDIBitmap(dc,
|
|
|
|
reinterpret_cast<CONST BITMAPINFOHEADER*>(&head),
|
|
|
|
CBM_INIT,
|
|
|
|
aImageData,
|
|
|
|
reinterpret_cast<CONST BITMAPINFO*>(&head),
|
|
|
|
DIB_RGB_COLORS);
|
|
|
|
::ReleaseDC(NULL, dc);
|
|
|
|
return bmp;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
char reserved_space[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2];
|
|
|
|
BITMAPINFOHEADER& head = *(BITMAPINFOHEADER*)reserved_space;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
head.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
head.biWidth = aWidth;
|
|
|
|
head.biHeight = aHeight;
|
|
|
|
head.biPlanes = 1;
|
|
|
|
head.biBitCount = (WORD)aDepth;
|
|
|
|
head.biCompression = BI_RGB;
|
|
|
|
head.biSizeImage = 0; // Uncompressed
|
|
|
|
head.biXPelsPerMeter = 0;
|
|
|
|
head.biYPelsPerMeter = 0;
|
|
|
|
head.biClrUsed = 0;
|
|
|
|
head.biClrImportant = 0;
|
|
|
|
|
|
|
|
BITMAPINFO& bi = *(BITMAPINFO*)reserved_space;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aDepth == 1) {
|
|
|
|
RGBQUAD black = { 0, 0, 0, 0 };
|
|
|
|
RGBQUAD white = { 255, 255, 255, 0 };
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
bi.bmiColors[0] = white;
|
|
|
|
bi.bmiColors[1] = black;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
HBITMAP bmp = ::CreateDIBitmap(dc, &head, CBM_INIT, aImageData, &bi, DIB_RGB_COLORS);
|
|
|
|
::ReleaseDC(NULL, dc);
|
|
|
|
return bmp;
|
|
|
|
#else
|
|
|
|
return nsnull;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Setting the actual cursor
|
|
|
|
NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
|
|
|
|
PRUint32 aHotspotX, PRUint32 aHotspotY)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sCursorImgContainer == aCursor && sHCursor) {
|
|
|
|
::SetCursor(sHCursor);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Get the image data
|
|
|
|
nsCOMPtr<gfxIImageFrame> frame;
|
|
|
|
aCursor->GetFrameAt(0, getter_AddRefs(frame));
|
|
|
|
if (!frame)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRInt32 width, height;
|
|
|
|
frame->GetWidth(&width);
|
|
|
|
frame->GetHeight(&height);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
frame->LockImageData();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRUint32 dataLen;
|
|
|
|
PRUint8 *data;
|
|
|
|
nsresult rv = frame->GetImageData(&data, &dataLen);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
frame->UnlockImageData();
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
HBITMAP bmp = DataToBitmap(data, width, -height, 32);
|
|
|
|
PRUint8* a1data = Data32BitTo1Bit(data, width, height);
|
|
|
|
frame->UnlockImageData();
|
|
|
|
if (!a1data) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
HBITMAP mbmp = DataToBitmap(a1data, width, -height, 1);
|
|
|
|
PR_Free(a1data);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
ICONINFO info = {0};
|
|
|
|
info.fIcon = FALSE;
|
|
|
|
info.xHotspot = aHotspotX;
|
|
|
|
info.yHotspot = aHotspotY;
|
|
|
|
info.hbmMask = mbmp;
|
|
|
|
info.hbmColor = bmp;
|
|
|
|
|
|
|
|
HCURSOR cursor = ::CreateIconIndirect(&info);
|
|
|
|
::DeleteObject(mbmp);
|
|
|
|
::DeleteObject(bmp);
|
|
|
|
if (cursor == NULL) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mCursor = nsCursor(-1);
|
|
|
|
::SetCursor(cursor);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_IF_RELEASE(sCursorImgContainer);
|
|
|
|
sCursorImgContainer = aCursor;
|
|
|
|
NS_ADDREF(sCursorImgContainer);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sHCursor != NULL)
|
|
|
|
::DestroyIcon(sHCursor);
|
|
|
|
sHCursor = cursor;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Get/SetTransparencyMode
|
|
|
|
*
|
|
|
|
* Manage the transparency mode of the top-level window
|
|
|
|
* containing this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
nsTransparencyMode nsWindow::GetTransparencyMode()
|
|
|
|
{
|
|
|
|
return GetTopLevelWindow(PR_TRUE)->GetWindowTranslucencyInner();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
void nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
|
|
|
|
{
|
|
|
|
GetTopLevelWindow(PR_TRUE)->SetWindowTranslucencyInner(aMode);
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::HideWindowChrome
|
|
|
|
*
|
|
|
|
* Show or hide window chrome.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_IMETHODIMP nsWindow::HideWindowChrome(PRBool aShouldHide)
|
|
|
|
{
|
|
|
|
HWND hwnd = GetTopLevelHWND(mWnd, PR_TRUE);
|
|
|
|
if (!GetNSWindowPtr(hwnd))
|
|
|
|
{
|
|
|
|
NS_WARNING("Trying to hide window decorations in an embedded context");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
DWORD_PTR style, exStyle;
|
|
|
|
if (aShouldHide) {
|
|
|
|
DWORD_PTR tempStyle = ::GetWindowLongPtrW(hwnd, GWL_STYLE);
|
|
|
|
DWORD_PTR tempExStyle = ::GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
style = tempStyle & ~(WS_CAPTION | WS_THICKFRAME);
|
|
|
|
exStyle = tempExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE |
|
|
|
|
WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mOldStyle = tempStyle;
|
|
|
|
mOldExStyle = tempExStyle;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!mOldStyle || !mOldExStyle) {
|
|
|
|
mOldStyle = ::GetWindowLongPtrW(hwnd, GWL_STYLE);
|
|
|
|
mOldExStyle = ::GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
style = mOldStyle;
|
|
|
|
exStyle = mOldExStyle;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
VERIFY_WINDOW_STYLE(style);
|
|
|
|
::SetWindowLongPtrW(hwnd, GWL_STYLE, style);
|
|
|
|
::SetWindowLongPtrW(hwnd, GWL_EXSTYLE, exStyle);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Validate, nsIWidget::Invalidate
|
|
|
|
*
|
|
|
|
* Validate or invalidate an area of the client for painting.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Validate a visible area of a widget.
|
|
|
|
NS_METHOD nsWindow::Validate()
|
|
|
|
{
|
|
|
|
if (mWnd)
|
|
|
|
VERIFY(::ValidateRect(mWnd, NULL));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Invalidate this component visible area
|
|
|
|
NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
|
|
|
|
{
|
|
|
|
if (mWnd)
|
|
|
|
{
|
|
|
|
#ifdef WIDGET_DEBUG_OUTPUT
|
|
|
|
debug_DumpInvalidate(stdout,
|
|
|
|
this,
|
|
|
|
nsnull,
|
|
|
|
aIsSynchronous,
|
|
|
|
nsCAutoString("noname"),
|
|
|
|
(PRInt32) mWnd);
|
|
|
|
#endif // WIDGET_DEBUG_OUTPUT
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
VERIFY(::InvalidateRect(mWnd, NULL, FALSE));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aIsSynchronous) {
|
|
|
|
VERIFY(::UpdateWindow(mWnd));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Invalidate this component visible area
|
|
|
|
NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect, PRBool aIsSynchronous)
|
|
|
|
{
|
|
|
|
if (mWnd)
|
|
|
|
{
|
|
|
|
#ifdef WIDGET_DEBUG_OUTPUT
|
|
|
|
debug_DumpInvalidate(stdout,
|
|
|
|
this,
|
|
|
|
&aRect,
|
|
|
|
aIsSynchronous,
|
|
|
|
nsCAutoString("noname"),
|
|
|
|
(PRInt32) mWnd);
|
|
|
|
#endif // WIDGET_DEBUG_OUTPUT
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
RECT rect;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
rect.left = aRect.x;
|
|
|
|
rect.top = aRect.y;
|
|
|
|
rect.right = aRect.x + aRect.width;
|
|
|
|
rect.bottom = aRect.y + aRect.height;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
VERIFY(::InvalidateRect(mWnd, &rect, FALSE));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aIsSynchronous) {
|
|
|
|
VERIFY(::UpdateWindow(mWnd));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Update
|
|
|
|
*
|
|
|
|
* Force a synchronous repaint of the window.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_IMETHODIMP nsWindow::Update()
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// updates can come through for windows no longer holding an mWnd during
|
|
|
|
// deletes triggered by JavaScript in buttons with mouse feedback
|
|
|
|
if (mWnd)
|
|
|
|
VERIFY(::UpdateWindow(mWnd));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return rv;
|
|
|
|
}
|
2008-01-18 10:39:49 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::Scroll
|
|
|
|
*
|
|
|
|
* Scroll this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Invalidates a window if it's not one of ours, for example
|
|
|
|
// a window created by a plugin.
|
|
|
|
BOOL CALLBACK nsWindow::InvalidateForeignChildWindows(HWND aWnd, LPARAM aMsg)
|
|
|
|
{
|
|
|
|
LONG_PTR proc = ::GetWindowLongPtrW(aWnd, GWLP_WNDPROC);
|
|
|
|
if (proc != (LONG_PTR)&nsWindow::WindowProc) {
|
|
|
|
// This window is not one of our windows so invalidate it.
|
|
|
|
VERIFY(::InvalidateRect(aWnd, NULL, FALSE));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Scroll
|
|
|
|
NS_METHOD nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect)
|
2007-08-21 01:40:41 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
RECT trect;
|
2007-09-27 09:38:26 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull != aClipRect)
|
|
|
|
{
|
|
|
|
trect.left = aClipRect->x;
|
|
|
|
trect.top = aClipRect->y;
|
|
|
|
trect.right = aClipRect->XMost();
|
|
|
|
trect.bottom = aClipRect->YMost();
|
2007-08-21 01:40:41 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
::ScrollWindowEx(mWnd, aDx, aDy, NULL, (nsnull != aClipRect) ? &trect : NULL,
|
|
|
|
NULL, NULL, SW_INVALIDATE | SW_SCROLLCHILDREN);
|
|
|
|
// Invalidate all child windows that aren't ours; we're moving them, and we
|
|
|
|
// expect them to be painted at the new location even if they're outside the
|
|
|
|
// region we're bit-blit scrolling. See bug 387701.
|
|
|
|
#if !defined(WINCE)
|
|
|
|
::EnumChildWindows(GetWindowHandle(), nsWindow::InvalidateForeignChildWindows, NULL);
|
|
|
|
#else
|
|
|
|
nsWindowCE::EnumChildWindows(GetWindowHandle(), nsWindow::InvalidateForeignChildWindows, NULL);
|
|
|
|
#endif
|
|
|
|
::UpdateWindow(mWnd);
|
|
|
|
return NS_OK;
|
2007-08-21 01:40:41 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
2007-09-27 09:38:26 -07:00
|
|
|
*
|
2009-06-29 12:36:16 -07:00
|
|
|
* SECTION: Native data storage
|
2007-09-27 09:38:26 -07:00
|
|
|
*
|
2009-06-29 12:36:16 -07:00
|
|
|
* nsIWidget::GetNativeData
|
|
|
|
* nsIWidget::FreeNativeData
|
|
|
|
*
|
|
|
|
* Set or clear native data based on a constant.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Return some native data according to aDataType
|
|
|
|
void* nsWindow::GetNativeData(PRUint32 aDataType)
|
|
|
|
{
|
|
|
|
switch (aDataType) {
|
2008-11-26 21:42:18 -08:00
|
|
|
case NS_NATIVE_PLUGIN_PORT:
|
|
|
|
mIsPluginWindow = 1;
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_NATIVE_WIDGET:
|
|
|
|
case NS_NATIVE_WINDOW:
|
|
|
|
return (void*)mWnd;
|
|
|
|
case NS_NATIVE_GRAPHIC:
|
|
|
|
// XXX: This is sleezy!! Remember to Release the DC after using it!
|
|
|
|
#ifdef MOZ_XUL
|
2008-08-12 17:44:14 -07:00
|
|
|
return (void*)(eTransparencyTransparent == mTransparencyMode) ?
|
2007-03-22 10:30:00 -07:00
|
|
|
mMemoryDC : ::GetDC(mWnd);
|
|
|
|
#else
|
|
|
|
return (void*)::GetDC(mWnd);
|
|
|
|
#endif
|
2009-02-10 12:56:51 -08:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
2009-02-23 00:56:33 -08: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 12:56:51 -08:00
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Free some native data according to aDataType
|
2007-03-22 10:30:00 -07:00
|
|
|
void nsWindow::FreeNativeData(void * data, PRUint32 aDataType)
|
|
|
|
{
|
|
|
|
switch (aDataType)
|
|
|
|
{
|
|
|
|
case NS_NATIVE_GRAPHIC:
|
|
|
|
#ifdef MOZ_XUL
|
2008-08-12 17:44:14 -07:00
|
|
|
if (eTransparencyTransparent != mTransparencyMode)
|
2007-03-22 10:30:00 -07:00
|
|
|
::ReleaseDC(mWnd, (HDC)data);
|
|
|
|
#else
|
|
|
|
::ReleaseDC(mWnd, (HDC)data);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case NS_NATIVE_WIDGET:
|
|
|
|
case NS_NATIVE_WINDOW:
|
|
|
|
case NS_NATIVE_PLUGIN_PORT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetTitle
|
|
|
|
*
|
|
|
|
* Set the main windows title text.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_METHOD nsWindow::SetTitle(const nsAString& aTitle)
|
2007-11-07 00:54:06 -08:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
const nsString& strTitle = PromiseFlatString(aTitle);
|
|
|
|
::SendMessageW(mWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)(LPCWSTR)strTitle.get());
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-11-07 00:54:06 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::SetIcon
|
|
|
|
*
|
|
|
|
* Set the main windows icon.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
NS_METHOD nsWindow::SetIcon(const nsAString& aIconSpec)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
// Assume the given string is a local identifier for an icon file.
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
|
|
|
printf( "\nIcon load error; icon=%s, rc=0x%08X\n\n", cPath.get(), ::GetLastError() );
|
|
|
|
}
|
|
|
|
#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);
|
|
|
|
printf( "\nSmall icon load error; icon=%s, rc=0x%08X\n\n", cPath.get(), ::GetLastError() );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif // WINCE
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::WidgetToScreenOffset
|
|
|
|
*
|
|
|
|
* Return this widget's origin in screen coordinates.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIntPoint nsWindow::WidgetToScreenOffset()
|
|
|
|
{
|
|
|
|
POINT point;
|
|
|
|
point.x = 0;
|
|
|
|
point.y = 0;
|
|
|
|
::ClientToScreen(mWnd, &point);
|
|
|
|
return nsIntPoint(point.x, point.y);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Deferred window positioning.
|
|
|
|
*
|
|
|
|
* nsIWidget::BeginResizingChildren,
|
|
|
|
* nsIWidget::EndResizingChildren
|
|
|
|
*
|
|
|
|
* Filters child paint events during a resize operation.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_METHOD nsWindow::BeginResizingChildren(void)
|
|
|
|
{
|
|
|
|
if (NULL == mDeferredPositioner)
|
|
|
|
mDeferredPositioner = ::BeginDeferWindowPos(1);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_METHOD nsWindow::EndResizingChildren(void)
|
|
|
|
{
|
|
|
|
if (NULL != mDeferredPositioner) {
|
|
|
|
::EndDeferWindowPos(mDeferredPositioner);
|
|
|
|
mDeferredPositioner = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
LPARAM nsWindow::lParamToClient(LPARAM lParam)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
POINT pt;
|
|
|
|
pt.x = GET_X_LPARAM(lParam);
|
|
|
|
pt.y = GET_Y_LPARAM(lParam);
|
|
|
|
::ScreenToClient(mWnd, &pt);
|
|
|
|
return MAKELPARAM(pt.x, pt.y);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::EnableDragDrop
|
|
|
|
*
|
|
|
|
* Enables/Disables drag and drop of files on this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
#if !defined(WINCE) // implemented in nsWindowCE.cpp
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_METHOD nsWindow::EnableDragDrop(PRBool aEnable)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (nsnull != mWnd && NULL != mNativeDragTarget) {
|
|
|
|
::RevokeDragDrop(mWnd);
|
|
|
|
if (S_OK == ::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget, FALSE, TRUE)) {
|
|
|
|
rv = NS_OK;
|
|
|
|
}
|
2007-09-28 15:45:14 -07:00
|
|
|
mNativeDragTarget->mDragCancelled = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_RELEASE(mNativeDragTarget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::CaptureMouse
|
|
|
|
*
|
|
|
|
* Enables/Disables system mouse capture.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
NS_METHOD nsWindow::CaptureMouse(PRBool aCapture)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!nsToolkit::gMouseTrailer) {
|
|
|
|
NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aCapture) {
|
|
|
|
nsToolkit::gMouseTrailer->SetCaptureWindow(mWnd);
|
|
|
|
::SetCapture(mWnd);
|
|
|
|
} else {
|
|
|
|
nsToolkit::gMouseTrailer->SetCaptureWindow(NULL);
|
|
|
|
::ReleaseCapture();
|
|
|
|
}
|
|
|
|
mIsInMouseCapture = aCapture;
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener,
|
|
|
|
PRBool aDoCapture,
|
|
|
|
PRBool aConsumeRollupEvent)
|
|
|
|
{
|
|
|
|
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(sRollupListener);
|
|
|
|
NS_IF_RELEASE(sRollupWidget);
|
|
|
|
sRollupListener = aListener;
|
|
|
|
NS_ADDREF(aListener);
|
|
|
|
sRollupWidget = this;
|
|
|
|
NS_ADDREF(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
if (!sMsgFilterHook && !sCallProcHook && !sCallMouseHook) {
|
|
|
|
RegisterSpecialDropdownHooks();
|
|
|
|
}
|
|
|
|
sProcessHook = PR_TRUE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} else {
|
|
|
|
NS_IF_RELEASE(sRollupListener);
|
|
|
|
NS_IF_RELEASE(sRollupWidget);
|
|
|
|
|
|
|
|
#ifndef WINCE
|
|
|
|
sProcessHook = PR_FALSE;
|
|
|
|
UnregisterSpecialDropdownHooks();
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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)
|
|
|
|
{
|
|
|
|
#ifndef WINCE
|
|
|
|
// Got window?
|
|
|
|
if (!mWnd)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
// Don't flash if the flash count is 0 or if the
|
|
|
|
// top level window is already active.
|
|
|
|
HWND fgWnd = ::GetForegroundWindow();
|
|
|
|
if (aCycleCount == 0 || fgWnd == GetTopLevelHWND(mWnd))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
HWND flashWnd = mWnd;
|
|
|
|
while (HWND ownerWnd = ::GetWindow(flashWnd, GW_OWNER)) {
|
|
|
|
flashWnd = ownerWnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't flash if the owner window is active either.
|
|
|
|
if (fgWnd == flashWnd)
|
|
|
|
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);
|
|
|
|
#endif
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
void nsWindow::StopFlashing()
|
2008-12-14 19:54:54 -08:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
HWND flashWnd = mWnd;
|
|
|
|
while (HWND ownerWnd = ::GetWindow(flashWnd, GW_OWNER)) {
|
|
|
|
flashWnd = ownerWnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
FLASHWINFO flashInfo = { sizeof(FLASHWINFO), flashWnd,
|
|
|
|
FLASHW_STOP, 0, 0 };
|
|
|
|
::FlashWindowEx(&flashInfo);
|
|
|
|
#endif
|
2008-12-14 19:54:54 -08:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::HasPendingInputEvent
|
|
|
|
*
|
|
|
|
* Ask whether there user input events pending. All input events are
|
|
|
|
* included, including those not targeted at this nsIwidget instance.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsWindow::HasPendingInputEvent()
|
2008-04-29 21:12:15 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
WORD qstatus = HIWORD(GetQueueStatus(QS_INPUT));
|
|
|
|
nsToolkit* toolkit = (nsToolkit *)mToolkit;
|
|
|
|
return qstatus || (toolkit && toolkit->UserIsMovingWindow());
|
|
|
|
}
|
2008-04-29 21:12:15 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::GetThebesSurface
|
|
|
|
*
|
|
|
|
* Get the Thebes surface associated with this widget.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
gfxASurface *nsWindow::GetThebesSurface()
|
|
|
|
{
|
|
|
|
if (mPaintDC)
|
|
|
|
return (new gfxWindowsSurface(mPaintDC));
|
|
|
|
|
|
|
|
return (new gfxWindowsSurface(mWnd));
|
2008-04-29 21:12:15 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: nsSwitchToUIThread impl.
|
|
|
|
**
|
|
|
|
** Switch thread to match the thread the widget was created
|
|
|
|
** in so messages will be dispatched.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2008-05-05 16:01:07 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsSwitchToUIThread::CallMethod
|
|
|
|
*
|
|
|
|
* Every function that needs a thread switch goes through this function
|
|
|
|
* by calling SendMessage (..WM_CALLMETHOD..) in nsToolkit::CallMethod.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
BOOL nsWindow::CallMethod(MethodInfo *info)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
BOOL bRet = TRUE;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (info->methodId) {
|
|
|
|
case nsWindow::CREATE:
|
|
|
|
NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
|
|
|
|
Create((nsIWidget*)(info->args[0]),
|
|
|
|
(nsIntRect&)*(nsIntRect*)(info->args[1]),
|
|
|
|
(EVENT_CALLBACK)(info->args[2]),
|
|
|
|
(nsIDeviceContext*)(info->args[3]),
|
|
|
|
(nsIAppShell *)(info->args[4]),
|
|
|
|
(nsIToolkit*)(info->args[5]),
|
|
|
|
(nsWidgetInitData*)(info->args[6]));
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case nsWindow::CREATE_NATIVE:
|
|
|
|
NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
|
|
|
|
Create((nsNativeWidget)(info->args[0]),
|
|
|
|
(nsIntRect&)*(nsIntRect*)(info->args[1]),
|
|
|
|
(EVENT_CALLBACK)(info->args[2]),
|
|
|
|
(nsIDeviceContext*)(info->args[3]),
|
|
|
|
(nsIAppShell *)(info->args[4]),
|
|
|
|
(nsIToolkit*)(info->args[5]),
|
|
|
|
(nsWidgetInitData*)(info->args[6]));
|
|
|
|
return TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case nsWindow::DESTROY:
|
|
|
|
NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
|
|
|
|
Destroy();
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case nsWindow::SET_FOCUS:
|
|
|
|
NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
|
|
|
|
SetFocus(PR_FALSE);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
bRet = FALSE;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Moz Events
|
|
|
|
**
|
|
|
|
** Moz GUI event management.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Mozilla event initialization
|
|
|
|
*
|
|
|
|
* Helpers for initializing moz events.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Event intialization
|
|
|
|
MSG nsWindow::InitMSG(UINT aMessage, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2007-03-22 10:30:00 -07:00
|
|
|
MSG msg;
|
2009-06-29 12:36:16 -07:00
|
|
|
msg.message = aMessage;
|
|
|
|
msg.wParam = wParam;
|
|
|
|
msg.lParam = lParam;
|
|
|
|
return msg;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
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-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
DWORD pos = ::GetMessagePos();
|
|
|
|
POINT cpos;
|
|
|
|
|
|
|
|
cpos.x = GET_X_LPARAM(pos);
|
|
|
|
cpos.y = GET_Y_LPARAM(pos);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
::ScreenToClient(mWnd, &cpos);
|
|
|
|
event.refPoint.x = cpos.x;
|
|
|
|
event.refPoint.y = cpos.y;
|
|
|
|
} else {
|
|
|
|
event.refPoint.x = 0;
|
|
|
|
event.refPoint.y = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
else {
|
|
|
|
// use the point override if provided
|
|
|
|
event.refPoint.x = aPoint->x;
|
|
|
|
event.refPoint.y = aPoint->y;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.time = ::GetMessageTime();
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mLastPoint = event.refPoint;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Moz event dispatch helpers
|
|
|
|
*
|
|
|
|
* Helpers for dispatching different types of moz events.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2008-05-05 16:01:07 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Main event dispatch. Invokes callback and ProcessEvent method on
|
|
|
|
// Event Listener object. Part of nsIWidget.
|
|
|
|
NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef WIDGET_DEBUG_OUTPUT
|
|
|
|
debug_DumpEvent(stdout,
|
|
|
|
event->widget,
|
|
|
|
event,
|
|
|
|
nsCAutoString("something"),
|
|
|
|
(PRInt32) mWnd);
|
|
|
|
#endif // WIDGET_DEBUG_OUTPUT
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
aStatus = nsEventStatus_eIgnore;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// skip processing of suppressed blur events
|
|
|
|
if (event->message == NS_DEACTIVATE && BlurEventsSuppressed())
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull != mEventCallback) {
|
|
|
|
aStatus = (*mEventCallback)(event);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Dispatch to event listener if event was not consumed
|
|
|
|
if ((aStatus != nsEventStatus_eIgnore) && (nsnull != mEventListener)) {
|
|
|
|
aStatus = mEventListener->ProcessEvent(*event);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::DispatchStandardEvent(PRUint32 aMsg)
|
|
|
|
{
|
|
|
|
nsGUIEvent event(PR_TRUE, aMsg, this);
|
|
|
|
InitEvent(event);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool result = DispatchWindowEvent(&event);
|
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
|
|
|
|
{
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(event, status);
|
|
|
|
return ConvertStatus(status);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::DispatchWindowEvent(nsGUIEvent* event, nsEventStatus &aStatus) {
|
|
|
|
DispatchEvent(event, aStatus);
|
|
|
|
return ConvertStatus(aStatus);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode,
|
|
|
|
const nsTArray<nsAlternativeCharCode>* aAlternativeCharCodes,
|
|
|
|
UINT aVirtualCharCode, const MSG *aMsg,
|
|
|
|
const nsModifierKeyState &aModKeyState,
|
|
|
|
PRUint32 aFlags)
|
|
|
|
{
|
|
|
|
nsKeyEvent event(PR_TRUE, aEventType, this);
|
|
|
|
nsIntPoint point(0, 0);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
InitEvent(event, &point); // this add ref's event.widget
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.flags |= aFlags;
|
|
|
|
event.charCode = aCharCode;
|
|
|
|
if (aAlternativeCharCodes)
|
|
|
|
event.alternativeCharCodes.AppendElements(*aAlternativeCharCodes);
|
|
|
|
event.keyCode = aVirtualCharCode;
|
|
|
|
|
|
|
|
#ifdef KE_DEBUG
|
|
|
|
static cnt=0;
|
|
|
|
printf("%d DispatchKE Type: %s charCode %d keyCode %d ", cnt++,
|
|
|
|
(NS_KEY_PRESS == aEventType) ? "PRESS" : (aEventType == NS_KEY_UP ? "Up" : "Down"),
|
|
|
|
event.charCode, event.keyCode);
|
|
|
|
printf("Shift: %s Control %s Alt: %s \n",
|
|
|
|
(mIsShiftDown ? "D" : "U"), (mIsControlDown ? "D" : "U"), (mIsAltDown ? "D" : "U"));
|
|
|
|
printf("[%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' : ' ');
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.isShift = aModKeyState.mIsShiftDown;
|
|
|
|
event.isControl = aModKeyState.mIsControlDown;
|
|
|
|
event.isMeta = PR_FALSE;
|
|
|
|
event.isAlt = aModKeyState.mIsAltDown;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
if (aMsg && PluginHasFocus()) {
|
|
|
|
pluginEvent.event = aMsg->message;
|
|
|
|
pluginEvent.wParam = aMsg->wParam;
|
|
|
|
pluginEvent.lParam = aMsg->lParam;
|
|
|
|
event.nativeMsg = (void *)&pluginEvent;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool result = DispatchWindowEvent(&event);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::DispatchCommandEvent(PRUint32 aEventCommand)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> command;
|
|
|
|
switch (aEventCommand) {
|
|
|
|
case APPCOMMAND_BROWSER_BACKWARD:
|
|
|
|
command = nsWidgetAtoms::Back;
|
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_FORWARD:
|
|
|
|
command = nsWidgetAtoms::Forward;
|
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_REFRESH:
|
|
|
|
command = nsWidgetAtoms::Reload;
|
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_STOP:
|
|
|
|
command = nsWidgetAtoms::Stop;
|
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_SEARCH:
|
|
|
|
command = nsWidgetAtoms::Search;
|
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_FAVORITES:
|
|
|
|
command = nsWidgetAtoms::Bookmarks;
|
|
|
|
break;
|
|
|
|
case APPCOMMAND_BROWSER_HOME:
|
|
|
|
command = nsWidgetAtoms::Home;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
nsCommandEvent event(PR_TRUE, nsWidgetAtoms::onAppCommand, command, this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
InitEvent(event);
|
|
|
|
DispatchWindowEvent(&event);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
if (GetUpdateRect(aWnd, NULL, FALSE)) {
|
|
|
|
VERIFY(::UpdateWindow(aWnd));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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()
|
|
|
|
{
|
|
|
|
gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Quickly check to see if there are any
|
|
|
|
// paint events pending.
|
|
|
|
if (::GetQueueStatus(QS_PAINT)) {
|
|
|
|
// Find the top level window.
|
|
|
|
HWND topWnd = GetTopLevelHWND(mWnd);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Dispatch pending paints for all topWnd's descendant windows.
|
|
|
|
// Note: EnumChildWindows enumerates all descendant windows not just
|
|
|
|
// it's children.
|
|
|
|
#if !defined(WINCE)
|
|
|
|
::EnumChildWindows(topWnd, nsWindow::DispatchStarvedPaints, NULL);
|
|
|
|
#else
|
|
|
|
nsWindowCE::EnumChildWindows(topWnd, nsWindow::DispatchStarvedPaints, NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Deal with plugin events
|
|
|
|
PRBool nsWindow::DispatchPluginEvent(const MSG &aMsg)
|
|
|
|
{
|
|
|
|
if (!PluginHasFocus())
|
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsGUIEvent event(PR_TRUE, NS_PLUGIN_EVENT, this);
|
|
|
|
nsIntPoint point(0, 0);
|
|
|
|
InitEvent(event, &point);
|
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
pluginEvent.event = aMsg.message;
|
|
|
|
pluginEvent.wParam = aMsg.wParam;
|
|
|
|
pluginEvent.lParam = aMsg.lParam;
|
|
|
|
event.nativeMsg = (void *)&pluginEvent;
|
|
|
|
return DispatchWindowEvent(&event);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
void nsWindow::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg,
|
|
|
|
UINT aLastMsg)
|
|
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
::GetMessageW(&msg, mWnd, aFirstMsg, aLastMsg);
|
|
|
|
DispatchPluginEvent(msg);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Deal with all sort of mouse event
|
|
|
|
PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam,
|
|
|
|
LPARAM lParam, PRBool aIsContextMenuKey,
|
|
|
|
PRInt16 aButton)
|
|
|
|
{
|
|
|
|
PRBool result = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!mEventCallback) {
|
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIntPoint eventPoint;
|
|
|
|
eventPoint.x = GET_X_LPARAM(lParam);
|
|
|
|
eventPoint.y = GET_Y_LPARAM(lParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsMouseEvent event(PR_TRUE, aEventType, this, nsMouseEvent::eReal,
|
|
|
|
aIsContextMenuKey
|
|
|
|
? nsMouseEvent::eContextMenuKey
|
|
|
|
: nsMouseEvent::eNormal);
|
|
|
|
if (aEventType == NS_CONTEXTMENU && aIsContextMenuKey) {
|
|
|
|
nsIntPoint zero(0, 0);
|
|
|
|
InitEvent(event, &zero);
|
|
|
|
} else {
|
|
|
|
InitEvent(event, &eventPoint);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
|
|
|
event.isMeta = PR_FALSE;
|
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
event.button = aButton;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIntPoint mpScreen = eventPoint + WidgetToScreenOffset();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool insideMovementThreshold = (abs(sLastMousePoint.x - eventPoint.x) < (short)::GetSystemMetrics(SM_CXDOUBLECLK)) &&
|
|
|
|
(abs(sLastMousePoint.y - eventPoint.y) < (short)::GetSystemMetrics(SM_CYDOUBLECLK));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
BYTE eventButton;
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
eventButton = VK_LBUTTON;
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2009-06-29 12:36:16 -07:00
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
eventButton = VK_MBUTTON;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
eventButton = VK_RBUTTON;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
eventButton = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG_XX
|
|
|
|
printf("Msg: %d Last: %d Dif: %d Max %d\n", curMsgTime, sLastMouseDownTime, curMsgTime-sLastMouseDownTime, ::GetDoubleClickTime());
|
|
|
|
printf("Mouse %d %d\n", abs(sLastMousePoint.x - mp.x), abs(sLastMousePoint.y - mp.y));
|
|
|
|
#endif
|
|
|
|
if (((curMsgTime - sLastMouseDownTime) < (LONG)::GetDoubleClickTime()) && insideMovementThreshold &&
|
|
|
|
eventButton == sLastMouseButton) {
|
|
|
|
sLastClickCount ++;
|
|
|
|
} else {
|
|
|
|
// reset the click count, to count *this* click
|
|
|
|
sLastClickCount = 1;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
}
|
|
|
|
event.clickCount = sLastClickCount;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef NS_DEBUG_XX
|
|
|
|
printf("Msg Time: %d Click Count: %d\n", curMsgTime, event.clickCount);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
|
|
|
|
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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
2009-06-29 12:36:16 -07:00
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
pluginEvent.event = WM_MOUSEMOVE;
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
pluginEvent.event = WM_NULL;
|
|
|
|
break;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
pluginEvent.wParam = wParam; // plugins NEED raw OS event flags!
|
|
|
|
pluginEvent.lParam = lParam;
|
2009-03-23 18:10:36 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.nativeMsg = (void *)&pluginEvent;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// call the event callback
|
|
|
|
if (nsnull != mEventCallback) {
|
|
|
|
if (nsToolkit::gMouseTrailer)
|
|
|
|
nsToolkit::gMouseTrailer->Disable();
|
|
|
|
if (aEventType == NS_MOUSE_MOVE) {
|
|
|
|
if (nsToolkit::gMouseTrailer && !mIsInMouseCapture) {
|
|
|
|
nsToolkit::gMouseTrailer->SetMouseTrailerWindow(mWnd);
|
|
|
|
}
|
|
|
|
nsIntRect rect;
|
|
|
|
GetBounds(rect);
|
|
|
|
rect.x = 0;
|
|
|
|
rect.y = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (rect.Contains(event.refPoint)) {
|
|
|
|
if (sCurrentWindow == NULL || sCurrentWindow != this) {
|
|
|
|
if ((nsnull != sCurrentWindow) && (!sCurrentWindow->mIsDestroying)) {
|
|
|
|
LPARAM pos = sCurrentWindow->lParamToClient(lParamToScreen(lParam));
|
|
|
|
sCurrentWindow->DispatchMouseEvent(NS_MOUSE_EXIT, wParam, pos);
|
|
|
|
}
|
|
|
|
sCurrentWindow = this;
|
|
|
|
if (!mIsDestroying) {
|
|
|
|
LPARAM pos = sCurrentWindow->lParamToClient(lParamToScreen(lParam));
|
|
|
|
sCurrentWindow->DispatchMouseEvent(NS_MOUSE_ENTER, wParam, pos);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
} else if (aEventType == NS_MOUSE_EXIT) {
|
|
|
|
if (sCurrentWindow == this) {
|
|
|
|
sCurrentWindow = nsnull;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
result = DispatchWindowEvent(&event);
|
2008-09-23 16:16:11 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsToolkit::gMouseTrailer)
|
|
|
|
nsToolkit::gMouseTrailer->Enable();
|
2008-04-08 18:51:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Release the widget with NS_IF_RELEASE() just in case
|
|
|
|
// the context menu key code in nsEventListenerManager::HandleEvent()
|
|
|
|
// released it already.
|
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Deal with accessibile event
|
2008-02-06 12:34:35 -08:00
|
|
|
#ifdef ACCESSIBILITY
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::DispatchAccessibleEvent(PRUint32 aEventType, nsIAccessible** aAcc, nsIntPoint* aPoint)
|
|
|
|
{
|
|
|
|
PRBool result = PR_FALSE;
|
2008-02-06 12:34:35 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull == mEventCallback) {
|
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
*aAcc = nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsAccessibleEvent event(PR_TRUE, aEventType, this);
|
|
|
|
InitEvent(event, aPoint);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
|
|
|
event.isMeta = PR_FALSE;
|
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
event.accessible = nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
result = DispatchWindowEvent(&event);
|
|
|
|
|
|
|
|
// if the event returned an accesssible get it.
|
|
|
|
if (event.accessible)
|
|
|
|
*aAcc = event.accessible;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::DispatchFocusToTopLevelWindow(PRUint32 aEventType)
|
|
|
|
{
|
|
|
|
if (aEventType == NS_ACTIVATE)
|
|
|
|
sJustGotActivate = PR_FALSE;
|
|
|
|
sJustGotDeactivate = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// clear the flags, and retrieve the toplevel window. This way, it doesn't
|
|
|
|
// mattter what child widget received the focus event and it will always be
|
|
|
|
// fired at the toplevel window.
|
|
|
|
HWND toplevelWnd = GetTopLevelHWND(mWnd);
|
|
|
|
if (toplevelWnd) {
|
|
|
|
nsWindow *win = GetNSWindowPtr(toplevelWnd);
|
|
|
|
if (win)
|
|
|
|
return win->DispatchFocus(aEventType);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Deal with focus messages
|
|
|
|
PRBool nsWindow::DispatchFocus(PRUint32 aEventType)
|
|
|
|
{
|
|
|
|
// call the event callback
|
|
|
|
if (mEventCallback) {
|
|
|
|
nsGUIEvent event(PR_TRUE, aEventType, this);
|
|
|
|
InitEvent(event);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
//focus and blur event should go to their base widget loc, not current mouse pos
|
|
|
|
event.refPoint.x = 0;
|
|
|
|
event.refPoint.y = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsPluginEvent pluginEvent;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.nativeMsg = (void *)&pluginEvent;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return DispatchWindowEvent(&event);
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::IsTopLevelMouseExit(HWND aWnd)
|
|
|
|
{
|
|
|
|
DWORD pos = ::GetMessagePos();
|
|
|
|
POINT mp;
|
|
|
|
mp.x = GET_X_LPARAM(pos);
|
|
|
|
mp.y = GET_Y_LPARAM(pos);
|
|
|
|
HWND mouseWnd = ::WindowFromPoint(mp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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 = nsWindow::GetTopLevelHWND(mouseWnd);
|
|
|
|
if (mouseWnd == mouseTopLevel)
|
|
|
|
return PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return nsWindow::GetTopLevelHWND(aWnd) != mouseTopLevel;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::BlurEventsSuppressed()
|
|
|
|
{
|
|
|
|
// are they suppressed in this window?
|
|
|
|
if (mBlurSuppressLevel > 0)
|
|
|
|
return PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// are they suppressed by any container widget?
|
|
|
|
HWND parentWnd = ::GetParent(mWnd);
|
|
|
|
if (parentWnd) {
|
|
|
|
nsWindow *parent = GetNSWindowPtr(parentWnd);
|
|
|
|
if (parent)
|
|
|
|
return parent->BlurEventsSuppressed();
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
void nsWindow::SuppressBlurEvents(PRBool aSuppress)
|
|
|
|
{
|
|
|
|
if (aSuppress)
|
|
|
|
++mBlurSuppressLevel; // for this widget
|
|
|
|
else {
|
|
|
|
NS_ASSERTION(mBlurSuppressLevel > 0, "unbalanced blur event suppression");
|
|
|
|
if (mBlurSuppressLevel > 0)
|
|
|
|
--mBlurSuppressLevel;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::ConvertStatus(nsEventStatus aStatus)
|
|
|
|
{
|
|
|
|
return aStatus == nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Native events
|
|
|
|
**
|
|
|
|
** Main Windows message handlers and OnXXX handlers for
|
|
|
|
** Windows event handling.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Wind proc.
|
|
|
|
*
|
|
|
|
* The main Windows event procedures and associated
|
|
|
|
* message processing methods.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// The WndProc procedure for all nsWindows in this toolkit
|
|
|
|
LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
// create this here so that we store the last rolled up popup until after
|
|
|
|
// the event has been processed.
|
|
|
|
nsAutoRollup autoRollup;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
LRESULT popupHandlingResult;
|
|
|
|
if ( DealWithPopups(hWnd, msg, wParam, lParam, &popupHandlingResult) )
|
|
|
|
return popupHandlingResult;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Get the window which caused the event and ask it to process the message
|
|
|
|
nsWindow *someWindow = GetNSWindowPtr(hWnd);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
if (!someWindow->mIsDestroying) // not if we're in the destructor!
|
|
|
|
kungFuDeathGrip = do_QueryInterface((nsBaseWidget*)someWindow);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Re-direct a tab change message destined for its parent window to the
|
|
|
|
// the actual window which generated the event.
|
|
|
|
if (msg == WM_NOTIFY) {
|
|
|
|
LPNMHDR pnmh = (LPNMHDR) lParam;
|
|
|
|
if (pnmh->code == TCN_SELCHANGE) {
|
|
|
|
someWindow = GetNSWindowPtr(pnmh->hwndFrom);
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Call ProcessMessage
|
|
|
|
if (nsnull != someWindow) {
|
|
|
|
LRESULT retValue;
|
|
|
|
if (PR_TRUE == someWindow->ProcessMessage(msg, wParam, lParam, &retValue)) {
|
|
|
|
return retValue;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return ::CallWindowProcW(someWindow->GetPrevWindowProc(),
|
|
|
|
hWnd, msg, wParam, lParam);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
PRBool
|
|
|
|
nsWindow::ProcessMessageForPlugin(const MSG &aMsg,
|
|
|
|
LRESULT *aResult,
|
|
|
|
PRBool &aCallDefWndProc)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aResult, "aResult must be non-null.");
|
|
|
|
*aResult = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
aCallDefWndProc = PR_FALSE;
|
|
|
|
PRBool fallBackToNonPluginProcess = PR_FALSE;
|
|
|
|
PRBool eventDispatched = PR_FALSE;
|
|
|
|
PRBool dispatchPendingEvents = PR_TRUE;
|
|
|
|
switch (aMsg.message) {
|
|
|
|
case WM_INPUTLANGCHANGEREQUEST:
|
|
|
|
case WM_INPUTLANGCHANGE:
|
|
|
|
DispatchPluginEvent(aMsg);
|
|
|
|
return PR_FALSE; // go to non-plug-ins processing
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_CHAR:
|
|
|
|
case WM_SYSCHAR:
|
|
|
|
*aResult = ProcessCharMessage(aMsg, &eventDispatched);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_KEYUP:
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
*aResult = ProcessKeyUpMessage(aMsg, &eventDispatched);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_KEYDOWN:
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
*aResult = ProcessKeyDownMessage(aMsg, &eventDispatched);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_DEADCHAR:
|
|
|
|
case WM_SYSDEADCHAR:
|
|
|
|
case WM_CONTEXTMENU:
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_CUT:
|
|
|
|
case WM_COPY:
|
|
|
|
case WM_PASTE:
|
|
|
|
case WM_CLEAR:
|
|
|
|
case WM_UNDO:
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_IME_STARTCOMPOSITION:
|
|
|
|
case WM_IME_COMPOSITION:
|
|
|
|
case WM_IME_ENDCOMPOSITION:
|
|
|
|
case WM_IME_CHAR:
|
|
|
|
case WM_IME_COMPOSITIONFULL:
|
|
|
|
case WM_IME_CONTROL:
|
|
|
|
case WM_IME_KEYDOWN:
|
|
|
|
case WM_IME_KEYUP:
|
|
|
|
case WM_IME_NOTIFY:
|
|
|
|
case WM_IME_REQUEST:
|
|
|
|
case WM_IME_SELECT:
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_IME_SETCONTEXT:
|
|
|
|
// Don't synchronously dispatch when we receive WM_IME_SETCONTEXT
|
|
|
|
// because we get it during plugin destruction. (bug 491848)
|
|
|
|
dispatchPendingEvents = PR_FALSE;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!eventDispatched)
|
|
|
|
aCallDefWndProc = !DispatchPluginEvent(aMsg);
|
|
|
|
if (dispatchPendingEvents)
|
|
|
|
DispatchPendingEvents();
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// The main windows message processing method.
|
|
|
|
PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
|
|
|
LRESULT *aRetValue)
|
|
|
|
{
|
|
|
|
// (Large blocks of code should be broken out into OnEvent handlers.)
|
|
|
|
|
|
|
|
PRBool eatMessage;
|
|
|
|
if (nsIMM32Handler::ProcessMessage(this, msg, wParam, lParam, aRetValue,
|
|
|
|
eatMessage)) {
|
|
|
|
return mWnd ? eatMessage : PR_TRUE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (PluginHasFocus()) {
|
|
|
|
PRBool callDefaultWndProc;
|
|
|
|
MSG nativeMsg = InitMSG(msg, wParam, lParam);
|
|
|
|
if (ProcessMessageForPlugin(nativeMsg, aRetValue, callDefaultWndProc)) {
|
|
|
|
return mWnd ? !callDefaultWndProc : PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
static UINT vkKeyCached = 0; // caches VK code fon WM_KEYDOWN
|
|
|
|
PRBool result = PR_FALSE; // call the default nsWindow proc
|
|
|
|
*aRetValue = 0;
|
|
|
|
nsPaletteInfo palInfo;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined (WINCE)
|
|
|
|
static PRBool getWheelInfo = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07: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
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (msg) {
|
|
|
|
case WM_COMMAND:
|
|
|
|
{
|
|
|
|
WORD wNotifyCode = HIWORD(wParam); // notification code
|
|
|
|
if ((CBN_SELENDOK == wNotifyCode) || (CBN_SELENDCANCEL == wNotifyCode)) { // Combo box change
|
|
|
|
nsGUIEvent event(PR_TRUE, NS_CONTROL_CHANGE, this);
|
|
|
|
nsIntPoint point(0,0);
|
|
|
|
InitEvent(event, &point); // this add ref's event.widget
|
|
|
|
result = DispatchWindowEvent(&event);
|
|
|
|
} else if (wNotifyCode == 0) { // Menu selection
|
|
|
|
nsMenuEvent event(PR_TRUE, NS_MENU_SELECTED, this);
|
|
|
|
event.mCommand = LOWORD(wParam);
|
|
|
|
InitEvent(event);
|
|
|
|
result = DispatchWindowEvent(&event);
|
2009-02-10 12:56:51 -08:00
|
|
|
}
|
2008-08-12 17:44:14 -07:00
|
|
|
}
|
|
|
|
break;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
// 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 =
|
|
|
|
do_GetService("@mozilla.org/observer-service;1");
|
|
|
|
nsCOMPtr<nsISupportsPRBool> cancelQuit =
|
|
|
|
do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID);
|
|
|
|
cancelQuit->SetData(PR_FALSE);
|
|
|
|
obsServ->NotifyObservers(cancelQuit, "quit-application-requested", nsnull);
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool abortQuit;
|
|
|
|
cancelQuit->GetData(&abortQuit);
|
|
|
|
sCanQuit = abortQuit ? TRI_FALSE : TRI_TRUE;
|
|
|
|
}
|
|
|
|
*aRetValue = sCanQuit ? TRUE : FALSE;
|
2009-04-02 12:34:31 -07:00
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_ENDSESSION:
|
|
|
|
if (wParam == TRUE && sCanQuit == TRI_TRUE)
|
|
|
|
{
|
|
|
|
// 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 =
|
|
|
|
do_GetService("@mozilla.org/observer-service;1");
|
|
|
|
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;
|
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_DISPLAYCHANGE:
|
|
|
|
DispatchStandardEvent(NS_DISPLAYCHANGED);
|
|
|
|
break;
|
|
|
|
#endif
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_SYSCOLORCHANGE:
|
|
|
|
// 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);
|
|
|
|
break;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_NOTIFY:
|
|
|
|
// TAB change
|
|
|
|
{
|
|
|
|
LPNMHDR pnmh = (LPNMHDR) lParam;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (pnmh->code) {
|
|
|
|
case TCN_SELCHANGE:
|
|
|
|
{
|
|
|
|
DispatchStandardEvent(NS_TABCHANGE);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-04-02 12:34:31 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
break;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_XP_THEMECHANGED:
|
|
|
|
{
|
|
|
|
DispatchStandardEvent(NS_THEMECHANGED);
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Invalidate the window so that the repaint will
|
|
|
|
// pick up the new theme.
|
|
|
|
Invalidate(PR_FALSE);
|
|
|
|
}
|
|
|
|
break;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_FONTCHANGE:
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
PRBool didChange = PR_FALSE;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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) {
|
|
|
|
// 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
|
|
|
|
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
|
|
if (prefs) {
|
|
|
|
nsCOMPtr<nsIPrefBranch> fiPrefs;
|
|
|
|
prefs->GetBranch("font.internaluseonly.", getter_AddRefs(fiPrefs));
|
|
|
|
if (fiPrefs) {
|
|
|
|
PRBool fontInternalChange = PR_FALSE;
|
|
|
|
fiPrefs->GetBoolPref("changed", &fontInternalChange);
|
|
|
|
fiPrefs->SetBoolPref("changed", !fontInternalChange);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} //if (NS_SUCCEEDED(rv))
|
|
|
|
}
|
|
|
|
break;
|
2009-04-02 12:34:31 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
case WM_POWERBROADCAST:
|
|
|
|
// only hidden window handle this
|
|
|
|
// to prevent duplicate notification
|
|
|
|
if (mWindowType == eWindowType_invisible) {
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case PBT_APMSUSPEND:
|
|
|
|
PostSleepWakeNotification("sleep_notification");
|
|
|
|
break;
|
|
|
|
case PBT_APMRESUMEAUTOMATIC:
|
|
|
|
case PBT_APMRESUMECRITICAL:
|
|
|
|
case PBT_APMRESUMESUSPEND:
|
|
|
|
PostSleepWakeNotification("wake_notification");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_MOVE: // Window moved
|
|
|
|
{
|
|
|
|
PRInt32 x = GET_X_LPARAM(lParam); // horizontal position in screen coordinates
|
|
|
|
PRInt32 y = GET_Y_LPARAM(lParam); // vertical position in screen coordinates
|
|
|
|
result = OnMove(x, y);
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_CLOSE: // close request
|
|
|
|
DispatchStandardEvent(NS_XUL_CLOSE);
|
|
|
|
result = PR_TRUE; // abort window closure
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_DESTROY:
|
|
|
|
// clean up.
|
|
|
|
OnDestroy();
|
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_PAINT:
|
|
|
|
*aRetValue = (int) OnPaint();
|
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
case WM_PRINTCLIENT:
|
|
|
|
result = OnPaint((HDC) wParam);
|
|
|
|
break;
|
|
|
|
#endif
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_HOTKEY:
|
|
|
|
result = OnHotKey(wParam, lParam);
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_SYSCHAR:
|
|
|
|
case WM_CHAR:
|
|
|
|
{
|
|
|
|
MSG nativeMsg = InitMSG(msg, wParam, lParam);
|
|
|
|
result = ProcessCharMessage(nativeMsg, nsnull);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_SYSKEYUP:
|
|
|
|
case WM_KEYUP:
|
|
|
|
{
|
|
|
|
MSG nativeMsg = InitMSG(msg, wParam, lParam);
|
|
|
|
result = ProcessKeyUpMessage(nativeMsg, nsnull);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
{
|
|
|
|
MSG nativeMsg = InitMSG(msg, wParam, lParam);
|
|
|
|
result = ProcessKeyDownMessage(nativeMsg, nsnull);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// say we've dealt with erase background if widget does
|
|
|
|
// not need auto-erasing
|
|
|
|
case WM_ERASEBKGND:
|
|
|
|
if (! AutoErase()) {
|
|
|
|
*aRetValue = 1;
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_GETDLGCODE:
|
|
|
|
*aRetValue = DLGC_WANTALLKEYS;
|
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
PRBool userMovedMouse = PR_FALSE;
|
|
|
|
if ((sLastMouseMovePoint.x != mp.x) || (sLastMouseMovePoint.y != mp.y)) {
|
|
|
|
userMovedMouse = PR_TRUE;
|
|
|
|
}
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
result = DispatchMouseEvent(NS_MOUSE_MOVE, wParam, lParam);
|
|
|
|
if (userMovedMouse) {
|
|
|
|
DispatchPendingEvents();
|
2008-12-14 19:54:54 -08:00
|
|
|
}
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
{
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam,
|
|
|
|
PR_FALSE, nsMouseEvent::eLeftButton);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_LBUTTONUP:
|
|
|
|
{
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, wParam, lParam,
|
|
|
|
PR_FALSE, nsMouseEvent::eLeftButton);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
case WM_MOUSELEAVE:
|
|
|
|
{
|
|
|
|
// 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());
|
|
|
|
DispatchMouseEvent(NS_MOUSE_EXIT, mouseState, pos);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_CONTEXTMENU:
|
|
|
|
{
|
|
|
|
// if the context menu is brought up from the keyboard, |lParam|
|
|
|
|
// will be maxlong.
|
|
|
|
LPARAM pos;
|
|
|
|
PRBool contextMenukey = PR_FALSE;
|
|
|
|
if (lParam == 0xFFFFFFFF)
|
|
|
|
{
|
|
|
|
contextMenukey = PR_TRUE;
|
|
|
|
pos = lParamToClient(GetMessagePos());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pos = lParamToClient(lParam);
|
|
|
|
}
|
|
|
|
result = DispatchMouseEvent(NS_CONTEXTMENU, wParam, pos, contextMenukey,
|
|
|
|
contextMenukey ?
|
|
|
|
nsMouseEvent::eLeftButton :
|
|
|
|
nsMouseEvent::eRightButton);
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_LBUTTONDBLCLK:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, wParam, lParam, PR_FALSE,
|
|
|
|
nsMouseEvent::eLeftButton);
|
2008-12-14 19:54:54 -08:00
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
{
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam, PR_FALSE,
|
|
|
|
nsMouseEvent::eMiddleButton);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_MBUTTONUP:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, wParam, lParam, PR_FALSE,
|
|
|
|
nsMouseEvent::eMiddleButton);
|
|
|
|
DispatchPendingEvents();
|
2009-05-14 20:08:41 -07:00
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_MBUTTONDBLCLK:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam, PR_FALSE,
|
|
|
|
nsMouseEvent::eMiddleButton);
|
2008-12-14 19:54:54 -08:00
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
{
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, wParam, lParam, PR_FALSE,
|
|
|
|
nsMouseEvent::eRightButton);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
}
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_RBUTTONUP:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_BUTTON_UP, wParam, lParam, PR_FALSE,
|
|
|
|
nsMouseEvent::eRightButton);
|
|
|
|
DispatchPendingEvents();
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_RBUTTONDBLCLK:
|
|
|
|
result = DispatchMouseEvent(NS_MOUSE_DOUBLECLICK, wParam, lParam, PR_FALSE,
|
|
|
|
nsMouseEvent::eRightButton);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_APPCOMMAND:
|
|
|
|
{
|
|
|
|
PRUint32 appCommand = GET_APPCOMMAND_LPARAM(lParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// default = PR_FALSE - tell the driver that the event was not handled
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_HSCROLL:
|
|
|
|
case WM_VSCROLL:
|
|
|
|
// check for the incoming nsWindow handle to be null in which case
|
|
|
|
// we assume the message is coming from a horizontal scrollbar inside
|
|
|
|
// a listbox and we don't bother processing it (well, we don't have to)
|
|
|
|
if (lParam) {
|
|
|
|
nsWindow* scrollbar = GetNSWindowPtr((HWND)lParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (scrollbar) {
|
|
|
|
result = scrollbar->OnScroll(LOWORD(wParam), (short)HIWORD(wParam));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_CTLCOLORLISTBOX:
|
|
|
|
case WM_CTLCOLOREDIT:
|
|
|
|
case WM_CTLCOLORBTN:
|
|
|
|
//case WM_CTLCOLORSCROLLBAR: //XXX causes the scrollbar to be drawn incorrectly
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
|
|
if (lParam) {
|
|
|
|
nsWindow* control = GetNSWindowPtr((HWND)lParam);
|
|
|
|
if (control) {
|
|
|
|
control->SetUpForPaint((HDC)wParam);
|
|
|
|
*aRetValue = (LPARAM)control->OnControlColor();
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(WINCE_HAVE_SOFTKB)
|
|
|
|
if (mIsTopWidgetWindow && sSoftKeyboardState)
|
|
|
|
nsWindowCE::ToggleSoftKB(fActive);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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
|
|
|
|
sJustGotDeactivate = PR_TRUE;
|
|
|
|
#ifndef WINCE
|
|
|
|
if (mIsTopWidgetWindow)
|
|
|
|
mLastKeyboardLayout = gKbdLayout.GetLayout();
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
} else {
|
|
|
|
StopFlashing();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
sJustGotActivate = PR_TRUE;
|
|
|
|
nsMouseEvent event(PR_TRUE, NS_MOUSE_ACTIVATE, this,
|
|
|
|
nsMouseEvent::eReal);
|
|
|
|
InitEvent(event);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.acceptActivation = PR_TRUE;
|
|
|
|
|
|
|
|
PRBool result = DispatchWindowEvent(&event);
|
|
|
|
#ifndef WINCE
|
|
|
|
if (event.acceptActivation)
|
|
|
|
*aRetValue = MA_ACTIVATE;
|
|
|
|
else
|
|
|
|
*aRetValue = MA_NOACTIVATE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sSwitchKeyboardLayout && mLastKeyboardLayout)
|
|
|
|
ActivateKeyboardLayout(mLastKeyboardLayout, 0);
|
|
|
|
#else
|
|
|
|
*aRetValue = 0;
|
2009-02-12 18:26:02 -08:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
|
|
|
}
|
2009-02-12 18:26:02 -08:00
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
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;
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
|
|
{
|
|
|
|
LPWINDOWPOS info = (LPWINDOWPOS) lParam;
|
|
|
|
OnWindowPosChanging(info);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_SETFOCUS:
|
|
|
|
if (sJustGotActivate) {
|
|
|
|
result = DispatchFocusToTopLevelWindow(NS_ACTIVATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
if (nsWindow::sIsAccessibilityOn) {
|
|
|
|
// Create it for the first time so that it can start firing events
|
|
|
|
nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible();
|
|
|
|
}
|
2009-02-12 18:26:02 -08:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(WINCE_HAVE_SOFTKB)
|
|
|
|
{
|
|
|
|
// On Windows CE, we have a window that overlaps
|
|
|
|
// the ISP button. In this case, we should always
|
|
|
|
// try to hide it when we are activated
|
|
|
|
|
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
// Open the IME
|
|
|
|
ImmSetOpenStatus(IMEContext.get(), TRUE);
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_KILLFOCUS:
|
|
|
|
#if defined(WINCE_HAVE_SOFTKB)
|
|
|
|
{
|
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
ImmSetOpenStatus(IMEContext.get(), FALSE);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (sJustGotDeactivate) {
|
|
|
|
result = DispatchFocusToTopLevelWindow(NS_DEACTIVATE);
|
2008-09-13 14:52:17 -07:00
|
|
|
}
|
2009-02-13 00:34:42 -08:00
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
|
|
{
|
|
|
|
WINDOWPOS *wp = (LPWINDOWPOS)lParam;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// We only care about a resize, so filter out things like z-order
|
|
|
|
// changes. Note: there's a WM_MOVE handler above which is why we're
|
|
|
|
// not handling them here...
|
|
|
|
if (0 == (wp->flags & SWP_NOSIZE)) {
|
|
|
|
// XXX Why are we using the client size area? If the size notification
|
|
|
|
// is for the client area then the origin should be (0,0) and not
|
|
|
|
// the window origin in screen coordinates...
|
|
|
|
RECT r;
|
|
|
|
::GetWindowRect(mWnd, &r);
|
|
|
|
PRInt32 newWidth, newHeight;
|
|
|
|
newWidth = PRInt32(r.right - r.left);
|
|
|
|
newHeight = PRInt32(r.bottom - r.top);
|
|
|
|
nsIntRect rect(wp->x, wp->y, newWidth, newHeight);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
ResizeTranslucentWindow(newWidth, newHeight);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (newWidth > mLastSize.width)
|
|
|
|
{
|
|
|
|
RECT drect;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
//getting wider
|
|
|
|
drect.left = wp->x + mLastSize.width;
|
|
|
|
drect.top = wp->y;
|
|
|
|
drect.right = drect.left + (newWidth - mLastSize.width);
|
|
|
|
drect.bottom = drect.top + newHeight;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
::RedrawWindow(mWnd, &drect, NULL,
|
|
|
|
RDW_INVALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ERASENOW | RDW_ALLCHILDREN);
|
|
|
|
}
|
|
|
|
if (newHeight > mLastSize.height)
|
|
|
|
{
|
|
|
|
RECT drect;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
//getting taller
|
|
|
|
drect.left = wp->x;
|
|
|
|
drect.top = wp->y + mLastSize.height;
|
|
|
|
drect.right = drect.left + newWidth;
|
|
|
|
drect.bottom = drect.top + (newHeight - mLastSize.height);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
::RedrawWindow(mWnd, &drect, NULL,
|
|
|
|
RDW_INVALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ERASENOW | RDW_ALLCHILDREN);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mBounds.width = newWidth;
|
|
|
|
mBounds.height = newHeight;
|
|
|
|
mLastSize.width = newWidth;
|
|
|
|
mLastSize.height = newHeight;
|
|
|
|
///nsRect rect(wp->x, wp->y, wp->cx, wp->cy);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// If we're being minimized, don't send the resize event to Gecko because
|
|
|
|
// it will cause the scrollbar in the content area to go away and we'll
|
|
|
|
// forget the scroll position of the page. Note that we need to check the
|
|
|
|
// toplevel window, because child windows seem to go to 0x0 on minimize.
|
|
|
|
HWND toplevelWnd = GetTopLevelHWND(mWnd);
|
|
|
|
if (!newWidth && !newHeight && IsIconic(toplevelWnd)) {
|
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// recalculate the width and height
|
|
|
|
// this time based on the client area
|
|
|
|
if (::GetClientRect(mWnd, &r)) {
|
|
|
|
rect.width = PRInt32(r.right - r.left);
|
|
|
|
rect.height = PRInt32(r.bottom - r.top);
|
|
|
|
}
|
|
|
|
result = OnResize(rect);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/* handle size mode changes
|
|
|
|
(the framechanged message seems a handy place to hook in,
|
|
|
|
because it happens early enough (WM_SIZE is too late) and
|
|
|
|
because in testing it seems an accurate harbinger of
|
|
|
|
an impending min/max/restore change (WM_NCCALCSIZE would
|
|
|
|
also work, but it's also sent when merely resizing.)) */
|
|
|
|
if (wp->flags & SWP_FRAMECHANGED && ::IsWindowVisible(mWnd)) {
|
|
|
|
nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this);
|
|
|
|
#ifndef WINCE
|
|
|
|
WINDOWPLACEMENT pl;
|
|
|
|
pl.length = sizeof(pl);
|
|
|
|
::GetWindowPlacement(mWnd, &pl);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (pl.showCmd == SW_SHOWMAXIMIZED)
|
|
|
|
event.mSizeMode = nsSizeMode_Maximized;
|
|
|
|
else if (pl.showCmd == SW_SHOWMINIMIZED)
|
|
|
|
event.mSizeMode = nsSizeMode_Minimized;
|
|
|
|
else
|
|
|
|
event.mSizeMode = nsSizeMode_Normal;
|
|
|
|
#else
|
|
|
|
event.mSizeMode = nsSizeMode_Normal;
|
2009-03-08 22:06:59 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
InitEvent(event);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
result = DispatchWindowEvent(&event);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_SETTINGCHANGE:
|
|
|
|
#if !defined (WINCE)
|
|
|
|
getWheelInfo = PR_TRUE;
|
|
|
|
#endif
|
|
|
|
OnSettingsChange(wParam, lParam);
|
|
|
|
break;
|
2007-08-02 13:55:25 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_PALETTECHANGED:
|
|
|
|
if ((HWND)wParam == mWnd) {
|
|
|
|
// We caused the WM_PALETTECHANGED message so avoid realizing
|
|
|
|
// another foreground palette
|
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall thru...
|
2007-08-02 13:55:25 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_QUERYNEWPALETTE: // this window is about to become active
|
|
|
|
mContext->GetPaletteInfo(palInfo);
|
|
|
|
if (palInfo.isPaletteDevice && palInfo.palette) {
|
|
|
|
HDC hDC = ::GetDC(mWnd);
|
|
|
|
HPALETTE hOldPal = ::SelectPalette(hDC, (HPALETTE)palInfo.palette, TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Realize the drawing palette
|
|
|
|
int i = ::RealizePalette(hDC);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
//printf("number of colors that changed=%d\n",i);
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
// we should always invalidate.. because the lookup may have changed
|
|
|
|
::InvalidateRect(mWnd, (LPRECT)NULL, TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
::ReleaseDC(mWnd, hDC);
|
|
|
|
*aRetValue = TRUE;
|
|
|
|
}
|
|
|
|
result = PR_TRUE;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
case WM_INPUTLANGCHANGEREQUEST:
|
|
|
|
*aRetValue = TRUE;
|
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_INPUTLANGCHANGE:
|
|
|
|
result = OnInputLangChange((HKL)lParam);
|
|
|
|
break;
|
|
|
|
#endif // WINCE
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_DESTROYCLIPBOARD:
|
|
|
|
{
|
|
|
|
nsIClipboard* clipboard;
|
|
|
|
nsresult rv = CallGetService(kCClipboardCID, &clipboard);
|
|
|
|
clipboard->EmptyClipboard(nsIClipboard::kGlobalClipboard);
|
|
|
|
NS_RELEASE(clipboard);
|
|
|
|
}
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
case WM_GETOBJECT:
|
|
|
|
{
|
|
|
|
*aRetValue = 0;
|
|
|
|
if (lParam == OBJID_CLIENT) { // oleacc.dll will be loaded dynamically
|
|
|
|
nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible(); // Held by a11y cache
|
|
|
|
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
|
|
|
|
result = PR_TRUE; // We handled the WM_GETOBJECT message
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2008-04-03 04:55:14 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
// prevent Windows from trimming the working set. bug 76831
|
|
|
|
if (!sTrimOnMinimize && wParam == SC_MINIMIZE) {
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMINIMIZED);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2009-02-15 17:09:11 -08:00
|
|
|
|
2008-04-03 04:55:14 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef WINCE
|
|
|
|
case WM_HIBERNATE:
|
|
|
|
nsMemory::HeapMinimize(PR_TRUE);
|
|
|
|
break;
|
|
|
|
#endif
|
2008-04-03 04:55:14 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
case WM_MOUSEHWHEEL:
|
|
|
|
if (OnMouseWheel(msg, wParam, lParam, getWheelInfo, result, aRetValue))
|
|
|
|
return result;
|
|
|
|
break;
|
|
|
|
#endif
|
2008-04-03 04:55:14 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
case WM_DWMCOMPOSITIONCHANGED:
|
|
|
|
BroadcastMsg(mWnd, WM_DWMCOMPOSITIONCHANGED);
|
|
|
|
DispatchStandardEvent(NS_THEMECHANGED);
|
|
|
|
if (nsUXThemeData::CheckForCompositor() && mTransparencyMode == eTransparencyGlass) {
|
|
|
|
MARGINS margins = { -1, -1, -1, -1 };
|
|
|
|
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(mWnd, &margins);
|
|
|
|
}
|
|
|
|
Invalidate(PR_FALSE);
|
|
|
|
break;
|
|
|
|
#endif
|
2008-04-03 04:55:14 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
/* Gesture support events */
|
|
|
|
case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
|
|
|
|
// According to MS samples, this must be handled to enable
|
|
|
|
// rotational support in multi-touch drivers.
|
|
|
|
result = PR_TRUE;
|
|
|
|
*aRetValue = TABLET_ROTATE_GESTURE_ENABLE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_GESTURE:
|
|
|
|
result = OnGesture(wParam, lParam);
|
|
|
|
break;
|
|
|
|
#endif // !defined(WINCE)
|
2009-02-15 17:09:11 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
if (msg == WM_USER_TSF_TEXTCHANGE) {
|
|
|
|
nsTextStore::OnTextChangeMsg();
|
|
|
|
}
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
#if defined(HEAP_DUMP_EVENT)
|
|
|
|
if (msg == GetHeapMsg()) {
|
|
|
|
HeapDump(msg, wParam, lParam);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
2009-02-15 17:09:11 -08:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
//*aRetValue = result;
|
|
|
|
if (mWnd) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//Events which caused mWnd destruction and aren't consumed
|
|
|
|
//will crash during the Windows default processing.
|
|
|
|
return PR_TRUE;
|
2008-04-03 04:55:14 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Broadcast messaging
|
|
|
|
*
|
|
|
|
* Broadcast messages to all windows.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Enumerate all child windows sending aMsg to each of them
|
|
|
|
BOOL CALLBACK nsWindow::BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg)
|
2009-04-22 17:48:30 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07: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-22 17:48:30 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return TRUE;
|
2009-04-22 17:48:30 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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.
|
|
|
|
#if !defined(WINCE)
|
|
|
|
::EnumChildWindows(aTopWindow, nsWindow::BroadcastMsgToChildren, aMsg);
|
|
|
|
#else
|
|
|
|
nsWindowCE::EnumChildWindows(aTopWindow, nsWindow::BroadcastMsgToChildren, aMsg);
|
2009-04-22 17:48:30 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
return TRUE;
|
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// This method is called from nsToolkit::WindowProc to forward global
|
|
|
|
// messages which need to be dispatched to all child windows.
|
|
|
|
void nsWindow::GlobalMsgWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (msg) {
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
|
|
// Code to dispatch WM_SYSCOLORCHANGE message to all child windows.
|
|
|
|
// WM_SYSCOLORCHANGE is only sent to top-level windows, but the
|
|
|
|
// cross platform API requires that NS_SYSCOLORCHANGE message be sent to
|
|
|
|
// all child windows as well. When running in an embedded application
|
|
|
|
// we may not receive a WM_SYSCOLORCHANGE message because the top
|
|
|
|
// level window is owned by the embeddor.
|
|
|
|
// System color changes are posted to top-level windows only.
|
|
|
|
// The NS_SYSCOLORCHANGE must be dispatched to all child
|
|
|
|
// windows as well.
|
|
|
|
#if !defined(WINCE)
|
|
|
|
::EnumThreadWindows(GetCurrentThreadId(), nsWindow::BroadcastMsg, msg);
|
2009-06-23 16:35:40 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: Event processing helpers
|
|
|
|
*
|
|
|
|
* Special processing for certain event types and
|
|
|
|
* synthesized events.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
void nsWindow::PostSleepWakeNotification(const char* aNotification)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
|
|
|
|
if (observerService)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
observerService->NotifyObservers(nsnull, aNotification, nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
LRESULT nsWindow::ProcessCharMessage(const MSG &aMsg, PRBool *aEventDispatched)
|
|
|
|
{
|
|
|
|
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",
|
|
|
|
aMsg.message == WM_SYSCHAR ? "WM_SYSCHAR" : "WM_CHAR",
|
|
|
|
aMsg.wParam, HIWORD(aMsg.lParam) & 0xFF));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
LRESULT nsWindow::ProcessKeyUpMessage(const MSG &aMsg, PRBool *aEventDispatched)
|
|
|
|
{
|
|
|
|
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 ?
|
|
|
|
"WM_SYSKEYUP" : "WM_KEYUP", aMsg.wParam));
|
2008-09-27 15:40:34 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsModifierKeyState modKeyState;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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 04:55:14 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!nsIMM32Handler::IsComposing(this) &&
|
|
|
|
(aMsg.message != WM_KEYUP || aMsg.message != VK_MENU)) {
|
|
|
|
// 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);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
LRESULT nsWindow::ProcessKeyDownMessage(const MSG &aMsg,
|
|
|
|
PRBool *aEventDispatched)
|
|
|
|
{
|
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("%s VK=%d\n", aMsg.message == WM_SYSKEYDOWN ?
|
|
|
|
"WM_SYSKEYDOWN" : "WM_KEYDOWN", aMsg.wParam));
|
|
|
|
NS_PRECONDITION(aMsg.message == WM_KEYDOWN || aMsg.message == WM_SYSKEYDOWN,
|
|
|
|
"message is not keydown event");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsModifierKeyState modKeyState;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
LRESULT result = 0;
|
|
|
|
if (modKeyState.mIsAltDown && nsIMM32Handler::IsStatusChanged()) {
|
|
|
|
nsIMM32Handler::NotifyEndStatusChange();
|
|
|
|
} else if (!nsIMM32Handler::IsComposing(this)) {
|
|
|
|
result = OnKeyDown(aMsg, modKeyState, aEventDispatched, nsnull);
|
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
if (aMsg.wParam == VK_MENU ||
|
|
|
|
(aMsg.wParam == VK_F10 && !modKeyState.mIsShiftDown)) {
|
|
|
|
// We need to let Windows handle this keypress,
|
|
|
|
// by returning PR_FALSE, if there's a native menu
|
|
|
|
// bar somewhere in our containing window hierarchy.
|
|
|
|
// Otherwise we handle the keypress and don't pass
|
|
|
|
// it on to Windows, by returning PR_TRUE.
|
|
|
|
PRBool hasNativeMenu = PR_FALSE;
|
|
|
|
HWND hWnd = mWnd;
|
|
|
|
while (hWnd) {
|
|
|
|
if (::GetMenu(hWnd)) {
|
|
|
|
hasNativeMenu = PR_TRUE;
|
|
|
|
break;
|
2009-04-22 17:48:30 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
hWnd = ::GetParent(hWnd);
|
2009-04-22 17:48:30 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
result = !hasNativeMenu;
|
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
#endif
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return result;
|
|
|
|
}
|
2009-03-08 22:08:41 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsresult
|
|
|
|
nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
|
|
|
PRInt32 aNativeKeyCode,
|
|
|
|
PRUint32 aModifierFlags,
|
|
|
|
const nsAString& aCharacters,
|
|
|
|
const nsAString& aUnmodifiedCharacters)
|
|
|
|
{
|
|
|
|
#ifndef WINCE //Win CE doesn't support many of the calls used in this method, perhaps theres another way
|
|
|
|
nsPrintfCString layoutName("%08x", aNativeKeyboardLayout);
|
|
|
|
HKL loadedLayout = LoadKeyboardLayoutA(layoutName.get(), KLF_NOTELLSHELL);
|
|
|
|
if (loadedLayout == NULL)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2009-03-08 22:08:41 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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-08 22:08:41 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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-22 17:48:30 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
::SetKeyboardState(kbdState);
|
|
|
|
nsModifierKeyState modKeyState;
|
|
|
|
MSG msg = InitMSG(WM_KEYDOWN, key, 0);
|
|
|
|
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-22 17:48:30 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07: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-22 17:48:30 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
::SetKeyboardState(kbdState);
|
|
|
|
nsModifierKeyState modKeyState;
|
|
|
|
MSG msg = InitMSG(WM_KEYUP, key, 0);
|
|
|
|
OnKeyUp(msg, modKeyState, nsnull);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Restore old key state and layout
|
|
|
|
::SetKeyboardState(originalKbdState);
|
|
|
|
gKbdLayout.LoadLayout(oldLayout);
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
UnloadKeyboardLayout(loadedLayout);
|
|
|
|
return NS_OK;
|
|
|
|
#else //XXX: is there another way to do this?
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2009-04-22 17:48:30 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: OnXXX message handlers
|
|
|
|
*
|
|
|
|
* For message handlers that need to be broken out or
|
|
|
|
* implemented in specific platform code.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
BOOL nsWindow::OnInputLangChange(HKL aHKL)
|
|
|
|
{
|
|
|
|
#ifdef KE_DEBUG
|
|
|
|
printf("OnInputLanguageChange\n");
|
2009-04-22 17:48:30 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
gKbdLayout.LoadLayout(aHKL);
|
2009-04-22 17:48:30 -07:00
|
|
|
#endif
|
2009-04-14 15:12:38 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_FALSE; // always pass to child window
|
|
|
|
}
|
2009-04-14 15:12:38 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
void nsWindow::OnWindowPosChanging(LPWINDOWPOS& info)
|
|
|
|
{
|
|
|
|
// enforce local z-order rules
|
|
|
|
if (!(info->flags & SWP_NOZORDER)) {
|
|
|
|
HWND hwndAfter = info->hwndInsertAfter;
|
|
|
|
|
|
|
|
nsZLevelEvent event(PR_TRUE, NS_SETZLEVEL, this);
|
|
|
|
nsWindow *aboveWindow = 0;
|
2009-04-14 15:12:38 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
InitEvent(event);
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
aboveWindow = GetNSWindowPtr(hwndAfter);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
event.mReqBelow = aboveWindow;
|
|
|
|
event.mActualBelow = nsnull;
|
|
|
|
|
|
|
|
event.mImmediate = PR_FALSE;
|
|
|
|
event.mAdjusted = PR_FALSE;
|
|
|
|
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);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_IF_RELEASE(event.mActualBelow);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
// prevent rude external programs from making hidden window visible
|
|
|
|
if (mWindowType == eWindowType_invisible)
|
|
|
|
info->flags &= ~SWP_SHOWWINDOW;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Gesture event processing. Handles WM_GESTURE events.
|
|
|
|
#if !defined(WINCE)
|
|
|
|
PRBool nsWindow::OnGesture(WPARAM wParam, LPARAM lParam)
|
2009-06-23 13:57:45 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
// Treatment for pan events which translate into scroll events:
|
|
|
|
if (mGesture.IsPanEvent(lParam)) {
|
|
|
|
nsMouseScrollEvent event(PR_TRUE, NS_MOUSE_PIXEL_SCROLL, this);
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if ( !mGesture.ProcessPanMessage(mWnd, wParam, lParam) )
|
|
|
|
return PR_FALSE; // ignore
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsEventStatus status;
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
event.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
|
|
|
event.isMeta = PR_FALSE;
|
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
event.button = 0;
|
|
|
|
event.time = ::GetMessageTime();
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool endFeedback = PR_TRUE;
|
|
|
|
|
|
|
|
if (mGesture.PanDeltaToPixelScrollX(event)) {
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
}
|
|
|
|
mGesture.UpdatePanFeedbackX(mWnd, event, endFeedback);
|
|
|
|
|
|
|
|
if (mGesture.PanDeltaToPixelScrollY(event)) {
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
}
|
|
|
|
mGesture.UpdatePanFeedbackY(mWnd, event, endFeedback);
|
|
|
|
mGesture.PanFeedbackFinalize(mWnd, endFeedback);
|
|
|
|
mGesture.CloseGestureInfoHandle((HGESTUREINFO)lParam);
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_TRUE;
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Other gestures translate into simple gesture events:
|
|
|
|
nsSimpleGestureEvent event(PR_TRUE, 0, this, 0, 0.0);
|
|
|
|
if ( !mGesture.ProcessGestureMessage(mWnd, wParam, lParam, event) ) {
|
|
|
|
return PR_FALSE; // fall through to DefWndProc
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
|
|
|
event.isMeta = PR_FALSE;
|
|
|
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
event.button = 0;
|
|
|
|
event.time = ::GetMessageTime();
|
|
|
|
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
if (status == nsEventStatus_eIgnore) {
|
|
|
|
return PR_FALSE; // Ignored, fall through
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Only close this if we process and return true.
|
|
|
|
mGesture.CloseGestureInfoHandle((HGESTUREINFO)lParam);
|
|
|
|
|
|
|
|
return PR_TRUE; // Handled
|
|
|
|
}
|
|
|
|
#endif // !defined(WINCE)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OnMouseWheel - mouse wheele event processing. This was originally embedded
|
|
|
|
* within the message case block. If returning true result should be returned
|
|
|
|
* immediately (no more processing).
|
|
|
|
*/
|
|
|
|
#if !defined(WINCE) // implemented in nsWindowCE
|
|
|
|
PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& getWheelInfo, PRBool& result, LRESULT *aRetValue)
|
|
|
|
{
|
|
|
|
// Handle both flavors of mouse wheel events.
|
|
|
|
static int iDeltaPerLine, iDeltaPerChar;
|
|
|
|
static ULONG ulScrollLines, ulScrollChars = 1;
|
|
|
|
static int currentVDelta, currentHDelta;
|
|
|
|
static HWND currentWindow = 0;
|
|
|
|
|
|
|
|
PRBool isVertical = msg == WM_MOUSEWHEEL;
|
|
|
|
|
|
|
|
// Get mouse wheel metrics (but only once).
|
|
|
|
if (getWheelInfo) {
|
|
|
|
getWheelInfo = PR_FALSE;
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0);
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// ulScrollLines usually equals 3 or 0 (for no scrolling)
|
|
|
|
// WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// However, if ulScrollLines > WHEEL_DELTA, we assume that
|
|
|
|
// the mouse driver wants a page scroll. The docs state that
|
|
|
|
// ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
|
|
|
|
// since some mouse drivers use an arbitrary large number instead,
|
|
|
|
// we have to handle that as well.
|
|
|
|
|
|
|
|
iDeltaPerLine = 0;
|
|
|
|
if (ulScrollLines) {
|
|
|
|
if (ulScrollLines <= WHEEL_DELTA) {
|
|
|
|
iDeltaPerLine = WHEEL_DELTA / ulScrollLines;
|
|
|
|
} else {
|
|
|
|
ulScrollLines = WHEEL_PAGESCROLL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
|
|
|
|
&ulScrollChars, 0)) {
|
|
|
|
// Note that we may always fail to get the value before Win Vista.
|
|
|
|
ulScrollChars = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
iDeltaPerChar = 0;
|
|
|
|
if (ulScrollChars) {
|
|
|
|
if (ulScrollChars <= WHEEL_DELTA) {
|
|
|
|
iDeltaPerChar = WHEEL_DELTA / ulScrollChars;
|
|
|
|
} else {
|
|
|
|
ulScrollChars = WHEEL_PAGESCROLL;
|
|
|
|
}
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if ((isVertical && ulScrollLines != WHEEL_PAGESCROLL && !iDeltaPerLine) ||
|
|
|
|
(!isVertical && ulScrollChars != WHEEL_PAGESCROLL && !iDeltaPerChar))
|
|
|
|
return PR_FALSE; // break
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// The mousewheel event will be dispatched to the toplevel
|
|
|
|
// window. We need to give it to the child window
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
POINT point;
|
|
|
|
point.x = GET_X_LPARAM(lParam);
|
|
|
|
point.y = GET_Y_LPARAM(lParam);
|
|
|
|
HWND destWnd = ::WindowFromPoint(point);
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Since we receive mousewheel events for as long as
|
|
|
|
// we are focused, it's entirely possible that there
|
|
|
|
// is another app's window or no window under the
|
|
|
|
// pointer.
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!destWnd) {
|
|
|
|
// No window is under the pointer
|
|
|
|
return PR_FALSE; // break
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
// We don't care about windows belonging to other processes.
|
|
|
|
DWORD processId = 0;
|
|
|
|
GetWindowThreadProcessId(destWnd, &processId);
|
|
|
|
if (processId != GetCurrentProcessId())
|
|
|
|
{
|
|
|
|
// Somebody elses window
|
|
|
|
return PR_FALSE; // break
|
|
|
|
}
|
|
|
|
|
|
|
|
nsWindow* destWindow = GetNSWindowPtr(destWnd);
|
|
|
|
if (!destWindow || destWindow->mIsPluginWindow) {
|
|
|
|
// Some other app, or a plugin window.
|
|
|
|
// Windows directs WM_MOUSEWHEEL to the focused window.
|
|
|
|
// However, Mozilla does not like plugins having focus, so a
|
|
|
|
// Mozilla window (ie, the plugin's parent (us!) has focus.)
|
|
|
|
// Therefore, plugins etc _should_ get first grab at the
|
|
|
|
// message, but this focus vaguary means the plugin misses
|
|
|
|
// out. If the window is a child of ours, forward it on.
|
|
|
|
// Determine if a child by walking the parent list until
|
|
|
|
// we find a parent matching our wndproc.
|
|
|
|
HWND parentWnd = ::GetParent(destWnd);
|
|
|
|
while (parentWnd) {
|
|
|
|
nsWindow* parentWindow = GetNSWindowPtr(parentWnd);
|
|
|
|
if (parentWindow) {
|
|
|
|
// We have a child window - quite possibly a plugin window.
|
|
|
|
// However, not all plugins are created equal - some will handle this message themselves,
|
|
|
|
// some will forward directly back to us, while others will call DefWndProc, which
|
|
|
|
// itself still forwards back to us.
|
|
|
|
// So if we have sent it once, we need to handle it ourself.
|
|
|
|
if (mInWheelProcessing) {
|
|
|
|
destWnd = parentWnd;
|
|
|
|
destWindow = parentWindow;
|
|
|
|
} else {
|
|
|
|
// First time we have seen this message.
|
|
|
|
// Call the child - either it will consume it, or
|
|
|
|
// it will wind it's way back to us, triggering the destWnd case above.
|
|
|
|
// either way, when the call returns, we are all done with the message,
|
|
|
|
mInWheelProcessing = PR_TRUE;
|
|
|
|
if (0 == ::SendMessageW(destWnd, msg, wParam, lParam)) {
|
|
|
|
result = PR_TRUE; // consumed - don't call DefWndProc
|
|
|
|
}
|
|
|
|
destWnd = nsnull;
|
|
|
|
mInWheelProcessing = PR_FALSE;
|
|
|
|
}
|
|
|
|
return PR_FALSE; // break; // stop parent search
|
|
|
|
}
|
|
|
|
parentWnd = ::GetParent(parentWnd);
|
|
|
|
} // while parentWnd
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
if (destWnd == nsnull)
|
|
|
|
return PR_FALSE;
|
|
|
|
if (destWnd != mWnd) {
|
|
|
|
if (destWindow) {
|
|
|
|
result = destWindow->ProcessMessage(msg, wParam, lParam, aRetValue);
|
|
|
|
return PR_TRUE; // return result immediately
|
|
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
else
|
|
|
|
printf("WARNING: couldn't get child window for MW event\n");
|
|
|
|
#endif
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// We should cancel the surplus delta if the current window is not
|
|
|
|
// same as previous.
|
|
|
|
if (currentWindow != mWnd) {
|
|
|
|
currentVDelta = 0;
|
|
|
|
currentHDelta = 0;
|
|
|
|
currentWindow = mWnd;
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
|
|
|
scrollEvent.delta = 0;
|
|
|
|
if (isVertical) {
|
|
|
|
scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
|
|
|
|
if (ulScrollLines == WHEEL_PAGESCROLL) {
|
|
|
|
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? -1 : 1;
|
|
|
|
} else {
|
|
|
|
currentVDelta -= (short) HIWORD (wParam);
|
|
|
|
if (PR_ABS(currentVDelta) >= iDeltaPerLine) {
|
|
|
|
scrollEvent.delta = currentVDelta / iDeltaPerLine;
|
|
|
|
currentVDelta %= iDeltaPerLine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
scrollEvent.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
|
|
|
|
if (ulScrollChars == WHEEL_PAGESCROLL) {
|
|
|
|
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? 1 : -1;
|
|
|
|
} else {
|
|
|
|
currentHDelta += (short) HIWORD (wParam);
|
|
|
|
if (PR_ABS(currentHDelta) >= iDeltaPerChar) {
|
|
|
|
scrollEvent.delta = currentHDelta / iDeltaPerChar;
|
|
|
|
currentHDelta %= iDeltaPerChar;
|
|
|
|
}
|
|
|
|
}
|
2009-06-23 13:57:45 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 23:02:07 -07:00
|
|
|
if (!scrollEvent.delta)
|
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
scrollEvent.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
scrollEvent.isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
|
|
|
scrollEvent.isMeta = PR_FALSE;
|
|
|
|
scrollEvent.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
|
|
|
InitEvent(scrollEvent);
|
|
|
|
if (nsnull != mEventCallback) {
|
|
|
|
result = DispatchWindowEvent(&scrollEvent);
|
|
|
|
}
|
|
|
|
// Note that we should return zero if we process WM_MOUSEWHEEL.
|
|
|
|
// But if we process WM_MOUSEHWHEEL, we should return non-zero.
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (result)
|
|
|
|
result = isVertical ? 0 : TRUE;
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_FALSE; // break;
|
|
|
|
}
|
|
|
|
#endif // !defined(WINCE)
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
static PRBool
|
|
|
|
StringCaseInsensitiveEquals(const PRUnichar* aChars1, const PRUint32 aNumChars1,
|
|
|
|
const PRUnichar* aChars2, const PRUint32 aNumChars2)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aNumChars1 != aNumChars2)
|
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsCaseInsensitiveStringComparator comp;
|
|
|
|
return comp(aChars1, aChars2, aNumChars1) == 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
UINT nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode)
|
2008-03-12 15:44:45 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
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
|
|
|
|
}
|
|
|
|
#endif
|
2008-04-23 15:51:27 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return aNativeKeyCode;
|
2008-03-12 15:44:45 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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,
|
|
|
|
PRBool *aEventDispatched,
|
|
|
|
nsFakeCharMessage* aFakeCharMessage)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
UINT virtualKeyCode = aMsg.wParam;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
gKbdLayout.OnKeyDown (virtualKeyCode);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Use only DOMKeyCode for XP processing.
|
|
|
|
// Use aVirtualKeyCode for gKbdLayout and native processing.
|
|
|
|
UINT DOMKeyCode = nsIMM32Handler::IsComposing(this) ?
|
|
|
|
virtualKeyCode : MapFromNativeToDOM(virtualKeyCode);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
//printf("In OnKeyDown virt: %d\n", DOMKeyCode);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool noDefault =
|
|
|
|
DispatchKeyEvent(NS_KEY_DOWN, 0, nsnull, DOMKeyCode, &aMsg, aModKeyState);
|
|
|
|
if (aEventDispatched)
|
|
|
|
*aEventDispatched = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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)
|
|
|
|
#ifdef WINCE
|
|
|
|
))
|
|
|
|
#else
|
|
|
|
&& !gKbdLayout.IsDeadKey() && KeyboardLayout::IsPrintableCharKey(virtualKeyCode)))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// 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
|
|
|
|
PRBool anyCharMessagesRemoved = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aFakeCharMessage) {
|
|
|
|
anyCharMessagesRemoved = PR_TRUE;
|
|
|
|
} else {
|
|
|
|
while (gotMsg && (msg.message == WM_CHAR || msg.message == WM_SYSCHAR))
|
|
|
|
{
|
|
|
|
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));
|
|
|
|
RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST);
|
|
|
|
anyCharMessagesRemoved = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
gotMsg = ::PeekMessageW (&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
else if (gotMsg &&
|
|
|
|
(aFakeCharMessage ||
|
|
|
|
msg.message == WM_CHAR || msg.message == WM_SYSCHAR || msg.message == WM_DEADCHAR)) {
|
|
|
|
if (aFakeCharMessage)
|
|
|
|
return OnCharRaw(aFakeCharMessage->mCharCode,
|
|
|
|
aFakeCharMessage->mScanCode, aModKeyState, extraFlags);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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())
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
// We need to send the removed message to focused plug-in.
|
|
|
|
DispatchPluginEvent(msg);
|
|
|
|
return noDefault;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
else if (!aModKeyState.mIsControlDown && !aModKeyState.mIsAltDown &&
|
|
|
|
(KeyboardLayout::IsPrintableCharKey(virtualKeyCode) ||
|
|
|
|
KeyboardLayout::IsNumpadKey(virtualKeyCode)))
|
|
|
|
{
|
|
|
|
// 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 15:44:45 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (gKbdLayout.IsDeadKey ())
|
|
|
|
return PluginHasFocus() && noDefault;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
default:
|
2009-06-29 12:36:16 -07:00
|
|
|
if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
|
|
|
|
numOfUniChars = numOfShiftStates =
|
|
|
|
gKbdLayout.GetUniChars(uniChars, shiftStates,
|
|
|
|
NS_ARRAY_LENGTH(uniChars));
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aModKeyState.mIsControlDown ^ aModKeyState.mIsAltDown) {
|
|
|
|
PRUint8 capsLockState = (::GetKeyState(VK_CAPITAL) & 1) ? eCapsLock : 0;
|
|
|
|
numOfUnshiftedChars =
|
|
|
|
gKbdLayout.GetUniCharsWithShiftState(virtualKeyCode, capsLockState,
|
|
|
|
unshiftedChars, NS_ARRAY_LENGTH(unshiftedChars));
|
|
|
|
numOfShiftedChars =
|
|
|
|
gKbdLayout.GetUniCharsWithShiftState(virtualKeyCode,
|
|
|
|
capsLockState | eShift,
|
|
|
|
shiftedChars, NS_ARRAY_LENGTH(shiftedChars));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (numOfUniChars > 0 || numOfShiftedChars > 0 || numOfUnshiftedChars > 0) {
|
|
|
|
PRUint32 num = PR_MAX(numOfUniChars,
|
|
|
|
PR_MAX(numOfShiftedChars, numOfUnshiftedChars));
|
|
|
|
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);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
DispatchKeyEvent(NS_KEY_PRESS, uniChar, &altArray,
|
|
|
|
keyCode, nsnull, aModKeyState, extraFlags);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
DispatchKeyEvent(NS_KEY_PRESS, 0, nsnull, DOMKeyCode, nsnull, aModKeyState,
|
|
|
|
extraFlags);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return noDefault;
|
|
|
|
}
|
|
|
|
|
|
|
|
// OnKeyUp
|
|
|
|
LRESULT nsWindow::OnKeyUp(const MSG &aMsg,
|
|
|
|
nsModifierKeyState &aModKeyState,
|
|
|
|
PRBool *aEventDispatched)
|
|
|
|
{
|
|
|
|
UINT virtualKeyCode = aMsg.wParam;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
|
|
|
("nsWindow::OnKeyUp VK=%d\n", virtualKeyCode));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!nsIMM32Handler::IsComposing(this)) {
|
|
|
|
virtualKeyCode = MapFromNativeToDOM(virtualKeyCode);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aEventDispatched)
|
|
|
|
*aEventDispatched = PR_TRUE;
|
|
|
|
return DispatchKeyEvent(NS_KEY_UP, 0, nsnull, virtualKeyCode, &aMsg,
|
|
|
|
aModKeyState);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// OnChar
|
|
|
|
LRESULT nsWindow::OnChar(const MSG &aMsg, nsModifierKeyState &aModKeyState,
|
|
|
|
PRBool *aEventDispatched, PRUint32 aFlags)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
return OnCharRaw(aMsg.wParam, HIWORD(aMsg.lParam) & 0xFF, aModKeyState,
|
|
|
|
aFlags, &aMsg, aEventDispatched);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// OnCharRaw
|
|
|
|
LRESULT nsWindow::OnCharRaw(UINT charCode, UINT aScanCode,
|
|
|
|
nsModifierKeyState &aModKeyState, PRUint32 aFlags,
|
|
|
|
const MSG *aMsg, PRBool *aEventDispatched)
|
|
|
|
{
|
|
|
|
// 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;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// WM_CHAR with Control and Alt (== AltGr) down really means a normal character
|
|
|
|
PRBool saveIsAltDown = aModKeyState.mIsAltDown;
|
|
|
|
PRBool saveIsControlDown = aModKeyState.mIsControlDown;
|
|
|
|
if (aModKeyState.mIsAltDown && aModKeyState.mIsControlDown)
|
|
|
|
aModKeyState.mIsAltDown = aModKeyState.mIsControlDown = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
wchar_t uniChar;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsIMM32Handler::IsComposing(this)) {
|
|
|
|
ResetInputState();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07: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);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool result = DispatchKeyEvent(NS_KEY_PRESS, uniChar, nsnull,
|
|
|
|
charCode, aMsg, aModKeyState, aFlags);
|
|
|
|
if (aEventDispatched)
|
|
|
|
*aEventDispatched = PR_TRUE;
|
|
|
|
aModKeyState.mIsAltDown = saveIsAltDown;
|
|
|
|
aModKeyState.mIsControlDown = saveIsControlDown;
|
2007-03-22 10:30:00 -07:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07: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 11:00:39 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sModifierKeyMap); ++i) {
|
|
|
|
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 11:00:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// OnDestroy
|
|
|
|
void nsWindow::OnDestroy()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
mOnDestroyCalled = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
SubclassWindow(FALSE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// We have to destroy the native drag target before we null out our
|
|
|
|
// window pointer
|
|
|
|
EnableDragDrop(PR_FALSE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
mWnd = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// free GDI objects
|
|
|
|
if (mBrush) {
|
|
|
|
VERIFY(::DeleteObject(mBrush));
|
|
|
|
mBrush = NULL;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// if we were in the middle of deferred window positioning then
|
|
|
|
// free the memory for the multiple-window position structure
|
|
|
|
if (mDeferredPositioner) {
|
|
|
|
VERIFY(::EndDeferWindowPos(mDeferredPositioner));
|
|
|
|
mDeferredPositioner = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// release references to children, device context, toolkit, and app shell
|
|
|
|
nsBaseWidget::OnDestroy();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// dispatch the event
|
|
|
|
if (!mIsDestroying) {
|
|
|
|
// dispatching of the event may cause the reference count to drop to 0
|
|
|
|
// and result in this object being destroyed. To avoid that, add a reference
|
|
|
|
// and then release it after dispatching the event
|
|
|
|
AddRef();
|
|
|
|
DispatchStandardEvent(NS_DESTROY);
|
|
|
|
Release();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// OnMove
|
|
|
|
PRBool nsWindow::OnMove(PRInt32 aX, PRInt32 aY)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
|
|
|
|
|
|
|
nsGUIEvent event(PR_TRUE, NS_MOVE, this);
|
|
|
|
InitEvent(event);
|
|
|
|
event.refPoint.x = aX;
|
|
|
|
event.refPoint.y = aY;
|
|
|
|
|
|
|
|
return DispatchWindowEvent(&event);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Send a resize message to the listener
|
|
|
|
PRBool nsWindow::OnResize(nsIntRect &aWindowRect)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
// call the event callback
|
|
|
|
if (mEventCallback) {
|
|
|
|
nsSizeEvent event(PR_TRUE, NS_SIZE, this);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
return DispatchWindowEvent(&event);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if !defined(WINCE) // implemented in nsWindowCE.cpp
|
|
|
|
PRBool nsWindow::OnHotKey(WPARAM wParam, LPARAM lParam)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // !defined(WINCE)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
void nsWindow::OnSettingsChange(WPARAM wParam, LPARAM lParam)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(WINCE_WINDOWS_MOBILE)
|
|
|
|
if (wParam == SPI_SETSIPINFO) {
|
|
|
|
nsWindowCE::NotifySoftKbObservers();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsWindowGfx::OnSettingsChangeGfx(wParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Deal with scrollbar messages (actually implemented only in nsScrollbar)
|
|
|
|
PRBool nsWindow::OnScroll(UINT scrollCode, int cPos)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Return the brush used to paint the background of this control
|
|
|
|
HBRUSH nsWindow::OnControlColor()
|
|
|
|
{
|
|
|
|
return mBrush;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Can be overriden. Controls auot-erase of background.
|
2007-03-22 10:30:00 -07:00
|
|
|
PRBool nsWindow::AutoErase()
|
|
|
|
{
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: IME management and accessibility
|
|
|
|
**
|
|
|
|
** Handles managing IME input and accessibility.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2009-03-04 01:09:09 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP nsWindow::ResetInputState()
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_KBSTATE
|
|
|
|
printf("ResetInputState\n");
|
|
|
|
#endif
|
2009-02-10 12:56:51 -08:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::CommitComposition(PR_FALSE);
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2009-05-03 15:20:11 -07:00
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
if (IMEContext.IsValid()) {
|
|
|
|
::ImmNotifyIME(IMEContext.get(), NI_COMPOSITIONSTR, CPS_COMPLETE, NULL);
|
|
|
|
::ImmNotifyIME(IMEContext.get(), NI_COMPOSITIONSTR, CPS_CANCEL, NULL);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsWindow::SetIMEOpenState(PRBool aState)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_KBSTATE
|
|
|
|
printf("SetIMEOpenState %s\n", (aState ? "Open" : "Close"));
|
|
|
|
#endif
|
2009-02-10 12:56:51 -08:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::SetIMEOpenState(aState);
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2009-05-03 15:20:11 -07:00
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
if (IMEContext.IsValid()) {
|
|
|
|
::ImmSetOpenStatus(IMEContext.get(), aState ? TRUE : FALSE);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsWindow::GetIMEOpenState(PRBool* aState)
|
|
|
|
{
|
2009-05-03 15:20:11 -07:00
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
if (IMEContext.IsValid()) {
|
|
|
|
BOOL isOpen = ::ImmGetOpenStatus(IMEContext.get());
|
2007-03-22 10:30:00 -07:00
|
|
|
*aState = isOpen ? PR_TRUE : PR_FALSE;
|
|
|
|
} else
|
|
|
|
*aState = PR_FALSE;
|
2009-02-10 12:56:51 -08:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
*aState |= nsTextStore::GetIMEOpenState();
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-15 06:43:55 -07:00
|
|
|
NS_IMETHODIMP nsWindow::SetIMEEnabled(PRUint32 aState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-02-10 12:56:51 -08:00
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::SetIMEEnabled(aState);
|
|
|
|
#endif //NS_ENABLE_TSF
|
2009-02-19 23:03:46 -08:00
|
|
|
#ifdef DEBUG_KBSTATE
|
|
|
|
printf("SetIMEEnabled: %s\n", (aState == nsIWidget::IME_STATUS_ENABLED ||
|
|
|
|
aState == nsIWidget::IME_STATUS_PLUGIN)?
|
|
|
|
"Enabled": "Disabled");
|
|
|
|
#endif
|
2009-05-03 15:20:11 -07:00
|
|
|
if (nsIMM32Handler::IsComposing(this))
|
2007-03-22 10:30:00 -07:00
|
|
|
ResetInputState();
|
2007-04-15 06:43:55 -07:00
|
|
|
mIMEEnabled = aState;
|
2008-12-14 19:54:54 -08:00
|
|
|
PRBool enable = (aState == nsIWidget::IME_STATUS_ENABLED ||
|
|
|
|
aState == nsIWidget::IME_STATUS_PLUGIN);
|
2009-02-19 23:03:46 -08:00
|
|
|
|
|
|
|
#if defined(WINCE_HAVE_SOFTKB)
|
2009-06-29 12:36:16 -07:00
|
|
|
sSoftKeyboardState = (aState != nsIWidget::IME_STATUS_DISABLED);
|
|
|
|
nsWindowCE::ToggleSoftKB(sSoftKeyboardState);
|
2009-02-19 23:03:46 -08:00
|
|
|
#endif
|
|
|
|
|
2007-04-15 06:43:55 -07:00
|
|
|
if (!enable != !mOldIMC)
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
2007-04-15 06:43:55 -07:00
|
|
|
mOldIMC = ::ImmAssociateContext(mWnd, enable ? mOldIMC : NULL);
|
|
|
|
NS_ASSERTION(!enable || !mOldIMC, "Another IMC was associated");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-15 06:43:55 -07:00
|
|
|
NS_IMETHODIMP nsWindow::GetIMEEnabled(PRUint32* aState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-02-19 23:03:46 -08:00
|
|
|
#ifdef DEBUG_KBSTATE
|
|
|
|
printf("GetIMEEnabled: %s\n", mIMEEnabled? "Enabled": "Disabled");
|
|
|
|
#endif
|
2007-04-15 06:43:55 -07:00
|
|
|
*aState = mIMEEnabled;
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsWindow::CancelIMEComposition()
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_KBSTATE
|
|
|
|
printf("CancelIMEComposition\n");
|
|
|
|
#endif
|
2009-02-10 12:56:51 -08:00
|
|
|
|
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
nsTextStore::CommitComposition(PR_TRUE);
|
|
|
|
#endif //NS_ENABLE_TSF
|
|
|
|
|
2009-05-03 15:20:11 -07:00
|
|
|
nsIMEContext IMEContext(mWnd);
|
|
|
|
if (IMEContext.IsValid()) {
|
|
|
|
::ImmNotifyIME(IMEContext.get(), NI_COMPOSITIONSTR, CPS_CANCEL, NULL);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-06-16 12:19:46 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_KBSTATE
|
|
|
|
printf("GetToggledKeyState\n");
|
|
|
|
#endif
|
|
|
|
NS_ENSURE_ARG_POINTER(aLEDState);
|
|
|
|
*aLEDState = (::GetKeyState(aKeyCode) & 1) != 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-02-10 12:56:51 -08:00
|
|
|
#ifdef NS_ENABLE_TSF
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::OnIMEFocusChange(PRBool aFocus)
|
|
|
|
{
|
2009-05-04 23:15:23 -07:00
|
|
|
nsresult rv = nsTextStore::OnFocusChange(aFocus, this, mIMEEnabled);
|
|
|
|
if (rv == NS_ERROR_NOT_AVAILABLE)
|
|
|
|
rv = NS_OK; // TSF is not enabled, maybe.
|
|
|
|
return rv;
|
2009-02-10 12:56:51 -08: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
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
already_AddRefed<nsIAccessible> nsWindow::GetRootAccessible()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
nsWindow::sIsAccessibilityOn = TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mIsDestroying || mOnDestroyCalled || mWindowType == eWindowType_invisible) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsIAccessible *rootAccessible = nsnull;
|
|
|
|
|
|
|
|
// If accessibility is turned on, we create this even before it is requested
|
|
|
|
// when the window gets focused. We need it to be created early so it can
|
|
|
|
// generate accessibility events right away
|
|
|
|
nsWindow* accessibleWindow = nsnull;
|
|
|
|
if (mContentType != eContentTypeInherit) {
|
|
|
|
// We're on a MozillaContentWindowClass or MozillaUIWindowClass window.
|
|
|
|
// Search for the correct visible child window to get an accessible
|
|
|
|
// document from. Make sure to use an active child window
|
|
|
|
HWND accessibleWnd = ::GetTopWindow(mWnd);
|
|
|
|
while (accessibleWnd) {
|
|
|
|
// Loop through windows and find the first one with accessibility info
|
|
|
|
accessibleWindow = GetNSWindowPtr(accessibleWnd);
|
|
|
|
if (accessibleWindow) {
|
|
|
|
accessibleWindow->DispatchAccessibleEvent(NS_GETACCESSIBLE, &rootAccessible);
|
|
|
|
if (rootAccessible) {
|
|
|
|
break; // Success, one of the child windows was active
|
|
|
|
}
|
|
|
|
}
|
|
|
|
accessibleWnd = ::GetNextWindow(accessibleWnd, GW_HWNDNEXT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DispatchAccessibleEvent(NS_GETACCESSIBLE, &rootAccessible);
|
2008-08-20 13:28:15 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return rootAccessible;
|
|
|
|
}
|
2008-08-20 13:28:15 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
STDMETHODIMP_(LRESULT)
|
|
|
|
nsWindow::LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc)
|
|
|
|
{
|
|
|
|
// open the dll dynamically
|
|
|
|
if (!sAccLib)
|
|
|
|
sAccLib =::LoadLibraryW(L"OLEACC.DLL");
|
2009-03-26 17:15:41 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sAccLib) {
|
|
|
|
if (!sLresultFromObject)
|
|
|
|
sLresultFromObject = (LPFNLRESULTFROMOBJECT)GetProcAddress(sAccLib,"LresultFromObject");
|
2009-03-26 17:15:41 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sLresultFromObject)
|
|
|
|
return sLresultFromObject(riid,wParam,pAcc);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2009-03-26 18:10:52 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Transparency
|
|
|
|
**
|
|
|
|
** Window transparency helpers.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
|
|
|
|
void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight, PRBool force)
|
|
|
|
{
|
|
|
|
if (!force && aNewWidth == mBounds.width && aNewHeight == mBounds.height)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mTransparentSurface = new gfxWindowsSurface(gfxIntSize(aNewWidth, aNewHeight), gfxASurface::ImageFormatARGB32);
|
|
|
|
mMemoryDC = mTransparentSurface->GetDC();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode)
|
2009-03-26 17:15:41 -07:00
|
|
|
{
|
2009-03-26 18:10:52 -07:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
if (aMode == mTransparencyMode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
HWND hWnd = GetTopLevelHWND(mWnd, PR_TRUE);
|
|
|
|
nsWindow* topWindow = GetNSWindowPtr(hWnd);
|
|
|
|
|
|
|
|
if (!topWindow)
|
|
|
|
{
|
|
|
|
NS_WARNING("Trying to use transparent chrome in an embedded context");
|
|
|
|
return;
|
2009-03-26 17:15:41 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
LONG_PTR style = 0, exStyle = 0;
|
|
|
|
switch(aMode) {
|
|
|
|
case eTransparencyTransparent:
|
|
|
|
exStyle |= WS_EX_LAYERED;
|
|
|
|
case eTransparencyOpaque:
|
|
|
|
case eTransparencyGlass:
|
|
|
|
topWindow->mTransparencyMode = aMode;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
style |= topWindow->WindowStyle();
|
|
|
|
exStyle |= topWindow->WindowExStyle();
|
|
|
|
|
|
|
|
if (aMode == eTransparencyTransparent) {
|
|
|
|
style &= ~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
|
|
|
|
exStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
VERIFY_WINDOW_STYLE(style);
|
|
|
|
::SetWindowLongPtrW(hWnd, GWL_STYLE, style);
|
|
|
|
::SetWindowLongPtrW(hWnd, GWL_EXSTYLE, exStyle);
|
|
|
|
|
|
|
|
mTransparencyMode = aMode;
|
|
|
|
|
|
|
|
SetupTranslucentWindowMemoryBitmap(aMode);
|
|
|
|
MARGINS margins = { 0, 0, 0, 0 };
|
|
|
|
if(eTransparencyGlass == aMode)
|
|
|
|
margins.cxLeftWidth = -1;
|
|
|
|
if(nsUXThemeData::sHaveCompositor)
|
|
|
|
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd, &margins);
|
2009-03-26 18:10:52 -07:00
|
|
|
#endif
|
2009-03-26 17:15:41 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
void nsWindow::SetupTranslucentWindowMemoryBitmap(nsTransparencyMode aMode)
|
2009-04-21 16:53:52 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (eTransparencyTransparent == aMode) {
|
|
|
|
ResizeTranslucentWindow(mBounds.width, mBounds.height, PR_TRUE);
|
|
|
|
} else {
|
|
|
|
mTransparentSurface = nsnull;
|
|
|
|
mMemoryDC = NULL;
|
|
|
|
}
|
2009-04-21 16:53:52 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
nsresult nsWindow::UpdateTranslucentWindow()
|
|
|
|
{
|
|
|
|
#ifndef WINCE
|
|
|
|
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 };
|
|
|
|
HWND hWnd = GetTopLevelHWND(mWnd, PR_TRUE);
|
|
|
|
RECT winRect;
|
|
|
|
::GetWindowRect(hWnd, &winRect);
|
|
|
|
|
|
|
|
// perform the alpha blend
|
|
|
|
if (!::UpdateLayeredWindow(hWnd, NULL, (POINT*)&winRect, &winSize, mMemoryDC, &srcPos, 0, &bf, ULW_ALPHA))
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //MOZ_XUL
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Popup rollup hooks
|
|
|
|
**
|
|
|
|
** Deals with CaptureRollup on popup windows.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#ifndef WINCE
|
|
|
|
// Schedules a timer for a window, so we can rollup after processing the hook event
|
|
|
|
void nsWindow::ScheduleHookTimer(HWND aWnd, UINT aMsgId)
|
|
|
|
{
|
|
|
|
// In some cases multiple hooks may be scheduled
|
|
|
|
// so ignore any other requests once one timer is scheduled
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sHookTimerId == 0) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// Remember the window handle and the message ID to be used later
|
2009-06-29 12:36:16 -07:00
|
|
|
sRollupMsgId = aMsgId;
|
|
|
|
sRollupMsgWnd = aWnd;
|
2007-03-22 10:30:00 -07:00
|
|
|
// Schedule native timer for doing the rollup after
|
|
|
|
// this event is done being processed
|
2009-06-29 12:36:16 -07:00
|
|
|
sHookTimerId = ::SetTimer(NULL, 0, 0, (TIMERPROC)HookTimerForPopups);
|
|
|
|
NS_ASSERTION(sHookTimerId, "Timer couldn't be created.");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
int gLastMsgCode = 0;
|
|
|
|
extern MSGFEventMsgInfo gMSGFEvents[];
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Process Menu messages, rollup when popup is clicked.
|
2007-03-22 10:30:00 -07:00
|
|
|
LRESULT CALLBACK nsWindow::MozSpecialMsgFilter(int code, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (sProcessHook) {
|
2007-03-22 10:30:00 -07: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) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf("MozSpecialMessageProc - code: 0x%X - %s hw: %p\n", code, gMSGFEvents[inx].mStr, pMsg->hwnd);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf("MozSpecialMessageProc - code: 0x%X - %d hw: %p\n", code, gMSGFEvents[inx].mId, pMsg->hwnd);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
gLastMsgCode = code;
|
|
|
|
}
|
|
|
|
PrintEvent(pMsg->message, FALSE, FALSE);
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // #ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sProcessHook && code == MSGF_MENU) {
|
2007-03-22 10:30:00 -07:00
|
|
|
MSG* pMsg = (MSG*)lParam;
|
|
|
|
ScheduleHookTimer( pMsg->hwnd, pMsg->message);
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return ::CallNextHookEx(sMsgFilterHook, code, wParam, lParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Process all mouse messages. Roll up when a click is in a native window
|
|
|
|
// that doesn't have an nsIWidget.
|
2007-03-22 10:30:00 -07:00
|
|
|
LRESULT CALLBACK nsWindow::MozSpecialMouseProc(int code, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sProcessHook) {
|
2008-11-26 21:42:18 -08:00
|
|
|
switch (wParam) {
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
case WM_MOUSEHWHEEL:
|
|
|
|
{
|
|
|
|
MOUSEHOOKSTRUCT* ms = (MOUSEHOOKSTRUCT*)lParam;
|
|
|
|
nsIWidget* mozWin = (nsIWidget*)GetNSWindowPtr(ms->hwnd);
|
|
|
|
if (mozWin) {
|
|
|
|
// If this window is windowed plugin window, the mouse events are not
|
|
|
|
// sent to us.
|
|
|
|
if (static_cast<nsWindow*>(mozWin)->mIsPluginWindow)
|
|
|
|
ScheduleHookTimer(ms->hwnd, (UINT)wParam);
|
|
|
|
} else {
|
|
|
|
ScheduleHookTimer(ms->hwnd, (UINT)wParam);
|
|
|
|
}
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return ::CallNextHookEx(sCallMouseHook, code, wParam, lParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Process all messages. Roll up when the window is moving, or
|
|
|
|
// is resizing or when maximized or mininized.
|
2007-03-22 10:30:00 -07:00
|
|
|
LRESULT CALLBACK nsWindow::MozSpecialWndProc(int code, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (sProcessHook) {
|
2007-03-22 10:30:00 -07:00
|
|
|
CWPSTRUCT* cwpt = (CWPSTRUCT*)lParam;
|
|
|
|
PrintEvent(cwpt->message, FALSE, FALSE);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sProcessHook) {
|
2007-03-22 10:30:00 -07:00
|
|
|
CWPSTRUCT* cwpt = (CWPSTRUCT*)lParam;
|
|
|
|
if (cwpt->message == WM_MOVING ||
|
|
|
|
cwpt->message == WM_SIZING ||
|
|
|
|
cwpt->message == WM_GETMINMAXINFO) {
|
|
|
|
ScheduleHookTimer(cwpt->hwnd, (UINT)cwpt->message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return ::CallNextHookEx(sCallProcHook, code, wParam, lParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Register the special "hooks" for dropdown processing.
|
2007-03-22 10:30:00 -07:00
|
|
|
void nsWindow::RegisterSpecialDropdownHooks()
|
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
NS_ASSERTION(!sMsgFilterHook, "sMsgFilterHook must be NULL!");
|
|
|
|
NS_ASSERTION(!sCallProcHook, "sCallProcHook must be NULL!");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
DISPLAY_NMM_PRT("***************** Installing Msg Hooks ***************\n");
|
|
|
|
|
|
|
|
//HMODULE hMod = GetModuleHandle("gkwidget.dll");
|
|
|
|
|
|
|
|
// Install msg hook for moving the window and resizing
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!sMsgFilterHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Hooking sMsgFilterHook!\n");
|
|
|
|
sMsgFilterHook = SetWindowsHookEx(WH_MSGFILTER, MozSpecialMsgFilter, NULL, GetCurrentThreadId());
|
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (!sMsgFilterHook) {
|
2007-03-22 10:30:00 -07:00
|
|
|
printf("***** SetWindowsHookEx is NOT installed for WH_MSGFILTER!\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Install msg hook for menus
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!sCallProcHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Hooking sCallProcHook!\n");
|
|
|
|
sCallProcHook = SetWindowsHookEx(WH_CALLWNDPROC, MozSpecialWndProc, NULL, GetCurrentThreadId());
|
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (!sCallProcHook) {
|
2007-03-22 10:30:00 -07:00
|
|
|
printf("***** SetWindowsHookEx is NOT installed for WH_CALLWNDPROC!\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Install msg hook for the mouse
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!sCallMouseHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Hooking sCallMouseHook!\n");
|
|
|
|
sCallMouseHook = SetWindowsHookEx(WH_MOUSE, MozSpecialMouseProc, NULL, GetCurrentThreadId());
|
|
|
|
#ifdef POPUP_ROLLUP_DEBUG_OUTPUT
|
|
|
|
if (!sCallMouseHook) {
|
2007-03-22 10:30:00 -07:00
|
|
|
printf("***** SetWindowsHookEx is NOT installed for WH_MOUSE!\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Unhook special message hooks for dropdowns.
|
2007-03-22 10:30:00 -07:00
|
|
|
void nsWindow::UnregisterSpecialDropdownHooks()
|
|
|
|
{
|
|
|
|
DISPLAY_NMM_PRT("***************** De-installing Msg Hooks ***************\n");
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sCallProcHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Unhooking sCallProcHook!\n");
|
|
|
|
if (!::UnhookWindowsHookEx(sCallProcHook)) {
|
|
|
|
DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallProcHook!\n");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
sCallProcHook = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sMsgFilterHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Unhooking sMsgFilterHook!\n");
|
|
|
|
if (!::UnhookWindowsHookEx(sMsgFilterHook)) {
|
|
|
|
DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sMsgFilterHook!\n");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
sMsgFilterHook = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sCallMouseHook) {
|
|
|
|
DISPLAY_NMM_PRT("***** Unhooking sCallMouseHook!\n");
|
|
|
|
if (!::UnhookWindowsHookEx(sCallMouseHook)) {
|
|
|
|
DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for sCallMouseHook!\n");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
sCallMouseHook = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This timer is designed to only fire one time at most each time a "hook" function
|
2009-06-29 12:36:16 -07: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.
|
2007-03-22 10:30:00 -07:00
|
|
|
//
|
|
|
|
// For example, if an MFC control takes focus, the combobox will lose focus and rollup
|
|
|
|
// before this function fires.
|
|
|
|
VOID CALLBACK nsWindow::HookTimerForPopups(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
|
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sHookTimerId != 0) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// if the window is NULL then we need to use the ID to kill the timer
|
2009-06-29 12:36:16 -07:00
|
|
|
BOOL status = ::KillTimer(NULL, sHookTimerId);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(status, "Hook Timer was not killed.");
|
2009-06-29 12:36:16 -07:00
|
|
|
sHookTimerId = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sRollupMsgId != 0) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// Note: DealWithPopups does the check to make sure that
|
2009-06-29 12:36:16 -07:00
|
|
|
// sRollupListener and sRollupWidget are not NULL
|
2007-03-22 10:30:00 -07:00
|
|
|
LRESULT popupHandlingResult;
|
2007-12-03 08:33:42 -08:00
|
|
|
nsAutoRollup autoRollup;
|
2009-06-29 12:36:16 -07:00
|
|
|
DealWithPopups(sRollupMsgWnd, sRollupMsgId, 0, 0, &popupHandlingResult);
|
|
|
|
sRollupMsgId = 0;
|
|
|
|
sRollupMsgWnd = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // WinCE
|
|
|
|
|
2008-11-26 21:42:18 -08:00
|
|
|
static PRBool IsDifferentThreadWindow(HWND aWnd)
|
|
|
|
{
|
|
|
|
return ::GetCurrentThreadId() != ::GetWindowThreadProcessId(aWnd, NULL);
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool
|
|
|
|
nsWindow::EventIsInsideWindow(UINT Msg, nsWindow* aWindow)
|
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
|
|
|
|
#ifndef WINCE
|
|
|
|
if (Msg == WM_ACTIVATEAPP)
|
|
|
|
// don't care about activation/deactivation
|
|
|
|
return PR_FALSE;
|
|
|
|
#else
|
|
|
|
if (Msg == WM_ACTIVATE)
|
|
|
|
// but on Windows CE we do care about
|
|
|
|
// activation/deactivation because there doesn't exist
|
|
|
|
// cancelable Mouse Activation events
|
|
|
|
return PR_TRUE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
::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?
|
|
|
|
return (PRBool) PtInRect(&r, mp);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
|
2007-03-22 10:30:00 -07:00
|
|
|
BOOL
|
2009-06-29 12:36:16 -07:00
|
|
|
nsWindow::DealWithPopups(HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inLParam, LRESULT* outResult)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
if (sRollupListener && sRollupWidget && ::IsWindowVisible(inWnd)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (inMsg == WM_LBUTTONDOWN || inMsg == WM_RBUTTONDOWN || inMsg == WM_MBUTTONDOWN ||
|
2008-11-26 21:42:18 -08:00
|
|
|
inMsg == WM_MOUSEWHEEL || inMsg == WM_MOUSEHWHEEL || inMsg == WM_ACTIVATE ||
|
|
|
|
(inMsg == WM_KILLFOCUS && IsDifferentThreadWindow((HWND)inWParam))
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
||
|
|
|
|
inMsg == WM_NCRBUTTONDOWN ||
|
|
|
|
inMsg == WM_MOVING ||
|
|
|
|
inMsg == WM_SIZING ||
|
|
|
|
inMsg == WM_NCLBUTTONDOWN ||
|
2007-03-22 10:30:00 -07:00
|
|
|
inMsg == WM_NCMBUTTONDOWN ||
|
|
|
|
inMsg == WM_MOUSEACTIVATE ||
|
|
|
|
inMsg == WM_ACTIVATEAPP ||
|
2008-12-06 04:21:26 -08:00
|
|
|
inMsg == WM_MENUSELECT
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// Rollup if the event is outside the popup.
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool rollup = !nsWindow::EventIsInsideWindow(inMsg, (nsWindow*)sRollupWidget);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (rollup && (inMsg == WM_MOUSEWHEEL || inMsg == WM_MOUSEHWHEEL))
|
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
sRollupListener->ShouldRollupOnMouseWheelEvent(&rollup);
|
2007-03-22 10:30:00 -07:00
|
|
|
*outResult = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 11:23:16 -07:00
|
|
|
PRUint32 popupsToRollup = PR_UINT32_MAX;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (rollup) {
|
2009-06-29 12:36:16 -07:00
|
|
|
nsCOMPtr<nsIMenuRollup> menuRollup ( do_QueryInterface(sRollupListener) );
|
2007-03-22 10:30:00 -07:00
|
|
|
if ( menuRollup ) {
|
2008-01-16 22:57:13 -08:00
|
|
|
nsAutoTArray<nsIWidget*, 5> widgetChain;
|
2009-06-12 11:23:16 -07:00
|
|
|
PRUint32 sameTypeCount = menuRollup->GetSubmenuWidgetChain(&widgetChain);
|
2008-01-16 22:57:13 -08:00
|
|
|
for ( PRUint32 i = 0; i < widgetChain.Length(); ++i ) {
|
|
|
|
nsIWidget* widget = widgetChain[i];
|
|
|
|
if ( nsWindow::EventIsInsideWindow(inMsg, (nsWindow*)widget) ) {
|
2009-06-12 11:23:16 -07:00
|
|
|
// don't roll up if the mouse event occured within a menu of the
|
|
|
|
// same type. If the mouse event occured in a menu higher than
|
|
|
|
// that, roll up, but pass the number of popups to Rollup so
|
|
|
|
// that only those of the same type close up.
|
|
|
|
if (i < sameTypeCount) {
|
|
|
|
rollup = PR_FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
popupsToRollup = sameTypeCount;
|
|
|
|
}
|
2008-01-16 22:57:13 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} // foreach parent menu widget
|
2007-03-22 10:30:00 -07:00
|
|
|
} // if rollup listener knows about menus
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef WINCE
|
2009-06-12 11:23:16 -07:00
|
|
|
if (inMsg == WM_MOUSEACTIVATE && popupsToRollup == PR_UINT32_MAX) {
|
2007-03-22 10:30:00 -07: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.
|
2009-06-29 12:36:16 -07:00
|
|
|
sRollupListener->ShouldRollupOnMouseActivate(&rollup);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!rollup)
|
|
|
|
{
|
|
|
|
*outResult = MA_NOACTIVATE;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if we've still determined that we should still rollup everything, do it.
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if ( rollup ) {
|
2009-06-29 12:36:16 -07:00
|
|
|
// sRollupConsumeEvent may be modified by
|
2008-11-17 22:15:24 -08:00
|
|
|
// nsIRollupListener::Rollup.
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool consumeRollupEvent = sRollupConsumeEvent;
|
2007-12-03 08:33:42 -08:00
|
|
|
// only need to deal with the last rollup for left mouse down events.
|
2009-06-29 12:36:16 -07:00
|
|
|
sRollupListener->Rollup(popupsToRollup, inMsg == WM_LBUTTONDOWN ? &mLastRollup : nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Tell hook to stop processing messages
|
2009-06-29 12:36:16 -07:00
|
|
|
sProcessHook = PR_FALSE;
|
|
|
|
sRollupMsgId = 0;
|
|
|
|
sRollupMsgWnd = NULL;
|
2007-03-22 10:30:00 -07: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-17 22:15:24 -08:00
|
|
|
if (consumeRollupEvent && inMsg != WM_RBUTTONDOWN) {
|
2007-03-22 10:30:00 -07:00
|
|
|
*outResult = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-06-12 12:15:36 -07:00
|
|
|
#ifndef WINCE
|
2009-06-12 11:23:16 -07: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;
|
|
|
|
}
|
2009-06-12 12:15:36 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
} // if event that might trigger a popup to rollup
|
|
|
|
} // if rollup listeners registered
|
|
|
|
|
|
|
|
return FALSE;
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: Misc. utility methods and functions.
|
|
|
|
**
|
|
|
|
** General use.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// nsModifierKeyState used in various character processing.
|
|
|
|
nsModifierKeyState::nsModifierKeyState()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
mIsShiftDown = IS_VK_DOWN(NS_VK_SHIFT);
|
|
|
|
mIsControlDown = IS_VK_DOWN(NS_VK_CONTROL);
|
|
|
|
mIsAltDown = IS_VK_DOWN(NS_VK_ALT);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRInt32 nsWindow::GetWindowsVersion()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifdef WINCE
|
|
|
|
return 0x500;
|
|
|
|
#else
|
|
|
|
static PRInt32 version = 0;
|
|
|
|
static PRBool didCheck = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!didCheck)
|
|
|
|
{
|
|
|
|
didCheck = PR_TRUE;
|
|
|
|
OSVERSIONINFOEX osInfo;
|
|
|
|
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
|
|
// This cast is safe and supposed to be here, don't worry
|
|
|
|
::GetVersionEx((OSVERSIONINFO*)&osInfo);
|
|
|
|
version = (osInfo.dwMajorVersion & 0xff) << 8 | (osInfo.dwMinorVersion & 0xff);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return version;
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Note that the result of GetTopLevelWindow method can be different from the
|
|
|
|
// result of GetTopLevelHWND method. The result can be non-floating window.
|
|
|
|
// Because our top level window may be contained in another window which is
|
|
|
|
// not managed by us.
|
2008-09-09 10:22:12 -07:00
|
|
|
nsWindow* nsWindow::GetTopLevelWindow(PRBool aStopOnDialogOrPopup)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsWindow* curWindow = this;
|
|
|
|
|
2008-09-09 10:22:12 -07:00
|
|
|
while (PR_TRUE) {
|
|
|
|
if (aStopOnDialogOrPopup) {
|
|
|
|
switch (curWindow->mWindowType) {
|
|
|
|
case eWindowType_dialog:
|
|
|
|
case eWindowType_popup:
|
|
|
|
return curWindow;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-04-19 12:15:25 -07:00
|
|
|
// Retrieve the top level parent or owner window
|
|
|
|
nsWindow* parentWindow = curWindow->GetParentWindow(PR_TRUE);
|
2008-09-09 10:22:12 -07:00
|
|
|
|
|
|
|
if (!parentWindow)
|
2007-03-22 10:30:00 -07:00
|
|
|
return curWindow;
|
2008-09-09 10:22:12 -07:00
|
|
|
|
|
|
|
curWindow = parentWindow;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// Note that the result of GetTopLevelHWND can be different from the result
|
|
|
|
// of GetTopLevelWindow method. Because this is checking whether the window
|
|
|
|
// is top level only in Win32 window system. Therefore, the result window
|
|
|
|
// may not be managed by us.
|
|
|
|
HWND nsWindow::GetTopLevelHWND(HWND aWnd, PRBool aStopOnDialogOrPopup)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
HWND curWnd = aWnd;
|
|
|
|
HWND topWnd = NULL;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
while (curWnd) {
|
|
|
|
topWnd = curWnd;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aStopOnDialogOrPopup) {
|
|
|
|
DWORD_PTR style = ::GetWindowLongPtrW(curWnd, GWL_STYLE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
VERIFY_WINDOW_STYLE(style);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (!(style & WS_CHILD)) // first top-level window
|
|
|
|
break;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
curWnd = ::GetParent(curWnd); // Parent or owner (if has no parent)
|
|
|
|
}
|
|
|
|
|
|
|
|
return topWnd;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
static BOOL CALLBACK gEnumWindowsProc(HWND hwnd, LPARAM lParam)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
DWORD pid;
|
|
|
|
::GetWindowThreadProcessId(hwnd, &pid);
|
|
|
|
if (pid == GetCurrentProcessId() && ::IsWindowVisible(hwnd))
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
gWindowsVisible = PR_TRUE;
|
|
|
|
return FALSE;
|
2009-02-24 08:53:32 -08:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool nsWindow::CanTakeFocus()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
gWindowsVisible = PR_FALSE;
|
|
|
|
EnumWindows(gEnumWindowsProc, 0);
|
|
|
|
if (!gWindowsVisible) {
|
|
|
|
return PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
} else {
|
2009-06-29 12:36:16 -07:00
|
|
|
HWND fgWnd = ::GetForegroundWindow();
|
|
|
|
if (!fgWnd) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
DWORD pid;
|
|
|
|
GetWindowThreadProcessId(fgWnd, &pid);
|
|
|
|
if (pid == GetCurrentProcessId()) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** BLOCK: ChildWindow impl.
|
|
|
|
**
|
|
|
|
** Child window overrides.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// Deal with all sort of mouse event
|
|
|
|
PRBool ChildWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam, LPARAM lParam,
|
|
|
|
PRBool aIsContextMenuKey, PRInt16 aButton)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-06-29 12:36:16 -07:00
|
|
|
PRBool result = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (nsnull == mEventCallback) {
|
|
|
|
return result;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
switch (aEventType) {
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
CaptureMouse(PR_TRUE);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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:
|
|
|
|
if (!(wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) && mIsInMouseCapture)
|
|
|
|
CaptureMouse(PR_FALSE);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
} // switch
|
|
|
|
|
|
|
|
return nsWindow::DispatchMouseEvent(aEventType, wParam, lParam,
|
|
|
|
aIsContextMenuKey, aButton);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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;
|
|
|
|
}
|