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>
|
2009-08-31 15:19:06 -07:00
|
|
|
* Kyle Huey <me@kylehuey.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.
|
|
|
|
**
|
|
|
|
**************************************************************
|
|
|
|
**************************************************************/
|
|
|
|
|
2009-11-06 14:33:12 -08:00
|
|
|
#ifdef MOZ_IPC
|
|
|
|
#include "mozilla/ipc/SyncChannel.h"
|
|
|
|
#endif
|
|
|
|
|
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"
|
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"
|
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"
|
2009-10-06 11:47:46 -07:00
|
|
|
#include "nsIdleService.h"
|
2009-06-29 12:36:16 -07:00
|
|
|
#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-07-21 17:45:13 -07:00
|
|
|
#include "nsTHashtable.h"
|
|
|
|
#include "nsHashKeys.h"
|
2009-08-31 15:19:06 -07:00
|
|
|
#include "nsString.h"
|
2009-02-12 18:26:02 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(WINCE)
|
|
|
|
#include "nsWindowCE.h"
|
2009-08-27 13:11:04 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(WINCE_WINDOWS_MOBILE)
|
2009-08-19 09:23:30 -07:00
|
|
|
#define KILL_PRIORITY_ID 2444
|
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>
|
2009-08-10 02:14:01 -07:00
|
|
|
#include <richedit.h>
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // !defined(WINCE)
|
2009-04-22 17:48:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#if defined(ACCESSIBILITY)
|
2009-08-10 02:14:01 -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-10-05 19:26:54 -07:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
|
|
|
#include "nsIWinTaskbar.h"
|
|
|
|
#endif
|
|
|
|
|
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
|
2009-09-16 18:30:26 -07:00
|
|
|
#include "npapi.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#include "nsWindowDefs.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-08-20 15:15:01 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
#include "nsGfxCIID.h"
|
|
|
|
#endif
|
2009-08-04 14:28:17 -07:00
|
|
|
|
2009-11-05 11:58:21 -08:00
|
|
|
// A magic APP message that can be sent to quit, sort of like a QUERYENDSESSION/ENDSESSION,
|
|
|
|
// but without the query.
|
|
|
|
#define MOZ_WM_APP_QUIT (WM_APP+0x0300)
|
|
|
|
|
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-10-06 21:19:04 -07:00
|
|
|
// Default Trackpoint Hack to off
|
|
|
|
PRBool nsWindow::sTrackPointHack = PR_FALSE;
|
|
|
|
|
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
|
|
|
|
|
2009-08-26 09:07:15 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
// HTC Navigation Wheel Event
|
|
|
|
// This is the defined value for Gesture Mode
|
|
|
|
const int WM_HTCNAV = 0x0400 + 200;
|
|
|
|
|
|
|
|
typedef int (__stdcall * HTCApiNavOpen)(HANDLE, int);
|
|
|
|
typedef int (__stdcall * HTCApiNavSetMode)(HANDLE, unsigned int);
|
|
|
|
|
|
|
|
HTCApiNavOpen gHTCApiNavOpen = nsnull;
|
|
|
|
HTCApiNavSetMode gHTCApiNavSetMode = nsnull;
|
2009-08-31 15:13:24 -07:00
|
|
|
static PRBool gCheckForHTCApi = PR_FALSE;
|
2009-08-26 09:07:15 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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-10-06 11:47:46 -07:00
|
|
|
static void UpdateLastInputEventTime() {
|
|
|
|
gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
|
|
|
|
nsCOMPtr<nsIIdleService> idleService = do_GetService("@mozilla.org/widget/idleservice;1");
|
|
|
|
nsIdleService* is = static_cast<nsIdleService*>(idleService.get());
|
|
|
|
if (is)
|
|
|
|
is->IdleTimeWasModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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-08-20 15:15:01 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
|
|
|
|
#endif
|
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;
|
|
|
|
mOldIMC = nsnull;
|
|
|
|
mNativeDragTarget = nsnull;
|
2009-07-13 08:58:19 -07:00
|
|
|
mInDtor = PR_FALSE;
|
2009-06-29 12:36:16 -07:00
|
|
|
mIsVisible = PR_FALSE;
|
|
|
|
mHas3DBorder = PR_FALSE;
|
|
|
|
mIsInMouseCapture = PR_FALSE;
|
|
|
|
mIsTopWidgetWindow = PR_FALSE;
|
2009-08-31 15:19:06 -07:00
|
|
|
mInScrollProcessing = PR_FALSE;
|
2009-06-29 12:36:16 -07:00
|
|
|
mUnicodeWidget = PR_TRUE;
|
|
|
|
mWindowType = eWindowType_child;
|
|
|
|
mBorderStyle = eBorderStyle_default;
|
|
|
|
mPopupType = ePopupTypeAny;
|
2009-08-13 13:54:09 -07:00
|
|
|
mDisplayPanFeedback = PR_FALSE;
|
2009-06-29 12:36:16 -07:00
|
|
|
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-08-20 15:15:01 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
mInvalidatedRegion = do_CreateInstance(kRegionCID);
|
|
|
|
mInvalidatedRegion->Init();
|
|
|
|
#endif
|
|
|
|
|
2009-10-05 19:26:54 -07:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
|
|
|
mTaskbarPreview = nsnull;
|
|
|
|
mHasTaskbarIconBeenCreated = PR_FALSE;
|
|
|
|
#endif
|
|
|
|
|
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
|
2009-10-06 21:19:04 -07:00
|
|
|
|
|
|
|
#if !defined(WINCE)
|
|
|
|
InitTrackPointHack();
|
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
} // !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-07-13 08:58:19 -07:00
|
|
|
mInDtor = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-13 08:58:19 -07:00
|
|
|
// If the widget was released without calling Destroy() then the native window still
|
|
|
|
// exists, and we need to destroy it. This will also result in a call to OnDestroy.
|
|
|
|
//
|
|
|
|
// XXX How could this happen???
|
|
|
|
if (NULL != mWnd)
|
2009-06-29 12:36:16 -07:00
|
|
|
Destroy();
|
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.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
// 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-09-23 23:18:10 -07:00
|
|
|
// Create the proper widget
|
2009-06-29 12:36:16 -07:00
|
|
|
nsresult
|
2009-09-23 23:18:10 -07:00
|
|
|
nsWindow::Create(nsIWidget *aParent,
|
|
|
|
nsNativeWidget aNativeParent,
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
EVENT_CALLBACK aHandleEventFunction,
|
|
|
|
nsIDeviceContext *aContext,
|
|
|
|
nsIAppShell *aAppShell,
|
|
|
|
nsIToolkit *aToolkit,
|
|
|
|
nsWidgetInitData *aInitData)
|
2009-06-29 12:36:16 -07:00
|
|
|
{
|
2009-09-23 23:18:10 -07:00
|
|
|
if (aInitData)
|
|
|
|
mUnicodeWidget = aInitData->mUnicode;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
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
|
|
|
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) {
|
|
|
|
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;
|
2009-08-25 12:00:46 -07:00
|
|
|
} else if (mWindowType == eWindowType_invisible) {
|
|
|
|
// Make sure CreateWindowEx succeeds at creating a toplevel window
|
2009-08-25 13:13:23 -07:00
|
|
|
style &= ~0x40000000; // WS_CHILDWINDOW
|
2009-06-29 12:36:16 -07:00
|
|
|
} 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-10-06 21:19:04 -07:00
|
|
|
if (nsWindow::sTrackPointHack &&
|
|
|
|
mWindowType != eWindowType_plugin &&
|
2009-09-24 02:32:20 -07:00
|
|
|
mWindowType != eWindowType_invisible) {
|
|
|
|
// Ugly Thinkpad Driver Hack (Bug 507222)
|
|
|
|
// We create an invisible scrollbar to trick the
|
|
|
|
// Trackpoint driver into sending us scrolling messages
|
|
|
|
::CreateWindowW(L"SCROLLBAR", L"FAKETRACKPOINTSCROLLBAR",
|
|
|
|
WS_CHILD | WS_VISIBLE, 0,0,0,0, mWnd, NULL,
|
|
|
|
nsToolkit::mDllInstance, NULL);
|
|
|
|
}
|
2009-08-31 15:19:06 -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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#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
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-13 08:58:19 -07:00
|
|
|
// Close this nsWindow
|
|
|
|
NS_METHOD nsWindow::Destroy()
|
|
|
|
{
|
|
|
|
// WM_DESTROY has already fired, we're done.
|
|
|
|
if (nsnull == mWnd)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// During the destruction of all of our children, make sure we don't get deleted.
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
|
|
|
|
|
|
|
// The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
|
|
|
|
// and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
|
|
|
|
// from it. The function also destroys the window's menu, flushes the thread message queue,
|
|
|
|
// destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if
|
|
|
|
// the window is at the top of the viewer chain).
|
|
|
|
//
|
|
|
|
// If the specified window is a parent or owner window, DestroyWindow automatically destroys
|
|
|
|
// the associated child or owned windows when it destroys the parent or owner window. The
|
|
|
|
// function first destroys child or owned windows, and then it destroys the parent or owner
|
|
|
|
// window.
|
|
|
|
VERIFY(::DestroyWindow(mWnd));
|
|
|
|
|
|
|
|
// Our windows can be subclassed which may prevent us receiving WM_DESTROY. If OnDestroy()
|
|
|
|
// didn't get called, call it now.
|
|
|
|
if (PR_FALSE == mOnDestroyCalled)
|
|
|
|
OnDestroy();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
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;
|
2009-07-27 10:29:04 -07:00
|
|
|
wc.lpszClassName = kClassNameDropShadow;
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
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
|
|
|
|
2009-07-27 11:05:11 -07:00
|
|
|
return kClassNameDropShadow;
|
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) {
|
2009-09-24 02:32:20 -07:00
|
|
|
case eWindowType_plugin:
|
2009-06-29 12:36:16 -07:00
|
|
|
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;
|
2009-09-26 15:42:14 -07:00
|
|
|
if (mTransparencyMode != eTransparencyGlass) {
|
2009-06-29 12:36:16 -07:00
|
|
|
style |= WS_OVERLAPPED;
|
|
|
|
}
|
|
|
|
break;
|
2009-02-10 12:56:51 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default:
|
2009-08-14 07:09:00 -07:00
|
|
|
NS_ERROR("unknown border style");
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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-08-16 03:54:26 -07:00
|
|
|
if (mBorderStyle != eBorderStyle_default && mBorderStyle != eBorderStyle_all) {
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_border))
|
|
|
|
style &= ~WS_BORDER;
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_title)) {
|
|
|
|
style &= ~WS_DLGFRAME;
|
|
|
|
style |= WS_POPUP;
|
|
|
|
style &= ~WS_CHILD;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_close))
|
|
|
|
style &= ~0;
|
|
|
|
// XXX The close box can only be removed by changing the window class,
|
|
|
|
// as far as I know --- roc+moz@cs.cmu.edu
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none ||
|
|
|
|
!(mBorderStyle & (eBorderStyle_menu | eBorderStyle_close)))
|
|
|
|
style &= ~WS_SYSMENU;
|
|
|
|
// Looks like getting rid of the system menu also does away with the
|
|
|
|
// close box. So, we only get rid of the system menu if you want neither it
|
|
|
|
// nor the close box. How does the Windows "Dialog" window class get just
|
|
|
|
// closebox and no sysmenu? Who knows.
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_resizeh))
|
|
|
|
style &= ~WS_THICKFRAME;
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_minimize))
|
|
|
|
style &= ~WS_MINIMIZEBOX;
|
|
|
|
|
|
|
|
if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_maximize))
|
|
|
|
style &= ~WS_MAXIMIZEBOX;
|
|
|
|
}
|
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)
|
|
|
|
{
|
2009-09-24 02:32:20 -07:00
|
|
|
case eWindowType_plugin:
|
2009-06-29 12:36:16 -07:00
|
|
|
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:
|
2009-08-14 07:09:00 -07:00
|
|
|
NS_ERROR("unknown border style");
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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) {
|
2009-10-05 19:26:54 -07:00
|
|
|
//NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
|
|
|
|
if (!::IsWindow(mWnd)) {
|
|
|
|
NS_ERROR("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) {
|
2009-07-13 08:58:19 -07:00
|
|
|
// If we have no parent, SetParent should return the desktop.
|
|
|
|
VERIFY(::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.
|
2009-07-13 08:58:19 -07:00
|
|
|
if (mInDtor || mOnDestroyCalled)
|
2009-06-29 12:36:16 -07:00
|
|
|
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
|
2009-07-13 08:58:19 -07:00
|
|
|
if (widget->mInDtor) {
|
2009-06-29 12:36:16 -07:00
|
|
|
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
|
2009-07-08 09:13:13 -07:00
|
|
|
case nsSizeMode_Fullscreen:
|
|
|
|
::SetForegroundWindow(mWnd);
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMAXIMIZED);
|
|
|
|
MakeFullScreen(TRUE);
|
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case nsSizeMode_Maximized :
|
|
|
|
::SetForegroundWindow(mWnd);
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMAXIMIZED);
|
|
|
|
break;
|
|
|
|
// use default for nsSizeMode_Minimized on Windows CE
|
|
|
|
#else
|
2009-07-08 09:13:13 -07:00
|
|
|
case nsSizeMode_Fullscreen:
|
|
|
|
::ShowWindow(mWnd, SW_SHOWMAXIMIZED);
|
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
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
|
|
|
/**************************************************************
|
|
|
|
*
|
2009-10-06 09:11:59 -07:00
|
|
|
* SECTION: nsIWidget::Move, nsIWidget::Resize,
|
|
|
|
* nsIWidget::Size, nsIWidget::BeginResizeDrag
|
2009-06-29 12:36:16 -07:00
|
|
|
*
|
|
|
|
* 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-11-02 11:10:07 -08:00
|
|
|
if (mWindowType == eWindowType_toplevel ||
|
|
|
|
mWindowType == eWindowType_dialog) {
|
|
|
|
SetSizeMode(nsSizeMode_Normal);
|
|
|
|
}
|
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
|
2009-07-27 10:27:35 -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) {
|
|
|
|
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
|
2009-07-27 10:27:35 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
|
|
|
if (!aRepaint) {
|
|
|
|
flags |= SWP_NOREDRAW;
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-27 10:27:35 -07:00
|
|
|
ClearThemeRegion();
|
|
|
|
VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, aWidth, GetHeight(aHeight), flags));
|
|
|
|
SetThemeRegion();
|
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) {
|
|
|
|
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
|
|
|
|
#ifndef WINCE
|
|
|
|
if (!aRepaint) {
|
|
|
|
flags |= SWP_NOREDRAW;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-07-27 10:27:35 -07:00
|
|
|
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-10-06 09:11:59 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aEvent);
|
|
|
|
|
|
|
|
if (aEvent->eventStructType != NS_MOUSE_EVENT) {
|
|
|
|
// you can only begin a resize drag with a mouse event
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aEvent);
|
|
|
|
if (mouseEvent->button != nsMouseEvent::eLeftButton) {
|
|
|
|
// you can only begin a resize drag with the left mouse button
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// work out what sizemode we're talking about
|
|
|
|
WPARAM syscommand;
|
|
|
|
if (aVertical < 0) {
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_TOPLEFT;
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_TOP;
|
|
|
|
} else {
|
|
|
|
syscommand = SC_SIZE | WMSZ_TOPRIGHT;
|
|
|
|
}
|
|
|
|
} else if (aVertical == 0) {
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_LEFT;
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
} else {
|
|
|
|
syscommand = SC_SIZE | WMSZ_RIGHT;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_BOTTOMLEFT;
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
syscommand = SC_SIZE | WMSZ_BOTTOM;
|
|
|
|
} else {
|
|
|
|
syscommand = SC_SIZE | WMSZ_BOTTOMRIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// resizing doesn't work if the mouse is already captured
|
|
|
|
CaptureMouse(PR_FALSE);
|
|
|
|
|
|
|
|
// find the top-level window
|
|
|
|
HWND toplevelWnd = GetTopLevelHWND(mWnd, PR_TRUE);
|
|
|
|
|
|
|
|
// tell Windows to start the resize
|
|
|
|
::PostMessage(toplevelWnd, WM_SYSCOMMAND, syscommand,
|
|
|
|
POINTTOPOINTS(aEvent->refPoint));
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
#endif
|
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) {
|
2009-07-08 09:13:13 -07:00
|
|
|
case nsSizeMode_Fullscreen :
|
|
|
|
mode = SW_MAXIMIZE;
|
|
|
|
break;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case nsSizeMode_Maximized :
|
|
|
|
mode = SW_MAXIMIZE;
|
|
|
|
break;
|
2009-11-11 17:11:57 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case nsSizeMode_Minimized :
|
2009-11-11 17:11:57 -08:00
|
|
|
// Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
|
|
|
|
// keeps the window active in the tray. So after the window is minimized,
|
|
|
|
// windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
|
|
|
|
// we will do some additional processing to get the active window set right.
|
|
|
|
// If sTrimOnMinimize is set, we let windows handle minimization normally
|
|
|
|
// using SW_MINIMIZE.
|
2009-06-29 12:36:16 -07:00
|
|
|
mode = sTrimOnMinimize ? SW_MINIMIZE : SW_SHOWMINIMIZED;
|
|
|
|
break;
|
2009-11-11 17:11:57 -08:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
default :
|
|
|
|
mode = SW_RESTORE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
::ShowWindow(mWnd, mode);
|
2009-08-12 07:03:34 -07:00
|
|
|
// we dispatch an activate event here to ensure that the right child window
|
|
|
|
// is focused
|
|
|
|
if (mode == SW_RESTORE || mode == SW_MAXIMIZE)
|
|
|
|
DispatchFocusToTopLevelWindow(NS_ACTIVATE);
|
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
|
|
|
if (mWnd) {
|
2009-11-10 08:24:10 -08:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
|
|
|
if (mWnd == GetTopLevelHWND(mWnd))
|
|
|
|
printf("*** SetFocus: [ top] raise=%d\n", aRaise);
|
|
|
|
else
|
|
|
|
printf("*** SetFocus: [child] raise=%d\n", aRaise);
|
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
// Uniconify, if necessary
|
|
|
|
HWND toplevelWnd = GetTopLevelHWND(mWnd);
|
2009-09-26 19:07:43 -07:00
|
|
|
if (aRaise && ::IsIconic(toplevelWnd)) {
|
2009-06-29 12:36:16 -07:00
|
|
|
::ShowWindow(toplevelWnd, SW_RESTORE);
|
2009-09-26 19:07:43 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
::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
|
|
|
// 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-07-28 11:52:40 -07:00
|
|
|
PRInt32 width;
|
|
|
|
PRInt32 height;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-28 11:52:40 -07:00
|
|
|
nsresult rv;
|
|
|
|
rv = aCursor->GetWidth(&width);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aCursor->GetHeight(&height);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
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-07-28 11:52:40 -07:00
|
|
|
HCURSOR cursor;
|
|
|
|
rv = nsWindowGfx::CreateIcon(aCursor, PR_TRUE, aHotspotX, aHotspotY, &cursor);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
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
|
|
|
/**************************************************************
|
|
|
|
*
|
2009-09-07 14:48:23 -07:00
|
|
|
* SECTION: nsIWidget::Invalidate
|
2009-06-29 12:36:16 -07:00
|
|
|
*
|
2009-09-07 14:48:23 -07:00
|
|
|
* Invalidate an area of the client for painting.
|
2009-06-29 12:36:16 -07:00
|
|
|
*
|
|
|
|
**************************************************************/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-08-20 15:15:01 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
static inline void AddRECTToRegion(const RECT& aRect, nsIRegion* aRegion)
|
|
|
|
{
|
|
|
|
aRegion->Union(aRect.left, aRect.top, aRect.right - aRect.left, aRect.bottom - aRect.top);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
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
|
2009-08-20 15:15:01 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
// We need to keep track of our own invalidated region for Windows CE
|
|
|
|
RECT r;
|
|
|
|
GetClientRect(mWnd, &r);
|
|
|
|
AddRECTToRegion(r, mInvalidatedRegion);
|
|
|
|
#endif
|
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-08-20 15:15:01 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
// We need to keep track of our own invalidated region for Windows CE
|
|
|
|
AddRECTToRegion(rect, mInvalidatedRegion);
|
|
|
|
#endif
|
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-07-08 09:13:13 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::MakeFullScreen(PRBool aFullScreen)
|
|
|
|
{
|
2009-07-09 13:09:28 -07:00
|
|
|
#if WINCE_WINDOWS_MOBILE
|
2009-07-08 09:13:13 -07:00
|
|
|
RECT rc;
|
|
|
|
if (aFullScreen) {
|
|
|
|
SetForegroundWindow(mWnd);
|
|
|
|
SHFullScreen(mWnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON);
|
|
|
|
SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SHFullScreen(mWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON);
|
|
|
|
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE);
|
|
|
|
}
|
|
|
|
MoveWindow(mWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
|
2009-07-09 13:09:28 -07:00
|
|
|
|
|
|
|
if (aFullScreen)
|
|
|
|
mSizeMode = nsSizeMode_Fullscreen;
|
2009-07-08 09:13:13 -07:00
|
|
|
#endif
|
2009-07-09 13:09:28 -07:00
|
|
|
|
|
|
|
return nsBaseWidget::MakeFullScreen(aFullScreen);
|
2009-07-08 09:13:13 -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-07-26 14:19:15 -07:00
|
|
|
static PRBool
|
|
|
|
ClipRegionContainedInRect(const nsTArray<nsIntRect>& aClipRects,
|
|
|
|
const nsIntRect& aRect)
|
|
|
|
{
|
|
|
|
for (PRUint32 i = 0; i < aClipRects.Length(); ++i) {
|
|
|
|
if (!aRect.Contains(aClipRects[i]))
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-09-24 02:37:01 -07:00
|
|
|
// This function determines whether the given window has a descendant that
|
|
|
|
// does not intersect the given aScreenRect. If we encounter a window owned
|
|
|
|
// by another thread (which includes another process, since thread IDs
|
|
|
|
// are unique system-wide), then we give up and conservatively return true.
|
|
|
|
static PRBool
|
|
|
|
HasDescendantWindowOutsideRect(DWORD aThisThreadID, HWND aWnd,
|
|
|
|
const RECT& aScreenRect)
|
|
|
|
{
|
|
|
|
// If the window is owned by another thread, give up now, don't try to
|
|
|
|
// look at its children since they could change asynchronously.
|
|
|
|
// XXX should we try harder here for out-of-process plugins?
|
|
|
|
if (GetWindowThreadProcessId(aWnd, NULL) != aThisThreadID) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
for (HWND child = ::GetWindow(aWnd, GW_CHILD); child;
|
|
|
|
child = ::GetWindow(child, GW_HWNDNEXT)) {
|
|
|
|
RECT childScreenRect;
|
|
|
|
::GetWindowRect(child, &childScreenRect);
|
|
|
|
RECT result;
|
|
|
|
if (!::IntersectRect(&result, &childScreenRect, &aScreenRect)) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HasDescendantWindowOutsideRect(aThisThreadID, child, aScreenRect)) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-12-12 10:50:35 -08:00
|
|
|
static void
|
|
|
|
InvalidateRgnInWindowSubtree(HWND aWnd, HRGN aRgn, HRGN aTmpRgn)
|
|
|
|
{
|
|
|
|
RECT clientRect;
|
|
|
|
::GetClientRect(aWnd, &clientRect);
|
|
|
|
::SetRectRgn(aTmpRgn, clientRect.left, clientRect.top,
|
|
|
|
clientRect.right, clientRect.bottom);
|
|
|
|
if (::CombineRgn(aTmpRgn, aTmpRgn, aRgn, RGN_AND) == NULLREGION) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
::InvalidateRgn(aWnd, aTmpRgn, FALSE);
|
|
|
|
|
|
|
|
for (HWND child = ::GetWindow(aWnd, GW_CHILD); child;
|
|
|
|
child = ::GetWindow(child, GW_HWNDNEXT)) {
|
|
|
|
POINT pt = { 0, 0 };
|
|
|
|
::MapWindowPoints(child, aWnd, &pt, 1);
|
|
|
|
::OffsetRgn(aRgn, -pt.x, -pt.y);
|
|
|
|
InvalidateRgnInWindowSubtree(child, aRgn, aTmpRgn);
|
|
|
|
::OffsetRgn(aRgn, pt.x, pt.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-21 17:45:13 -07:00
|
|
|
void
|
2009-08-13 19:09:51 -07:00
|
|
|
nsWindow::Scroll(const nsIntPoint& aDelta,
|
|
|
|
const nsTArray<nsIntRect>& aDestRects,
|
2009-07-21 17:45:13 -07:00
|
|
|
const nsTArray<Configuration>& aConfigurations)
|
2009-06-29 12:36:16 -07:00
|
|
|
{
|
2009-07-26 14:19:15 -07:00
|
|
|
// We use SW_SCROLLCHILDREN if all the windows that intersect the
|
2009-07-21 17:45:13 -07:00
|
|
|
// affected area are moving by the scroll amount.
|
|
|
|
// First, build the set of widgets that are to be moved by the scroll
|
|
|
|
// amount.
|
|
|
|
// At the same time, set the clip region of all changed windows to the
|
|
|
|
// intersection of the current and new regions.
|
|
|
|
nsTHashtable<nsPtrHashKey<nsWindow> > scrolledWidgets;
|
|
|
|
scrolledWidgets.Init();
|
|
|
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
|
|
|
const Configuration& configuration = aConfigurations[i];
|
|
|
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
|
|
|
NS_ASSERTION(w->GetParent() == this,
|
|
|
|
"Configured widget is not a child");
|
|
|
|
if (configuration.mBounds == w->mBounds + aDelta) {
|
|
|
|
scrolledWidgets.PutEntry(w);
|
|
|
|
}
|
|
|
|
w->SetWindowClipRegion(configuration.mClipRegion, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-09-27 09:38:26 -07:00
|
|
|
|
2009-11-29 20:21:02 -08:00
|
|
|
// Create temporary regions
|
|
|
|
HRGN updateRgn = ::CreateRectRgn(0, 0, 0, 0);
|
|
|
|
if (!updateRgn) {
|
|
|
|
// OOM?
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
HRGN destRgn = ::CreateRectRgn(0, 0, 0, 0);
|
|
|
|
if (!destRgn) {
|
|
|
|
// OOM?
|
|
|
|
::DeleteObject((HGDIOBJ)updateRgn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-24 02:37:01 -07:00
|
|
|
DWORD ourThreadID = GetWindowThreadProcessId(mWnd, NULL);
|
|
|
|
|
2009-12-13 13:01:33 -08:00
|
|
|
for (BlitRectIter iter(aDelta, aDestRects); !iter.IsDone(); ++iter) {
|
|
|
|
const nsIntRect& destRect = iter.Rect();
|
2009-08-13 19:09:51 -07:00
|
|
|
nsIntRect affectedRect;
|
2009-11-29 20:21:02 -08:00
|
|
|
affectedRect.UnionRect(destRect, destRect - aDelta);
|
|
|
|
UINT flags = SW_SCROLLCHILDREN;
|
2009-08-13 19:09:51 -07:00
|
|
|
// Now check if any of our children would be affected by
|
|
|
|
// SW_SCROLLCHILDREN but not supposed to scroll.
|
|
|
|
for (nsWindow* w = static_cast<nsWindow*>(GetFirstChild()); w;
|
|
|
|
w = static_cast<nsWindow*>(w->GetNextSibling())) {
|
|
|
|
if (w->mBounds.Intersects(affectedRect)) {
|
|
|
|
// This child will be affected
|
|
|
|
nsPtrHashKey<nsWindow>* entry = scrolledWidgets.GetEntry(w);
|
|
|
|
if (entry) {
|
|
|
|
// It's supposed to be scrolled, so we can still use
|
|
|
|
// SW_SCROLLCHILDREN. But don't allow SW_SCROLLCHILDREN to be
|
2009-12-13 13:01:33 -08:00
|
|
|
// used on it again by a later rectangle; we don't want it to
|
|
|
|
// move twice!
|
2009-08-13 19:09:51 -07:00
|
|
|
scrolledWidgets.RawRemoveEntry(entry);
|
2009-09-24 02:37:01 -07:00
|
|
|
|
|
|
|
nsIntPoint screenOffset = WidgetToScreenOffset();
|
|
|
|
RECT screenAffectedRect = {
|
|
|
|
screenOffset.x + affectedRect.x,
|
|
|
|
screenOffset.y + affectedRect.y,
|
|
|
|
screenOffset.x + affectedRect.XMost(),
|
|
|
|
screenOffset.y + affectedRect.YMost()
|
|
|
|
};
|
|
|
|
if (HasDescendantWindowOutsideRect(ourThreadID, w->mWnd,
|
|
|
|
screenAffectedRect)) {
|
|
|
|
// SW_SCROLLCHILDREN seems to not move descendant windows
|
|
|
|
// that don't intersect the scrolled rectangle, *even if* the
|
|
|
|
// immediate child window of the scrolled window *does* intersect
|
|
|
|
// the scrolled window. So if w has a descendant window
|
|
|
|
// that would not be moved, SW_SCROLLCHILDREN will hopelessly mess
|
|
|
|
// things up and we must not use it.
|
|
|
|
flags &= ~SW_SCROLLCHILDREN;
|
|
|
|
}
|
2009-08-13 19:09:51 -07:00
|
|
|
} else {
|
|
|
|
flags &= ~SW_SCROLLCHILDREN;
|
|
|
|
// We may have removed some children from scrolledWidgets even
|
|
|
|
// though we decide here to not use SW_SCROLLCHILDREN. That's OK,
|
|
|
|
// it just means that we might not use SW_SCROLLCHILDREN
|
|
|
|
// for a later rectangle when we could have.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-07-21 17:45:13 -07:00
|
|
|
}
|
2007-08-21 01:40:41 -07:00
|
|
|
|
2009-08-13 19:09:51 -07:00
|
|
|
if (flags & SW_SCROLLCHILDREN) {
|
|
|
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
|
|
|
const Configuration& configuration = aConfigurations[i];
|
|
|
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
|
|
|
// Widgets that will be scrolled by SW_SCROLLCHILDREN but which
|
|
|
|
// will be partly visible outside the scroll area after scrolling
|
|
|
|
// must be invalidated, because SW_SCROLLCHILDREN doesn't
|
|
|
|
// update parts of widgets outside the area it scrolled, even
|
|
|
|
// if it moved them.
|
|
|
|
if (w->mBounds.Intersects(affectedRect) &&
|
|
|
|
!ClipRegionContainedInRect(configuration.mClipRegion,
|
|
|
|
affectedRect - (w->mBounds.TopLeft() + aDelta))) {
|
|
|
|
w->Invalidate(PR_FALSE);
|
|
|
|
}
|
2009-07-26 14:19:15 -07:00
|
|
|
}
|
2009-08-06 18:14:37 -07:00
|
|
|
|
|
|
|
// ScrollWindowEx will send WM_MOVE to each moved window to tell it
|
|
|
|
// its new position. Unfortunately those messages don't reach our
|
|
|
|
// WM_MOVE handler for some plugins, so we have to update their
|
|
|
|
// mBounds here. For windows that do receive WM_MOVE, this is OK,
|
|
|
|
// they'll just overwrite mBounds again with the correct value.
|
|
|
|
for (nsWindow* w = static_cast<nsWindow*>(GetFirstChild()); w;
|
|
|
|
w = static_cast<nsWindow*>(w->GetNextSibling())) {
|
|
|
|
if (w->mBounds.Intersects(affectedRect)) {
|
|
|
|
w->mBounds += aDelta;
|
|
|
|
}
|
|
|
|
}
|
2009-07-26 14:19:15 -07:00
|
|
|
}
|
|
|
|
|
2009-08-13 19:09:51 -07:00
|
|
|
RECT clip = { affectedRect.x, affectedRect.y, affectedRect.XMost(), affectedRect.YMost() };
|
2009-11-29 20:21:02 -08:00
|
|
|
::ScrollWindowEx(mWnd, aDelta.x, aDelta.y, &clip, &clip, updateRgn, NULL, flags);
|
|
|
|
|
|
|
|
// Areas that get scrolled into view from offscreen or under another
|
|
|
|
// window (but inside the scroll area) need to be repainted.
|
|
|
|
// ScrollWindowEx returns those areas in updateRgn, but also includes
|
|
|
|
// the area of the source that isn't covered by the destination.
|
|
|
|
// ScrollWindowEx will refuse to blit into an area that's already
|
|
|
|
// invalid. When we're blitting multiple adjacent rectangles, we have
|
|
|
|
// a problem where the source area of rectangle A overlaps the
|
|
|
|
// destination area of a subsequent rectangle B; the first ScrollWindowEx
|
|
|
|
// invalidates the source area of A that's outside of the destination
|
|
|
|
// area of A, and then the ScrollWindowEx for B will refuse to fully
|
|
|
|
// blit into B's destination. This produces nasty temporary glitches.
|
|
|
|
// We combat this by having ScrollWindowEx not invalidate directly,
|
|
|
|
// but give us back the region that needs to be invalidated,
|
|
|
|
// and restricting that region to the destination before invalidating
|
|
|
|
// it.
|
|
|
|
::SetRectRgn(destRgn, destRect.x, destRect.y, destRect.XMost(), destRect.YMost());
|
|
|
|
::CombineRgn(updateRgn, updateRgn, destRgn, RGN_AND);
|
2009-12-12 10:50:35 -08:00
|
|
|
if (flags & SW_SCROLLCHILDREN) {
|
|
|
|
InvalidateRgnInWindowSubtree(mWnd, updateRgn, destRgn);
|
|
|
|
} else {
|
|
|
|
::InvalidateRgn(mWnd, updateRgn, FALSE);
|
|
|
|
}
|
2009-08-13 19:09:51 -07:00
|
|
|
}
|
2009-07-21 17:45:13 -07:00
|
|
|
|
2009-11-29 20:21:02 -08:00
|
|
|
::DeleteObject((HGDIOBJ)updateRgn);
|
|
|
|
::DeleteObject((HGDIOBJ)destRgn);
|
|
|
|
|
2009-07-21 17:45:13 -07:00
|
|
|
// Now make sure all children actually get positioned, sized and clipped
|
|
|
|
// correctly. If SW_SCROLLCHILDREN already moved widgets to their correct
|
|
|
|
// locations, then the SetWindowPos calls this triggers will just be
|
|
|
|
// no-ops.
|
|
|
|
ConfigureChildren(aConfigurations);
|
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:
|
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: 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.
|
2009-07-21 15:53:04 -07:00
|
|
|
if (HIWORD(GetQueueStatus(QS_INPUT)))
|
|
|
|
return PR_TRUE;
|
2009-07-22 16:38:05 -07:00
|
|
|
#ifdef WINCE
|
|
|
|
return PR_FALSE;
|
|
|
|
#else
|
2009-07-21 15:53:04 -07:00
|
|
|
GUITHREADINFO guiInfo;
|
|
|
|
guiInfo.cbSize = sizeof(GUITHREADINFO);
|
|
|
|
if (!GetGUIThreadInfo(GetCurrentThreadId(), &guiInfo))
|
|
|
|
return PR_FALSE;
|
|
|
|
return GUI_INMOVESIZE == (guiInfo.flags & GUI_INMOVESIZE);
|
2009-07-22 16:38:05 -07:00
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
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-07-15 02:54:30 -07:00
|
|
|
/**************************************************************
|
|
|
|
*
|
|
|
|
* SECTION: nsIWidget::OnDefaultButtonLoaded
|
|
|
|
*
|
|
|
|
* Called after the dialog is loaded and it has a default button.
|
|
|
|
*
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::OnDefaultButtonLoaded(const nsIntRect &aButtonRect)
|
|
|
|
{
|
|
|
|
#ifdef WINCE
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
#else
|
|
|
|
if (aButtonRect.IsEmpty())
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// Don't snap when we are not active.
|
|
|
|
HWND activeWnd = ::GetActiveWindow();
|
|
|
|
if (activeWnd != ::GetForegroundWindow() ||
|
|
|
|
GetTopLevelHWND(mWnd, PR_TRUE) != GetTopLevelHWND(activeWnd, PR_TRUE)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool isAlwaysSnapCursor = PR_FALSE;
|
|
|
|
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
|
|
if (prefs) {
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch;
|
|
|
|
prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
|
|
|
|
if (prefBranch) {
|
|
|
|
prefBranch->GetBoolPref("ui.cursor_snapping.always_enabled",
|
|
|
|
&isAlwaysSnapCursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isAlwaysSnapCursor) {
|
|
|
|
BOOL snapDefaultButton;
|
|
|
|
if (!::SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0,
|
|
|
|
&snapDefaultButton, 0) || !snapDefaultButton)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntRect widgetRect;
|
|
|
|
nsresult rv = GetScreenBounds(widgetRect);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsIntRect buttonRect(aButtonRect + widgetRect.TopLeft());
|
|
|
|
|
|
|
|
nsIntPoint centerOfButton(buttonRect.x + buttonRect.width / 2,
|
|
|
|
buttonRect.y + buttonRect.height / 2);
|
|
|
|
// The center of the button can be outside of the widget.
|
|
|
|
// E.g., it could be hidden by scrolling.
|
|
|
|
if (!widgetRect.Contains(centerOfButton)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!::SetCursorPos(centerOfButton.x, centerOfButton.y)) {
|
|
|
|
NS_ERROR("SetCursorPos failed");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-09-24 03:58:04 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsWindow::OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta,
|
|
|
|
PRBool aIsHorizontal,
|
|
|
|
PRInt32 &aOverriddenDelta)
|
|
|
|
{
|
|
|
|
// The default vertical and horizontal scrolling speed is 3, this is defined
|
|
|
|
// on the document of SystemParametersInfo in MSDN.
|
|
|
|
const PRInt32 kSystemDefaultScrollingSpeed = 3;
|
|
|
|
|
|
|
|
// Compute the simple overridden speed.
|
|
|
|
PRInt32 computedOverriddenDelta;
|
|
|
|
nsresult rv =
|
|
|
|
nsBaseWidget::OverrideSystemMouseScrollSpeed(aOriginalDelta, aIsHorizontal,
|
|
|
|
computedOverriddenDelta);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
aOverriddenDelta = aOriginalDelta;
|
|
|
|
|
|
|
|
if (computedOverriddenDelta == aOriginalDelta) {
|
|
|
|
// We don't override now.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we should check whether the user customized the system settings
|
|
|
|
// or not. If the user did it, we should respect the will.
|
|
|
|
UINT systemSpeed;
|
|
|
|
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &systemSpeed, 0)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
// The default vertical scrolling speed is 3, this is defined on the document
|
|
|
|
// of SystemParametersInfo in MSDN.
|
|
|
|
if (systemSpeed != kSystemDefaultScrollingSpeed) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only Vista and later, Windows has the system setting of horizontal
|
|
|
|
// scrolling by the mouse wheel.
|
|
|
|
if (GetWindowsVersion() >= VISTA_VERSION) {
|
|
|
|
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &systemSpeed, 0)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
// The default horizontal scrolling speed is 3, this is defined on the
|
|
|
|
// document of SystemParametersInfo in MSDN.
|
|
|
|
if (systemSpeed != kSystemDefaultScrollingSpeed) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Limit the overridden delta value from the system settings. The mouse
|
|
|
|
// driver might accelerate the scrolling speed already. If so, we shouldn't
|
|
|
|
// override the scrolling speed for preventing the unexpected high speed
|
|
|
|
// scrolling.
|
|
|
|
PRInt32 deltaLimit;
|
|
|
|
rv =
|
|
|
|
nsBaseWidget::OverrideSystemMouseScrollSpeed(kSystemDefaultScrollingSpeed,
|
|
|
|
aIsHorizontal, deltaLimit);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
aOverriddenDelta = PR_MIN(computedOverriddenDelta, deltaLimit);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
/**************************************************************
|
|
|
|
**************************************************************
|
|
|
|
**
|
|
|
|
** 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-08-01 17:30:23 -07:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
event.time = ::GetMessageTime();
|
2009-08-01 17:30:23 -07:00
|
|
|
#else
|
|
|
|
event.time = PR_Now() / 1000;
|
|
|
|
#endif
|
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
|
|
|
// 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-09-16 18:30:26 -07:00
|
|
|
NPEvent pluginEvent;
|
2009-06-29 12:36:16 -07:00
|
|
|
if (aMsg && PluginHasFocus()) {
|
|
|
|
pluginEvent.event = aMsg->message;
|
|
|
|
pluginEvent.wParam = aMsg->wParam;
|
|
|
|
pluginEvent.lParam = aMsg->lParam;
|
2009-11-10 13:55:38 -08:00
|
|
|
event.pluginEvent = (void *)&pluginEvent;
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
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()
|
|
|
|
{
|
2009-11-30 15:14:04 -08:00
|
|
|
if (mPainting) {
|
|
|
|
NS_WARNING("We were asked to dispatch pending events during painting, "
|
|
|
|
"denying since that's unsafe.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-06 11:47:46 -07:00
|
|
|
UpdateLastInputEventTime();
|
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);
|
2009-09-16 18:30:26 -07:00
|
|
|
NPEvent pluginEvent;
|
2009-06-29 12:36:16 -07:00
|
|
|
pluginEvent.event = aMsg.message;
|
|
|
|
pluginEvent.wParam = aMsg.wParam;
|
|
|
|
pluginEvent.lParam = aMsg.lParam;
|
2009-11-10 13:55:38 -08:00
|
|
|
event.pluginEvent = (void *)&pluginEvent;
|
2009-06-29 12:36:16 -07:00
|
|
|
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*
|
2009-08-01 17:30:23 -07:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
LONG curMsgTime = ::GetMessageTime();
|
2009-08-01 17:30:23 -07:00
|
|
|
#else
|
|
|
|
LONG curMsgTime = PR_Now() / 1000;
|
|
|
|
#endif
|
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
|
|
|
|
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-09-16 18:30:26 -07:00
|
|
|
NPEvent pluginEvent;
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
switch (aEventType)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
pluginEvent.event = WM_LBUTTONDOWN;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
pluginEvent.event = WM_MBUTTONDOWN;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
pluginEvent.event = WM_RBUTTONDOWN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
pluginEvent.event = WM_LBUTTONUP;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
pluginEvent.event = WM_MBUTTONUP;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
pluginEvent.event = WM_RBUTTONUP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_DOUBLECLICK:
|
|
|
|
switch (aButton) {
|
|
|
|
case nsMouseEvent::eLeftButton:
|
|
|
|
pluginEvent.event = WM_LBUTTONDBLCLK;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
pluginEvent.event = WM_MBUTTONDBLCLK;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
pluginEvent.event = WM_RBUTTONDBLCLK;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
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-11-10 13:55:38 -08:00
|
|
|
event.pluginEvent = (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) {
|
2009-07-13 08:58:19 -07:00
|
|
|
if ((nsnull != sCurrentWindow) && (!sCurrentWindow->mInDtor)) {
|
2009-06-29 12:36:16 -07:00
|
|
|
LPARAM pos = sCurrentWindow->lParamToClient(lParamToScreen(lParam));
|
|
|
|
sCurrentWindow->DispatchMouseEvent(NS_MOUSE_EXIT, wParam, pos);
|
|
|
|
}
|
|
|
|
sCurrentWindow = this;
|
2009-07-13 08:58:19 -07:00
|
|
|
if (!mInDtor) {
|
2009-06-29 12:36:16 -07:00
|
|
|
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-12-09 08:34:14 -08:00
|
|
|
// retrive the toplevel window or dialog
|
|
|
|
HWND curWnd = mWnd;
|
|
|
|
HWND toplevelWnd = NULL;
|
|
|
|
while (curWnd) {
|
|
|
|
toplevelWnd = curWnd;
|
|
|
|
|
|
|
|
nsWindow *win = GetNSWindowPtr(curWnd);
|
|
|
|
if (win) {
|
|
|
|
nsWindowType wintype;
|
|
|
|
win->GetWindowType(wintype);
|
|
|
|
if (wintype == eWindowType_toplevel || wintype == eWindowType_dialog)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
curWnd = ::GetParent(curWnd); // Parent or owner (if has no parent)
|
|
|
|
}
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
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-09-16 18:30:26 -07:00
|
|
|
NPEvent 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-11-10 13:55:38 -08:00
|
|
|
event.pluginEvent = (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)
|
|
|
|
{
|
2009-11-06 14:33:12 -08:00
|
|
|
#ifdef MOZ_IPC
|
|
|
|
NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
|
|
|
|
"Failed to prevent a nonqueued message from running!");
|
|
|
|
#endif
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
// 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;
|
2009-07-13 08:58:19 -07:00
|
|
|
if (!someWindow->mInDtor) // not if we're in the destructor!
|
2009-06-29 12:36:16 -07:00
|
|
|
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.)
|
2009-08-13 16:04:39 -07:00
|
|
|
if (mWindowHook.Notify(mWnd, msg, wParam, lParam, aRetValue))
|
|
|
|
return PR_TRUE;
|
2009-06-29 12:36:16 -07:00
|
|
|
|
|
|
|
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;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
static PRBool getWheelInfo = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
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;
|
2009-11-05 11:58:21 -08:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-11-05 11:58:21 -08:00
|
|
|
#ifndef WINCE
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_ENDSESSION:
|
2009-11-05 11:58:21 -08:00
|
|
|
#endif
|
|
|
|
case MOZ_WM_APP_QUIT:
|
|
|
|
if (msg == MOZ_WM_APP_QUIT || (wParam == TRUE && sCanQuit == TRI_TRUE))
|
2009-06-29 12:36:16 -07:00
|
|
|
{
|
|
|
|
// Let's fake a shutdown sequence without actually closing windows etc.
|
|
|
|
// to avoid Windows killing us in the middle. A proper shutdown would
|
|
|
|
// require having a chance to pump some messages. Unfortunately
|
|
|
|
// Windows won't let us do that. Bug 212316.
|
|
|
|
nsCOMPtr<nsIObserverService> obsServ =
|
|
|
|
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-11-05 11:58:21 -08:00
|
|
|
#ifndef WINCE
|
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:
|
2009-09-02 17:40:10 -07:00
|
|
|
if (!AutoErase((HDC)wParam)) {
|
2009-06-29 12:36:16 -07:00
|
|
|
*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:
|
|
|
|
{
|
2009-08-27 16:26:43 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
2009-08-19 09:23:30 -07:00
|
|
|
// Reset the kill timer so that we can continue at this
|
|
|
|
// priority
|
|
|
|
SetTimer(mWnd, KILL_PRIORITY_ID, 2000 /* 2seconds */, NULL);
|
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
// Suppress dispatch of pending events
|
|
|
|
// when mouse moves are generated by widget
|
|
|
|
// creation instead of user input.
|
|
|
|
LPARAM lParamScreen = lParamToScreen(lParam);
|
|
|
|
POINT mp;
|
|
|
|
mp.x = GET_X_LPARAM(lParamScreen);
|
|
|
|
mp.y = GET_Y_LPARAM(lParamScreen);
|
|
|
|
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-08-27 13:11:04 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
2009-08-19 09:23:30 -07:00
|
|
|
case WM_TIMER:
|
|
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
|
|
|
|
KillTimer(mWnd, KILL_PRIORITY_ID);
|
|
|
|
break;
|
2009-08-27 13:11:04 -07:00
|
|
|
#endif
|
2009-08-19 09:23:30 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
{
|
2009-08-27 13:11:04 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
2009-08-19 09:23:30 -07:00
|
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
|
|
|
|
SetTimer(mWnd, KILL_PRIORITY_ID, 2000 /* 2 seconds */, NULL);
|
|
|
|
#endif
|
2009-06-29 12:36:16 -07:00
|
|
|
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();
|
2009-08-19 09:23:30 -07:00
|
|
|
|
2009-08-27 13:11:04 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
2009-08-19 09:23:30 -07:00
|
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
|
|
|
|
KillTimer(mWnd, KILL_PRIORITY_ID);
|
|
|
|
#endif
|
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
|
|
|
#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) {
|
2009-08-31 15:19:06 -07:00
|
|
|
result = scrollbar->OnScroll(msg, wParam, lParam);
|
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_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);
|
2009-08-13 13:34:17 -07:00
|
|
|
if (nsWindowCE::sShowSIPButton != TRI_TRUE && WA_INACTIVE != fActive) {
|
|
|
|
HWND hWndSIPB = FindWindowW(L"MS_SIPBUTTON", NULL );
|
|
|
|
if (hWndSIPB)
|
|
|
|
ShowWindow(hWndSIPB, SW_HIDE);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
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-07-08 09:13:13 -07:00
|
|
|
if (mSizeMode == nsSizeMode_Fullscreen)
|
|
|
|
MakeFullScreen(TRUE);
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
|
|
|
}
|
2009-08-26 09:07:15 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
2009-08-31 15:13:24 -07:00
|
|
|
if (!gCheckForHTCApi && gHTCApiNavOpen == nsnull) {
|
|
|
|
gCheckForHTCApi = PR_TRUE;
|
|
|
|
|
|
|
|
HINSTANCE library = LoadLibrary(L"HTCAPI.dll");
|
|
|
|
gHTCApiNavOpen = (HTCApiNavOpen) GetProcAddress(library, "HTCNavOpen");
|
|
|
|
gHTCApiNavSetMode = (HTCApiNavSetMode) GetProcAddress(library ,"HTCNavSetMode");
|
|
|
|
}
|
2009-08-26 09:07:15 -07:00
|
|
|
|
2009-08-31 15:13:24 -07:00
|
|
|
if (gHTCApiNavOpen != nsnull) {
|
2009-08-26 09:07:15 -07:00
|
|
|
gHTCApiNavOpen(mWnd, 1 /* undocumented value */);
|
2009-08-31 15:13:24 -07:00
|
|
|
|
|
|
|
if (gHTCApiNavSetMode != nsnull)
|
|
|
|
gHTCApiNavSetMode ( mWnd, 4);
|
|
|
|
// 4 is Gesture Mode. This will generate WM_HTCNAV events to the window
|
|
|
|
}
|
2009-08-26 09:07:15 -07:00
|
|
|
#endif
|
2009-02-12 18:26:02 -08:00
|
|
|
break;
|
2009-08-26 09:07:15 -07:00
|
|
|
|
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;
|
2009-08-11 10:29:53 -07:00
|
|
|
OnWindowPosChanged(wp, result);
|
2009-08-11 10:45:42 -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:
|
2009-07-08 17:26:30 -07:00
|
|
|
#if !defined (WINCE_WINDOWS_MOBILE)
|
2009-06-29 12:36:16 -07:00
|
|
|
getWheelInfo = PR_TRUE;
|
2009-09-01 11:56:51 -07:00
|
|
|
#else
|
|
|
|
switch (wParam) {
|
|
|
|
case SPI_SIPMOVE:
|
|
|
|
case SPI_SETSIPINFO:
|
|
|
|
case SPI_SETCURRENTIM:
|
|
|
|
nsWindowCE::NotifySoftKbObservers();
|
|
|
|
break;
|
2009-09-02 14:23:24 -07:00
|
|
|
case SETTINGCHANGE_RESET:
|
|
|
|
if (mWindowType == eWindowType_invisible) {
|
|
|
|
// The OS sees to get confused and think that the invisable window
|
|
|
|
// is in the foreground after an orientation change. By actually
|
|
|
|
// setting it to the foreground and hiding it, we set it strait.
|
|
|
|
// See bug 514007 for details.
|
|
|
|
SetForegroundWindow(mWnd);
|
|
|
|
ShowWindow(mWnd, SW_HIDE);
|
|
|
|
}
|
|
|
|
break;
|
2009-09-01 11:56:51 -07:00
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif
|
|
|
|
OnSettingsChange(wParam, lParam);
|
|
|
|
break;
|
2007-08-02 13:55:25 -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
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
case WM_MOUSEHWHEEL:
|
2009-06-30 11:19:15 -07:00
|
|
|
{
|
|
|
|
// If OnMouseWheel returns true, the event was forwarded directly to another
|
|
|
|
// mozilla window message handler (ProcessMessage). In this case the return
|
|
|
|
// value of the forwarded event is in 'result' which we should return immediately.
|
|
|
|
// If OnMouseWheel returns false, OnMouseWheel processed the event internally.
|
|
|
|
// 'result' and 'aRetValue' will be set based on what we did with the event, so
|
|
|
|
// we should fall through.
|
|
|
|
if (OnMouseWheel(msg, wParam, lParam, getWheelInfo, result, aRetValue))
|
|
|
|
return result;
|
|
|
|
}
|
2009-06-29 12:36:16 -07:00
|
|
|
break;
|
2008-04-03 04:55:14 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
#ifndef WINCE
|
2009-09-26 15:42:14 -07:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
2009-06-29 12:36:16 -07:00
|
|
|
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
|
|
|
/* 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;
|
2009-08-13 13:54:09 -07:00
|
|
|
|
|
|
|
case WM_GESTURENOTIFY:
|
|
|
|
{
|
|
|
|
if (mWindowType != eWindowType_invisible &&
|
|
|
|
mWindowType != eWindowType_plugin &&
|
|
|
|
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.
|
|
|
|
GESTURENOTIFYSTRUCT * gestureinfo = (GESTURENOTIFYSTRUCT*)lParam;
|
|
|
|
nsPointWin touchPoint;
|
|
|
|
touchPoint = gestureinfo->ptsLocation;
|
|
|
|
touchPoint.ScreenToClient(mWnd);
|
|
|
|
nsGestureNotifyEvent gestureNotifyEvent(PR_TRUE, NS_GESTURENOTIFY_EVENT_START, this);
|
|
|
|
gestureNotifyEvent.refPoint = touchPoint;
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(&gestureNotifyEvent, status);
|
|
|
|
mDisplayPanFeedback = gestureNotifyEvent.displayPanFeedback;
|
|
|
|
mGesture.SetWinGestureSupport(mWnd, gestureNotifyEvent.panDirection);
|
|
|
|
}
|
|
|
|
result = PR_FALSE; //should always bubble to DefWindowProc
|
|
|
|
}
|
|
|
|
break;
|
2009-06-29 12:36:16 -07:00
|
|
|
#endif // !defined(WINCE)
|
2009-02-15 17:09:11 -08:00
|
|
|
|
2009-08-07 08:11:17 -07:00
|
|
|
case WM_CLEAR:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_DELETE, this);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CUT:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_CUT, this);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COPY:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_COPY, this);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_PASTE:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_PASTE, this);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
#ifndef WINCE
|
|
|
|
case EM_UNDO:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_UNDO, this);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_REDO:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_REDO, this);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_CANPASTE:
|
|
|
|
{
|
|
|
|
// Support EM_CANPASTE message only when wParam isn't specified or
|
|
|
|
// is plain text format.
|
|
|
|
if (wParam == 0 || wParam == CF_TEXT || wParam == CF_UNICODETEXT) {
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_PASTE,
|
|
|
|
this, PR_TRUE);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_CANUNDO:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_UNDO,
|
|
|
|
this, PR_TRUE);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EM_CANREDO:
|
|
|
|
{
|
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_REDO,
|
|
|
|
this, PR_TRUE);
|
|
|
|
DispatchWindowEvent(&command);
|
|
|
|
*aRetValue = (LRESULT)(command.mSucceeded && command.mIsEnabled);
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2009-08-26 09:07:15 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
|
|
|
//HTC NAVIGATION WHEEL EVENT
|
|
|
|
case WM_HTCNAV:
|
|
|
|
{
|
|
|
|
int distance = wParam & 0x000000FF;
|
|
|
|
if ( (wParam & 0x000000100) != 0) // Counter Clockwise
|
|
|
|
distance *= -1;
|
|
|
|
if (OnMouseWheel(WM_MOUSEWHEEL, MAKEWPARAM(0, distance),
|
|
|
|
MAKELPARAM(GetSystemMetrics(SM_CXSCREEN) / 2,
|
|
|
|
GetSystemMetrics(SM_CYSCREEN) / 2),
|
|
|
|
getWheelInfo, result, aRetValue))
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
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;
|
|
|
|
}
|
2009-10-05 19:26:54 -07:00
|
|
|
#endif
|
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
|
|
|
|
if (msg == nsAppShell::GetTaskbarButtonCreatedMessage())
|
|
|
|
SetHasTaskbarIconBeenCreated();
|
2009-06-29 12:36:16 -07:00
|
|
|
#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-10-07 04:14:12 -07:00
|
|
|
nsresult
|
|
|
|
nsWindow::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
|
|
|
|
PRUint32 aNativeMessage,
|
|
|
|
PRUint32 aModifierFlags)
|
|
|
|
{
|
|
|
|
#ifndef WINCE // I don't think WINCE supports SendInput
|
|
|
|
RECT r;
|
|
|
|
::GetWindowRect(mWnd, &r);
|
|
|
|
::SetCursorPos(r.left + aPoint.x, r.top + aPoint.y);
|
|
|
|
|
|
|
|
INPUT input;
|
|
|
|
memset(&input, 0, sizeof(input));
|
|
|
|
|
|
|
|
input.type = INPUT_MOUSE;
|
|
|
|
input.mi.dwFlags = aNativeMessage;
|
|
|
|
::SendInput(1, &input, sizeof(INPUT));
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
#else
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
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-11-11 17:11:57 -08:00
|
|
|
#if !defined(WINCE) // implemented in nsWindowCE.cpp
|
2009-08-11 10:29:53 -07:00
|
|
|
void nsWindow::OnWindowPosChanged(WINDOWPOS *wp, PRBool& result)
|
|
|
|
{
|
|
|
|
if (wp == nsnull)
|
|
|
|
return;
|
|
|
|
|
2009-11-10 08:24:10 -08:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
|
|
|
if (mWnd == GetTopLevelHWND(mWnd))
|
|
|
|
printf("*** OnWindowPosChanged: [ top] ");
|
|
|
|
else
|
|
|
|
printf("*** OnWindowPosChanged: [child] ");
|
|
|
|
printf("WINDOWPOS flags:");
|
|
|
|
if (wp->flags & SWP_FRAMECHANGED)
|
|
|
|
printf("SWP_FRAMECHANGED ");
|
|
|
|
if (wp->flags & SWP_SHOWWINDOW)
|
|
|
|
printf("SWP_SHOWWINDOW ");
|
|
|
|
if (wp->flags & SWP_NOSIZE)
|
|
|
|
printf("SWP_NOSIZE ");
|
|
|
|
if (wp->flags & SWP_HIDEWINDOW)
|
|
|
|
printf("SWP_HIDEWINDOW ");
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Handle window size mode changes
|
|
|
|
if (wp->flags & SWP_FRAMECHANGED) {
|
|
|
|
nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this);
|
|
|
|
|
|
|
|
WINDOWPLACEMENT pl;
|
|
|
|
pl.length = sizeof(pl);
|
|
|
|
::GetWindowPlacement(mWnd, &pl);
|
|
|
|
|
|
|
|
if (pl.showCmd == SW_SHOWMAXIMIZED)
|
|
|
|
event.mSizeMode = nsSizeMode_Maximized;
|
|
|
|
else if (pl.showCmd == SW_SHOWMINIMIZED)
|
|
|
|
event.mSizeMode = nsSizeMode_Minimized;
|
|
|
|
else
|
|
|
|
event.mSizeMode = nsSizeMode_Normal;
|
|
|
|
|
|
|
|
// Windows has just changed the size mode of this window. The following
|
|
|
|
// NS_SIZEMODE event will trigger a call into SetSizeMode where we will
|
|
|
|
// set the min/max window state again or for nsSizeMode_Normal, call
|
|
|
|
// SetWindow with a parameter of SW_RESTORE. There's no need however as
|
|
|
|
// this window's mode has already changed. Updating mSizeMode here
|
|
|
|
// insures the SetSizeMode call is a no-op. Addresses a bug on Win7 related
|
|
|
|
// to window docking. (bug 489258)
|
|
|
|
mSizeMode = event.mSizeMode;
|
|
|
|
|
2009-11-11 17:11:57 -08:00
|
|
|
// If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
|
|
|
|
// SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
|
|
|
|
// prevents the working set from being trimmed but keeps the window active.
|
|
|
|
// After the window is minimized, we need to do some touch up work on the
|
|
|
|
// active window. (bugs 76831 & 499816)
|
|
|
|
if (!sTrimOnMinimize && nsSizeMode_Minimized == event.mSizeMode)
|
|
|
|
ActivateOtherWindowHelper(mWnd);
|
|
|
|
|
2009-11-10 08:24:10 -08:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
|
|
|
switch (mSizeMode) {
|
|
|
|
case nsSizeMode_Normal:
|
|
|
|
printf("*** mSizeMode: nsSizeMode_Normal\n");
|
|
|
|
break;
|
|
|
|
case nsSizeMode_Minimized:
|
|
|
|
printf("*** mSizeMode: nsSizeMode_Minimized\n");
|
|
|
|
break;
|
|
|
|
case nsSizeMode_Maximized:
|
|
|
|
printf("*** mSizeMode: nsSizeMode_Maximized\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("*** mSizeMode: ??????\n");
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
InitEvent(event);
|
|
|
|
|
|
|
|
result = DispatchWindowEvent(&event);
|
|
|
|
|
|
|
|
// Skip window size change events below on minimization.
|
|
|
|
if (mSizeMode == nsSizeMode_Minimized)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle window size changes
|
2009-08-11 10:29:53 -07:00
|
|
|
if (0 == (wp->flags & SWP_NOSIZE)) {
|
|
|
|
RECT r;
|
|
|
|
PRInt32 newWidth, newHeight;
|
2009-11-10 08:24:10 -08:00
|
|
|
|
|
|
|
::GetWindowRect(mWnd, &r);
|
|
|
|
|
|
|
|
newWidth = r.right - r.left;
|
|
|
|
newHeight = r.bottom - r.top;
|
2009-08-11 10:29:53 -07:00
|
|
|
nsIntRect rect(wp->x, wp->y, newWidth, newHeight);
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
ResizeTranslucentWindow(newWidth, newHeight);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (newWidth > mLastSize.width)
|
|
|
|
{
|
|
|
|
RECT drect;
|
|
|
|
|
2009-11-10 08:24:10 -08:00
|
|
|
// getting wider
|
|
|
|
drect.left = wp->x + mLastSize.width;
|
|
|
|
drect.top = wp->y;
|
|
|
|
drect.right = drect.left + (newWidth - mLastSize.width);
|
2009-08-11 10:29:53 -07:00
|
|
|
drect.bottom = drect.top + newHeight;
|
|
|
|
|
|
|
|
::RedrawWindow(mWnd, &drect, NULL,
|
2009-11-10 08:24:10 -08:00
|
|
|
RDW_INVALIDATE |
|
|
|
|
RDW_NOERASE |
|
|
|
|
RDW_NOINTERNALPAINT |
|
|
|
|
RDW_ERASENOW |
|
|
|
|
RDW_ALLCHILDREN);
|
2009-08-11 10:29:53 -07:00
|
|
|
}
|
|
|
|
if (newHeight > mLastSize.height)
|
|
|
|
{
|
|
|
|
RECT drect;
|
|
|
|
|
2009-11-10 08:24:10 -08:00
|
|
|
// getting taller
|
|
|
|
drect.left = wp->x;
|
|
|
|
drect.top = wp->y + mLastSize.height;
|
|
|
|
drect.right = drect.left + newWidth;
|
2009-08-11 10:29:53 -07:00
|
|
|
drect.bottom = drect.top + (newHeight - mLastSize.height);
|
|
|
|
|
|
|
|
::RedrawWindow(mWnd, &drect, NULL,
|
2009-11-10 08:24:10 -08:00
|
|
|
RDW_INVALIDATE |
|
|
|
|
RDW_NOERASE |
|
|
|
|
RDW_NOINTERNALPAINT |
|
|
|
|
RDW_ERASENOW |
|
|
|
|
RDW_ALLCHILDREN);
|
2009-08-11 10:29:53 -07:00
|
|
|
}
|
|
|
|
|
2009-11-10 08:24:10 -08:00
|
|
|
mBounds.width = newWidth;
|
|
|
|
mBounds.height = newHeight;
|
|
|
|
mLastSize.width = newWidth;
|
2009-08-11 10:29:53 -07:00
|
|
|
mLastSize.height = newHeight;
|
|
|
|
|
2009-11-10 08:24:10 -08:00
|
|
|
#ifdef WINSTATE_DEBUG_OUTPUT
|
|
|
|
printf("*** Resize window: %d x %d x %d x %d\n", wp->x, wp->y, newWidth, newHeight);
|
|
|
|
#endif
|
2009-08-11 10:29:53 -07:00
|
|
|
|
2009-11-10 08:24:10 -08:00
|
|
|
// Recalculate the width and height based on the client area for gecko events.
|
2009-08-11 10:29:53 -07:00
|
|
|
if (::GetClientRect(mWnd, &r)) {
|
2009-11-10 08:24:10 -08:00
|
|
|
rect.width = r.right - r.left;
|
|
|
|
rect.height = r.bottom - r.top;
|
2009-08-11 10:29:53 -07:00
|
|
|
}
|
2009-11-10 08:24:10 -08:00
|
|
|
|
|
|
|
// Send a gecko resize event
|
2009-08-11 10:29:53 -07:00
|
|
|
result = OnResize(rect);
|
|
|
|
}
|
|
|
|
}
|
2009-11-11 17:11:57 -08:00
|
|
|
|
|
|
|
// static
|
|
|
|
void nsWindow::ActivateOtherWindowHelper(HWND aWnd)
|
|
|
|
{
|
|
|
|
// Find the next window that is enabled, visible, and not minimized.
|
|
|
|
HWND hwndBelow = ::GetNextWindow(aWnd, GW_HWNDNEXT);
|
|
|
|
while (hwndBelow && (!::IsWindowEnabled(hwndBelow) || !::IsWindowVisible(hwndBelow) ||
|
|
|
|
::IsIconic(hwndBelow))) {
|
|
|
|
hwndBelow = ::GetNextWindow(hwndBelow, GW_HWNDNEXT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Push ourselves to the bottom of the stack, then activate the
|
|
|
|
// next window.
|
|
|
|
::SetWindowPos(aWnd, HWND_BOTTOM, 0, 0, 0, 0,
|
|
|
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
|
|
if (hwndBelow)
|
|
|
|
::SetForegroundWindow(hwndBelow);
|
|
|
|
|
|
|
|
// Play the minimize sound while we're here, since that is also
|
|
|
|
// forgotten when we use SW_SHOWMINIMIZED.
|
|
|
|
::PlaySoundW(L"Minimize", nsnull, SND_ALIAS | SND_NODEFAULT | SND_ASYNC);
|
|
|
|
}
|
2009-11-10 08:24:10 -08:00
|
|
|
#endif // !defined(WINCE)
|
2009-08-11 10:29:53 -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;
|
2009-07-29 23:01:27 -07:00
|
|
|
|
|
|
|
PRInt32 scrollOverflowX = 0;
|
|
|
|
PRInt32 scrollOverflowY = 0;
|
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mGesture.PanDeltaToPixelScrollX(event)) {
|
|
|
|
DispatchEvent(&event, status);
|
2009-07-29 23:01:27 -07:00
|
|
|
scrollOverflowX = event.scrollOverflow;
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2009-07-29 23:01:27 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
if (mGesture.PanDeltaToPixelScrollY(event)) {
|
|
|
|
DispatchEvent(&event, status);
|
2009-07-29 23:01:27 -07:00
|
|
|
scrollOverflowY = event.scrollOverflow;
|
|
|
|
}
|
|
|
|
|
2009-08-13 13:54:09 -07:00
|
|
|
if (mDisplayPanFeedback) {
|
2009-07-29 23:01:27 -07:00
|
|
|
mGesture.UpdatePanFeedbackX(mWnd, scrollOverflowX, endFeedback);
|
|
|
|
mGesture.UpdatePanFeedbackY(mWnd, scrollOverflowY, endFeedback);
|
|
|
|
mGesture.PanFeedbackFinalize(mWnd, endFeedback);
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2009-07-29 23:01:27 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
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).
|
|
|
|
*/
|
|
|
|
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-11-19 15:43:34 -08:00
|
|
|
PRBool quit;
|
|
|
|
if (!HandleScrollingPlugins(msg, wParam, lParam, result, aRetValue, quit))
|
|
|
|
return quit; // return immediately if its not our window
|
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) {
|
2009-09-03 00:07:18 -07:00
|
|
|
scrollEvent.delta = currentVDelta / iDeltaPerLine;
|
2009-06-29 12:36:16 -07:00
|
|
|
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)
|
2009-06-29 23:23:22 -07:00
|
|
|
return PR_FALSE; // break
|
2009-06-29 23:02:07 -07:00
|
|
|
|
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)
|
2009-06-30 11:19:15 -07:00
|
|
|
*aRetValue = isVertical ? 0 : TRUE;
|
2009-06-23 13:57:45 -07:00
|
|
|
|
2009-06-29 12:36:16 -07:00
|
|
|
return PR_FALSE; // break;
|
|
|
|
}
|
2009-08-04 14:28:17 -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-07-17 16:03:54 -07:00
|
|
|
} else {
|
2009-06-29 12:36:16 -07:00
|
|
|
DispatchKeyEvent(NS_KEY_PRESS, 0, nsnull, DOMKeyCode, nsnull, aModKeyState,
|
|
|
|
extraFlags);
|
2009-07-17 16:03:54 -07:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
UINT unichar = ::MapVirtualKey(virtualKeyCode, MAPVK_VK_TO_CHAR);
|
|
|
|
// Check for dead characters or no mapping
|
|
|
|
if (unichar & 0x80) {
|
|
|
|
return noDefault;
|
|
|
|
}
|
|
|
|
DispatchKeyEvent(NS_KEY_PRESS, unichar, nsnull, DOMKeyCode, nsnull, aModKeyState,
|
|
|
|
extraFlags);
|
|
|
|
}
|
|
|
|
#endif
|
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-07-21 17:44:55 -07:00
|
|
|
nsresult
|
|
|
|
nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
|
|
|
{
|
|
|
|
// XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos
|
|
|
|
// here, if that helps in some situations. So far I haven't seen a
|
|
|
|
// need.
|
|
|
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
|
|
|
const Configuration& configuration = aConfigurations[i];
|
|
|
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
|
|
|
NS_ASSERTION(w->GetParent() == this,
|
|
|
|
"Configured widget is not a child");
|
|
|
|
#ifdef WINCE
|
|
|
|
// MSDN says we should do on WinCE this before moving or resizing the window
|
|
|
|
// See http://msdn.microsoft.com/en-us/library/aa930600.aspx
|
|
|
|
// We put the region back just below, anyway.
|
|
|
|
::SetWindowRgn(w->mWnd, NULL, TRUE);
|
|
|
|
#endif
|
2009-07-26 14:19:15 -07:00
|
|
|
nsIntRect bounds;
|
|
|
|
w->GetBounds(bounds);
|
|
|
|
if (bounds.Size() != configuration.mBounds.Size()) {
|
|
|
|
w->Resize(configuration.mBounds.x, configuration.mBounds.y,
|
|
|
|
configuration.mBounds.width, configuration.mBounds.height,
|
|
|
|
PR_TRUE);
|
|
|
|
} else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
|
|
|
|
w->Move(configuration.mBounds.x, configuration.mBounds.y);
|
|
|
|
}
|
2009-07-21 17:44:55 -07:00
|
|
|
nsresult rv = w->SetWindowClipRegion(configuration.mClipRegion, PR_FALSE);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRGN
|
|
|
|
CreateHRGNFromArray(const nsTArray<nsIntRect>& aRects)
|
|
|
|
{
|
|
|
|
PRInt32 size = sizeof(RGNDATAHEADER) + sizeof(RECT)*aRects.Length();
|
|
|
|
nsAutoTArray<PRUint8,100> buf;
|
|
|
|
if (!buf.SetLength(size))
|
|
|
|
return NULL;
|
|
|
|
RGNDATA* data = reinterpret_cast<RGNDATA*>(buf.Elements());
|
|
|
|
RECT* rects = reinterpret_cast<RECT*>(data->Buffer);
|
|
|
|
data->rdh.dwSize = sizeof(data->rdh);
|
|
|
|
data->rdh.iType = RDH_RECTANGLES;
|
|
|
|
data->rdh.nCount = aRects.Length();
|
|
|
|
nsIntRect bounds;
|
|
|
|
for (PRUint32 i = 0; i < aRects.Length(); ++i) {
|
|
|
|
const nsIntRect& r = aRects[i];
|
|
|
|
bounds.UnionRect(bounds, r);
|
|
|
|
::SetRect(&rects[i], r.x, r.y, r.XMost(), r.YMost());
|
|
|
|
}
|
|
|
|
::SetRect(&data->rdh.rcBound, bounds.x, bounds.y, bounds.XMost(), bounds.YMost());
|
|
|
|
return ::ExtCreateRegion(NULL, buf.Length(), data);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
|
|
|
|
PRBool aIntersectWithExisting)
|
|
|
|
{
|
2009-07-26 14:19:15 -07:00
|
|
|
if (!aIntersectWithExisting) {
|
|
|
|
if (!StoreWindowClipRegion(aRects))
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-07-21 17:44:55 -07:00
|
|
|
HRGN dest = CreateHRGNFromArray(aRects);
|
|
|
|
if (!dest)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
if (aIntersectWithExisting) {
|
|
|
|
HRGN current = ::CreateRectRgn(0, 0, 0, 0);
|
|
|
|
if (current) {
|
|
|
|
if (::GetWindowRgn(mWnd, current) != 0 /*ERROR*/) {
|
|
|
|
::CombineRgn(dest, dest, current, RGN_AND);
|
|
|
|
}
|
|
|
|
::DeleteObject(current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!::SetWindowRgn(mWnd, dest, TRUE)) {
|
|
|
|
::DeleteObject(dest);
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-07-13 08:58:19 -07:00
|
|
|
// WM_DESTROY event handler
|
2009-06-29 12:36:16 -07:00
|
|
|
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-07-13 08:58:19 -07:00
|
|
|
// Make sure we don't get destroyed in the process of tearing down.
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
|
|
|
|
|
|
|
// Dispatch the NS_DESTROY event. Must be called before mEventCallback is cleared.
|
|
|
|
if (!mInDtor)
|
|
|
|
DispatchStandardEvent(NS_DESTROY);
|
|
|
|
|
|
|
|
// Prevent the widget from sending additional events.
|
|
|
|
mEventCallback = nsnull;
|
|
|
|
|
|
|
|
// Free our subclass and clear |this| stored in the window props. We will no longer
|
|
|
|
// receive events from Windows after this point.
|
2009-06-29 12:36:16 -07:00
|
|
|
SubclassWindow(FALSE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-13 08:58:19 -07:00
|
|
|
// Once mEventCallback is cleared and the subclass is reset, sCurrentWindow can be
|
|
|
|
// cleared. (It's used in tracking windows for mouse events.)
|
|
|
|
if (sCurrentWindow == this)
|
|
|
|
sCurrentWindow = nsnull;
|
|
|
|
|
|
|
|
// Disconnects us from our parent, will call our GetParent().
|
|
|
|
nsBaseWidget::Destroy();
|
|
|
|
|
|
|
|
// Release references to children, device context, toolkit, and app shell.
|
|
|
|
nsBaseWidget::OnDestroy();
|
|
|
|
|
|
|
|
// Clear our native parent handle.
|
|
|
|
// XXX Windows will take care of this in the proper order, and SetParent(nsnull)'s
|
|
|
|
// remove child on the parent already took place in nsBaseWidget's Destroy call above.
|
|
|
|
//SetParent(nsnull);
|
|
|
|
|
|
|
|
// We have to destroy the native drag target before we null out our window pointer.
|
2009-06-29 12:36:16 -07:00
|
|
|
EnableDragDrop(PR_FALSE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-13 08:58:19 -07:00
|
|
|
// If we're going away and for some reason we're still the rollup widget, rollup and
|
|
|
|
// turn off capture.
|
|
|
|
if ( this == sRollupWidget ) {
|
|
|
|
if ( sRollupListener )
|
|
|
|
sRollupListener->Rollup(nsnull, nsnull);
|
|
|
|
CaptureRollupEvents(nsnull, PR_FALSE, PR_TRUE);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-13 08:58:19 -07:00
|
|
|
// If IME is disabled, restore it.
|
|
|
|
if (mOldIMC) {
|
|
|
|
mOldIMC = ::ImmAssociateContext(mWnd, mOldIMC);
|
|
|
|
NS_ASSERTION(!mOldIMC, "Another IMC was associated");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn off mouse trails if enabled.
|
|
|
|
MouseTrailer* mtrailer = nsToolkit::gMouseTrailer;
|
|
|
|
if (mtrailer) {
|
|
|
|
if (mtrailer->GetMouseTrailerWindow() == mWnd)
|
|
|
|
mtrailer->DestroyTimer();
|
|
|
|
|
|
|
|
if (mtrailer->GetCaptureWindow() == mWnd)
|
|
|
|
mtrailer->SetCaptureWindow(nsnull);
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-13 08:58:19 -07:00
|
|
|
// Free GDI window class objects
|
|
|
|
if (mBrush) {
|
|
|
|
VERIFY(::DeleteObject(mBrush));
|
|
|
|
mBrush = NULL;
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
2009-07-13 08:58:19 -07:00
|
|
|
|
|
|
|
// Free app icon resources.
|
|
|
|
HICON icon;
|
|
|
|
icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM) 0);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
|
|
|
|
|
|
|
icon = (HICON) ::SendMessageW(mWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM) 0);
|
|
|
|
if (icon)
|
|
|
|
::DestroyIcon(icon);
|
|
|
|
|
|
|
|
// Destroy any custom cursor resources.
|
|
|
|
if (mCursor == -1)
|
|
|
|
SetCursor(eCursor_standard);
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
// Reset transparency
|
|
|
|
if (eTransparencyTransparent == mTransparencyMode)
|
|
|
|
SetupTranslucentWindowMemoryBitmap(eTransparencyOpaque);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Clear the main HWND.
|
|
|
|
mWnd = NULL;
|
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-09-17 17:41:43 -07:00
|
|
|
if (mWindowType == eWindowType_dialog ||
|
|
|
|
mWindowType == eWindowType_toplevel )
|
|
|
|
nsWindowGfx::OnSettingsChangeGfx(wParam);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-08-31 15:19:06 -07:00
|
|
|
// Scrolling helper function for handling plugins.
|
|
|
|
// Return value indicates whether the calling function should handle this
|
2009-11-19 15:43:34 -08:00
|
|
|
// aHandled indicates whether this was handled at all
|
|
|
|
// aQuitProcessing tells whether or not to continue processing the message
|
2009-08-31 15:19:06 -07:00
|
|
|
PRBool nsWindow::HandleScrollingPlugins(UINT aMsg, WPARAM aWParam,
|
2009-11-19 15:43:34 -08:00
|
|
|
LPARAM aLParam, PRBool& aHandled,
|
|
|
|
LRESULT* aRetValue,
|
|
|
|
PRBool& aQuitProcessing)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-08-31 15:19:06 -07:00
|
|
|
// The scroll event will be dispatched to the toplevel
|
|
|
|
// window. We need to give it to the child window
|
2009-11-19 15:43:34 -08:00
|
|
|
aQuitProcessing = PR_FALSE; // default is to not stop processing
|
2009-08-31 15:19:06 -07:00
|
|
|
POINT point;
|
2009-09-23 10:13:55 -07:00
|
|
|
DWORD dwPoints = ::GetMessagePos();
|
2009-08-31 15:19:06 -07:00
|
|
|
point.x = GET_X_LPARAM(dwPoints);
|
|
|
|
point.y = GET_Y_LPARAM(dwPoints);
|
2009-09-23 10:13:55 -07:00
|
|
|
|
|
|
|
static PRBool sMayBeUsingLogitechMouse = PR_FALSE;
|
|
|
|
if (aMsg == WM_MOUSEHWHEEL) {
|
|
|
|
// Logitech (Logicool) mouse driver (confirmed with 4.82.11 and MX-1100)
|
|
|
|
// always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs one
|
|
|
|
// message at first time, this time, ::GetMessagePos works fine.
|
|
|
|
// Then, we will return 0 (0 means we process it) to the message. Then, the
|
|
|
|
// driver will POST the same messages continuously during the wheel tilted.
|
|
|
|
// But ::GetMessagePos API always returns (0, 0), even if the actual mouse
|
|
|
|
// cursor isn't 0,0. Therefore, we cannot trust the result of
|
|
|
|
// ::GetMessagePos API if the sender is the driver.
|
|
|
|
if (!sMayBeUsingLogitechMouse && aLParam == 0 && aLParam != dwPoints &&
|
|
|
|
::InSendMessage()) {
|
|
|
|
sMayBeUsingLogitechMouse = PR_TRUE;
|
|
|
|
} else if (sMayBeUsingLogitechMouse && aLParam != 0 && ::InSendMessage()) {
|
|
|
|
// The user has changed the mouse from Logitech's to another one (e.g.,
|
|
|
|
// the user has changed to the touchpad of the notebook.
|
|
|
|
sMayBeUsingLogitechMouse = PR_FALSE;
|
|
|
|
}
|
|
|
|
// If the WM_MOUSEHWHEEL comes from Logitech's mouse driver, and the
|
|
|
|
// ::GetMessagePos isn't correct, probably, we should use ::GetCursorPos
|
|
|
|
// instead.
|
|
|
|
if (sMayBeUsingLogitechMouse && aLParam == 0 && dwPoints == 0) {
|
|
|
|
::GetCursorPos(&point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-31 15:19:06 -07:00
|
|
|
HWND destWnd = ::WindowFromPoint(point);
|
|
|
|
// Since we receive scroll 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.
|
|
|
|
|
|
|
|
if (!destWnd) {
|
|
|
|
// No window is under the pointer
|
2009-11-19 15:43:34 -08:00
|
|
|
return PR_FALSE; // break, but continue processing
|
2009-08-31 15:19:06 -07:00
|
|
|
}
|
|
|
|
// We don't care about windows belonging to other processes.
|
|
|
|
DWORD processId = 0;
|
|
|
|
GetWindowThreadProcessId(destWnd, &processId);
|
|
|
|
if (processId != GetCurrentProcessId())
|
|
|
|
{
|
|
|
|
// Somebody elses window
|
2009-11-19 15:43:34 -08:00
|
|
|
return PR_FALSE; // break, but continue processing
|
2009-08-31 15:19:06 -07:00
|
|
|
}
|
|
|
|
nsWindow* destWindow = GetNSWindowPtr(destWnd);
|
2009-09-24 02:32:20 -07:00
|
|
|
if (!destWindow || destWindow->mWindowType == eWindowType_plugin) {
|
2009-08-31 15:19:06 -07:00
|
|
|
// Some other app, or a plugin window.
|
|
|
|
// Windows directs scrolling messages 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 (mInScrollProcessing) {
|
|
|
|
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,
|
|
|
|
mInScrollProcessing = PR_TRUE;
|
|
|
|
if (0 == ::SendMessageW(destWnd, aMsg, aWParam, aLParam))
|
|
|
|
aHandled = PR_TRUE;
|
|
|
|
destWnd = nsnull;
|
|
|
|
mInScrollProcessing = PR_FALSE;
|
|
|
|
}
|
2009-11-19 15:43:34 -08:00
|
|
|
return PR_FALSE; // break, but continue processing
|
2009-08-31 15:19:06 -07:00
|
|
|
}
|
|
|
|
parentWnd = ::GetParent(parentWnd);
|
|
|
|
} // while parentWnd
|
|
|
|
}
|
|
|
|
if (destWnd == nsnull)
|
|
|
|
return PR_FALSE;
|
|
|
|
if (destWnd != mWnd) {
|
|
|
|
if (destWindow) {
|
2009-11-19 15:43:34 -08:00
|
|
|
aHandled = destWindow->ProcessMessage(aMsg, aWParam, aLParam, aRetValue);
|
|
|
|
aQuitProcessing = PR_TRUE;
|
|
|
|
return PR_FALSE; // break, and stop processing
|
2009-08-31 15:19:06 -07:00
|
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
else
|
|
|
|
printf("WARNING: couldn't get child window for SCROLL event\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return PR_TRUE; // caller should handle this
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsWindow::OnScroll(UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
|
|
|
{
|
|
|
|
if (aLParam)
|
|
|
|
{
|
|
|
|
// Scroll message generated by Thinkpad Trackpoint Driver or similar
|
|
|
|
// Treat as a mousewheel message and scroll appropriately
|
2009-11-19 15:43:34 -08:00
|
|
|
PRBool quit, result;
|
|
|
|
LRESULT retVal;
|
2009-08-31 15:19:06 -07:00
|
|
|
|
2009-11-19 15:43:34 -08:00
|
|
|
if (!HandleScrollingPlugins(aMsg, aWParam, aLParam, result, &retVal, quit))
|
|
|
|
return quit; // Return if it's not our message or has been dispatched
|
2009-08-31 15:19:06 -07:00
|
|
|
|
|
|
|
nsMouseScrollEvent scrollevent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
|
|
|
scrollevent.scrollFlags = (aMsg == WM_VSCROLL)
|
|
|
|
? nsMouseScrollEvent::kIsVertical
|
|
|
|
: nsMouseScrollEvent::kIsHorizontal;
|
|
|
|
switch (LOWORD(aWParam))
|
|
|
|
{
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
scrollevent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
scrollevent.delta = 1;
|
|
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
|
|
scrollevent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
|
|
|
case SB_LINEUP:
|
|
|
|
scrollevent.delta = -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
DispatchWindowEvent(&scrollevent);
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
// Scroll message generated by external application
|
|
|
|
// XXX Handle by scrolling the window in the desired manner (Bug 315727)
|
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-09-02 17:40:10 -07:00
|
|
|
// Can be overriden. Controls auto-erase of background.
|
|
|
|
PRBool nsWindow::AutoErase(HDC dc)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-02 19:01:05 -07:00
|
|
|
#ifdef WINCE_WINDOWS_MOBILE
|
2009-09-02 17:40:10 -07:00
|
|
|
RECT wrect;
|
|
|
|
GetClipBox(dc, &wrect);
|
|
|
|
AddRECTToRegion(wrect, mInvalidatedRegion);
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
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)
|
2009-10-04 18:45:43 -07:00
|
|
|
rv = NS_ERROR_NOT_IMPLEMENTED; // TSF is not enabled, maybe.
|
2009-05-04 23:15:23 -07:00
|
|
|
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-07-13 08:58:19 -07:00
|
|
|
if (mInDtor || mOnDestroyCalled || mWindowType == eWindowType_invisible) {
|
2009-06-29 12:36:16 -07:00
|
|
|
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);
|
2009-09-26 15:42:14 -07:00
|
|
|
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
|
|
|
MARGINS margins = { 0, 0, 0, 0 };
|
|
|
|
DWMNCRENDERINGPOLICY policy = DWMNCRP_USEWINDOWSTYLE;
|
|
|
|
if(eTransparencyGlass == aMode) {
|
|
|
|
margins.cxLeftWidth = -1;
|
|
|
|
policy = DWMNCRP_ENABLED;
|
|
|
|
}
|
|
|
|
if(nsUXThemeData::sHaveCompositor) {
|
2009-06-29 12:36:16 -07:00
|
|
|
nsUXThemeData::dwmExtendFrameIntoClientAreaPtr(hWnd, &margins);
|
2009-09-26 15:42:14 -07:00
|
|
|
nsUXThemeData::dwmSetWindowAttributePtr(hWnd, DWMWA_NCRENDERING_POLICY, &policy, sizeof policy);
|
|
|
|
}
|
|
|
|
#endif // #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
|
|
|
#endif // #ifndef WINCE
|
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.
|
2009-09-24 02:32:20 -07:00
|
|
|
if (static_cast<nsWindow*>(mozWin)->mWindowType == eWindowType_plugin)
|
2008-11-26 21:42:18 -08:00
|
|
|
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;
|
2009-07-08 16:34:03 -07:00
|
|
|
HWND upWnd = 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-07-08 16:34:03 -07:00
|
|
|
upWnd = ::GetParent(curWnd); // Parent or owner (if has no parent)
|
|
|
|
|
|
|
|
#ifdef WINCE
|
|
|
|
// For dialog windows, we want just the parent, not the owner.
|
|
|
|
// For other/popup windows, we want to find the first owner/parent
|
|
|
|
// that's a dialog and/or has an owner.
|
|
|
|
if (upWnd && ::GetWindow(curWnd, GW_OWNER) == upWnd) {
|
|
|
|
DWORD_PTR style = ::GetWindowLongPtrW(curWnd, GWL_STYLE);
|
|
|
|
if ((style & WS_DLGFRAME) != 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
curWnd = upWnd;
|
2009-06-29 12:36:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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-10-06 21:19:04 -07:00
|
|
|
#if !defined(WINCE)
|
|
|
|
void nsWindow::InitTrackPointHack()
|
|
|
|
{
|
|
|
|
// Init Trackpoint Hack
|
|
|
|
nsresult rv;
|
|
|
|
PRInt32 lHackValue;
|
|
|
|
long lResult;
|
|
|
|
const WCHAR wstrKeys[][40] = {L"Software\\Lenovo\\TrackPoint",
|
2009-10-10 13:21:12 -07:00
|
|
|
L"Software\\Lenovo\\UltraNav",
|
2009-11-14 09:24:02 -08:00
|
|
|
L"Software\\Alps\\Apoint\\TrackPoint",
|
2009-10-10 13:21:12 -07:00
|
|
|
L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2"};
|
2009-10-06 21:19:04 -07:00
|
|
|
// If anything fails turn the hack off
|
|
|
|
sTrackPointHack = false;
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
|
|
|
if(NS_SUCCEEDED(rv) && prefs) {
|
|
|
|
prefs->GetIntPref("ui.trackpoint_hack.enabled", &lHackValue);
|
|
|
|
switch (lHackValue) {
|
|
|
|
// 0 means hack disabled
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
// 1 means hack enabled
|
|
|
|
case 1:
|
|
|
|
sTrackPointHack = true;
|
|
|
|
break;
|
|
|
|
// -1 means autodetect
|
|
|
|
case -1:
|
2009-10-10 13:21:12 -07:00
|
|
|
for(int i = 0; i < NS_ARRAY_LENGTH(wstrKeys); i++) {
|
2009-10-06 21:19:04 -07:00
|
|
|
HKEY hKey;
|
|
|
|
lResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, (LPCWSTR)&wstrKeys[i],
|
|
|
|
0, KEY_READ, &hKey);
|
|
|
|
::RegCloseKey(hKey);
|
|
|
|
if(lResult == ERROR_SUCCESS) {
|
|
|
|
// If we detected a registry key belonging to a TrackPoint driver
|
|
|
|
// Turn on the hack
|
|
|
|
sTrackPointHack = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// Shouldn't be any other values, but treat them as disabled
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif // #if !defined(WINCE)
|
|
|
|
|
2009-07-27 10:27:35 -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);
|
|
|
|
}
|
|
|
|
|
|
|
|
LPARAM nsWindow::lParamToClient(LPARAM lParam)
|
|
|
|
{
|
|
|
|
POINT pt;
|
|
|
|
pt.x = GET_X_LPARAM(lParam);
|
|
|
|
pt.y = GET_Y_LPARAM(lParam);
|
|
|
|
::ScreenToClient(mWnd, &pt);
|
|
|
|
return MAKELPARAM(pt.x, pt.y);
|
|
|
|
}
|
|
|
|
|
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;
|
2009-08-01 17:30:23 -07:00
|
|
|
}
|