forked from Leak_Technologies/VideoTools
Vendor gotk3, add mpv cgo wrapper, and GTK mpv player stub
This commit is contained in:
parent
7f0ea613d6
commit
26c48ab981
149
cmd/gtkplayer/main.go
Normal file
149
cmd/gtkplayer/main.go
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.leaktechnologies.dev/stu/VT_Player/player/mpvembed"
|
||||||
|
|
||||||
|
"github.com/gotk3/gotk3/gdk"
|
||||||
|
"github.com/gotk3/gotk3/gtk"
|
||||||
|
)
|
||||||
|
|
||||||
|
// simple GTK + mpv embedded player demo (single pane).
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
gtk.Init(nil)
|
||||||
|
|
||||||
|
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("window: %v", err)
|
||||||
|
}
|
||||||
|
win.SetTitle("VT Player (GTK/mpv)")
|
||||||
|
win.SetDefaultSize(1280, 720)
|
||||||
|
|
||||||
|
grid, _ := gtk.GridNew()
|
||||||
|
grid.SetColumnHomogeneous(true)
|
||||||
|
grid.SetRowHomogeneous(false)
|
||||||
|
win.Add(grid)
|
||||||
|
|
||||||
|
// Drawing area for mpv
|
||||||
|
da, _ := gtk.DrawingAreaNew()
|
||||||
|
da.SetHexpand(true)
|
||||||
|
da.SetVexpand(true)
|
||||||
|
grid.Attach(da, 0, 1, 4, 1)
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
openBtn, _ := gtk.ButtonNewWithLabel("Open...")
|
||||||
|
playBtn, _ := gtk.ButtonNewWithLabel("Play")
|
||||||
|
pauseBtn, _ := gtk.ButtonNewWithLabel("Pause")
|
||||||
|
seekStartBtn, _ := gtk.ButtonNewWithLabel("<< Start")
|
||||||
|
grid.Attach(openBtn, 0, 0, 1, 1)
|
||||||
|
grid.Attach(playBtn, 1, 0, 1, 1)
|
||||||
|
grid.Attach(pauseBtn, 2, 0, 1, 1)
|
||||||
|
grid.Attach(seekStartBtn, 3, 0, 1, 1)
|
||||||
|
|
||||||
|
mpv, err := mpvembed.New()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("mpv: %v", err)
|
||||||
|
}
|
||||||
|
defer mpv.Destroy()
|
||||||
|
|
||||||
|
var duration float64
|
||||||
|
|
||||||
|
da.Connect("realize", func() {
|
||||||
|
w := da.GetWindow()
|
||||||
|
if w == nil {
|
||||||
|
log.Println("no window yet")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Bind native window ID
|
||||||
|
if xid := getWindowID(w); xid != 0 {
|
||||||
|
_ = mpv.SetWID(xid)
|
||||||
|
}
|
||||||
|
// Set options and init
|
||||||
|
_ = mpv.SetOptionString("pause", "yes")
|
||||||
|
if err := mpv.Initialize(); err != nil {
|
||||||
|
log.Fatalf("mpv init: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
openBtn.Connect("clicked", func() {
|
||||||
|
dlg, _ := gtk.FileChooserDialogNewWith1Button("Open Video", win, gtk.FILE_CHOOSER_ACTION_OPEN, "Open", gtk.RESPONSE_ACCEPT)
|
||||||
|
if resp := dlg.Run(); resp == int(gtk.RESPONSE_ACCEPT) {
|
||||||
|
filename := dlg.GetFilename()
|
||||||
|
if filename != "" {
|
||||||
|
loadFile(mpv, filename, &duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dlg.Destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
playBtn.Connect("clicked", func() {
|
||||||
|
_ = mpv.SetPropertyBool("pause", false)
|
||||||
|
})
|
||||||
|
pauseBtn.Connect("clicked", func() {
|
||||||
|
_ = mpv.SetPropertyBool("pause", true)
|
||||||
|
})
|
||||||
|
seekStartBtn.Connect("clicked", func() {
|
||||||
|
_ = mpv.Command("seek", "0", "absolute", "exact")
|
||||||
|
})
|
||||||
|
|
||||||
|
// Progress poll
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(250 * time.Millisecond)
|
||||||
|
defer t.Stop()
|
||||||
|
for range t.C {
|
||||||
|
pos, err := mpv.GetPropertyDouble("time-pos")
|
||||||
|
if err == nil && duration > 0 {
|
||||||
|
fmt.Printf("\r%.1f / %.1f", pos, duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
win.Connect("destroy", func() {
|
||||||
|
gtk.MainQuit()
|
||||||
|
})
|
||||||
|
|
||||||
|
win.ShowAll()
|
||||||
|
gtk.Main()
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFile(mpv *mpvembed.Client, path string, duration *float64) {
|
||||||
|
base := filepath.Base(path)
|
||||||
|
fmt.Printf("\nLoading: %s\n", base)
|
||||||
|
if err := mpv.Command("loadfile", path, "replace"); err != nil {
|
||||||
|
log.Printf("loadfile: %v", err)
|
||||||
|
}
|
||||||
|
if d, err := mpv.GetPropertyDouble("duration"); err == nil {
|
||||||
|
*duration = d
|
||||||
|
}
|
||||||
|
_ = mpv.SetPropertyBool("pause", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getWindowID returns the native window handle (XID on X11, HWND on Windows).
|
||||||
|
func getWindowID(w *gdk.Window) uint64 {
|
||||||
|
// X11
|
||||||
|
if xid := gdkWindowGetXID(w); xid != 0 {
|
||||||
|
return xid
|
||||||
|
}
|
||||||
|
// TODO: add Windows handle if needed.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// gdkWindowGetXID extracts the XID from a GDK window when running on X11.
|
||||||
|
func gdkWindowGetXID(w *gdk.Window) uint64 {
|
||||||
|
type xidGetter interface {
|
||||||
|
GetXID() uint
|
||||||
|
}
|
||||||
|
if xw, ok := w.(xidGetter); ok {
|
||||||
|
return uint64(xw.GetXID())
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
3
go.mod
3
go.mod
|
|
@ -4,9 +4,12 @@ go 1.25.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
fyne.io/fyne/v2 v2.7.1
|
fyne.io/fyne/v2 v2.7.1
|
||||||
|
github.com/gotk3/gotk3 v0.6.4
|
||||||
github.com/hajimehoshi/oto v0.7.1
|
github.com/hajimehoshi/oto v0.7.1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/gotk3/gotk3 => ./third_party/gotk3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 // indirect
|
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 // indirect
|
||||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -35,6 +35,8 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||||
|
github.com/gotk3/gotk3 v0.6.4 h1:5ur/PRr86PwCG8eSj98D1eXvhrNNK6GILS2zq779dCg=
|
||||||
|
github.com/gotk3/gotk3 v0.6.4/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
|
||||||
github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
|
github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
|
||||||
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
|
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
|
||||||
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
|
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
|
||||||
|
|
|
||||||
146
player/mpvembed/mpv.go
Normal file
146
player/mpvembed/mpv.go
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
package mpvembed
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo pkg-config: mpv
|
||||||
|
#include <mpv/client.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static inline const char* mpv_errstr(int err) { return mpv_error_string(err); }
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client wraps a libmpv handle.
|
||||||
|
type Client struct {
|
||||||
|
handle *C.mpv_handle
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new mpv client.
|
||||||
|
func New() (*Client, error) {
|
||||||
|
h := C.mpv_create()
|
||||||
|
if h == nil {
|
||||||
|
return nil, errors.New("mpv_create returned nil")
|
||||||
|
}
|
||||||
|
return &Client{handle: h}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize must be called before issuing commands.
|
||||||
|
func (c *Client) Initialize() error {
|
||||||
|
if c.handle == nil {
|
||||||
|
return errors.New("mpv handle is nil")
|
||||||
|
}
|
||||||
|
if res := C.mpv_initialize(c.handle); res < 0 {
|
||||||
|
return fmt.Errorf("mpv_initialize failed: %s", C.GoString(C.mpv_errstr(res)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy terminates and frees the client.
|
||||||
|
func (c *Client) Destroy() {
|
||||||
|
if c.handle != nil {
|
||||||
|
C.mpv_terminate_destroy(c.handle)
|
||||||
|
c.handle = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOptionString sets an option before initialize.
|
||||||
|
func (c *Client) SetOptionString(name, value string) error {
|
||||||
|
if c.handle == nil {
|
||||||
|
return errors.New("mpv handle is nil")
|
||||||
|
}
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
cval := C.CString(value)
|
||||||
|
defer C.free(unsafe.Pointer(cval))
|
||||||
|
if res := C.mpv_set_option_string(c.handle, cname, cval); res < 0 {
|
||||||
|
return fmt.Errorf("mpv_set_option_string %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOptionInt sets an integer option.
|
||||||
|
func (c *Client) SetOptionInt(name string, val int64) error {
|
||||||
|
if c.handle == nil {
|
||||||
|
return errors.New("mpv handle is nil")
|
||||||
|
}
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
cval := C.longlong(val)
|
||||||
|
if res := C.mpv_set_option(c.handle, cname, C.mpv_format(C.MPV_FORMAT_INT64), unsafe.Pointer(&cval)); res < 0 {
|
||||||
|
return fmt.Errorf("mpv_set_option %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWID binds a native window ID to mpv (for embedding).
|
||||||
|
func (c *Client) SetWID(wid uint64) error {
|
||||||
|
return c.SetOptionInt("wid", int64(wid))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command issues an mpv command with arguments.
|
||||||
|
func (c *Client) Command(args ...string) error {
|
||||||
|
if c.handle == nil {
|
||||||
|
return errors.New("mpv handle is nil")
|
||||||
|
}
|
||||||
|
// Build a NULL-terminated array of *char
|
||||||
|
cargs := make([]*C.char, len(args)+1)
|
||||||
|
for i, a := range args {
|
||||||
|
cstr := C.CString(a)
|
||||||
|
defer C.free(unsafe.Pointer(cstr))
|
||||||
|
cargs[i] = cstr
|
||||||
|
}
|
||||||
|
cargs[len(args)] = nil
|
||||||
|
if res := C.mpv_command(c.handle, &cargs[0]); res < 0 {
|
||||||
|
return fmt.Errorf("mpv_command %v failed: %s", args, C.GoString(C.mpv_errstr(res)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPropertyBool sets a boolean property.
|
||||||
|
func (c *Client) SetPropertyBool(name string, v bool) error {
|
||||||
|
if c.handle == nil {
|
||||||
|
return errors.New("mpv handle is nil")
|
||||||
|
}
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
cval := C.int(0)
|
||||||
|
if v {
|
||||||
|
cval = 1
|
||||||
|
}
|
||||||
|
if res := C.mpv_set_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_FLAG), unsafe.Pointer(&cval)); res < 0 {
|
||||||
|
return fmt.Errorf("mpv_set_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPropertyDouble sets a double property.
|
||||||
|
func (c *Client) SetPropertyDouble(name string, v float64) error {
|
||||||
|
if c.handle == nil {
|
||||||
|
return errors.New("mpv handle is nil")
|
||||||
|
}
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
cval := C.double(v)
|
||||||
|
if res := C.mpv_set_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_DOUBLE), unsafe.Pointer(&cval)); res < 0 {
|
||||||
|
return fmt.Errorf("mpv_set_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPropertyDouble gets a double property.
|
||||||
|
func (c *Client) GetPropertyDouble(name string) (float64, error) {
|
||||||
|
if c.handle == nil {
|
||||||
|
return 0, errors.New("mpv handle is nil")
|
||||||
|
}
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
var out C.double
|
||||||
|
if res := C.mpv_get_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_DOUBLE), unsafe.Pointer(&out)); res < 0 {
|
||||||
|
return 0, fmt.Errorf("mpv_get_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
||||||
|
}
|
||||||
|
return float64(out), nil
|
||||||
|
}
|
||||||
305
third_party/gotk3/gdk/gdk_since_3_22.go
vendored
Normal file
305
third_party/gotk3/gdk/gdk_since_3_22.go
vendored
Normal file
|
|
@ -0,0 +1,305 @@
|
||||||
|
// +build !gtk_3_6,!gtk_3_8,!gtk_3_10,!gtk_3_12,!gtk_3_14,!gtk_3_16,!gtk_3_18,!gtk_3_20
|
||||||
|
// Supports building with gtk 3.22+
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2014 Conformal Systems <info@conformal.com>
|
||||||
|
//
|
||||||
|
// This file originated from: http://opensource.conformal.com/
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package gdk
|
||||||
|
|
||||||
|
// #include <gdk/gdk.h>
|
||||||
|
// #include "gdk_since_3_22.go.h"
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/gotk3/gotk3/glib"
|
||||||
|
"github.com/gotk3/gotk3/internal/callback"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
tm := []glib.TypeMarshaler{
|
||||||
|
{glib.Type(C.gdk_subpixel_layout_get_type()), marshalSubpixelLayout},
|
||||||
|
}
|
||||||
|
|
||||||
|
glib.RegisterGValueMarshalers(tm)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SeatCapabilities is a representation of GDK's GdkSeatCapabilities
|
||||||
|
type SeatCapabilities int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SEAT_CAPABILITY_NONE SeatCapabilities = C.GDK_SEAT_CAPABILITY_NONE
|
||||||
|
SEAT_CAPABILITY_POINTER SeatCapabilities = C.GDK_SEAT_CAPABILITY_POINTER
|
||||||
|
SEAT_CAPABILITY_TOUCH SeatCapabilities = C.GDK_SEAT_CAPABILITY_TOUCH
|
||||||
|
SEAT_CAPABILITY_TABLET_STYLUS SeatCapabilities = C.GDK_SEAT_CAPABILITY_TABLET_STYLUS
|
||||||
|
SEAT_CAPABILITY_KEYBOARD SeatCapabilities = C.GDK_SEAT_CAPABILITY_KEYBOARD
|
||||||
|
SEAT_CAPABILITY_ALL_POINTING SeatCapabilities = C.GDK_SEAT_CAPABILITY_ALL_POINTING
|
||||||
|
SEAT_CAPABILITY_ALL SeatCapabilities = C.GDK_SEAT_CAPABILITY_ALL
|
||||||
|
)
|
||||||
|
|
||||||
|
func marshalSeatCapabilitiesLayout(p uintptr) (interface{}, error) {
|
||||||
|
c := C.g_value_get_enum((*C.GValue)(unsafe.Pointer(p)))
|
||||||
|
return SeatCapabilities(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubpixelLayout is a representation of GDK's GdkSubpixelLayout.
|
||||||
|
type SubpixelLayout int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SUBPIXEL_LAYOUT_UNKNOWN SubpixelLayout = C.GDK_SUBPIXEL_LAYOUT_UNKNOWN
|
||||||
|
SUBPIXEL_LAYOUT_NONE SubpixelLayout = C.GDK_SUBPIXEL_LAYOUT_NONE
|
||||||
|
SUBPIXEL_LAYOUT_HORIZONTAL_RGB SubpixelLayout = C.GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB
|
||||||
|
SUBPIXEL_LAYOUT_HORIZONTAL_BGR SubpixelLayout = C.GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR
|
||||||
|
SUBPIXEL_LAYOUT_VERTICAL_RGB SubpixelLayout = C.GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB
|
||||||
|
SUBPIXEL_LAYOUT_VERTICAL_BGR SubpixelLayout = C.GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR
|
||||||
|
)
|
||||||
|
|
||||||
|
func marshalSubpixelLayout(p uintptr) (interface{}, error) {
|
||||||
|
c := C.g_value_get_enum((*C.GValue)(unsafe.Pointer(p)))
|
||||||
|
return SubpixelLayout(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GdkDisplay
|
||||||
|
*/
|
||||||
|
|
||||||
|
// GetNMonitors is a wrapper around gdk_display_get_n_monitors().
|
||||||
|
func (v *Display) GetNMonitors() int {
|
||||||
|
c := C.gdk_display_get_n_monitors(v.native())
|
||||||
|
return int(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPrimaryMonitor is a wrapper around gdk_display_get_primary_monitor().
|
||||||
|
func (v *Display) GetPrimaryMonitor() (*Monitor, error) {
|
||||||
|
c := C.gdk_display_get_primary_monitor(v.native())
|
||||||
|
if c == nil {
|
||||||
|
return nil, nilPtrErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Monitor{glib.Take(unsafe.Pointer(c))}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMonitor is a wrapper around gdk_display_get_monitor().
|
||||||
|
func (v *Display) GetMonitor(num int) (*Monitor, error) {
|
||||||
|
c := C.gdk_display_get_monitor(v.native(), C.int(num))
|
||||||
|
if c == nil {
|
||||||
|
return nil, nilPtrErr
|
||||||
|
}
|
||||||
|
return &Monitor{glib.Take(unsafe.Pointer(c))}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMonitorAtWindow is a wrapper around gdk_display_get_monitor_at_window().
|
||||||
|
func (v *Display) GetMonitorAtWindow(w *Window) (*Monitor, error) {
|
||||||
|
c := C.gdk_display_get_monitor_at_window(v.native(), w.native())
|
||||||
|
if c == nil {
|
||||||
|
return nil, nilPtrErr
|
||||||
|
}
|
||||||
|
return &Monitor{glib.Take(unsafe.Pointer(c))}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMonitorAtPoint is a wrapper around gdk_display_get_monitor_at_point().
|
||||||
|
func (v *Display) GetMonitorAtPoint(x int, y int) (*Monitor, error) {
|
||||||
|
c := C.gdk_display_get_monitor_at_point(v.native(), C.int(x), C.int(y))
|
||||||
|
if c == nil {
|
||||||
|
return nil, nilPtrErr
|
||||||
|
}
|
||||||
|
return &Monitor{glib.Take(unsafe.Pointer(c))}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GdkSeat
|
||||||
|
*/
|
||||||
|
|
||||||
|
// GdkSeatGrabPrepareFunc
|
||||||
|
type GrabPrepareFunc func(seat *Seat, window *Window, user_data C.gpointer)
|
||||||
|
|
||||||
|
// GetDisplay is a wrapper around gdk_seat_get_display().
|
||||||
|
func (v *Seat) GetDisplay() (*Display, error) {
|
||||||
|
return toDisplay(C.gdk_seat_get_display(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab is a wrapper around gdk_seat_grab().
|
||||||
|
func (v *Seat) Grab(window *Window, capabilities SeatCapabilities, owner_events bool, cursor *Cursor, event *Event, prepare_func GrabPrepareFunc, prepare_func_data C.gpointer) GrabStatus {
|
||||||
|
return GrabStatus(C.gdk_seat_grab(v.native(), window.native(), C.GdkSeatCapabilities(capabilities), gbool(owner_events), cursor.native(), event.native(), (*[0]byte)(C.gpointer(callback.Assign(prepare_func))), prepare_func_data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnGrab is a wrapper around gdk_seat_ungrab().
|
||||||
|
func (v *Seat) UnGrab() {
|
||||||
|
C.gdk_seat_ungrab(v.native())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCapabilities is a wrapper around gdk_seat_get_capabilities().
|
||||||
|
func (v *Seat) GetCapabilities() SeatCapabilities {
|
||||||
|
return SeatCapabilities(C.gdk_seat_get_capabilities(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetKeyboard is a wrapper around gdk_seat_get_keyboard().
|
||||||
|
func (v *Seat) GetKeyboard() (*Device, error) {
|
||||||
|
return toDevice(C.gdk_seat_get_keyboard(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSlaves is a wrapper around gdk_seat_get_slaves().
|
||||||
|
func (v *Seat) GetSlaves(capabilities SeatCapabilities) *[]Device {
|
||||||
|
|
||||||
|
clist := C.gdk_seat_get_slaves(v.native(), C.GdkSeatCapabilities(capabilities))
|
||||||
|
if clist == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dlist := glib.WrapSList(uintptr(unsafe.Pointer(clist)))
|
||||||
|
defer dlist.Free()
|
||||||
|
|
||||||
|
var slaves = make([]Device, 0, dlist.Length())
|
||||||
|
for ; dlist.DataRaw() != nil; dlist = dlist.Next() {
|
||||||
|
|
||||||
|
d := (*C.GdkDevice)(dlist.DataRaw())
|
||||||
|
obj := &glib.Object{glib.ToGObject(unsafe.Pointer(d))}
|
||||||
|
|
||||||
|
slaves = append(slaves, Device{obj})
|
||||||
|
}
|
||||||
|
return &slaves
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GdkMonitor
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Monitor is a representation of GDK's GdkMonitor.
|
||||||
|
type Monitor struct {
|
||||||
|
*glib.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// native returns a pointer to the underlying GdkMonitor.
|
||||||
|
func (v *Monitor) native() *C.GdkMonitor {
|
||||||
|
if v == nil || v.GObject == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p := unsafe.Pointer(v.GObject)
|
||||||
|
return C.toGdkMonitor(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Native returns a pointer to the underlying GdkMonitor.
|
||||||
|
func (v *Monitor) Native() uintptr {
|
||||||
|
return uintptr(unsafe.Pointer(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalMonitor(p uintptr) (interface{}, error) {
|
||||||
|
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||||
|
obj := &glib.Object{glib.ToGObject(unsafe.Pointer(c))}
|
||||||
|
return &Monitor{obj}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toMonitor(s *C.GdkMonitor) (*Monitor, error) {
|
||||||
|
if s == nil {
|
||||||
|
return nil, nilPtrErr
|
||||||
|
}
|
||||||
|
obj := &glib.Object{glib.ToGObject(unsafe.Pointer(s))}
|
||||||
|
return &Monitor{obj}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDisplay is a wrapper around gdk_monitor_get_display().
|
||||||
|
func (v *Monitor) GetDisplay() (*Display, error) {
|
||||||
|
return toDisplay(C.gdk_monitor_get_display(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGeometry is a wrapper around gdk_monitor_get_geometry().
|
||||||
|
func (v *Monitor) GetGeometry() *Rectangle {
|
||||||
|
var rect C.GdkRectangle
|
||||||
|
|
||||||
|
C.gdk_monitor_get_geometry(v.native(), &rect)
|
||||||
|
|
||||||
|
return wrapRectangle(&rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWorkarea is a wrapper around gdk_monitor_get_workarea().
|
||||||
|
func (v *Monitor) GetWorkarea() *Rectangle {
|
||||||
|
var rect C.GdkRectangle
|
||||||
|
|
||||||
|
C.gdk_monitor_get_workarea(v.native(), &rect)
|
||||||
|
|
||||||
|
return wrapRectangle(&rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWidthMM is a wrapper around gdk_monitor_get_width_mm().
|
||||||
|
func (v *Monitor) GetWidthMM() int {
|
||||||
|
return int(C.gdk_monitor_get_width_mm(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeightMM is a wrapper around gdk_monitor_get_height_mm().
|
||||||
|
func (v *Monitor) GetHeightMM() int {
|
||||||
|
return int(C.gdk_monitor_get_height_mm(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetManufacturer is a wrapper around gdk_monitor_get_manufacturer().
|
||||||
|
func (v *Monitor) GetManufacturer() string {
|
||||||
|
// transfer none: don't free data after the code is done.
|
||||||
|
return C.GoString(C.gdk_monitor_get_manufacturer(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetModel is a wrapper around gdk_monitor_get_model().
|
||||||
|
func (v *Monitor) GetModel() string {
|
||||||
|
// transfer none: don't free data after the code is done.
|
||||||
|
return C.GoString(C.gdk_monitor_get_model(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetScaleFactor is a wrapper around gdk_monitor_get_scale_factor().
|
||||||
|
func (v *Monitor) GetScaleFactor() int {
|
||||||
|
return int(C.gdk_monitor_get_scale_factor(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRefreshRate is a wrapper around gdk_monitor_get_refresh_rate().
|
||||||
|
func (v *Monitor) GetRefreshRate() int {
|
||||||
|
return int(C.gdk_monitor_get_refresh_rate(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubpixelLayout is a wrapper around gdk_monitor_get_subpixel_layout().
|
||||||
|
func (v *Monitor) GetSubpixelLayout() SubpixelLayout {
|
||||||
|
return SubpixelLayout(C.gdk_monitor_get_subpixel_layout(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPrimary is a wrapper around gdk_monitor_is_primary().
|
||||||
|
func (v *Monitor) IsPrimary() bool {
|
||||||
|
return gobool(C.gdk_monitor_is_primary(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GdkDevice
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// gdk_device_get_axes().
|
||||||
|
// gdk_device_tool_get_serial().
|
||||||
|
// gdk_device_tool_get_tool_type().
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GdkGLContext
|
||||||
|
*/
|
||||||
|
|
||||||
|
// GetUseES is a wrapper around gdk_gl_context_get_use_es().
|
||||||
|
func (v *GLContext) GetUseES() bool {
|
||||||
|
return gobool(C.gdk_gl_context_get_use_es(v.native()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUseES is a wrapper around gdk_gl_context_set_use_es().
|
||||||
|
func (v *GLContext) SetUseES(es int) {
|
||||||
|
C.gdk_gl_context_set_use_es(v.native(), (C.int)(es))
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user