window: Move icon management to X11 implementation

It's still used by e.g. GNOME Shell to produce fallback icons for X11
applications that doesn't come with a .desktop file. Geometry stays in
the generic class because it's used for minimize animations and is
configured by the panel (e.g. the one in gnome-shell-extensions).

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2264>
This commit is contained in:
Jonas Ådahl
2022-01-29 00:02:24 +01:00
committed by Marge Bot
parent 35ac3a096d
commit aeae90d5d9
6 changed files with 155 additions and 138 deletions

View File

@ -60,10 +60,9 @@ typedef enum
{
META_QUEUE_CALC_SHOWING = 1 << 0,
META_QUEUE_MOVE_RESIZE = 1 << 1,
META_QUEUE_UPDATE_ICON = 1 << 2,
} MetaQueueType;
#define NUMBER_OF_QUEUES 3
#define NUMBER_OF_QUEUES 2
typedef enum
{
@ -185,9 +184,6 @@ struct _MetaWindow
char *desc; /* used in debug spew */
char *title;
cairo_surface_t *icon;
cairo_surface_t *mini_icon;
MetaWindowType type;
/* NOTE these five are not in UTF-8, we just treat them as random
@ -608,9 +604,10 @@ struct _MetaWindowClass
void (*get_default_skip_hints) (MetaWindow *window,
gboolean *skip_taskbar_out,
gboolean *skip_pager_out);
gboolean (*update_icon) (MetaWindow *window,
cairo_surface_t **icon,
cairo_surface_t **mini_icon);
cairo_surface_t * (*get_icon) (MetaWindow *window);
cairo_surface_t * (*get_mini_icon) (MetaWindow *window);
pid_t (*get_client_pid) (MetaWindow *window);
void (*update_main_monitor) (MetaWindow *window,
MetaWindowUpdateMonitorFlags flags);
@ -867,6 +864,10 @@ MetaLogicalMonitor * meta_window_get_main_logical_monitor (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window,
MetaWindowUpdateMonitorFlags flags);
cairo_surface_t * meta_window_get_icon (MetaWindow *window);
cairo_surface_t * meta_window_get_mini_icon (MetaWindow *window);
void meta_window_set_urgent (MetaWindow *window,
gboolean urgent);

View File

@ -26,7 +26,7 @@
* @short_description: A display-agnostic abstraction for a window.
*
* #MetaWindow is the core abstraction in Mutter of a window. It has the
* properties you'd expect, such as a title, an icon, whether it's fullscreen,
* properties you'd expect, such as a title, whether it's fullscreen,
* has decorations, etc.
*
* Since a lot of different kinds of windows exist, each window also a
@ -161,9 +161,6 @@ static void unminimize_window_and_all_transient_parents (MetaWindow *window);
static void meta_window_propagate_focus_appearance (MetaWindow *window,
gboolean focused);
static void meta_window_update_icon_now (MetaWindow *window,
gboolean force);
static void set_workspace_state (MetaWindow *window,
gboolean on_all_workspaces,
MetaWorkspace *workspace);
@ -181,7 +178,6 @@ static void update_edge_constraints (MetaWindow *window);
*/
static gboolean idle_calc_showing (gpointer data);
static gboolean idle_move_resize (gpointer data);
static gboolean idle_update_icon (gpointer data);
G_DEFINE_ABSTRACT_TYPE (MetaWindow, meta_window, G_TYPE_OBJECT);
@ -293,16 +289,6 @@ meta_window_real_get_default_skip_hints (MetaWindow *window,
*skip_pager_out = FALSE;
}
static gboolean
meta_window_real_update_icon (MetaWindow *window,
cairo_surface_t **icon,
cairo_surface_t **mini_icon)
{
*icon = NULL;
*mini_icon = NULL;
return FALSE;
}
static pid_t
meta_window_real_get_client_pid (MetaWindow *window)
{
@ -314,12 +300,6 @@ meta_window_finalize (GObject *object)
{
MetaWindow *window = META_WINDOW (object);
if (window->icon)
cairo_surface_destroy (window->icon);
if (window->mini_icon)
cairo_surface_destroy (window->mini_icon);
if (window->frame_bounds)
cairo_region_destroy (window->frame_bounds);
@ -373,10 +353,10 @@ meta_window_get_property(GObject *object,
g_value_set_string (value, win->title);
break;
case PROP_ICON:
g_value_set_pointer (value, win->icon);
g_value_set_pointer (value, meta_window_get_icon (win));
break;
case PROP_MINI_ICON:
g_value_set_pointer (value, win->mini_icon);
g_value_set_pointer (value, meta_window_get_mini_icon (win));
break;
case PROP_DECORATED:
g_value_set_boolean (value, win->decorated);
@ -479,7 +459,6 @@ meta_window_class_init (MetaWindowClass *klass)
klass->current_workspace_changed = meta_window_real_current_workspace_changed;
klass->update_struts = meta_window_real_update_struts;
klass->get_default_skip_hints = meta_window_real_get_default_skip_hints;
klass->update_icon = meta_window_real_update_icon;
klass->get_client_pid = meta_window_real_get_client_pid;
obj_props[PROP_TITLE] =
@ -1068,8 +1047,6 @@ _meta_window_shared_new (MetaDisplay *display,
window->xvisual = attrs->visual;
window->title = NULL;
window->icon = NULL;
window->mini_icon = NULL;
window->frame = NULL;
window->has_focus = FALSE;
@ -1218,9 +1195,6 @@ _meta_window_shared_new (MetaDisplay *display,
meta_window_manage (window);
if (!window->override_redirect)
meta_window_update_icon_now (window, TRUE);
if (window->initially_iconic)
{
/* WM_HINTS said minimized */
@ -1578,9 +1552,9 @@ meta_window_unmanage (MetaWindow *window,
if (window->maximized_horizontally || window->maximized_vertically)
unmaximize_window_before_freeing (window);
meta_window_unqueue (window, META_QUEUE_CALC_SHOWING |
META_QUEUE_MOVE_RESIZE |
META_QUEUE_UPDATE_ICON);
meta_window_unqueue (window,
(META_QUEUE_CALC_SHOWING |
META_QUEUE_MOVE_RESIZE));
set_workspace_state (window, FALSE, NULL);
@ -1805,8 +1779,8 @@ meta_window_calc_showing (MetaWindow *window)
implement_showing (window, meta_window_should_be_showing (window));
}
static guint queue_later[NUMBER_OF_QUEUES] = {0, 0, 0};
static GSList *queue_pending[NUMBER_OF_QUEUES] = {NULL, NULL, NULL};
static guint queue_later[NUMBER_OF_QUEUES] = {};
static GSList *queue_pending[NUMBER_OF_QUEUES] = {};
static int
stackcmp (gconstpointer a, gconstpointer b)
@ -1989,7 +1963,7 @@ idle_calc_showing (gpointer data)
#ifdef WITH_VERBOSE_MODE
static const gchar* meta_window_queue_names[NUMBER_OF_QUEUES] =
{"calc_showing", "move_resize", "update_icon"};
{"calc_showing", "move_resize", };
#endif
static void
@ -2053,16 +2027,14 @@ meta_window_queue (MetaWindow *window,
{
const MetaLaterType window_queue_later_when[NUMBER_OF_QUEUES] =
{
META_LATER_CALC_SHOWING, /* CALC_SHOWING */
META_LATER_RESIZE, /* MOVE_RESIZE */
META_LATER_BEFORE_REDRAW /* UPDATE_ICON */
META_LATER_CALC_SHOWING,
META_LATER_RESIZE,
};
const GSourceFunc window_queue_later_handler[NUMBER_OF_QUEUES] =
{
idle_calc_showing,
idle_move_resize,
idle_update_icon,
};
if (window->unmanaging)
@ -5533,85 +5505,26 @@ meta_window_set_icon_geometry (MetaWindow *window,
}
}
static void
redraw_icon (MetaWindow *window)
cairo_surface_t *
meta_window_get_icon (MetaWindow *window)
{
/* We could probably be smart and just redraw the icon here,
* instead of the whole frame.
*/
if (window->frame)
meta_frame_queue_draw (window->frame);
MetaWindowClass *klass = META_WINDOW_GET_CLASS (window);
if (klass->get_icon)
return klass->get_icon (window);
else
return NULL;
}
static void
meta_window_update_icon_now (MetaWindow *window,
gboolean force)
cairo_surface_t *
meta_window_get_mini_icon (MetaWindow *window)
{
gboolean changed;
cairo_surface_t *icon = NULL;
cairo_surface_t *mini_icon;
MetaWindowClass *klass = META_WINDOW_GET_CLASS (window);
g_return_if_fail (!window->override_redirect);
changed = META_WINDOW_GET_CLASS (window)->update_icon (window, &icon, &mini_icon);
if (changed || force)
{
if (window->icon)
cairo_surface_destroy (window->icon);
window->icon = icon;
if (window->mini_icon)
cairo_surface_destroy (window->mini_icon);
window->mini_icon = mini_icon;
g_object_freeze_notify (G_OBJECT (window));
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ICON]);
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MINI_ICON]);
g_object_thaw_notify (G_OBJECT (window));
redraw_icon (window);
}
}
static gboolean
idle_update_icon (gpointer data)
{
GSList *tmp;
GSList *copy;
guint queue_index = GPOINTER_TO_INT (data);
meta_topic (META_DEBUG_GEOMETRY, "Clearing the update_icon queue");
/* Work with a copy, for reentrancy. The allowed reentrancy isn't
* complete; destroying a window while we're in here would result in
* badness. But it's OK to queue/unqueue update_icons.
*/
copy = g_slist_copy (queue_pending[queue_index]);
g_slist_free (queue_pending[queue_index]);
queue_pending[queue_index] = NULL;
queue_later[queue_index] = 0;
destroying_windows_disallowed += 1;
tmp = copy;
while (tmp != NULL)
{
MetaWindow *window;
window = tmp->data;
meta_window_update_icon_now (window, FALSE);
window->is_in_queues &= ~META_QUEUE_UPDATE_ICON;
tmp = tmp->next;
}
g_slist_free (copy);
destroying_windows_disallowed -= 1;
return FALSE;
if (klass->get_mini_icon)
return klass->get_mini_icon (window);
else
return NULL;
}
GList*