Skip to content

Commit

Permalink
Merge pull request #300 from guillep/fix/osx/events
Browse files Browse the repository at this point in the history
Consume all events in the event queue to avoid application lockups
  • Loading branch information
eliotmiranda committed Oct 31, 2018
2 parents df9064a + b6cb192 commit 6fee3a7
Showing 1 changed file with 30 additions and 20 deletions.
50 changes: 30 additions & 20 deletions platforms/iOS/vm/OSX/sqSqueakOSXApplication+events.m
Expand Up @@ -67,27 +67,37 @@ - (sqButton) resolveModifier:(sqModifier)modifier forMouseButton:(sqButton)mouse

@implementation sqSqueakOSXApplication (events)

// Consume all pending events in the NSApp
// Events may come from the window open by the VM or windows open by other windowing systems
// We need to consume all events in the queue, otherwise this may produce lockups when e.g., switching resolutions
// If the event does not correspond to this window, we take it from the event queue anyways and re-post it afterwards
// This gives other windows the opportunity to consume their events
- (void) pumpRunLoopEventSendAndSignal:(BOOL)signal {
NSEvent *event;
while (event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil
inMode:NSEventTrackingRunLoopMode
dequeue:NO]) {
// If the event is not a system event or an event of *this* window, stop consuming events
// In case of multi window applications, it is the responsibility of the other windowing systems to consume their own events
// This is a cooperative event handling mechanism for simplicity
// Single window systems will be not affected by it
if (!(event.window == 0 || event.window == gDelegateApp.window)){
break;
}
[NSApp sendEvent: [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil
inMode:NSEventTrackingRunLoopMode
dequeue:YES]];
if (signal) {
interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex);
}
}
NSEvent *event;
NSMutableArray *alienEventQueue = [[NSMutableArray alloc] init];
while (event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil
inMode:NSEventTrackingRunLoopMode
dequeue:YES]) {
// If the event is not a system event or an event of *this* window, queue the event
// Otherwise treat the event normally and send it to the app
if (event.window && event.window != gDelegateApp.window){
[alienEventQueue addObject: event];
}else{
[NSApp sendEvent: event];
if (signal) {
interpreterProxy->signalSemaphoreWithIndex(gDelegateApp.squeakApplication.inputSemaphoreIndex);
}
}
}

// Put back in the queue all events that did not belong to this window
// They will be managed by other windowing systems
// (or by a subsequent invocation to this function)
while (event = [alienEventQueue firstObject]){
[NSApp postEvent: event atStart: NO];
[alienEventQueue removeObject: event];
}
}

- (void) pumpRunLoop {
Expand Down

0 comments on commit 6fee3a7

Please sign in to comment.