linebender/druid

X11 backend tracking issue

crsaracco opened this issue · 7 comments

This is a tracking issue for implementing an X11 druid-shell backend.

I expect that I'll be doing a lot of the implementation, but others are free to jump in as well!

Background / Motivation

VST plugins are always given a platform-native window to attach to (see #468).

Druid has platform-native backends for Mac OS (cocoa) and Windows (winapi), but uses GTK as the backend for Linux, which is non-"native".

In order to use Druid for VST plugin GUIs on X11 platforms, we need to implement an X11 druid-shell backend.

X11 windows are also compatible inside Wayland, so I think this should work for VSTs in Wayland environments, although I haven't tested this myself yet. (maybe not, see comments)

See #468 for some more VST-related background/motivation. Others may also find having a native X11 backend useful for other use cases.

Implementation details

I intend to keep GTK as the main backend for Linux, and only enable X11 if users specifically request it through a feature flag.

I'm planning to use the rust-xcb crate for interfacing with X11/XCB.

Progress

Each check mark corresponds roughly to one PR. This list might be incomplete; I will add to it as I discover more requirements.

  • (PR: #599) Bare-minimum X11 backend implemented
    • backend is behind a feature flag, basic window handling implemented, painting to the window implemented, and mouse + keyboard events are handled. Some hacks were involved in completing this, which will be handled in future bullet points / PRs.
  • (Issue: #829) Fix program not terminating when the window closes (users have to ^C to get it to quit)
  • Fix window syncing hack
    • Currently figure out the screen's refresh rate and sleep (!) for however long based on the refresh rate, which is probably not what we want to do. Better way to sync draws?
    • This might also be what's causing the window to blink a lot during re-rendering; if fixing this hack doesn't solve that issue, make a new task in this list.
  • Menu support
    • we might have to draw these ourselves? Or figure out a way to request the system's WM to do it for you?
  • Errors implemented in druid-shell/src/platform/x11/error.rs, and applied to the rest of the backend where necessary
  • Timer support implemented (WindowHandle::request_timer, etc)
  • Idle handle support (WindowHandle::get_idle_handle, etc)
  • File dialog support
  • Clipboard support
  • Locale support
  • DPI scaling support
  • Keyboard events are in a "proof-of-concept" state; clean it up (see #599, but also needs some discussion)
  • Investigate use of lazy_static and thread_local -- might not be suitable for a child window use-case (with VSTs being one such example)
    • Probably have to investigate other platforms too.
  • Investigate issue with window resizing where the window flies away from the user (I couldn't reproduce)
  • Custom mouse cursor support Druid-wide issue: #104

X11 windows are also compatible inside Wayland, so I think this should work for VSTs in Wayland environments, although I haven't tested this myself yet.

I think this is unlikely. Wayland is backwards-compatible with X11 clients, but if a native Wayland client creates a Wayland window, it is unlikely to be addressable as an X11 window.

Good to know (I'm not familiar with Wayland, just repeating something I thought I heard), thanks!

I need to access xcb::Connection, and the xcb::Window to get more native control for the window, for example position, and other properties that I can get by xprop:

_NET_WM_STATE(ATOM) = _NET_WM_STATE_ABOVE
_NET_WM_DESKTOP(CARDINAL) = 0
WM_STATE(WM_STATE):
		window state: Normal
		icon window: 0x0
_NET_WM_USER_TIME(CARDINAL) = 30033792
WM_NAME(UTF8_STRING) = "Vonal"
_NET_WM_NAME(UTF8_STRING) = "Vonal"
WM_NORMAL_HINTS(WM_SIZE_HINTS):
		program specified location: 0, 1060
		program specified minimum size: 3840 by 312
		program specified maximum size: 3840 by 312
XdndAware(ATOM) = BITMAP
_MOTIF_WM_HINTS(_MOTIF_WM_HINTS) = 0x2, 0x0, 0x0, 0x0, 0x0
_NET_WM_BYPASS_COMPOSITOR(CARDINAL) = 2
_NET_WM_SYNC_REQUEST_COUNTER(CARDINAL) = 14680066, 14680067
_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED(CARDINAL) = 1
WM_WINDOW_ROLE(STRING) = "browser-window"
WM_CLASS(STRING) = "vonal", "vonal"
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
_NET_WM_PID(CARDINAL) = 1055
WM_LOCALE_NAME(STRING) = "en_US.UTF-8"
WM_CLIENT_MACHINE(STRING) = "dbiro"
WM_PROTOCOLS(ATOM): protocols  WM_DELETE_WINDOW, _NET_WM_PING, _NET_WM_SYNC_REQUEST

It would be nice to have all this feature wrapped into a druid, but that's impossible.
Imagine it like a data Validator library that is awesome in validating email, phone number, etc..., but someone needs to validate, for e.g, URL which is not implemented. Since that's an unusual requirement, that shouldn't be implemented in the Validator, but Validator should support custom validations.

Anyway, I would like to contribute with this, but for the first glimpse, Druid uses GTK to make windows, and GTK also hides X, so I would need help.

@Ralith Wayland is not backward compatible, but it is possible to run Wayland applications in Weston compositor which runs on X. However, It is unable to control Weston's window from the application, so I wouldn't call this backward compatible.

Now, I still have to use XCB purely. Later I could reuse that code in Druid.

I think opening separate issues for those is the best way to go, especially when some discussion is needed.


Custom mouse cursor support

This is still an open issue for the whole of druid (#104).

Errors implemented in druid-shell/src/platform/x11/error.rs, and applied to the rest of the backend where necessary

I'm not quite sure what this means.

Investigate issue with window resizing where the window flies away from the user (I couldn't reproduce)

I'll give that a try on my laptop as well.

I think opening separate issues for those is the best way to go, especially when some discussion is needed.

To clarify: do you mean I should write all of these up as separate issues now? (if so, would we close this issue when I do, or keep it open as a reference?)

I'd be happy to if so, just didn't want to flood the issue tracker if not.

This is still an open issue for the whole of druid (#104).

Cool, noted.

I'm not quite sure what this [regarding error.rs] means.

Basically, this means that I didn't attempt to implement anything in x11/error.rs beyond what it took to compile.

When I wrote that, I was comparing x11/error.rs to windows/error.rs, and I didn't know what I needed to do to get that working. However, I just took a look at gtk/error.rs and mac/error.rs, and it looks like it's about ~95% of the way there?

It's possible X11 just needs to impl std::error::Error for Error {} and remove the TODOs (and the NoError).

To clarify: do you mean I should write all of these up as separate issues now?

Yes

If so, would we close this issue when I do, or keep it open as a reference?

I think this Issue can be closed, filtering by shell/x11 will give use the same tracking but automated

I've created separate issues for the tasks.