flatpak / xdg-desktop-portal-gtk

Gtk implementation of xdg-desktop-portal
GNU Lesser General Public License v2.1
129 stars 101 forks source link

A reused GtkFileChooserNative isn't focused 2nd time #137

Open hadess opened 6 years ago

hadess commented 6 years ago

The GTK+ code in "teoemulator" keeps file dialogs around (for reasons unknown).

The code looks roughly like:

gboolean first_time = TRUE;

if (first_time) {
    dialog = gtk_file_chooser_native_new ("Title", parent, GTK_FILE_CHOOSER_ACTION_OPEN, "Open", "Cancel");
    first_time = FALSE;
}

if (gtk_native_dialog_run (GTK_NATIVE_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
  //Do something
}

gtk_native_dialog_hide(GTK_NATIVE_DIALOG(dialog));

The first time that function is called, dialog gets the focus, but not the second time. Restarting xdg-desktop-portal-gtk at any point (even when the application is running) will focus the dialog correctly.

hadess commented 6 years ago

The version of the portal is xdg-desktop-portal-gtk-0.99-1.fc28.x86_64

wjt commented 2 years ago

The GTK+ code in "teoemulator" keeps file dialogs around (for reasons unknown).

I guess Chromium must do the same thing, because I see the same issue there.

yttrium commented 2 years ago

I filed the issue, being pointed out to this earlier report. I would wish to add some observations. I see this issue (i.e., a file dialog immediately losses focus, except for the first time a dialog is called)

smcv commented 2 years ago

I would guess that the difference between desktop environments is caused by GNOME Shell having better (or at least stricter) focus-stealing prevention than XFCE's window manager?

yttrium commented 2 years ago

Not all seem to agree on the "better", as indicated in this bug that is still open: https://gitlab.gnome.org/GNOME/mutter/-/issues/673, but yes, this may be at the cause of the issue manifesting on Gnome Shell but not in xfce. I actually have installed Mate briefly, and there, it also happens.

smcv commented 2 years ago

Not all seem to agree on the "better"

Yes, that's why I said "or at least stricter". Preventing unwanted focus-stealing is a trade-off: ideally you want a heuristic that focuses as many as possible of the windows that the user expected to be focused, while also focusing as few as possible of the windows that the user didn't expect to be focused.

Realistically, this heuristic is always going to have false positives or false negatives or both, and it's up to the developers of the window manager or compositor to choose which failure mode they'll treat as being less bad. GNOME Shell has gone quite far in the direction of preventing unwanted focus-stealing, and the cost of that is that sometimes it prevents focus from being taken by a window that the user would have expected to take focus.

chergert commented 2 years ago

Currently in GNOME Text Editor we are seeing the focus not transitioned to the filechooser at all if you're on X11. https://gitlab.gnome.org/GNOME/gnome-text-editor/-/issues/334#note_1415335 has some additional details.

yttrium commented 2 years ago

The issue seems to be getting worse instead of getting better.

It does not happen on a fully up to date Ubuntu 20.04 LTS with a flatpak version 1.12.7 (a newer version than the default flatpak version is required to install e.g. chromium), which comes with xdg-desktop-portal 1.6.0-1.

This issue seriously breaks a keyboard based workflow.

wjt commented 2 years ago

About 10 years ago, I remember that the hot new thing was gtk_window_present_with_time(), which accepts a parameter for the timestamp of the user interaction which triggered the call. When a window asked for itself to be presented, the window manager would compare the given timestamp to its own record of the last user action (click or keystroke); if the window's claimed timestamp was the same as that last action, the window manager would allow it to take focus.

Now, I could be misremembering, and it could be that this mechanism no longer works anyway.

But:

Could it be worth an experiment in plumbing the result of gtk_get_current_event_time() (which seems to have become gtk_event_controller_get_current_event_time() in GTK 4) through the OpenFile method in the options vardict; and passing it to present_with_time() when showing the file chooser?

hadess commented 2 years ago

Could it be worth an experiment in plumbing the result of gtk_get_current_event_time() (which seems to have become gtk_event_controller_get_current_event_time() in GTK 4) through the OpenFile method in the options vardict; and passing it to present_with_time() when showing the file chooser?

That sounds like busy work when gtk_window_present() already has fallback code which should behave the same way when the chooser is "visible" in the GTK sense of the word: https://gitlab.gnome.org//GNOME/gtk/blob/gtk-3-24/gtk/gtkwindow.c#L10554

There's a similar code path in GTK4 from what I can tell, although xdg-desktop-portal-gnome doesn't call gtk_window_present() at all.

It's definitely worth adding some instrumentation to mutter to see whether the dialog even asks to be focused so we can check whether the problem is on the xdg-desktop-portal-gtk/gtk side, or the compositor side.

wjt commented 2 years ago

Forgive me if I am missing something obvious, but that fallback path looks like this:

      /* 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 ();
        }

I've just had a quick look at the implementations of gdk_x11_display_get_user_time and gtk_get_current_event_time. In both cases it appears that they retrieve the time of (roughly) the current, or most recent, input event handled by the current process. But the user action which causes the file chooser to be opened is not in the xdg-desktop-portal-gtk process, it is in some other application. In that case gtk_get_current_event_time() (the simpler of the two) in xdg-desktop-portal-gtk will just return GDK_CURRENT_TIME, i.e. 0, since no input event is being handled?

Surely some plumbing is needed to get the event time from the application which is invoking OpenFile through to xdg-desktop-portal-g*?

(But I agree that instrumenting Mutter is probably the place to start.)

hadess commented 2 years ago

I've just had a quick look at the implementations of gdk_x11_display_get_user_time and gtk_get_current_event_time. In both cases it appears that they retrieve the time of (roughly) the current, or most recent, input event handled by the current process. But the user action which causes the file chooser to be opened is not in the xdg-desktop-portal-gtk process, it is in some other application. In that case gtk_get_current_event_time() (the simpler of the two) in xdg-desktop-portal-gtk will just return GDK_CURRENT_TIME, i.e. 0, since no input event is being handled?

But it also happens on X11 (see earlier comments) which has a fallback that doesn't require user action and always is non-zero. So I'm going to ask again, are we sure that the missing timestamp is the reason why the dialogue isn't focused?

pacho2 commented 2 years ago

Could it be worth an experiment in plumbing the result of gtk_get_current_event_time() (which seems to have become gtk_event_controller_get_current_event_time() in GTK 4) through the OpenFile method in the options vardict; and passing it to present_with_time() when showing the file chooser?

That sounds like busy work when gtk_window_present() already has fallback code which should behave the same way when the chooser is "visible" in the GTK sense of the word: https://gitlab.gnome.org//GNOME/gtk/blob/gtk-3-24/gtk/gtkwindow.c#L10554

There's a similar code path in GTK4 from what I can tell, although xdg-desktop-portal-gnome doesn't call gtk_window_present() at all.

It's definitely worth adding some instrumentation to mutter to see whether the dialog even asks to be focused so we can check whether the problem is on the xdg-desktop-portal-gtk/gtk side, or the compositor side.

I also suffer the issue with Gnome 42 and xdg-desktop-portal-gnome-42.3 (with gtk-4.6.6) and running on a Xsession

To reproduce, I can simply open Google Chrome and press Ctrl+O. The gtk4 filechooser will open and, if I continue typing without clicking anywhere, I keep typing in the background window (just checked again while writing this message)

yttrium commented 2 years ago

For xorg users, an excellent way to work around this bug is to use devilspie/devilspie2. For devilspie2, one can use the rule

if ( get_application_name() == 'xdg-desktop-portal-gnome' and get_window_type() == 'WINDOW_TYPE_DIALOG' ) then focus_window(); end

Credit goes here: https://ubuntuforums.org/showthread.php?t=2478830&p=14112414#post14112414

Wayland users have no control on window focus and placement.

joetech commented 1 year ago

No fix yet? I'm on Wayland and this is annoying me several times a day.

SR-G commented 1 year ago

This issue is driving me mad every single day. How can this still be an open bug ?

kovaxis commented 1 year ago

I'm in the same situation. What are the steps to follow in order to fix this?

chergert commented 1 year ago

I'm in the same situation. What are the steps to follow in order to fix this?

Probably a couple of options to fixing this depending on how intrusive you want to be. The easiest fix is to go make the applications you're using not re-use dialogs and instead create new dialogs each time.

The more intrusive fix is to make Mutter (and other Compositors) smart enough to know that the portal can make requests w/ a timestamp of another process. That means that the compositor either needs to "trust" the portal (and possibly use a private Wayland protocol between them) or another mechanism needs to be added to delegate priority from the application to the portal.

And this needs to be done in such a way that it can't be used to inject surfaces above an active application to steal input.

i18nde commented 1 year ago

Seams to be a never ending story. ;-)

rkantos commented 10 months ago

For xorg users, an excellent way to work around this bug is to use devilspie/devilspie2. For devilspie2, one can use the rule

if ( get_application_name() == 'xdg-desktop-portal-gnome' and get_window_type() == 'WINDOW_TYPE_DIALOG' ) then focus_window(); end

Credit goes here: https://ubuntuforums.org/showthread.php?t=2478830&p=14112414#post14112414

Wayland users have no control on window focus and placement.

For some reason this focus_window() method never worked with my setup. Instead I got this to work:

if (get_window_type() == 'WINDOW_TYPE_DIALOG') then
    local window_title = get_window_name()
    print('Window title: ' .. window_title)
    os.execute('xdotool search --name "' .. window_title .. '" windowactivate')
end
starball5 commented 7 months ago

I think I used to have this issue with Chrome. Now I don't. I'm not sure exactly why. Between the time it didn't work and now, I was previously on Ubuntu 22.04.2, and then updated to Ubuntu 23.10. I was and still am using Ubuntu with Xorg instead of Wayland. I don't remember what Chrome version I was on before. Now I'm on v122.

I'm not sure, but I think I'm still having this with VS Code (currently 1.87.1) installed as a Snap. When I use the "Open File..." command, the first time, the native file picker will show up in front of the VS Code window, and the second time, it won't, and instead, I get a desktop notification that the file picker is ready.

pacho2 commented 7 months ago

It also looks fixed for me with gtk4 filechooser (tested on xorg session)

jandermoreira commented 2 weeks ago

This issue is still around...