GithubHelp home page GithubHelp logo

glazier's People

Contributors

bzm3r avatar cmyr avatar derekdreery avatar dfrg avatar djmcnab avatar edwin0cheng avatar forloveofcats avatar futurepaul avatar jaicewizard avatar james-lawrence avatar jjl avatar jneem avatar lihram avatar lord avatar luleyleo avatar maan2003 avatar mrandri19 avatar poignardazur avatar psychon avatar raphlinus avatar ratmice avatar rhzk avatar rjwittams avatar rylev avatar sapphire-arches avatar teddemunnik avatar vbsteven avatar waywardmonkeys avatar xstrom avatar zaynetro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

glazier's Issues

suspicious of dp/px

I think that sometimes we are returning measurements in device points when we should be using physical pixels, and vice versa. winit use some newtype wrappers to make the two types of measurement distinct in the type system. Whether we copy this or not, we should audit the places that take or return measurements to make sure they are using the right units.

As a specific example, I think WindowHandle::get_size is returning physical pixels when the docs say device points.

Deciding the Linux strategy

Druid never settled on a clear Linux strategy. At first there was only the GTK backend due to the simplicity of implementation.
Then there were experimental backends for X11 and Wayland. Bringing the total to three. No clear focus, lots of effort spread thin.
There were several attempts to reach some sort of clarity on how to reduce the scope, but unfortunately no decisions made.

Complexity kills. Lack of focus kills. The scope of Glazier is already enormous with targeting Windows, macOS, web (sort of), and tentative plans for both Android and iOS. Having multiple backends for Linux doesn't seem like well spent resources. Yes there are occasional champions who contribute to specific backends, but for the general success of Glazier new features should work well on all platforms and receive proper maintenance. Far fewer volunteer for such ongoing work. Also, speaking as someone who tests all the Glazier platforms, I would love to spend less time on all the various Linux quirks.

I think it would serve us well to reduce scope and increase focus.

With that in mind, I went through the historic Druid discussion threads and also did a bit of digging across the Linux ecosystem landscape to see how things are today and how things are likely to be in a few years.

Cutting options

The first question is whether we should drop GTK or embrace it.

If we embrace GTK, then it would be rather straightforward to drop support for both X11 and Wayland native backends.

However if we drop GTK then we're still left with both X11 and Wayland. Still double the number of backends per platform compared to other platforms. Thus I think in the case where we drop GTK we should also seriously consider dropping X11 and focus solely on Wayland.

With such a decision tree in mind, I'll present various points regarding each of the backends.

GTK

Benefits of keeping

  • GTK has already solved a lot of issues that we'll need to redo.

    • Think menus, window decorations, alerts and other utility dialogs.
    • .. although rewriting those does align with the Rewrite-it-in-Rust ethos.
  • We've already implemented a lot of the GTK integration.

    • Unclear how much of it has to be rewritten for GTK 4 though.
  • Probably the fastest path, in dev time, to a stable Linux backend.

  • Most attractive when the alternative is to keep both Wayland and X11 as opposed to only Wayland.
    As GTK 4 will provide both X11 and Wayland support for us, while being only a single backend for Glazier.

Benefits of removing

  • There is some uncertainty around how well the Glazier model with Vello can even work with GTK.
    There are various claims that it can be done, but at the moment nobody has actually spent the time to do it.

  • People have complained about the GTK compile times for years. Most recently in #101.
    Some historic Druid tests showed it almost an order of magnitude slower than Windows.

  • People have also complained about app startup time.

  • Significantly reduces our dependency graph. A lot of it written in C. Results in faster compile times and potentially fewer security bugs.

  • Gives us a higher degree of control.

    • Ability to hunt for more performance.
    • Ability to use/create more niche features.
    • Ability to target a wider range of uses like VST plugins.
  • We're still on GTK 3 and should probably migrate to GTK 4. Removing the GTK backend skips that work.

  • Support for running on systems that don't have GTK installed. Admittedly not too many of those, but the dependency is huge.

Wayland

  • Clearly the future. Various major Linux ecosystem projects are overwhelmingly in agreement.
    The differences in thought come from the assessment of progress towards it.
    However the progress is towards it.

  • We already need to do a large amount of work on our Wayland backend.
    It would be a lot easier to justify this focus if this was essentially synonymous with Linux support.

  • Removal only makes sense if we focus on GTK instead.

X11

Benefits of keeping

  • We've already done a good chunk of the work.

  • Ability to run on setups that are either running old distributions or are custom configured to run X11.

  • There isn't a lot of statistics available on display server usage, but we have a tiny bit - sample size 5500 across distributions.
    Keep in mind that the kind of person that would seek out self reporting like this is also more likely to change their defaults.
    So reality is probably skewed more towards distribution defaults. That said, I'll link three Wayland usage charts.

    • Ubuntu Jan 2022 23.5% > Jan 2023 55.6%
    • Fedora Jan 2022 60.7% > Jan 2023 70.6%
    • All Jan 2022 15.1% > Jan 2023 27.0%

    The trend is aggressively towards Wayland. Wayland has been available for a long time, but adoption has really accelerated in just the last few years. All signs point towards the acceleration only growing. However it is an open question how long the last 10% will hold out.

Benefits of removing

  • X11 is increasingly abandoned.
    It still works but is missing support for modern features and that list will only grow.
    Legacy quirks are guaranteed to remain.

  • Significantly reduces our maintenance burden of the Linux platform.

  • Reduces our dependency graph even more.

  • App developer experience improves drastically if Linux is just one backend,
    because otherwise the app code needs to perform runtime checks on X11 vs Wayland guarded by a Linux cfg attribute.

  • X11 has no support for wide color gamuts or HDR and there are no plans either.
    Wayland doesn't have real support either, but there is serious ongoing work.
    For us to support these modern features X11 would at a minimum be a heavily degraded experience.

  • GTK team considered removing the X11 backend from GTK for the future GTK 5 release.
    Their current plan is to stop building the X11 backend by default in GTK 5,
    but they also aren't rushing to delete the code .. at least until the next major refactor.
    In general, the vibe I get from the GTK team is that they don't want to spend any more resources on X11 support.

  • Qt 6 docs state:
    In fact, it is difficult to run a client fluidly with X11, and reach 60 fps without tearing.
    Wayland, in contrast, is easier to implement, has better performance,
    and contains all the necessary parts to run efficiently on modern graphics hardware.

    Running fluidly at 60 fps, or indeed 144 fps, is one of the core goals of the Linebender stack.

  • If both GTK and Qt, the two biggest Linux GUI toolkits, are convinced that Wayland is the superior future,
    then why would we, with less resources, invest in X11 support for our toolkit that won't even be ready for years.

  • Opportunity for Glazier to help shape the future of Linux desktop.
    Yes Wayland has issues. If the path of least resistance is to just go back to X11, then Wayland issues remain.
    If switching back to X11 isn't easy, then the path of least resistance becomes to fix the Wayland issues.
    Instead of helping keep the fragmentation the way it is, we could be championing for the shift.

  • In the bigger Linebender picture we're already building for the future by targeting compute shaders and WebGPU.
    It seems to fit thematically that we'll also focus on the latest display server.
    Although I guess you could make the case that supporting X11 is similar to having a CPU fallback in Vello.

  • GNOME has defaulted to Wayland since ca Fedora 25.

  • The KDE team is pushing for Wayland by default in the upcoming Plasma 6 release.
    (Estimated release date Q1 2024)

  • Fedora has defaulted to Wayland with Plasma since Fedora 34, and with GNOME since Fedora 25.

  • The Fedora team is pushing to take it even further and have the Fedora Plasma 6 ship without X11.

  • Red Hat Enterprise Linux 9 deprecated X11, defaults to Wayland. X11 planned for removal in RHEL 10.

  • Ubuntu has defaulted to Wayland since Ubuntu 21.04.

  • Debian has defaulted to Wayland with GNOME since Debian 10.

  • Glazier 1.0 isn't likely for another few years.
    While large Linux distributions are looking to remove as much X11 code as they can,
    should we be looking to write new X11 code for 2025 and beyond? Seems like swimming against the current.

  • It is better to cut scope and increase focus.
    Deliver a single Wayland backend that is excellent, instead of two backends that are merely good.

Previous discussions

Feedback welcome

Given that the primary issue with having three Linux backends is the amount of work required, I especially want to encourage people to respond here if they have even tentative plans to contribute work towards specific backends.

In general, if anyone has more reasons to add or want to amplify one of the above reasons on why we should go with any of these options, please share your thoughts.

The ideal Wayland backend

In the process of unpiet, the Wayland backend needs some work under the hood as well. Since the backend is relatively immature, I'd recommend a rewrite of the Wayland backend while we are in progress with unpiet.

I may contribute some bits here and there in the future, but I am quite busy so I'll lay out the future ideal state of the Wayland backend:

A few implementation notes that would be useful:

  • Wayland and X11 effectively have the same keymap logic under the hood. It would be prudent to have this code shared between the two backends, but this comes at the cost of writing your own keyboard boilerplate (vs using what smithay's client toolkit has).
  • Use wayland-rs 0.30. Yes these are beta versioned crates, but 0.29.x is going away soon.
  • Continue using calloop under the hood. In particular, try to create a high precision event loop so that Linux can use timerfd which is more accurate than thread based timing.
  • Use smithay's client toolkit.
    • This should help with reducing some of the implementation boilerplate

And some implementation advice for fulling the scope of glazier:

  • Window creation, including subwindows
    • Using xdg-shell's xdg_toplevel and xdg_surface
  • System menus
    • Wayland doesn't really have a concept of a system menu and nor does X11. The DBusMenu for dbus could be used to support this, but users would have to be responsible for rendering in the case that the DBusMenu isn't made visible via the compositor for example.
    • For popup based menus, Wayland provides no assistance here. Effectively treat it like a window with special semantics.
  • Keyboard events
    • wl_keyboard, possibly some seat related stuff
  • Input Method Editor
    • See the zwp_input_method_v1 protocol
  • Mouse, pointer (touch and pen) events.
    • wl_pointer (for mice), and the tablet-unstable-v2 protocol for drawing tablets.
  • Cursors (including custom images)
    • Part of core wl_pointer.
  • DPI Info
    • At the time of writing, only integer scales. This will change in the future given 3 proposals to add fractional scaling.
  • Clipboard
    • See wl_data_device
  • File dialogs
    • ashpd like current druid-shell.
  • Frame pacing

The general philosophy is that a task is in scope if it requires deep integration with the platform and is not easy to separate out as a separate library that layers on top of Glazier.

A few things worth discussion here include:

  • Client side decorations (including allowing the user to only have CSD, use it as a fallback or fully commit to server side decorations)
    • If libdecor is considered, note that libdecor acts more like a shell than a set of decorations. Plus some issues with libdecor need to be ironed out before it is safe to use in Rust (some callbacks in libdecor are reentrant).
  • Primary selections (Think X11 middle-click to copy a selection in another window)
  • Idle inhibition (using the new idle-inhibit protocol)
  • xdg-activation (XDG_ACTIVATION_TOKEN)

There are some less clear, but nice things we could support that are more Wayland specific:

  • The layer shell, this may become a privileged protocol in the future, restricting what clients can use the layer shell per compositor policy. This has use for system docks and bars on Linux.

paint is never called on Wayland

In the shello example, the window that opens takes up the whole screen and "looks transparent" (which might just be kwin not painting anything, rather than painting full transparency). The window still receives clicks and keyboard events. render() never gets called.

Support window close / minimize buttons with content in full view

Currently glazier allows the title bar to be disabled but this also disables the OS native buttons for closing and resizing (and macOS and windows stop treating them as main application windows).

This is fine but it would be nice to be able to configure a the window to have a full content view but still keep the OS native buttons and title_bar.

On macOS this can be done by adding NSWindowStyleMask::NSFullSizeContentViewWindowMask to the style_mask here

and by setting the window.setTitlebarAppearsTransparent_ with true.

I could open a PR for this but I wasn't sure how to name these items and also how to ensure consistency with windows / linux.

Window destruction

Symptom: the shello example runs fine, but hangs on exit.

Apparent cause: the X11 backend destroys a window before user state (handler) gets destroyed. This is potentially a problem because that user state may include stuff which depends on the window. At least, I appear to be hitting this issue:

So to fix this, naively, we need to destroy the RenderSurface before the window, like this:

impl WindowState {
    // ...
    fn destroy(&mut self) {
        drop(self.surface.take());

        Application::global().quit()
    }
}

... but there are two problems here:

  1. We rely on user applications to handle destruction in the correct order, despite this being a cross-platform API and the requirement only being present on one platform (X11)
  2. WGPU doesn't actually destroy the swapchain here (I'm not even sure if it is supposed to, though the Surface is the only part which is window-specific)

The alternative would be to keep the X11 window alive until after user state (handler) has been destroyed. This can't simply be done from backend::x11::window::Window::destroy since self.handler is borrowed when this method is called so further redesign would be needed (e.g. ensure the user state is destroyed immediately after handle_destroy_notify is called).

There is a further complication in that user state may hold a copy of a WindowHandle, which contains a Weak reference to the window object. I wonder whether further design changes are sensible:

  • Pass handle: &WindowHandle into all methods of WinHandler, remove Clone impl
  • Application::clipboard returns a temporary (non-Clone) object Clipboard<'_>

Consider adding async support

Right now, the Application structure exposes a run() method that blocks indefinitely until the application finishes. It would be nice if there were a way to run a Future inside of this blocking loop, so that it would be possible to multiplex an asynchronous task with the GUI on one thread.

This would require changing the backend such that it can be woken up via a Waker. While you could just create a Waker to send an event to the loop, there is a more elegant way of doing this that can circumvent the normal event loops, based on the platform.

  • Windows lets you interrupt the message loop using MsgWaitForMultipleObjects.
  • With GTK, you can just register the future in the GLib event loop.
  • X11/Wayland can just be registered into epoll.
  • macOS requires some system hacks to get the Mach port belonging to GCD, but once you have it it can just be used in kqueue.
  • I'm not sure about web.

I'm willing to implement this behavior into the current system.

GNOME (Wayland): On-Screen keyboard doesn't display in edit_text

This does work in Firefox, but not in our Wayland backend. It's not clear if we need to implement an additional API for this. Naรฏvely, I'd expect this to be based on the text input protocol, but I believe we implement this correctly.

Based on alacritty/alacritty#6644, it appears that this should work. However, a test of the latest Alacritty release at the time of writing:

fsh โฏ alacritty --version
alacritty 0.12.2

doesn't support the on-screen keyboard on my machine.

Testing also using Konsole and Kwrite (KDE's QT based terminal emulator and text editor) also shows the on-screen keyboard not working. This suggests that the on-screen keyboard uses some GTK specific API, so unless we can find where this is documented, I don't believe we can fix this.
See also microsoft/vscode#81962.

The Alacritty issue does bring up an additional feature we need to implement - namely zwp_text_input_v3::set_content_type. Winit uses a simple API for this - we should instead have this be part of the input lock, but we need to make similar choices about a set of options.

Does not support X11 forwarding?

Using MobaXter or vcxsrv as X server on a Win10.
Run some examples from Ubuntu 22.04, the window is balck at all.

image

:~/proj/rust/glazier$ cargo r --example wgpu-triangle
    Finished dev [unoptimized + debuginfo] target(s) in 0.19s
     Running `target/debug/examples/wgpu-triangle`
[src/backend/x11/application.rs:673] ev = MapNotify(
    MapNotifyEvent {
        response_type: 19,
        sequence: 197,
        event: 2097154,
        window: 2097154,
        override_redirect: false,
    },
)
[src/backend/x11/application.rs:673] ev = ReparentNotify(
    ReparentNotifyEvent {
        response_type: 149,
        sequence: 198,
        event: 2097154,
        window: 2097154,
        parent: 197,
        x: 138,
        y: 161,
        override_redirect: true,
    },
)

draw is not called on macOS

To reproduce on macos:

  • run an example with a resizable window, like wgpu-triangle
  • grab one of the corners of the window and drag it around randomly for like ten seconds
  • attempt to close the window, and note that this takes a few seconds instead of working instantly

Haven't yet investigated what causes this

Switch from winapi to windows-rs

The winapi crate hasn't been updated in over a year and has been deprecated by windows-rs which are the official rust bindings to the windows api.

I think it would be better to switch sooner rather than later.

One consideration would be whether to use the windows or windows-sys crate.

Event for when the application will close

We have:

glazier/src/window.rs

Lines 773 to 779 in 618382a

/// Called when the shell requests to close the window, for example because the user clicked
/// the little "X" in the titlebar.
///
/// If you want to actually close the window in response to this request, call
/// [`WindowHandle::close`]. If you don't implement this method, clicking the titlebar "X" will
/// have no effect.
fn request_close(&mut self) {}

However, we don't report when the actual application is closing. This is most useful on macOS, as in other desktop environments (generally) the application is finished when the final window is closed1.
But for consistency, we should have the same API across all backends. This could be used for saving states, for example.
This would be slightly earlier than AppHandler::drop - the event loop might still be running at this point (?)

An implementation for macOS exists in 86f0494 (from lapce's fork)

An implementation note:
This should not be called upon calling Application::quit, for consistency with the Window methods.

AppHandler::drop could possibly be used in that case?

CC @waywardmonkeys, as discussed in Zulip.

Footnotes

  1. Customising this behaviour could make sense - e.g. for close to tray on Windows (and Linux in theory, except that there's no tray) โ†ฉ

Move `druid::WindowConfig` to glazier

Druid has the following data structure.

pub struct WindowConfig {
    pub(crate) size_policy: WindowSizePolicy,
    pub(crate) size: Option<Size>,
    pub(crate) min_size: Option<Size>,
    pub(crate) position: Option<Point>,
    pub(crate) resizable: Option<bool>,
    pub(crate) transparent: Option<bool>,
    pub(crate) show_titlebar: Option<bool>,
    pub(crate) level: Option<WindowLevel>,
    pub(crate) state: Option<WindowState>,
}

That struct is directly tied to WindowBuilder. Eg it has an apply_to_builder method:

/// Apply this window configuration to the given WindowBuilder
pub fn apply_to_builder(&self, builder: &mut WindowBuilder) {
    if let Some(resizable) = self.resizable {
        builder.resizable(resizable);
    }

    if let Some(show_titlebar) = self.show_titlebar {
        builder.show_titlebar(show_titlebar);
    }

    if let Some(size) = self.size {
        builder.set_size(size);
    } else if let WindowSizePolicy::Content = self.size_policy {
        builder.set_size(Size::new(0., 0.));
    }

    if let Some(position) = self.position {
        builder.set_position(position);
    }

    if let Some(transparent) = self.transparent {
        builder.set_transparent(transparent);
    }

    if let Some(level) = &self.level {
        builder.set_level(level.clone())
    }

    if let Some(state) = self.state {
        builder.set_window_state(state);
    }

    if let Some(min_size) = self.min_size {
        builder.set_min_size(min_size);
    }
}

Almost every method of WindowBuilder has a matching field in WindowConfig. So I think it would make sense to move WindowConfig to glazier directly. (And it would remove redundant interfaces from druid / masonry).

Quit menu isn't enabled

Branched from linebender/xilem#1. The quit menu item is not enabled on mac, and quitting also doesn't work on Linux. I haven't investigated deeply, but the code to create the menu seems ok (it's the same as the druid-shell version).

Alternative to WinHandler::connect()

Writing down this idea just so I don't forget: one thing I've noticed is most implementations of WinHandler end up containing a ton of Options, which only get filled in after connect() is called. If we changed set_handler to take a FnOnce(&WindowHandle) -> WinHandler as an argument instead of an explicit WinHandler, perhaps we could handle some complexity for the user? (Although the user must be careful to not call any methods of the WindowHandle during initialization that would require the WinHandler to exist.)

Soundness issue with `Counter`

In Glazier there is a counter struct that wraps an atomic number and provides unique IDs. There is a method on it that returns a NonZeroU*, and if the inner number overflows then it will get initialized with zero, which is UB. I don't think the doc comment is sufficient here, unless we mark the methods on the Counter as unsafe. Alternatively we should acquare exclusive access while we check that the number is not u*::MAX before we increment it and get our ID. This will lead to a little more contention, but the alternative is UB.

AccessKit integration

I'll be implementing this, building on my previous work on druid-shell.

Question: Is it OK to open a PR for this when it's only implemented on Windows? The first stage of the AccessKit macOS adapter is close to being merged. I'm not sure how soon the Linux (AT-SPI) adapter will be merged, and we don't yet have any support for the web platform.

`WindowLevel` should implement `std::fmt::Debug`

Self-explanatory. Implementation could be roughly:

match &self {
  WindowLevel::AppWindow => "AppWindow",
  WindowLevel::Tooltip(_) => "ToolTip",
  WindowLevel::DropDown(_) => "DropDown",
  WindowLevel::Modal(_) => "Modal",
}

and skip the AppHandle values, since it's hard to get meaningful debug info from them.

Order of events on window creation

There's a panic in linebender/xilem#1 on window creation with the Wayland back-end. This probably has to do with the order of events on window creation being different. It certainly would be possible to fix this by making the xilem code more robust, but I think it's better to fix this at the glazier level, making the order of events more consistent from platform to platform, to reduce the burden on other potential clients.

Also see https://xi.zulipchat.com/#narrow/stream/351333-glazier/topic/Running.20callbacks.20when.20building.20windows.2E where this was discussed a bit.

What to do with presentation strategy logic?

I am working on silencing some clippy lints, which is pointing me to consider what is happening with regards to presentation strategy in druid-shell:

let dxgi_state = unsafe {

compared to in unpiet, where presentation strategy logic goes out the window:

let handle = self.handle.borrow().to_owned();

Tracing various threads back, I am lead to the blocker being create_dxgi_state, particularly the creation of a D3D11Device, as explained by Raph here.

Which leads me to wonder: does the presentation strategy logic also not belong in glazier? That seems to clash with my understanding of the purpose of glazier, so I'm wondering if I can have some insight.

Wayland backend: Features to implement

In #107, we've landed the beginnings of a new wayland backend. Here are some features which need to be implemented for it, and some hints for these. This all works towards #28.

  • Keyboard input - Implemented in #119. There are some decisions which might need to be rethought, but it should work well enough
  • Pointers
    This requires several things, at different levels of complexity:
    wl_pointer object's events. Smithay-client-toolkit's abstraction over this might be sufficient for our needs.
    wl_touch - there's also a sctk abstraction.
    To support graphics tablets and pen input, see zwp_tablet_manager_v2. I believe this to be lower priority.
  • Timers - in progress in #150
    This requires adding a Timer to the calloop event loop, then removing it once the timer fires. Should be straightforward.
  • Proper invalidation
    There are two levels to this, reporting it to the client, and reporting it to the compositor.
    For reporting to the application, we just need to store the requested region, and send that in paint.
    Reporting it to the server, it's unclear if we can do this. See linebender/druid#402 and gfx-rs/wgpu#682. The vulkan spec isn't clear1 whether we can use the damage command ourselves
  • Pop-up windows
    This is xdg_popup. This has an abstraction. We need to change a few things around in the implementation of Window - the window may either be a popup or a toplevel, but not both.
  • Accessibility
    The crate to look at is accesskit_unix. This will also involve fixing #112.
    This can probably also be wired up to the X11 backend, as the interface appears to be relatively straightforward.
    One open question is how to represent multiple windows, but that should be the same as in all other backends
  • Cursors
    That is, setting the cursor icon etc. This should use wp_cursor_shape_manager_v1 and wl_pointer::set_cursor, depending on the mode. See #136
  • XDG desktop portal (file open/save, etc.)
    This should be able to share the implementation with the x11 backend
  • Fractional scaling
    This requires the wp_fractional_scale_manager_v1 extension to be used. Because smithay-client-toolkit doesn't enable the staging protocols, we need to either depend on wayland-protocols directly, or work with client-toolkit to enable this
  • App Menus
    A few sources report that KDE supports global menus. I think this is a dbus service, but we should integrate properly with this whatever the case may be
    This is the KDE AppMenu protocol. This appears to want to display window menus, rather than the application level menu. Is it meaningful to have it support both?
  • Light and dark theme
    I believe this is a dbus API

These are other features which we need, but which require API changes across all backends:

  • Clipboard
    At the moment, our clipboard API is synchronous. However, wayland's wl_data_source is async
  • Monitors
    At the moment, the monitor API is global. However, I believe that the monitor API only really makes sense in the context of an Application. It's worth also asking what we expect the monitors API to be used for.
    The monitors can be accessed through OutputState
    We can also report changes in the outputs to the AppHandler.

These are other features which we need, but which require API changes (only/primarily) to support wayland

  • Customise the App ID
    At the time of writing, we unconditionally set the app id to "org.linebender.glazier.user_app". We need an API to set this
  • Client side decorations
    This needs its own tracking issue. We should be able to enable this on all frontends, but it's required for Wayland
  • Menus of all kinds
    Right click and popup. This needs to be implemented at a higher level than Glazier. Again, the custom styles can be used on all frontends.

Footnotes

  1. The wl_surface.attach, wl_surface.damage, and wl_surface.commit requests must be issued by the implementation during the call to vkQueuePresentKHR and must not be issued by the implementation outside of vkQueuePresentKHR. - https://registry.khronos.org/vulkan/specs/1.1-extensions/html/vkspec.html#platformCreateSurface_wayland โ†ฉ

X11 doesn't repaint on resize.

If you resize the window, it doesn't repaint until some other trigger (e.g. mouse over a button).

Needs repro - I've only seen it on my machine so far. Might be an issue with my setup, might not.

Make use of physical and logical size types

It isn't always clear whether a size is in pixel or display points. Better documentation could help, but making use of the type system would be even better.

I think there are 2 ways of going about this. Using wrapper types

pub struct Physical<S: Scalable> {
    pub pixels: S,
}

pub struct Logical<S: Scalable> {
    pub points: S,
}

Or using an enum. This is how winit does it

pub enum Dip<S: Scalable> {
    Pixels(S),
    Points(S),
}

Handle multi-clicks in Wayland backend

Currently, the Wayland backend code for mouse presses is roughly this:

self.clickevent.borrow_mut().debounce(MouseEvtKind::Down(
    mouse::MouseEvent {
        pos: self.pos.get(),
        buttons: *self.buttons.borrow(),
        mods: Modifiers::empty(),
        count: 1,
        focus: false,
        button,
        wheel_delta: Vec2::ZERO,
    },
))

Notice that the click count is always one; this means double-clicks and triple-clicks aren't detected.

Rename `Application` to `AppHandler`

Application is the global-equivalent of WindHandler it should be called AppHandler for a few reasons:

  • Consistency with WinHandler
  • Clearer name. To me, finding an "Application" in your code implies you've found the composition root of your app-specific state, when in fact you've found a lightweight handle to platform bindings.

I've bumped into this problem when writing Masonry, and I think @maan2003 bumped into it as well last year: https://xi.zulipchat.com/#narrow/stream/147926-druid/topic/Remove.20Application.3A.3Aglobal/near/238902785

AccessKit example fails to build on Linux

The AccessKit example fails to even build on Linux (with both Wayland & X11). We had to disable Linux testing of it in #111.

Run cargo build --features x11,accesskit --no-default-features --example accesskit
 Downloading crates ...
  Downloaded accesskit v0.11.0
 Downloading crates ...
  Downloaded accesskit_macos v0.7.1
 Downloading crates ...
  Downloaded accesskit_windows v0.14.0
   Compiling glazier v0.7.0 (/home/runner/work/glazier/glazier)
   Compiling accesskit v0.11.0
error[E0599]: no method named `update_accesskit_if_active` found for enum `backend::linux::window::WindowHandle` in the current scope
    --> src/window.rs:436:16
     |
436  |         self.0.update_accesskit_if_active(update_factory)
     |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `WindowHandle`
     |
    ::: src/backend/linux/window.rs:233:1
     |
233  | pub(crate) enum WindowHandle {
     | ---------------------------- method `update_accesskit_if_active` not found for this enum
     |
note: the method `update_accesskit_if_active` exists on the type `x11::window::WindowHandle`
    --> src/backend/x11/window.rs:1457:5
     |
1457 | /     pub fn update_accesskit_if_active(
145[8](https://github.com/linebender/glazier/actions/runs/5486073995/jobs/9995685149#step:8:9) | |         &self,
145[9](https://github.com/linebender/glazier/actions/runs/5486073995/jobs/9995685149#step:8:10) | |         _update_factory: impl FnOnce() -> accesskit::TreeUpdate,
1460 | |     ) {
     | |_____^

For more information about this error, try `rustc --explain E0599`.
error: could not compile `glazier` (lib) due to previous error
Error: Process completed with exit code [10](https://github.com/linebender/glazier/actions/runs/5486073995/jobs/9995685149#step:8:11)1.

Moving forward this should be resolved.
The example should at least build, even if that means an empty main function guarded by #[cfg].
Then we can have a unified CI that tests all examples on all platforms.

Feature Request - C API

Is it feasible to ask to provide some kind of C API for working with Glazier, so it can be used in other languages?
This would be really helpful for using it in other languages, but I'm not sure how easy would this be.

I'm willing to potentially put time into this, given acceptance and proper guidance for this proposal.

Rename WinHandler methods

After implementing druid-shell's WinHandler in masonry, I feel like some of the methods have unclear names and would benefit from a rename:

  • size -> resize
  • scale -> rescale
  • command -> select_menu
  • save_as -> save_dialog_res
  • open_file -> open_dialog_res
  • timer -> timer_complete

The pattern with most of these names is the same: the name implies that the method fetches information, when what it does it tell the implementor "some event happened, react to it".

Thoughts?

Input events are not correctly filtered on the X11 backend

When playing around with Xilem, I found that event handlers are triggered twice. E.g. in the button example bin, the counter is incremened twice per click.
After some suggestions on Zulip, I cloned glazier and debug-printed all input events, and they are duplicated in the following form (one click):

XinputButtonPress(ButtonPressEvent { response_type: 35, extension: 131, sequence: 650, length: 22, event_type: 4, deviceid: 11, time: 309212286, detail: 1, root: 475, event: 142606366, child: 0, root_x: 36498396, root_y: 40442140, event_x: 33221596, event_y: 32643356, sourceid: 11, flags: 0, mods: ModifierInfo { base: 0, latched: 0, locked: 0, effective: 0 }, group: GroupInfo { base: 0, latched: 0, locked: 0, effective: 0 }, button_mask: [0, 0, 0, 0, 0, 0, 0, 0], valuator_mask: [0, 0], axisvalues: [] })
XinputButtonPress(ButtonPressEvent { response_type: 35, extension: 131, sequence: 650, length: 22, event_type: 4, deviceid: 2, time: 309212286, detail: 1, root: 475, event: 142606366, child: 0, root_x: 36498396, root_y: 40442140, event_x: 33221596, event_y: 32643356, sourceid: 11, flags: 0, mods: ModifierInfo { base: 0, latched: 0, locked: 0, effective: 0 }, group: GroupInfo { base: 0, latched: 0, locked: 0, effective: 0 }, button_mask: [0, 0, 0, 0, 0, 0, 0, 0], valuator_mask: [0, 0], axisvalues: [] })
XinputButtonRelease(ButtonPressEvent { response_type: 35, extension: 131, sequence: 650, length: 22, event_type: 5, deviceid: 11, time: 309212403, detail: 1, root: 475, event: 142606366, child: 0, root_x: 36498396, root_y: 40442140, event_x: 33221596, event_y: 32643356, sourceid: 11, flags: 0, mods: ModifierInfo { base: 0, latched: 0, locked: 0, effective: 0 }, group: GroupInfo { base: 0, latched: 0, locked: 0, effective: 0 }, button_mask: [2, 0, 0, 0, 0, 0, 0, 0], valuator_mask: [0, 0], axisvalues: [] })
XinputButtonRelease(ButtonPressEvent { response_type: 35, extension: 131, sequence: 650, length: 22, event_type: 5, deviceid: 2, time: 309212403, detail: 1, root: 475, event: 142606366, child: 0, root_x: 36498396, root_y: 40442140, event_x: 33221596, event_y: 32643356, sourceid: 11, flags: 0, mods: ModifierInfo { base: 0, latched: 0, locked: 0, effective: 0 }, group: GroupInfo { base: 0, latched: 0, locked: 0, effective: 0 }, button_mask: [2, 0, 0, 0, 0, 0, 0, 0], valuator_mask: [0, 0], axisvalues: [] })

Note how they only differ in the deviceid field, being sent from devices 2 and 11. According to xinput, device 2 is a Virtual Core Pointer (master pointer) and device 11 is my actual mouse (slave pointer). Running xev, it does not show duplicate events, so it shouldn't be my configuration but insufficient control logic from glazier.

For reference, my system setup is the following

OS: Manjaro Linux x86_64
Host: 81SX Legion Y540-15IRH
Kernel: 5.15.94-1-MANJARO
Uptime: 5 days, 22 hours, 56 mins
Packages: 2904 (pacman), 7 (snap)
Shell: fish 3.6.0
Resolution: 1920x1080, 1920x1080
DE: GNOME 43.3
WM: Mutter
WM Theme: Adwaita
Theme: Adw-dark [GTK2/3]
Icons: Papirus-Dark-Maia [GTK2/3]
Terminal: alacritty
CPU: Intel i7-9750H (12) @ 4.500GHz
GPU: NVIDIA GeForce GTX 1660 Ti Mobile
Memory: 24277MiB / 32021MiB

and I am running X11, a backtrace also shows that the x11 backend is used.
I am using the main branch of Xilem and these issues happen both with its selected glazier version as well as a manually cloned main branch version of glazier (I did not check if those are different or the same).

How to reproduce:

  • Run the Xilem button demo on an X11 linux desktop
  • The counter should increment by 2 with each click

Shello example missing glyphs

I'm on Ubuntu 20.04 and running when running the shello example, some glyphs are missing. See attached screen shot.

Note: As far as I understand this would be due to one of the example's dependencies rather than glazier itself but I'm not sure where might be a better place to create an issue.
glazier_missing_glyphs

Investigate splitting gtk-rs dependency

(Not sure if this is still up to date. Will need to investigate further.)

The gtk-rs crate takes a huge chunk of Glazier, Druid and Masonry's build times, but these crates only use a small fraction of the features offered by gtk. It might be feasible to cut out most of the unneeded features and get a much leaner dependency for shorter build times.

Readme doesn't mention xkb dependency

Right now when I compile glazier, I get this error:

Package xkbcommon-x11 was not found in the pkg-config search path.
  Perhaps you should add the directory containing `xkbcommon-x11.pc'
  to the PKG_CONFIG_PATH environment variable
  No package 'xkbcommon-x11' found
  ', build.rs:20:36

I can roughly guess what I need to do, but I feel like you shouldn't get a build error because of a missing dependency if the README doesn't mention you have to install that dependency.

`schedule_idle` not taking `&self`

Is there a reason why IdleHandle::schedule_idle takes a &mut self instead of just &self like add_idle_callback? The underlying function add_idle_token doesn't seem to require mut access in any of the backends.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.