mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
338153 Frontport bug 332579 to trunk, consolidating the native event improvements made on the 1.8 branch (332579) and trunk (326273). r=josh sr=darin
This commit is contained in:
parent
0277af7788
commit
a46bfe2646
@ -70,11 +70,5 @@ EXPORTS = \
|
||||
nsThemeConstants.h \
|
||||
$(NULL)
|
||||
|
||||
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
||||
EXPORTS += \
|
||||
nsRepeater.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -1,82 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 ***** */
|
||||
|
||||
#ifndef nsRepeater_h___
|
||||
#define nsRepeater_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "widgetCore.h"
|
||||
|
||||
class EventRecord;
|
||||
|
||||
class NS_WIDGET Repeater
|
||||
{
|
||||
public:
|
||||
|
||||
Repeater();
|
||||
virtual ~Repeater();
|
||||
|
||||
virtual void RepeatAction(const EventRecord &aMacEvent) {}
|
||||
virtual void IdleAction(const EventRecord &aMacEvent) {}
|
||||
|
||||
void StartRepeating();
|
||||
void StopRepeating();
|
||||
void StartIdling();
|
||||
void StopIdling();
|
||||
|
||||
static void DoRepeaters(const EventRecord &aMacEvent);
|
||||
static void DoIdlers(const EventRecord &aMacEvent);
|
||||
|
||||
protected:
|
||||
|
||||
void AddToRepeatList();
|
||||
void RemoveFromRepeatList();
|
||||
void AddToIdleList();
|
||||
void RemoveFromIdleList();
|
||||
|
||||
static Repeater* sRepeaters;
|
||||
static Repeater* sIdlers;
|
||||
|
||||
bool mRepeating;
|
||||
bool mIdling;
|
||||
Repeater* mPrevRptr;
|
||||
Repeater* mNextRptr;
|
||||
Repeater* mPrevIdlr;
|
||||
Repeater* mNextIdlr;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,172 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 ***** */
|
||||
|
||||
|
||||
/* to build this, build mozilla/widget/macbuild/_WidgetSupport.mcp
|
||||
* I hope I'm the last person to waste 30 minutes looking for the project that builds this file */
|
||||
#pragma export on
|
||||
|
||||
#include "nsRepeater.h"
|
||||
|
||||
Repeater* Repeater::sRepeaters = NULL;
|
||||
Repeater* Repeater::sIdlers = NULL;
|
||||
|
||||
Repeater::Repeater()
|
||||
: mRepeating(false)
|
||||
, mIdling(false)
|
||||
, mPrevRptr(NULL)
|
||||
, mNextRptr(NULL)
|
||||
, mPrevIdlr(NULL)
|
||||
, mNextIdlr(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Repeater::~Repeater()
|
||||
{
|
||||
if (mRepeating) RemoveFromRepeatList();
|
||||
if (mIdling) RemoveFromIdleList();
|
||||
}
|
||||
|
||||
// protected helper functs
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Repeater::AddToRepeatList()
|
||||
{
|
||||
if (sRepeaters)
|
||||
{
|
||||
sRepeaters->mPrevRptr = this;
|
||||
mNextRptr = sRepeaters;
|
||||
}
|
||||
sRepeaters = this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Repeater::RemoveFromRepeatList()
|
||||
{
|
||||
if (sRepeaters == this) sRepeaters = mNextRptr;
|
||||
if (mPrevRptr) mPrevRptr->mNextRptr = mNextRptr;
|
||||
if (mNextRptr) mNextRptr->mPrevRptr = mPrevRptr;
|
||||
mPrevRptr = NULL;
|
||||
mNextRptr = NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Repeater::AddToIdleList()
|
||||
{
|
||||
if (sIdlers)
|
||||
{
|
||||
sIdlers->mPrevIdlr = this;
|
||||
mNextIdlr = sIdlers;
|
||||
}
|
||||
sIdlers = this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Repeater::RemoveFromIdleList()
|
||||
{
|
||||
if (sIdlers == this) sIdlers = mNextIdlr;
|
||||
if (mPrevIdlr) mPrevIdlr->mNextIdlr = mNextIdlr;
|
||||
if (mNextIdlr) mNextIdlr->mPrevIdlr = mPrevIdlr;
|
||||
mPrevIdlr = NULL;
|
||||
mNextIdlr = NULL;
|
||||
}
|
||||
|
||||
// repeater methods
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Repeater::StartRepeating()
|
||||
{
|
||||
if (!mRepeating)
|
||||
{
|
||||
AddToRepeatList();
|
||||
mRepeating = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Repeater::StopRepeating()
|
||||
{
|
||||
if (mRepeating)
|
||||
{
|
||||
RemoveFromRepeatList();
|
||||
mRepeating = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Repeater::DoRepeaters(const EventRecord &aMacEvent)
|
||||
{
|
||||
Repeater* theRepeater = sRepeaters;
|
||||
while (theRepeater)
|
||||
{
|
||||
Repeater* nextRepeater = theRepeater->mNextRptr;
|
||||
theRepeater->RepeatAction(aMacEvent);
|
||||
theRepeater = nextRepeater;
|
||||
}
|
||||
}
|
||||
|
||||
// idler methods
|
||||
|
||||
void Repeater::StartIdling()
|
||||
{
|
||||
if (!mIdling)
|
||||
{
|
||||
AddToIdleList();
|
||||
mIdling = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Repeater::StopIdling()
|
||||
{
|
||||
if (mIdling)
|
||||
{
|
||||
RemoveFromIdleList();
|
||||
mIdling = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Repeater::DoIdlers(const EventRecord &aMacEvent)
|
||||
{
|
||||
Repeater* theIdler = sIdlers;
|
||||
while (theIdler)
|
||||
{
|
||||
Repeater* nextIdler = theIdler->mNextIdlr;
|
||||
theIdler->IdleAction(aMacEvent);
|
||||
theIdler = nextIdler;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma export off
|
@ -83,10 +83,6 @@ REQUIRES += glitz glitzagl
|
||||
endif
|
||||
endif
|
||||
|
||||
GFX_LCPPSRCS = \
|
||||
nsRepeater.cpp \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsAppShell.cpp \
|
||||
nsBidiKeyboard.cpp \
|
||||
nsChildWindow.cpp \
|
||||
@ -123,7 +119,6 @@ CPPSRCS = nsAppShell.cpp \
|
||||
nsPrintOptionsX.cpp \
|
||||
nsPrintSettingsX.cpp \
|
||||
nsPrintSessionX.cpp \
|
||||
$(GFX_LCPPSRCS) \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS += \
|
||||
@ -148,16 +143,11 @@ ifdef MOZ_ENABLE_CAIRO_GFX
|
||||
EXTRA_DSO_LDOPTS += -lthebes
|
||||
endif
|
||||
|
||||
GARBAGE += $(GFX_LCPPSRCS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
RESOURCE = libwidget.rsrc
|
||||
RES_SRC = $(srcdir)/nsMacWidget.r
|
||||
|
||||
export:: $(addprefix $(topsrcdir)/gfx/src/mac/,$(GFX_LCPPSRCS))
|
||||
$(INSTALL) $^ .
|
||||
|
||||
$(RESOURCE): $(RES_SRC)
|
||||
/Developer/Tools/Rez -i /Developer/Headers/FlatCarbon -useDF $< -o $@
|
||||
|
||||
|
@ -47,36 +47,12 @@
|
||||
#include "nsToolkit.h"
|
||||
#include "nsMacMessagePump.h"
|
||||
|
||||
// kWNETransitionEventList
|
||||
//
|
||||
// This list encompasses all Carbon events that can be converted into
|
||||
// EventRecords. Not all will necessarily be called; not all will necessarily
|
||||
// be handled. Some items here may be redundant in that handlers are already
|
||||
// installed elsewhere. This may need a good audit.
|
||||
//
|
||||
static const EventTypeSpec kWNETransitionEventList[] = {
|
||||
{ kEventClassMouse, kEventMouseDown },
|
||||
{ kEventClassMouse, kEventMouseUp },
|
||||
{ kEventClassMouse, kEventMouseMoved },
|
||||
{ kEventClassMouse, kEventMouseDragged },
|
||||
{ kEventClassKeyboard, kEventRawKeyDown },
|
||||
{ kEventClassKeyboard, kEventRawKeyUp },
|
||||
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
||||
{ kEventClassWindow, kEventWindowUpdate },
|
||||
{ kEventClassWindow, kEventWindowActivated },
|
||||
{ kEventClassWindow, kEventWindowDeactivated },
|
||||
{ kEventClassWindow, kEventWindowCursorChange },
|
||||
{ kEventClassApplication, kEventAppActivated },
|
||||
{ kEventClassApplication, kEventAppDeactivated },
|
||||
{ kEventClassAppleEvent, kEventAppleEvent },
|
||||
{ kEventClassControl, kEventControlTrack },
|
||||
};
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
// nsAppShell implementation
|
||||
|
||||
nsAppShell::nsAppShell()
|
||||
: mWNETransitionEventHandler(NULL)
|
||||
, mCFRunLoop(NULL)
|
||||
: mCFRunLoop(NULL)
|
||||
, mCFRunLoopSource(NULL)
|
||||
, mRunningEventLoop(PR_FALSE)
|
||||
{
|
||||
@ -92,9 +68,6 @@ nsAppShell::~nsAppShell()
|
||||
|
||||
if (mCFRunLoop)
|
||||
::CFRelease(mCFRunLoop);
|
||||
|
||||
if (mWNETransitionEventHandler)
|
||||
::RemoveEventHandler(mWNETransitionEventHandler);
|
||||
}
|
||||
|
||||
// Init
|
||||
@ -114,18 +87,10 @@ nsAppShell::Init()
|
||||
return rv;
|
||||
|
||||
nsIToolkit *toolkit = mToolkit.get();
|
||||
mMacPump = new nsMacMessagePump(static_cast<nsToolkit*>(toolkit));
|
||||
if (!mMacPump.get() || !nsMacMemoryCushion::EnsureMemoryCushion())
|
||||
mMacPump = new nsMacMessagePump(NS_STATIC_CAST(nsToolkit*, toolkit));
|
||||
if (!mMacPump.get())
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
OSStatus err = ::InstallApplicationEventHandler(
|
||||
::NewEventHandlerUPP(WNETransitionEventHandler),
|
||||
GetEventTypeCount(kWNETransitionEventList),
|
||||
kWNETransitionEventList,
|
||||
(void*)this,
|
||||
&mWNETransitionEventHandler);
|
||||
NS_ENSURE_TRUE(err == noErr, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Add a CFRunLoopSource to the main native run loop. The source is
|
||||
// responsible for interrupting the run loop when Gecko events are ready.
|
||||
|
||||
@ -227,29 +192,3 @@ nsAppShell::ProcessGeckoEvents(void* aInfo)
|
||||
|
||||
NS_RELEASE(self);
|
||||
}
|
||||
|
||||
// WNETransitionEventHandler
|
||||
//
|
||||
// Transitional WaitNextEvent handler. Accepts Carbon events from
|
||||
// kWNETransitionEventList, converts them into EventRecords, and
|
||||
// dispatches them through the path they would have gone if they
|
||||
// had been received as EventRecords from WaitNextEvent.
|
||||
//
|
||||
// protected static
|
||||
pascal OSStatus
|
||||
nsAppShell::WNETransitionEventHandler(EventHandlerCallRef aHandlerCallRef,
|
||||
EventRef aEvent,
|
||||
void* aUserData)
|
||||
{
|
||||
nsAppShell* self = NS_STATIC_CAST(nsAppShell*, aUserData);
|
||||
|
||||
EventRecord eventRecord;
|
||||
::ConvertEventRefToEventRecord(aEvent, &eventRecord);
|
||||
|
||||
PRBool handled = self->mMacPump->DispatchEvent(PR_TRUE, &eventRecord);
|
||||
|
||||
if (handled)
|
||||
return noErr;
|
||||
|
||||
return eventNotHandledErr;
|
||||
}
|
||||
|
@ -45,7 +45,6 @@
|
||||
#ifndef nsAppShell_h__
|
||||
#define nsAppShell_h__
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include "nsBaseAppShell.h"
|
||||
@ -69,17 +68,11 @@ protected:
|
||||
virtual PRBool ProcessNextNativeEvent(PRBool aMayWait);
|
||||
|
||||
static void ProcessGeckoEvents(void* aInfo);
|
||||
static pascal OSStatus WNETransitionEventHandler(
|
||||
EventHandlerCallRef aHandlerCallRef,
|
||||
EventRef aEvent,
|
||||
void* aUserData);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIToolkit> mToolkit;
|
||||
nsAutoPtr<nsMacMessagePump> mMacPump;
|
||||
|
||||
EventHandlerRef mWNETransitionEventHandler;
|
||||
|
||||
CFRunLoopRef mCFRunLoop;
|
||||
CFRunLoopSourceRef mCFRunLoopSource;
|
||||
|
||||
|
@ -92,6 +92,20 @@ nsMacEventDispatchHandler gEventDispatchHandler;
|
||||
static void ConvertKeyEventToContextMenuEvent(const nsKeyEvent* inKeyEvent, nsMouseEvent* outCMEvent);
|
||||
static inline PRBool IsContextMenuKey(const nsKeyEvent& inKeyEvent);
|
||||
|
||||
class StPackedBoolSetter {
|
||||
public:
|
||||
StPackedBoolSetter(PRPackedBool& aFlag): mFlag(aFlag) {
|
||||
mFlag = PR_TRUE;
|
||||
};
|
||||
|
||||
~StPackedBoolSetter() {
|
||||
mFlag = PR_FALSE;
|
||||
};
|
||||
|
||||
protected:
|
||||
PRPackedBool& mFlag;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
@ -379,6 +393,7 @@ nsMacEventHandler::nsMacEventHandler(nsMacWindow* aTopLevelWidget)
|
||||
mIMEIsComposing = PR_FALSE;
|
||||
mIMECompositionStr = nsnull;
|
||||
|
||||
mHandlingKeyEvent = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -1030,6 +1045,12 @@ PRUint32 nsMacEventHandler::ConvertKeyEventToUnicode(EventRecord& aOSEvent)
|
||||
|
||||
PRBool nsMacEventHandler::HandleKeyEvent(EventRecord& aOSEvent)
|
||||
{
|
||||
// Avoid reentrancy
|
||||
if (mHandlingKeyEvent)
|
||||
return PR_FALSE;
|
||||
|
||||
StPackedBoolSetter handling(mHandlingKeyEvent);
|
||||
|
||||
nsresult result = NS_ERROR_UNEXPECTED;
|
||||
nsWindow* checkFocusedWidget;
|
||||
|
||||
@ -1145,6 +1166,12 @@ IsContextMenuKey(const nsKeyEvent& inKeyEvent)
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsMacEventHandler::HandleUKeyEvent(const PRUnichar* text, long charCount, EventRecord& aOSEvent)
|
||||
{
|
||||
// Avoid reentrancy
|
||||
if (mHandlingKeyEvent)
|
||||
return PR_FALSE;
|
||||
|
||||
StPackedBoolSetter handling(mHandlingKeyEvent);
|
||||
|
||||
nsresult result = NS_ERROR_UNEXPECTED;
|
||||
// get the focused widget
|
||||
nsWindow* focusedWidget = gEventDispatchHandler.GetActive();
|
||||
|
@ -170,8 +170,9 @@ protected:
|
||||
RgnHandle mUpdateRgn;
|
||||
TSMDocumentID mTSMDocument;
|
||||
nsPoint mIMEPos;
|
||||
PRBool mIMEIsComposing;
|
||||
nsAutoString *mIMECompositionStr;
|
||||
PRPackedBool mIMEIsComposing;
|
||||
PRPackedBool mHandlingKeyEvent;
|
||||
};
|
||||
|
||||
#endif // MacMacEventHandler_h__
|
||||
|
@ -20,6 +20,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Mentovai <mark@moxienet.com>
|
||||
*
|
||||
* 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
|
||||
@ -35,454 +36,188 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//
|
||||
// nsMacMessagePump
|
||||
//
|
||||
// This file contains the default implementation for the mac event loop. Events that
|
||||
// pertain to the layout engine are routed there via a MessageSink that is passed in
|
||||
// at creation time. Events not destined for layout are handled here (such as window
|
||||
// moved).
|
||||
//
|
||||
// Clients may either use this implementation or write their own. Embedding applications
|
||||
// will almost certainly write their own because they will want control of the event
|
||||
// loop to do other processing. There is nothing in the architecture which forces the
|
||||
// embedding app to use anything called a "message pump" so the event loop can actually
|
||||
// live anywhere the app wants.
|
||||
//
|
||||
/*
|
||||
* Dispatcher for a variety of application-scope events. The real event loop
|
||||
* is in nsAppShell.
|
||||
*/
|
||||
|
||||
#include "nsMacMessagePump.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsToolkit.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "nsRepeater.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "prthread.h"
|
||||
#include "nsMacTSMMessagePump.h"
|
||||
#include "nsIRollupListener.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsGfxUtils.h"
|
||||
#include "nsMacWindow.h"
|
||||
|
||||
#include <MacWindows.h>
|
||||
#include <ToolUtils.h>
|
||||
#ifndef XP_MACOSX
|
||||
#include <DiskInit.h>
|
||||
#endif
|
||||
#include <Devices.h>
|
||||
#include <LowMem.h>
|
||||
#include <Sound.h>
|
||||
#include <Quickdraw.h>
|
||||
#include "nsCarbonHelpers.h"
|
||||
|
||||
#include "nsIEventSink.h"
|
||||
#include "nsIRollupListener.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsPIWidgetMac.h"
|
||||
#include "nsPIEventSinkStandalone.h"
|
||||
|
||||
//#include "nsISocketTransportService.h"
|
||||
//include "nsIFileTransportService.h"
|
||||
#include "nsGfxUtils.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsMacTSMMessagePump.h"
|
||||
#include "nsToolkit.h"
|
||||
|
||||
#if !XP_MACOSX
|
||||
#include "MenuSharing.h"
|
||||
#endif
|
||||
|
||||
#ifndef topLeft
|
||||
#define topLeft(r) (((Point *) &(r))[0])
|
||||
#endif
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#ifndef botRight
|
||||
#define botRight(r) (((Point *) &(r))[1])
|
||||
#endif
|
||||
|
||||
#if DEBUG && !defined(XP_MACOSX)
|
||||
#include <SIOUX.h>
|
||||
#include "macstdlibextras.h"
|
||||
#endif
|
||||
|
||||
#define DRAW_ON_RESIZE 0 // if 1, enable live-resize except when the command key is down
|
||||
|
||||
const short kMinWindowWidth = 125;
|
||||
const short kMinWindowHeight = 150;
|
||||
|
||||
extern nsIRollupListener * gRollupListener;
|
||||
extern nsIWidget * gRollupWidget;
|
||||
|
||||
|
||||
|
||||
//======================================================================================
|
||||
// PROFILE
|
||||
//======================================================================================
|
||||
#ifdef DEBUG
|
||||
|
||||
// Important Notes:
|
||||
// ----------------
|
||||
//
|
||||
// - To turn the profiler on, define "#pragma profile on" in IDE_Options.h
|
||||
// then set $PROFILE to 1 in BuildNGLayoutDebug.pl and recompile everything.
|
||||
//
|
||||
// - You may need to turn the profiler off ("#pragma profile off")
|
||||
// in NSPR.Debug.Prefix because of incompatiblity with NSPR threads.
|
||||
// It usually isn't a problem but it may be one when profiling things like
|
||||
// imap or network i/o.
|
||||
//
|
||||
// - The profiler utilities (ProfilerUtils.c) and the profiler
|
||||
// shared library (ProfilerLib) sit in NSRuntime.mcp.
|
||||
//
|
||||
|
||||
// Define this if you want to start profiling when the Caps Lock
|
||||
// key is pressed. Press Caps Lock, start the command you want to
|
||||
// profile, release Caps Lock when the command is done. It works
|
||||
// for all the major commands: display a page, open a window, etc...
|
||||
//
|
||||
// If you want to profile the project, you must make sure that the
|
||||
// global prefix file (IDE_Options.h) contains "#pragma profile on".
|
||||
|
||||
//#define PROFILE
|
||||
|
||||
|
||||
// Define this if you want to let the profiler run while you're
|
||||
// spending time in other apps. Usually you don't.
|
||||
|
||||
//#define PROFILE_WAITNEXTEVENT
|
||||
|
||||
|
||||
#ifdef PROFILE
|
||||
#include "ProfilerUtils.h"
|
||||
#endif //PROFILE
|
||||
#endif //DEBUG
|
||||
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#if !XP_MACOSX
|
||||
#pragma mark MenuSharingToolkitSupport
|
||||
//=================================================================
|
||||
static pascal void ErrorDialog (Str255 s)
|
||||
{
|
||||
//ParamText (s, "\p", "\p", "\p");
|
||||
//Alert (kMenuSharingAlertID, nil);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
static pascal void EventFilter (EventRecord *ev)
|
||||
{
|
||||
// Hrm, prolly should do _something_ here
|
||||
}
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
|
||||
//=================================================================
|
||||
/* Constructor
|
||||
* @update dc 08/31/98
|
||||
* @param aToolkit -- The toolkit created by the application
|
||||
* @return NONE
|
||||
*/
|
||||
nsMacMessagePump::nsMacMessagePump(nsToolkit *aToolkit)
|
||||
: mToolkit(aToolkit), mTSMMessagePump(NULL)
|
||||
: mToolkit(aToolkit)
|
||||
, mMouseClickEventHandler(NULL)
|
||||
, mWNETransitionEventHandler(NULL)
|
||||
{
|
||||
mRunning = PR_FALSE;
|
||||
mMouseRgn = ::NewRgn();
|
||||
|
||||
NS_ASSERTION(mToolkit, "No toolkit");
|
||||
|
||||
// This list encompasses all Carbon events that can be converted into
|
||||
// EventRecords. Not all will necessarily be called; not all will necessarily
|
||||
// be handled. Some items here may be redundant in that handlers are already
|
||||
// installed elsewhere. This may need a good audit.
|
||||
const EventTypeSpec kWNETransitionEventList[] = {
|
||||
{ kEventClassMouse, kEventMouseDown },
|
||||
{ kEventClassMouse, kEventMouseUp },
|
||||
{ kEventClassMouse, kEventMouseMoved },
|
||||
{ kEventClassMouse, kEventMouseDragged },
|
||||
{ kEventClassKeyboard, kEventRawKeyDown },
|
||||
{ kEventClassKeyboard, kEventRawKeyUp },
|
||||
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
||||
{ kEventClassWindow, kEventWindowUpdate },
|
||||
{ kEventClassWindow, kEventWindowActivated },
|
||||
{ kEventClassWindow, kEventWindowDeactivated },
|
||||
{ kEventClassWindow, kEventWindowCursorChange },
|
||||
{ kEventClassApplication, kEventAppActivated },
|
||||
{ kEventClassApplication, kEventAppDeactivated },
|
||||
{ kEventClassAppleEvent, kEventAppleEvent },
|
||||
{ kEventClassControl, kEventControlTrack },
|
||||
};
|
||||
|
||||
static EventHandlerUPP sWNETransitionEventHandlerUPP;
|
||||
if (!sWNETransitionEventHandlerUPP)
|
||||
sWNETransitionEventHandlerUPP =
|
||||
::NewEventHandlerUPP(WNETransitionEventHandler);
|
||||
|
||||
OSStatus err =
|
||||
::InstallApplicationEventHandler(sWNETransitionEventHandlerUPP,
|
||||
GetEventTypeCount(kWNETransitionEventList),
|
||||
kWNETransitionEventList,
|
||||
NS_STATIC_CAST(void*, this),
|
||||
&mWNETransitionEventHandler);
|
||||
|
||||
NS_ASSERTION(err == noErr, "Could not install WNETransitionEventHandler");
|
||||
|
||||
// For middle clicks. Install this handler second, because
|
||||
// WNETransitionEventHandler swallows all events, and MouseClickEventHandler
|
||||
// needs to be able to handle mouse-click events (punting non-middle-click
|
||||
// ones).
|
||||
const EventTypeSpec kMouseClickEventList[] = {
|
||||
{ kEventClassMouse, kEventMouseDown },
|
||||
{ kEventClassMouse, kEventMouseUp },
|
||||
};
|
||||
|
||||
static EventHandlerUPP sMouseClickEventHandlerUPP;
|
||||
if (!sMouseClickEventHandlerUPP)
|
||||
sMouseClickEventHandlerUPP = ::NewEventHandlerUPP(MouseClickEventHandler);
|
||||
|
||||
err =
|
||||
::InstallApplicationEventHandler(sMouseClickEventHandlerUPP,
|
||||
GetEventTypeCount(kMouseClickEventList),
|
||||
kMouseClickEventList,
|
||||
NS_STATIC_CAST(void*, this),
|
||||
&mMouseClickEventHandler);
|
||||
NS_ASSERTION(err == noErr, "Could not install MouseClickEventHandler");
|
||||
|
||||
//
|
||||
// create the TSM Message Pump
|
||||
//
|
||||
mTSMMessagePump = nsMacTSMMessagePump::GetSingleton();
|
||||
NS_ASSERTION(mTSMMessagePump!=NULL,"nsMacMessagePump::nsMacMessagePump: Unable to create TSM Message Pump.");
|
||||
|
||||
#if !XP_MACOSX
|
||||
// added to support Menu Sharing API. Initializes the Menu Sharing API.
|
||||
InitSharedMenus (ErrorDialog, EventFilter);
|
||||
#endif
|
||||
|
||||
// To handle middle-button clicks we must use Carbon Events
|
||||
const EventTypeSpec eventTypes[] = {
|
||||
{ kEventClassMouse, kEventMouseDown },
|
||||
{ kEventClassMouse, kEventMouseUp }
|
||||
};
|
||||
|
||||
EventHandlerUPP handlerUPP =
|
||||
::NewEventHandlerUPP(nsMacMessagePump::CarbonMouseHandler);
|
||||
::InstallApplicationEventHandler(handlerUPP, GetEventTypeCount(eventTypes),
|
||||
eventTypes, (void*)this, NULL);
|
||||
nsMacTSMMessagePump* tsmMessagePump = nsMacTSMMessagePump::GetSingleton();
|
||||
NS_ASSERTION(tsmMessagePump, "Unable to create TSM Message Pump");
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
/* Destructor
|
||||
* @update dc 08/31/98
|
||||
* @param NONE
|
||||
* @return NONE
|
||||
*/
|
||||
nsMacMessagePump::~nsMacMessagePump()
|
||||
{
|
||||
if (mMouseRgn)
|
||||
::DisposeRgn(mMouseRgn);
|
||||
if (mMouseClickEventHandler)
|
||||
::RemoveEventHandler(mMouseClickEventHandler);
|
||||
|
||||
//¥TODO? release the toolkits and sinks? not if we use COM_auto_ptr.
|
||||
|
||||
//
|
||||
// release the TSM Message Pump
|
||||
//
|
||||
}
|
||||
if (mWNETransitionEventHandler)
|
||||
::RemoveEventHandler(mWNETransitionEventHandler);
|
||||
|
||||
|
||||
//=================================================================
|
||||
/* Return the frontmost window that is not the SIOUX console
|
||||
*/
|
||||
WindowPtr nsMacMessagePump::GetFrontApplicationWindow()
|
||||
{
|
||||
WindowPtr firstAppWindow = ::FrontWindow();
|
||||
|
||||
#if DEBUG && !defined(XP_MACOSX)
|
||||
if (IsSIOUXWindow(firstAppWindow))
|
||||
firstAppWindow = ::GetNextWindow(firstAppWindow);
|
||||
#endif
|
||||
|
||||
return firstAppWindow;
|
||||
}
|
||||
|
||||
|
||||
//=================================================================
|
||||
/* Runs the message pump for the macintosh
|
||||
* @update dc 08/31/98
|
||||
* @param NONE
|
||||
*/
|
||||
void nsMacMessagePump::DoMessagePump()
|
||||
{
|
||||
PRBool haveEvent;
|
||||
EventRecord theEvent;
|
||||
|
||||
nsToolkit::AppInForeground();
|
||||
|
||||
while (mRunning)
|
||||
{
|
||||
#ifdef PROFILE
|
||||
if (KeyDown(0x39)) // press [caps lock] to start the profile
|
||||
ProfileStart();
|
||||
else
|
||||
ProfileStop();
|
||||
#endif // PROFILE
|
||||
|
||||
#ifdef PROFILE
|
||||
#ifndef PROFILE_WAITNEXTEVENT
|
||||
ProfileSuspend();
|
||||
#endif // PROFILE_WAITNEXTEVENT
|
||||
#endif // PROFILE
|
||||
|
||||
haveEvent = GetEvent(theEvent, PR_TRUE);
|
||||
|
||||
#ifdef PROFILE
|
||||
#ifndef PROFILE_WAITNEXTEVENT
|
||||
ProfileResume();
|
||||
#endif // PROFILE_WAITNEXTEVENT
|
||||
#endif // PROFILE
|
||||
|
||||
DispatchEvent(haveEvent, &theEvent);
|
||||
}
|
||||
}
|
||||
|
||||
//static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
||||
//static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
|
||||
|
||||
//#define BUSINESS_INDICATOR
|
||||
#define kIdleHysterysisTicks 60
|
||||
|
||||
//=================================================================
|
||||
/* Return TRUE if the program is busy, like doing network stuff.
|
||||
*
|
||||
*/
|
||||
PRBool nsMacMessagePump::BrowserIsBusy()
|
||||
{
|
||||
// we avoid frenetic oscillations between busy and idle states by not going
|
||||
// idle for a few ticks after we've detected idleness. This was added after
|
||||
// observing rapid busy/idle oscillations during chrome loading.
|
||||
static PRUint32 sNextIdleTicks = 0;
|
||||
PRBool foundActivity = PR_TRUE;
|
||||
|
||||
do // convenience for breaking. We'll start by assuming that we're busy.
|
||||
{
|
||||
/*
|
||||
* Don't count connections for now; mailnews holds server connections open,
|
||||
* and that causes us to behave as busy even when we're not, which eats CPU
|
||||
* time and makes machines run hot.
|
||||
|
||||
nsCOMPtr<nsISocketTransportService> socketTransport = do_GetService(kSocketTransportServiceCID);
|
||||
if (socketTransport)
|
||||
{
|
||||
PRUint32 inUseTransports;
|
||||
socketTransport->GetInUseTransportCount(&inUseTransports);
|
||||
if (inUseTransports > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFileTransportService> fileTransport = do_GetService(kFileTransportServiceCID);
|
||||
if (fileTransport)
|
||||
{
|
||||
PRUint32 inUseTransports;
|
||||
fileTransport->GetInUseTransportCount(&inUseTransports);
|
||||
if (inUseTransports > 0)
|
||||
break;
|
||||
}
|
||||
*/
|
||||
if (mToolkit->ToolkitBusy())
|
||||
break;
|
||||
|
||||
foundActivity = PR_FALSE;
|
||||
|
||||
} while(0);
|
||||
|
||||
PRBool isBusy = foundActivity;
|
||||
|
||||
if (foundActivity)
|
||||
sNextIdleTicks = ::TickCount() + kIdleHysterysisTicks;
|
||||
else if (::TickCount() < sNextIdleTicks)
|
||||
isBusy = PR_TRUE;
|
||||
|
||||
#ifdef BUSINESS_INDICATOR
|
||||
static PRBool wasBusy;
|
||||
if (isBusy != wasBusy)
|
||||
{
|
||||
printf("*** Message pump became %s at %ld (next idle %ld)\n", isBusy ? "busy" : "idle", ::TickCount(), sNextIdleTicks);
|
||||
wasBusy = isBusy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return isBusy;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
/* Fetch a single event
|
||||
* @update dc 08/31/98
|
||||
* @param NONE
|
||||
* @return A boolean which states whether we have a real event
|
||||
*/
|
||||
PRBool nsMacMessagePump::GetEvent(EventRecord &theEvent, PRBool mayWait)
|
||||
{
|
||||
PRBool inForeground = nsToolkit::IsAppInForeground();
|
||||
PRBool buttonDown = ::Button();
|
||||
|
||||
// when in the background, we don't want to chew up time processing mouse move
|
||||
// events, so set the mouse region to null. If we're in the fg, however,
|
||||
// we want every mouseMove event we can get our grubby little hands on, so set
|
||||
// it to a 1x1 rect.
|
||||
RgnHandle mouseRgn = inForeground ? mMouseRgn : nsnull;
|
||||
|
||||
// if the mouse is down, and we're in the foreground, then eat
|
||||
// CPU so we respond quickly when scrolling etc.
|
||||
SInt32 sleepTime = (!mayWait || (buttonDown && inForeground)) ? 0 : 5;
|
||||
|
||||
::SetEventMask(everyEvent); // we need keyUp events
|
||||
PRBool haveEvent = ::WaitNextEvent(everyEvent, &theEvent, sleepTime, mouseRgn);
|
||||
|
||||
return haveEvent;
|
||||
nsMacTSMMessagePump::Shutdown();
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
/* Dispatch a single event
|
||||
* @param theEvent - the event to dispatch
|
||||
* @param anEvent - the event to dispatch
|
||||
* @return A boolean which states whether we handled the event
|
||||
*/
|
||||
PRBool nsMacMessagePump::DispatchEvent(PRBool aRealEvent, EventRecord *anEvent)
|
||||
PRBool nsMacMessagePump::DispatchEvent(EventRecord *anEvent)
|
||||
{
|
||||
PRBool handled = PR_FALSE;
|
||||
|
||||
if (aRealEvent == PR_TRUE)
|
||||
{
|
||||
|
||||
#if DEBUG && !defined(XP_MACOSX)
|
||||
if ((anEvent->what != kHighLevelEvent) && SIOUXHandleOneEvent(anEvent))
|
||||
return PR_TRUE;
|
||||
#endif
|
||||
switch(anEvent->what) {
|
||||
// diskEvt is gone in Carbon, and so is unhandled here.
|
||||
|
||||
switch(anEvent->what)
|
||||
{
|
||||
case keyUp:
|
||||
case keyDown:
|
||||
case autoKey:
|
||||
handled = DoKey(*anEvent);
|
||||
break;
|
||||
case keyUp:
|
||||
case keyDown:
|
||||
case autoKey:
|
||||
handled = DoKey(*anEvent);
|
||||
break;
|
||||
|
||||
case mouseDown:
|
||||
handled = DoMouseDown(*anEvent);
|
||||
break;
|
||||
case mouseDown:
|
||||
handled = DoMouseDown(*anEvent);
|
||||
break;
|
||||
|
||||
case mouseUp:
|
||||
handled = DoMouseUp(*anEvent);
|
||||
break;
|
||||
case mouseUp:
|
||||
handled = DoMouseUp(*anEvent);
|
||||
break;
|
||||
|
||||
case updateEvt:
|
||||
handled = DoUpdate(*anEvent);
|
||||
break;
|
||||
case updateEvt:
|
||||
handled = DoUpdate(*anEvent);
|
||||
break;
|
||||
|
||||
case activateEvt:
|
||||
handled = DoActivate(*anEvent);
|
||||
break;
|
||||
case activateEvt:
|
||||
handled = DoActivate(*anEvent);
|
||||
break;
|
||||
|
||||
case diskEvt:
|
||||
handled = DoDisk(*anEvent);
|
||||
break;
|
||||
case osEvt: {
|
||||
unsigned char eventType = ((anEvent->message >> 24) & 0x00ff);
|
||||
switch (eventType)
|
||||
{
|
||||
case suspendResumeMessage:
|
||||
if (anEvent->message & resumeFlag)
|
||||
nsToolkit::AppInForeground(); // resume message
|
||||
else
|
||||
nsToolkit::AppInBackground(); // suspend message
|
||||
|
||||
case osEvt:
|
||||
{
|
||||
unsigned char eventType = ((anEvent->message >> 24) & 0x00ff);
|
||||
switch (eventType)
|
||||
{
|
||||
case suspendResumeMessage:
|
||||
if ( anEvent->message & resumeFlag )
|
||||
nsToolkit::AppInForeground(); // resume message
|
||||
else
|
||||
nsToolkit::AppInBackground(); // suspend message
|
||||
|
||||
handled = DoMouseMove(*anEvent);
|
||||
break;
|
||||
|
||||
case mouseMovedMessage:
|
||||
handled = DoMouseMove(*anEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kHighLevelEvent:
|
||||
::AEProcessAppleEvent(anEvent);
|
||||
handled = PR_TRUE;
|
||||
break;
|
||||
handled = DoMouseMove(*anEvent);
|
||||
break;
|
||||
|
||||
case mouseMovedMessage:
|
||||
handled = DoMouseMove(*anEvent);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kHighLevelEvent:
|
||||
::AEProcessAppleEvent(anEvent);
|
||||
handled = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DoIdle(*anEvent);
|
||||
|
||||
if (mRunning)
|
||||
Repeater::DoIdlers(*anEvent);
|
||||
|
||||
// yield to other threads
|
||||
::PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
handled = PR_FALSE;
|
||||
}
|
||||
|
||||
if (mRunning)
|
||||
Repeater::DoRepeaters(*anEvent);
|
||||
|
||||
NS_ASSERTION(ValidateDrawingState(), "Bad drawing state");
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoUpdate
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
//#include "ProfilerUtils.h"
|
||||
PRBool nsMacMessagePump::DoUpdate(EventRecord &anEvent)
|
||||
{
|
||||
|
||||
WindowPtr whichWindow = reinterpret_cast<WindowPtr>(anEvent.message);
|
||||
|
||||
StPortSetter portSetter(whichWindow);
|
||||
@ -494,7 +229,6 @@ PRBool nsMacMessagePump::DoUpdate(EventRecord &anEvent)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoMouseDown
|
||||
@ -530,15 +264,8 @@ PRBool nsMacMessagePump::DoMouseDown(EventRecord &anEvent)
|
||||
}
|
||||
else
|
||||
{
|
||||
long menuResult = ::MenuSelect(anEvent.where);
|
||||
::MenuSelect(anEvent.where);
|
||||
handled = PR_TRUE;
|
||||
#if USE_MENUSELECT
|
||||
if (HiWord(menuResult) != 0)
|
||||
{
|
||||
menuResult = ConvertOSMenuResultToPPMenuResult(menuResult);
|
||||
handled = DoMenu(anEvent, menuResult);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
@ -629,74 +356,21 @@ PRBool nsMacMessagePump::DoMouseDown(EventRecord &anEvent)
|
||||
{
|
||||
nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);
|
||||
|
||||
// use the cmd-key to do the opposite of the DRAW_ON_RESIZE setting.
|
||||
Boolean cmdKeyDown = (anEvent.modifiers & cmdKey) != 0;
|
||||
Boolean drawOnResize = DRAW_ON_RESIZE ? !cmdKeyDown : cmdKeyDown;
|
||||
if (drawOnResize)
|
||||
{
|
||||
Point oldPt = anEvent.where;
|
||||
while (::WaitMouseUp())
|
||||
{
|
||||
Repeater::DoRepeaters(anEvent);
|
||||
Rect sizeLimit;
|
||||
sizeLimit.top = kMinWindowHeight;
|
||||
sizeLimit.left = kMinWindowWidth;
|
||||
sizeLimit.bottom = 0x7FFF;
|
||||
sizeLimit.right = 0x7FFF;
|
||||
|
||||
Point origin = {0,0};
|
||||
::LocalToGlobal(&origin);
|
||||
Point newPt;
|
||||
::GetMouse(&newPt);
|
||||
::LocalToGlobal(&newPt);
|
||||
if (::DeltaPoint(oldPt, newPt))
|
||||
{
|
||||
Rect portRect;
|
||||
::GetWindowPortBounds(whichWindow, &portRect);
|
||||
Rect newSize;
|
||||
::ResizeWindow(whichWindow, anEvent.where, &sizeLimit, &newSize);
|
||||
|
||||
short width = newPt.h - origin.h;
|
||||
short height = newPt.v - origin.v;
|
||||
if (width < kMinWindowWidth)
|
||||
width = kMinWindowWidth;
|
||||
if (height < kMinWindowHeight)
|
||||
height = kMinWindowHeight;
|
||||
Point newPt = botRight(newSize);
|
||||
::LocalToGlobal(&newPt);
|
||||
newPt.h -= 8, newPt.v -= 8;
|
||||
anEvent.where = newPt; // important!
|
||||
handled = DispatchOSEventToRaptor(anEvent, whichWindow);
|
||||
|
||||
oldPt = newPt;
|
||||
::SizeWindow(whichWindow, width, height, true);
|
||||
|
||||
// simulate a click in the grow icon
|
||||
anEvent.where.h = width - 8; // on Aqua, clicking at (width, height) misses the grow icon. inset a bit.
|
||||
anEvent.where.v = height - 8;
|
||||
::LocalToGlobal(&anEvent.where);
|
||||
DispatchOSEventToRaptor(anEvent, whichWindow);
|
||||
|
||||
Boolean haveEvent;
|
||||
EventRecord updateEvent;
|
||||
haveEvent = ::WaitNextEvent(updateMask, &updateEvent, 0, nil);
|
||||
if (haveEvent)
|
||||
DoUpdate(updateEvent);
|
||||
}
|
||||
}
|
||||
handled = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rect sizeRect;
|
||||
::GetRegionBounds(::GetGrayRgn(), &sizeRect);
|
||||
|
||||
/* rjc sez (paraphrased) the maximum window size could also reasonably be
|
||||
taken from the size of ::GetRegionBounds(::GetGrayRgn(),...) (not simply
|
||||
the region bounds, but its width and height) or perhaps the size of the
|
||||
screen to which the window mostly belongs. But why be so restrictive? */
|
||||
sizeRect.top = kMinWindowHeight;
|
||||
sizeRect.left = kMinWindowWidth;
|
||||
sizeRect.bottom = 0x7FFF;
|
||||
sizeRect.right = 0x7FFF;
|
||||
long newSize = ::GrowWindow(whichWindow, anEvent.where, &sizeRect);
|
||||
if (newSize != 0)
|
||||
::SizeWindow(whichWindow, newSize & 0x0FFFF, (newSize >> 16) & 0x0FFFF, true);
|
||||
Rect portRect;
|
||||
Point newPt = botRight(*::GetWindowPortBounds(whichWindow, &portRect));
|
||||
::LocalToGlobal(&newPt);
|
||||
newPt.h -= 8, newPt.v -= 8;
|
||||
anEvent.where = newPt; // important!
|
||||
handled = DispatchOSEventToRaptor(anEvent, whichWindow);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -739,7 +413,6 @@ PRBool nsMacMessagePump::DoMouseDown(EventRecord &anEvent)
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoMouseUp
|
||||
@ -757,7 +430,7 @@ PRBool nsMacMessagePump::DoMouseUp(EventRecord &anEvent)
|
||||
// when the user clicks a widget, keeps the mouse button pressed and
|
||||
// releases it outside the window, the event needs to be reported to
|
||||
// the widget so that it can deactivate itself.
|
||||
whichWindow = GetFrontApplicationWindow();
|
||||
whichWindow = ::FrontWindow();
|
||||
}
|
||||
|
||||
PRBool handled = DispatchOSEventToRaptor(anEvent, whichWindow);
|
||||
@ -779,15 +452,9 @@ PRBool nsMacMessagePump::DoMouseMove(EventRecord &anEvent)
|
||||
PRInt16 partCode;
|
||||
PRBool handled = PR_FALSE;
|
||||
|
||||
if (mMouseRgn)
|
||||
{
|
||||
Point globalMouse = anEvent.where;
|
||||
::SetRectRgn(mMouseRgn, globalMouse.h, globalMouse.v, globalMouse.h + 1, globalMouse.v + 1);
|
||||
}
|
||||
|
||||
partCode = ::FindWindow(anEvent.where, &whichWindow);
|
||||
if (whichWindow == nil)
|
||||
whichWindow = GetFrontApplicationWindow();
|
||||
whichWindow = ::FrontWindow();
|
||||
|
||||
/* Disable mouse moved events for windowshaded windows -- this prevents tooltips
|
||||
from popping up in empty space.
|
||||
@ -797,7 +464,6 @@ PRBool nsMacMessagePump::DoMouseMove(EventRecord &anEvent)
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoKey
|
||||
@ -808,82 +474,10 @@ PRBool nsMacMessagePump::DoMouseMove(EventRecord &anEvent)
|
||||
PRBool nsMacMessagePump::DoKey(EventRecord &anEvent)
|
||||
{
|
||||
PRBool handled = PR_FALSE;
|
||||
{
|
||||
handled = DispatchOSEventToRaptor(anEvent, GetFrontApplicationWindow());
|
||||
#if USE_MENUSELECT
|
||||
/* we want to call this if cmdKey is pressed and no other modifier keys are pressed */
|
||||
if((!handled) && (anEvent.what == keyDown) && (anEvent.modifiers == cmdKey) )
|
||||
{
|
||||
// do a menu key command
|
||||
long menuResult = ::MenuKey(theChar);
|
||||
if (HiWord(menuResult) != 0)
|
||||
{
|
||||
menuResult = ConvertOSMenuResultToPPMenuResult(menuResult);
|
||||
DoMenu(anEvent, menuResult);
|
||||
handled = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
handled = DispatchOSEventToRaptor(anEvent, ::FrontWindow());
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoDisk
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsMacMessagePump::DoDisk(const EventRecord& anEvent)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoMenu
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
extern Boolean SIOUXIsAppWindow(WindowPtr window);
|
||||
|
||||
#if USE_MENUSELECT
|
||||
PRBool nsMacMessagePump::DoMenu(EventRecord &anEvent, long menuResult)
|
||||
{
|
||||
// The app can handle its menu commands here or
|
||||
// in the nsNativeBrowserWindow and nsNativeViewerApp
|
||||
|
||||
extern const PRInt16 kAppleMenuID; // Danger Will Robinson!!! - this currently requires
|
||||
// APPLE_MENU_HACK to be defined in nsMenu.h
|
||||
// One of these days it'll become a non-hack
|
||||
// and things will be less convoluted
|
||||
|
||||
// See if it was the Apple Menu
|
||||
if (HiWord(menuResult) == kAppleMenuID)
|
||||
{
|
||||
short theItem = LoWord(menuResult);
|
||||
if (theItem > 2)
|
||||
{
|
||||
Str255 daName;
|
||||
GrafPtr savePort;
|
||||
|
||||
::GetMenuItemText(::GetMenuHandle(kAppleMenuID), theItem, daName);
|
||||
::GetPort(&savePort);
|
||||
::OpenDeskAcc(daName);
|
||||
::SetPort(savePort);
|
||||
HiliteMenu(0);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we still give Raptor a shot at the event as it will eventually
|
||||
// handle the About... selection
|
||||
PRBool handled = DispatchMenuCommandToRaptor(anEvent, menuResult);
|
||||
HiliteMenu(0);
|
||||
return handled;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoActivate
|
||||
@ -918,40 +512,6 @@ PRBool nsMacMessagePump::DoActivate(EventRecord &anEvent)
|
||||
return DispatchOSEventToRaptor(anEvent, whichWindow);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DoIdle
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
void nsMacMessagePump::DoIdle(EventRecord &anEvent)
|
||||
{
|
||||
// send mouseMove event
|
||||
static Point lastWhere = {0, 0};
|
||||
|
||||
#if !XP_MACOSX
|
||||
if ( nsToolkit::IsAppInForeground() )
|
||||
{
|
||||
// Shared Menu support - note we hardcode first menu ID available as 31000
|
||||
CheckSharedMenus(31000);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*(long*)&lastWhere == *(long*)&anEvent.where)
|
||||
return;
|
||||
|
||||
EventRecord localEvent = anEvent;
|
||||
localEvent.what = nullEvent;
|
||||
lastWhere = localEvent.where;
|
||||
if ( nsToolkit::IsAppInForeground() )
|
||||
DoMouseMove(localEvent);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DispatchOSEventToRaptor
|
||||
@ -969,71 +529,68 @@ PRBool nsMacMessagePump::DispatchOSEventToRaptor(
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
#if USE_MENUSELECT
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DispatchMenuCommandToRaptor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsMacMessagePump::DispatchMenuCommandToRaptor(
|
||||
EventRecord &anEvent,
|
||||
long menuResult)
|
||||
{
|
||||
PRBool handled = PR_FALSE;
|
||||
WindowPtr theFrontWindow = GetFrontApplicationWindow();
|
||||
|
||||
nsCOMPtr<nsIEventSink> sink;
|
||||
nsToolkit::GetWindowEventSink ( theFrontWindow, getter_AddRefs(sink) );
|
||||
nsCOMPtr<nsPIEventSinkStandalone> menuSink ( do_QueryInterface(sink) );
|
||||
if ( menuSink )
|
||||
menuSink->DispatchMenuEvent ( &anEvent, menuResult, &handled );
|
||||
return handled;
|
||||
}
|
||||
|
||||
#endif // USE_MENUSELECT
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// CarbonMouseHandler
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
pascal OSStatus nsMacMessagePump::CarbonMouseHandler(
|
||||
EventHandlerCallRef nextHandler,
|
||||
EventRef theEvent, void *userData)
|
||||
pascal OSStatus
|
||||
nsMacMessagePump::MouseClickEventHandler(EventHandlerCallRef aHandlerCallRef,
|
||||
EventRef aEvent,
|
||||
void* aUserData)
|
||||
{
|
||||
EventMouseButton button;
|
||||
OSErr err = ::GetEventParameter(theEvent, kEventParamMouseButton,
|
||||
OSErr err = ::GetEventParameter(aEvent, kEventParamMouseButton,
|
||||
typeMouseButton, NULL,
|
||||
sizeof(EventMouseButton), NULL, &button);
|
||||
if (err != noErr)
|
||||
|
||||
// Only handle middle click events here. Let the rest fall through.
|
||||
if (err != noErr || button != kEventMouseButtonTertiary)
|
||||
return eventNotHandledErr;
|
||||
|
||||
// Only handle middle click events here. Let the rest fall through to
|
||||
// WaitNextEvent().
|
||||
if (button != kEventMouseButtonTertiary)
|
||||
return eventNotHandledErr;
|
||||
|
||||
EventRecord theRecord;
|
||||
if (!::ConvertEventRefToEventRecord(theEvent, &theRecord)) {
|
||||
EventRecord eventRecord;
|
||||
if (!::ConvertEventRefToEventRecord(aEvent, &eventRecord)) {
|
||||
// This will return FALSE on a middle click event; that's to let us know
|
||||
// it's giving us a nullEvent, which is expected since Classic events
|
||||
// don't support the middle button normally.
|
||||
//
|
||||
// We know better, so let's restore the actual event kind.
|
||||
UInt32 kind = ::GetEventKind(theEvent);
|
||||
theRecord.what = (kind == kEventMouseDown) ? mouseDown : mouseUp;
|
||||
UInt32 kind = ::GetEventKind(aEvent);
|
||||
eventRecord.what = (kind == kEventMouseDown) ? mouseDown : mouseUp;
|
||||
}
|
||||
|
||||
// Classic mouse events don't record the button specifier. The message
|
||||
// parameter is unused in mouse click events, so let's stuff it there.
|
||||
// We'll pick it up in nsMacEventHandler::HandleMouseDownEvent().
|
||||
theRecord.message = (UInt32)button;
|
||||
eventRecord.message = NS_STATIC_CAST(UInt32, button);
|
||||
|
||||
// Process the modified event internally
|
||||
nsMacMessagePump *pump = (nsMacMessagePump*)userData;
|
||||
PRBool handled = pump->DispatchEvent(PR_TRUE, &theRecord);
|
||||
return handled ? noErr : eventNotHandledErr;
|
||||
nsMacMessagePump* self = NS_STATIC_CAST(nsMacMessagePump*, aUserData);
|
||||
PRBool handled = self->DispatchEvent(&eventRecord);
|
||||
|
||||
if (handled)
|
||||
return noErr;
|
||||
|
||||
return eventNotHandledErr;
|
||||
}
|
||||
|
||||
// WNETransitionEventHandler
|
||||
//
|
||||
// Transitional WaitNextEvent handler. Accepts Carbon events from
|
||||
// kWNETransitionEventList, converts them into EventRecords, and
|
||||
// dispatches them through the path they would have gone if they
|
||||
// had been received as EventRecords from WaitNextEvent.
|
||||
//
|
||||
// protected static
|
||||
pascal OSStatus
|
||||
nsMacMessagePump::WNETransitionEventHandler(EventHandlerCallRef aHandlerCallRef,
|
||||
EventRef aEvent,
|
||||
void* aUserData)
|
||||
{
|
||||
nsMacMessagePump* self = NS_STATIC_CAST(nsMacMessagePump*, aUserData);
|
||||
|
||||
EventRecord eventRecord;
|
||||
::ConvertEventRefToEventRecord(aEvent, &eventRecord);
|
||||
|
||||
PRBool handled = self->DispatchEvent(&eventRecord);
|
||||
|
||||
if (!handled)
|
||||
return eventNotHandledErr;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Mentovai <mark@moxienet.com>
|
||||
*
|
||||
* 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
|
||||
@ -35,89 +36,56 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//
|
||||
// nsMacMessagePump
|
||||
//
|
||||
// This file contains the default implementation for the mac event loop. Events that
|
||||
// pertain to the layout engine are routed there via a MessageSink that is passed in
|
||||
// at creation time. Events not destined for layout are handled here (such as window
|
||||
// moved).
|
||||
//
|
||||
// Clients may either use this implementation or write their own. Embedding applications
|
||||
// will almost certainly write their own because they will want control of the event
|
||||
// loop to do other processing. There is nothing in the architecture which forces the
|
||||
// embedding app to use anything called a "message pump" so the event loop can actually
|
||||
// live anywhere the app wants.
|
||||
//
|
||||
/*
|
||||
* Dispatcher for a variety of application-scope events. The real event loop
|
||||
* is in nsAppShell.
|
||||
*/
|
||||
|
||||
#ifndef nsMacMessagePump_h__
|
||||
#define nsMacMessagePump_h__
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
#include <Events.h>
|
||||
#include "prtypes.h"
|
||||
|
||||
class nsToolkit;
|
||||
class nsMacTSMMessagePump;
|
||||
class nsIEventSink;
|
||||
class nsIWidget;
|
||||
|
||||
|
||||
//================================================
|
||||
|
||||
// Macintosh Message Pump Class
|
||||
class nsMacMessagePump
|
||||
{
|
||||
// CLASS MEMBERS
|
||||
private:
|
||||
PRBool mRunning;
|
||||
Point mMousePoint; // keep track of where the mouse is at all times
|
||||
RgnHandle mMouseRgn;
|
||||
nsToolkit* mToolkit;
|
||||
nsMacTSMMessagePump* mTSMMessagePump;
|
||||
public:
|
||||
nsMacMessagePump(nsToolkit *aToolKit);
|
||||
virtual ~nsMacMessagePump();
|
||||
|
||||
// CLASS METHODS
|
||||
|
||||
public:
|
||||
nsMacMessagePump(nsToolkit *aToolKit);
|
||||
virtual ~nsMacMessagePump();
|
||||
PRBool ProcessEvents(PRBool aProcessEvents);
|
||||
|
||||
void DoMessagePump();
|
||||
PRBool GetEvent(EventRecord &theEvent, PRBool mayWait);
|
||||
// returns true if handled
|
||||
PRBool DispatchEvent(PRBool aRealEvent, EventRecord *anEvent);
|
||||
void StartRunning() {mRunning = PR_TRUE;}
|
||||
void StopRunning() {mRunning = PR_FALSE;}
|
||||
// returns PR_TRUE if the event was handled
|
||||
PRBool DispatchEvent(EventRecord *anEvent);
|
||||
|
||||
private:
|
||||
protected:
|
||||
// these all return PR_TRUE if the event was handled
|
||||
PRBool DoMouseDown(EventRecord &anEvent);
|
||||
PRBool DoMouseUp(EventRecord &anEvent);
|
||||
PRBool DoMouseMove(EventRecord &anEvent);
|
||||
PRBool DoUpdate(EventRecord &anEvent);
|
||||
PRBool DoKey(EventRecord &anEvent);
|
||||
PRBool DoActivate(EventRecord &anEvent);
|
||||
|
||||
// these all return PR_TRUE if the event was handled
|
||||
PRBool DoMouseDown(EventRecord &anEvent);
|
||||
PRBool DoMouseUp(EventRecord &anEvent);
|
||||
PRBool DoMouseMove(EventRecord &anEvent);
|
||||
PRBool DoUpdate(EventRecord &anEvent);
|
||||
PRBool DoKey(EventRecord &anEvent);
|
||||
#if USE_MENUSELECT
|
||||
PRBool DoMenu(EventRecord &anEvent, long menuResult);
|
||||
#endif
|
||||
PRBool DoDisk(const EventRecord &anEvent);
|
||||
PRBool DoActivate(EventRecord &anEvent);
|
||||
void DoIdle(EventRecord &anEvent);
|
||||
PRBool DispatchOSEventToRaptor(EventRecord &anEvent, WindowPtr aWindow);
|
||||
|
||||
PRBool DispatchOSEventToRaptor(EventRecord &anEvent, WindowPtr aWindow);
|
||||
#if USE_MENUSELECT
|
||||
PRBool DispatchMenuCommandToRaptor(EventRecord &anEvent, long menuResult);
|
||||
#endif
|
||||
static pascal OSStatus MouseClickEventHandler(
|
||||
EventHandlerCallRef aHandlerCallRef,
|
||||
EventRef aEvent,
|
||||
void* aUserData);
|
||||
static pascal OSStatus WNETransitionEventHandler(
|
||||
EventHandlerCallRef aHandlerCallRef,
|
||||
EventRef aEvent,
|
||||
void* aUserData);
|
||||
|
||||
PRBool BrowserIsBusy();
|
||||
|
||||
WindowPtr GetFrontApplicationWindow();
|
||||
|
||||
static pascal OSStatus CarbonMouseHandler(EventHandlerCallRef nextHandler,
|
||||
EventRef theEvent, void *userData);
|
||||
protected:
|
||||
nsToolkit* mToolkit;
|
||||
nsMacTSMMessagePump* mTSMMessagePump;
|
||||
EventHandlerRef mMouseClickEventHandler;
|
||||
EventHandlerRef mWNETransitionEventHandler;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // nsMacMessagePump_h__
|
||||
|
||||
|
@ -83,26 +83,26 @@ nsMacTSMMessagePump::nsMacTSMMessagePump()
|
||||
NS_ASSERTION(mPos2OffsetUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[Pos2Pffset] failed");
|
||||
|
||||
err = AEInstallEventHandler(kTextServiceClass, kPos2Offset, mPos2OffsetUPP, (long)this, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Pos2Offset] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[Pos2Offset] failed");
|
||||
|
||||
err = AEInstallEventHandler(kTextServiceClass, kOffset2Pos, mOffset2PosUPP, (long)this, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Offset2Pos] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[Offset2Pos] failed");
|
||||
|
||||
err = AEInstallEventHandler(kTextServiceClass, kUpdateActiveInputArea, mUpdateUPP, (long)this, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Update] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[Update] failed");
|
||||
|
||||
if (tsmstrategy.UseUnicodeForKeyboard()) {
|
||||
mKeyboardUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::UnicodeNotFromInputMethodHandler);
|
||||
NS_ASSERTION(mKeyboardUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[FromInputMethod] failed");
|
||||
|
||||
err = AEInstallEventHandler(kTextServiceClass, kUnicodeNotFromInputMethod, mKeyboardUPP, (long)this, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[FromInputMethod] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[FromInputMethod] failed");
|
||||
|
||||
mGetSelectedTextUPP = NewAEEventHandlerUPP(nsMacTSMMessagePump::UnicodeGetSelectedTextHandler);
|
||||
NS_ASSERTION(mGetSelectedTextUPP!=NULL, "nsMacTSMMessagePump::InstallTSMAEHandlers: NewAEEventHandlerUPP[GetSelectedText] failed");
|
||||
|
||||
err = AEInstallEventHandler(kTextServiceClass, kGetSelectedText, mGetSelectedTextUPP, (long)this, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[GetSelectedText] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandler[GetSelectedText] failed");
|
||||
|
||||
}
|
||||
|
||||
@ -113,13 +113,13 @@ nsMacTSMMessagePump::~nsMacTSMMessagePump()
|
||||
OSErr err;
|
||||
|
||||
err = AERemoveEventHandler(kTextServiceClass, kPos2Offset, mPos2OffsetUPP, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Pos2Offset] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[Pos2Offset] failed");
|
||||
|
||||
err = AERemoveEventHandler(kTextServiceClass, kOffset2Pos, mOffset2PosUPP, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Offset2Pos] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[Offset2Pos] failed");
|
||||
|
||||
err = AERemoveEventHandler(kTextServiceClass, kUpdateActiveInputArea, mUpdateUPP, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[Update] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[Update] failed");
|
||||
|
||||
::DisposeAEEventHandlerUPP(mPos2OffsetUPP);
|
||||
::DisposeAEEventHandlerUPP(mOffset2PosUPP);
|
||||
@ -128,11 +128,11 @@ nsMacTSMMessagePump::~nsMacTSMMessagePump()
|
||||
nsTSMStrategy tsmstrategy;
|
||||
if (tsmstrategy.UseUnicodeForKeyboard()) {
|
||||
err = AERemoveEventHandler(kTextServiceClass, kUnicodeNotFromInputMethod, mKeyboardUPP, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[FromInputMethod] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[FromInputMethod] failed");
|
||||
::DisposeAEEventHandlerUPP(mKeyboardUPP);
|
||||
|
||||
err = AERemoveEventHandler(kTextServiceClass, kGetSelectedText, mGetSelectedTextUPP, false);
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::InstallTSMAEHandlers: AEInstallEventHandlers[GetSelectedText] failed");
|
||||
NS_ASSERTION(err==noErr, "nsMacTSMMessagePump::RemoveTSMAEHandlers: AERemoveEventHandler[GetSelectedText] failed");
|
||||
::DisposeAEEventHandlerUPP(mGetSelectedTextUPP);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
~nsMacTSMMessagePump();
|
||||
|
||||
static nsMacTSMMessagePump* GetSingleton();
|
||||
void Shutdown();
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
static pascal OSErr PositionToOffsetHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
|
||||
@ -77,4 +77,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif // NSMACTSMMESSAGEPUMP_h__
|
||||
#endif // NSMACTSMMESSAGEPUMP_h__
|
||||
|
@ -36,93 +36,14 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsToolkit.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsWidgetAtoms.h"
|
||||
|
||||
#include "nsIEventSink.h"
|
||||
|
||||
#include "nsWidgetSupport.h"
|
||||
|
||||
#include <Gestalt.h>
|
||||
#include <Movies.h>
|
||||
|
||||
#include "nsIEventSink.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsGfxCIID.h"
|
||||
#include "nsIPref.h"
|
||||
|
||||
|
||||
static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMacNSPREventQueueHandler::nsMacNSPREventQueueHandler(): Repeater()
|
||||
{
|
||||
mRefCnt = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMacNSPREventQueueHandler::~nsMacNSPREventQueueHandler()
|
||||
{
|
||||
StopRepeating();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
void nsMacNSPREventQueueHandler::StartPumping()
|
||||
{
|
||||
++mRefCnt;
|
||||
NS_LOG_ADDREF(this, mRefCnt, "nsMacNSPREventQueueHandler", sizeof(*this));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsMacNSPREventQueueHandler::StopPumping()
|
||||
{
|
||||
if (mRefCnt > 0) {
|
||||
--mRefCnt;
|
||||
NS_LOG_RELEASE(this, mRefCnt, "nsMacNSPREventQueueHandler");
|
||||
if (mRefCnt == 0) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
void nsMacNSPREventQueueHandler::RepeatAction(const EventRecord& inMacEvent)
|
||||
{
|
||||
ProcessPLEventQueue();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsMacNSPREventQueueHandler::EventsArePending()
|
||||
{
|
||||
return NS_HasPendingEvents(NS_GetCurrentThread());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
void nsMacNSPREventQueueHandler::ProcessPLEventQueue()
|
||||
{
|
||||
NS_ProcessPendingEvents(NS_GetCurrentThread());
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
// assume we begin as the fg app
|
||||
@ -133,9 +54,6 @@ bool nsToolkit::sInForeground = true;
|
||||
//-------------------------------------------------------------------------
|
||||
nsToolkit::nsToolkit()
|
||||
{
|
||||
if (gEventQueueHandler == nsnull)
|
||||
gEventQueueHandler = new nsMacNSPREventQueueHandler;
|
||||
|
||||
::EnterMovies(); // Required for nsSound to Work! -- fix for bug 194632
|
||||
}
|
||||
|
||||
@ -144,17 +62,6 @@ nsToolkit::nsToolkit()
|
||||
//-------------------------------------------------------------------------
|
||||
nsToolkit::~nsToolkit()
|
||||
{
|
||||
/* StopPumping decrements a refcount on gEventQueueHandler; a prelude toward
|
||||
stopping event handling. This is not something you want to do unless you've
|
||||
bloody well started event handling and incremented the refcount. That's
|
||||
done in the Init method, not the constructor, and that's what mInited is about.
|
||||
*/
|
||||
if (mInited && gEventQueueHandler) {
|
||||
if (gEventQueueHandler->StopPumping()) {
|
||||
delete gEventQueueHandler;
|
||||
gEventQueueHandler = nsnull;
|
||||
}
|
||||
}
|
||||
::ExitMovies(); // done with Movie Toolbox -- fix for bug 194632
|
||||
}
|
||||
|
||||
@ -165,21 +72,9 @@ nsToolkit::~nsToolkit()
|
||||
nsresult
|
||||
nsToolkit::InitEventQueue(PRThread * aThread)
|
||||
{
|
||||
if (gEventQueueHandler)
|
||||
gEventQueueHandler->StartPumping();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsToolkit::ToolkitBusy()
|
||||
{
|
||||
return (gEventQueueHandler) ? gEventQueueHandler->EventsArePending() : PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsToolkit :: AppInForeground ( )
|
||||
{
|
||||
@ -266,116 +161,3 @@ nsToolkitBase* NS_CreateToolkitInstance()
|
||||
{
|
||||
return new nsToolkit();
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
Handle nsMacMemoryCushion::sMemoryReserve;
|
||||
|
||||
nsMacMemoryCushion::nsMacMemoryCushion()
|
||||
: mBufferHandle(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
nsMacMemoryCushion::~nsMacMemoryCushion()
|
||||
{
|
||||
StopRepeating();
|
||||
::SetGrowZone(nsnull);
|
||||
|
||||
NS_ASSERTION(sMemoryReserve, "Memory reserve was nil");
|
||||
if (sMemoryReserve)
|
||||
{
|
||||
::DisposeHandle(sMemoryReserve);
|
||||
sMemoryReserve = nil;
|
||||
}
|
||||
|
||||
if (mBufferHandle)
|
||||
::DisposeHandle(mBufferHandle);
|
||||
}
|
||||
|
||||
|
||||
OSErr nsMacMemoryCushion::Init(Size bufferSize, Size reserveSize)
|
||||
{
|
||||
sMemoryReserve = ::NewHandle(reserveSize);
|
||||
if (sMemoryReserve == nsnull)
|
||||
return ::MemError();
|
||||
|
||||
mBufferHandle = ::NewHandle(bufferSize);
|
||||
if (mBufferHandle == nsnull)
|
||||
return ::MemError();
|
||||
|
||||
// make this purgable
|
||||
::HPurge(mBufferHandle);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
void nsMacMemoryCushion::RepeatAction(const EventRecord &aMacEvent)
|
||||
{
|
||||
if (!RecoverMemoryReserve(kMemoryReserveSize))
|
||||
{
|
||||
// NS_ASSERTION(0, "Failed to recallocate memory reserve. Flushing caches");
|
||||
nsMemory::HeapMinimize(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Boolean nsMacMemoryCushion::RecoverMemoryReserve(Size reserveSize)
|
||||
{
|
||||
if (!sMemoryReserve) return true; // not initted yet
|
||||
if (*sMemoryReserve != nsnull) return true; // everything is OK
|
||||
|
||||
::ReallocateHandle(sMemoryReserve, reserveSize);
|
||||
if (::MemError() != noErr || !*sMemoryReserve) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean nsMacMemoryCushion::RecoverMemoryBuffer(Size bufferSize)
|
||||
{
|
||||
if (!mBufferHandle) return true; // not initted yet
|
||||
if (*mBufferHandle != nsnull) return true; // everything is OK
|
||||
|
||||
::ReallocateHandle(mBufferHandle, bufferSize);
|
||||
if (::MemError() != noErr || !*mBufferHandle) return false;
|
||||
|
||||
// make this purgable
|
||||
::HPurge(mBufferHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
pascal long nsMacMemoryCushion::GrowZoneProc(Size amountNeeded)
|
||||
{
|
||||
long freedMem = 0;
|
||||
|
||||
if (sMemoryReserve && *sMemoryReserve && sMemoryReserve != ::GZSaveHnd())
|
||||
{
|
||||
freedMem = ::GetHandleSize(sMemoryReserve);
|
||||
::EmptyHandle(sMemoryReserve);
|
||||
}
|
||||
|
||||
return freedMem;
|
||||
}
|
||||
|
||||
std::auto_ptr<nsMacMemoryCushion> gMemoryCushion;
|
||||
|
||||
Boolean nsMacMemoryCushion::EnsureMemoryCushion()
|
||||
{
|
||||
if (!gMemoryCushion.get())
|
||||
{
|
||||
nsMacMemoryCushion* softFluffyCushion = new nsMacMemoryCushion();
|
||||
if (!softFluffyCushion) return false;
|
||||
|
||||
OSErr err = softFluffyCushion->Init(nsMacMemoryCushion::kMemoryBufferSize, nsMacMemoryCushion::kMemoryReserveSize);
|
||||
if (err != noErr)
|
||||
{
|
||||
delete softFluffyCushion;
|
||||
return false;
|
||||
}
|
||||
|
||||
gMemoryCushion.reset(softFluffyCushion);
|
||||
softFluffyCushion->StartRepeating();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -38,12 +38,7 @@
|
||||
#ifndef TOOLKIT_H
|
||||
#define TOOLKIT_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "nsToolkitBase.h"
|
||||
#include "nsRepeater.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
/**
|
||||
* The toolkit abstraction is necessary because the message pump must
|
||||
@ -60,13 +55,7 @@
|
||||
*
|
||||
* All this has changed: the application now usually creates one copy of
|
||||
* the nsToolkit per window and the special widgets had to be moved
|
||||
* to the nsMacEventHandler. Also, to avoid creating several repeaters,
|
||||
* the NSPR event queue has been moved to a global object of its own:
|
||||
* the nsMacNSPREventQueueHandler declared below.
|
||||
*
|
||||
* If by any chance we support one day several threads for the UI
|
||||
* on the Mac, will have to create one instance of the NSPR
|
||||
* event queue per nsToolkit.
|
||||
* to the nsMacEventHandler.
|
||||
*/
|
||||
|
||||
#include <MacTypes.h>
|
||||
@ -87,9 +76,6 @@ public:
|
||||
nsToolkit();
|
||||
virtual ~nsToolkit();
|
||||
|
||||
// are there pending events on the toolkit's event queue?
|
||||
PRBool ToolkitBusy();
|
||||
|
||||
protected:
|
||||
|
||||
virtual nsresult InitEventQueue(PRThread * aThread);
|
||||
@ -114,74 +100,4 @@ protected:
|
||||
|
||||
static bool sInForeground;
|
||||
};
|
||||
|
||||
|
||||
class nsMacNSPREventQueueHandler : public Repeater
|
||||
{
|
||||
public:
|
||||
nsMacNSPREventQueueHandler();
|
||||
virtual ~nsMacNSPREventQueueHandler();
|
||||
|
||||
virtual void StartPumping();
|
||||
virtual PRBool StopPumping();
|
||||
|
||||
// Repeater interface
|
||||
virtual void RepeatAction(const EventRecord& inMacEvent);
|
||||
|
||||
PRBool EventsArePending();
|
||||
|
||||
protected:
|
||||
|
||||
void ProcessPLEventQueue();
|
||||
|
||||
protected:
|
||||
|
||||
nsrefcnt mRefCnt;
|
||||
};
|
||||
|
||||
|
||||
// class for low memory detection and handling
|
||||
class nsMacMemoryCushion : public Repeater
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
kMemoryBufferSize = 64 * 1024, // 64k reserve, purgeable handle purged first
|
||||
kMemoryReserveSize = 32 * 1024 // 32k memory reserve, freed by the GrowZoneProc
|
||||
};
|
||||
|
||||
nsMacMemoryCushion();
|
||||
~nsMacMemoryCushion();
|
||||
|
||||
OSErr Init(Size bufferSize, Size reserveSize);
|
||||
|
||||
|
||||
void RepeatAction(const EventRecord &aMacEvent);
|
||||
|
||||
protected:
|
||||
|
||||
// reallocate the memory buffer. Returns true on success
|
||||
Boolean RecoverMemoryBuffer(Size bufferSize);
|
||||
|
||||
// allocate or recover the memory reserve. Returns true on success
|
||||
Boolean RecoverMemoryReserve(Size reserveSize);
|
||||
|
||||
|
||||
static pascal long GrowZoneProc(Size amountNeeded);
|
||||
|
||||
public:
|
||||
|
||||
static Boolean EnsureMemoryCushion();
|
||||
|
||||
protected:
|
||||
|
||||
static Handle sMemoryReserve;
|
||||
|
||||
Handle mBufferHandle; // this is first to go
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // TOOLKIT_H
|
||||
|
Loading…
Reference in New Issue
Block a user