Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux: Add support for embedded Ozone/Wayland windows #2804

Open
magreenblatt opened this issue Nov 13, 2019 · 45 comments
Open

Linux: Add support for embedded Ozone/Wayland windows #2804

magreenblatt opened this issue Nov 13, 2019 · 45 comments
Labels
Framework Related to framework code or APIs help wanted Issue resolution will likely require community contributions linux Linux platform native Related to a native (non-Views) framework proposal Proposed change or action

Comments

@magreenblatt
Copy link
Collaborator

Original report by Maksim Sisov (Bitbucket: Maksim Sisov).


Hi Marshall,

I have already contacted you about Ozone/Wayland/X11 support via e-mail as you remember, but I think it’s better to move the discussion here.

As we discussed, Ozone/Wayland/X11 can only be used with views framework now, but it does not allow to embed host windows into client windows.

Whereas adding support for Ozone/X11 is trivial, the Ozone/Wayland requires some design changes. That is, you proposed to start with cefclient application and here is what I think: the cefclient has two main window classes - RootWindowGtk that uses the GTK toolkit to create windows and BrowserWindowStdGtk (I don’t take osr here as it does not look like there are any changes needed to make it work with Wayland as it is going to be the client hosting the top level window without any need to embed a CEF window into that).

The RootWindowGtk receives callback events from GTK (window state changes, focus changes, bounds changes and etc) and calls the BrowserWindowStdGtk to say it to make changes to a CEF native window. The BrowserWindowStdGtk may either call to the CEF native window through browser_->GetHost()->Blah() or through X11 native APIs like XChangeProperty, XConfigureWindow and etc.

The first approach (browser_->GetHost()->Blah()) results in calling the WindowX11, which then uses X11 native APIs to change own properties and the properties of its child window, which is a Chromium window (either via changing properties of the child window directly or via changing own properties first… and when ConfigureNotify or any other event comes, it does the same change via X11 native APIs for its child (chromium) window. Then, the chromium’s X11 window receives events from X11 and passes all core stuff for processing to PlatformWindowDelegate to aura/views/blink and etc…).

The second approach (through X11 native APIs) does pretty much the same except the fact that it's the client who uses X11 APIs to change properties of the CEF native window, which then receives X11 messages from the X server and does the same changes for it’s child via the same X11 APis.

I haven’t really checked mac or win and might be mistaken, but it seems like they do the same.

However, it is not the case for Wayland… And embedding will look different for that. I analyzed different approaches and it seems like wl_subsurface is the way to go.

In case of Wayland, clients should take a wl_surface that they created (either via gdk, native Wayland or qt toolkit or whatever) and a wl_display they used and pass them to CEF. Depending on whether a parent wl_surface is passed or not, the CEF either will create a toplevel window or a subsurface that it will parent with the passed parent wl_surface. Then, it will also pass own wl_surface that it created along with a wl_subsurface, which Chromium will use to associate own wl_subsurface with.

The mechanism, which X11 uses for property changes (XChangeProperty or XConfigureWindow) to manipulate the state of any X11 windows, won’t work with Wayland. Instead, a client will always manipulate the CEF browser window via browser_->GetHost()->DoSmth(Args…). However, one must realizethat the calls that manipulate the state of the window (such as SetBounds(), Hide(), Show() and etc) may not result in actual Wayland calls as a subsurface should be treated as an overlay above a parent surface that cannot be really hidden, shown or placed to some arbitrary area in respect to parent’s local coordinates. Instead, the state changes must be propagated through calls to views::Widget or whatever mechanism content api provides.

What do you think about that?

@magreenblatt
Copy link
Collaborator Author

Original comment by Czarek Tomczak (Bitbucket: Czarek, GitHub: Czarek).


Any plans for improved integration with Wayland? :)

@magreenblatt
Copy link
Collaborator Author

Original comment by Maksim Sisov (Bitbucket: Maksim Sisov).


Hi. It’s almost complete. It’s now possible to embed cef Wayland into gtk client, but there are still some problems.

@magreenblatt
Copy link
Collaborator Author

Original comment by Czarek Tomczak (Bitbucket: Czarek, GitHub: Czarek).


Can you send a Pull request and name it “WIP” (work in progress), so others can see it and possibly help with the issues?

@magreenblatt
Copy link
Collaborator Author

Original comment by Maksim Sisov (Bitbucket: Maksim Sisov).


Sure. Will do that tomorrow when back to work

@magreenblatt
Copy link
Collaborator Author

Original comment by Maksim Sisov (Bitbucket: Maksim Sisov).


Hey. My excuses I couldn’t complete that today. I noticed cef was updated and started to rebase them, but didn’t have time to complete that today.

@magreenblatt
Copy link
Collaborator Author

Original comment by Czarek Tomczak (Bitbucket: Czarek, GitHub: Czarek).


No problem. Just send when you can.

@magreenblatt
Copy link
Collaborator Author

Original comment by Maksim Sisov (Bitbucket: Maksim Sisov).


here it is https://bitbucket.org/chromiumembedded/cef/pull-requests/288/wip-add-better-ozone-wayland-x11-support/

@magreenblatt
Copy link
Collaborator Author

Original comment by santosh mahto (Bitbucket: Santosh_Collabora).


Great job, I have been also looking in this feature and had done some exploration and agreed on same approach implemented by you. Thanks for doing this.

@magreenblatt
Copy link
Collaborator Author

Original comment by Laurenz Bihlmayer (Bitbucket: Laurenz Bihlmayer).


Hi @{5d89fce57324700c9f5fe590}

Whats the status of this issue? To me it seems pretty stale, which is a shame, because distros start using Wayland as their default window manager (protocol), most notably Ubuntu 21.04.

I would love to see continued development and hope that your pull request can get merged soon.

@magreenblatt
Copy link
Collaborator Author

Original comment by Maksim Sisov (Bitbucket: Maksim Sisov).


You can already use CEF with Wayland. The only case that is missing is the embedding one and I need to revisit the implementation at some point.

@magreenblatt
Copy link
Collaborator Author

Original comment by Laurenz Bihlmayer (Bitbucket: Laurenz Bihlmayer).


Okay I understand, but i guess the embedding one is the one that Steam, Spotify etc. are using for their apps.

It would be very nice if this implementation could be merged at some point, so we can finally get rid of the drawbacks that XWayland has.

@magreenblatt
Copy link
Collaborator Author

Original comment by Störm Poorun (Bitbucket: Störm Poorun).


Indeed, Ubuntu, Debian, Fedora, Manjaro, Red Hat, OpenSuse… all ship Wayland as default

So it appears many users (myself included) are now are getting blurry windows when using CEF-embedded apps, particulary on HiDPI applications (OnlyOffice, Spotify, Steam)

One appreciates there are many priorities and limited resources, but hopes this will be considered carefully by those able.

@magreenblatt
Copy link
Collaborator Author

The X11 implementation is now based on Ozone, see https://crrev.com/cecaf7e62f (M95+).

@magreenblatt
Copy link
Collaborator Author

Original comment by tytan652 (Bitbucket: tytan652, GitHub: tytan652).


Any update about the Wayland implementation for the CEF and the “WIP” Pull request ?

@magreenblatt
Copy link
Collaborator Author

Ozone builds can currently run with different platform backends (Wayland, X11, etc). Usage of the Views framework is required, and the cefclient sample application is not supported. See issue #2296.

What’s currently missing (and covered by this issue) is the ability to embed CEF windows in third-party Wayland applications. That requires providing a Wayland alternative to the X11 code that is currently #ifdef-d out of the CEF Ozone build.

@magreenblatt
Copy link
Collaborator Author

  • changed title from "Ozone/Wayland/X11 support." to "Linux: Add support for embedded Ozone/Wayland windows"

@iMonZ
Copy link

iMonZ commented Jul 29, 2023

Any news here?

@polluxau
Copy link

i would also like this to be merged, wayland is the future, steam, discord are one of the last apps that i use that havent updated to wayland yet.

@famiu
Copy link

famiu commented Oct 4, 2023

This issue also blocks OBS Studio's custom browser docks from working on Wayland. An update on this would be really appreciated

@magreenblatt
Copy link
Collaborator Author

An update on this would be really appreciated

I'm not aware of anyone working on this currently. Perhaps someone else would like to pick up where Maksim left off?

@konradmoesch
Copy link

Whats still left to do, what can I do to help bring wayland support for CEF?
The linked PR on bitbucket seems to be done:

What works:

  • Everything seem to work. However, more testing is required.

What is broken:

  • I’m not aware about any problems yet.

@magreenblatt magreenblatt added the native Related to a native (non-Views) framework label Nov 15, 2023
@madmalkav
Copy link

What works:

  • Everything seem to work. However, more testing is required.

You got any additional info? I can´t help with code, but I can help with the "more testing" part :)

@famiu
Copy link

famiu commented Mar 15, 2024

Whats still left to do, what can I do to help bring wayland support for CEF? The linked PR on bitbucket seems to be done:

What works:

  • Everything seem to work. However, more testing is required.

What is broken:

  • I’m not aware about any problems yet.

@magreenblatt any updates on this yet? With Plasma 6 seemingly planning to drop Xorg, this is more necessary than ever.

@ruineka
Copy link

ruineka commented May 29, 2024

I am running into this issue now and with most distros moving to Wayland as the default and hardware configurations not being compatible with X11 (Ultrawide high refresh rate multi monitor setups) this is a big issue moving forward that needs to be resolved.

@magreenblatt
Copy link
Collaborator Author

Contributions are welcome. Someone (maybe you?) will need to implement this functionality and commit to maintaining it going forward.

@ruineka
Copy link

ruineka commented May 29, 2024

Contributions are welcome. Someone (maybe you?) will need to implement this functionality and commit to maintaining it going forward.

I am not going to make any promises, but I will see if there is anything I can help with. I have a little experience with Wayland thanks to working with gamescope and wayland protocols, so maybe there is something I can figure out.

@QushyQushy
Copy link

Are there any news on this? I'm unable to use even XWayland for Docks and Screen Capture anymore.

Specs:
7945HX
4090M
32 GBs DDR5
BazziteOS
OBS Flatpak

@jwinarske
Copy link

I have done quite a bit of Wayland work in the past three years. I may have some bandwidth to help here. We started work on integrating CEF+Flutter in an embedded Linux Wayland environment as of last week.

My preference would be to not use GTK in any way, and I avoid GLFW like the plague; neither are a good solution for custom Wayland environments. libdecor can be used to provide window chrome; opposed to GTK. I also have a Wayland cpp client library I have been evolving: https://github.com/jwinarske/waypp

My current build config:

export GN_DEFINES="use_sysroot=false use_allocator=none symbol_level=1 is_cfi=false use_thin_lto=false use_vaapi=false use_ozone=true ozone_auto_platforms=false ozone_platform_headless=true ozone_platform_wayland=true ozone_platform_x11=false use_system_wayland_scanner=true use_xkbcommon=true use_system_minigbm=true use_system_libdrm=true use_system_libffi=true use_gtk=false"
cd cef
./cef_create_projects.sh
cd ..
ninja -C out/Debug_GN_x64/ cefclient cefsimple ceftests chrome_sandbox -j30

In above case one passes --ozone-platform=wayland

But I see there are a few gaps still... Is there a project board? Might be useful to quantify the Wayland work.

@vadz
Copy link

vadz commented Sep 26, 2024

My preference would be to not use GTK in any way

How would this work with embedding CEF into GTK applications?

@jwinarske
Copy link

My preference would be to not use GTK in any way

How would this work with embedding CEF into GTK applications?

If you want to embed CEF using your favorite windowing toolkit, then it would require said toolkit.

I think if there were a GitHub project created we could easily capture the requirements, and track status. Task execution priority would be determined by those doing the work.

@vadz
Copy link

vadz commented Sep 26, 2024

Sorry, if the question was unclear. Right now it's possible to embed CEF, using X11, into a GTK application (even if there are some known bugs). I'd like this to still be possible with Wayland. Will it be or is it becoming an explicit non-goal of this project?

@magreenblatt
Copy link
Collaborator Author

Chrome/Chromium uses GTK, so it will be necessary for CEF to maintain GTK compatibility.

@jthoward64
Copy link

I think what @jwinarske is getting at is that embedding CEF in Wayland should not require GTK

@jwinarske
Copy link

jwinarske commented Sep 26, 2024

snippet from ozone_overview.md

Native file dialogs are currently supported through the GTK toolkit. That
implies that the browser is compiled with glib and gtk enabled. Please
append the following gn args to your configuration:

``` shell
use_ozone=true
use_system_minigbm=true
use_system_libdrm=true
use_xkbcommon=true
use_glib=true
use_gtk=true

If you have a use case that does not require native dialogs (GTK); then you would want use_gtk=false.

grep of the source tree indicates usage of build flag:

~/code/chromium_git/chromium/src$ grep -r use_gtk
build/args/headless.gn:use_gtk = false
build/config/linux/gtk/gtk.gni:  use_gtk = is_linux && !is_castos
chromeos/lacros/BUILD.gn:assert(!use_gtk)
docs/ozone_overview.md:use_gtk=true
remoting/remoting_enable.gni:                    (!is_linux || (target_cpu != "arm64" && use_gtk))
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  gboolean use_gtk;
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  use_gtk = (operation->priv->handler == NULL) ||
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  if (use_gtk)
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  gboolean use_gtk;
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  use_gtk = (operation->priv->handler == NULL);
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  if (use_gtk)
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  gboolean use_gtk;
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  use_gtk = (operation->priv->handler == NULL);
third_party/wayland-protocols/gtk/gtk/gtkmountoperation.c:  if (use_gtk)
ui/base/BUILD.gn:    "USE_GTK=$use_gtk",
ui/gtk/gtk_ui.h:  // caller while |use_gtk_| is true.
ui/linux/BUILD.gn:  if (use_gtk) {
cef/BUILD.gn:    # GTK dependencies at all, in which case they can set `cef_use_gtk=false`.
cef/BUILD.gn:    cef_use_gtk = !use_sysroot
cef/BUILD.gn:  if (is_linux && cef_use_gtk) {
cef/BUILD.gn:      if (cef_use_gtk) {

CEF needs to support the use_gtk=false case.

@gelbphoenix
Copy link

Short question for my understanding: Why does CEF depend on GTK (if I picked that up right)?

@magreenblatt
Copy link
Collaborator Author

magreenblatt commented Sep 26, 2024

Native file dialogs are currently supported through the GTK toolkit.
CEF needs to support the use_gtk=false case.

use_gtk=false is not a configuration that we're likely to support or test officially, as we don't plan to ship CEF binaries lacking default dialogs. However, use_gtk=false may become a community-supported custom build configuration similar to how ozone_platform_x11=false works currently (original description, updated details).

@magreenblatt
Copy link
Collaborator Author

magreenblatt commented Sep 26, 2024

Note that Chromium is also developing a Qt backend as an alternative to GTK. Qt is currently disabled with CEF.

@magreenblatt
Copy link
Collaborator Author

magreenblatt commented Sep 26, 2024

I think if there were a GitHub project created we could easily capture the requirements, and track status. Task execution priority would be determined by those doing the work.

@jwinarske We should probably discuss/agree on goals before planning any work. For example, this specific issue is about embedding Wayland windows (created by CEF/Chromium) in third-party applications, and not specifically related to GTK. Do you have a proposal for how to accomplish that?

As a recap, this is the approach suggested by the original poster:

In case of Wayland, clients should take a wl_surface that they created (either via gdk, native Wayland or qt toolkit or whatever) and a wl_display they used and pass them to CEF. Depending on whether a parent wl_surface is passed or not, the CEF either will create a toplevel window or a subsurface that it will parent with the passed parent wl_surface. Then, it will also pass own wl_surface that it created along with a wl_subsurface, which Chromium will use to associate own wl_subsurface with.

The mechanism, which X11 uses for property changes (XChangeProperty or XConfigureWindow) to manipulate the state of any X11 windows, won’t work with Wayland. Instead, a client will always manipulate the CEF browser window via browser_->GetHost()->DoSmth(Args…). However, one must realizethat the calls that manipulate the state of the window (such as SetBounds(), Hide(), Show() and etc) may not result in actual Wayland calls as a subsurface should be treated as an overlay above a parent surface that cannot be really hidden, shown or placed to some arbitrary area in respect to parent’s local coordinates. Instead, the state changes must be propagated through calls to views::Widget or whatever mechanism content api provides.

@jwinarske
Copy link

jwinarske commented Sep 26, 2024

@magreenblatt Is the requirement to share within the same process, or different process?

The original description is sort-of correct, and relative to type of client you use. Not including xdg client toplevel constructs, to create a sub-surface you need:

  • valid wl_display
  • valid wl_compositor
  • valid parent wl_surface - usually the base wl_surface of the process; required for on_frame callbacks to work

To create EGL surface on sub-surface

  • valid egl physical display pointer

Example code that creates a sub-surface (includes optional egl surface creation):
https://github.com/toyota-connected/ivi-homescreen/blob/v2.0/shell/view/compositor_surface.cc#L64-L84

To create Vulkan surface on sub-surface

The benefit to using the Wayland frame callback mechanism is that it will suspend rendering when the window is occluded; saves resources

@magreenblatt
Copy link
Collaborator Author

Is the requirement to share within the same process, or different process?

I would say same process to start, as calling CefBrowserHost methods from a different process would require a client-specific IPC mechanism.

@jwinarske
Copy link

@magreenblatt Makes sense.

I'm thinking first pass is to add logic to mux X11 and Wayland includes/calls in CEF targets; treating them as mutually exclusive. Build could use the GN ozone variables. If you want to support subsurface in pre-GDK 3.90 then the sub-surface would have to be managed manually; if that's what we want. A positioner interface is available in the xdg-shell client.

Related GTK API

GDK_AVAILABLE_IN_ALL
struct wl_display      *gdk_wayland_display_get_wl_display      (GdkDisplay *display);

GDK_AVAILABLE_IN_ALL
struct wl_compositor   *gdk_wayland_display_get_wl_compositor   (GdkDisplay *display);

GDK_AVAILABLE_IN_ALL
struct wl_surface       *gdk_wayland_window_get_wl_surface       (GdkWindow *window);

GDK_AVAILABLE_IN_3_90
GdkWindow *              gdk_wayland_window_new_subsurface       (GdkDisplay            *display,
                                                                  int                    event_mask,
                                                                  const GdkRectangle    *position);

I'm out on holidays September 27, back October 14th.

@magreenblatt
Copy link
Collaborator Author

I'm thinking first pass is to add logic to mux X11 and Wayland includes/calls in CEF targets; treating them as mutually exclusive. Build could use the GN ozone variables.

Sounds reasonable. We should also make sure that switching backend at runtime via --ozone-platform works as expected.

I'm out on holidays September 27, back October 14th.

Have a good holiday!

@smathles
Copy link

smathles commented Oct 7, 2024

+1 for really hoping this is supported soon (spotify/discord can work with dirty workarounds, steam is just completely broken).

Excited to see some movement in the works! I'm afraid I'm not a wayland compositor expert in terms of contributing, but maybe there's some way I could help test things?

@eszlari
Copy link

eszlari commented Nov 1, 2024

There is a fallback in chromium if neither GTK nor Qt is available:
https://github.com/chromium/chromium/blob/main/ui/linux/fallback_linux_ui.cc

@carlosvalin94
Copy link

Hi, any news?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Framework Related to framework code or APIs help wanted Issue resolution will likely require community contributions linux Linux platform native Related to a native (non-Views) framework proposal Proposed change or action
Projects
None yet
Development

No branches or pull requests