forked from AuroraMiddleware/gtk
Merge branch 'wip/widget-position-changed-callbacks' into 'master'
widget: Add surface relative position changed callback See merge request GNOME/gtk!760
This commit is contained in:
commit
2516f1142d
256
gtk/gtkwidget.c
256
gtk/gtkwidget.c
@ -713,6 +713,9 @@ static void gtk_widget_update_input_shape (GtkWidget *widget);
|
||||
|
||||
static gboolean gtk_widget_class_get_visible_by_default (GtkWidgetClass *widget_class);
|
||||
|
||||
static void remove_parent_surface_transform_changed_listener (GtkWidget *widget);
|
||||
static void add_parent_surface_transform_changed_listener (GtkWidget *widget);
|
||||
|
||||
|
||||
/* --- variables --- */
|
||||
static gint GtkWidget_private_offset = 0;
|
||||
@ -2905,6 +2908,9 @@ gtk_widget_root (GtkWidget *widget)
|
||||
if (priv->context)
|
||||
gtk_style_context_set_display (priv->context, gtk_root_get_display (priv->root));
|
||||
|
||||
if (priv->surface_transform_changed_callbacks)
|
||||
add_parent_surface_transform_changed_listener (widget);
|
||||
|
||||
GTK_WIDGET_GET_CLASS (widget)->root (widget);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_ROOT]);
|
||||
@ -2922,6 +2928,9 @@ gtk_widget_unroot (GtkWidget *widget)
|
||||
g_assert (priv->root);
|
||||
g_assert (!priv->realized);
|
||||
|
||||
if (priv->parent_surface_transform_changed_parent)
|
||||
remove_parent_surface_transform_changed_listener (widget);
|
||||
|
||||
GTK_WIDGET_GET_CLASS (widget)->unroot (widget);
|
||||
|
||||
if (priv->context)
|
||||
@ -3586,6 +3595,249 @@ gtk_widget_disconnect_frame_clock (GtkWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _GtkSurfaceTransformChangedCallbackInfo GtkSurfaceTransformChangedCallbackInfo;
|
||||
|
||||
struct _GtkSurfaceTransformChangedCallbackInfo
|
||||
{
|
||||
guint id;
|
||||
GtkSurfaceTransformChangedCallback callback;
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
};
|
||||
|
||||
static void
|
||||
surface_transform_changed_callback_info_destroy (GtkSurfaceTransformChangedCallbackInfo *info)
|
||||
{
|
||||
if (info->notify)
|
||||
info->notify (info->user_data);
|
||||
|
||||
g_slice_free (GtkSurfaceTransformChangedCallbackInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_surface_transform_changed (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
graphene_matrix_t *surface_transform;
|
||||
GList *l;
|
||||
|
||||
if (priv->cached_surface_transform_valid)
|
||||
surface_transform = &priv->cached_surface_transform;
|
||||
else
|
||||
surface_transform = NULL;
|
||||
|
||||
for (l = priv->surface_transform_changed_callbacks; l;)
|
||||
{
|
||||
GtkSurfaceTransformChangedCallbackInfo *info = l->data;
|
||||
GList *l_next = l->next;
|
||||
|
||||
if (info->callback (widget,
|
||||
surface_transform,
|
||||
info->user_data) == G_SOURCE_REMOVE)
|
||||
{
|
||||
priv->surface_transform_changed_callbacks =
|
||||
g_list_delete_link (priv->surface_transform_changed_callbacks, l);
|
||||
surface_transform_changed_callback_info_destroy (info);
|
||||
}
|
||||
|
||||
l = l_next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_surface_transform_changed_callbacks (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->surface_transform_changed_callbacks; l;)
|
||||
{
|
||||
GtkSurfaceTransformChangedCallbackInfo *info = l->data;
|
||||
GList *l_next = l->next;
|
||||
|
||||
priv->surface_transform_changed_callbacks =
|
||||
g_list_delete_link (priv->surface_transform_changed_callbacks, l);
|
||||
surface_transform_changed_callback_info_destroy (info);
|
||||
|
||||
l = l_next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sync_widget_surface_transform (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
gboolean was_valid;
|
||||
graphene_matrix_t prev_transform;
|
||||
|
||||
was_valid = priv->cached_surface_transform_valid;
|
||||
prev_transform = priv->cached_surface_transform;
|
||||
|
||||
if (GTK_IS_ROOT (widget))
|
||||
{
|
||||
gsk_transform_to_matrix (priv->transform,
|
||||
&priv->cached_surface_transform);
|
||||
priv->cached_surface_transform_valid = TRUE;
|
||||
}
|
||||
else if (!priv->root)
|
||||
{
|
||||
priv->cached_surface_transform_valid = FALSE;
|
||||
}
|
||||
else if (gtk_widget_compute_transform (widget, GTK_WIDGET (priv->root),
|
||||
&priv->cached_surface_transform))
|
||||
{
|
||||
priv->cached_surface_transform_valid = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Could not compute surface transform");
|
||||
priv->cached_surface_transform_valid = FALSE;
|
||||
}
|
||||
|
||||
if (was_valid != priv->cached_surface_transform_valid ||
|
||||
(was_valid && priv->cached_surface_transform_valid &&
|
||||
!graphene_matrix_equal (&priv->cached_surface_transform,
|
||||
&prev_transform)))
|
||||
notify_surface_transform_changed (widget);
|
||||
}
|
||||
|
||||
static guint surface_transform_changed_callback_id;
|
||||
|
||||
static gboolean
|
||||
parent_surface_transform_changed_cb (GtkWidget *parent,
|
||||
const graphene_matrix_t *transform,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (user_data);
|
||||
|
||||
sync_widget_surface_transform (widget);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_parent_surface_transform_changed_listener (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
g_assert (priv->parent_surface_transform_changed_parent);
|
||||
|
||||
gtk_widget_remove_surface_transform_changed_callback (
|
||||
priv->parent_surface_transform_changed_parent,
|
||||
priv->parent_surface_transform_changed_id);
|
||||
priv->parent_surface_transform_changed_id = 0;
|
||||
g_clear_object (&priv->parent_surface_transform_changed_parent);
|
||||
}
|
||||
|
||||
static void
|
||||
add_parent_surface_transform_changed_listener (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GtkWidget *parent;
|
||||
|
||||
g_assert (!priv->parent_surface_transform_changed_parent);
|
||||
|
||||
parent = priv->parent;
|
||||
priv->parent_surface_transform_changed_id =
|
||||
gtk_widget_add_surface_transform_changed_callback (
|
||||
parent,
|
||||
parent_surface_transform_changed_cb,
|
||||
widget,
|
||||
NULL);
|
||||
priv->parent_surface_transform_changed_parent = g_object_ref (parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_add_surface_transform_changed_callback:
|
||||
* @widget: a #GtkWidget
|
||||
* @callback: a function to call when the surface transform changes
|
||||
* @user_data: data to pass to @callback
|
||||
* @notify: function to call to free @user_data when the callback is removed
|
||||
*
|
||||
* Invokes the callback whenever the surface relative transform of the widget
|
||||
* changes.
|
||||
*
|
||||
* Returns: an id for the connection of this callback. Remove the callback by
|
||||
* passing the id returned from this funcction to
|
||||
* gtk_widget_remove_surface_transform_changed_callback()
|
||||
*/
|
||||
guint
|
||||
gtk_widget_add_surface_transform_changed_callback (GtkWidget *widget,
|
||||
GtkSurfaceTransformChangedCallback callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
GtkSurfaceTransformChangedCallbackInfo *info;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
|
||||
g_return_val_if_fail (callback, 0);
|
||||
|
||||
priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
if (priv->parent && !priv->parent_surface_transform_changed_id)
|
||||
add_parent_surface_transform_changed_listener (widget);
|
||||
|
||||
if (!priv->surface_transform_changed_callbacks)
|
||||
sync_widget_surface_transform (widget);
|
||||
|
||||
info = g_slice_new0 (GtkSurfaceTransformChangedCallbackInfo);
|
||||
|
||||
info->id = ++surface_transform_changed_callback_id;
|
||||
info->callback = callback;
|
||||
info->user_data = user_data;
|
||||
info->notify = notify;
|
||||
|
||||
priv->surface_transform_changed_callbacks =
|
||||
g_list_prepend (priv->surface_transform_changed_callbacks, info);
|
||||
|
||||
return info->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_remove_surface_transform_changed_callback:
|
||||
* @widget: a #GtkWidget
|
||||
* @id: an id returned by gtk_widget_add_surface_transform_changed_callback()
|
||||
*
|
||||
* Removes a surface transform changed callback previously registered with
|
||||
* gtk_widget_add_surface_transform_changed_callback().
|
||||
*/
|
||||
void
|
||||
gtk_widget_remove_surface_transform_changed_callback (GtkWidget *widget,
|
||||
guint id)
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (id);
|
||||
|
||||
priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
for (l = priv->surface_transform_changed_callbacks; l; l = l->next)
|
||||
{
|
||||
GtkSurfaceTransformChangedCallbackInfo *info = l->data;
|
||||
|
||||
if (info->id == id)
|
||||
{
|
||||
priv->surface_transform_changed_callbacks =
|
||||
g_list_delete_link (priv->surface_transform_changed_callbacks, l);
|
||||
|
||||
surface_transform_changed_callback_info_destroy (info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!priv->surface_transform_changed_callbacks)
|
||||
{
|
||||
if (priv->parent_surface_transform_changed_parent)
|
||||
remove_parent_surface_transform_changed_listener (widget);
|
||||
|
||||
g_signal_handler_disconnect (widget, priv->parent_changed_handler_id);
|
||||
priv->parent_changed_handler_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_realize:
|
||||
* @widget: a #GtkWidget
|
||||
@ -4200,6 +4452,9 @@ gtk_widget_allocate (GtkWidget *widget,
|
||||
|
||||
priv->transform = transform;
|
||||
|
||||
if (priv->surface_transform_changed_callbacks)
|
||||
sync_widget_surface_transform (widget);
|
||||
|
||||
if (!alloc_needed && !size_changed && !baseline_changed)
|
||||
{
|
||||
/* Still have to move the window... */
|
||||
@ -8125,6 +8380,7 @@ gtk_widget_real_destroy (GtkWidget *object)
|
||||
gtk_grab_remove (widget);
|
||||
|
||||
destroy_tick_callbacks (widget);
|
||||
destroy_surface_transform_changed_callbacks (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -41,6 +41,10 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef gboolean (*GtkSurfaceTransformChangedCallback) (GtkWidget *widget,
|
||||
const graphene_matrix_t *surface_transform,
|
||||
gpointer user_data);
|
||||
|
||||
#define GTK_STATE_FLAGS_BITS 14
|
||||
|
||||
struct _GtkWidgetPrivate
|
||||
@ -116,6 +120,14 @@ struct _GtkWidgetPrivate
|
||||
guint clock_tick_id;
|
||||
GList *tick_callbacks;
|
||||
|
||||
/* Surface relative transform updates callbacks */
|
||||
guint parent_surface_transform_changed_id;
|
||||
GtkWidget *parent_surface_transform_changed_parent;
|
||||
gulong parent_changed_handler_id;
|
||||
GList *surface_transform_changed_callbacks;
|
||||
gboolean cached_surface_transform_valid;
|
||||
graphene_matrix_t cached_surface_transform;
|
||||
|
||||
/* The widget's name. If the widget does not have a name
|
||||
* (the name is NULL), then its name (as returned by
|
||||
* "gtk_widget_get_name") is its class's name.
|
||||
@ -344,6 +356,15 @@ gboolean gtk_widget_run_controllers (GtkWidget
|
||||
GtkPropagationPhase phase);
|
||||
|
||||
|
||||
guint gtk_widget_add_surface_transform_changed_callback (GtkWidget *widget,
|
||||
GtkSurfaceTransformChangedCallback callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
void gtk_widget_remove_surface_transform_changed_callback (GtkWidget *widget,
|
||||
guint id);
|
||||
|
||||
|
||||
/* inline getters */
|
||||
|
||||
static inline GtkWidget *
|
||||
|
@ -35,7 +35,7 @@ gdk_pixbuf_req = '>= 2.30.0'
|
||||
introspection_req = '>= 1.39.0'
|
||||
wayland_proto_req = '>= 1.12'
|
||||
wayland_req = '>= 1.14.91'
|
||||
graphene_req = '>= 1.8.5'
|
||||
graphene_req = '>= 1.8.7'
|
||||
epoxy_req = '>= 1.4'
|
||||
cloudproviders_req = '>= 0.2.5'
|
||||
xkbcommon_req = '>= 0.2.0'
|
||||
|
Loading…
Reference in New Issue
Block a user