GNOME Bugzilla – Bug 766284
[Wayland] gtk_window_present() not working
Last modified: 2018-05-30 12:20:29 UTC
Have some Application A in Workspace A, Epiphany in Workspace B. Click a link in an app in workspace A. Expected: Epiphany loads the page and grabs window focus; gnome-shell switches to workspace B. Actual: Epiphany loads the page, but you have no idea, because it's happening on a different workspace. Really frustrating. We used to use libwnck for this in X11. Any ideas for how to accomplish this in Wayland?
(In reply to Michael Catanzaro from comment #0) > Expected: Epiphany loads the page and grabs window focus; gnome-shell > switches to workspace B. Er, no. That would be better than what we do now, and easy to implement, so maybe we should do that. But the really expected behavior (the current behavior under X11) is to never switch workspaces, and open a new window if and only if none exists in the current workspace.
Hm... I wonder how this currently works under X11, because our libwnck dependency is not actually used anywhere in the code. I just removed it. It's definitely a Wayland regression, though.
OK, the problem is that the application is not setting the DESKTOP_STARTUP_ID env variable, which we use to get the user activation time from. In this case, we have in ephy-main.c a weird fallback to get the startup time from the X server, using X11 APIs directly. No such fallback exists for Wayland, so we consider the startup time to be 0, pass that to gtk_window_present_with_time(), and then of course the window does not get focused and the workspace does not get switched. This seems like it should be really easy to fix by checking in ephy_shell_open_uris_idle() if the startup time is 0 and, if so, calling gtk_window_present() instead of gtk_window_present_with_time(). Only problem is: it doesn't work, the call to gtk_window_present() does nothing. Have not investigated this yet besides to confirm it really is being called.
(In reply to Michael Catanzaro from comment #3) > Only problem is: it doesn't work, the call to gtk_window_present() does > nothing. Have not investigated this yet besides to confirm it really is > being called. It works if I call gtk_window_present_with_time() with the current time. Let's do that I guess.
The following fixes have been pushed:
The following fix has been pushed: af6a08f ephy-shell: Always focus the main window when loading tabs in Wayland
Created attachment 328034 [details] [review] ephy-shell: Always focus the main window when loading tabs in Wayland Else the window will never get focused, because most apps don't set DESKTOP_STARTUP_ID when launching Epiphany and therefore we have no plausible time to pass to gtk_window_present_with_time(). Note that gtk_window_present() on its own seems to do nothing.
For the record, this patch is completely bogus: X11 timestamps (which mutter uses on wayland as well) are in milliseconds from the monotonic clock, and you're passing seconds from the epoch. The reason it works is that mutter corrects invalid timestamps to CurrentTime (aka 0), and emits a warning to the logs. If the apps don't set a valid startup notification then fix the apps, don't work around it in a broken way.
(In reply to Giovanni Campagna from comment #8) > For the record, this patch is completely bogus: X11 timestamps (which mutter > uses on wayland as well) are in milliseconds from the monotonic clock, and > you're passing seconds from the epoch. Thanks for the heads up. > The reason it works is that mutter corrects invalid timestamps to > CurrentTime (aka 0), and emits a warning to the logs. If 0 is the current time, then why doesn't gtk_window_present_with_time(window, 0) work? That's what we were doing before this patch. And why doesn't gtk_window_present() work? Seems this should always focus the window, but it doesn't do anything. > If the apps don't set a valid startup notification then fix the apps, don't > work around it in a broken way. We really need a reliable way to force present the window when apps don't set a time in DESKTOP_STARTUP_ID. Such apps include Empathy, Evolution, Terminal; in fact, I'm not aware of any apps that are setting it as Epiphany requires.
> We really need a reliable way to force present the window The wayland protocol doesn't have api for this at all. As far as Wayland is concerned, managing the stacking order and focus is between the user and the compositor. That being said, we do have a "present" request in gtk-shell.
(In reply to Michael Catanzaro from comment #9) > We really need a reliable way to force present the window when apps don't > set a time in DESKTOP_STARTUP_ID. Such apps include Empathy, Evolution, > Terminal; in fact, I'm not aware of any apps that are setting it as Epiphany > requires. As Giovanni said, buggy apps need to be fixed.
(In reply to Michael Catanzaro from comment #4) > (In reply to Michael Catanzaro from comment #3) > > Only problem is: it doesn't work, the call to gtk_window_present() does > > nothing. Have not investigated this yet besides to confirm it really is > > being called. > > It works if I call gtk_window_present_with_time() with the current time. > Let's do that I guess. I'm not sure whats wrong here; the gtk code looks like it should work on wayland without extra shenanigans: we replace GDK_CURRENT_TIME / 0 with the timestamp from the last event we received.
The problem is the second early return (with the comment) here: static void gdk_wayland_window_focus (GdkWindow *window, guint32 timestamp) { GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); if (!impl->display_server.gtk_surface) return; /* We didn't have an event to fetch a time from, meaning we have nothing valid * to send. This should rather be translated to a 'needs-attention' request or * something. */ if (timestamp == GDK_CURRENT_TIME) return; gtk_surface1_present (impl->display_server.gtk_surface, timestamp); }
But look at this code in gtk_window_present_with_time: /* Translate a timestamp of GDK_CURRENT_TIME appropriately */ if (timestamp == GDK_CURRENT_TIME) { #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_WINDOW(gdk_window)) { GdkDisplay *display; display = gtk_widget_get_display (widget); timestamp = gdk_x11_display_get_user_time (display); } else #endif timestamp = gtk_get_current_event_time (); } gdk_window_focus (gdk_window, timestamp); I don't think GDK_CURRENT_TIME should reach gdk
*** Bug 771231 has been marked as a duplicate of this bug. ***
I think this needs to be debugged on the epiphany side. Which code paths are actually taken in your case in gtk_window_present_with_time and in gdk_wayland_window_focus ?
As this bug is assigned to epiphany, can the Bug 771231 be detached, and set as a separate bug?
(In reply to Mohammed Sadiq from comment #17) > As this bug is assigned to epiphany, can the Bug 771231 be detached, and set > as a separate bug? I think it is a duplicate; there's little change that this is an Epiphany issue. I will debug further soon and respond to Matthias. Setting NEEDINFO against myself in the meantime.
(In reply to Michael Catanzaro from comment #18) > I will debug further soon and respond to Matthias. Nevermind, there was the xdg-shell protocol bump so I'm stuck testing the GDK X11 backend right now. Will check it again in a month or two after I upgrade to F25.
*** Bug 775802 has been marked as a duplicate of this bug. ***
(In reply to Matthias Clasen from comment #16) > I think this needs to be debugged on the epiphany side. Which code paths are > actually taken in your case in gtk_window_present_with_time and in > gdk_wayland_window_focus ? Seems that gtk_get_current_event_time() returns GDK_CURRENT_TIME in gtk_window_present_with_time(). Due to bug #769835, this doesn't occur until I switch to the workspace that the existing Epiphany window is present on.
So yeah, bug #769835 really ruins things here. It's not a duplicate, because this issue predates WebKit's use of GtkGLArea and occurs in apps that do not use GtkGLArea at all (e.g. the nautilus bugs #771231 and bug #775802 that are duplicates of this), but it blocks debugging this further with Epiphany.
*** Bug 768151 has been marked as a duplicate of this bug. ***
*** Bug 775358 has been marked as a duplicate of this bug. ***
(In reply to Michael Catanzaro from comment #22) > So yeah, bug #769835 really ruins things here. It's not a duplicate, because > this issue predates WebKit's use of GtkGLArea and occurs in apps that do not > use GtkGLArea at all (e.g. the nautilus bugs #771231 and bug #775802 that > are duplicates of this), but it blocks debugging this further with Epiphany. Note that this can be tested this with nautilus or gedit instead to avoid this issue. All the duplicate reports are complaints about one of hose apps.
*** Bug 756202 has been marked as a duplicate of this bug. ***
*** Bug 784642 has been marked as a duplicate of this bug. ***
I wonder if the patch in https://bugzilla.gnome.org/show_bug.cgi?id=786455 might help for the timestamp==0 case that Michael described. Just deleting that if statement seems very simplistic to me though, no idea if 0 is a valid timestamp in wayland. The X11 backend has some heuristic for the timestamp==0 case as far as I remember.
*** Bug 786455 has been marked as a duplicate of this bug. ***
*** Bug 731101 has been marked as a duplicate of this bug. ***
*** Bug 787137 has been marked as a duplicate of this bug. ***
*** Bug 787384 has been marked as a duplicate of this bug. ***
This bug is present with GNOME 3.28. Always using X11 because of this bug. Any news on this? Happen with all GTK apps when clicking on a Shell notification.
Another broken case: - Launch gedit - Go to another workspace - Launch nautilus - Open a text file from nautilus - Nothing is happening (text file is opened in gedit but gnome-shell is not going to gedit workspace)
To summarize the issue, gtk_window_present() has no effect on Wayland. Nor does gtk_window_present_with_time() if you pass GDK_CURRENT_TIME (=0) as the timestamp. gtk_window_present_with_time() *does* work if you use a bogus timestamp like 42. My test setup is an app that's currently behind another app [both on the current workspace] that calls gtk_window_present() on itself. This is Bug 790724.
*** Bug 790724 has been marked as a duplicate of this bug. ***
I'm on Fedora 27, Gnome 3.26.2. I cannot reproduce the case described in comment #34. When I click on a text file in Nautilus, gedit is launched on current workspace in a new window. Another case: if I click on a link in Geary in a workspace, the shell switches to the workspace where Firefox is open and shows me the URL I clicked. I confirm the issue with Epiphany: tab opened in other workspace, focus remains on the current workspace. All these different behaviours are quite confusing. I came here while following bug #776881 (geary).
@federico: Firefox is not a wayland application, gtk_window_present() works for XWayland. The gedit case is if it's already launched, and you open a new file for nautilus, the focus should be given to the gedit windows, it doesn't work, does it?
Yes, it works for me. gedit was already launched and in workspace 1. I opened Nautilus in workspace 2 and clicked on a text file. gedit launches in workspace 2 in a new window and gets the focus. I thought some plugins enabled in gedit, like Restore Tabs, could be the reason why it works differently from you. I disabled it and tested it again. Same behaviour.
// Use present_with_time and a made up time so the present // actually works, as a work around for Bug 766284 // <https://bugzilla.gnome.org/show_bug.cgi?id=766284>. this.controller.main_window.present_with_time( (uint32) (get_real_time() / 1000) ); How geary fixed the issue with a workaround.
(In reply to Giovanni Campagna from comment #8) > For the record, this patch is completely bogus: X11 timestamps (which mutter > uses on wayland as well) are in milliseconds from the monotonic clock, and > you're passing seconds from the epoch. > The reason it works is that mutter corrects invalid timestamps to > CurrentTime (aka 0), and emits a warning to the logs. Still, this clearly does work in practice.
It seems kinda embarrassing that there isn't at least a workaround for this. Until someone figures out the perfect philosophical resolution to the whole current-time thing, can't we at least have a kludge that makes simply present()ing windows work, on the compositor we're telling everyone is superior?
The geary workaround does not work for everyone, here it make Gnome Shell unable to switch windows with Alt-Tab after this.
I am using since a while a Fedora copr repo with a patch to remove the check against GDK_CURRENT_TIME in gdk_wayland_window_focus and it works quite well for me, even if I have no idea if this is valid :) https://copr.fedorainfracloud.org/coprs/matmaul/gtkfix-f27/
I tried to fix the issue using present_with_time() but timestamp seems to be a GdkX11 thing... >timestamp = gtk_get_current_event_time (); >I don't think GDK_CURRENT_TIME should reach gdk Matthias, it should not but when you react to external events in your software: - Opening a new link in a browser - Raising window when software is launched from command line but already running gtk_get_current_event_time() will return GDK_CURRENT_TIME. So I guess the check in gdk_wayland_window_focus is wrong.
Can confirm Mathieu Velten comment, patching GTK by removing the check against GDK_CURRENT_TIME fixed the issue without any visible regression.
(In reply to Matthias Clasen from comment #14) > But look at this code in gtk_window_present_with_time: > > /* Translate a timestamp of GDK_CURRENT_TIME appropriately */ > if (timestamp == GDK_CURRENT_TIME) > { > #ifdef GDK_WINDOWING_X11 > if (GDK_IS_X11_WINDOW(gdk_window)) > { > GdkDisplay *display; > > display = gtk_widget_get_display (widget); > timestamp = gdk_x11_display_get_user_time (display); > } > else > #endif > timestamp = gtk_get_current_event_time (); > } > > gdk_window_focus (gdk_window, timestamp); > > > I don't think GDK_CURRENT_TIME should reach gdk I think that, under Wayland, we should be using the current time from the system if gtk_get_current_event_time() returns 0. Either in gdk_wayland_window_focus() (probably a bit late), or gtk_window_present_with_time() (better, IMO). I don't remember whether GTK+ Wayland expects monotonic time, and in which unit, but the output of g_get_monotonic_time() should be what you're looking to fallback to. Anyone to cook up a patch?
this is just more broken workarounds on top of broken workarounds, imo. If presenting a window without an event timestamp is a valid use case, then the Wayland protocol should just provide for that, and we can stop the handwringing for where to get a fake timestamp.
*** Bug 795690 has been marked as a duplicate of this bug. ***
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gtk/issues/624.
*** Bug 795534 has been marked as a duplicate of this bug. ***
*** Bug 796451 has been marked as a duplicate of this bug. ***