Re: Focus stealing prevention
- From: Benjamin Kahn <xkahn ximian com>
- To: Elijah Newren <newren gmail com>
- Cc: Gnome Desktop Development List <desktop-devel-list gnome org>
- Subject: Re: Focus stealing prevention
- Date: Mon, 06 Dec 2004 13:24:17 -0500
Elijah,
Seems like this would fit quite nicely in this document:
http://developer.gnome.org/doc/guides/programming-guidelines/book1.html
Which is linked to from here:
http://developer.gnome.org/doc/guides/programming-guidelines/
On Sun, 2004-12-05 at 16:14 -0700, Elijah Newren wrote:
> Focus stealing prevention is active in Metacity. Roughly, it means
> that if a window was launched at time A, and the user interacted with
> a different window at time B, and B>A, then the launched window will
> not be focused when it appears. This allows a user to work with an
> application while impatiently waiting for that really slow app
> (*cough* OpenOffice *cough*) to show up without being interrupted
> mid-thought when it finally does. It also prevents those annoying
> Instant Message windows from taking your keystrokes and sending them
> to someone when you meant to be typing them into the application
> window asking for your root password.
>
> There's a couple small bugs with it (the dependencies of #149028 for
> the curious), but it mostly works right now. The main thing that we
> need is for applications to do more to support it. gtk+ tries to
> handle things in a sane manner so that things just work, but it
> doesn't always have sufficient information. Therefore, we need to (A)
> make sure applications are launched with startup notification, and (B)
> get applications to set the timestamp causing a new window to be shown
> in the cases where gtk+'s default is not correct. The exact
> requirements are listed below.
>
> Summary of what applications need to do:
> ----------------------------------------------------------------------
>
> - If you are launching applications:
> 1) Use startup notification (i.e. use gnome_desktop_item_launch()
> or a related function)
>
> - If you open a window "out of the blue" (not in response to user
> input):
> 1) Call gtk_window_set_focus_on_map (window, FALSE) before showing
> the window
>
> - If you open a window a delayed amount of time after a user action
> (and the user could feasibly interact further with the application
> before the window appears):
> 1) Obtain the timestamp of the user action that results in the
> later window opening
> 2) Call gdk_x11_window_set_user_time (gtk_toplevel_window->window,
> timestamp_of_launch_event)
> after realizing (i.e. gtk_widget_realize()) the window but
> before showing it
>
> - If you have a new instance of your app tell a previously running
> instance to open a new window and then you quit the new instance:
> 1) Get the launch timestamp from the DESKTOP_STARTUP_ID environment
> variable (format is "<unique>_TIME<timestamp>") at program start
> 2) Forward the timestamp to the previous instance
> 3) Have the previous instance call
> gdk_x11_window_set_user_time (gtk_toplevel_window->window,
> timestamp_of_launch_event)
> after realizing the new window but before showing it.
>
> - If you have one application request a different already-running
> application to open a new window:
> 1) Obtain the timestamp of the user action that results in the
> request to the other app to open a window
> 2) Send the timestamp along with the request
> 3) Have other other app call
> gdk_x11_window_set_user_time (gtk_toplevel_window->window,
> timestamp_of_launch_event)
> after realizing the window but before showing it.
>
>
> All the nasty details of why applications need to do this:
> ----------------------------------------------------------------------
>
> Making sure applications are launched with startup-notification:
>
> If applications aren't launched with startup-notification, then there
> will be no timestamp to compare with for the first window that opens.
> This means that focus stealing prevention can't work. For now,
> metacity focuses new windows under this circumstance, but we may
> change that (mainly to make it easier to find broken application
> launchers that don't use startup-notification). Even if we don't
> change it, there's more than just the inconvenience of having a window
> steal focus: for those applications that need to forward the launch
> timestamp to a previous instance such as gnome-terminal, they won't be
> able to obtain any such timestamp if they aren't launched with startup
> notification--meaning that the new window that gets open will likely
> not be focused as it should be. (An example of where this problem
> currently occurs is in the right-click desktop menu to open a
> gnome-terminal). So, we really do need startup notification to be
> used when launching applications. gnome_desktop_item_launch() and its
> friends are meant to handle this.
>
> Getting applications to set the timestamp of launch when needed:
>
> When a new window is opened, gtk+ sets the timestamp specifying when
> it was launched to the user's last interaction with the application.
> (If it is the first window of an app, then startup-notification is
> used since the user hasn't yet interacted with the app). This fails
> under four circumstances: (1) if a window appears "out of nowhere"
> (i.e. not in response to user input--for example, think of a
> word-processor trying to do auto-save, failing, and then displaying an
> error dialog), (2) if a window appears after a delay from the user
> interaction and the user has meanwhile interacted with that same
> application (think of trying to load a mis-typed URL in one tab while
> typing in another tab or window), (3) if an application, when
> launched, forwards a "please open a new window" request to a
> previously running instance instead of opening a window itself (this
> is what applications like nautilus, gnome-terminal, epiphany, galeon,
> mozilla, etc. do), and (4) if a user interaction in one application
> causes a different application to open a window (think of a user
> clicking on a URL in an email client and the email client sending a
> message to an already running web browser, for example)
>
> Note that in cases (1) and (2) the problem is that the window can be
> focused when it shouldn't be. That's no worse than the behavior we've
> always had, but it would be nice to improve things. In cases (3) and
> (4) we get the problem that the window may not be focused when it
> should be, i.e. a regression from previous behavior.
>
> In case (1), if a window appears out of nowhere, the window shouldn't
> take focus. To ensure this, the application needs to call
> gtk_window_set_focus_on_map (window, FALSE)
> before showing the window.
>
> In case (2), the timestamp gtk+ will be using will be the wrong one.
> To fix this, the application will need to get the timestamp of the
> event that caused the window to be launched, and then after realizing
> the window but before showing it, the application will need to call
> gdk_x11_window_set_user_time (gtk_toplevel_window->window,
> timestamp_of_launch_event)
>
> In case (3), the application needs to obtain the timestamp that caused
> it to be launched from startup-notification, forward that to the
> previously running instance, and then have the previously running
> instance set the timestamp manually. The timestamp can be obtained
> from startup-notification by reading the DESKTOP_STARTUP_ID
> environment variable before calling gtk_init (gtk_init unsets that
> environment variable); it has the format
> <unique identifier>_TIME<timestamp of launch event>
> After forwarding the timestamp, the previous instance sets the
> timestamp for the new window it opens using
> gdk_x11_window_set_user_time (just as is done for case (2) above).
> Note that for case (3), things are simplified considerably if you are
> already forwarding the DESKTOP_STARTUP_ID from the new instance to the
> old (which is a good idea anyway so that you can tell the desktop when
> to quit the hourglass cursor thingy for startup notification); bug
> 156413 has a patch that shows how simple this case is for
> gnome-terminal under this condition.
>
> Case (4) is somewhat of a mix of cases 2 and 3. The application needs
> to get the timestamp from the relevant ButtonPress or KeyPress event
> (or call gtk_get_current_event_time()), forward it to the other
> application that will open a window, and then the application that
> opens a window will need to call gdk_x11_window_set_user_time() as
> described above.
> _______________________________________________
> desktop-devel-list mailing list
> desktop-devel-list gnome org
> http://mail.gnome.org/mailman/listinfo/desktop-devel-list
>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]