IOFrameBufferShared中的不同游标格式

时间:2010-03-12 14:05:42

标签: c++ cocoa macos graphics macos-carbon

我正在阅读StdFBShmem_t结构中的moust光标像素图数据,如IOFrameBufferShared API中所定义。

一切正常,90%的时间。但是,我注意到Mac上的某些应用程序将游标设置为不同的格式。根据数据结构的文档,光标像素图格式应始终与帧缓冲区的格式相同。我的帧缓冲区是32 bpp。我希望pixmap数据的格式为0xAARRGGBB,这是(大多数时候)。但是,在某些情况下,我正在读取看起来像面具的数据。具体来说,此数据中的像素将为0x00FFFFFF或“0x00000000”。这使我成为存储在其他地方的单独像素数据的掩码。

据我所知,唯一使用此游标像素格式的应用程序是Qt Creator,但我需要处理所有应用程序,所以我想对此进行排序。

我用来读取光标像素图数据的代码是:

NSAutoreleasePool *autoReleasePool = [[NSAutoreleasePool alloc] init];

NSPoint mouseLocation = [NSEvent mouseLocation];
NSArray *allScreens = [NSScreen screens];
NSEnumerator *screensEnum = [allScreens objectEnumerator];
NSScreen *screen;
NSDictionary *screenDesc = nil;
while ((screen = [screensEnum nextObject]))
{
    NSRect screenFrame = [screen frame];
    screenDesc = [screen deviceDescription];
    if (NSMouseInRect(mouseLocation, screenFrame, NO))
        break;
}

if (screen)
{
    kern_return_t err;

    CGDirectDisplayID displayID = (CGDirectDisplayID) [[screenDesc objectForKey:@"NSScreenNumber"] pointerValue];
    task_port_t taskPort = mach_task_self();
    io_service_t displayServicePort = CGDisplayIOServicePort(displayID);
    io_connect_t displayConnection =0;
    err = IOFramebufferOpen(displayServicePort,
                            taskPort,
                            kIOFBSharedConnectType,
                            &displayConnection);
    if (KERN_SUCCESS == err)
    {
        union
        {
            vm_address_t vm_ptr;
            StdFBShmem_t *fbshmem;
        } cursorInfo;
        vm_size_t size;

        err = IOConnectMapMemory(displayConnection,
                                 kIOFBCursorMemory,
                                 taskPort,
                                 &cursorInfo.vm_ptr,
                                 &size,
                                 kIOMapAnywhere | kIOMapDefaultCache | kIOMapReadOnly);
        if (KERN_SUCCESS == err)
        {
            // For some reason, cursor data is not always in the same format as
            // the frame buffer. For this reason, we need some way to detect
            // which structure we should be reading.
            QByteArray pixData(
              (const char*)cursorInfo.fbshmem->cursor.rgb24.image[currentFrame],
              m_mouseInfo.currentSize.width() * m_mouseInfo.currentSize.height() * 4);

            IOConnectUnmapMemory(displayConnection,
                                 kIOFBCursorMemory,
                                 taskPort,
                                 cursorInfo.vm_ptr);
        } // IOConnectMapMemory
        else
            qDebug() << "IOConnectMapMemory Failed:" << err;
        IOServiceClose(displayConnection);
    } // IOServiceOpen
    else
        qDebug() << "IOFramebufferOpen Failed:" << err;
}// if screen
[autoReleasePool release];

我的问题是:

  1. 如何检测光标是否为其他格式 来自framebuffer?

  2. 我在哪里可以读取实际的像素数据? bm18Cursor 结构包含一个掩码部分,但它不在 我可以使用代码阅读它 上方。

2 个答案:

答案 0 :(得分:2)

  

如何检测光标是否与帧缓冲区的格式不同?

光标位于帧缓冲区中。它的格式不能与其本身不同。

没有办法说出它的格式(x-radar:// problem / 7751503)。如果你可以知道光标有多少帧,那么有一种方法可以至少判断每个像素的字节数,但是因为你不能(这个信息没有设置为10.6.1 - x-radar:/ / problem / 7751530),你只想弄清楚四因素产品的两个因素(每像素字节数×宽度×高度×帧数,你只有宽度,高度和产品)。即使你能找出那两个缺失的因素,你仍然不知道字节的顺序是什么,或者颜色分量是否被alpha分量预乘。

  

我在哪里可以读取实际的像素数据?

在共享游标内存结构的cursor成员中。

在包含I / O Kit标头之前,您应该定义IOFB_ARBITRARY_SIZE_CURSOR。游标现在可以是任何大小,而不仅仅是16×16,这是您未定义该常量时所期望的大小。例如,通常的Mac箭头光标为24×24,CrossOver中的“Windows”箭头光标为32×32,X11中的箭头光标为10×16。

  

但是,在某些情况下,我正在读取看起来像面具的数据。具体而言,此数据中的像素将为0x00FFFFFF0x00000000。这使我成为存储在其他地方的单独像素数据的掩码。

这听起来更像是带有8位alpha通道的16位像素。至少它更可能是5-6-5而不是5-5-5。

  

据我所知,唯一使用这种光标像素格式的应用程序是Qt Creator,但我需要处理所有应用程序,所以我想对此进行排序。

我可以使用my new cursor-capturing app捕获该应用中的当前光标。我应该点击应用程序的特定部分,以便向我显示特定的光标吗?

答案 1 :(得分:2)

您可以尝试使用CGSCreateRegisteredCursorImage函数,demonstrated by Karsten in a comment on my weblog

它是一个私有函数,因此它可能随时更改或消失,因此您应该检查它是否存在并保留IOFramebuffer,但只要它确实存在,您可能会发现它比复杂更可靠并且记录在案的IOFramebuffer。