/* -*- 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; }