Window "yanks" when moving

20 Views Asked by At

I'm trying to debug an issue in my GLFW/Metal application where when I start moving the window, the window "yanks", meaning the window freezes for a second, then jumps to where the mouse has moved meanwhile and as long as I don't release the mouse it moves smoothly after the initial freeze. Note that during the freeze period the run loop does not halt (I tested that by printing in the loop).

I reduced the problem to only Cocoa API calls, basically by copying the GLFW implementation and removing anything unnecessary.

Here is the code:

#include <thread>

#include <AppKit/AppKit.h>

@interface MyAppDelegate : NSObject<NSApplicationDelegate> @end

@implementation MyAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
    NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
                                        location:NSMakePoint(0, 0)
                                   modifierFlags:0
                                       timestamp:0
                                    windowNumber:0
                                         context:nil
                                         subtype:0
                                           data1:0
                                           data2:0];
    [NSApp postEvent:event atStart:YES];
    [NSApp stop:nil];
}
@end // MyAppDelegate

static void init() {
    @autoreleasepool {
        [NSApplication sharedApplication];
        MyAppDelegate* delegate = [[MyAppDelegate alloc] init];
        [NSApp setDelegate:delegate];
        if (![[NSRunningApplication currentApplication] isFinishedLaunching])
            [NSApp run];
        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
    } // autoreleasepool
}

static void pollEvents() {
    @autoreleasepool {
        NSEvent* event;
        while ((event = [NSApp nextEventMatchingMask:NSEventMaskAny
                                           untilDate:[NSDate distantPast]
                                              inMode:NSDefaultRunLoopMode
                                             dequeue:YES])) {
            [NSApp sendEvent:event];
        }
    }
}

static void waitEvents() {
    @autoreleasepool {
        NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
                                            untilDate:[NSDate distantFuture]
                                               inMode:NSDefaultRunLoopMode
                                              dequeue:YES];
        [NSApp sendEvent:event];
        pollEvents();
    }
}

static NSWindow* makeWindow(int width, int height) {
    NSRect contentRect = NSMakeRect(0, 0, width, height);
    NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
    styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
    styleMask |= NSWindowStyleMaskResizable;
    NSWindow* window = [[NSWindow alloc]
        initWithContentRect:contentRect
                  styleMask:styleMask
                    backing:NSBackingStoreBuffered
                      defer:NO];
    [window center];
    [window orderFront:nil];
    return window;
}

static void simulateRenderering() {
    std::this_thread::sleep_for(std::chrono::milliseconds(16));
}

int main() {
    init();
    makeWindow(800, 500);
    while (true) {
        simulateRenderering(); // If I don't call this the problem goes away
        pollEvents(); // If I call waitEvents() instead the problem also goes away
    }
}

I have no idea if the Cocoa API is supposed to be used like this, but this is what GLFW does.

As the comments suggest, if I don't sleep for a few milliseconds in the loop or if I call waitevents() instead of pollEvents(), the window moves smoothly.

So my question is, why does my window "yank" like this, and how can I make it go away, preferably without fundamentally changing the basic architecture.

0

There are 0 best solutions below