From d85affb0f55905bdeebaaca97b2e1dd72dad10a0 Mon Sep 17 00:00:00 2001 From: beard Date: Wed, 22 Apr 1998 02:10:33 +0000 Subject: [PATCH] Added FE_AllocateMenuID, and CPluginWindow wrapper class for top-level plugin windows. git-svn-id: svn://10.0.0.236/trunk@485 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/cmd/macfe/applevnt/mplugin.cp | 383 +++++++++++++++++++++++--- 1 file changed, 341 insertions(+), 42 deletions(-) diff --git a/mozilla/cmd/macfe/applevnt/mplugin.cp b/mozilla/cmd/macfe/applevnt/mplugin.cp index 8d8f3ea95e6..d8a068dbbdc 100644 --- a/mozilla/cmd/macfe/applevnt/mplugin.cp +++ b/mozilla/cmd/macfe/applevnt/mplugin.cp @@ -55,6 +55,8 @@ #include "MoreMixedMode.h" #include +#include "LMenuSharing.h" + // On a powerPC, plugins depend on being able to find qd in our symbol table #ifdef powerc #pragma export qd @@ -922,12 +924,221 @@ void FE_UnregisterWindow(void *plugin, void* window) ((CPluginView*)plugin)->UnregisterWindow(window); } +SInt16 FE_AllocateMenuID(void *plugin, XP_Bool isSubmenu) +{ + return ((CPluginView*)plugin)->AllocateMenuID(isSubmenu); +} + +// +// Rather than having to scan an explicit list of windows each time an event +// comes in, why not use a sub-class of LWindow, and let PowerPlant do the work +// for us? +// + +#pragma mark ### CPluginWindow ### + +class CPluginWindow : public LWindow, public LPeriodical { +public: + CPluginWindow(CPluginView* plugin, WindowPtr window); + virtual ~CPluginWindow(); + + virtual void HandleClick(const EventRecord& inMacEvent, Int16 inPart); + virtual void EventMouseUp(const EventRecord &inMacEvent); + virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam); + virtual Boolean HandleKeyPress(const EventRecord& inKeyEvent); + virtual void DrawSelf(); + virtual void SpendTime(const EventRecord& inMacEvent); + virtual void ActivateSelf(); + virtual void DeactivateSelf(); + virtual void AdjustCursorSelf(Point inPortPt, const EventRecord& inMacEvent); + +private: + CPluginView* mPlugin; + SInt16 mKind; +}; + +CPluginWindow::CPluginWindow(CPluginView* plugin, WindowPtr window) +{ + mPlugin = plugin; + mMacWindowP = window; + + // The following is cribbed from one of the LWindow constructors. + + // "bless" the plugin window so it will be considered to be a first-class PowerPlant window. + mKind = ::GetWindowKind(window); + ::SetWindowKind(window, PP_Window_Kind); + ::SetWRefCon(window, long(this)); + + // Set some default attributes. + SetAttribute(windAttr_CloseBox | windAttr_TitleBar | windAttr_Resizable + | windAttr_SizeBox | windAttr_Targetable | windAttr_Enabled); + + // Window Frame and Image are the same as its portRect. + short width = mMacWindowP->portRect.right - mMacWindowP->portRect.left; + short height = mMacWindowP->portRect.bottom - mMacWindowP->portRect.top; + + ResizeFrameTo(width, height, false); + ResizeImageTo(width, height, false); + + CalcRevealedRect(); + + // Initial size and location are the "user" state for zooming. + CalcPortFrameRect(mUserBounds); + PortToGlobalPoint(topLeft(mUserBounds)); + PortToGlobalPoint(botRight(mUserBounds)); + + mVisible = triState_Off; + mActive = triState_Off; + mEnabled = triState_Off; + if (HasAttribute(windAttr_Enabled)) { + mEnabled = triState_On; + } + + FocusDraw(); + ::GetForeColor(&mForeColor); + ::GetBackColor(&mBackColor); + + StartIdling(); +} + +CPluginWindow::~CPluginWindow() +{ + // prevent the LWindow destructor from clobbering the window. + if (mMacWindowP != NULL) { + WindowPtr window = mMacWindowP; + if (IsWindowVisible(window)) + HideSelf(); + + // Restore kind and refCon to original values. + ::SetWindowKind(window, mKind); + ::SetWRefCon(window, 0); + + mMacWindowP = NULL; + } +} + +void CPluginWindow::HandleClick(const EventRecord& inMacEvent, Int16 inPart) +{ + EventRecord mouseEvent = inMacEvent; + if (!mPlugin->PassWindowEvent(mouseEvent, mMacWindowP)) + LWindow::HandleClick(inMacEvent, inPart); +} + +void CPluginWindow::EventMouseUp(const EventRecord& inMouseUp) +{ + EventRecord mouseEvent = inMouseUp; + mPlugin->PassWindowEvent(mouseEvent, mMacWindowP); +} + +Boolean CPluginWindow::ObeyCommand(CommandT inCommand, void *ioParam) +{ + if (mPlugin->IsPluginCommand(inCommand)) { + // assume this is a plugin menu item, since menusharing didn't handle it. + EventRecord menuEvent; + ::OSEventAvail(0, &menuEvent); + menuEvent.what = menuCommandEvent; + menuEvent.message = -inCommand; // PowerPlant encodes a raw menu selection as the negation of the selection. + return mPlugin->PassWindowEvent(menuEvent, mMacWindowP); + } +#if 0 + if (inCommand == cmd_Close) { + HideSelf(); + return true; + } +#endif + return LWindow::ObeyCommand(inCommand, ioParam); +} + +Boolean CPluginWindow::HandleKeyPress(const EventRecord& inKeyEvent) +{ + EventRecord keyEvent = inKeyEvent; + return mPlugin->PassWindowEvent(keyEvent, mMacWindowP); +} + + +void CPluginWindow::DrawSelf() +{ + EventRecord updateEvent; + ::OSEventAvail(0, &updateEvent); + updateEvent.what = updateEvt; + updateEvent.message = UInt32(mMacWindowP); + mPlugin->PassWindowEvent(updateEvent, mMacWindowP); +} + +void CPluginWindow::SpendTime(const EventRecord& inMacEvent) +{ + // Need to poll various states, because the plugin can change things like + // the window's visibility, size, etc. + + // Put the visible state in synch with the window's visibility. + mVisible = (IsWindowVisible(mMacWindowP) ? triState_On : triState_Off); + + // Make sure the window's size hasn't changed (what about location?) + short width = mMacWindowP->portRect.right - mMacWindowP->portRect.left; + short height = mMacWindowP->portRect.bottom - mMacWindowP->portRect.top; + if (mFrameSize.width != width || mFrameSize.height != height) { + ResizeFrameTo(width, height, false); + ResizeImageTo(width, height, false); + CalcRevealedRect(); + } + + EventRecord macEvent = inMacEvent; + mPlugin->PassWindowEvent(macEvent, mMacWindowP); + + // + // If weÕre in SpendTime because of a non-null event, send a + // null event too. Some plug-ins (e.g. Shockwave) rely on null + // events for animation, so it doesnÕt matter if weÕre giving + // them lots of time with mouseMoved or other events -- if they + // donÕt get null events, they donÕt animate fast. + // + if (macEvent.what != nullEvent) { + macEvent.what = nullEvent; + mPlugin->PassWindowEvent(macEvent, mMacWindowP); + } +} + +void CPluginWindow::ActivateSelf() +{ + LWindow::ActivateSelf(); + + EventRecord activateEvent; + ::OSEventAvail(0, &activateEvent); + activateEvent.what = activateEvt; + activateEvent.modifiers |= activeFlag; + activateEvent.message = UInt32(mMacWindowP); + mPlugin->PassWindowEvent(activateEvent, mMacWindowP); +} + + +void CPluginWindow::DeactivateSelf() +{ + LWindow::DeactivateSelf(); + + EventRecord activateEvent; + ::OSEventAvail(0, &activateEvent); + activateEvent.what = activateEvt; + activateEvent.modifiers &= ~activeFlag; + activateEvent.message = UInt32(mMacWindowP); + mPlugin->PassWindowEvent(activateEvent, mMacWindowP); +} + +void CPluginWindow::AdjustCursorSelf(Point inPortPt, const EventRecord& inMacEvent) +{ + EventRecord cursorEvent = inMacEvent; + cursorEvent.what = adjustCursorEvent; + if (!mPlugin->PassWindowEvent(cursorEvent, mMacWindowP)) + LWindow::AdjustCursorSelf(inPortPt, inMacEvent); +} + + // ************************************************************************************* // // CPluginView methods // // ************************************************************************************* +#pragma mark ### CPluginView ### CPluginView* CPluginView::sPluginTarget = NULL; LArray* CPluginView::sPluginList = NULL; @@ -950,6 +1161,8 @@ void CPluginView::BroadcastPluginEvent(const EventRecord& event) } } +// XXX The following two methods are obsolete -- CPluginWindow now does the work. + // This gets called for every event - a performance analysis/review would be good Boolean CPluginView::PluginWindowEvent(const EventRecord& event) { @@ -980,74 +1193,142 @@ Boolean CPluginView::PluginWindowEvent(const EventRecord& event) default: return false; } - - if(sPluginList != NULL) - { - // iterate through each plugin instance - LArrayIterator pluginIterator(*sPluginList); - CPluginView* plugin = NULL; - while (pluginIterator.Next(&plugin)) - { - if(plugin->fWindowList != NULL) - { - // then iterate through each window for each instance - LArrayIterator windowIterator(*(plugin->fWindowList)); - WindowPtr window = NULL; - while(windowIterator.Next(&window)) - { - if(window == hitWindow) - { - EventRecord eventCopy = event; - return plugin->PassWindowEvent(eventCopy, window); - } - } - } + +#if 1 + // Determine which plugin owns this window. + Boolean isActivateEvent = (event.what == activateEvt && (event.modifiers & activeFlag)); + CPluginView* owningPlugin = FindPlugin(hitWindow); + if (owningPlugin != NULL) { + EventRecord eventCopy = event; + return owningPlugin->PassWindowEvent(eventCopy, hitWindow); + } +#else + if (sPluginList != NULL) { + // iterate through each plugin instance + LArrayIterator pluginIterator(*sPluginList); + CPluginView* plugin = NULL; + while (pluginIterator.Next(&plugin)) { + if (plugin->fWindowList != NULL) { + // then iterate through each window for each instance + LArrayIterator windowIterator(*(plugin->fWindowList)); + WindowPtr window = NULL; + while (windowIterator.Next(&window)) { + if (window == hitWindow) { + EventRecord eventCopy = event; + return plugin->PassWindowEvent(eventCopy, window); + } } + } } + } +#endif // we didn't find a match return false; } +// Determines which plugin owns the specified window. + +CPluginView* CPluginView::FindPlugin(WindowPtr window) +{ + // Make sure the window isn't a PowerPlant window. + LWindow* windowObj = LWindow::FetchWindowObject(window); + if (windowObj == NULL && sPluginList != NULL) { + // iterate through each plugin instance + LArrayIterator pluginIterator(*sPluginList); + CPluginView* plugin = NULL; + while (pluginIterator.Next(&plugin)) { + if (plugin->fWindowList != NULL) { + // then iterate through each window for each instance + LArrayIterator windowIterator(*(plugin->fWindowList)); + WindowPtr pluginWindow = NULL; + while (windowIterator.Next(&pluginWindow)) { + if (window == pluginWindow) + return plugin; + } + } + } + } + return NULL; +} + void CPluginView::RegisterWindow(void* window) { - if(fWindowList == NULL) + // Register the pluginWindow with PowerPlant. + + // Set the default commander to the application, to limit the depth of the chain of command. + // I've seen this get ridiculously deep. + LCommander::LCommander::SetDefaultCommander(LCommander::GetTopCommander()); + CPluginWindow* pluginWindow = new CPluginWindow(this, WindowPtr(window)); + +#if 0 + if (fWindowList == NULL) fWindowList = new LArray; - if(fWindowList != NULL) + if (fWindowList != NULL) fWindowList->InsertItemsAt(1, 0, &window); +#endif } void CPluginView::UnregisterWindow(void* window) { - if (fWindowList != NULL) - { + // Toss the pluginWindow itself. + LWindow* pluginWindow = LWindow::FetchWindowObject(WindowPtr(window)); + if (pluginWindow != NULL) { + // Notify PowerPlant that the window is no longer active. + pluginWindow->Deactivate(); + delete pluginWindow; + } + +#if 0 + if (fWindowList != NULL) { Int32 index = fWindowList->FetchIndexOf(&window); if (index > 0) fWindowList->RemoveItemsAt(1, index); - if (fWindowList->GetCount() == 0) - { + if (fWindowList->GetCount() == 0) { delete fWindowList; fWindowList = NULL; } } +#endif +} + + +SInt16 CPluginView::AllocateMenuID(Boolean isSubmenu) +{ + SInt16 menuID = LMenuSharingAttachment::AllocatePluginMenuID(isSubmenu); + + if (fMenuList == NULL) + fMenuList = new TArray; + if (fMenuList != NULL) + fMenuList->AddItem(menuID); + + return menuID; +} + +Boolean CPluginView::IsPluginCommand(CommandT inCommand) +{ + // Since only one plugin can have menus in the menu bar at a time, + // the test only checks to see if this plugin has any menus, and + // whether the command is synthetic and is from one of the plugin's menus. + if (fMenuList != NULL) { + short menuId, menuItem; + if (LCommander::IsSyntheticCommand(inCommand, menuId, menuItem)) { + TArray& menus = *fMenuList; + UInt32 count = menus.GetCount(); + for (UInt32 i = count; i > 0; --i) + if (menus[i] == menuId) + return true; + } + } + return false; } Boolean CPluginView::PassWindowEvent(EventRecord& inEvent, WindowPtr window) { Boolean eventHandled = false; if (fApp) { - // Treat update events specially, need to use BeginUpdate to clear the event. - if (inEvent.what == updateEvt) { - GrafPtr oldPort; - ::GetPort(&oldPort); - ::SetPort(window); - ::BeginUpdate(window); - eventHandled = NPL_HandleEvent(fApp, (NPEvent*)&inEvent, (void*) window); - ::EndUpdate(window); - ::SetPort(oldPort); - } else - eventHandled = NPL_HandleEvent(fApp, (NPEvent*)&inEvent, (void*) window); + eventHandled = NPL_HandleEvent(fApp, (NPEvent*)&inEvent, (void*) window); } return eventHandled; } @@ -1063,6 +1344,7 @@ CPluginView::CPluginView(LStream *inStream) : LView(inStream), LDragAndDrop(nil, fBrokenIcon = NULL; fIsPrinting = false; fWindowList = NULL; + fMenuList = NULL; // // Add the new plug-in to a global list of all plug-ins. @@ -1094,13 +1376,17 @@ CPluginView::~CPluginView() CPluginView::sPluginTarget = NULL; // we're assuming the plugin has already killed the windows themselves - if(fWindowList != NULL) + if (fWindowList != NULL) delete fWindowList; + + // release the menu IDs used by this plugin? + if (fMenuList != NULL) + delete fMenuList; + // // Remove the deleted plug-in from the global list of all plug-ins. // - if (sPluginList != NULL) - { + if (sPluginList != NULL) { Int32 index = sPluginList->FetchIndexOf(&this); if (index > 0) sPluginList->RemoveItemsAt(1, index); @@ -1362,6 +1648,19 @@ void CPluginView::EventMouseUp(const EventRecord& inMouseUp) } +Boolean CPluginView::ObeyCommand(CommandT inCommand, void *ioParam) +{ + if (IsPluginCommand(inCommand)) { + // assume this is a plugin menu item, since menusharing didn't handle it. + EventRecord menuEvent; + ::memset(&menuEvent, 0, sizeof(EventRecord)); + menuEvent.what = menuCommandEvent; + menuEvent.message = -inCommand; // PowerPlant encodes a raw menu selection as the negation of the selection. + return PassEvent(menuEvent); + } + return LCommander::ObeyCommand(inCommand, ioParam); +} + Boolean CPluginView::HandleKeyPress(const EventRecord& inKeyEvent) { if (fWindowed) {