~eliasnaur/gio#8:
X11 support

IIUC, gio currently requires Wayland, which I don’t (yet) have in any of my Linux environments for various reasons.

I suspect I’m not the only one with this issue. Is there any chance X11 support could be added?

Thanks in advance,

Status
REPORTED
Submitter
~stapelberg
Assigned to
No-one
Submitted
2 months ago
Updated
a day ago
Labels
No labels applied.

~eliasnaur 2 months ago

I had hoped to avoid X11 support altogether given the stage of the Wayland transition. However, given enough interest, there is no technical reason X11 couldn't be added.

~stapelberg 2 months ago

I think you might be over-estimating how far the Wayland transition is along :)

I certainly will have to use X11 in various environments for years to come.

~dolanor 2 months ago

Same here, still on Ubuntu 16.04, and given the feedbacks of breakage with 18.04, I'm hesitant to migrate.

~rkanchan 2 months ago

Same with elementaryOS Juno. Wayland is yet to arrive.

~theclapp 2 months ago

I don't know much about Wayland. Is there some docker- or vm-based solution y'all could run? That is, some docker image or virtual machine image that runs Wayland, that you could use to run Gio? What's a few gig of disk among friends? :)

Failing that, I've had some luck getting Gio to run in Chrome on the Mac, so running via your browser might be a possibility.

Failing that ... there's only (he said naively) about 1500 lines of Go and C (mostly Go) in the Wayland-specific code. (There's about 3400 lines of generated C.) Are Wayland and X11 similar enough that the Wayland code would make the X11 port comparatively easy? (Compared to developing it from scratch.)

~mvdan 2 months ago

Yesterday, I successfully ran sway out of the box within X11, fired a terminal, and ran a couple of gio examples in Wayland. Ctrl+D allows you to run any program via dmenu, so that let me start my terminal emulator.

It's a bit clunky, because the parent window manager takes precedence with keyboard shortcuts, but it mostly works.

Having said this, I agree X11 support would be good. We all have plans to move to Wayland eventually, but I think X11 support would be key to Gio's success in the short term.

~eliasnaur could you write a short doc with the steps one would have to follow to implement X11 support? Perhaps then someone with enough interest could step in and start contributing patches.

~eliasnaur 2 months ago

~eliasnaur could you write a short doc with the steps one would have to follow to implement X11 support? Perhaps then someone with enough interest could step in and start contributing patches.

Good idea.

The platform specific packages in Gio are ui/app and ui/app/internal/gl.

I don't think you need anything X11 specific in the gl package.

The app package takes care of creating a native window, binding an OpenGL ES context and handling input. I suggest you use the Wayland port as a starting point.

Dynamic switching between the Wayland and X11 backends would be nice, but as a first goal I suggest defining a build tag, say x11, that switches from Wayland to X11 at build time.

So the first step is adding

// +build !x11

to every wayland-specific Go and C files. You'll have to modify the go:generate directives in oswayland.go to add the x11 condition to the generated Wayland C files (waylandxdgshell.c, waylandxdgdecoration.c, waylandtext_input.c).

What I usually do at this point of adding a new port is to make minimal changes and empty types, functions, methods etc. to make a Gio program build and run. Use the hello or gophers example for that.

Then, I work through the necessary steps for creating a Window and binding a context. The goal is to get the drawing to show up in a window. Note that Gio programs won't draw before Window.setStage(StateRunning) has been called.

For input I wire up event handling to route mouse and keyboard input back to the Gio program. My experience with X11 tells that this is where most of the issues will be. Things like key code translation, scroll wheel etc. were fiddly when I did the X11 port for LWJGL.

Finally, polish: lifecycle for minimizing/maxizing, setting the window title and size and so on.

Hope that helps. I'll gladly expand on any issues you run into.

  • elias

~dennwc a month ago

Initial version of X11 backend can be checked here:

https://github.com/dennwc/gio/commits/x11_test

It currently supports: - Rendering - Window resize - Window close - Mouse events

To test it, add this line to your go.mod:

replace gioui.org/ui => github.com/dennwc/gio/ui v0.0.0-20190828194120-1078c141cc54

This change will be submitted to the upstream soon.

~eliasnaur a month ago

On Thu Aug 29, 2019 at 9:03 PM ~dennwc wrote:

Initial version of X11 backend can be checked here:

https://github.com/dennwc/gio/commits/x11_test

It currently supports:

  • Rendering
  • Window resize
  • Window close
  • Mouse events

Very nice!

-- elias

~rkanchan a month ago

Awesome work ~dennwc. Tested with success, the hello app on elementaryOS. Thank you

~rkanchan a month ago

text input is not working for me in the gophers app. In fact it did not work in the wayland version as well when I had earlier tried inside of a VM(ubuntu 18.04)

~dolanor a month ago

Nice, I need to try it! Will come back with feedback.

~dolanor a month ago

It works. That is my feedback. That's great! Thanks!

~dennwc a month ago

text input is not working for me in the gophers app

~rkanchan X11 backend doesn't support keyboard input yet :)

~rkanchan a month ago

ah ok. I'll wait for it :)

~cryptix referenced this from #35 a month ago

~eliasnaur referenced this from #35 a month ago

~fhs a month ago

Yesterday, I successfully ran sway out of the box within X11, fired a terminal, and ran a couple of gio examples in Wayland. Ctrl+D allows you to run any program via dmenu, so that let me start my terminal emulator.

It's a bit clunky, because the parent window manager takes precedence with keyboard shortcuts, but it mostly works.

A better alternative to running it within sway is the run in inside cage. Just run:

cage gio_app_command

and it opens a standalone window with the app. I'd imagine clipboard sharing will still be an issue, so a native X11 support would be great.

~rkanchan 21 days ago

~dennwc Are you still working on the X11 backend?

~eliasnaur 21 days ago

FWIW, I extracted the XKB logic to a separate file independent of Wayland. Perhaps the X11 backend can reuse the code.

https://gioui.org/commit/51cfb4e

~dennwc 21 days ago

Are you still working on the X11 backend?

Yes, but I was busy recently. Will make the changes in following days.

FWIW, I extracted the XKB logic to a separate file independent of Wayland. Perhaps the X11 backend can reuse the code.

This is awesome! I'll check if I can reuse it directly, or there is something else needed on X11 side.

On Thu, 26 Sep 2019 at 11:05, ~eliasnaur outgoing@sr.ht wrote:

FWIW, I extracted the XKB logic to a separate file independent of Wayland. Perhaps the X11 backend can reuse the code.

https://gioui.org/commit/51cfb4e

View on the web: https://todo.sr.ht/~eliasnaur/gio/8#comment-3896

Denys

~dennwc referenced this from #8 21 days ago

~dennwc 15 days ago

~eliasnaur Still busy, sorry. If you have time to apply the mentioned change, may I ask you to do it on your side? I'll jump back to it to finish XKB as soon as I can.

On Thu, 26 Sep 2019 at 14:07, Denys Smirnov denis.smirnov.91@gmail.com wrote:

Are you still working on the X11 backend?

Yes, but I was busy recently. Will make the changes in following days.

FWIW, I extracted the XKB logic to a separate file independent of Wayland. Perhaps the X11 backend can reuse the code.

This is awesome! I'll check if I can reuse it directly, or there is something else needed on X11 side.

On Thu, 26 Sep 2019 at 11:05, ~eliasnaur outgoing@sr.ht wrote:

FWIW, I extracted the XKB logic to a separate file independent of Wayland. Perhaps the X11 backend can reuse the code.

https://gioui.org/commit/51cfb4e

View on the web: https://todo.sr.ht/~eliasnaur/gio/8#comment-3896

Denys

Denys

~dennwc referenced this from #8 15 days ago

~eliasnaur 15 days ago

On Wed Oct 2, 2019 at 12:01 PM ~dennwc wrote:

~eliasnaur Still busy, sorry. If you have time to apply the mentioned

change, may I ask you to do it on your side? I'll jump back to it to

finish XKB as soon as I can.

I'm not sure what change you're referring to.

-- elias

~dennwc 15 days ago

The move/rename of the native type (C type for EGL).

~eliasnaur 15 days ago

On Wed Oct 2, 2019 at 6:21 PM ~dennwc wrote:

The move/rename of the native type (C type for EGL).

Done in 9e2c413c1d2ecead60feb07e7863ca368ffd3be8 and fc5b660efc31e38e10acfdba02101da09736f0ea.

-- elias

~eliasnaur 15 days ago

On Wed Oct 2, 2019 at 11:31 PM Elias Naur wrote:

On Wed Oct 2, 2019 at 6:21 PM ~dennwc wrote:

The move/rename of the native type (C type for EGL).

Done in 9e2c413c1d2ecead60feb07e7863ca368ffd3be8 and fc5b660efc31e38e10acfdba02101da09736f0ea.

Whoops, I mean

gioui.org/commit/2dcbf6fe3c9e648c9c8ef049aa58ad4873ccb858
gioui.org/commit/07a36d71d9b0e6c89b6d750b03bb026500ff2dd7

-- elias

~eliasnaur closed duplicate ticket #40 13 days ago

~stuartdd closed duplicate ticket #40 13 days ago

~db47h 8 days ago

While dynamic fallback from Wayland to X11 would be a nice feature, it requires the executable to dynamically link with libwayland-egl.so and a couple others (unless we start to do ugly things like dl'open/GetProcAddress). I'm not sure that this is desirable for X11 builds.

~eliasnaur 7 days ago

On Wed Oct 9, 2019 at 4:11 PM ~db47h wrote:

While dynamic fallback from Wayland to X11 would be a nice feature, it requires the executable to dynamically link with libwayland-egl.so and a couple others (unless we start to do ugly things like dl'open/GetProcAddress). I'm not sure that this is desirable for X11 builds.

I suspect many systems have libwayland-egl.so installed even though the user runs X11.

Your point is still valid, however. A less radical solution is a nowayland tag for building without Wayland support.

~db47h 7 days ago

Your point is still valid, however. A less radical solution is a nowayland tag for building without Wayland support.

fair enough. Looking at the current implementation, I'm wondering why Window.driver is not an actual interface: there's a check that the window type implements a non-declared driver interface, so why not declare it as such? It would make implementing the wayland and x11 drivers (with optional support for the other) much easier.

~eliasnaur 7 days ago

On Thu Oct 10, 2019 at 1:36 PM ~db47h wrote:

Your point is still valid, however. A less radical solution is a nowayland tag for building without Wayland support.

fair enough. Looking at the current implementation, I'm wondering why Window.driver is not an actual interface: there's a check that the window type implements a non-declared driver interface, so why not declare it as such? It would make implementing the wayland and x11 drivers (with optional support for the other) much easier.

FWIW, I believe ~dennwc's work incomplete patch promotes the anonymous interface to a named type.

I tend to avoid interfaces I don't need, and Gio didn't need multiple drivers in one build before X11.

~db47h 6 days ago

FWIW, I believe ~dennwc's work incomplete patch promotes the anonymous interface to a named type.

He resorted to a stub window type that hods pointers to a wlWindow and an x11Window and calls methods of x11Window if the wlWindow is nil.

I tend to avoid interfaces I don't need, and Gio didn't need multiple drivers in one build before X11.

Same here. I was just wondering if it would have any non obvious side effects.

Since @dennwc looks busy, I took the liberty to go ahead and integrate his work on top of latest master: https://github.com/db47h/gio/commits/x11 (still without keyboard support).

The first two commits are pretty straight forward: decalre a windowDriver interface, make newContext a window method in order to prevent conflicts between eglDriver/windowDriver, and remove refs to the wayland-only conn variable in the xkb driver.

X11 support proper is a straight copy-paste of ~dennwc's os_x11.go. I just added the few bits and pieces to have the default linux builds to provide dual wayland/x11 support and optionally disabling them with a nowayland or nox11 tag.

If this looks good to everyone, I'd like to go ahead and add keyboard support.

Denis

~eliasnaur 6 days ago

On Fri Oct 11, 2019 at 1:15 PM ~db47h wrote:

Since @dennwc looks busy, I took the liberty to go ahead and integrate his work on top of latest master: https://github.com/db47h/gio/commits/x11 (still without keyboard support).

Great!

The first two commits are pretty straight forward: decalre a windowDriver interface, make newContext a window method in order to prevent conflicts between eglDriver/windowDriver, and remove refs to the wayland-only conn variable in the xkb driver.

X11 support proper is a straight copy-paste of ~dennwc's os_x11.go. I just added the few bits and pieces to have the default linux builds to provide dual wayland/x11 support and optionally disabling them with a nowayland or nox11 tag.

If this looks good to everyone, I'd like to go ahead and add keyboard support.

Looks good to me; I left a few comments on GitHub. I also took the liberty of integrating your xkb fix.

~db47h 5 days ago

Updated with EGL stuff moved where it belongs. Sorry, I did a force push after rebasing on master with the xkb changes so your comments are gone.

Anyhow, about using an array for drivers in https://github.com/db47h/gio/commit/1c5614b4ed63104f8f98b0ad3eff50312a3b39f6#diff-70a2c89ac82cfe06c897443a159d0563 : I thought about it, but for only two linux specific drivers, I believe it would be a bad case of over engineering (need to set-up some self-registering mechanism with a mutex and a priority system).

On the other hand, this could be the basis for multi-driver support on all platforms (I'm thinking native win API instead of EGL on Windows), but it needs some more thought. For example on what kind of errors do we fallback to the next driver (had to declare errWLDisplayConnectFailed in os_linux.go), how to setup priorities and so on. Maybe talk about it in another issue thread?

~eliasnaur 5 days ago

On Sat Oct 12, 2019 at 12:54 PM ~db47h wrote:

Updated with EGL stuff moved where it belongs. Sorry, I did a force push after rebasing on master with the xkb changes so your comments are gone.

Anyhow, about using an array for drivers in https://github.com/ db47h/gio/commit/1c5614b4ed63104f8f98b0ad3eff50312a3b39f6#diff-70a2c89ac 82cfe06c897443a159d0563 : I thought about it, but for only two linux specific drivers, I believe it would be a bad case of over engineering (need to set-up some self-registering mechanism with a mutex and a priority system).

I don't think you need a mutex, since the drivers are registered in init functions that run in a single goroutine.

You're right about priorities, however. Go probably runs init functions within a package in a particular order, but that's too subtle to rely on.

~db47h 5 days ago

I don't think you need a mutex, since the drivers are registered in init functions that run in a single goroutine.

That's correct, and they are called in lexical order. But like you said, too subtle to rely on.

~db47h 2 days ago

Keyboard support added: https://github.com/db47h/gio/commit/f6458e67809bb39985cc9526be35aff6b7595798

I didn't use XKB and went for XIM. A few things worth noting:

  • setlocale needs to be called in createWindow(). It is only set temporarily for XOpenIM then reverted back to whatever it was before. I don't like to call setlocale in general, even less in Go, but this is unavoidable here.
  • CTRL-SHIFT-U + unicode code point works, however the helper window showing what code point you enter appears at the bottom left of the GIO window. If anyone has a clue on how to move it or better show it inline in a text editor, that would be awesome. Plus it shouldn't be available unless actively editing something.

TODOs:

  • merge master...
  • proper dp/sp setup
  • animation

~eliasnaur 2 days ago

On Tue Oct 15, 2019 at 1:50 PM ~db47h wrote:

Keyboard support added: https://github.com/db47h/gio/commit/f6458e67809b b39985cc9526be35aff6b7595798

Nice.

I didn't use XKB and went for XIM. A few things worth noting:

  • CTRL-SHIFT-U

?

  • unicode code point works, however the helper window showing what code point you enter appears at the bottom left of the GIO window. If anyone has a clue on how to move it or better show it inline in a text editor, that would be awesome.

This is not something the Editor supports today.

Gio needs better support for IMs for the mobile platforms, at which point I suspect the OS would like to know the window coordinates of the caret.

Plus it shouldn't be available unless actively editing something.

Gio calls ShowTextInput(visible) on the native window to guide the soft keyboards on the mobiles. Perhaps that is also useful to show and hide the XIM window.

~db47h 2 days ago

On a bog standard Ubuntu/X11/Gnome you can enter any unicode code point by pressing CTRL-SHIFT-U followed by the hex value of the unicode code point (much like Alt+keypad on Windows). For example, to enter (U+2026), press CTRL-SHIFT-U, 2, 0, 2, 6, Enter. While you key in the code point, and depending on the application, you have either a small window near the caret that shows an underscored u followed by whatever you enter or it's just displayed inline in the input widget (like chrome does).

Gio calls ShowTextInput(visible) on the native window to guide the soft keyboards on the mobiles. Perhaps that is also useful to show and hide the XIM window.

Good thinking. I'll have to check for possible issues with devices without a physical keyboard though.

Onto merging master...

~db47h 2 days ago

And master merged: https://github.com/db47h/gio/tree/x11_v2

Still need to implement animation before it's usable.

~eliasnaur a day ago

On Wed Oct 16, 2019 at 4:07 PM ~db47h wrote:

Basic animation added : https://github.com/db47h/gio/tree/x11_v2

It is in a usable state, so please give it a go.

I said basic animation because right now the event loop is throttled to draw at a fixed 1/60s interval while animating. While this helps limit CPU usage from the app itself, oddly enough Gnome Shell shows 80% CPU usage...

Is there any way to get feedback from eglDriver.Present() (i.e. vsync), or some other timer in gio in order to throttle the event loop? Well, I know that hoping for a reliable vsync is a pipe dream on X11, but a ticker from gio would be awesome.

There is eglSwapInterval. See the comment in egl.go:

// eglSwapInterval 1 leads to erratic frame rates and unnecessary blocking.
    // We rely on platform specific frame rate limiting instead, except on Windows
    // where eglSwapInterval is all there is.
    if runtime.GOOS != "windows" {
      eglSwapInterval(eglCtx.disp, 0)
    } else {
      eglSwapInterval(eglCtx.disp, 1)
    }

I suppose eglSwapInterval should be used on X11 as well.

~db47h a day ago

Yes, eglSwapInterval should be used on X11, but since context.Present() calls it already, I was hoping for a notification that the function has returned. On the other hand, one cannot rely on vsync on X11 since it's not always working, especially on optimus laptops.

Here's where I'm coming from: https://web.archive.org/web/20190506122532/http://gafferongames.com/post/fix_your_timestep/

In the main loop, I usually wait for events if there is no animation going on, and just poll events if there is any animation. The only thing that is expected from the platform driver is a PollEvent() and an abortable WaitForEvent(). All this with vsync enabled: no tearing and no erratic frame rate.

Also, since one can never be sure that vsync works, I throw in a frame throttling mechanism, just not to kill the CPU while doing nothing (then rely on gl.Flush and hope for the best tearing-wise).

~eliasnaur a day ago

On Wed Oct 16, 2019 at 5:29 PM ~db47h wrote:

Yes, eglSwapInterval should be used on X11, but since context.Present() calls it already, I was hoping for a notification that the function has returned. On the other hand, one cannot rely on vsync on X11 since it's not always working, especially on optimus laptops.

It's possible we're talking past each other. Yes, eglSwapBuffers is called by Present, but eglSwapInterval(1) for enabling v-sync (as far as the driver allows), is currently called on Windows only.

There is an implicit notification that eglSwapBuffers completed: the gpu.Flush call waits for the result of the previous frame before returning, which includes the buffer swap. The separate Flush is necessary to give the main goroutine a chance to work concurrently with the GPU goroutine.

On Wayland eglSwapInterval is 0, but the frame rate is throttled by wayland frame callbacks instead, as per

https://emersion.fr/blog/2018/wayland-rendering-loop/

Here's where I'm coming from: https://web.archive.org/web/20190506122532/http://gafferong ames.com/post/fixyourtimestep/

In the main loop, I usually wait for events if there is no animation going on, and just poll events if there is any animation. The only thing that is expected from the platform driver is a PollEvent() and an abortable WaitForEvent(). All this with vsync enabled: no tearing and no erratic frame rate.

It's entirely possible the animation protocol between app.Window and the native peer could be improved. I'm open to alternative designs.

Also, since one can never be sure that vsync works, I throw in a frame throttling mechanism, just not to kill the CPU while doing nothing (then rely on gl.Flush and hope for the best tearing-wise).

SGTM.

-- elias

~db47h a day ago

It's possible we're talking past each other. Yes, eglSwapBuffers is called by Present, but eglSwapInterval(1) for enabling v-sync (as far as the driver allows), is currently called on Windows only.

Yes, sorry about that. I did not see the eglSwapInterval(0) on linux. And I still don't have a full picture of the various goroutines running and how they interact with each other.

Thanks for the clarification on how this works on Wayland.

It's entirely possible the animation protocol between app.Window and the native peer could be improved. I'm open to alternative designs.

I'll get a fully working X11 implementation first ;)

Register here or Log in to comment, or comment via email.