Don't unconditionally place splashscreens (and other not-to-befocused

2005-02-12  Elijah Newren  <newren@gmail.com>

	Don't unconditionally place splashscreens (and other
	not-to-befocused windows) below the focus window.  Fixes #167042.

	* src/window.c: (intervening_user_event_occurred): new function
	taken from the timestamp comparison portion of the old
	window_takes_focus_on_map function, (window_state_on_map): new
	function with remainder of old window_takes_focus_on_map function
	that determines both whether the window will take focus and
	whether it should be placed on top, (meta_window_show): use
	place_on_top_on_map to determine window stacking instead of trying
	to infer it from takes_focus_on_map
This commit is contained in:
Elijah Newren 2005-02-12 07:19:41 +00:00 committed by Elijah Newren
parent d31a0829be
commit 9fa5c1d4b9
2 changed files with 138 additions and 82 deletions

View File

@ -1,3 +1,17 @@
2005-02-12 Elijah Newren <newren@gmail.com>
Don't unconditionally place splashscreens (and other
not-to-befocused windows) below the focus window. Fixes #167042.
* src/window.c: (intervening_user_event_occurred): new function
taken from the timestamp comparison portion of the old
window_takes_focus_on_map function, (window_state_on_map): new
function with remainder of old window_takes_focus_on_map function
that determines both whether the window will take focus and
whether it should be placed on top, (meta_window_show): use
place_on_top_on_map to determine window stacking instead of trying
to infer it from takes_focus_on_map
2005-02-11 Elijah Newren <newren@gmail.com>
Avoid new windows being obscured by the focus window (and thus

View File

@ -1542,104 +1542,134 @@ meta_window_queue_calc_showing (MetaWindow *window)
}
static gboolean
window_takes_focus_on_map (MetaWindow *window)
intervening_user_event_occurred (MetaWindow *window)
{
Time compare;
MetaWindow *focus_window;
focus_window = window->display->focus_window;
meta_topic (META_DEBUG_STARTUP,
"COMPARISON:\n"
" net_wm_user_time_set : %d\n"
" net_wm_user_time : %lu\n"
" initial_timestamp_set: %d\n"
" initial_timestamp : %lu\n",
window->net_wm_user_time_set,
window->net_wm_user_time,
window->initial_timestamp_set,
window->initial_timestamp);
if (focus_window != NULL)
{
meta_topic (META_DEBUG_STARTUP,
"COMPARISON (continued):\n"
" focus_window : %s\n"
" fw->net_wm_user_time : %lu\n",
focus_window->desc,
focus_window->net_wm_user_time);
}
/* We expect the most common case for not focusing a new window
* to be when a hint to not focus it has been set. Since we can
* deal with that case rapidly, we use special case it--this is
* merely a preliminary optimization. :)
*/
if ( ((window->net_wm_user_time_set == TRUE) &&
(window->net_wm_user_time == 0))
||
((window->initial_timestamp_set == TRUE) &&
(window->initial_timestamp == 0)))
{
meta_topic (META_DEBUG_STARTUP,
"window %s explicitly requested no focus\n",
window->desc);
return TRUE;
}
if (!(window->net_wm_user_time_set) && !(window->initial_timestamp_set))
{
meta_topic (META_DEBUG_STARTUP,
"no information about window %s found\n",
window->desc);
return FALSE;
}
/* To determine the "launch" time of an application,
* startup-notification can set the TIMESTAMP and the
* application (usually via its toolkit such as gtk or qt) can
* set the _NET_WM_USER_TIME. If both are set, then it means
* the user has interacted with the application since it
* launched, and _NET_WM_USER_TIME is the value that should be
* used in the comparison.
*/
compare = window->initial_timestamp_set ? window->initial_timestamp : 0;
compare = window->net_wm_user_time_set ? window->net_wm_user_time : compare;
if ((focus_window != NULL) &&
XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time))
{
meta_topic (META_DEBUG_STARTUP,
"window %s focus prevented by other activity; %lu < %lu\n",
window->desc, compare,
focus_window->net_wm_user_time);
return TRUE;
}
else
{
meta_topic (META_DEBUG_STARTUP,
"new window %s with no intervening events\n",
window->desc);
return FALSE;
}
}
/* This function determines what state the window should have assuming that it
* and the focus_window have no relation
*/
static void
window_state_on_map (MetaWindow *window,
gboolean *takes_focus,
gboolean *places_on_top)
{
gboolean intervening_events;
intervening_events = intervening_user_event_occurred (window);
*takes_focus = !intervening_events;
*places_on_top = *takes_focus;
/* don't initially focus windows that are intended to not accept
* focus
*/
if (!(window->input || window->take_focus))
return FALSE;
{
*takes_focus = FALSE;
return;
}
switch (window->type)
{
case META_WINDOW_UTILITY:
case META_WINDOW_TOOLBAR:
*takes_focus = FALSE;
*places_on_top = FALSE;
break;
case META_WINDOW_DOCK:
case META_WINDOW_DESKTOP:
case META_WINDOW_UTILITY:
case META_WINDOW_SPLASHSCREEN:
case META_WINDOW_TOOLBAR:
case META_WINDOW_MENU:
/* don't focus these */
/* don't focus any of these; places_on_top may be irrelevant for some of
* these (e.g. dock)--but you never know--the focus window might also be
* of the same type in some weird situation...
*/
*takes_focus = FALSE;
break;
case META_WINDOW_NORMAL:
case META_WINDOW_DIALOG:
case META_WINDOW_MODAL_DIALOG:
meta_topic (META_DEBUG_STARTUP,
"COMPARISON:\n"
" net_wm_user_time_set : %d\n"
" net_wm_user_time : %lu\n"
" initial_timestamp_set: %d\n"
" initial_timestamp : %lu\n",
window->net_wm_user_time_set,
window->net_wm_user_time,
window->initial_timestamp_set,
window->initial_timestamp);
if (window->display->focus_window != NULL) {
meta_topic (META_DEBUG_STARTUP,
"COMPARISON (continued):\n"
" focus_window : %s\n"
" fw->net_wm_user_time : %lu\n",
window->display->focus_window->desc,
window->display->focus_window->net_wm_user_time);
}
/* We expect the most common case for not focusing a new window
* to be when a hint to not focus it has been set. Since we can
* deal with that case rapidly, we use special case it--this is
* merely a preliminary optimization. :)
*/
if ( ((window->net_wm_user_time_set == TRUE) &&
(window->net_wm_user_time == 0))
||
((window->initial_timestamp_set == TRUE) &&
(window->initial_timestamp == 0)))
{
meta_topic (META_DEBUG_STARTUP,
"window %s explicitly requested no focus\n",
window->desc);
return FALSE;
}
if (!(window->net_wm_user_time_set) && !(window->initial_timestamp_set))
{
meta_topic (META_DEBUG_STARTUP,
"no information about window %s found\n",
window->desc);
return TRUE;
}
/* To determine the "launch" time of an application,
* startup-notification can set the TIMESTAMP and the
* application (usually via its toolkit such as gtk or qt) can
* set the _NET_WM_USER_TIME. If both are set, then it means
* the user has interacted with the application since it
* launched, and _NET_WM_USER_TIME is the value that should be
* used in the comparison.
*/
compare = window->initial_timestamp_set ? window->initial_timestamp : 0;
compare = window->net_wm_user_time_set ? window->net_wm_user_time : compare;
if ((window->display->focus_window != NULL) &&
XSERVER_TIME_IS_BEFORE (compare, window->display->focus_window->net_wm_user_time))
{
meta_topic (META_DEBUG_STARTUP,
"window %s focus prevented by other activity; %lu is before %lu\n",
window->desc, compare, window->display->focus_window->net_wm_user_time);
return FALSE;
}
else
{
meta_topic (META_DEBUG_STARTUP,
"new window %s with no intervening events\n",
window->desc);
return TRUE;
}
/* The default is correct for these */
break;
}
return FALSE;
}
void
@ -1648,6 +1678,7 @@ meta_window_show (MetaWindow *window)
gboolean did_placement;
gboolean did_show;
gboolean takes_focus_on_map;
gboolean place_on_top_on_map;
meta_topic (META_DEBUG_WINDOW_STATE,
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
@ -1655,11 +1686,18 @@ meta_window_show (MetaWindow *window)
did_show = FALSE;
did_placement = FALSE;
takes_focus_on_map = window_takes_focus_on_map (window);
window_state_on_map (window, &takes_focus_on_map, &place_on_top_on_map);
if ( (!takes_focus_on_map) && (window->display->focus_window != NULL) )
meta_topic (META_DEBUG_WINDOW_STATE,
"Window %s %s focus on map, and %s place on top on map.\n",
window->desc,
takes_focus_on_map ? "does" : "does not",
place_on_top_on_map ? "does" : "does not");
if ( !takes_focus_on_map &&
window->display->focus_window != NULL &&
!place_on_top_on_map )
{
if (meta_window_is_ancestor_of_transient (window->display->focus_window,
window))
{
@ -1778,7 +1816,11 @@ meta_window_show (MetaWindow *window)
}
else
{
window->wm_state_demands_attention = TRUE;
/* Only set the demands attention hint if the window doesn't
* take focus on map and it isn't placed on top on map.
*/
if (!place_on_top_on_map)
window->wm_state_demands_attention = TRUE;
/* Prevent EnterNotify events in sloppy/mouse focus from
* erroneously focusing the window that had been denied