Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes
nsMacMessagePump Class Reference

#include <nsMacMessagePump.h>

Collaboration diagram for nsMacMessagePump:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsMacMessagePump (nsToolkit *aToolKit)
virtual ~nsMacMessagePump ()
PRBool ProcessEvents (PRBool aProcessEvents)
PRBool DispatchEvent (EventRecord *anEvent)

Protected Member Functions

PRBool DoMouseDown (EventRecord &anEvent)
PRBool DoMouseUp (EventRecord &anEvent)
PRBool DoMouseMove (EventRecord &anEvent)
PRBool DispatchOSEventToRaptor (EventRecord &anEvent, WindowPtr aWindow)

Static Protected Member Functions

static pascal OSStatus MouseClickEventHandler (EventHandlerCallRef aHandlerCallRef, EventRef aEvent, void *aUserData)
static pascal OSStatus WNETransitionEventHandler (EventHandlerCallRef aHandlerCallRef, EventRef aEvent, void *aUserData)

Protected Attributes

nsToolkitmToolkit
nsMacTSMMessagePumpmTSMMessagePump
EventHandlerRef mMouseClickEventHandler
EventHandlerRef mWNETransitionEventHandler
PRPackedBool mProcessEvents

Detailed Description

Definition at line 54 of file nsMacMessagePump.h.


Constructor & Destructor Documentation

Definition at line 68 of file nsMacMessagePump.cpp.

: mToolkit(aToolkit)
, mMouseClickEventHandler(NULL)
, mWNETransitionEventHandler(NULL)
, mProcessEvents(PR_FALSE)
{
  NS_ASSERTION(mToolkit, "No toolkit");
  
  // This list encompasses Carbon events that can be converted into
  // EventRecords, and that still require dispatch through
  // nsMacMessagePump::DispatchEvent because they haven't yet been converted
  // completetly to Carbon events.
  const EventTypeSpec kWNETransitionEventList[] = {
    { kEventClassMouse,       kEventMouseDown },
    { kEventClassMouse,       kEventMouseUp },
    { kEventClassMouse,       kEventMouseMoved },
    { kEventClassMouse,       kEventMouseDragged },
    { 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
  //
  nsMacTSMMessagePump* tsmMessagePump = nsMacTSMMessagePump::GetSingleton();
  NS_ASSERTION(tsmMessagePump, "Unable to create TSM Message Pump");
}

Here is the call graph for this function:

Definition at line 131 of file nsMacMessagePump.cpp.

Here is the call graph for this function:


Member Function Documentation

PRBool nsMacMessagePump::DispatchEvent ( EventRecord *  anEvent)

Definition at line 154 of file nsMacMessagePump.cpp.

{
  PRBool handled = PR_FALSE;

  if (!mProcessEvents)
    return handled;
  
  switch(anEvent->what) {
    // diskEvt is gone in Carbon, and so is unhandled here.
    // keyUp, keyDown, and autoKey now have Carbon event handlers in
    //  nsMacWindow.

    case mouseDown:
      handled = DoMouseDown(*anEvent);
      break;

    case mouseUp:
      handled = DoMouseUp(*anEvent);
      break;

    case osEvt: {
      unsigned char eventType = ((anEvent->message >> 24) & 0x00ff);
      if (eventType == mouseMovedMessage)
        handled = DoMouseMove(*anEvent);
      break;
    }
      
    case kHighLevelEvent:
      ::AEProcessAppleEvent(anEvent);
      handled = PR_TRUE;
      break;
  }

  return handled;
}

Here is the call graph for this function:

PRBool nsMacMessagePump::DispatchOSEventToRaptor ( EventRecord &  anEvent,
WindowPtr  aWindow 
) [protected]

Definition at line 431 of file nsMacMessagePump.cpp.

{
  PRBool handled = PR_FALSE;
  nsCOMPtr<nsIEventSink> sink;
  nsToolkit::GetWindowEventSink ( aWindow, getter_AddRefs(sink) );
  if ( sink )
    sink->DispatchEvent ( &anEvent, &handled );
  return handled;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsMacMessagePump::DoMouseDown ( EventRecord &  anEvent) [protected]

Definition at line 195 of file nsMacMessagePump.cpp.

{
  WindowPtr     whichWindow;
  WindowPartCode        partCode;
  PRBool  handled = PR_FALSE;
  
  partCode = ::FindWindow(anEvent.where, &whichWindow);
  
  switch (partCode)
  {
      case inNoWindow:
        break;

      case inCollapseBox:   // we never seem to get this.
      case inSysWindow:
        if ( gRollupListener && gRollupWidget )
          gRollupListener->Rollup();
        break;

      case inMenuBar:
      {
        // If a xul popup is displayed, roll it up and don't allow the click
        // through to the menu code. This is how MacOS context menus work, so
        // I think this is a valid solution.
        if ( gRollupListener && gRollupWidget )
        {
          gRollupListener->Rollup();
        }
        else
        {
          ::MenuSelect(anEvent.where);
          handled = PR_TRUE;
        }
        
        break;
      }

      case inContent:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);
        if ( IsWindowHilited(whichWindow) || (gRollupListener && gRollupWidget) )
          handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        else {
          nsCOMPtr<nsIWidget> topWidget;
          nsToolkit::GetTopWidget ( whichWindow, getter_AddRefs(topWidget) );
          nsCOMPtr<nsPIWidgetMac> macWindow ( do_QueryInterface(topWidget) );
          if ( macWindow ) {
            // a click occurred in a background window. Use WaitMouseMove() to determine if
            // it was a click or a drag. If it was a drag, send a drag gesture to the
            // background window. We don't need to rely on the ESM to track the gesture,
            // the OS has just told us.  If it was a click, bring it to the front like normal.
            Boolean initiateDragFromBGWindow = ::WaitMouseMoved(anEvent.where);
            if ( initiateDragFromBGWindow ) {
              nsCOMPtr<nsIEventSink> sink ( do_QueryInterface(topWidget) );
              if ( sink ) {
                // dispach a mousedown, an update event to paint any changes,
                // then the drag gesture event
                PRBool handled = PR_FALSE;
                sink->DispatchEvent ( &anEvent, &handled );
                
                EventRecord updateEvent = anEvent;
                updateEvent.what = updateEvt;
                updateEvent.message = NS_REINTERPRET_CAST(UInt32, whichWindow);
                sink->DispatchEvent ( &updateEvent, &handled );
                
                sink->DragEvent ( NS_DRAGDROP_GESTURE, anEvent.where.h, anEvent.where.v, 0L, &handled );                
              }
            }
            else {
              PRBool enabled;
              if (NS_SUCCEEDED(topWidget->IsEnabled(&enabled)) && !enabled)
                ::SysBeep(1);
              else
                macWindow->ComeToFront();
            }
            handled = PR_TRUE;
          }
        }
        break;
      }

      case inDrag:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);

        Point   oldTopLeft = {0, 0};
        ::LocalToGlobal(&oldTopLeft);
        
        // roll up popups BEFORE we start the drag
        if ( gRollupListener && gRollupWidget )
          gRollupListener->Rollup();

        Rect screenRect;
        ::GetRegionBounds(::GetGrayRgn(), &screenRect);
        ::DragWindow(whichWindow, anEvent.where, &screenRect);

        Point   newTopLeft = {0, 0};
        ::LocalToGlobal(&newTopLeft);

        // only activate if the command key is not down
        if (!(anEvent.modifiers & cmdKey))
        {
          nsCOMPtr<nsIWidget> topWidget;
          nsToolkit::GetTopWidget(whichWindow, getter_AddRefs(topWidget));
          
          nsCOMPtr<nsPIWidgetMac> macWindow ( do_QueryInterface(topWidget) );
          if ( macWindow )
            macWindow->ComeToFront();
        }
        
        // Dispatch the event because some windows may want to know that they have been moved.
        anEvent.where.h += newTopLeft.h - oldTopLeft.h;
        anEvent.where.v += newTopLeft.v - oldTopLeft.v;
        
        handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        break;
      }

      case inGrow:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);

        Rect sizeLimit;
        sizeLimit.top = kMinWindowHeight;
        sizeLimit.left = kMinWindowWidth;
        sizeLimit.bottom = 0x7FFF;
        sizeLimit.right = 0x7FFF;

        Rect newSize;
        ::ResizeWindow(whichWindow, anEvent.where, &sizeLimit, &newSize);

        Point newPt = botRight(newSize);
        ::LocalToGlobal(&newPt);
        newPt.h -= 8, newPt.v -= 8;
        anEvent.where = newPt;  // important!
        handled = DispatchOSEventToRaptor(anEvent, whichWindow);

        break;
      }

      case inGoAway:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);
        if (::TrackGoAway(whichWindow, anEvent.where)) {
          handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        }
        break;
      }

      case inZoomIn:
      case inZoomOut:
        if (::TrackBox(whichWindow, anEvent.where, partCode))
        {
          if (partCode == inZoomOut)
          {
            nsCOMPtr<nsIWidget> topWidget;
            nsToolkit::GetTopWidget ( whichWindow, getter_AddRefs(topWidget) );
            nsCOMPtr<nsPIWidgetMac> macWindow ( do_QueryInterface(topWidget) );
            if ( macWindow )
              macWindow->CalculateAndSetZoomedSize();
          }
          // !!!  Do not call ZoomWindow before calling DispatchOSEventToRaptor
          //    otherwise nsMacEventHandler::HandleMouseDownEvent won't get
          //    the right partcode for the click location
          
          handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        }
        break;

      case inToolbarButton:           // Mac OS X only
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);
        handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        break;

  }

  return handled;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsMacMessagePump::DoMouseMove ( EventRecord &  anEvent) [protected]

Definition at line 406 of file nsMacMessagePump.cpp.

{
  // same thing as DoMouseUp
  WindowPtr     whichWindow;
  PRInt16       partCode;
  PRBool        handled = PR_FALSE;
  
  partCode = ::FindWindow(anEvent.where, &whichWindow);
  if (whichWindow == nil)
    whichWindow = ::FrontWindow();

  /* Disable mouse moved events for windowshaded windows -- this prevents tooltips
     from popping up in empty space.
  */
  if (whichWindow == nil || !::IsWindowCollapsed(whichWindow))
    handled = DispatchOSEventToRaptor(anEvent, whichWindow);
  return handled;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsMacMessagePump::DoMouseUp ( EventRecord &  anEvent) [protected]

Definition at line 379 of file nsMacMessagePump.cpp.

{
    WindowPtr     whichWindow;
    PRInt16       partCode;

  partCode = ::FindWindow(anEvent.where, &whichWindow);
  if (whichWindow == nil)
  {
    // We need to report the event even when it happens over no window:
    // 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 = ::FrontWindow();
  }
  
  PRBool handled = DispatchOSEventToRaptor(anEvent, whichWindow);
  // consume mouse ups in the title bar, since nsMacWindow doesn't do that for us
  if (partCode == inDrag)
    handled = PR_TRUE;
  return handled;
}

Here is the call graph for this function:

Here is the caller graph for this function:

pascal OSStatus nsMacMessagePump::MouseClickEventHandler ( EventHandlerCallRef  aHandlerCallRef,
EventRef  aEvent,
void aUserData 
) [static, protected]

Definition at line 444 of file nsMacMessagePump.cpp.

{
  EventMouseButton button;
  OSErr err = ::GetEventParameter(aEvent, kEventParamMouseButton,
                                  typeMouseButton, NULL,
                                  sizeof(EventMouseButton), NULL, &button);

  // Only handle middle click events here.  Let the rest fall through.
  if (err != noErr || button != kEventMouseButtonTertiary)
    return eventNotHandledErr;

  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(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().
  eventRecord.message = NS_STATIC_CAST(UInt32, button);

  // Process the modified event internally
  nsMacMessagePump* self = NS_STATIC_CAST(nsMacMessagePump*, aUserData);
  PRBool handled = self->DispatchEvent(&eventRecord);

  if (handled)
    return noErr;

  return eventNotHandledErr;
}

Here is the caller graph for this function:

Definition at line 142 of file nsMacMessagePump.cpp.

{
  PRBool wasProcessing = mProcessEvents;
  mProcessEvents = aProcessEvents;
  return wasProcessing;
}
pascal OSStatus nsMacMessagePump::WNETransitionEventHandler ( EventHandlerCallRef  aHandlerCallRef,
EventRef  aEvent,
void aUserData 
) [static, protected]

Definition at line 492 of file nsMacMessagePump.cpp.

{
  nsMacMessagePump* self = NS_STATIC_CAST(nsMacMessagePump*, aUserData);

  EventRecord eventRecord;
  ::ConvertEventRefToEventRecord(aEvent, &eventRecord);

  PRBool handled = self->DispatchEvent(&eventRecord);

  if (!handled)
    return eventNotHandledErr;

  return noErr;
}

Here is the caller graph for this function:


Member Data Documentation

EventHandlerRef nsMacMessagePump::mMouseClickEventHandler [protected]

Definition at line 85 of file nsMacMessagePump.h.

Definition at line 87 of file nsMacMessagePump.h.

Definition at line 83 of file nsMacMessagePump.h.

Definition at line 84 of file nsMacMessagePump.h.

EventHandlerRef nsMacMessagePump::mWNETransitionEventHandler [protected]

Definition at line 86 of file nsMacMessagePump.h.


The documentation for this class was generated from the following files: