代码之家  ›  专栏  ›  技术社区  ›  Thomi

ioframebuffershared中的不同光标格式

  •  2
  • Thomi  · 技术社区  · 14 年前

    我正在从 StdFBShmem_t 结构,定义见 IOFrameBufferShared API .

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

    据我所知,唯一使用这种光标像素格式的应用程序是 Qt Creator ,但我需要处理所有应用程序,所以我想解决这个问题。

    我用来读取光标pixmap数据的代码是:

    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. 如何检测光标的格式是否不同 从帧缓冲区?

    2. 在哪里可以读取实际像素数据?这个 bm18Cursor 结构包含一个掩码部分,但它不在 正确的地方让我用密码读 上面。

    2 回复  |  直到 14 年前
        1
  •  2
  •   Peter Hosey    14 年前

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

    光标在帧缓冲区中。它的格式不能和它本身不同。

    无法判断它的格式(x-radar://problem/7751503)。如果你能知道光标有多少帧,那么至少可以预测每个像素的字节数,但是由于你不能(这个信息没有在10.6.1–x-radar://problem/7751530中设置),你只能试图找出四因子乘积中的两个因子(每p字节数ixel_width_height_151;number of frames,其中只有宽度、高度和产品)。即使你能找出这两个缺失的因素,你仍然不知道字节的顺序,或者颜色分量是否是由alpha分量预乘的。

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

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

    你应该定义 IOFB_ARBITRARY_SIZE_CURSOR 在包含I/O工具包头之前。游标现在可以是任意大小,而不仅仅是1616,这是您在不定义该常量时所期望的大小。例如,通常的mac箭头光标是2424,crossover中的windows箭头光标是3232,x11中的箭头光标是1016。

    但是,在某些情况下,我读取的数据看起来像一个掩码。具体来说,该数据中的像素将是 0x00FFFFFF 0x00000000 . 在我看来,这是存储在其他地方的单独像素数据的掩码。

    在我看来,这更像是一个8位alpha通道的16位像素。至少可能是5-6-5而不是5-5-5。

    据我所知,唯一使用这种光标像素格式的应用程序是qt creator,但我需要处理所有应用程序,所以我想整理一下。

    我可以很好地捕获应用程序中的当前光标 my new cursor-capturing app . 是否有一个特定的部分,我应该点击,使它显示给我一个特定的光标?

        2
  •  2
  •   Peter Hosey    14 年前

    您可以尝试cgscreateregisteredcursorimage函数,如下所示 demonstrated by Karsten in a comment on my weblog .

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