Objective c 在macOS上尝试将VNC帧缓冲区快速绘制到NSView时,我做错了什么?

Objective c 在macOS上尝试将VNC帧缓冲区快速绘制到NSView时,我做错了什么?,objective-c,macos,cocoa,vnc,Objective C,Macos,Cocoa,Vnc,我正在使用它在macOS上创建一个专门的VNC查看器(在Mojave上开发)。我已经用C++和Linux、*BSD甚至Mac OS编写了这个应用程序。我想要一些“本地”macOS,所以我选择了Cocoa和Objective-C。我现在不想使用Swift。另外,我是以编程方式编写的,而不是使用Xcode。我真的不想使用Xcode,因为它在莫哈韦有多麻烦 对于VNC查看器,我使用了一个子类NSView,其设置如下。此查看器嵌入在NSScrollView中: - (id)initWithFrame:(

我正在使用它在macOS上创建一个专门的VNC查看器(在Mojave上开发)。我已经用C++和Linux、*BSD甚至Mac OS编写了这个应用程序。我想要一些“本地”macOS,所以我选择了Cocoa和Objective-C。我现在不想使用Swift。另外,我是以编程方式编写的,而不是使用Xcode。我真的不想使用Xcode,因为它在莫哈韦有多麻烦

对于VNC查看器,我使用了一个子类NSView,其设置如下。此查看器嵌入在NSScrollView中:

- (id)initWithFrame:(NSRect)frame 
{
    self = [super initWithFrame:frame];

    return self;
}

- (BOOL)isFlipped
{
    return YES;
}

- (BOOL)opaque
{
    return YES;
}
有两个主要事件用于绘制:在NSView查看器上使更改的矩形无效,然后实际告诉查看器绘制。以下是失效部分:

/* this fires *every* time something is changed on the vnc server's screen */
static void handleFrameBufferUpdate (rfbClient * cl, int x, int y, int w, int h)
{
    dispatch_async(dispatch_get_main_queue(), 
    ^{
        NSRect rUp = NSMakeRect(x, y, w, h);
        [vncViewer setNeedsDisplayInRect:rUp];
    });
}
下面是一个事件,它告诉视图在一定数量的无效调用后绘制自身:

static void handleFinishedFrameBufferUpdate (rfbClient * cl)
{
    dispatch_async(dispatch_get_main_queue(), 
    ^{    
        [vncViewer displayIfNeededIgnoringOpacity];
    });
}
来自VNC服务器的所有像素数据都由libvncclient写入RGBA格式的帧缓冲区——一个
uint8\t
(或
uchar
,取决于您的体系结构)数组。每像素32位,每采样8位,每像素4个采样

对于实际图形,以下是相关代码(指向
uint8\u t
的帧缓冲区数组的指针称为:
vnc.vncClient->frameBuffer

当我连接到VNC服务器时,屏幕并没有完全填满,但看起来与此类似,每次更新时,白色非图像区域会四处移动:

不幸的是,我发现服务器或libvncclient将每个像素的alpha部分设置为0,从而有效地隐藏了它。我添加了这段黑客代码,以便在绘制任何图形之前,将每个像素设置为完全alpha:

    // if there's an alpha byte, set it to 255
    if ([vnc bytesPerPixel] == 2 || [vnc bytesPerPixel] == 4)
    {
        for (int i = ([vnc bytesPerPixel] - 1); i < [vnc buffSize]; i+= [vnc bytesPerPixel])
            vnc.vncClient->frameBuffer[i] = 255;
    }
//如果有alpha字节,则将其设置为255
if([vnc字节每像素]==2 | |[vnc字节每像素]==4)
{
对于(int i=([vnc字节像素]-1);i<[vnc buffSize];i+=[vnc字节像素])
vnc.vncClient->frameBuffer[i]=255;
}
查看器现在可以填充更多的图像,但我仍然可以看到白色矩形的移动区域,如下图所示:


  • 是否有任何方法可以让NSView“保留”在其上绘制的内容,而不必在每次更新时将其清除

  • 这个子类NSView是这个工作的正确工具,还是应该使用其他工具?VNC服务器每秒更新帧缓冲区很多次,我需要我的查看器具有响应性,而不是“滞后”

谢谢

    // if there's an alpha byte, set it to 255
    if ([vnc bytesPerPixel] == 2 || [vnc bytesPerPixel] == 4)
    {
        for (int i = ([vnc bytesPerPixel] - 1); i < [vnc buffSize]; i+= [vnc bytesPerPixel])
            vnc.vncClient->frameBuffer[i] = 255;
    }