doterax's picture

How to fix the frozen menu on Mac OS X, if you game implements manual event loop processing.

Project:The Open Toolkit library
Version:1.0.0-rc1
Component:Miscellaneous
Category:task
Priority:normal
Assigned:the Fiddler
Status:confirmed
Description

link to my description of the patch on the Russian.

http://dl.dropbox.com/u/18568924/MacOS%20Programming/MenuHotfix.pdf

You can translate this document to English. Source of this PDF for translators:

http://dl.dropbox.com/u/18568924/MacOS%20Programming/MenuHotfix.odt


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
doterax's picture

#1

Solving the problem with menu in Mac OS X or how correctly pump messages in Mac OS X.

Google translated text below, sorry :-)

For that would render the game more smoothly, we use a series of pumping messages. That is - we each frame is pumping messages that have occurred over time, rendering the previous frame, and we do it like this:

static bool ProcessMessages()
{
    IntPtr theEvent;
    IntPtr theTarget = API.GetEventDispatcherTarget();
    while(true)
    {
        OSStatus status =
        API.ReceiveNextEvent(0, IntPtr.Zero, 0.0,
            true, out theEvent);
        if (status == OSStatus.EventLoopTimedOut)
            break;
        if (status == OSStatus.EventLoopQuit)
            return false;
        if (status != OSStatus.NoError)//отдельно для дебага
            return false;
        if (theEvent == IntPtr.Zero)
        {
            break;
        }
        try
        {
            API.SendEventToEventTarget(theEvent, theTarget);
        }
        catch (System.ExecutionEngineException e){}
        EventInfo evt = new EventInfo(theEvent);
        API.ReleaseEvent(theEvent);
    }
    return true;
}

The main loop looks like this (pseudocode):

static void mainLoop()
{
    while( ProcessMessages() );
}
static void main()
{
    init();
    mainLoop();
    done();
}

As it turns out that's not enough, the whole point is that the treatment menu is only as a function of RunApplicationEventLoop.
And in order to handle this - it is necessary the main loop of the application to make in the context of the function RunApplicationEventLoop.
To do this, create a unique event specifications, signed by him and a handler sent him, and in the handler put the main message loop. Such an approach is completely solved the problem with the menu.

This is done like this (pseudocode):

static void mainLoop()
{
    while( ProcessMessages() );
    API.QuitApplicationEventLoop();
}
static void mainLoopInApplicationEventLoop()
{
    EventTypeSpec specCustomEvent =
        new EventTypeSpec(EventClass.Window + 1, AppEventKind.AppQuit + 1);
    EventTypeSpec[] eventTypes = new EventTypeSpec[] { specCustomEvent };
    IntPtr hotFixFrozenMenuHandlerUPP = API.NewEventHandlerUPP(mainLoop);
    API.InstallApplicationEventHandler(hotFixFrozenMenuHandlerUPP, eventTypes,IntPtr.Zero,IntPtr.Zero);
    IntPtr theCustomEvent = API.CreateEvent(specCustomEvent);
    IntPtr eventQueue = API.GetCurrentEventQueue();
    OSStatus postResult =  API.PostEventToQueue(eventQueue, theCustomEvent,EventPriority.kEventPriorityHigh);
    API.ReleaseEvent(theCustomEvent);
    API.RunApplicationEventLoop();
}
static void main()
{
    init();
    mainLoopInApplicationEventLoop();
    done();
}
the Fiddler's picture

#2

Assigned to:Anonymous» the Fiddler
Status:open» confirmed