Re: Focus stealing prevention



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]