wmww / gtk-layer-shell

A library to create panels and other desktop components for Wayland using the Layer Shell protocol
GNU General Public License v3.0
318 stars 16 forks source link

webkit2gtk not working with layer shell #114

Closed FriederHannenheim closed 2 years ago

FriederHannenheim commented 2 years ago

I wanted to make a top bar that can be styled with html and css so I choose webkit2gtk and gtk layer shell. With the layer shell code commented out webkit2gtk works perfectly. But once I uncomment gtk_layer_init_for_window the window is completely transparent. I tried adding a button to see if the window is there at all but it didn't render either. It only rendered when I removed the WebView widget

wmww commented 2 years ago

Hmm, that's strange. Can you run the broken app with WAYLAND_DEBUG=1 and provide me the result of stderr? I can then use wayland-debug to see what it's doing.

For example:

WAYLAND_DEBUG=1 ./your_app 2>broken.log

And then upload broken.log

Also, what Wayland compositor and version are you running? (Sway v1.6.1?)

FriederHannenheim commented 2 years ago

Yeah I'm using Sway 1.6.1. Here's the log: http://ix.io/3IYP I could also send you the code/make the repo public but it's in Rust.

FriederHannenheim commented 2 years ago

Oh and I also have tested this with GTK v3.24.26 since that's the version known to work in compatibility.md. If you want I can downgrade and also get the logs from that version

wmww commented 2 years ago

Hmm, your code might be helpful. At first glance all I can tell is that it's making 4 different Wayland connections, which unfortunately limits the usefulness of the logs (they're all jumbled together, it's a known limitation of libwayland logging). I wonder why it would need more than 1 Wayland connection, or if this could be part of the problem.

FriederHannenheim commented 2 years ago

The code is here: https://github.com/FriederHannenheim/WebBar I haven't done anything with multiple Wayland connections but maybe the rust bindings are not perfect.

wmww commented 2 years ago

It appears the multiple Wayland connections is because it's spinning up an auxiliary process and acting as a Wayland server to it. Why WebKit that I do not know, but it doesn't seem to be the issue.

I noticed that when using GTK Layer Shell the main client connection is only attaching a null buffer to a surface. Without GTK Layer Shell (when it works) it's obviously attaching buffers to surfaces. By using wayland-debug and setting a breakpoint on wl_surface.attach in GDB mode I found the callstack for when it attaches a buffer:

#0  serialize_closure (closure=closure@entry=0x555555735920, buffer=buffer@entry=0x555555b39270, buffer_count=buffer_count@entry=5) at ../wayland/src/connection.c:1122
#1  0x00007ffff06d6506 in wl_closure_send (closure=closure@entry=0x555555735920, connection=0x55555565c4f0) at ../wayland/src/connection.c:1225
#2  0x00007ffff06d2c16 in wl_proxy_marshal_array_flags
    (proxy=proxy@entry=0x5555559704b0, opcode=opcode@entry=1, interface=interface@entry=0x0, version=version@entry=3, flags=flags@entry=0, args=args@entry=0x7fffffffcc90) at ../wayland/src/wayland-client.c:852
#3  0x00007ffff06d2ea0 in wl_proxy_marshal_flags (proxy=0x5555559704b0, opcode=1, interface=0x0, version=3, flags=0) at ../wayland/src/wayland-client.c:784
#4  0x00007ffff3b6a99d in  () at /usr/lib/libgdk-3.so.0
#5  0x00007ffff3b70c88 in  () at /usr/lib/libgdk-3.so.0
#6  0x00007ffff3b45633 in  () at /usr/lib/libgdk-3.so.0
#7  0x00007ffff3b45a28 in gdk_window_end_draw_frame () at /usr/lib/libgdk-3.so.0
#8  0x00007ffff3dd19c4 in gtk_main_do_event () at /usr/lib/libgtk-3.so.0
#9  0x00007ffff3b3a643 in  () at /usr/lib/libgdk-3.so.0
#10 0x00007ffff3b41fc2 in  () at /usr/lib/libgdk-3.so.0
#11 0x00007ffff3b4682b in  () at /usr/lib/libgdk-3.so.0
#12 0x00007ffff3b46a29 in  () at /usr/lib/libgdk-3.so.0
#13 0x00007ffff1be01c0 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#14 0x00007ffff1be0330 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#15 0x00007ffff3b3e179 in  () at /usr/lib/libgdk-3.so.0
#16 0x00007ffff3b2b5dc in  () at /usr/lib/libgdk-3.so.0
#17 0x00007ffff1acead4 in  () at /usr/lib/libglib-2.0.so.0
#18 0x00007ffff1ace435 in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#19 0x00007ffff1b227b9 in  () at /usr/lib/libglib-2.0.so.0
#20 0x00007ffff1acdab3 in g_main_loop_run () at /usr/lib/libglib-2.0.so.0
#21 0x00007ffff3dc793f in gtk_main () at /usr/lib/libgtk-3.so.0
#22 0x0000555555568f6a in gtk::auto::functions::main () at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gtk-0.14.3/src/auto/functions.rs:402
#23 0x00005555555659e7 in webbar::run (app=0x7fffffffdce8) at src/lib.rs:42
#24 0x0000555555564179 in core::ops::function::Fn::call<fn(&gtk::auto::application::Application), (&gtk::auto::application::Application)> ()
    at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ops/function.rs:70
#25 0x000055555556402b in gio::auto::application::{impl#2}::connect_activate::activate_trampoline<gtk::auto::application::Application, fn(&gtk::auto::application::Application)> (this=0x5555556350f0, f=0x1)
    at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.14.8/src/auto/application.rs:600
#26 0x00007ffff1bc2d8f in g_closure_invoke () at /usr/lib/libgobject-2.0.so.0
#27 0x00007ffff1bde718 in  () at /usr/lib/libgobject-2.0.so.0
#28 0x00007ffff1bdfdd9 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#29 0x00007ffff1be0330 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#30 0x00007ffff3831739 in  () at /usr/lib/libgio-2.0.so.0
#31 0x00007ffff383c28a in g_application_run () at /usr/lib/libgio-2.0.so.0
#32 0x00005555555645f7 in gio::application::{impl#0}::run_with_args<gtk::auto::application::Application, alloc::string::String> (self=0x7fffffffe370, args=...)
    at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.14.8/src/application.rs:30
#33 0x00005555555646e6 in gio::application::{impl#0}::run<gtk::auto::application::Application> (self=0x7fffffffe370)
    at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.14.8/src/application.rs:23
#34 0x0000555555563e2f in webbar::main () at src/main.rs:11

It looks like with GTK Layer Shell, gdk_window_end_draw_frame is not called for some reason.

wmww commented 2 years ago

Same stack trace (the one where it works), but with GTK built from source for debug symbols:

#0  serialize_closure (closure=closure@entry=0x555555723b20, buffer=buffer@entry=0x555555b36da0, buffer_count=buffer_count@entry=5) at ../wayland/src/connection.c:1122
#1  0x00007ffff0653506 in wl_closure_send (closure=closure@entry=0x555555723b20, connection=0x55555565cec0) at ../wayland/src/connection.c:1225
#2  0x00007ffff064fc16 in wl_proxy_marshal_array_flags
    (proxy=proxy@entry=0x555555b30b30, opcode=opcode@entry=1, interface=interface@entry=0x0, version=version@entry=3, flags=flags@entry=0, args=args@entry=0x7fffffffcb20) at ../wayland/src/wayland-client.c:852
#3  0x00007ffff064fea0 in wl_proxy_marshal_flags (proxy=0x555555b30b30, opcode=1, interface=0x0, version=3, flags=0) at ../wayland/src/wayland-client.c:784
#4  0x00007ffff3aee836 in wl_surface_attach (y=0, x=0, buffer=0x555555b45ee0, wl_surface=0x555555b30b30) at /usr/include/wayland-client-protocol.h:3739
#5  gdk_wayland_window_attach_image (window=window@entry=0x555555669370) at ../gdk/wayland/gdkwindow-wayland.c:869
#6  0x00007ffff3af0298 in gdk_window_impl_wayland_end_paint (window=0x555555669370) at ../gdk/wayland/gdkwindow-wayland.c:1042
#7  0x00007ffff3acea8b in gdk_window_end_paint_internal (window=window@entry=0x555555669370) at ../gdk/gdkwindow.c:3043
#8  0x00007ffff3acee20 in gdk_window_end_draw_frame (window=0x555555669370, context=0x555555b39810) at ../gdk/gdkwindow.c:3311
#9  0x00007ffff3d8c843 in gtk_main_do_event (event=0x7fffffffceb0) at ../gtk/gtkmain.c:1844
#10 gtk_main_do_event (event=<optimized out>) at ../gtk/gtkmain.c:1691
#11 0x00007ffff3ab5d55 in _gdk_event_emit (event=event@entry=0x7fffffffceb0) at ../gdk/gdkevents.c:73
#12 0x00007ffff3ac4f91 in _gdk_window_process_updates_recurse_helper (window=0x555555669370, expose_region=<optimized out>) at ../gdk/gdkwindow.c:3874
#13 0x00007ffff3ac6be1 in gdk_window_process_updates_internal (window=0x555555669370) at ../gdk/gdkwindow.c:4020
#14 0x00007ffff3ac6dd8 in gdk_window_process_updates_with_mode (window=<optimized out>, recurse_mode=<optimized out>) at ../gdk/gdkwindow.c:4215
#15 0x00007ffff1b5d1c0 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#16 0x00007ffff1b5d330 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#17 0x00007ffff3abe40f in _gdk_frame_clock_emit_paint (frame_clock=<optimized out>) at ../gdk/gdkframeclock.c:657
#18 0x00007ffff3abf0aa in gdk_frame_clock_paint_idle (data=<optimized out>) at ../gdk/gdkframeclockidle.c:597
#19 0x00007ffff3aaac29 in gdk_threads_dispatch (data=0x5555557f6540) at ../gdk/gdk.c:769
#20 0x00007ffff1a4bad4 in  () at /usr/lib/libglib-2.0.so.0
#21 0x00007ffff1a4b435 in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#22 0x00007ffff1a9f7b9 in  () at /usr/lib/libglib-2.0.so.0
#23 0x00007ffff1a4aab3 in g_main_loop_run () at /usr/lib/libglib-2.0.so.0
#24 0x00007ffff3d8b965 in gtk_main () at ../gtk/gtkmain.c:1329
#25 0x0000555555568f6a in gtk::auto::functions::main () at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gtk-0.14.3/src/auto/functions.rs:402
#26 0x00005555555659e7 in webbar::run (app=0x7fffffffdb58) at src/lib.rs:42
#27 0x0000555555564179 in core::ops::function::Fn::call<fn(&gtk::auto::application::Application), (&gtk::auto::application::Application)> ()
    at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ops/function.rs:70
#28 0x000055555556402b in gio::auto::application::{impl#2}::connect_activate::activate_trampoline<gtk::auto::application::Application, fn(&gtk::auto::application::Application)> (this=0x5555556350f0, f=0x1)
    at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.14.8/src/auto/application.rs:600
#29 0x00007ffff1b3fd8f in g_closure_invoke () at /usr/lib/libgobject-2.0.so.0
#30 0x00007ffff1b5b718 in  () at /usr/lib/libgobject-2.0.so.0
#31 0x00007ffff1b5cdd9 in g_signal_emit_valist () at /usr/lib/libgobject-2.0.so.0
#32 0x00007ffff1b5d330 in g_signal_emit () at /usr/lib/libgobject-2.0.so.0
#33 0x00007ffff37ae739 in  () at /usr/lib/libgio-2.0.so.0
#34 0x00007ffff37b928a in g_application_run () at /usr/lib/libgio-2.0.so.0
#35 0x00005555555645f7 in gio::application::{impl#0}::run_with_args<gtk::auto::application::Application, alloc::string::String> (self=0x7fffffffe1e0, args=...)
    at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.14.8/src/application.rs:30
#36 0x00005555555646e6 in gio::application::{impl#0}::run<gtk::auto::application::Application> (self=0x7fffffffe1e0)
    at /home/wmww/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.14.8/src/application.rs:23
#37 0x0000555555563e2f in webbar::main () at src/main.rs:11
wmww commented 2 years ago

Ah ha! On GTK Layer Shell we can't handle the wl_surface.frame callback which means we never call gdk_frame_clock_idle_thaw() which means _gdk_frame_clock_emit_paint() is not called in gdk_frame_clock_paint_idle() which means the buffer isn't attached.

(this is all more for my benefit than for yours, otherwise I won't remember anything)

wmww commented 2 years ago

The chain of cause and effect is really long and I'm a bit foggy on it, but I eventually discovered that in GTK source code commenting out:

GDK_PRIVATE_CALL (gdk_window_freeze_toplevel_updates) (gdk_window);

on line 10112 of gtkwindow.c fixes it. Now to figure out how to prevent that call from happening from within GTK Layer Shell.

wmww commented 2 years ago

When playing around with your code, I first discovered that putting the webview in a container seems to fix it. Upon further investigation, I found that the problem only occurs when the GtkWindow or widget within does not have a size request set. #115 just sets the size request for all custom surface windows based on their default size.

In the mean time while that is released and trickles down to distros, you can work around this bug by simply setting the size request on your GtkWindow.