jezek / xgb

The X Go Binding is a low-level API to communicate with the X server. It is modeled on XCB and supports many X extensions.
Other
130 stars 13 forks source link

xfixes.GetCursorImage how to #25

Open codemodify opened 1 month ago

codemodify commented 1 month ago

I'm trying to capture the screen with the cursor. Seems I have to break this down into two steps

  1. capture screen (I know how to do)
  2. capture mouse cursor using xfixes.GetCursorImage() (I don't know how to unpack the output)

here is a sample code

    var cursorImageCookie xfixes.GetCursorImageCookie
    cursorImageCookie = xfixes.GetCursorImage(X)

    var cursorImageReply *xfixes.GetCursorImageReply
    cursorImageReply, err = cursorImageCookie.Reply()
    if err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }

    cursorImageReply.CursorImage // what to do with this

how do I convert the cursorImageReply.CursorImage to a golang image.Image or any other golang image formats

codemodify commented 1 month ago

Also when calling the function, I'm getting this

image

jezek commented 1 month ago

how do I convert the cursorImageReply.CursorImage to a golang image.Image or any other golang image formats

I've never worked, with xfixes extension, but whenI read the docs of type GetCursorImageReply, there is a comment after CursorImage // size: xgb.Pad(((int(Width) * int(Height)) * 4)). Which could indicate there is a image in RGBA format stored there byte by byte. Basicaly xgb (x bindings for go) is the same as xcb (x bindings for c), so if I was you, I would search in xcb documentation, how the image is stored.

Also when calling the function, I'm getting this

Please don't attach images with error messages. Always copy-paste text. It's easier to work with. Also the whole error message is very badly readable from your image.

codemodify commented 1 month ago

sorry, this is the sample code, the line cursorImageReply, err = cursorImageCookie.Reply() returns BadRequest {NiceName: Request, Sequence: 2, BadValue: 0, MinorOpcode: 4, MajorOpcode: 138}

func main() {
    X, err := xgb.NewConn()
    if err != nil {
        fmt.Println(err)
        return
    }
    defer X.Close()

    // xproto.Setup retrieves the Setup information from the setup bytes
    // gathered during connection.
    setup := xproto.Setup(X)

    // This is the default screen with all its associated info.
    screen := setup.DefaultScreen(X)
    fmt.Println(screen.Root)

    err = xfixes.Init(X)
    if err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }

    var cursorImageCookie xfixes.GetCursorImageCookie
    cursorImageCookie = xfixes.GetCursorImage(X)

    var cursorImageReply *xfixes.GetCursorImageReply
    cursorImageReply, err = cursorImageCookie.Reply()
    if err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }

    fmt.Println(cursorImageReply.CursorImage)
}
aarzilli commented 1 month ago

You are not initializing the extension correctly: https://www.x.org/releases/X11R7.7/doc/fixesproto/fixesproto.txt

codemodify commented 1 month ago

the library api only has this err = xfixes.Init(X) to init, does it mean the implementation is not up to date ?

jezek commented 1 month ago

I've asked ChatGPT how to do it and it suggests querying for version after xfixes init (for both xcb and xgb version) like this:

    // Query xfixes version
    versionCookie := xfixes.QueryVersion(conn, xfixes.MajorVersion, xfixes.MinorVersion)
    versionReply, err := versionCookie.Reply()
    if err != nil {
        log.Fatalf("Error: Cannot get xfixes version: %v\n", err)
    }

Note: I haven't tested it, so I don't know if ChatGPT is right, but from my previous experience it is mostly right and a good helper for debuging and source for inspiration.

Note2: If you succeed to get and decode the cursor image, could you write an example (into examples dir) for getting the image and let's say writing it to a file, please? It would be a big help for future package users.