mirror of
https://github.com/brl/mutter.git
synced 2024-11-30 12:00:44 -05:00
core: Make keyboard focus handling happen per-keyboard
MetaFocusInfo is a struct holding all necessary info, code has been updated to use the per-keyboard focus info instead of the old fields.
This commit is contained in:
parent
4cb9a5e3bf
commit
bde0d28f1b
@ -230,6 +230,35 @@ bell_flash_window_frame (MetaWindow *window)
|
|||||||
bell_unflash_frame, window->frame, NULL);
|
bell_unflash_frame, window->frame, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaWindow *
|
||||||
|
get_flash_window (MetaDisplay *display,
|
||||||
|
XkbAnyEvent *xkb_ev)
|
||||||
|
{
|
||||||
|
XkbBellNotifyEvent *xkb_bell_event;
|
||||||
|
MetaWindow *window;
|
||||||
|
|
||||||
|
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||||
|
|
||||||
|
xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
||||||
|
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||||
|
|
||||||
|
if (!window &&
|
||||||
|
g_hash_table_size (display->focus_info) == 1)
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
MetaFocusInfo *info;
|
||||||
|
|
||||||
|
/* If there is only one focused window, use it */
|
||||||
|
g_hash_table_iter_init (&iter, display->focus_info);
|
||||||
|
|
||||||
|
if (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info) &&
|
||||||
|
info->focus_window && info->focus_window->frame)
|
||||||
|
window = info->focus_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flashes the frame of the focussed window. If there is no focussed window,
|
* Flashes the frame of the focussed window. If there is no focussed window,
|
||||||
* flashes the screen.
|
* flashes the screen.
|
||||||
@ -241,15 +270,11 @@ static void
|
|||||||
bell_flash_frame (MetaDisplay *display,
|
bell_flash_frame (MetaDisplay *display,
|
||||||
XkbAnyEvent *xkb_ev)
|
XkbAnyEvent *xkb_ev)
|
||||||
{
|
{
|
||||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
|
|
||||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
window = get_flash_window (display, xkb_ev);
|
||||||
if (!window && (display->focus_window))
|
|
||||||
{
|
|
||||||
window = display->focus_window;
|
|
||||||
}
|
|
||||||
if (window && window->frame)
|
if (window && window->frame)
|
||||||
{
|
{
|
||||||
bell_flash_window_frame (window);
|
bell_flash_window_frame (window);
|
||||||
@ -310,9 +335,7 @@ meta_bell_notify (MetaDisplay *display,
|
|||||||
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
|
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
|
||||||
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
|
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
|
||||||
|
|
||||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
window = get_flash_window (display, xkb_ev);
|
||||||
if (!window && (display->focus_window) && (display->focus_window->frame))
|
|
||||||
window = display->focus_window;
|
|
||||||
|
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +58,7 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
|
|||||||
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||||
|
|
||||||
typedef struct _MetaGrabInfo MetaGrabInfo;
|
typedef struct _MetaGrabInfo MetaGrabInfo;
|
||||||
|
typedef struct _MetaFocusInfo MetaFocusInfo;
|
||||||
|
|
||||||
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
|
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
@ -126,6 +127,26 @@ struct _MetaGrabInfo
|
|||||||
int grab_resize_timeout_id;
|
int grab_resize_timeout_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _MetaFocusInfo
|
||||||
|
{
|
||||||
|
/* This is the actual window from focus events,
|
||||||
|
* not the one we last set
|
||||||
|
*/
|
||||||
|
MetaWindow *focus_window;
|
||||||
|
|
||||||
|
/* window we are expecting a FocusIn event for or the current focus
|
||||||
|
* window if we are not expecting any FocusIn/FocusOut events; not
|
||||||
|
* perfect because applications can call XSetInputFocus directly.
|
||||||
|
* (It could also be messed up if a timestamp later than current
|
||||||
|
* time is sent to meta_display_set_input_focus_window, though that
|
||||||
|
* would be a programming error). See bug 154598 for more info.
|
||||||
|
*/
|
||||||
|
MetaWindow *expected_focus_window;
|
||||||
|
|
||||||
|
/* last timestamp passed to XSetInputFocus */
|
||||||
|
guint32 last_focus_time;
|
||||||
|
};
|
||||||
|
|
||||||
struct _MetaDisplay
|
struct _MetaDisplay
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
@ -144,22 +165,8 @@ struct _MetaDisplay
|
|||||||
#include <meta/atomnames.h>
|
#include <meta/atomnames.h>
|
||||||
#undef item
|
#undef item
|
||||||
|
|
||||||
/* This is the actual window from focus events,
|
/* keyboard -> MetaFocusInfo hashtable */
|
||||||
* not the one we last set
|
GHashTable *focus_info;
|
||||||
*/
|
|
||||||
MetaWindow *focus_window;
|
|
||||||
|
|
||||||
/* window we are expecting a FocusIn event for or the current focus
|
|
||||||
* window if we are not expecting any FocusIn/FocusOut events; not
|
|
||||||
* perfect because applications can call XSetInputFocus directly.
|
|
||||||
* (It could also be messed up if a timestamp later than current
|
|
||||||
* time is sent to meta_display_set_input_focus_window, though that
|
|
||||||
* would be a programming error). See bug 154598 for more info.
|
|
||||||
*/
|
|
||||||
MetaWindow *expected_focus_window;
|
|
||||||
|
|
||||||
/* last timestamp passed to XSetInputFocus */
|
|
||||||
guint32 last_focus_time;
|
|
||||||
|
|
||||||
/* last user interaction time in any app */
|
/* last user interaction time in any app */
|
||||||
guint32 last_user_time;
|
guint32 last_user_time;
|
||||||
@ -478,5 +485,8 @@ void meta_display_remove_grab_info (MetaDisplay *display,
|
|||||||
|
|
||||||
MetaGrabInfo * meta_display_get_grab_info (MetaDisplay *display,
|
MetaGrabInfo * meta_display_get_grab_info (MetaDisplay *display,
|
||||||
MetaDevice *device);
|
MetaDevice *device);
|
||||||
|
MetaFocusInfo * meta_display_get_focus_info (MetaDisplay *display,
|
||||||
|
MetaDevice *device);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -189,7 +189,8 @@ static void prefs_changed_callback (MetaPreference pref,
|
|||||||
static void sanity_check_timestamps (MetaDisplay *display,
|
static void sanity_check_timestamps (MetaDisplay *display,
|
||||||
guint32 known_good_timestamp);
|
guint32 known_good_timestamp);
|
||||||
|
|
||||||
MetaGroup* get_focussed_group (MetaDisplay *display);
|
MetaGroup* get_focussed_group (MetaDisplay *display,
|
||||||
|
MetaDevice *keyboard);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_display_get_property(GObject *object,
|
meta_display_get_property(GObject *object,
|
||||||
@ -202,7 +203,16 @@ meta_display_get_property(GObject *object,
|
|||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
case PROP_FOCUS_WINDOW:
|
case PROP_FOCUS_WINDOW:
|
||||||
g_value_set_object (value, display->focus_window);
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *device;
|
||||||
|
|
||||||
|
/* Always follow the VCK focus */
|
||||||
|
device = meta_device_map_lookup (display->device_map,
|
||||||
|
META_CORE_KEYBOARD_ID);
|
||||||
|
focus_info = meta_display_get_focus_info (display, device);
|
||||||
|
g_value_set_object (value, focus_info->focus_window);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
@ -468,8 +478,6 @@ meta_display_open (void)
|
|||||||
the_display->pending_pings = NULL;
|
the_display->pending_pings = NULL;
|
||||||
the_display->autoraise_timeout_id = 0;
|
the_display->autoraise_timeout_id = 0;
|
||||||
the_display->autoraise_window = NULL;
|
the_display->autoraise_window = NULL;
|
||||||
the_display->focus_window = NULL;
|
|
||||||
the_display->expected_focus_window = NULL;
|
|
||||||
|
|
||||||
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
|
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
|
||||||
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
|
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
|
||||||
@ -551,6 +559,8 @@ meta_display_open (void)
|
|||||||
|
|
||||||
the_display->current_grabs = g_hash_table_new_full (NULL, NULL, NULL,
|
the_display->current_grabs = g_hash_table_new_full (NULL, NULL, NULL,
|
||||||
(GDestroyNotify) g_free);
|
(GDestroyNotify) g_free);
|
||||||
|
the_display->focus_info = g_hash_table_new_full (NULL, NULL, NULL,
|
||||||
|
(GDestroyNotify) g_free);
|
||||||
the_display->edge_resistance_info = g_hash_table_new (NULL, NULL);
|
the_display->edge_resistance_info = g_hash_table_new (NULL, NULL);
|
||||||
|
|
||||||
#ifdef HAVE_XSYNC
|
#ifdef HAVE_XSYNC
|
||||||
@ -784,7 +794,6 @@ meta_display_open (void)
|
|||||||
DefaultRootWindow (the_display->xdisplay),
|
DefaultRootWindow (the_display->xdisplay),
|
||||||
PropertyChangeMask);
|
PropertyChangeMask);
|
||||||
|
|
||||||
the_display->last_focus_time = timestamp;
|
|
||||||
the_display->last_user_time = timestamp;
|
the_display->last_user_time = timestamp;
|
||||||
the_display->compositor = NULL;
|
the_display->compositor = NULL;
|
||||||
|
|
||||||
@ -1954,8 +1963,14 @@ event_callback (XEvent *event,
|
|||||||
/* This is from our synchronous grab since
|
/* This is from our synchronous grab since
|
||||||
* it has no modifiers and was on the client window
|
* it has no modifiers and was on the client window
|
||||||
*/
|
*/
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *keyboard;
|
||||||
int mode;
|
int mode;
|
||||||
|
|
||||||
|
/* This is a pointer event, get the paired keyboard */
|
||||||
|
keyboard = meta_device_get_paired_device (device);
|
||||||
|
focus_info = meta_display_get_focus_info (display, keyboard);
|
||||||
|
|
||||||
/* When clicking a different app in click-to-focus
|
/* When clicking a different app in click-to-focus
|
||||||
* in application-based mode, and the different
|
* in application-based mode, and the different
|
||||||
* app is not a dock or desktop, eat the focus click.
|
* app is not a dock or desktop, eat the focus click.
|
||||||
@ -1965,9 +1980,9 @@ event_callback (XEvent *event,
|
|||||||
!window->has_focus &&
|
!window->has_focus &&
|
||||||
window->type != META_WINDOW_DOCK &&
|
window->type != META_WINDOW_DOCK &&
|
||||||
window->type != META_WINDOW_DESKTOP &&
|
window->type != META_WINDOW_DESKTOP &&
|
||||||
(display->focus_window == NULL ||
|
(focus_info == NULL || focus_info->focus_window == NULL ||
|
||||||
!meta_window_same_application (window,
|
!meta_window_same_application (window,
|
||||||
display->focus_window)))
|
focus_info->focus_window)))
|
||||||
mode = AsyncPointer; /* eat focus click */
|
mode = AsyncPointer; /* eat focus click */
|
||||||
else
|
else
|
||||||
mode = ReplayPointer; /* give event back */
|
mode = ReplayPointer; /* give event back */
|
||||||
@ -2051,6 +2066,9 @@ event_callback (XEvent *event,
|
|||||||
detail != NotifyInferior &&
|
detail != NotifyInferior &&
|
||||||
meta_display_focus_sentinel_clear (display))
|
meta_display_focus_sentinel_clear (display))
|
||||||
{
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *keyboard;
|
||||||
|
|
||||||
switch (meta_prefs_get_focus_mode ())
|
switch (meta_prefs_get_focus_mode ())
|
||||||
{
|
{
|
||||||
case META_FOCUS_MODE_SLOPPY:
|
case META_FOCUS_MODE_SLOPPY:
|
||||||
@ -2082,6 +2100,10 @@ event_callback (XEvent *event,
|
|||||||
"Auto raise is disabled\n");
|
"Auto raise is disabled\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyboard = meta_device_get_paired_device (device);
|
||||||
|
focus_info = meta_display_get_focus_info (display, keyboard);
|
||||||
|
|
||||||
/* In mouse focus mode, we defocus when the mouse *enters*
|
/* In mouse focus mode, we defocus when the mouse *enters*
|
||||||
* the DESKTOP window, instead of defocusing on LeaveNotify.
|
* the DESKTOP window, instead of defocusing on LeaveNotify.
|
||||||
* This is because having the mouse enter override-redirect
|
* This is because having the mouse enter override-redirect
|
||||||
@ -2093,12 +2115,14 @@ event_callback (XEvent *event,
|
|||||||
*/
|
*/
|
||||||
if (window->type == META_WINDOW_DESKTOP &&
|
if (window->type == META_WINDOW_DESKTOP &&
|
||||||
meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
|
meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
|
||||||
display->expected_focus_window != NULL)
|
focus_info->expected_focus_window != NULL)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Unsetting focus from %s due to mouse entering "
|
"Unsetting focus on device %d "
|
||||||
|
"from %s due to mouse entering "
|
||||||
"the DESKTOP window\n",
|
"the DESKTOP window\n",
|
||||||
display->expected_focus_window->desc);
|
meta_device_get_id (keyboard),
|
||||||
|
focus_info->expected_focus_window->desc);
|
||||||
meta_display_focus_the_no_focus_window (display,
|
meta_display_focus_the_no_focus_window (display,
|
||||||
window->screen,
|
window->screen,
|
||||||
evtime);
|
evtime);
|
||||||
@ -4165,12 +4189,18 @@ meta_display_increment_event_serial (MetaDisplay *display)
|
|||||||
void
|
void
|
||||||
meta_display_update_active_window_hint (MetaDisplay *display)
|
meta_display_update_active_window_hint (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *keyboard;
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
|
|
||||||
gulong data[1];
|
gulong data[1];
|
||||||
|
|
||||||
if (display->focus_window)
|
keyboard = meta_device_map_lookup (display->device_map,
|
||||||
data[0] = display->focus_window->xwindow;
|
META_CORE_KEYBOARD_ID);
|
||||||
|
focus_info = meta_display_get_focus_info (display, keyboard);
|
||||||
|
|
||||||
|
if (focus_info && focus_info->focus_window)
|
||||||
|
data[0] = focus_info->focus_window->xwindow;
|
||||||
else
|
else
|
||||||
data[0] = None;
|
data[0] = None;
|
||||||
|
|
||||||
@ -4558,23 +4588,29 @@ meta_display_window_has_pending_pings (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaGroup*
|
MetaGroup*
|
||||||
get_focussed_group (MetaDisplay *display)
|
get_focussed_group (MetaDisplay *display,
|
||||||
|
MetaDevice *keyboard)
|
||||||
{
|
{
|
||||||
if (display->focus_window)
|
MetaFocusInfo *focus_info;
|
||||||
return display->focus_window->group;
|
|
||||||
|
focus_info = meta_display_get_focus_info (display, keyboard);
|
||||||
|
|
||||||
|
if (focus_info && focus_info->focus_window)
|
||||||
|
return focus_info->focus_window->group;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \
|
#define IN_TAB_CHAIN(w,d,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \
|
||||||
|| ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \
|
|| ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \
|
||||||
|| ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focussed_group(w->display))))
|
|| ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focussed_group(w->display, d))))
|
||||||
|
|
||||||
static MetaWindow*
|
static MetaWindow*
|
||||||
find_tab_forward (MetaDisplay *display,
|
find_tab_forward (MetaDisplay *display,
|
||||||
MetaTabList type,
|
MetaTabList type,
|
||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
MetaWorkspace *workspace,
|
MetaWorkspace *workspace,
|
||||||
|
MetaDevice *device,
|
||||||
GList *start,
|
GList *start,
|
||||||
gboolean skip_first)
|
gboolean skip_first)
|
||||||
{
|
{
|
||||||
@ -4592,7 +4628,7 @@ find_tab_forward (MetaDisplay *display,
|
|||||||
MetaWindow *window = tmp->data;
|
MetaWindow *window = tmp->data;
|
||||||
|
|
||||||
if (window->screen == screen &&
|
if (window->screen == screen &&
|
||||||
IN_TAB_CHAIN (window, type))
|
IN_TAB_CHAIN (window, device, type))
|
||||||
return window;
|
return window;
|
||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
@ -4603,7 +4639,7 @@ find_tab_forward (MetaDisplay *display,
|
|||||||
{
|
{
|
||||||
MetaWindow *window = tmp->data;
|
MetaWindow *window = tmp->data;
|
||||||
|
|
||||||
if (IN_TAB_CHAIN (window, type))
|
if (IN_TAB_CHAIN (window, device, type))
|
||||||
return window;
|
return window;
|
||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
@ -4617,6 +4653,7 @@ find_tab_backward (MetaDisplay *display,
|
|||||||
MetaTabList type,
|
MetaTabList type,
|
||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
MetaWorkspace *workspace,
|
MetaWorkspace *workspace,
|
||||||
|
MetaDevice *device,
|
||||||
GList *start,
|
GList *start,
|
||||||
gboolean skip_last)
|
gboolean skip_last)
|
||||||
{
|
{
|
||||||
@ -4633,7 +4670,7 @@ find_tab_backward (MetaDisplay *display,
|
|||||||
MetaWindow *window = tmp->data;
|
MetaWindow *window = tmp->data;
|
||||||
|
|
||||||
if (window->screen == screen &&
|
if (window->screen == screen &&
|
||||||
IN_TAB_CHAIN (window, type))
|
IN_TAB_CHAIN (window, device, type))
|
||||||
return window;
|
return window;
|
||||||
|
|
||||||
tmp = tmp->prev;
|
tmp = tmp->prev;
|
||||||
@ -4644,7 +4681,7 @@ find_tab_backward (MetaDisplay *display,
|
|||||||
{
|
{
|
||||||
MetaWindow *window = tmp->data;
|
MetaWindow *window = tmp->data;
|
||||||
|
|
||||||
if (IN_TAB_CHAIN (window, type))
|
if (IN_TAB_CHAIN (window, device, type))
|
||||||
return window;
|
return window;
|
||||||
|
|
||||||
tmp = tmp->prev;
|
tmp = tmp->prev;
|
||||||
@ -4654,11 +4691,12 @@ find_tab_backward (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_display_get_tab_list:
|
* meta_display_get_device_tab_list:
|
||||||
* @display: a #MetaDisplay
|
* @display: a #MetaDisplay
|
||||||
* @type: type of tab list
|
* @type: type of tab list
|
||||||
* @screen: a #MetaScreen
|
* @screen: a #MetaScreen
|
||||||
* @workspace: origin workspace
|
* @workspace: origin workspace
|
||||||
|
* @device: keyboard triggering Alt-TAB
|
||||||
*
|
*
|
||||||
* Determine the list of windows that should be displayed for Alt-TAB
|
* Determine the list of windows that should be displayed for Alt-TAB
|
||||||
* functionality. The windows are returned in most recently used order.
|
* functionality. The windows are returned in most recently used order.
|
||||||
@ -4666,10 +4704,11 @@ find_tab_backward (MetaDisplay *display,
|
|||||||
* Returns: (transfer container) (element-type Meta.Window): List of windows
|
* Returns: (transfer container) (element-type Meta.Window): List of windows
|
||||||
*/
|
*/
|
||||||
GList*
|
GList*
|
||||||
meta_display_get_tab_list (MetaDisplay *display,
|
meta_display_get_device_tab_list (MetaDisplay *display,
|
||||||
MetaTabList type,
|
MetaTabList type,
|
||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
MetaWorkspace *workspace)
|
MetaWorkspace *workspace,
|
||||||
|
MetaDevice *device)
|
||||||
{
|
{
|
||||||
GList *tab_list;
|
GList *tab_list;
|
||||||
|
|
||||||
@ -4689,7 +4728,7 @@ meta_display_get_tab_list (MetaDisplay *display,
|
|||||||
|
|
||||||
if (!window->minimized &&
|
if (!window->minimized &&
|
||||||
window->screen == screen &&
|
window->screen == screen &&
|
||||||
IN_TAB_CHAIN (window, type))
|
IN_TAB_CHAIN (window, device, type))
|
||||||
tab_list = g_list_prepend (tab_list, window);
|
tab_list = g_list_prepend (tab_list, window);
|
||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
@ -4706,7 +4745,7 @@ meta_display_get_tab_list (MetaDisplay *display,
|
|||||||
|
|
||||||
if (window->minimized &&
|
if (window->minimized &&
|
||||||
window->screen == screen &&
|
window->screen == screen &&
|
||||||
IN_TAB_CHAIN (window, type))
|
IN_TAB_CHAIN (window, device, type))
|
||||||
tab_list = g_list_prepend (tab_list, window);
|
tab_list = g_list_prepend (tab_list, window);
|
||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
@ -4729,7 +4768,7 @@ meta_display_get_tab_list (MetaDisplay *display,
|
|||||||
/* Check to see if it demands attention */
|
/* Check to see if it demands attention */
|
||||||
if (l_window->wm_state_demands_attention &&
|
if (l_window->wm_state_demands_attention &&
|
||||||
l_window->workspace!=workspace &&
|
l_window->workspace!=workspace &&
|
||||||
IN_TAB_CHAIN (l_window, type))
|
IN_TAB_CHAIN (l_window, device, type))
|
||||||
{
|
{
|
||||||
/* if it does, add it to the popup */
|
/* if it does, add it to the popup */
|
||||||
tab_list = g_list_prepend (tab_list, l_window);
|
tab_list = g_list_prepend (tab_list, l_window);
|
||||||
@ -4742,6 +4781,107 @@ meta_display_get_tab_list (MetaDisplay *display,
|
|||||||
return tab_list;
|
return tab_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_display_get_tab_list:
|
||||||
|
* @display: a #MetaDisplay
|
||||||
|
* @type: type of tab list
|
||||||
|
* @screen: a #MetaScreen
|
||||||
|
* @workspace: origin workspace
|
||||||
|
*
|
||||||
|
* Determine the list of windows that should be displayed for Alt-TAB
|
||||||
|
* functionality. The windows are returned in most recently used order.
|
||||||
|
*
|
||||||
|
* Returns: (transfer container) (element-type Meta.Window): List of windows
|
||||||
|
*/
|
||||||
|
GList*
|
||||||
|
meta_display_get_tab_list (MetaDisplay *display,
|
||||||
|
MetaTabList type,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace)
|
||||||
|
{
|
||||||
|
MetaDevice *keyboard;
|
||||||
|
|
||||||
|
keyboard = meta_device_map_lookup (display->device_map,
|
||||||
|
META_CORE_KEYBOARD_ID);
|
||||||
|
|
||||||
|
return meta_display_get_device_tab_list (display, type,
|
||||||
|
screen, workspace,
|
||||||
|
keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_display_get_device_tab_next:
|
||||||
|
* @display: a #MetaDisplay
|
||||||
|
* @type: type of tab list
|
||||||
|
* @screen: a #MetaScreen
|
||||||
|
* @workspace: origin workspace
|
||||||
|
* @window: (allow-none): starting window
|
||||||
|
* @device: keyboard triggering Alt-TAB
|
||||||
|
* @backward: If %TRUE, look for the previous window.
|
||||||
|
*
|
||||||
|
* Determine the next window that should be displayed for Alt-TAB
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): Next window
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
MetaWindow*
|
||||||
|
meta_display_get_device_tab_next (MetaDisplay *display,
|
||||||
|
MetaTabList type,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace,
|
||||||
|
MetaWindow *window,
|
||||||
|
MetaDevice *device,
|
||||||
|
gboolean backward)
|
||||||
|
{
|
||||||
|
gboolean skip;
|
||||||
|
GList *tab_list;
|
||||||
|
MetaWindow *ret;
|
||||||
|
tab_list = meta_display_get_tab_list(display,
|
||||||
|
type,
|
||||||
|
screen,
|
||||||
|
workspace);
|
||||||
|
|
||||||
|
if (tab_list == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (window != NULL)
|
||||||
|
{
|
||||||
|
g_assert (window->display == display);
|
||||||
|
|
||||||
|
if (backward)
|
||||||
|
ret = find_tab_backward (display, type, screen, workspace,
|
||||||
|
device,
|
||||||
|
g_list_find (tab_list,
|
||||||
|
window),
|
||||||
|
TRUE);
|
||||||
|
else
|
||||||
|
ret = find_tab_forward (display, type, screen, workspace,
|
||||||
|
device,
|
||||||
|
g_list_find (tab_list,
|
||||||
|
window),
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
|
focus_info = meta_display_get_focus_info (display, device);
|
||||||
|
|
||||||
|
skip = focus_info->focus_window != NULL &&
|
||||||
|
tab_list->data == focus_info->focus_window;
|
||||||
|
if (backward)
|
||||||
|
ret = find_tab_backward (display, type, screen, workspace,
|
||||||
|
device, tab_list, skip);
|
||||||
|
else
|
||||||
|
ret = find_tab_forward (display, type, screen, workspace,
|
||||||
|
device, tab_list, skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (tab_list);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_display_get_tab_next:
|
* meta_display_get_tab_next:
|
||||||
* @display: a #MetaDisplay
|
* @display: a #MetaDisplay
|
||||||
@ -4765,46 +4905,51 @@ meta_display_get_tab_next (MetaDisplay *display,
|
|||||||
MetaWindow *window,
|
MetaWindow *window,
|
||||||
gboolean backward)
|
gboolean backward)
|
||||||
{
|
{
|
||||||
gboolean skip;
|
MetaDevice *keyboard;
|
||||||
GList *tab_list;
|
|
||||||
MetaWindow *ret;
|
|
||||||
tab_list = meta_display_get_tab_list(display,
|
|
||||||
type,
|
|
||||||
screen,
|
|
||||||
workspace);
|
|
||||||
|
|
||||||
if (tab_list == NULL)
|
keyboard = meta_device_map_lookup (display->device_map,
|
||||||
return NULL;
|
META_CORE_KEYBOARD_ID);
|
||||||
|
|
||||||
if (window != NULL)
|
return meta_display_get_device_tab_next (display, type,
|
||||||
{
|
screen, workspace,
|
||||||
g_assert (window->display == display);
|
window, keyboard,
|
||||||
|
backward);
|
||||||
if (backward)
|
}
|
||||||
ret = find_tab_backward (display, type, screen, workspace,
|
|
||||||
g_list_find (tab_list,
|
/**
|
||||||
window),
|
* meta_display_get_device_tab_current:
|
||||||
TRUE);
|
* @display: a #MetaDisplay
|
||||||
else
|
* @type: type of tab list
|
||||||
ret = find_tab_forward (display, type, screen, workspace,
|
* @screen: a #MetaScreen
|
||||||
g_list_find (tab_list,
|
* @workspace: origin workspace
|
||||||
window),
|
* @device: keyboard triggering alt-TAB
|
||||||
TRUE);
|
*
|
||||||
}
|
* Determine the active window that should be displayed for Alt-TAB.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): Current window
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
MetaWindow*
|
||||||
|
meta_display_get_device_tab_current (MetaDisplay *display,
|
||||||
|
MetaTabList type,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace,
|
||||||
|
MetaDevice *device)
|
||||||
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaWindow *window;
|
||||||
|
|
||||||
|
focus_info = meta_display_get_focus_info (display, device);
|
||||||
|
window = focus_info->focus_window;
|
||||||
|
|
||||||
|
if (window != NULL &&
|
||||||
|
window->screen == screen &&
|
||||||
|
IN_TAB_CHAIN (window, device, type) &&
|
||||||
|
(workspace == NULL ||
|
||||||
|
meta_window_located_on_workspace (window, workspace)))
|
||||||
|
return window;
|
||||||
else
|
else
|
||||||
{
|
return NULL;
|
||||||
skip = display->focus_window != NULL &&
|
|
||||||
tab_list->data == display->focus_window;
|
|
||||||
if (backward)
|
|
||||||
ret = find_tab_backward (display, type, screen, workspace,
|
|
||||||
tab_list, skip);
|
|
||||||
else
|
|
||||||
ret = find_tab_forward (display, type, screen, workspace,
|
|
||||||
tab_list, skip);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_list_free (tab_list);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4825,18 +4970,14 @@ meta_display_get_tab_current (MetaDisplay *display,
|
|||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
MetaWorkspace *workspace)
|
MetaWorkspace *workspace)
|
||||||
{
|
{
|
||||||
MetaWindow *window;
|
MetaDevice *keyboard;
|
||||||
|
|
||||||
window = display->focus_window;
|
keyboard = meta_device_map_lookup (display->device_map,
|
||||||
|
META_CORE_KEYBOARD_ID);
|
||||||
if (window != NULL &&
|
|
||||||
window->screen == screen &&
|
return meta_display_get_device_tab_current (display, type,
|
||||||
IN_TAB_CHAIN (window, type) &&
|
screen, workspace,
|
||||||
(workspace == NULL ||
|
keyboard);
|
||||||
meta_window_located_on_workspace (window, workspace)))
|
|
||||||
return window;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -5351,15 +5492,29 @@ static void
|
|||||||
sanity_check_timestamps (MetaDisplay *display,
|
sanity_check_timestamps (MetaDisplay *display,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time))
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *keyboard;
|
||||||
|
GHashTableIter iter;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, display->focus_info);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next (&iter,
|
||||||
|
(gpointer *) &keyboard,
|
||||||
|
(gpointer *) &focus_info))
|
||||||
{
|
{
|
||||||
meta_warning ("last_focus_time (%u) is greater than comparison "
|
if (XSERVER_TIME_IS_BEFORE (timestamp, focus_info->last_focus_time))
|
||||||
"timestamp (%u). This most likely represents a buggy "
|
{
|
||||||
"client sending inaccurate timestamps in messages such as "
|
meta_warning ("last_focus_time (%u) for device %d is greater than comparison "
|
||||||
"_NET_ACTIVE_WINDOW. Trying to work around...\n",
|
"timestamp (%u). This most likely represents a buggy "
|
||||||
display->last_focus_time, timestamp);
|
"client sending inaccurate timestamps in messages such as "
|
||||||
display->last_focus_time = timestamp;
|
"_NET_ACTIVE_WINDOW. Trying to work around...\n",
|
||||||
|
focus_info->last_focus_time,
|
||||||
|
meta_device_get_id (keyboard),
|
||||||
|
timestamp);
|
||||||
|
focus_info->last_focus_time = timestamp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time))
|
if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time))
|
||||||
{
|
{
|
||||||
GSList *windows;
|
GSList *windows;
|
||||||
@ -5396,14 +5551,19 @@ sanity_check_timestamps (MetaDisplay *display,
|
|||||||
static gboolean
|
static gboolean
|
||||||
timestamp_too_old (MetaDisplay *display,
|
timestamp_too_old (MetaDisplay *display,
|
||||||
MetaWindow *window,
|
MetaWindow *window,
|
||||||
|
MetaDevice *device,
|
||||||
guint32 *timestamp)
|
guint32 *timestamp)
|
||||||
{
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
|
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
|
||||||
* us to sanity check the timestamp here and ensure it doesn't correspond to
|
* us to sanity check the timestamp here and ensure it doesn't correspond to
|
||||||
* a future time (though we would want to rename to
|
* a future time (though we would want to rename to
|
||||||
* timestamp_too_old_or_in_future).
|
* timestamp_too_old_or_in_future).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
focus_info = meta_display_get_focus_info (display, device);
|
||||||
|
|
||||||
if (*timestamp == CurrentTime)
|
if (*timestamp == CurrentTime)
|
||||||
{
|
{
|
||||||
meta_warning ("Got a request to focus %s with a timestamp of 0. This "
|
meta_warning ("Got a request to focus %s with a timestamp of 0. This "
|
||||||
@ -5413,31 +5573,34 @@ timestamp_too_old (MetaDisplay *display,
|
|||||||
*timestamp = meta_display_get_current_time_roundtrip (display);
|
*timestamp = meta_display_get_current_time_roundtrip (display);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
|
else if (XSERVER_TIME_IS_BEFORE (*timestamp, focus_info->last_focus_time))
|
||||||
{
|
{
|
||||||
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
|
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Ignoring focus request for %s since %u "
|
"Ignoring focus request for device %d, %s since %u "
|
||||||
"is less than %u and %u.\n",
|
"is less than %u and %u.\n",
|
||||||
|
meta_device_get_id (device),
|
||||||
window ? window->desc : "the no_focus_window",
|
window ? window->desc : "the no_focus_window",
|
||||||
*timestamp,
|
*timestamp,
|
||||||
display->last_user_time,
|
display->last_user_time,
|
||||||
display->last_focus_time);
|
focus_info->last_focus_time);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Received focus request for %s which is newer than most "
|
"Received focus request for device %d, %s "
|
||||||
|
"which is newer than most "
|
||||||
"recent user_time, but less recent than "
|
"recent user_time, but less recent than "
|
||||||
"last_focus_time (%u < %u < %u); adjusting "
|
"last_focus_time (%u < %u < %u); adjusting "
|
||||||
"accordingly. (See bug 167358)\n",
|
"accordingly. (See bug 167358)\n",
|
||||||
|
meta_device_get_id (device),
|
||||||
window ? window->desc : "the no_focus_window",
|
window ? window->desc : "the no_focus_window",
|
||||||
display->last_user_time,
|
display->last_user_time,
|
||||||
*timestamp,
|
*timestamp,
|
||||||
display->last_focus_time);
|
focus_info->last_focus_time);
|
||||||
*timestamp = display->last_focus_time;
|
*timestamp = focus_info->last_focus_time;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5446,23 +5609,29 @@ timestamp_too_old (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_display_set_input_focus_window (MetaDisplay *display,
|
meta_display_set_keyboard_focus (MetaDisplay *display,
|
||||||
MetaWindow *window,
|
MetaWindow *window,
|
||||||
gboolean focus_frame,
|
MetaDevice *keyboard,
|
||||||
guint32 timestamp)
|
gboolean focus_frame,
|
||||||
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
if (timestamp_too_old (display, window, ×tamp))
|
MetaFocusInfo *focus_info;
|
||||||
|
Window xwindow;
|
||||||
|
|
||||||
|
if (timestamp_too_old (display, window, keyboard, ×tamp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
xwindow = focus_frame ? window->frame->xwindow : window->xwindow;
|
||||||
|
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push (display);
|
||||||
XSetInputFocus (display->xdisplay,
|
meta_device_keyboard_set_focus_window (META_DEVICE_KEYBOARD (keyboard),
|
||||||
focus_frame ? window->frame->xwindow : window->xwindow,
|
xwindow, timestamp);
|
||||||
RevertToPointerRoot,
|
|
||||||
timestamp);
|
|
||||||
meta_error_trap_pop (display);
|
meta_error_trap_pop (display);
|
||||||
|
|
||||||
display->expected_focus_window = window;
|
focus_info = meta_display_get_focus_info (display, keyboard);
|
||||||
display->last_focus_time = timestamp;
|
|
||||||
|
focus_info->expected_focus_window = window;
|
||||||
|
focus_info->last_focus_time = timestamp;
|
||||||
display->active_screen = window->screen;
|
display->active_screen = window->screen;
|
||||||
|
|
||||||
if (window != display->autoraise_window)
|
if (window != display->autoraise_window)
|
||||||
@ -5470,24 +5639,56 @@ meta_display_set_input_focus_window (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_display_focus_the_no_focus_window (MetaDisplay *display,
|
meta_display_unset_keyboard_focus (MetaDisplay *display,
|
||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
guint32 timestamp)
|
MetaDevice *keyboard,
|
||||||
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
if (timestamp_too_old (display, NULL, ×tamp))
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
|
if (timestamp_too_old (display, NULL, keyboard, ×tamp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
XSetInputFocus (display->xdisplay,
|
meta_device_keyboard_set_focus_window (META_DEVICE_KEYBOARD (keyboard),
|
||||||
screen->no_focus_window,
|
screen->no_focus_window,
|
||||||
RevertToPointerRoot,
|
timestamp);
|
||||||
timestamp);
|
|
||||||
display->expected_focus_window = NULL;
|
focus_info = meta_display_get_focus_info (display, keyboard);
|
||||||
display->last_focus_time = timestamp;
|
|
||||||
|
focus_info->expected_focus_window = NULL;
|
||||||
|
focus_info->last_focus_time = timestamp;
|
||||||
display->active_screen = screen;
|
display->active_screen = screen;
|
||||||
|
|
||||||
meta_display_remove_autoraise_callback (display);
|
meta_display_remove_autoraise_callback (display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_display_set_input_focus_window (MetaDisplay *display,
|
||||||
|
MetaWindow *window,
|
||||||
|
gboolean focus_frame,
|
||||||
|
guint32 timestamp)
|
||||||
|
{
|
||||||
|
MetaDevice *keyboard;
|
||||||
|
|
||||||
|
keyboard = meta_device_map_lookup (display->device_map,
|
||||||
|
META_CORE_KEYBOARD_ID);
|
||||||
|
meta_display_set_keyboard_focus (display, window, keyboard,
|
||||||
|
focus_frame, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_display_focus_the_no_focus_window (MetaDisplay *display,
|
||||||
|
MetaScreen *screen,
|
||||||
|
guint32 timestamp)
|
||||||
|
{
|
||||||
|
MetaDevice *keyboard;
|
||||||
|
|
||||||
|
keyboard = meta_device_map_lookup (display->device_map,
|
||||||
|
META_CORE_KEYBOARD_ID);
|
||||||
|
meta_display_unset_keyboard_focus (display, screen, keyboard,
|
||||||
|
timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_display_remove_autoraise_callback (MetaDisplay *display)
|
meta_display_remove_autoraise_callback (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
@ -5552,6 +5753,30 @@ meta_display_has_shape (MetaDisplay *display)
|
|||||||
return META_DISPLAY_HAS_SHAPE (display);
|
return META_DISPLAY_HAS_SHAPE (display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_display_get_keyboard_focus_window:
|
||||||
|
* @display: a #MetaDisplay
|
||||||
|
* @keyboard: keyboard to get current focus window for
|
||||||
|
*
|
||||||
|
* Returns the window that is currently receiving events for
|
||||||
|
* the keyboard @keyboard. We may have already sent a request
|
||||||
|
* to the X server to move the focus window elsewhere. (The
|
||||||
|
* expected_focus_window records where we've last set the input
|
||||||
|
* focus.)
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): window receiving @keyboard focus
|
||||||
|
**/
|
||||||
|
MetaWindow *
|
||||||
|
meta_display_get_keyboard_focus_window (MetaDisplay *display,
|
||||||
|
MetaDevice *keyboard)
|
||||||
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
|
focus_info = meta_display_get_focus_info (display, keyboard);
|
||||||
|
|
||||||
|
return focus_info->focus_window;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_display_get_focus_window:
|
* meta_display_get_focus_window:
|
||||||
* @display: a #MetaDisplay
|
* @display: a #MetaDisplay
|
||||||
@ -5567,7 +5792,12 @@ meta_display_has_shape (MetaDisplay *display)
|
|||||||
MetaWindow *
|
MetaWindow *
|
||||||
meta_display_get_focus_window (MetaDisplay *display)
|
meta_display_get_focus_window (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
return display->focus_window;
|
MetaDevice *keyboard;
|
||||||
|
|
||||||
|
keyboard = meta_device_map_lookup (display->device_map,
|
||||||
|
META_CORE_KEYBOARD_ID);
|
||||||
|
|
||||||
|
return meta_display_get_keyboard_focus_window (display, keyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -5689,3 +5919,28 @@ meta_display_get_grab_info (MetaDisplay *display,
|
|||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaFocusInfo *
|
||||||
|
meta_display_get_focus_info (MetaDisplay *display,
|
||||||
|
MetaDevice *device)
|
||||||
|
{
|
||||||
|
MetaFocusInfo *info;
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
info = g_hash_table_lookup (display->focus_info, device);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
{
|
||||||
|
if (!META_IS_DEVICE_KEYBOARD (device))
|
||||||
|
device = meta_device_get_paired_device (device);
|
||||||
|
|
||||||
|
info = g_slice_new0 (MetaFocusInfo);
|
||||||
|
info->last_focus_time = display->current_time;
|
||||||
|
|
||||||
|
g_hash_table_insert (display->focus_info, device, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
@ -3108,20 +3108,26 @@ handle_activate_window_menu (MetaDisplay *display,
|
|||||||
MetaKeyBinding *binding,
|
MetaKeyBinding *binding,
|
||||||
gpointer dummy)
|
gpointer dummy)
|
||||||
{
|
{
|
||||||
if (display->focus_window)
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *device;
|
||||||
|
|
||||||
|
device = meta_input_event_get_device (display, event);
|
||||||
|
focus_info = meta_display_get_focus_info (display, device);
|
||||||
|
|
||||||
|
if (focus_info->focus_window)
|
||||||
{
|
{
|
||||||
Time evtime;
|
Time evtime;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
meta_window_get_position (display->focus_window,
|
meta_window_get_position (focus_info->focus_window,
|
||||||
&x, &y);
|
&x, &y);
|
||||||
|
|
||||||
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
|
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
|
||||||
x += display->focus_window->rect.width;
|
x += focus_info->focus_window->rect.width;
|
||||||
|
|
||||||
evtime = meta_input_event_get_time (display, event);
|
evtime = meta_input_event_get_time (display, event);
|
||||||
|
|
||||||
meta_window_show_menu (display->focus_window,
|
meta_window_show_menu (focus_info->focus_window,
|
||||||
x, y,
|
x, y,
|
||||||
0,
|
0,
|
||||||
evtime);
|
evtime);
|
||||||
|
@ -354,10 +354,17 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
|||||||
* know about the modal-to-the-main-window part.
|
* know about the modal-to-the-main-window part.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MetaWindow *focus_window;
|
MetaWindow *focus_window = NULL;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
MetaRectangle overlap;
|
MetaRectangle overlap;
|
||||||
|
MetaDevice *pointer, *keyboard;
|
||||||
|
|
||||||
focus_window = window->display->focus_window;
|
pointer = meta_window_guess_grab_pointer (window);
|
||||||
|
keyboard = meta_device_get_paired_device (pointer);
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
|
||||||
|
if (focus_window)
|
||||||
|
focus_window = focus_info->focus_window;
|
||||||
|
|
||||||
if (window->denied_focus_and_not_transient &&
|
if (window->denied_focus_and_not_transient &&
|
||||||
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
|
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
|
||||||
@ -913,8 +920,16 @@ meta_window_place (MetaWindow *window,
|
|||||||
gboolean found_fit;
|
gboolean found_fit;
|
||||||
MetaWindow *focus_window;
|
MetaWindow *focus_window;
|
||||||
MetaRectangle overlap;
|
MetaRectangle overlap;
|
||||||
|
MetaDevice *pointer, *keyboard;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
focus_window = window->display->focus_window;
|
pointer = meta_window_guess_grab_pointer (window);
|
||||||
|
keyboard = meta_device_get_paired_device (pointer);
|
||||||
|
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
g_assert (focus_info != NULL);
|
||||||
|
|
||||||
|
focus_window = focus_info->focus_window;
|
||||||
g_assert (focus_window != NULL);
|
g_assert (focus_window != NULL);
|
||||||
|
|
||||||
/* No need to do anything if the window doesn't overlap at all */
|
/* No need to do anything if the window doesn't overlap at all */
|
||||||
|
@ -211,13 +211,23 @@ meta_stack_thaw (MetaStack *stack)
|
|||||||
stack_sync_to_server (stack);
|
stack_sync_to_server (stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _FocusedForeachData FocusedForeachData;
|
||||||
|
|
||||||
|
struct _FocusedForeachData
|
||||||
|
{
|
||||||
|
MetaWindow *window;
|
||||||
|
gboolean focused_transient;
|
||||||
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_focused_foreach (MetaWindow *window,
|
is_focused_foreach (MetaWindow *window,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
if (window == window->display->expected_focus_window)
|
FocusedForeachData *focused_data = data;
|
||||||
|
|
||||||
|
if (window == focused_data->window)
|
||||||
{
|
{
|
||||||
*((gboolean*) data) = TRUE;
|
focused_data->focused_transient = TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -240,6 +250,9 @@ get_standalone_layer (MetaWindow *window)
|
|||||||
{
|
{
|
||||||
MetaStackLayer layer;
|
MetaStackLayer layer;
|
||||||
gboolean focused_transient = FALSE;
|
gboolean focused_transient = FALSE;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *keyboard;
|
||||||
|
FocusedForeachData focused_data = { 0 };
|
||||||
|
|
||||||
switch (window->type)
|
switch (window->type)
|
||||||
{
|
{
|
||||||
@ -263,20 +276,30 @@ get_standalone_layer (MetaWindow *window)
|
|||||||
case META_WINDOW_OVERRIDE_OTHER:
|
case META_WINDOW_OVERRIDE_OTHER:
|
||||||
layer = META_LAYER_OVERRIDE_REDIRECT;
|
layer = META_LAYER_OVERRIDE_REDIRECT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
/* FIXME: How about other keyboards? should
|
||||||
|
* we allow fullscreen for non-VCP/K anyway?
|
||||||
|
*/
|
||||||
|
keyboard = meta_device_map_lookup (window->display->device_map,
|
||||||
|
META_CORE_KEYBOARD_ID);
|
||||||
|
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
focused_data.window = focus_info->expected_focus_window;
|
||||||
|
|
||||||
meta_window_foreach_transient (window,
|
meta_window_foreach_transient (window,
|
||||||
is_focused_foreach,
|
is_focused_foreach,
|
||||||
&focused_transient);
|
&focused_data);
|
||||||
|
|
||||||
if (window->wm_state_below)
|
if (window->wm_state_below)
|
||||||
layer = META_LAYER_BOTTOM;
|
layer = META_LAYER_BOTTOM;
|
||||||
else if (window->fullscreen &&
|
else if (window->fullscreen &&
|
||||||
(focused_transient ||
|
(focused_transient ||
|
||||||
window == window->display->expected_focus_window ||
|
!focus_info ||
|
||||||
window->display->expected_focus_window == NULL ||
|
window == focus_info->expected_focus_window ||
|
||||||
(window->display->expected_focus_window != NULL &&
|
focus_info->expected_focus_window == NULL ||
|
||||||
|
(focus_info->expected_focus_window != NULL &&
|
||||||
windows_on_different_monitor (window,
|
windows_on_different_monitor (window,
|
||||||
window->display->expected_focus_window))))
|
focus_info->expected_focus_window))))
|
||||||
layer = META_LAYER_FULLSCREEN;
|
layer = META_LAYER_FULLSCREEN;
|
||||||
else if (window->wm_state_above)
|
else if (window->wm_state_above)
|
||||||
layer = META_LAYER_TOP;
|
layer = META_LAYER_TOP;
|
||||||
|
@ -318,6 +318,12 @@ struct _MetaWindow
|
|||||||
/* if TRUE, application is buggy and SYNC resizing is turned off */
|
/* if TRUE, application is buggy and SYNC resizing is turned off */
|
||||||
guint disable_sync : 1;
|
guint disable_sync : 1;
|
||||||
|
|
||||||
|
/* if TRUE, window didn't yet get the FocusIn for window->focus_keyboard */
|
||||||
|
guint expecting_focus_in : 1;
|
||||||
|
|
||||||
|
/* Keyboard currently owning the window focus, or NULL */
|
||||||
|
MetaDevice *focus_keyboard;
|
||||||
|
|
||||||
/* if non-NULL, the bounds of the window frame */
|
/* if non-NULL, the bounds of the window frame */
|
||||||
cairo_region_t *frame_bounds;
|
cairo_region_t *frame_bounds;
|
||||||
|
|
||||||
@ -398,6 +404,9 @@ struct _MetaWindow
|
|||||||
|
|
||||||
/* Current grab op for this window, or NULL */
|
/* Current grab op for this window, or NULL */
|
||||||
MetaGrabInfo *cur_grab;
|
MetaGrabInfo *cur_grab;
|
||||||
|
|
||||||
|
/* Focus info if the window is focused, or NULL */
|
||||||
|
MetaFocusInfo *cur_focus;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaWindowClass
|
struct _MetaWindowClass
|
||||||
@ -647,6 +656,7 @@ void meta_window_update_monitor (MetaWindow *window);
|
|||||||
void meta_window_update_on_all_workspaces (MetaWindow *window);
|
void meta_window_update_on_all_workspaces (MetaWindow *window);
|
||||||
|
|
||||||
void meta_window_propagate_focus_appearance (MetaWindow *window,
|
void meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||||
|
MetaDevice *keyboard,
|
||||||
gboolean focused);
|
gboolean focused);
|
||||||
|
|
||||||
MetaDevice * meta_window_guess_grab_pointer (MetaWindow *window);
|
MetaDevice * meta_window_guess_grab_pointer (MetaWindow *window);
|
||||||
|
@ -1471,7 +1471,9 @@ reload_transient_for (MetaWindow *window,
|
|||||||
MetaWindow *parent = NULL;
|
MetaWindow *parent = NULL;
|
||||||
|
|
||||||
if (meta_window_appears_focused (window) && window->xtransient_for != None)
|
if (meta_window_appears_focused (window) && window->xtransient_for != None)
|
||||||
meta_window_propagate_focus_appearance (window, FALSE);
|
meta_window_propagate_focus_appearance (window,
|
||||||
|
window->focus_keyboard,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
window->xtransient_for = None;
|
window->xtransient_for = None;
|
||||||
|
|
||||||
@ -1537,7 +1539,9 @@ reload_transient_for (MetaWindow *window,
|
|||||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||||
|
|
||||||
if (meta_window_appears_focused (window) && window->xtransient_for != None)
|
if (meta_window_appears_focused (window) && window->xtransient_for != None)
|
||||||
meta_window_propagate_focus_appearance (window, TRUE);
|
meta_window_propagate_focus_appearance (window,
|
||||||
|
window->focus_keyboard,
|
||||||
|
TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1481,6 +1481,7 @@ void
|
|||||||
meta_window_unmanage (MetaWindow *window,
|
meta_window_unmanage (MetaWindow *window,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
|
MetaFocusInfo *focus_info = NULL;
|
||||||
GList *tmp;
|
GList *tmp;
|
||||||
|
|
||||||
meta_verbose ("Unmanaging 0x%lx\n", window->xwindow);
|
meta_verbose ("Unmanaging 0x%lx\n", window->xwindow);
|
||||||
@ -1527,6 +1528,10 @@ meta_window_unmanage (MetaWindow *window,
|
|||||||
* group if window->unmanaging
|
* group if window->unmanaging
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (window->focus_keyboard)
|
||||||
|
focus_info = meta_display_get_focus_info (window->display,
|
||||||
|
window->focus_keyboard);
|
||||||
|
|
||||||
/* If we have the focus, focus some other window.
|
/* If we have the focus, focus some other window.
|
||||||
* This is done first, so that if the unmap causes
|
* This is done first, so that if the unmap causes
|
||||||
* an EnterNotify the EnterNotify will have final say
|
* an EnterNotify the EnterNotify will have final say
|
||||||
@ -1534,22 +1539,24 @@ meta_window_unmanage (MetaWindow *window,
|
|||||||
* invariants.
|
* invariants.
|
||||||
*/
|
*/
|
||||||
if (meta_window_appears_focused (window))
|
if (meta_window_appears_focused (window))
|
||||||
meta_window_propagate_focus_appearance (window, FALSE);
|
meta_window_propagate_focus_appearance (window,
|
||||||
if (window->has_focus)
|
window->focus_keyboard,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
if (window->focus_keyboard)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
if (window->expecting_focus_in)
|
||||||
"Focusing default window since we're unmanaging %s\n",
|
{
|
||||||
window->desc);
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
"Focusing default window since expected focus window freed %s\n",
|
||||||
window,
|
window->desc);
|
||||||
timestamp);
|
focus_info->expected_focus_window = NULL;
|
||||||
}
|
}
|
||||||
else if (window->display->expected_focus_window == window)
|
else
|
||||||
{
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
"Focusing default window since we're unmanaging %s\n",
|
||||||
"Focusing default window since expected focus window freed %s\n",
|
window->desc);
|
||||||
window->desc);
|
|
||||||
window->display->expected_focus_window = NULL;
|
|
||||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||||
window,
|
window,
|
||||||
timestamp);
|
timestamp);
|
||||||
@ -1579,10 +1586,14 @@ meta_window_unmanage (MetaWindow *window,
|
|||||||
|
|
||||||
g_assert (window->cur_grab == NULL);
|
g_assert (window->cur_grab == NULL);
|
||||||
|
|
||||||
if (window->display->focus_window == window)
|
if (focus_info &&
|
||||||
|
focus_info->focus_window == window)
|
||||||
{
|
{
|
||||||
window->display->focus_window = NULL;
|
focus_info->focus_window = NULL;
|
||||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
|
||||||
|
if (window->focus_keyboard &&
|
||||||
|
meta_device_get_id (window->focus_keyboard) == META_CORE_KEYBOARD_ID)
|
||||||
|
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->maximized_horizontally || window->maximized_vertically)
|
if (window->maximized_horizontally || window->maximized_vertically)
|
||||||
@ -2349,12 +2360,17 @@ meta_window_queue (MetaWindow *window, guint queuebits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
intervening_user_event_occurred (MetaWindow *window)
|
intervening_user_event_occurred (MetaWindow *window,
|
||||||
|
MetaDevice *keyboard)
|
||||||
{
|
{
|
||||||
guint32 compare;
|
guint32 compare;
|
||||||
MetaWindow *focus_window;
|
MetaWindow *focus_window = NULL;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
focus_window = window->display->focus_window;
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
|
||||||
|
if (focus_info)
|
||||||
|
focus_window = focus_info->focus_window;
|
||||||
|
|
||||||
meta_topic (META_DEBUG_STARTUP,
|
meta_topic (META_DEBUG_STARTUP,
|
||||||
"COMPARISON:\n"
|
"COMPARISON:\n"
|
||||||
@ -2503,12 +2519,15 @@ __window_is_terminal (MetaWindow *window)
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
window_state_on_map (MetaWindow *window,
|
window_state_on_map (MetaWindow *window,
|
||||||
gboolean *takes_focus,
|
MetaDevice *keyboard,
|
||||||
gboolean *places_on_top)
|
gboolean *takes_focus,
|
||||||
|
gboolean *places_on_top)
|
||||||
{
|
{
|
||||||
gboolean intervening_events;
|
gboolean intervening_events;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
intervening_events = intervening_user_event_occurred (window);
|
intervening_events = intervening_user_event_occurred (window, keyboard);
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
|
||||||
*takes_focus = !intervening_events;
|
*takes_focus = !intervening_events;
|
||||||
*places_on_top = *takes_focus;
|
*places_on_top = *takes_focus;
|
||||||
@ -2530,11 +2549,11 @@ window_state_on_map (MetaWindow *window,
|
|||||||
* terminals due to new window map, but the latter is a much easier
|
* terminals due to new window map, but the latter is a much easier
|
||||||
* approximation to enforce so we do that.
|
* approximation to enforce so we do that.
|
||||||
*/
|
*/
|
||||||
if (*takes_focus &&
|
if (*takes_focus && focus_info &&
|
||||||
meta_prefs_get_focus_new_windows () == META_FOCUS_NEW_WINDOWS_STRICT &&
|
meta_prefs_get_focus_new_windows () == META_FOCUS_NEW_WINDOWS_STRICT &&
|
||||||
!window->display->allow_terminal_deactivation &&
|
!window->display->allow_terminal_deactivation &&
|
||||||
__window_is_terminal (window->display->focus_window) &&
|
__window_is_terminal (focus_info->focus_window) &&
|
||||||
!meta_window_is_ancestor_of_transient (window->display->focus_window,
|
!meta_window_is_ancestor_of_transient (focus_info->focus_window,
|
||||||
window))
|
window))
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
@ -2765,20 +2784,30 @@ meta_window_show (MetaWindow *window)
|
|||||||
gboolean takes_focus_on_map;
|
gboolean takes_focus_on_map;
|
||||||
gboolean place_on_top_on_map;
|
gboolean place_on_top_on_map;
|
||||||
gboolean needs_stacking_adjustment;
|
gboolean needs_stacking_adjustment;
|
||||||
MetaWindow *focus_window;
|
MetaWindow *focus_window = NULL;
|
||||||
gboolean toplevel_was_mapped;
|
gboolean toplevel_was_mapped;
|
||||||
gboolean toplevel_now_mapped;
|
gboolean toplevel_now_mapped;
|
||||||
gboolean notify_demands_attention = FALSE;
|
gboolean notify_demands_attention = FALSE;
|
||||||
|
MetaDevice *pointer, *keyboard;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
meta_topic (META_DEBUG_WINDOW_STATE,
|
meta_topic (META_DEBUG_WINDOW_STATE,
|
||||||
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
|
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
|
||||||
window->desc, window->shaded, window->iconic, window->placed);
|
window->desc, window->shaded, window->iconic, window->placed);
|
||||||
|
|
||||||
|
pointer = meta_window_guess_grab_pointer (window);
|
||||||
|
keyboard = meta_device_get_paired_device (pointer);
|
||||||
|
|
||||||
toplevel_was_mapped = meta_window_toplevel_is_mapped (window);
|
toplevel_was_mapped = meta_window_toplevel_is_mapped (window);
|
||||||
|
|
||||||
focus_window = window->display->focus_window; /* May be NULL! */
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
|
||||||
|
if (focus_info)
|
||||||
|
focus_window = focus_info->focus_window;
|
||||||
|
|
||||||
did_show = FALSE;
|
did_show = FALSE;
|
||||||
window_state_on_map (window, &takes_focus_on_map, &place_on_top_on_map);
|
window_state_on_map (window, keyboard,
|
||||||
|
&takes_focus_on_map, &place_on_top_on_map);
|
||||||
needs_stacking_adjustment = FALSE;
|
needs_stacking_adjustment = FALSE;
|
||||||
|
|
||||||
meta_topic (META_DEBUG_WINDOW_STATE,
|
meta_topic (META_DEBUG_WINDOW_STATE,
|
||||||
@ -3109,14 +3138,13 @@ meta_window_hide (MetaWindow *window)
|
|||||||
invalidate_work_areas (window);
|
invalidate_work_areas (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The check on expected_focus_window is a temporary workaround for
|
/* The check on expected_focus_in is a temporary workaround for
|
||||||
* https://bugzilla.gnome.org/show_bug.cgi?id=597352
|
* https://bugzilla.gnome.org/show_bug.cgi?id=597352
|
||||||
* We may have already switched away from this window but not yet
|
* We may have already switched away from this window but not yet
|
||||||
* gotten FocusIn/FocusOut events. A more complete comprehensive
|
* gotten FocusIn/FocusOut events. A more complete comprehensive
|
||||||
* fix for these type of issues is described in the bug.
|
* fix for these type of issues is described in the bug.
|
||||||
*/
|
*/
|
||||||
if (window->has_focus &&
|
if (window->has_focus && window->expecting_focus_in)
|
||||||
window == window->display->expected_focus_window)
|
|
||||||
{
|
{
|
||||||
MetaWindow *not_this_one = NULL;
|
MetaWindow *not_this_one = NULL;
|
||||||
MetaWorkspace *my_workspace = meta_window_get_workspace (window);
|
MetaWorkspace *my_workspace = meta_window_get_workspace (window);
|
||||||
@ -5312,13 +5340,22 @@ meta_window_focus (MetaWindow *window,
|
|||||||
|
|
||||||
if (window->take_focus)
|
if (window->take_focus)
|
||||||
{
|
{
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
MetaDevice *keyboard;
|
||||||
|
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Sending WM_TAKE_FOCUS to %s since take_focus = true\n",
|
"Sending WM_TAKE_FOCUS to %s since take_focus = true\n",
|
||||||
window->desc);
|
window->desc);
|
||||||
meta_window_send_icccm_message (window,
|
meta_window_send_icccm_message (window,
|
||||||
window->display->atom_WM_TAKE_FOCUS,
|
window->display->atom_WM_TAKE_FOCUS,
|
||||||
timestamp);
|
timestamp);
|
||||||
window->display->expected_focus_window = window;
|
|
||||||
|
keyboard = meta_device_get_paired_device (device);
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
|
||||||
|
focus_info->expected_focus_window = window;
|
||||||
|
window->focus_keyboard = keyboard;
|
||||||
|
window->expecting_focus_in = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5858,7 +5895,16 @@ meta_window_configure_request (MetaWindow *window,
|
|||||||
if (event->xconfigurerequest.value_mask & CWStackMode)
|
if (event->xconfigurerequest.value_mask & CWStackMode)
|
||||||
{
|
{
|
||||||
MetaWindow *active_window;
|
MetaWindow *active_window;
|
||||||
active_window = window->display->expected_focus_window;
|
MetaDevice *pointer, *keyboard;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
|
pointer = meta_window_guess_grab_pointer (window);
|
||||||
|
keyboard = meta_device_get_paired_device (pointer);
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
|
||||||
|
if (focus_info)
|
||||||
|
active_window = focus_info->expected_focus_window;
|
||||||
|
|
||||||
if (meta_prefs_get_disable_workarounds ())
|
if (meta_prefs_get_disable_workarounds ())
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_STACK,
|
meta_topic (META_DEBUG_STACK,
|
||||||
@ -6477,17 +6523,26 @@ meta_window_client_message (MetaWindow *window,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
meta_window_propagate_focus_appearance (MetaWindow *window,
|
meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||||
|
MetaDevice *keyboard,
|
||||||
gboolean focused)
|
gboolean focused)
|
||||||
{
|
{
|
||||||
MetaWindow *child, *parent, *focus_window;
|
MetaWindow *child, *parent, *focus_window;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
|
||||||
if (!meta_prefs_get_attach_modal_dialogs ())
|
if (!meta_prefs_get_attach_modal_dialogs ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
focus_window = window->display->focus_window;
|
|
||||||
|
|
||||||
child = window;
|
child = window;
|
||||||
parent = meta_window_get_transient_for (child);
|
parent = meta_window_get_transient_for (child);
|
||||||
|
|
||||||
|
if (keyboard)
|
||||||
|
{
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
focus_window = focus_info->focus_window;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
focus_window = NULL;
|
||||||
|
|
||||||
while (parent && (!focused || child->type == META_WINDOW_MODAL_DIALOG))
|
while (parent && (!focused || child->type == META_WINDOW_MODAL_DIALOG))
|
||||||
{
|
{
|
||||||
gboolean child_focus_state_changed;
|
gboolean child_focus_state_changed;
|
||||||
@ -6508,7 +6563,7 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (child_focus_state_changed && !parent->has_focus &&
|
if (child_focus_state_changed && !parent->has_focus &&
|
||||||
parent != window->display->expected_focus_window)
|
(!focus_info || parent != focus_info->expected_focus_window))
|
||||||
{
|
{
|
||||||
g_object_notify (G_OBJECT (parent), "appears-focused");
|
g_object_notify (G_OBJECT (parent), "appears-focused");
|
||||||
if (parent->frame)
|
if (parent->frame)
|
||||||
@ -6525,6 +6580,8 @@ meta_window_notify_focus (MetaWindow *window,
|
|||||||
XEvent *event)
|
XEvent *event)
|
||||||
{
|
{
|
||||||
guint evtype, mode, detail;
|
guint evtype, mode, detail;
|
||||||
|
MetaFocusInfo *focus_info = NULL;
|
||||||
|
MetaDevice *keyboard;
|
||||||
Window xwindow;
|
Window xwindow;
|
||||||
|
|
||||||
/* note the event can be on either the window or the frame,
|
/* note the event can be on either the window or the frame,
|
||||||
@ -6550,14 +6607,19 @@ meta_window_notify_focus (MetaWindow *window,
|
|||||||
meta_input_event_get_crossing_details (window->display, event,
|
meta_input_event_get_crossing_details (window->display, event,
|
||||||
&mode, &detail);
|
&mode, &detail);
|
||||||
xwindow = meta_input_event_get_window (window->display, event);
|
xwindow = meta_input_event_get_window (window->display, event);
|
||||||
|
keyboard = meta_input_event_get_device (window->display, event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xwindow = event->xany.window;
|
xwindow = event->xany.window;
|
||||||
evtype = event->type;
|
evtype = event->type;
|
||||||
mode = detail = 0;
|
mode = detail = 0;
|
||||||
|
keyboard = window->focus_keyboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keyboard)
|
||||||
|
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||||
|
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Focus %s event received on %s 0x%lx (%s) "
|
"Focus %s event received on %s 0x%lx (%s) "
|
||||||
"mode %s detail %s\n",
|
"mode %s detail %s\n",
|
||||||
@ -6611,17 +6673,22 @@ meta_window_notify_focus (MetaWindow *window,
|
|||||||
{
|
{
|
||||||
if (window->override_redirect)
|
if (window->override_redirect)
|
||||||
{
|
{
|
||||||
window->display->focus_window = NULL;
|
focus_info->focus_window = NULL;
|
||||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
|
||||||
|
if (meta_device_get_id (keyboard) == META_CORE_KEYBOARD_ID)
|
||||||
|
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window != window->display->focus_window)
|
if (window != focus_info->focus_window)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"* Focus --> %s\n", window->desc);
|
"* Focus --> %s\n", window->desc);
|
||||||
window->display->focus_window = window;
|
focus_info->focus_window = window;
|
||||||
window->has_focus = TRUE;
|
window->has_focus = TRUE;
|
||||||
|
window->focus_keyboard = keyboard;
|
||||||
|
window->expecting_focus_in = FALSE;
|
||||||
|
|
||||||
/* Move to the front of the focusing workspace's MRU list.
|
/* Move to the front of the focusing workspace's MRU list.
|
||||||
* We should only be "removing" it from the MRU list if it's
|
* We should only be "removing" it from the MRU list if it's
|
||||||
@ -6679,7 +6746,9 @@ meta_window_notify_focus (MetaWindow *window,
|
|||||||
meta_display_ungrab_focus_window_button (window->display, window);
|
meta_display_ungrab_focus_window_button (window->display, window);
|
||||||
|
|
||||||
g_signal_emit (window, window_signals[FOCUS], 0);
|
g_signal_emit (window, window_signals[FOCUS], 0);
|
||||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
|
||||||
|
if (meta_device_get_id (keyboard) == META_CORE_KEYBOARD_ID)
|
||||||
|
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||||
|
|
||||||
if (!window->attached_focus_window)
|
if (!window->attached_focus_window)
|
||||||
{
|
{
|
||||||
@ -6687,7 +6756,7 @@ meta_window_notify_focus (MetaWindow *window,
|
|||||||
if (window->frame)
|
if (window->frame)
|
||||||
meta_frame_queue_draw (window->frame);
|
meta_frame_queue_draw (window->frame);
|
||||||
}
|
}
|
||||||
meta_window_propagate_focus_appearance (window, TRUE);
|
meta_window_propagate_focus_appearance (window, keyboard, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (evtype == FocusOut ||
|
else if (evtype == FocusOut ||
|
||||||
@ -6703,7 +6772,8 @@ meta_window_notify_focus (MetaWindow *window,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window == window->display->focus_window)
|
if (focus_info &&
|
||||||
|
window == focus_info->focus_window)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"%s is now the previous focus window due to being focused out or unmapped\n",
|
"%s is now the previous focus window due to being focused out or unmapped\n",
|
||||||
@ -6712,11 +6782,18 @@ meta_window_notify_focus (MetaWindow *window,
|
|||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"* Focus --> NULL (was %s)\n", window->desc);
|
"* Focus --> NULL (was %s)\n", window->desc);
|
||||||
|
|
||||||
meta_window_propagate_focus_appearance (window, FALSE);
|
meta_window_propagate_focus_appearance (window, keyboard, FALSE);
|
||||||
|
focus_info->focus_window = NULL;
|
||||||
|
|
||||||
|
if (meta_device_get_id (keyboard) == META_CORE_KEYBOARD_ID)
|
||||||
|
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||||
|
|
||||||
window->display->focus_window = NULL;
|
|
||||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
|
||||||
window->has_focus = FALSE;
|
window->has_focus = FALSE;
|
||||||
|
window->focus_keyboard = NULL;
|
||||||
|
window->expecting_focus_in = FALSE;
|
||||||
|
|
||||||
|
if (meta_device_get_id (keyboard) == META_CORE_KEYBOARD_ID)
|
||||||
|
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||||
|
|
||||||
if (!window->attached_focus_window)
|
if (!window->attached_focus_window)
|
||||||
{
|
{
|
||||||
|
@ -75,6 +75,9 @@ gboolean meta_display_has_shape (MetaDisplay *display);
|
|||||||
|
|
||||||
MetaScreen *meta_display_screen_for_root (MetaDisplay *display,
|
MetaScreen *meta_display_screen_for_root (MetaDisplay *display,
|
||||||
Window xroot);
|
Window xroot);
|
||||||
|
|
||||||
|
MetaWindow *meta_display_get_keyboard_focus_window (MetaDisplay *display,
|
||||||
|
MetaDevice *keyboard);
|
||||||
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
|
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
|
||||||
|
|
||||||
gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
|
gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
|
||||||
@ -109,6 +112,26 @@ MetaWindow* meta_display_get_tab_current (MetaDisplay *display,
|
|||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
MetaWorkspace *workspace);
|
MetaWorkspace *workspace);
|
||||||
|
|
||||||
|
GList* meta_display_get_device_tab_list (MetaDisplay *display,
|
||||||
|
MetaTabList type,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace,
|
||||||
|
MetaDevice *device);
|
||||||
|
|
||||||
|
MetaWindow* meta_display_get_device_tab_next (MetaDisplay *display,
|
||||||
|
MetaTabList type,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace,
|
||||||
|
MetaWindow *window,
|
||||||
|
MetaDevice *device,
|
||||||
|
gboolean backward);
|
||||||
|
|
||||||
|
MetaWindow* meta_display_get_device_tab_current (MetaDisplay *display,
|
||||||
|
MetaTabList type,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace,
|
||||||
|
MetaDevice *device);
|
||||||
|
|
||||||
gboolean meta_display_begin_grab_op (MetaDisplay *display,
|
gboolean meta_display_begin_grab_op (MetaDisplay *display,
|
||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
MetaWindow *window,
|
MetaWindow *window,
|
||||||
@ -134,6 +157,16 @@ MetaKeyBindingAction meta_display_get_keybinding_action (MetaDisplay *display,
|
|||||||
unsigned int keycode,
|
unsigned int keycode,
|
||||||
unsigned long mask);
|
unsigned long mask);
|
||||||
|
|
||||||
|
void meta_display_set_keyboard_focus (MetaDisplay *display,
|
||||||
|
MetaWindow *window,
|
||||||
|
MetaDevice *keyboard,
|
||||||
|
gboolean focus_frame,
|
||||||
|
guint32 timestamp);
|
||||||
|
void meta_display_unset_keyboard_focus (MetaDisplay *display,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaDevice *keyboard,
|
||||||
|
guint32 timestamp);
|
||||||
|
|
||||||
/* meta_display_set_input_focus_window is like XSetInputFocus, except
|
/* meta_display_set_input_focus_window is like XSetInputFocus, except
|
||||||
* that (a) it can't detect timestamps later than the current time,
|
* that (a) it can't detect timestamps later than the current time,
|
||||||
* since Mutter isn't part of the XServer, and thus gives erroneous
|
* since Mutter isn't part of the XServer, and thus gives erroneous
|
||||||
|
@ -858,12 +858,21 @@ static WnckWindowDisplayInfo
|
|||||||
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
|
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
|
||||||
{
|
{
|
||||||
WnckWindowDisplayInfo wnck_window;
|
WnckWindowDisplayInfo wnck_window;
|
||||||
|
MetaFocusInfo *focus_info;
|
||||||
|
GHashTableIter iter;
|
||||||
|
|
||||||
wnck_window.icon = window->icon;
|
wnck_window.icon = window->icon;
|
||||||
wnck_window.mini_icon = window->mini_icon;
|
wnck_window.mini_icon = window->mini_icon;
|
||||||
|
|
||||||
wnck_window.is_active = FALSE;
|
wnck_window.is_active = FALSE;
|
||||||
if (window == window->display->expected_focus_window)
|
|
||||||
wnck_window.is_active = TRUE;
|
g_hash_table_iter_init (&iter, window->display->focus_info);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &focus_info))
|
||||||
|
{
|
||||||
|
if (window == focus_info->expected_focus_window)
|
||||||
|
wnck_window.is_active = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (window->frame)
|
if (window->frame)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user