Different cursor formats in IOFrameBufferShared

Posted by Thomi on Stack Overflow See other posts from Stack Overflow or by Thomi
Published on 2010-03-12T14:05:41Z Indexed on 2010/03/12 14:07 UTC
Read the original article Hit count: 258

Filed under:
|
|
|
|

Hi,

I'm reading the moust cursor pixmap data from the StdFBShmem_t structure, as defined in the IOFrameBufferShared API.

Everything works fine, 90% of the time. However, I have noticed that some applications on the mac set a cursor in a different format. According to the documentation for the data structures, the cursor pixmap format should always be in the same format as the frame buffer. My frame buffer is 32BPP. I expect the pixmap data to be in the format 0xAARRGGBB, which is it. However, in some cases, I'm reading data that looks like a mask. Specifically, the pixel will either be 0x00FFFFFF or `0x00000000. This looks to me to be a mask for separate pixel data stored somewhere else.

As far as I can tell, the only application that uses this cursor pixel format is Qt Creator, but I need to work with all applications, so I'd like to sort this out.

The code I'm using to read the cursor pixmap data is:

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];

My question is:

  1. How can I detect if the cursor is a different format from the framebuffer?
  2. Where can I read the actual pixel data? the bm18Cursor structure contains a mask section, but it's not in the right place for me to be reading it using the code above.

Cheers,

© Stack Overflow or respective owner

Related posts about c++

Related posts about carbon