gio-plugins

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2024 License: BSD-3-Clause, MIT

README

Gio-Plugins

Gio plugins is a system to use third-party plugins similar to Gio features, this package also holds one collection of plugins for the Gio. All plugins uses the same interface, and just one line of code must be added in the main-loop, as explained below. Furthermore, some packages can be used as standalone and doesn't require the plugin package.

That package also serves as experimentation ground for "plugin system", which may land to Gio in the future.

Motivation

Gio is a great GUI library, but it lacks some features that are important for some applications. I worked in some extensions before, and I also maintained one fork of Gio, which contains some changes. However, that leads to many issues: keeping the fork updated is problematic. Creating extensions that are similar to Gio is impossible.

I decided to create a plugin system to make it easier to use third-party extensions. I also proposed this idea to the Gio-core .

Usage

First, you must download the plugin package:

go get -u github.com/gioui-plugins/gio-plugins@latest

Now, you need to modify your event-loop, you must include plugin.Install() in your event-loop, before handling events:

for evt := range w.Events() { // Gio main event loop
+    plugin.Install(w, evt)

    switch evt := evt.(type) {
        // ...
    }
}

Each plugin has its own README.md file, explaining how to use it. In general, you can simple use nameOfPlugin.SomeOp{}.Add(gtx.Ops), similar of how you use clipboard.ReadOp{}.Add(gtx.Ops), native from Gio.

Once plugin.Install is set, you can use the plugins as simple op commands. If you are unsure if the plugin is working, you can use the pingpong package, which will return on PongEvent to the given Tag:

pingpong.PingOp{Tag: &something}.Add(gtx.Ops)

You can receive responses using the Tag, as Gio-core operations:

for _, evt := range gtx.Events(&something) {
    if evt, ok := evt.(pingpong.PongEvent); ok {
        fmt.Println(evt.Pong)
    } 
}

Of course, pingpong has no use in real-world applications, but it can be used to test if the plugin is working.

Plugins

We have few plugins available:

Name Description OS
PingPong Test if the plugin system is working. Android, iOS, macOS, Windows, WebAssembly, Linux, FreeBSD
Share Share text/links using the native share dialog. Android, iOS, macOS, Windows, WebAssembly
WebViewer Display in-app webview using the native webview implementation on each platform. Android, iOS, macOS, Windows, WebAssembly
Hyperlink Open hyperlinks in the default browser. Android, iOS, macOS, Windows, WebAssembly
Explorer Opens the native file-dialog, to read/write files. Android, iOS, macOS, Windows, WebAssembly
Safedata Read/Write files into the secure storage of the device. Android, iOS, macOS, Windows, WebAssembly
We have few plugins planned:

Some plugins are planned, but not yet implemented, follow the development at https://github.com/orgs/gioui-plugins/projects/1. Also, consider send some 👍 on issues which mentions features that you like.

If you want to help, please open an issue or a PR! If you want to suggest a plugin, please open an issue.


Creating a new plugin

If you want to create a new plugin, you can check the pingpog package, which is the simplest plugin available. Generally, you need implement plugin.Handler, and call plugin.Register in your init() function. Your code will get specific events and ops, which you define in your Handler implementation.

Limitations
  • Android: XML/Manifest: There's no direct integration with gogio. Consequently, your plugin cannot require any additional XML file or changes in the manifest. That may limit some plugins, but it's a limitation of gogio itself.
  • General: Position: There's no way to get relative position of each operation, or mimic the paint.PaintOp{}, so if your plugin is adding views to the screen, you must use absolute positions. This is a limitation of Gio itself, which doesn't easily expose the relative position of each operation.

Compatibility

Most packages are compatible with the latest version of Gio, and only the latest version should be supported. Beware that internal changes in the Gio API can break the compatibility with plugin. None of the packages has stable API, and breaking changes can happen at any time.

Most plugins are compatible with Android 5+, iOS 13+, MacOS 12+, Windows 10+ and WebAssembly. Currently, we consider the Windows and Android as high-priority, and the WebAssembly as medium-priority, MacOS and iOS as low-priority. Furthermore, we don't have any plans to support Linux and FreeBSD due to the low market-share and the lack of API standards.

Security

This package heavily uses unsafe, and as it suggest: it can be unsafe to use. We are not responsible for any damage caused by this package. Some plugins also use unsafe and CGO to interact with the native platform. While we try to keep the code safe, we can't guarantee that it is safe enough for your use-case. Also, is impossible to verify the integrity of native-APIs, so we can't guarantee that the native-APIs will have the expected behavior.

Testing

Since we have limited resources and devices, we can't test all plugins on all platforms and devices. Currently, we have a few devices available and with limited range of OS versions. Plugins are usually tested on those devices:

  • Android: Motorola Droid Max, Motorola E6, Xiaomi A7, Xiaomi Note 9, (+ BrowserStack)
  • iOS: iPhone SE 2Gen (2020), (+ BrowserStack)
  • WASM: Chrome, Firefox, Safari, (+ BrowserStack)
  • Windows: Custom (Ryzen 3900X+RX 5700XT), Proxmox VM (EPYC 7501P)
  • MacOS: MacBook Air (M1, 2020)
  • Linux: Proxmox VM (EPYC 7501P)
  • FreeBSD: Proxmox VM (EPYC 7501P)

Tests are performed manually, since most features interact with the native platform, and automated tests are not easy to implement. We are open to suggestions on how to improve the testing process.

Please, if you find any bug, open an issue or a PR!

Hacking

Each OS has its own way to interact with the native APIs. For example, on Android, you need to create a Java class and call it using JNI. On iOS and MacOS you need to write some Objective-C code and call it using CGO. On Windows, you need to write some code using syscall to each DLL, which may use COM API, some APIs uses WinRT instead of Win32, which can be harder to use. On WebAssembly, you need to use syscall/js to interact with the browser APIs, or use InkWasm, which is faster. On Linux/FreeBSD you may need to use C and CGO to interact with the native APIs.

License

This package is licensed under the MIT License, some pre-compiled files may have other license. See the LICENSE file for details.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL