4

IOFrameBufferShared APIStdFBShmem_tで定義されているように、構造体からマウス カーソルのピックスマップ データを読み取っています。

90% の確率で、すべてが正常に機能します。ただし、Mac の一部のアプリケーションではカーソルが別の形式で設定されていることに気付きました。データ構造のドキュメントによると、カーソルのピックスマップ形式は常にフレーム バッファーと同じ形式にする必要があります。私のフレーム バッファは 32 bppです。ピックスマップ データの形式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. カーソルがフレームバッファとは異なるフォーマットであるかどうかを検出するにはどうすればよいですか?

  2. 実際のピクセル データはどこで読み取ることができますか? 構造にはマスク セクションが含まれていますが、上記bm18Cursor のコードを使用してそれを読み取るには適切な場所ではありません。

4

2 に答える 2

2

カーソルがフレームバッファとは異なるフォーマットであるかどうかを検出するにはどうすればよいですか?

カーソルはフレームバッファにあります。それ自体と異なる形式にすることはできません。

それがどの形式であるかを知る方法はありません (x-radar://problem/7751503)。カーソルのフレーム数がわかれば、少なくともピクセルあたりのバイト数を推測する方法がありますが、それができないためです (その情報は 10.6.1 の時点では設定されていません — x-radar:/ /problem/7751530)、4 要素積の 2 つの要素 (1 ピクセルあたりのバイト数 × 幅 × 高さ × フレーム数、幅、高さ、および積のみ) を計算しなければなりません。また、欠落している 2 つの要素を特定できたとしても、バイトの順序や、色成分がアルファ成分によって事前に乗算されているかどうかはまだわかりません。

実際のピクセル データはどこで読み取ることができますか?

cursorshared-cursor-memory 構造体のメンバー内。

IOFB_ARBITRARY_SIZE_CURSORI/O Kit ヘッダーを含める前に定義する必要があります。カーソルは、16×16 だけでなく、任意のサイズにすることができます。これは、その定数を定義しない場合に予想されるサイズです。例として、通常の Mac の矢印カーソルは 24×24、CrossOver の「Windows」の矢印カーソルは 32×32、X11 の矢印カーソルは 10×16 です。

ただし、場合によっては、マスクのように見えるデータを読み取っています。具体的には、このデータのピクセルは または のいずれかになり0x00FFFFFFます0x00000000。これは、別の場所に保存されている個別のピクセル データのマスクのように見えます。

それは、8 ビットのアルファ チャネルを持つ 16 ビット ピクセルのように思えます。少なくとも、5-5-5 よりも 5-6-5 である可能性が高いです。

私が知る限り、このカーソル ピクセル形式を使用するアプリケーションは Qt Creator だけですが、すべてのアプリケーションを操作する必要があるため、これを整理したいと思います。

新しいカーソルキャプチャアプリで、そのアプリの現在のカーソルを問題なくキャプチャできます。特定のカーソルを表示するためにヒットする必要があるアプリの特定の部分はありますか?

于 2010-03-13T22:27:30.453 に答える
2

私のウェブログのコメントで Karsten が示しているように、CGSCreateRegisteredCursorImage 関数を試すことができます。

プライベートな機能なので、いつでも変わったり消えたりする可能性があるので、存在を確認して IOFramebuffer を確保しておく必要がありますが、存在する限り、複雑で薄い -文書化された IOFramebuffer。

于 2010-03-15T08:47:46.237 に答える