405 lines
10 KiB
C++
405 lines
10 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "nsMacEventHandler.h"
|
|
#include "prinrval.h"
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// nsMacEventHandler constructor/destructor
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsMacEventHandler::nsMacEventHandler(nsWindow* aTopLevelWidget)
|
|
{
|
|
mTopLevelWidget = aTopLevelWidget;
|
|
mLastWidgetHit = nsnull;
|
|
mLastWidgetPointed = nsnull;
|
|
}
|
|
|
|
|
|
nsMacEventHandler::~nsMacEventHandler()
|
|
{
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// HandleOSEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleOSEvent(
|
|
EventRecord& aOSEvent)
|
|
{
|
|
PRBool retVal = PR_FALSE;
|
|
|
|
switch (aOSEvent.what)
|
|
{
|
|
case keyUp:
|
|
case keyDown:
|
|
case autoKey:
|
|
retVal = HandleKeyEvent(aOSEvent);
|
|
break;
|
|
|
|
case activateEvt:
|
|
retVal = HandleActivateEvent(aOSEvent);
|
|
break;
|
|
|
|
case updateEvt:
|
|
retVal = HandleUpdateEvent(aOSEvent);
|
|
break;
|
|
|
|
case mouseDown:
|
|
retVal = HandleMouseDownEvent(aOSEvent);
|
|
break;
|
|
|
|
case mouseUp:
|
|
retVal = HandleMouseUpEvent(aOSEvent);
|
|
break;
|
|
|
|
case osEvt:
|
|
case nullEvent:
|
|
retVal = HandleMouseMoveEvent(aOSEvent);
|
|
break;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Handle Menu commands
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleMenuCommand(
|
|
EventRecord& aOSEvent,
|
|
long aMenuResult)
|
|
{
|
|
// get focused widget
|
|
nsWindow* focusedWidget = mTopLevelWidget;
|
|
|
|
//¥TODO: should get the focus from the toolkit and
|
|
// propagate the event all the way up to the window
|
|
// if it's not handled by the different parents
|
|
|
|
|
|
// nsEvent
|
|
nsMenuEvent menuEvent;
|
|
menuEvent.eventStructType = NS_MENU_EVENT;
|
|
menuEvent.message = NS_MENU_SELECTED;
|
|
menuEvent.point.x = aOSEvent.where.h;
|
|
menuEvent.point.y = aOSEvent.where.v;
|
|
menuEvent.time = PR_IntervalNow();
|
|
|
|
// nsGUIEvent
|
|
menuEvent.widget = focusedWidget;
|
|
menuEvent.nativeMsg = (void*)&aOSEvent;
|
|
|
|
// nsMenuEvent
|
|
menuEvent.mMenuItem = nsnull; //¥TODO: initialize mMenuItem
|
|
menuEvent.mCommand = aMenuResult;
|
|
|
|
return (focusedWidget->DispatchWindowEvent(menuEvent));
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// HandleKeyEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleKeyEvent(EventRecord& aOSEvent)
|
|
{
|
|
// get the focused widget
|
|
nsWindow* focusedWidget = nsnull;
|
|
nsToolkit* toolkit = (nsToolkit*)mTopLevelWidget->GetToolkit();
|
|
if (toolkit)
|
|
{
|
|
focusedWidget = toolkit->GetFocus();
|
|
NS_RELEASE(toolkit);
|
|
}
|
|
|
|
if (focusedWidget == nsnull)
|
|
focusedWidget = mTopLevelWidget;
|
|
|
|
// nsEvent
|
|
nsKeyEvent keyEvent;
|
|
keyEvent.eventStructType = NS_KEY_EVENT;
|
|
switch (aOSEvent.what)
|
|
{
|
|
case keyUp: keyEvent.message = NS_KEY_UP; break;
|
|
case keyDown: keyEvent.message = NS_KEY_DOWN; break;
|
|
case autoKey: keyEvent.message = NS_KEY_DOWN; break;
|
|
}
|
|
keyEvent.point.x = 0;
|
|
keyEvent.point.y = 0;
|
|
keyEvent.time = PR_IntervalNow();
|
|
|
|
// nsGUIEvent
|
|
keyEvent.widget = focusedWidget;
|
|
keyEvent.nativeMsg = (void*)&aOSEvent;
|
|
|
|
// nsInputEvent
|
|
keyEvent.isShift = ((aOSEvent.modifiers & shiftKey) != 0);
|
|
keyEvent.isControl = ((aOSEvent.modifiers & controlKey) != 0);
|
|
keyEvent.isAlt = ((aOSEvent.modifiers & optionKey) != 0);
|
|
|
|
// nsKeyEvent
|
|
keyEvent.keyCode = (aOSEvent.message & charCodeMask); //¥TODO: do special keys conversions for NS_VK_F1 etc...
|
|
|
|
return(focusedWidget->DispatchWindowEvent(keyEvent));
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// HandleActivateEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleActivateEvent(EventRecord& aOSEvent)
|
|
{
|
|
Boolean isActive = ((aOSEvent.modifiers & activeFlag) != 0);
|
|
if (isActive)
|
|
{
|
|
// get focused widget
|
|
nsWindow* focusedWidget = mTopLevelWidget;
|
|
nsIMenuBar* menuBar = focusedWidget->GetMenuBar();
|
|
//¥TODO: should get the focus from the toolkit and
|
|
// look all the way up to the window
|
|
// until one of the parents has a menubar
|
|
|
|
//¥TODO: set the menu bar here
|
|
}
|
|
return PR_TRUE;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// HandleUpdateEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleUpdateEvent(EventRecord& aOSEvent)
|
|
{
|
|
mTopLevelWidget->Update();
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// HandleMouseDownEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleMouseDownEvent(
|
|
EventRecord& aOSEvent)
|
|
{
|
|
PRBool retVal = PR_FALSE;
|
|
|
|
WindowPtr whichWindow;
|
|
short partCode = ::FindWindow(aOSEvent.where, &whichWindow);
|
|
|
|
switch (partCode)
|
|
{
|
|
case inDrag:
|
|
{
|
|
Point macPoint;
|
|
macPoint = topLeft(whichWindow->portRect);
|
|
::LocalToGlobal(&macPoint);
|
|
mTopLevelWidget->Move(macPoint.h, macPoint.v);
|
|
break;
|
|
}
|
|
|
|
case inGrow:
|
|
{
|
|
Rect macRect = whichWindow->portRect;
|
|
::LocalToGlobal(&topLeft(macRect));
|
|
::LocalToGlobal(&botRight(macRect));
|
|
mTopLevelWidget->Resize(macRect.right - macRect.left, macRect.bottom - macRect.top, PR_FALSE);
|
|
break;
|
|
}
|
|
|
|
case inGoAway:
|
|
{
|
|
mTopLevelWidget->Destroy();
|
|
break;
|
|
}
|
|
|
|
case inContent:
|
|
{
|
|
nsMouseEvent mouseEvent;
|
|
ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_LEFT_BUTTON_DOWN);
|
|
nsWindow* widgetHit = (nsWindow*)mouseEvent.widget;
|
|
if (widgetHit)
|
|
{
|
|
// set the focus on the widget hit
|
|
nsToolkit* toolkit = (nsToolkit*)widgetHit->GetToolkit();
|
|
if (toolkit)
|
|
{
|
|
toolkit->SetFocus(widgetHit);
|
|
NS_RELEASE(toolkit);
|
|
}
|
|
|
|
// dispatch the event
|
|
retVal = widgetHit->DispatchMouseEvent(mouseEvent);
|
|
}
|
|
mLastWidgetHit = widgetHit;
|
|
break;
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// HandleMouseUpEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleMouseUpEvent(
|
|
EventRecord& aOSEvent)
|
|
{
|
|
PRBool retVal = PR_FALSE;
|
|
|
|
nsMouseEvent mouseEvent;
|
|
ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_LEFT_BUTTON_UP);
|
|
|
|
nsWindow* widgetReleased = (nsWindow*)mouseEvent.widget;
|
|
if ((widgetReleased != nsnull) && (widgetReleased != mLastWidgetHit))
|
|
retVal |= widgetReleased->DispatchMouseEvent(mouseEvent);
|
|
|
|
if (mLastWidgetHit != nsnull)
|
|
{
|
|
retVal |= mLastWidgetHit->DispatchMouseEvent(mouseEvent);
|
|
mLastWidgetHit = nsnull;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// HandleMouseMoveEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsMacEventHandler::HandleMouseMoveEvent(
|
|
EventRecord& aOSEvent)
|
|
{
|
|
PRBool retVal = PR_FALSE;
|
|
|
|
nsMouseEvent mouseEvent;
|
|
ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_MOVE);
|
|
|
|
nsWindow* widgetPointed = (nsWindow*)mouseEvent.widget;
|
|
if (widgetPointed != mLastWidgetPointed)
|
|
{
|
|
if (mLastWidgetPointed != nsnull)
|
|
{
|
|
mouseEvent.widget = mLastWidgetPointed;
|
|
mouseEvent.message = NS_MOUSE_EXIT;
|
|
retVal |= mLastWidgetPointed->DispatchMouseEvent(mouseEvent);
|
|
mLastWidgetPointed = nsnull;
|
|
mouseEvent.widget = widgetPointed;
|
|
}
|
|
if (widgetPointed != nsnull)
|
|
{
|
|
mouseEvent.message = NS_MOUSE_ENTER;
|
|
retVal |= widgetPointed->DispatchMouseEvent(mouseEvent);
|
|
mLastWidgetPointed = widgetPointed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (widgetPointed != nsnull)
|
|
retVal |= widgetPointed->DispatchMouseEvent(mouseEvent);
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// ConvertOSEventToMouseEvent
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsMacEventHandler::ConvertOSEventToMouseEvent(
|
|
EventRecord& aOSEvent,
|
|
nsMouseEvent& aMouseEvent,
|
|
PRUint32 aMessage)
|
|
{
|
|
static long lastWhen = 0;
|
|
static Point lastWhere = {0, 0};
|
|
static short lastClickCount = 0;
|
|
|
|
// get the click count
|
|
if (((aOSEvent.when - lastWhen) < ::LMGetDoubleTime())
|
|
&& (abs(aOSEvent.where.h - lastWhere.h) < 5)
|
|
&& (abs(aOSEvent.where.v - lastWhere.v) < 5))
|
|
{
|
|
if (aOSEvent.what == mouseDown)
|
|
lastClickCount ++;
|
|
}
|
|
else
|
|
{
|
|
if (! ::StillDown())
|
|
lastClickCount = 0;
|
|
}
|
|
lastWhen = aOSEvent.when;
|
|
lastWhere = aOSEvent.where;
|
|
|
|
// get the widget hit and its hit point
|
|
Point hitPoint = aOSEvent.where;
|
|
::SetOrigin(0, 0);
|
|
::GlobalToLocal(&hitPoint);
|
|
nsPoint widgetHitPoint(hitPoint.h, hitPoint.v);
|
|
|
|
nsWindow* widgetHit = mTopLevelWidget->FindWidgetHit(hitPoint);
|
|
if (widgetHit)
|
|
{
|
|
nsRect bounds;
|
|
widgetHit->GetBounds(bounds);
|
|
nsPoint widgetOrigin(bounds.x, bounds.y);
|
|
widgetHit->LocalToWindowCoordinate(widgetOrigin);
|
|
widgetHitPoint.MoveBy(-widgetOrigin.x, -widgetOrigin.y);
|
|
}
|
|
|
|
// nsEvent
|
|
aMouseEvent.eventStructType = NS_MOUSE_EVENT;
|
|
aMouseEvent.message = aMessage;
|
|
aMouseEvent.point = widgetHitPoint;
|
|
aMouseEvent.time = PR_IntervalNow();
|
|
|
|
// nsGUIEvent
|
|
aMouseEvent.widget = widgetHit;
|
|
aMouseEvent.nativeMsg = (void*)&aOSEvent;
|
|
|
|
// nsInputEvent
|
|
aMouseEvent.isShift = ((aOSEvent.modifiers & shiftKey) != 0);
|
|
aMouseEvent.isControl = ((aOSEvent.modifiers & controlKey) != 0);
|
|
aMouseEvent.isAlt = ((aOSEvent.modifiers & optionKey) != 0);
|
|
|
|
// nsMouseEvent
|
|
aMouseEvent.clickCount = lastClickCount;
|
|
}
|