How to get mouse events in fullscreen AGL?

DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #1
Carbon.
I am curious how to get mouse events in fullscreen mode, since I would normally get it with my window's event handler. In fullscreen AGL, it seems like I have no window, ergo no window event handler.

Apple's fullscreen example uses a polling event loop, which I don't want to do, since I use the Carbon event model for windowed OpenGL.

Any ideas? I have not found anything on this in the dev docs.
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #2
I've been working on something similar that I want to upload as sample code when I am done. Just do something like this:

Code:
EventHandlerRef        gMouseEventHandlerRef        = NULL;

OSStatus    ErrCode;


    // Mouse Events (Sent before the tab control switches its control value):
    static const EventTypeSpec mouseControlEvents[] =
    {
    { kEventClassMouse,        kEventMouseDown },
    { kEventClassMouse,        kEventMouseUp },
    { kEventClassMouse,        kEventMouseMoved },
    { kEventClassMouse,        kEventMouseDragged },
    { kEventClassMouse,        kEventMouseEntered },
    { kEventClassMouse,        kEventMouseExited },
    { kEventClassMouse,        kEventMouseWheelMoved }
    };
    
    ErrCode = InstallEventHandler( GetApplicationEventTarget(), NewEventHandlerUPP( MouseEventHandlerProc ), GetEventTypeCount(mouseControlEvents), mouseControlEvents, 0, &gMouseEventHandlerRef );

    if ( ErrCode != noErr ) FatalAlert( "Error in InitializeCarbonEvents(): Unable to install Mouse Event handler.", (int) ErrCode );

and then

Code:
static pascal OSStatus MouseEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData )
{
   //UInt32    eventClass    = GetEventClass( inEvent );
    UInt32    eventKind     = GetEventKind( inEvent );
    //EventTime    timeInSeconds = GetEventTime( inEvent );
    //EventTime    currentTime   = GetCurrentEventTime(); // Seconds since system startup.

    //EventRecord event;
    //Boolean     ConvertEventRefToEventRecord( EventRef inEvent, EventRecord event );

    Point    where;
    
    switch(eventKind)
    {
        case kEventMouseDown:        // A mouse button was pressed.

            printf("MouseDown.\n");
            
            GetEventParameter( inEvent, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &where );

            // kEventMouseButtonPrimary   -- Left button.
            // kEventMouseButtonSecondary -- Right button.
            // kEventMouseButtonTertiary  -- Middle button.

            // kEventParamMouseLocation (display coordinates), kEventParamWindowMouseLocation (window coordinates).

            //UInt32 GetCurrentEventButtonState(void);
            //Bit zero indicates the state of the primary button, bit one the state of the secondary button, and so on.
                
            break;

        case kEventMouseUp:        // A mouse button was released.

            printf("MouseUp.\n");
            
            break;

        case kEventMouseMoved:        // The mouse was moved.

           // printf("MouseMoved.\n");

            GetEventParameter( inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &where );
            GetEventParameter( inEvent, kEventParamMouseDelta, typeQDPoint, NULL, sizeof(Point), NULL, &where );

            break;

        case kEventMouseDragged:    // The mouse was moved, and a button was down.

            printf("MouseDragged.\n");
            
            break;

        case kEventMouseEntered:    // The mouse entered a tracking area.

            printf("MouseEntered.\n");
            
            break;

        case kEventMouseExited:        // The mouse exited a tracking area.

            printf("MouseExited.\n");
            
            break;

        case kEventMouseWheelMoved:    // The mouse wheel was moved. (Mac OS X only)

            printf("MouseWheelMoved.\n");

            //kEventMouseWheelAxisX -- The X axis (left or right).
            //kEventMouseWheelAxisY -- The Y axis (up or down).
            
            break;
    };

    return( eventNotHandledErr ); // Use default handlers for things like kHICommandBringAllToFront.
}

When you are done with your application, release the mouse event handler:

Code:
RemoveEventHandler( gMouseEventHandlerRef );

You can do that for windows events, application events, control and menu events and so on.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #3
So you say my application event handler can recieve mouse events? I haven't been able to do that, that's why I have posted in the first place. Only my window event handler recieved mouse events, the app event handler did not, even though I registered it to recieve them. Hmm. I will look into it, maybe the App does receive the events if the window handler is not registered for it...

I've been looking through the darn Carbon documentation all day trying to find a clue. I want to know what the logic behind this is.
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #4
Make sure that you have set this at the end of your window event handler, otherwise the event won't propagate until it reaches the mouse event handler.

Code:
return( eventNotHandledErr );

In addition, if you block this return error code, the window won't benefit from the standard behaviors. The documention is fragmented among several documents located in different parts of the Apple developer web-site. It was a pain to find everything I needed to make it work.

If you are working in fullscreen mode, you can use these:

Code:
// Window Events for FullScreen Diplay Capture application (Sent before the tab control switches its control value):
    static const EventTypeSpec windowControlEvents[] =
    {
    { kEventClassWindow, kEventWindowUpdate },
    { kEventClassWindow, kEventWindowDrawContent },
    { kEventClassWindow, kEventWindowActivated },
    { kEventClassWindow, kEventWindowDeactivated },
    { kEventClassWindow, kEventWindowGetClickActivation },
    { kEventClassWindow, kEventWindowBoundsChanging },
    { kEventClassWindow, kEventWindowBoundsChanged },
    { kEventClassWindow, kEventWindowShown },
    { kEventClassWindow, kEventWindowShowing },
    { kEventClassWindow, kEventWindowHidden },
    { kEventClassWindow, kEventWindowHiding },
    { kEventClassWindow, kEventWindowResizeStarted },
    { kEventClassWindow, kEventWindowResizeCompleted },
    { kEventClassWindow, kEventWindowDragStarted },
    { kEventClassWindow, kEventWindowDragCompleted },
    { kEventClassWindow, kEventWindowCursorChange },
    { kEventClassWindow, kEventWindowClosed }
    };

    ErrCode = InstallEventHandler( GetApplicationEventTarget(), NewEventHandlerUPP( WindowEventHandlerProc ), GetEventTypeCount(windowControlEvents), windowControlEvents, 0, &gMainWindowEventHandlerRef );

    if ( ErrCode != noErr ) FatalAlert( "Error in InitializeCarbonEvents(): Unable to install Window Event handler.", (int) ErrCode );

Code:
static pascal OSStatus WindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData )
{
    //UInt32    eventClass = GetEventClass( inEvent );
    UInt32    eventKind  = GetEventKind( inEvent );

    //EventRecord event;
    //Boolean     ConvertEventRefToEventRecord( EventRef inEvent, EventRecord *event );

    //short    part;
    //Rect    tempRect;
    WindowRef    whichWindow;

    GetEventParameter( inEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &whichWindow );
    
    //part = FindWindow(event.where, &whichWindow);

    switch(eventKind)
    {
        case kEventWindowUpdate:

            /*
             Low-level update event. Sent to any window that needs updating regardless of whether
             the window has the standard window handler installed. You must call the Window Manager
             function BeginUpdate, and the QuickDraw function SetPort before drawing your window
             content, then call EndUpdate when you are finished.

             The standard window handler for this event calls BeginUpdate and SetPort, sends a
             kEventWindowDrawContent event to the window, and then calls EndUpdate.

             Note that this event is sent directly to the window target. If no handler takes the
             event (that is, they all return eventNotHandledErr), then the Window Manager posts this
             event to the event queue. Doing so allows the Carbon Event Manager to convert the event
             into an old-style event record (EventRecord), to be returned from WaitNextEvent.
             */

            printf("WindowUpdate.\n");
              
            break;

        case kEventWindowDrawContent:

            /*
             Higher-level update event sent only if you have the standard window handler installed.
             Functions exactly as kEventWindowUpdate, except that the Carbon Event Manager calls
             Begin/EndUpdate and SetPort for you (QuickDraw). All you need to do is draw the window content.

             The standard window handler calls DrawControls for this window.
             */

            printf("WindowDrawContent.\n");

            break;

        case kEventWindowPaint:

            /*
             Sent when it is time to draw the entire window (such as when the window is first displayed).
             This is a convenience event that gives you a chance to draw all the window elements at once.

             If you do not handle this event, the Window Manager sends the kEventWindowDrawFrame event to
             your window and erases the content region to its background color.

             Available in Mac OS X only.
             */

            printf("kEventWindowPaint.\n");

            break;
            // etc - for all other registered events...
    };

    return( eventNotHandledErr ); // Use default handlers for things like kHICommandBringAllToFront.
}
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #5
Well, well, this is really not doing what it should. I registered the app event handler ONLY for mouse events, its not getting them. checked that eventNotHandled is returned everywhere, correctly, it is.

I tried without even registering a window event handler, still same results. Strange. Though, this was not in fullscreen mode. I will tinker with this later, I have other things to do, too.
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #6
I've just uploaded the source I've been working on. There's just one AIFF file missing (not used anyway), but you should be able to compile it with ProjectBuilder right away.

It's a 1.2 Mb download. Here's the address: http://home.earthlink.net/~yexirocks/MyGameSource.dmg

Let me know if this works for you.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #7
Well, I figured it out...I...forgot...to...darn, this was really stupid. I forgot to pass the userData pointer to the InstallEventHandler() function...when the userData points to my application object.

Thanks for all the help, though.
Quote this message in a reply
Member
Posts: 156
Joined: 2002.11
Post: #8
That's OK. It's not as bad as:

Code:
AudioBufferList    *outBufferList = NULL, inBufferList = NULL;

// where it should be:
// AudioBufferList    *outBufferList = NULL, *inBufferList = NULL;

...and then trying to set *inBufferList. Smile
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Tip: Fullscreen mouse event gotcha Fenris 3 3,073 Feb 13, 2006 07:41 PM
Last Post: AnotherJake
  Mouse coordinates in fullscreen TomorrowPlusX 9 5,580 Aug 26, 2005 09:03 PM
Last Post: arekkusu
  Mouse Position In Fullscreen... thaeez 6 4,295 Nov 5, 2004 02:38 PM
Last Post: thaeez