AWTK-WIDGET-WEB-VIEW 实现笔记 (3) - MacOS

MacOS 上实现 AWTK-WIDGET-WEB-VIEW 有点麻烦,主要原因是没有一个简单的办法将一个 WebView 嵌入到一个窗口中。所以,我们只能通过创建一个独立的窗口来实现。

1. 创建窗口

我对 Object-C 不熟悉,也不熟悉 Cocoa 框架,在 ChatGPT 的帮助下,实现了一个简单的窗口创建函数。这个函数接受一个 SDL_Window 指针作为父窗口,然后创建一个新的窗口,将其设置为父窗口的子窗口。这样,新窗口就会在父窗口的上方显示。

在移动窗口时,子窗口也会跟着移动,但是有些延迟。

c 复制代码
webview_os_window_t webview_os_window_create(SDL_Window* parent, int x, int y, int w, int h) {
    SDL_SysWMinfo info;
    SDL_VERSION(&info.version);
    SDL_GetWindowWMInfo(parent, &info);

    NSRect frame = NSMakeRect(x, y, w, h);
    NSWindow *parentWindow = (NSWindow *)info.info.cocoa.window;
    NSWindow* childWindow = [[NSWindow alloc] initWithContentRect:frame
                                                styleMask:NSWindowStyleMaskBorderless // 无边框样式
                                                  backing:NSBackingStoreBuffered
                                                    defer:NO];
    
    // 设置窗口级别以确保它在父窗口上方
    [childWindow setLevel:NSFloatingWindowLevel]; // 使子窗口浮动在父窗口之上

    // 设置子窗口的初始位置相对于父窗口
    NSRect parentFrame = [parentWindow frame];
    CGFloat childX = NSMinX(parentFrame) + x;
    CGFloat childY = NSMaxY(parentFrame) - y - NSHeight(frame); // 倒置 y 轴以适应窗口坐标系统

    [childWindow setParentWindow:parentWindow]; // 设置父窗口

    // 设置子窗口的位置
    [childWindow setFrame:NSMakeRect(childX, childY, w, h) display:YES];

    // 使子窗口成为关键窗口并显示
    [childWindow makeKeyAndOrderFront:nil];

    // 观察父窗口的移动和大小变化
    [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidMoveNotification
                                                      object:parentWindow
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
        NSRect newParentFrame = [parentWindow frame];
        [childWindow setFrameOrigin:NSMakePoint(NSMinX(newParentFrame) + x, NSMaxY(newParentFrame) - y - NSHeight(frame))];
    }];

    [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidResizeNotification
                                                      object:parentWindow
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
        NSRect newParentFrame = [parentWindow frame];
        [childWindow setFrameOrigin:NSMakePoint(NSMinX(newParentFrame) + x, NSMaxY(newParentFrame) - y - NSHeight(frame))];
    }];

    // 观察父窗口切换到后面时,自动切换到后面
    [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidResignKeyNotification
                                                      object:parentWindow
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
        [childWindow orderOut:nil];
    }];

    [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification
                                                      object:parentWindow
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
        [childWindow makeKeyAndOrderFront:nil];
    }];
    
    return (__bridge void*)childWindow; // 使用 __bridge 传递所有权
}

2. 调整窗口大小

奇怪的是从 subwindow 获取父窗口的方法不起作用,所以通过传递父窗口的指针来调整子窗口的大小。

c 复制代码
void webview_os_window_move_resize(SDL_Window* parent, webview_os_window_t subwindow, int x, int y, int w, int h) {
    SDL_SysWMinfo info;
    SDL_VERSION(&info.version);
    SDL_GetWindowWMInfo(parent, &info);
    NSWindow *childWindow = (__bridge NSWindow*)subwindow;
    NSWindow *parentWindow = info.info.cocoa.window;

    NSRect frame = NSMakeRect(x, y, w, h);
    [childWindow setFrame:frame display:YES];
     
    NSRect newParentFrame = [parentWindow frame];
    [childWindow setFrameOrigin:NSMakePoint(NSMinX(newParentFrame) + x, NSMaxY(newParentFrame) - y - NSHeight(frame))];
}

3. 销毁窗口

销毁窗口时,需要将子窗口从父窗口中移除。

c 复制代码
void webview_os_window_destroy(webview_os_window_t subwindow) {
    NSWindow *childWindow = (__bridge NSWindow*)subwindow;
    [[NSNotificationCenter defaultCenter] removeObserver:childWindow];
    [childWindow close];
}
相关推荐
梦魇梦狸º7 小时前
mac 配置 python 环境变量
chrome·python·macos
丁总学Java12 小时前
macOS如何进入 Application Support 目录(cd: string not in pwd: Application)
macos
qdprobot13 小时前
Mixly米思齐1.0 2.0 3.0 软件windows版本MAC苹果电脑系统安装使用常见问题与解决
windows·macos
麦克Mapp13 小时前
不用安装双系统,如何在mac上玩windows游戏呢?
macos
符小易13 小时前
Mac苹果电脑 怎么用word文档和Excel表格?
macos·word·excel
梦魇梦狸º17 小时前
node安装与管理
macos·node.js
缘友一世1 天前
macOS查看当前项目的 tree 结构
macos
梦魇梦狸º1 天前
mac 安装 python2
python·macos
篮l球场2 天前
mac m1下载maven安装并配置环境变量
macos
YAIMZA2 天前
mac配置 iTerm2 使用lrzsz与服务器传输文件
服务器·macos·lrzsz