无法使用 NSOpenGLView 从 nextEventMatchingMask 获取 NSMouseMoved 事件

发布于 2024-12-17 14:16:34 字数 3274 浏览 5 评论 0原文

我正在尝试使用典型的 win 风格事件循环创建一个带有鼠标输入的基本 opengl 窗口。问题是我正在努力尝试生成 NSMouseMoved 事件。以下代码输出有关“鼠标向上”、“鼠标向下”、“鼠标拖动”等的调试信息,但没有“鼠标移动”,即使我已告诉窗口 setAcceptsMouseMovedEvents:YES。那么,关于如何让鼠标移动在以下示例中工作有什么想法吗?

显然,我创建窗口的方式非常不像可可,但我正在尝试移植一个基于 makefile 的 Windows C++ 代码库,该代码库可以执行一些棘手的线程操作。这就是为什么我坚持使用类似于使用 GetMsg() 的 win32 循环的风格。

另外,为了构建我只是使用:

gcc -o hellogl hellogl.m -framework Foundation -framework Cocoa -framework OpenGL

感谢您的帮助!

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

#include <OpenGL/gl.h>
#include <stdlib.h>

@interface BaseWinDelegate : NSWindow<NSWindowDelegate>

@end

@implementation BaseWinDelegate
- (void) windowWillClose:(NSNotification*)notification
{
    printf("Closing.\n");

    NSEvent * evt = [NSEvent otherEventWithType:NSApplicationDefined
                     location: NSMakePoint(0,0)
                     modifierFlags: 0
                     timestamp: 0.0
                     windowNumber: 0
                     context: nil
                     subtype: 0
                     data1: 0
                     data2: 0];

    [NSApp postEvent:evt atStart:NO];
}
@end

@interface BaseView : NSOpenGLView
- (void) update;
- (void) drawRect:(NSRect)rect;
- (void) reshape;
@end

@implementation BaseView

- (void) drawRect:(NSRect)rect
{
    glClearColor(0.2f,0.2f,0.2f,0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    [[self openGLContext] flushBuffer];
}

- (void) update
{
    printf("Update.\n");
}

- (void) reshape
{
    NSRect rect;

    [[self openGLContext] update];
    rect = [self bounds];

    printf("Reshape - %f, %f\n", rect.size.width,rect.size.height);
}

@end

int main(int argc, const char * argv[])
{
    printf("Starting.\n");

    NSAutoreleasePool * myPool = [[NSAutoreleasePool alloc] init ];
    NSApplicationLoad();

    NSRect rect = NSMakeRect(100,100,640,480);
    NSWindow * win = [[NSWindow alloc] initWithContentRect:rect
                        styleMask:NSTitledWindowMask |     NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
                        backing: NSBackingStoreBuffered
                        defer: NO];

    NSOpenGLPixelFormatAttribute attributes[] =
    {
        NSOpenGLPFADoubleBuffer,
        0
    };

    NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc]     initWithAttributes:attributes];

    BaseView * pView = [[BaseView alloc] initWithFrame:rect pixelFormat:pf];
        BaseWinDelegate * myDelegate = [BaseWinDelegate alloc];

    [win setDelegate:myDelegate];
    [win setContentView: pView];
    [win makeKeyAndOrderFront: NSApp];
    [win setAcceptsMouseMovedEvents:YES];

    do
    {
        NSEvent * evt = [NSApp nextEventMatchingMask : NSAnyEventMask
                               untilDate : [NSDate distantFuture]
                               inMode : NSDefaultRunLoopMode
                               dequeue : YES ];

        NSEventType evtType = [evt type];

        if (evtType == NSApplicationDefined)
        {
            break;
        }

        printf("%d\n",(int)evtType);
        [NSApp sendEvent : evt];
    } while (1);

    [myPool drain];
    return EXIT_SUCCESS;
}

I'm trying to create a basic opengl window with mouse input using a typical win-style event loop. The problem is that I'm pulling my hair out trying to get a NSMouseMoved event to generate. The following code outputs debug info on Mouse Up, Mouse Down, Mouse Drag, etc but no Mouse Move even though I've told the window setAcceptsMouseMovedEvents:YES. So, any ideas on how to get mouse move to work in the following example?

Obviously, the way I'm creating the window is very un-cocoa like, but I'm trying to port a makefile-based windows c++ codebase that does some tricky threading things. That's why I'm sticking with a style similar to a win32 loop using GetMsg().

Also, to build I'm just using:

gcc -o hellogl hellogl.m -framework Foundation -framework Cocoa -framework OpenGL

Thanks for the help!

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

#include <OpenGL/gl.h>
#include <stdlib.h>

@interface BaseWinDelegate : NSWindow<NSWindowDelegate>

@end

@implementation BaseWinDelegate
- (void) windowWillClose:(NSNotification*)notification
{
    printf("Closing.\n");

    NSEvent * evt = [NSEvent otherEventWithType:NSApplicationDefined
                     location: NSMakePoint(0,0)
                     modifierFlags: 0
                     timestamp: 0.0
                     windowNumber: 0
                     context: nil
                     subtype: 0
                     data1: 0
                     data2: 0];

    [NSApp postEvent:evt atStart:NO];
}
@end

@interface BaseView : NSOpenGLView
- (void) update;
- (void) drawRect:(NSRect)rect;
- (void) reshape;
@end

@implementation BaseView

- (void) drawRect:(NSRect)rect
{
    glClearColor(0.2f,0.2f,0.2f,0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    [[self openGLContext] flushBuffer];
}

- (void) update
{
    printf("Update.\n");
}

- (void) reshape
{
    NSRect rect;

    [[self openGLContext] update];
    rect = [self bounds];

    printf("Reshape - %f, %f\n", rect.size.width,rect.size.height);
}

@end

int main(int argc, const char * argv[])
{
    printf("Starting.\n");

    NSAutoreleasePool * myPool = [[NSAutoreleasePool alloc] init ];
    NSApplicationLoad();

    NSRect rect = NSMakeRect(100,100,640,480);
    NSWindow * win = [[NSWindow alloc] initWithContentRect:rect
                        styleMask:NSTitledWindowMask |     NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
                        backing: NSBackingStoreBuffered
                        defer: NO];

    NSOpenGLPixelFormatAttribute attributes[] =
    {
        NSOpenGLPFADoubleBuffer,
        0
    };

    NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc]     initWithAttributes:attributes];

    BaseView * pView = [[BaseView alloc] initWithFrame:rect pixelFormat:pf];
        BaseWinDelegate * myDelegate = [BaseWinDelegate alloc];

    [win setDelegate:myDelegate];
    [win setContentView: pView];
    [win makeKeyAndOrderFront: NSApp];
    [win setAcceptsMouseMovedEvents:YES];

    do
    {
        NSEvent * evt = [NSApp nextEventMatchingMask : NSAnyEventMask
                               untilDate : [NSDate distantFuture]
                               inMode : NSDefaultRunLoopMode
                               dequeue : YES ];

        NSEventType evtType = [evt type];

        if (evtType == NSApplicationDefined)
        {
            break;
        }

        printf("%d\n",(int)evtType);
        [NSApp sendEvent : evt];
    } while (1);

    [myPool drain];
    return EXIT_SUCCESS;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暮年慕年 2024-12-24 14:16:34

好吧,想通了。问题是它不是前台进程。所以添加这段代码就可以解决这个问题。

ProcessSerialNumber psn;
GetCurrentProcess(&psn);
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
SetFrontProcess(&psn);

这可以防止窗口成为关键窗口并发送鼠标移动事件。希望它对其他人有帮助(即喜欢处理自己的事件循环的 0.1% 的人)。

Ok, figured it out. The problem is that it's not a foreground process. So adding this code fixes it.

ProcessSerialNumber psn;
GetCurrentProcess(&psn);
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
SetFrontProcess(&psn);

That was preventing the window from becoming the key window and sending off mouse moved events. Hope it helps someone else (i.e. the 0.1% of people who like to handle their own event loop).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文