diff options
Diffstat (limited to 'gtk')
106 files changed, 1792 insertions, 2473 deletions
diff --git a/gtk/a11y/gtkentryaccessible.c b/gtk/a11y/gtkentryaccessible.c index d83d9f9c55..ccdd8cc948 100644 --- a/gtk/a11y/gtkentryaccessible.c +++ b/gtk/a11y/gtkentryaccessible.c @@ -367,7 +367,7 @@ static void delete_text_cb (GtkEditable *editable, gint end); static gboolean check_for_selection_change (GtkEntryAccessible *entry, - GtkEntry *gtk_entry); + GtkEditable *editable); static void atk_editable_text_interface_init (AtkEditableTextIface *iface); @@ -465,56 +465,57 @@ gtk_entry_accessible_notify_gtk (GObject *obj, { GtkWidget *widget; AtkObject* atk_obj; - GtkEntry* gtk_entry; GtkEntryAccessible* entry; GtkEntryAccessiblePrivate *priv; widget = GTK_WIDGET (obj); atk_obj = gtk_widget_get_accessible (widget); - gtk_entry = GTK_ENTRY (widget); entry = GTK_ENTRY_ACCESSIBLE (atk_obj); priv = entry->priv; if (g_strcmp0 (pspec->name, "cursor-position") == 0) { - if (check_for_selection_change (entry, gtk_entry)) + if (check_for_selection_change (entry, GTK_EDITABLE (widget))) g_signal_emit_by_name (atk_obj, "text-selection-changed"); /* * The entry cursor position has moved so generate the signal. */ g_signal_emit_by_name (atk_obj, "text-caret-moved", - entry->priv->cursor_position); + gtk_editable_get_position (GTK_EDITABLE (widget))); } else if (g_strcmp0 (pspec->name, "selection-bound") == 0) { - if (check_for_selection_change (entry, gtk_entry)) + if (check_for_selection_change (entry, GTK_EDITABLE (widget))) g_signal_emit_by_name (atk_obj, "text-selection-changed"); } - else if (g_strcmp0 (pspec->name, "editable") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "editable") == 0) { gboolean value; g_object_get (obj, "editable", &value, NULL); atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value); } - else if (g_strcmp0 (pspec->name, "visibility") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "visibility") == 0) { gboolean visibility; AtkRole new_role; - visibility = gtk_entry_get_visibility (gtk_entry); + visibility = gtk_entry_get_visibility (GTK_ENTRY (widget)); new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT; atk_object_set_role (atk_obj, new_role); } - else if (g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0) { - if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY]) + if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY]) { priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_PRIMARY); g_signal_emit_by_name (entry, "children-changed::add", 0, priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL); } - else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY]) + else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY]) { gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY])); g_signal_emit_by_name (entry, "children-changed::remove", 0, @@ -522,16 +523,17 @@ gtk_entry_accessible_notify_gtk (GObject *obj, g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]); } } - else if (g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0) { gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0); - if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY]) + if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY]) { priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_SECONDARY); g_signal_emit_by_name (entry, "children-changed::add", index, priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL); } - else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY]) + else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY]) { gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY])); g_signal_emit_by_name (entry, "children-changed::remove", index, @@ -539,100 +541,100 @@ gtk_entry_accessible_notify_gtk (GObject *obj, g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]); } } - else if (g_strcmp0 (pspec->name, "primary-icon-name") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "primary-icon-name") == 0) { if (priv->icons[GTK_ENTRY_ICON_PRIMARY]) { const gchar *name; - name = gtk_entry_get_icon_name (gtk_entry, - GTK_ENTRY_ICON_PRIMARY); + name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY); if (name) atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name); } } - else if (g_strcmp0 (pspec->name, "secondary-icon-name") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "secondary-icon-name") == 0) { if (priv->icons[GTK_ENTRY_ICON_SECONDARY]) { const gchar *name; - name = gtk_entry_get_icon_name (gtk_entry, - GTK_ENTRY_ICON_SECONDARY); + name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY); if (name) atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name); } } - else if (g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0) { if (priv->icons[GTK_ENTRY_ICON_PRIMARY]) { gchar *text; - text = gtk_entry_get_icon_tooltip_text (gtk_entry, - GTK_ENTRY_ICON_PRIMARY); + text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY); if (text) { - atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], - text); + atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], text); g_free (text); } else { - atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], - ""); + atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], ""); } } } - else if (g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0) { if (priv->icons[GTK_ENTRY_ICON_SECONDARY]) { gchar *text; - text = gtk_entry_get_icon_tooltip_text (gtk_entry, - GTK_ENTRY_ICON_SECONDARY); + text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY); if (text) { - atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], - text); + atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], text); g_free (text); } else { - atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], - ""); + atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], ""); } } } - else if (g_strcmp0 (pspec->name, "primary-icon-activatable") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "primary-icon-activatable") == 0) { if (priv->icons[GTK_ENTRY_ICON_PRIMARY]) { - gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_PRIMARY); + gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY); atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY], ATK_STATE_ENABLED, on); } } - else if (g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0) { if (priv->icons[GTK_ENTRY_ICON_SECONDARY]) { - gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_SECONDARY); + gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY); atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY], ATK_STATE_ENABLED, on); } } - else if (g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0) { if (priv->icons[GTK_ENTRY_ICON_PRIMARY]) { - gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_PRIMARY); + gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY); atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY], ATK_STATE_SENSITIVE, on); } } - else if (g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0) + else if (GTK_IS_ENTRY (widget) && + g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0) { if (priv->icons[GTK_ENTRY_ICON_SECONDARY]) { - gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_SECONDARY); + gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY); atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY], ATK_STATE_SENSITIVE, on); } @@ -1450,12 +1452,12 @@ delete_text_cb (GtkEditable *editable, static gboolean check_for_selection_change (GtkEntryAccessible *accessible, - GtkEntry *entry) + GtkEditable *editable) { gboolean ret_val = FALSE; gint start, end; - if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end)) + if (gtk_editable_get_selection_bounds (editable, &start, &end)) { if (end != accessible->priv->cursor_position || start != accessible->priv->selection_bound) @@ -228,7 +228,6 @@ #include <gtk/gtktoolshell.h> #include <gtk/gtktooltip.h> #include <gtk/gtktestutils.h> -#include <gtk/gtktransform.h> #include <gtk/gtktreednd.h> #include <gtk/gtktreelistmodel.h> #include <gtk/gtktreemodel.h> diff --git a/gtk/gtkapplication-dbus.c b/gtk/gtkapplication-dbus.c index 3345a79573..b73d86046c 100644 --- a/gtk/gtkapplication-dbus.c +++ b/gtk/gtkapplication-dbus.c @@ -26,6 +26,8 @@ #include "gtksettings.h" #include "gtkprivate.h" +#include "gdk/gdkconstructor.h" + G_DEFINE_TYPE (GtkApplicationImplDBus, gtk_application_impl_dbus, GTK_TYPE_APPLICATION_IMPL) #define DBUS_BUS_NAME "org.freedesktop.DBus" diff --git a/gtk/gtkassistant.c b/gtk/gtkassistant.c index 8d3d67cd1d..1306bb4bd2 100644 --- a/gtk/gtkassistant.c +++ b/gtk/gtkassistant.c @@ -74,14 +74,15 @@ #include "gtkintl.h" #include "gtkimage.h" #include "gtklabel.h" -#include "gtkstack.h" +#include "gtklistlistmodelprivate.h" +#include "gtkmaplistmodel.h" #include "gtkprivate.h" #include "gtksettings.h" #include "gtksizegroup.h" #include "gtksizerequest.h" +#include "gtkstack.h" +#include "gtkstylecontext.h" #include "gtktypebuiltins.h" -#include "gtklistlistmodelprivate.h" -#include "gtkmaplistmodel.h" #include "a11y/gtkwindowaccessible.h" diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c index 6b2346cdba..8414bec0e3 100644 --- a/gtk/gtkbutton.c +++ b/gtk/gtkbutton.c @@ -66,6 +66,7 @@ #include "gtkmain.h" #include "gtkmarshalers.h" #include "gtkprivate.h" +#include "gtkstylecontext.h" #include "gtktypebuiltins.h" #include "a11y/gtkbuttonaccessible.h" diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c index 6b941ced3e..32df686852 100644 --- a/gtk/gtkcalendar.c +++ b/gtk/gtkcalendar.c @@ -295,6 +295,8 @@ static gboolean gtk_calendar_key_controller_key_pressed (GtkEventControllerKey * GdkModifierType state, GtkWidget *widget); static void gtk_calendar_key_controller_focus (GtkEventControllerKey *controller, + GdkCrossingMode mode, + GdkNotifyType detail, GtkWidget *widget); static void gtk_calendar_grab_notify (GtkWidget *widget, gboolean was_grabbed); @@ -2854,6 +2856,8 @@ gtk_calendar_key_controller_key_pressed (GtkEventControllerKey *controller, static void gtk_calendar_key_controller_focus (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkWidget *widget) { GtkCalendar *calendar = GTK_CALENDAR (widget); diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c index 3fc37a3dac..eb4db09263 100644 --- a/gtk/gtkcellarea.c +++ b/gtk/gtkcellarea.c @@ -352,6 +352,7 @@ #include "gtkmarshalers.h" #include "gtkprivate.h" #include "gtksnapshot.h" +#include "gtkstylecontext.h" #include <gobject/gvaluecollector.h> diff --git a/gtk/gtkcellrenderer.c b/gtk/gtkcellrenderer.c index 7c176b020c..72780c77c9 100644 --- a/gtk/gtkcellrenderer.c +++ b/gtk/gtkcellrenderer.c @@ -23,6 +23,7 @@ #include "gtkmarshalers.h" #include "gtkprivate.h" #include "gtksnapshot.h" +#include "gtkstylecontext.h" #include "gtktreeprivate.h" #include "gtktypebuiltins.h" diff --git a/gtk/gtkcellrendererprogress.c b/gtk/gtkcellrendererprogress.c index 43f4b138b6..1bacf77757 100644 --- a/gtk/gtkcellrendererprogress.c +++ b/gtk/gtkcellrendererprogress.c @@ -31,6 +31,7 @@ #include "gtkorientable.h" #include "gtkprivate.h" #include "gtksnapshot.h" +#include "gtkstylecontext.h" /** diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index ddacdc4e3c..9e6f238aa5 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -26,6 +26,7 @@ #include "gtkprivate.h" #include "gtksizerequest.h" #include "gtksnapshot.h" +#include "gtkstylecontext.h" #include "gtktreeprivate.h" #include "a11y/gtktextcellaccessible.h" diff --git a/gtk/gtkcolorbutton.c b/gtk/gtkcolorbutton.c index 0c8abded61..7e10a78abc 100644 --- a/gtk/gtkcolorbutton.c +++ b/gtk/gtkcolorbutton.c @@ -43,6 +43,7 @@ #include "gtkmarshalers.h" #include "gtkprivate.h" #include "gtksnapshot.h" +#include "gtkstylecontext.h" /** diff --git a/gtk/gtkcolorchooserwidget.c b/gtk/gtkcolorchooserwidget.c index 9f2d286017..8ba5df0d17 100644 --- a/gtk/gtkcolorchooserwidget.c +++ b/gtk/gtkcolorchooserwidget.c @@ -29,6 +29,7 @@ #include "gtkprivate.h" #include "gtkintl.h" #include "gtksizegroup.h" +#include "gtkstylecontext.h" #include <math.h> diff --git a/gtk/gtkcoloreditor.c b/gtk/gtkcoloreditor.c index 34f5991ca2..8670027631 100644 --- a/gtk/gtkcoloreditor.c +++ b/gtk/gtkcoloreditor.c @@ -36,6 +36,7 @@ #include "gtkspinbutton.h" #include "gtkstylecontext.h" #include "gtkeventcontrollerkey.h" +#include "gtkroot.h" #include <math.h> @@ -224,7 +225,7 @@ popup_edit (GtkWidget *widget, { dismiss_current_popup (editor); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editor)); - g_set_object (&editor->priv->popdown_focus, gtk_window_get_focus (GTK_WINDOW (toplevel))); + g_set_object (&editor->priv->popdown_focus, gtk_root_get_focus (GTK_ROOT (toplevel))); editor->priv->current_popup = popup; editor->priv->popup_position = position; gtk_widget_show (popup); diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c index 516326e6c1..7ad2bb0945 100644 --- a/gtk/gtkcolorswatch.c +++ b/gtk/gtkcolorswatch.c @@ -35,7 +35,6 @@ #include "gtkmodelbutton.h" #include "gtkpopover.h" #include "gtkprivate.h" -#include "gtkroundedboxprivate.h" #include "gtksnapshot.h" #include "gtkstylecontextprivate.h" #include "gtkwidgetprivate.h" @@ -43,8 +42,6 @@ #include "a11y/gtkcolorswatchaccessibleprivate.h" -#include "gsk/gskroundedrectprivate.h" - /* * GtkColorSwatch has two CSS nodes, the main one named colorswatch * and a subnode named overlay. The main node gets the .light or .dark @@ -97,30 +94,21 @@ swatch_snapshot (GtkWidget *widget, { GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch); - GtkStyleContext *context; - - context = gtk_widget_get_style_context (widget); if (priv->has_color) { cairo_pattern_t *pattern; cairo_matrix_t matrix; - GskRoundedRect content_box; - - gtk_rounded_boxes_init_for_style (NULL, - NULL, - &content_box, - gtk_style_context_lookup_style (context), - 0, 0, - gtk_widget_get_width (widget), - gtk_widget_get_height (widget)); - gtk_snapshot_push_rounded_clip (snapshot, &content_box); if (priv->use_alpha && !gdk_rgba_is_opaque (&priv->color)) { cairo_t *cr; - cr = gtk_snapshot_append_cairo (snapshot, &content_box.bounds); + cr = gtk_snapshot_append_cairo (snapshot, + &GRAPHENE_RECT_INIT ( + 0, 0, + gtk_widget_get_width (widget), + gtk_widget_get_height (widget))); cairo_set_source_rgb (cr, 0.33, 0.33, 0.33); cairo_paint (cr); @@ -136,7 +124,10 @@ swatch_snapshot (GtkWidget *widget, gtk_snapshot_append_color (snapshot, &priv->color, - &content_box.bounds); + &GRAPHENE_RECT_INIT ( + 0, 0, + gtk_widget_get_width (widget), + gtk_widget_get_height (widget))); } else { @@ -146,10 +137,11 @@ swatch_snapshot (GtkWidget *widget, gtk_snapshot_append_color (snapshot, &color, - &content_box.bounds); + &GRAPHENE_RECT_INIT ( + 0, 0, + gtk_widget_get_width (widget), + gtk_widget_get_height (widget))); } - - gtk_snapshot_pop (snapshot); } gtk_widget_snapshot_child (widget, priv->overlay_widget, snapshot); @@ -576,6 +568,7 @@ gtk_color_swatch_init (GtkColorSwatch *swatch) gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE); gtk_widget_set_has_surface (GTK_WIDGET (swatch), FALSE); + gtk_widget_set_overflow (GTK_WIDGET (swatch), GTK_OVERFLOW_HIDDEN); gesture = gtk_gesture_long_press_new (); gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), diff --git a/gtk/gtkcssboxesprivate.h b/gtk/gtkcssboxesprivate.h index d90ba1e598..24a38ff0de 100644 --- a/gtk/gtkcssboxesprivate.h +++ b/gtk/gtkcssboxesprivate.h @@ -19,6 +19,7 @@ #define __GTK_CSS_BOXES_PRIVATE_H__ #include "gtkcsstypesprivate.h" +#include "gtktypes.h" G_BEGIN_DECLS diff --git a/gtk/gtkcssimageprivate.h b/gtk/gtkcssimageprivate.h index 7bdfc23823..f39d73ae8d 100644 --- a/gtk/gtkcssimageprivate.h +++ b/gtk/gtkcssimageprivate.h @@ -26,6 +26,7 @@ #include "gtk/gtkcssparserprivate.h" #include "gtk/gtkcsstypesprivate.h" #include "gtk/gtksnapshot.h" +#include "gtk/gtkstyleprovider.h" G_BEGIN_DECLS diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h index 7335fb30da..20ef434e7e 100644 --- a/gtk/gtkcssnodeprivate.h +++ b/gtk/gtkcssnodeprivate.h @@ -23,6 +23,7 @@ #include "gtkcssstylechangeprivate.h" #include "gtkbitmaskprivate.h" #include "gtkcsstypesprivate.h" +#include "gtkstylecontext.h" G_BEGIN_DECLS diff --git a/gtk/gtkcssparserprivate.h b/gtk/gtkcssparserprivate.h index 3fb30f9136..8dd99ff9c5 100644 --- a/gtk/gtkcssparserprivate.h +++ b/gtk/gtkcssparserprivate.h @@ -18,7 +18,6 @@ #ifndef __GTK_CSS_PARSER_PRIVATE_H__ #define __GTK_CSS_PARSER_PRIVATE_H__ -#include "gtk/gtkcsstypesprivate.h" #include <gtk/gtkcssprovider.h> G_BEGIN_DECLS diff --git a/gtk/gtkcssshadowsvalueprivate.h b/gtk/gtkcssshadowsvalueprivate.h index e79a131a1f..fe1cc65816 100644 --- a/gtk/gtkcssshadowsvalueprivate.h +++ b/gtk/gtkcssshadowsvalueprivate.h @@ -23,6 +23,7 @@ #include <cairo.h> #include <pango/pango.h> +#include "gtkborder.h" #include "gtktypes.h" #include "gtkcssparserprivate.h" #include "gtkcssvalueprivate.h" diff --git a/gtk/gtkcssshadowvalueprivate.h b/gtk/gtkcssshadowvalueprivate.h index 4633c8abed..78d6eacc97 100644 --- a/gtk/gtkcssshadowvalueprivate.h +++ b/gtk/gtkcssshadowvalueprivate.h @@ -23,6 +23,7 @@ #include <cairo.h> #include <pango/pango.h> +#include "gtkborder.h" #include "gtktypes.h" #include "gtkcssparserprivate.h" #include "gtkcssvalueprivate.h" diff --git a/gtk/gtkcsstransformvalue.c b/gtk/gtkcsstransformvalue.c index 5868627025..51e9a06fdc 100644 --- a/gtk/gtkcsstransformvalue.c +++ b/gtk/gtkcsstransformvalue.c @@ -23,7 +23,7 @@ #include <string.h> #include "gtkcssnumbervalueprivate.h" -#include "gtktransform.h" +#include "gsktransform.h" typedef union _GtkCssTransform GtkCssTransform; @@ -35,7 +35,8 @@ typedef enum { GTK_CSS_TRANSFORM_SCALE, GTK_CSS_TRANSFORM_SKEW, GTK_CSS_TRANSFORM_SKEW_X, - GTK_CSS_TRANSFORM_SKEW_Y + GTK_CSS_TRANSFORM_SKEW_Y, + GTK_CSS_TRANSFORM_PERSPECTIVE } GtkCssTransformType; union _GtkCssTransform { @@ -66,6 +67,10 @@ union _GtkCssTransform { GtkCssTransformType type; GtkCssValue *skew; } skew_x, skew_y; + struct { + GtkCssTransformType type; + GtkCssValue *depth; + } perspective; }; struct _GtkCssValue { @@ -110,6 +115,9 @@ gtk_css_transform_clear (GtkCssTransform *transform) case GTK_CSS_TRANSFORM_SKEW_Y: _gtk_css_value_unref (transform->skew_y.skew); break; + case GTK_CSS_TRANSFORM_PERSPECTIVE: + _gtk_css_value_unref (transform->perspective.depth); + break; case GTK_CSS_TRANSFORM_NONE: default: g_assert_not_reached (); @@ -117,7 +125,7 @@ gtk_css_transform_clear (GtkCssTransform *transform) } } -static void +static gboolean gtk_css_transform_init_identity (GtkCssTransform *transform, GtkCssTransformType type) { @@ -152,28 +160,33 @@ gtk_css_transform_init_identity (GtkCssTransform *transform, case GTK_CSS_TRANSFORM_SKEW_Y: transform->skew_y.skew = _gtk_css_number_value_new (0, GTK_CSS_DEG); break; + case GTK_CSS_TRANSFORM_PERSPECTIVE: + return FALSE; + case GTK_CSS_TRANSFORM_NONE: default: g_assert_not_reached (); - break; + return FALSE; } transform->type = type; + + return TRUE; } -static GtkTransform * +static GskTransform * gtk_css_transform_apply (const GtkCssTransform *transform, - GtkTransform *next) + GskTransform *next) { graphene_matrix_t skew; switch (transform->type) { case GTK_CSS_TRANSFORM_MATRIX: - return gtk_transform_matrix (next, &transform->matrix.matrix); + return gsk_transform_matrix (next, &transform->matrix.matrix); case GTK_CSS_TRANSFORM_TRANSLATE: - return gtk_transform_translate_3d (next, + return gsk_transform_translate_3d (next, &GRAPHENE_POINT3D_INIT ( _gtk_css_number_value_get (transform->translate.x, 100), _gtk_css_number_value_get (transform->translate.y, 100), @@ -188,34 +201,38 @@ gtk_css_transform_apply (const GtkCssTransform *transform, _gtk_css_number_value_get (transform->rotate.x, 1), _gtk_css_number_value_get (transform->rotate.y, 1), _gtk_css_number_value_get (transform->rotate.z, 1)); - return gtk_transform_rotate_3d (next, + return gsk_transform_rotate_3d (next, _gtk_css_number_value_get (transform->rotate.angle, 100), &axis); } case GTK_CSS_TRANSFORM_SCALE: - return gtk_transform_scale_3d (next, + return gsk_transform_scale_3d (next, _gtk_css_number_value_get (transform->scale.x, 1), _gtk_css_number_value_get (transform->scale.y, 1), _gtk_css_number_value_get (transform->scale.z, 1)); - break; + case GTK_CSS_TRANSFORM_SKEW: graphene_matrix_init_skew (&skew, _gtk_css_number_value_get (transform->skew.x, 100) / 180.0f * G_PI, _gtk_css_number_value_get (transform->skew.y, 100) / 180.0f * G_PI); - return gtk_transform_matrix (next, &skew); + return gsk_transform_matrix (next, &skew); case GTK_CSS_TRANSFORM_SKEW_X: graphene_matrix_init_skew (&skew, _gtk_css_number_value_get (transform->skew_x.skew, 100) / 180.0f * G_PI, 0); - return gtk_transform_matrix (next, &skew); + return gsk_transform_matrix (next, &skew); case GTK_CSS_TRANSFORM_SKEW_Y: graphene_matrix_init_skew (&skew, 0, _gtk_css_number_value_get (transform->skew_y.skew, 100) / 180.0f * G_PI); - return gtk_transform_matrix (next, &skew); + return gsk_transform_matrix (next, &skew); + + case GTK_CSS_TRANSFORM_PERSPECTIVE: + return gsk_transform_perspective (next, + _gtk_css_number_value_get (transform->perspective.depth, 100)); case GTK_CSS_TRANSFORM_NONE: default: @@ -225,10 +242,10 @@ gtk_css_transform_apply (const GtkCssTransform *transform, } /* NB: The returned matrix may be invalid */ -static GtkTransform * +static GskTransform * gtk_css_transform_value_compute_transform (const GtkCssValue *value) { - GtkTransform *transform; + GskTransform *transform; guint i; transform = NULL; @@ -303,6 +320,9 @@ gtk_css_transform_compute (GtkCssTransform *dest, case GTK_CSS_TRANSFORM_SKEW_Y: dest->skew_y.skew = _gtk_css_value_compute (src->skew_y.skew, property_id, provider, style, parent_style); return dest->skew_y.skew == src->skew_y.skew; + case GTK_CSS_TRANSFORM_PERSPECTIVE: + dest->perspective.depth = _gtk_css_value_compute (src->perspective.depth, property_id, provider, style, parent_style); + return dest->perspective.depth == src->perspective.depth; case GTK_CSS_TRANSFORM_NONE: default: g_assert_not_reached (); @@ -389,6 +409,8 @@ gtk_css_transform_equal (const GtkCssTransform *transform1, return _gtk_css_value_equal (transform1->skew_x.skew, transform2->skew_x.skew); case GTK_CSS_TRANSFORM_SKEW_Y: return _gtk_css_value_equal (transform1->skew_y.skew, transform2->skew_y.skew); + case GTK_CSS_TRANSFORM_PERSPECTIVE: + return _gtk_css_value_equal (transform1->perspective.depth, transform2->perspective.depth); case GTK_CSS_TRANSFORM_NONE: default: g_assert_not_reached (); @@ -416,7 +438,8 @@ gtk_css_value_transform_equal (const GtkCssValue *value1, { GtkCssTransform transform; - gtk_css_transform_init_identity (&transform, larger->transforms[i].type); + if (!gtk_css_transform_init_identity (&transform, larger->transforms[i].type)) + return FALSE; if (!gtk_css_transform_equal (&larger->transforms[i], &transform)) { @@ -431,6 +454,38 @@ gtk_css_value_transform_equal (const GtkCssValue *value1, } static void +gtk_css_transform_transition_default (GtkCssTransform *result, + const GtkCssTransform *start, + const GtkCssTransform *end, + guint property_id, + double progress) +{ + graphene_matrix_t start_mat, end_mat; + GskTransform *trans; + + result->type = GTK_CSS_TRANSFORM_MATRIX; + + if (start) + trans = gtk_css_transform_apply (start, NULL); + else + trans = NULL; + gsk_transform_to_matrix (trans, &start_mat); + gsk_transform_unref (trans); + + if (end) + trans = gtk_css_transform_apply (end, NULL); + else + trans = NULL; + gsk_transform_to_matrix (trans, &end_mat); + gsk_transform_unref (trans); + + graphene_matrix_interpolate (&start_mat, + &end_mat, + progress, + &result->matrix.matrix); +} + +static void gtk_css_transform_transition (GtkCssTransform *result, const GtkCssTransform *start, const GtkCssTransform *end, @@ -473,6 +528,9 @@ gtk_css_transform_transition (GtkCssTransform *result, case GTK_CSS_TRANSFORM_SKEW_Y: result->skew_y.skew = _gtk_css_value_transition (start->skew_y.skew, end->skew_y.skew, property_id, progress); break; + case GTK_CSS_TRANSFORM_PERSPECTIVE: + gtk_css_transform_transition_default (result, start, end, property_id, progress); + break; case GTK_CSS_TRANSFORM_NONE: default: g_assert_not_reached (); @@ -512,16 +570,16 @@ gtk_css_value_transform_transition (GtkCssValue *start, { if (start->transforms[i].type != end->transforms[i].type) { - GtkTransform *transform; + GskTransform *transform; graphene_matrix_t start_matrix, end_matrix; transform = gtk_css_transform_value_compute_transform (start); - gtk_transform_to_matrix (transform, &start_matrix); - gtk_transform_unref (transform); + gsk_transform_to_matrix (transform, &start_matrix); + gsk_transform_unref (transform); transform = gtk_css_transform_value_compute_transform (end); - gtk_transform_to_matrix (transform, &end_matrix); - gtk_transform_unref (transform); + gsk_transform_to_matrix (transform, &end_matrix); + gsk_transform_unref (transform); result = gtk_css_transform_value_alloc (1); result->transforms[0].type = GTK_CSS_TRANSFORM_MATRIX; @@ -546,25 +604,45 @@ gtk_css_value_transform_transition (GtkCssValue *start, { GtkCssTransform transform; - gtk_css_transform_init_identity (&transform, start->transforms[i].type); - gtk_css_transform_transition (&result->transforms[i], - &start->transforms[i], - &transform, - property_id, - progress); - gtk_css_transform_clear (&transform); + if (gtk_css_transform_init_identity (&transform, start->transforms[i].type)) + { + gtk_css_transform_transition (&result->transforms[i], + &start->transforms[i], + &transform, + property_id, + progress); + gtk_css_transform_clear (&transform); + } + else + { + gtk_css_transform_transition_default (&result->transforms[i], + &start->transforms[i], + NULL, + property_id, + progress); + } } for (; i < end->n_transforms; i++) { GtkCssTransform transform; - gtk_css_transform_init_identity (&transform, end->transforms[i].type); - gtk_css_transform_transition (&result->transforms[i], - &transform, - &end->transforms[i], - property_id, - progress); - gtk_css_transform_clear (&transform); + if (gtk_css_transform_init_identity (&transform, end->transforms[i].type)) + { + gtk_css_transform_transition (&result->transforms[i], + &transform, + &end->transforms[i], + property_id, + progress); + gtk_css_transform_clear (&transform); + } + else + { + gtk_css_transform_transition_default (&result->transforms[i], + NULL, + &end->transforms[i], + property_id, + progress); + } } g_assert (i == MAX (start->n_transforms, end->n_transforms)); @@ -678,6 +756,11 @@ gtk_css_transform_print (const GtkCssTransform *transform, _gtk_css_value_print (transform->skew_y.skew, string); g_string_append (string, ")"); break; + case GTK_CSS_TRANSFORM_PERSPECTIVE: + g_string_append (string, "perspective("); + _gtk_css_value_print (transform->perspective.depth, string); + g_string_append (string, ")"); + break; case GTK_CSS_TRANSFORM_NONE: default: g_assert_not_reached (); @@ -1046,6 +1129,14 @@ gtk_css_transform_parse (GtkCssTransform *transform, if (transform->skew_y.skew == NULL) return FALSE; } + else if (_gtk_css_parser_try (parser, "perspective(", TRUE)) + { + transform->type = GTK_CSS_TRANSFORM_PERSPECTIVE; + + transform->perspective.depth = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH); + if (transform->perspective.depth == NULL) + return FALSE; + } else { _gtk_css_parser_error (parser, "unknown syntax for transform"); @@ -1098,7 +1189,7 @@ _gtk_css_transform_value_parse (GtkCssParser *parser) return value; } -GtkTransform * +GskTransform * gtk_css_transform_value_get_transform (const GtkCssValue *transform) { g_return_val_if_fail (transform->class == >K_CSS_VALUE_TRANSFORM, FALSE); diff --git a/gtk/gtkcsstransformvalueprivate.h b/gtk/gtkcsstransformvalueprivate.h index 77114cd6b4..143dd87868 100644 --- a/gtk/gtkcsstransformvalueprivate.h +++ b/gtk/gtkcsstransformvalueprivate.h @@ -28,7 +28,7 @@ G_BEGIN_DECLS GtkCssValue * _gtk_css_transform_value_new_none (void); GtkCssValue * _gtk_css_transform_value_parse (GtkCssParser *parser); -GtkTransform * gtk_css_transform_value_get_transform (const GtkCssValue *transform); +GskTransform * gtk_css_transform_value_get_transform (const GtkCssValue *transform); G_END_DECLS diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h index 0c9ae190d2..ece3703208 100644 --- a/gtk/gtkcsstypesprivate.h +++ b/gtk/gtkcsstypesprivate.h @@ -20,7 +20,6 @@ #include <glib-object.h> #include <gsk/gsk.h> -#include <gtk/gtkstylecontext.h> G_BEGIN_DECLS diff --git a/gtk/gtkcssvalueprivate.h b/gtk/gtkcssvalueprivate.h index 53ba739bce..7aba6b023c 100644 --- a/gtk/gtkcssvalueprivate.h +++ b/gtk/gtkcssvalueprivate.h @@ -21,7 +21,9 @@ #define __GTK_CSS_VALUE_PRIVATE_H__ #include <glib-object.h> + #include "gtkcsstypesprivate.h" +#include "gtkstyleprovider.h" G_BEGIN_DECLS diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c index db6cbac56e..11b4d7be9b 100644 --- a/gtk/gtkdialog.c +++ b/gtk/gtkdialog.c @@ -44,6 +44,7 @@ #include "gtksettings.h" #include "gtktypebuiltins.h" #include "gtksizegroup.h" +#include "gtkstylecontext.h" /** * SECTION:gtkdialog diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index 0313566573..46aeba742a 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -33,6 +33,7 @@ #include "gtkpicture.h" #include "gtkselectionprivate.h" #include "gtksettingsprivate.h" +#include "gtkstylecontext.h" #include "gtktooltipprivate.h" #include "gtkwidgetprivate.h" #include "gtkwindowgroup.h" diff --git a/gtk/gtkeditable.c b/gtk/gtkeditable.c index f710d51cc0..9569c4bc20 100644 --- a/gtk/gtkeditable.c +++ b/gtk/gtkeditable.c @@ -935,7 +935,10 @@ gtk_editable_delegate_set_property (GObject *object, GType type = G_TYPE_FROM_INSTANCE (object); guint first_prop; - first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data)); + do { + first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data)); + type = g_type_parent (type); + } while (first_prop == 0 && type != 0); if (prop_id < first_prop) return FALSE; @@ -994,7 +997,10 @@ gtk_editable_delegate_get_property (GObject *object, GType type = G_TYPE_FROM_INSTANCE (object); guint first_prop; - first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data)); + do { + first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data)); + type = g_type_parent (type); + } while (first_prop == 0 && type != 0); if (prop_id < first_prop) return FALSE; diff --git a/gtk/gtkemojichooser.c b/gtk/gtkemojichooser.c index d59ca4f5cc..26fdfb3584 100644 --- a/gtk/gtkemojichooser.c +++ b/gtk/gtkemojichooser.c @@ -34,6 +34,7 @@ #include "gtkintl.h" #include "gtkprivate.h" #include "gtksearchentryprivate.h" +#include "gtkstylecontext.h" #include "gtktext.h" #define BOX_SPACE 6 diff --git a/gtk/gtkemojicompletion.c b/gtk/gtkemojicompletion.c index 3c8796f920..e432128ee7 100644 --- a/gtk/gtkemojicompletion.c +++ b/gtk/gtkemojicompletion.c @@ -32,6 +32,7 @@ #include "gtkeventcontrollerkey.h" #include "gtkflowbox.h" #include "gtkstack.h" +#include "gtkstylecontext.h" struct _GtkEmojiCompletion { diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 02e5dd9317..499fbe9a84 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -124,13 +124,9 @@ * |[<!-- language="plain" --> * entry[.flat][.warning][.error] * ├── text[.readonly] - * ├── placeholder * ├── image.left * ├── image.right - * ├── [selection] - * ├── [block-cursor] * ├── [progress[.pulse]] - * ╰── [window.popup] * ]| * * GtkEntry has a main node with the name entry. Depending on the properties @@ -140,25 +136,11 @@ * When the entry shows icons, it adds subnodes with the name image and the * style class .left or .right, depending on where the icon appears. * - * When the entry has a selection, it adds a subnode with the name selection. - * - * When the entry is in overwrite mode, it adds a subnode with the name block-cursor - * that determines how the block cursor is drawn. - * * When the entry shows progress, it adds a subnode with the name progress. * The node has the style class .pulse when the shown progress is pulsing. * - * The CSS node for a context menu is added as a subnode below entry as well. - * - * The undershoot nodes are used to draw the underflow indication when content - * is scrolled out of view. These nodes get the .left and .right style classes - * added depending on where the indication is drawn. - * - * When touch is used and touch selection handles are shown, they are using - * CSS nodes with name cursor-handle. They get the .top or .bottom style class - * depending on where they are shown in relation to the selection. If there is - * just a single handle for the text cursor, it gets the style class - * .insertion-cursor. + * For all the subnodes added to the text node in various situations, + * see #GtkText. */ #define NAT_ENTRY_WIDTH 150 @@ -332,6 +314,18 @@ gtk_entry_grab_focus (GtkWidget *widget) gtk_widget_grab_focus (priv->text); } +static gboolean +gtk_entry_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling) +{ + GtkEntry *entry = GTK_ENTRY (widget); + GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry); + + gtk_widget_grab_focus (priv->text); + + return TRUE; +} + static void gtk_entry_class_init (GtkEntryClass *class) { @@ -351,6 +345,7 @@ gtk_entry_class_init (GtkEntryClass *class) widget_class->query_tooltip = gtk_entry_query_tooltip; widget_class->direction_changed = gtk_entry_direction_changed; widget_class->grab_focus = gtk_entry_grab_focus; + widget_class->mnemonic_activate = gtk_entry_mnemonic_activate; quark_entry_completion = g_quark_from_static_string ("gtk-entry-completion-key"); @@ -3110,6 +3105,7 @@ gtk_entry_ensure_progress_widget (GtkEntry *entry) priv->progress_widget = g_object_new (GTK_TYPE_PROGRESS_BAR, "css-name", "progress", NULL); + gtk_widget_set_can_pick (priv->progress_widget, FALSE); gtk_widget_set_parent (priv->progress_widget, GTK_WIDGET (entry)); diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c index f1b28d999b..f7f3fe1017 100644 --- a/gtk/gtkeventcontrollerkey.c +++ b/gtk/gtkeventcontrollerkey.c @@ -36,6 +36,7 @@ #include "gtkeventcontrollerkey.h" #include "gtkbindings.h" #include "gtkenums.h" +#include "gtkmain.h" #include <gdk/gdk.h> @@ -46,6 +47,9 @@ struct _GtkEventControllerKey GHashTable *pressed_keys; const GdkEvent *current_event; + + guint is_focus : 1; + guint contains_focus : 1; }; struct _GtkEventControllerKeyClass @@ -65,11 +69,19 @@ enum { static guint signals[N_SIGNALS] = { 0 }; +enum { + PROP_IS_FOCUS = 1, + PROP_CONTAINS_FOCUS, + NUM_PROPERTIES +}; + +static GParamSpec *props[NUM_PROPERTIES] = { NULL, }; + G_DEFINE_TYPE (GtkEventControllerKey, gtk_event_controller_key, GTK_TYPE_EVENT_CONTROLLER) static void -gtk_event_controller_finalize (GObject *object) +gtk_event_controller_key_finalize (GObject *object) { GtkEventControllerKey *key = GTK_EVENT_CONTROLLER_KEY (object); @@ -79,6 +91,50 @@ gtk_event_controller_finalize (GObject *object) G_OBJECT_CLASS (gtk_event_controller_key_parent_class)->finalize (object); } +static void +update_focus (GtkEventControllerKey *key, + gboolean focus_in, + GdkNotifyType detail) +{ + gboolean is_focus; + gboolean contains_focus; + + switch (detail) + { + case GDK_NOTIFY_VIRTUAL: + case GDK_NOTIFY_NONLINEAR_VIRTUAL: + is_focus = FALSE; + contains_focus = focus_in; + break; + case GDK_NOTIFY_ANCESTOR: + case GDK_NOTIFY_NONLINEAR: + is_focus = focus_in; + contains_focus = FALSE; + break; + case GDK_NOTIFY_INFERIOR: + is_focus = focus_in; + contains_focus = !focus_in; + break; + case GDK_NOTIFY_UNKNOWN: + default: + g_warning ("Unknown focus change detail"); + return; + } + + g_object_freeze_notify (G_OBJECT (key)); + if (key->is_focus != is_focus) + { + key->is_focus = is_focus; + g_object_notify (G_OBJECT (key), "is-focus"); + } + if (key->contains_focus != contains_focus) + { + key->contains_focus = contains_focus; + g_object_notify (G_OBJECT (key), "contains-focus"); + } + g_object_thaw_notify (G_OBJECT (key)); +} + static gboolean gtk_event_controller_key_handle_event (GtkEventController *controller, const GdkEvent *event) @@ -93,11 +149,23 @@ gtk_event_controller_key_handle_event (GtkEventController *controller, if (event_type == GDK_FOCUS_CHANGE) { gboolean focus_in; + GdkCrossingMode mode; + GdkNotifyType detail; + + gdk_event_get_focus_in (event, &focus_in); + gdk_event_get_crossing_mode (event, &mode); + gdk_event_get_crossing_detail (event, &detail); + + update_focus (key, focus_in, detail); - if (gdk_event_get_focus_in (event, &focus_in) && focus_in) - g_signal_emit (controller, signals[FOCUS_IN], 0); + key->current_event = event; + + if (focus_in) + g_signal_emit (controller, signals[FOCUS_IN], 0, mode, detail); else - g_signal_emit (controller, signals[FOCUS_OUT], 0); + g_signal_emit (controller, signals[FOCUS_OUT], 0, mode, detail); + + key->current_event = NULL; return FALSE; } @@ -159,15 +227,76 @@ gtk_event_controller_key_handle_event (GtkEventController *controller, } static void +gtk_event_controller_key_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkEventControllerKey *controller = GTK_EVENT_CONTROLLER_KEY (object); + + switch (prop_id) + { + case PROP_IS_FOCUS: + g_value_set_boolean (value, controller->is_focus); + break; + + case PROP_CONTAINS_FOCUS: + g_value_set_boolean (value, controller->contains_focus); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) { GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = gtk_event_controller_finalize; + object_class->finalize = gtk_event_controller_key_finalize; + object_class->get_property = gtk_event_controller_key_get_property; controller_class->handle_event = gtk_event_controller_key_handle_event; /** + * GtkEventControllerKey:is-focus: + * + * Whether focus is in the controllers widget itself, + * as opposed to in a descendent widget. See + * #GtkEventControllerKey:contains-focus. + * + * When handling focus events, this property is updated + * before #GtkEventControllerKey::focus-in or + * #GtkEventControllerKey::focus-out are emitted. + */ + props[PROP_IS_FOCUS] = + g_param_spec_boolean ("is-focus", + P_("Is Focus"), + P_("Whether the focus is in the controllers widget"), + FALSE, + G_PARAM_READABLE); + + /** + * GtkEventControllerKey:contains-focus: + * + * Whether focus is in a descendant of the controllers widget. + * See #GtkEventControllerKey:is-focus. + * + * When handling focus events, this property is updated + * before #GtkEventControllerKey::focus-in or + * #GtkEventControllerKey::focus-out are emitted. + */ + props[PROP_CONTAINS_FOCUS] = + g_param_spec_boolean ("contains-focus", + P_("Contains Focus"), + P_("Whether the focus is in a descendant of the controllers widget"), + FALSE, + G_PARAM_READABLE); + + g_object_class_install_properties (object_class, NUM_PROPERTIES, props); + + /** * GtkEventControllerKey::key-pressed: * @controller: the object which received the signal. * @keyval: the pressed key. @@ -233,38 +362,50 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) GTK_TYPE_EVENT_CONTROLLER_KEY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, G_TYPE_NONE, 0); /** * GtkEventControllerKey::focus-in: * @controller: the object which received the signal. + * @mode: crossing mode indicating what caused this change + * @detail: detail indication where the focus is coming from * - * This signal is emitted whenever the #GtkEventController:widget controlled - * by the @controller is given the keyboard focus. + * This signal is emitted whenever the widget controlled + * by the @controller or one of its descendants) is given + * the keyboard focus. */ signals[FOCUS_IN] = g_signal_new (I_("focus-in"), GTK_TYPE_EVENT_CONTROLLER_KEY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, + G_TYPE_NONE, + 2, + GDK_TYPE_CROSSING_MODE, + GDK_TYPE_NOTIFY_TYPE); /** * GtkEventControllerKey::focus-out: * @controller: the object which received the signal. + * @mode: crossing mode indicating what caused this change + * @detail: detail indication where the focus is going * - * This signal is emitted whenever the #GtkEventController:widget controlled - * by the @controller loses the keyboard focus. + * This signal is emitted whenever the widget controlled + * by the @controller (or one of its descendants) loses + * the keyboard focus. */ signals[FOCUS_OUT] = g_signal_new (I_("focus-out"), GTK_TYPE_EVENT_CONTROLLER_KEY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, + G_TYPE_NONE, + 2, + GDK_TYPE_CROSSING_MODE, + GDK_TYPE_NOTIFY_TYPE); } static void @@ -283,8 +424,7 @@ gtk_event_controller_key_init (GtkEventControllerKey *controller) GtkEventController * gtk_event_controller_key_new (void) { - return g_object_new (GTK_TYPE_EVENT_CONTROLLER_KEY, - NULL); + return g_object_new (GTK_TYPE_EVENT_CONTROLLER_KEY, NULL); } /** @@ -330,6 +470,13 @@ gtk_event_controller_key_get_im_context (GtkEventControllerKey *controller) * * Forwards the current event of this @controller to a @widget. * + * This function can only be used in handlers for the + * #GtkEventControllerKey::key-pressed, + * #GtkEventControllerKey::key-released + * or + * #GtkEventControllerKey::modifiers + * signals. + * * Returns: whether the @widget handled the event **/ gboolean @@ -339,6 +486,8 @@ gtk_event_controller_key_forward (GtkEventControllerKey *controller, g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), FALSE); g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (controller->current_event != NULL, FALSE); + g_return_val_if_fail (gdk_event_get_event_type (controller->current_event) == GDK_KEY_PRESS || + gdk_event_get_event_type (controller->current_event) == GDK_KEY_RELEASE, FALSE); if (!gtk_widget_get_realized (widget)) gtk_widget_realize (widget); @@ -377,3 +526,64 @@ gtk_event_controller_key_get_group (GtkEventControllerKey *controller) return group; } + +/** + * gtk_event_controller_key_get_focus_origin: + * @controller: a #GtkEventControllerKey + * + * Returns the widget that was holding focus before. + * + * This function can only be used in handlers for the + * #GtkEventControllerKey::focus-in and + * #GtkEventControllerKey::focus-out signals. + * + * Returns: (transfer none): the previous focus + */ +GtkWidget * +gtk_event_controller_key_get_focus_origin (GtkEventControllerKey *controller) +{ + gboolean focus_in; + GtkWidget *origin; + + g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), NULL); + g_return_val_if_fail (controller->current_event != NULL, NULL); + g_return_val_if_fail (gdk_event_get_event_type (controller->current_event) == GDK_FOCUS_CHANGE, NULL); + + gdk_event_get_focus_in (controller->current_event, &focus_in); + + if (focus_in) + origin = (GtkWidget *)gdk_event_get_related_target (controller->current_event); + else + origin = (GtkWidget *)gdk_event_get_target (controller->current_event); + + return origin; +} + +/** + * gtk_event_controller_key_get_focus_target: + * @controller: a #GtkEventControllerKey + * + * Returns the widget that will be holding focus afterwards. + * + * This function can only be used in handlers for the + * #GtkEventControllerKey::focus-in and + * #GtkEventControllerKey::focus-out signals. + * + * Returns: (transfer none): the next focus + */ +GtkWidget * +gtk_event_controller_key_get_focus_target (GtkEventControllerKey *controller) +{ + gboolean focus_in; + + g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), NULL); + g_return_val_if_fail (controller->current_event != NULL, NULL); + g_return_val_if_fail (gdk_event_get_event_type (controller->current_event) == GDK_FOCUS_CHANGE, NULL); + + gdk_event_get_focus_in (controller->current_event, &focus_in); + + if (focus_in) + return (GtkWidget *)gdk_event_get_target (controller->current_event); + else + return (GtkWidget *)gdk_event_get_related_target (controller->current_event); +} diff --git a/gtk/gtkeventcontrollerkey.h b/gtk/gtkeventcontrollerkey.h index c8a579773a..b036bde7ec 100644 --- a/gtk/gtkeventcontrollerkey.h +++ b/gtk/gtkeventcontrollerkey.h @@ -58,6 +58,11 @@ gboolean gtk_event_controller_key_forward (GtkEventControllerK GDK_AVAILABLE_IN_ALL guint gtk_event_controller_key_get_group (GtkEventControllerKey *controller); +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_event_controller_key_get_focus_origin (GtkEventControllerKey *controller); +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_event_controller_key_get_focus_target (GtkEventControllerKey *controller); + G_END_DECLS #endif /* __GTK_EVENT_CONTROLLER_KEY_H__ */ diff --git a/gtk/gtkeventcontrollermotion.c b/gtk/gtkeventcontrollermotion.c index f1d0d33a77..38fd81c37f 100644 --- a/gtk/gtkeventcontrollermotion.c +++ b/gtk/gtkeventcontrollermotion.c @@ -29,7 +29,8 @@ #include "config.h" #include "gtkintl.h" -#include "gtkwidget.h" +#include "gtkprivate.h" +#include "gtkwidgetprivate.h" #include "gtkeventcontrollerprivate.h" #include "gtkeventcontrollermotion.h" #include "gtktypebuiltins.h" @@ -38,6 +39,11 @@ struct _GtkEventControllerMotion { GtkEventController parent_instance; + + const GdkEvent *current_event; + + guint is_pointer_focus : 1; + guint contains_pointer_focus : 1; }; struct _GtkEventControllerMotionClass @@ -52,14 +58,67 @@ enum { N_SIGNALS }; +enum { + PROP_IS_POINTER_FOCUS = 1, + PROP_CONTAINS_POINTER_FOCUS, + NUM_PROPERTIES +}; + +static GParamSpec *props[NUM_PROPERTIES] = { NULL, }; + static guint signals[N_SIGNALS] = { 0 }; G_DEFINE_TYPE (GtkEventControllerMotion, gtk_event_controller_motion, GTK_TYPE_EVENT_CONTROLLER) +static void +update_pointer_focus (GtkEventControllerMotion *motion, + gboolean enter, + GdkNotifyType detail) +{ + gboolean is_pointer; + gboolean contains_pointer; + + switch (detail) + { + case GDK_NOTIFY_VIRTUAL: + case GDK_NOTIFY_NONLINEAR_VIRTUAL: + is_pointer = FALSE; + contains_pointer = enter; + break; + case GDK_NOTIFY_ANCESTOR: + case GDK_NOTIFY_NONLINEAR: + is_pointer = enter; + contains_pointer = FALSE; + break; + case GDK_NOTIFY_INFERIOR: + is_pointer = enter; + contains_pointer = !enter; + break; + case GDK_NOTIFY_UNKNOWN: + default: + g_warning ("Unknown crossing detail"); + return; + } + + g_object_freeze_notify (G_OBJECT (motion)); + if (motion->is_pointer_focus != is_pointer) + { + motion->is_pointer_focus = is_pointer; + g_object_notify (G_OBJECT (motion), "is-pointer-focus"); + } + if (motion->contains_pointer_focus != contains_pointer) + { + motion->contains_pointer_focus = contains_pointer; + g_object_notify (G_OBJECT (motion), "contains-pointer-focus"); + } + g_object_thaw_notify (G_OBJECT (motion)); +} + static gboolean gtk_event_controller_motion_handle_event (GtkEventController *controller, const GdkEvent *event) { + GtkEventControllerMotion *motion = GTK_EVENT_CONTROLLER_MOTION (controller); GtkEventControllerClass *parent_class; GdkEventType type; @@ -67,17 +126,43 @@ gtk_event_controller_motion_handle_event (GtkEventController *controller, if (type == GDK_ENTER_NOTIFY) { double x, y; + GdkCrossingMode mode; + GdkNotifyType detail; + gdk_event_get_coords (event, &x, &y); - g_signal_emit (controller, signals[ENTER], 0, x, y); + gdk_event_get_crossing_mode (event, &mode); + gdk_event_get_crossing_detail (event, &detail); + + update_pointer_focus (motion, TRUE, detail); + + motion->current_event = event; + + g_signal_emit (controller, signals[ENTER], 0, x, y, mode, detail); + + motion->current_event = NULL; } else if (type == GDK_LEAVE_NOTIFY) { - g_signal_emit (controller, signals[LEAVE], 0); + GdkCrossingMode mode; + GdkNotifyType detail; + + gdk_event_get_crossing_mode (event, &mode); + gdk_event_get_crossing_detail (event, &detail); + + update_pointer_focus (motion, FALSE, detail); + + motion->current_event = event; + + g_signal_emit (controller, signals[LEAVE], 0, mode, detail); + + motion->current_event = NULL; } else if (type == GDK_MOTION_NOTIFY) { double x, y; + gdk_event_get_coords (event, &x, &y); + g_signal_emit (controller, signals[MOTION], 0, x, y); } @@ -87,13 +172,76 @@ gtk_event_controller_motion_handle_event (GtkEventController *controller, } static void +gtk_event_controller_motion_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkEventControllerMotion *controller = GTK_EVENT_CONTROLLER_MOTION (object); + + switch (prop_id) + { + case PROP_IS_POINTER_FOCUS: + g_value_set_boolean (value, controller->is_pointer_focus); + break; + + case PROP_CONTAINS_POINTER_FOCUS: + g_value_set_boolean (value, controller->contains_pointer_focus); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass); + object_class->get_property = gtk_event_controller_motion_get_property; + controller_class->handle_event = gtk_event_controller_motion_handle_event; /** + * GtkEventControllerMotion:is-pointer-focus: + * + * Whether the pointer is in the controllers widget itself, + * as opposed to in a descendent widget. See + * #GtkEventControllerMotion:contains-pointer-focus. + * + * When handling crossing events, this property is updated + * before #GtkEventControllerMotion::enter or + * #GtkEventControllerMotion::leave are emitted. + */ + props[PROP_IS_POINTER_FOCUS] = + g_param_spec_boolean ("is-pointer-focus", + P_("Is Pointer Focus"), + P_("Whether the pointer is in the controllers widget"), + FALSE, + G_PARAM_READABLE); + + /** + * GtkEventControllerMotion:contains-pointer-focus: + * + * Whether the pointer is in a descendant of the controllers widget. + * See #GtkEventControllerMotion:is-pointer-focus. + * + * When handling crossing events, this property is updated + * before #GtkEventControllerMotion::enter or + * #GtkEventControllerMotion::leave are emitted. + */ + props[PROP_CONTAINS_POINTER_FOCUS] = + g_param_spec_boolean ("contains-pointer-focus", + P_("Contains Pointer Focus"), + P_("Whether the pointer is in a descendant of the controllers widget"), + FALSE, + G_PARAM_READABLE); + + g_object_class_install_properties (object_class, NUM_PROPERTIES, props); + + /** * GtkEventControllerMotion::enter: * @controller: The object that received the signal * @x: the x coordinate @@ -107,7 +255,12 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass) G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE); + G_TYPE_NONE, + 4, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + GDK_TYPE_CROSSING_MODE, + GDK_TYPE_NOTIFY_TYPE); /** * GtkEventControllerMotion::leave: @@ -121,7 +274,10 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass) G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); + G_TYPE_NONE, + 2, + GDK_TYPE_CROSSING_MODE, + GDK_TYPE_NOTIFY_TYPE); /** * GtkEventControllerMotion::motion: @@ -158,3 +314,56 @@ gtk_event_controller_motion_new (void) return g_object_new (GTK_TYPE_EVENT_CONTROLLER_MOTION, NULL); } + +/** + * gtk_event_controller_motion_get_pointer_origin: + * @controller: a #GtkEventControllerMotion + * + * Returns the widget that contained the pointer before. + * + * This function can only be used in handlers for the + * #GtkEventControllerMotion::enter and + * #GtkEventControllerMotion::leave signals. + * + * Returns: (transfer none): the previous pointer focus + */ +GtkWidget * +gtk_event_controller_motion_get_pointer_origin (GtkEventControllerMotion *controller) +{ + GtkWidget *origin; + + g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_MOTION (controller), NULL); + g_return_val_if_fail (controller->current_event != NULL, NULL); + + if (gdk_event_get_event_type (controller->current_event) == GDK_ENTER_NOTIFY) + origin = (GtkWidget *)gdk_event_get_related_target (controller->current_event); + else + origin = (GtkWidget *)gdk_event_get_target (controller->current_event); + + return origin; +} + +/** + * gtk_event_controller_motion_get_pointer_target: + * @controller: a #GtkEventControllerMotion + * + * Returns the widget that will contain the pointer afterwards. + * + * This function can only be used in handlers for the + * #GtkEventControllerMotion::enter and + * #GtkEventControllerMotion::leave signals. + * + * Returns: (transfer none): the next pointer focus + */ +GtkWidget * +gtk_event_controller_motion_get_pointer_target (GtkEventControllerMotion *controller) +{ + g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_MOTION (controller), NULL); + g_return_val_if_fail (controller->current_event != NULL, NULL); + + if (gdk_event_get_event_type (controller->current_event) == GDK_ENTER_NOTIFY) + return (GtkWidget *)gdk_event_get_target (controller->current_event); + else + return (GtkWidget *)gdk_event_get_related_target (controller->current_event); +} + diff --git a/gtk/gtkeventcontrollermotion.h b/gtk/gtkeventcontrollermotion.h index 9377a7ba12..05d1852986 100644 --- a/gtk/gtkeventcontrollermotion.h +++ b/gtk/gtkeventcontrollermotion.h @@ -45,6 +45,11 @@ GType gtk_event_controller_motion_get_type (void) G_GNUC_CONST; GDK_AVAILABLE_IN_ALL GtkEventController *gtk_event_controller_motion_new (void); +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_event_controller_motion_get_pointer_origin (GtkEventControllerMotion *controller); +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_event_controller_motion_get_pointer_target (GtkEventControllerMotion *controller); + G_END_DECLS #endif /* __GTK_EVENT_CONTROLLER_MOTION_H__ */ diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 4d9ab00e05..3227a84e1f 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -82,6 +82,7 @@ #include "gtkdebug.h" #include "gtkfilechoosererrorstackprivate.h" #include "gtkentryprivate.h" +#include "gtkroot.h" #include <cairo-gobject.h> @@ -340,6 +341,7 @@ struct _GtkFileChooserWidgetPrivate { GSource *focus_entry_idle; gulong toplevel_set_focus_id; + GtkWidget *toplevel_current_focus_widget; GtkWidget *toplevel_last_focus_widget; gint sort_column; @@ -1361,7 +1363,7 @@ key_press_cb (GtkEventController *controller, GtkWidget *default_widget, *focus_widget; default_widget = gtk_window_get_default_widget (window); - focus_widget = gtk_window_get_focus (window); + focus_widget = gtk_root_get_focus (GTK_ROOT (window)); if (widget != default_widget && !(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget)))) @@ -2709,7 +2711,7 @@ location_mode_set (GtkFileChooserWidget *impl, switch_to_file_list = FALSE; if (toplevel) { - current_focus = gtk_window_get_focus (toplevel); + current_focus = gtk_root_get_focus (GTK_ROOT (toplevel)); if (!current_focus || current_focus == priv->location_entry) switch_to_file_list = TRUE; } @@ -3560,13 +3562,14 @@ gtk_file_chooser_widget_dispose (GObject *object) * widget on our toplevel. See gtk_file_chooser_widget_hierarchy_changed() */ static void -toplevel_set_focus_cb (GtkWindow *window, - GtkWidget *focus, +toplevel_set_focus_cb (GtkWindow *window, + GParamSpec *pspec, GtkFileChooserWidget *impl) { GtkFileChooserWidgetPrivate *priv = impl->priv; - priv->toplevel_last_focus_widget = gtk_window_get_focus (window); + priv->toplevel_last_focus_widget = priv->toplevel_current_focus_widget; + priv->toplevel_current_focus_widget = gtk_root_get_focus (GTK_ROOT (window)); } /* We monitor the focus widget on our toplevel to be able to know which widget @@ -3584,9 +3587,10 @@ gtk_file_chooser_widget_root (GtkWidget *widget) toplevel = gtk_widget_get_toplevel (widget); g_assert (priv->toplevel_set_focus_id == 0); - priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus", + priv->toplevel_set_focus_id = g_signal_connect (toplevel, "notify::focus-widget", G_CALLBACK (toplevel_set_focus_cb), impl); - priv->toplevel_last_focus_widget = gtk_window_get_focus (GTK_WINDOW (toplevel)); + priv->toplevel_last_focus_widget = NULL; + priv->toplevel_current_focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel)); } static void @@ -3602,6 +3606,7 @@ gtk_file_chooser_widget_unroot (GtkWidget *widget) g_signal_handler_disconnect (toplevel, priv->toplevel_set_focus_id); priv->toplevel_set_focus_id = 0; priv->toplevel_last_focus_widget = NULL; + priv->toplevel_current_focus_widget = NULL; } GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->unroot (widget); @@ -5806,7 +5811,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) toplevel = get_toplevel (GTK_WIDGET (impl)); if (toplevel) - current_focus = gtk_window_get_focus (toplevel); + current_focus = gtk_root_get_focus (GTK_ROOT (toplevel)); else current_focus = NULL; @@ -6655,7 +6660,7 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed) retval = FALSE; - current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel)); + current_focus = gtk_root_get_focus (GTK_ROOT (toplevel)); if (current_focus == priv->browse_files_tree_view) { diff --git a/gtk/gtkfontbutton.c b/gtk/gtkfontbutton.c index 3d87ffb103..6e12768c2f 100644 --- a/gtk/gtkfontbutton.c +++ b/gtk/gtkfontbutton.c @@ -29,21 +29,20 @@ #include "gtkfontbutton.h" -#include "gtkmain.h" #include "gtkbox.h" -#include "gtklabel.h" +#include "gtkcssprovider.h" #include "gtkfontchooser.h" #include "gtkfontchooserdialog.h" -#include "gtkimage.h" +#include "gtkfontchooserutils.h" +#include "gtkintl.h" +#include "gtklabel.h" #include "gtkmarshalers.h" -#include "gtkseparator.h" #include "gtkprivate.h" -#include "gtkintl.h" -#include "gtkcssprovider.h" +#include "gtkseparator.h" +#include "gtkstylecontext.h" #include <string.h> #include <stdio.h> -#include "gtkfontchooserutils.h" /** diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index cf97d48ba2..06d1240fb4 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -164,6 +164,8 @@ static void gtk_icon_view_motion (GtkEventControl double y, gpointer user_data); static void gtk_icon_view_leave (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data); static void gtk_icon_view_button_press (GtkGestureMultiPress *gesture, int n_press, @@ -1875,6 +1877,8 @@ gtk_icon_view_motion (GtkEventController *controller, static void gtk_icon_view_leave (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data) { GtkIconView *icon_view; diff --git a/gtk/gtkimcontextxim.c b/gtk/gtkimcontextxim.c index 98f6e530a6..c203f502df 100644 --- a/gtk/gtkimcontextxim.c +++ b/gtk/gtkimcontextxim.c @@ -1580,40 +1580,6 @@ on_status_toplevel_notify_display (GtkWindow *toplevel, gtk_widget_get_display (GTK_WIDGET (toplevel))); } -/* Called when the toplevel window is moved; updates the position of - * the status window to follow it. - */ -static gboolean -on_status_toplevel_configure (GtkWidget *toplevel, - GdkEvent *event, - StatusWindow *status_window) -{ - if (gdk_event_get_event_type (event) == GDK_CONFIGURE) - { - GdkRectangle rect; - GtkRequisition requisition; - gint y; - gint height; - - if (status_window->window) - { - height = DisplayHeight(GDK_SURFACE_XDISPLAY (gtk_widget_get_surface (toplevel)), 0); - - gdk_surface_get_frame_extents (gtk_widget_get_surface (toplevel), &rect); - gtk_widget_get_preferred_size ( (status_window->window), &requisition, NULL); - - if (rect.y + rect.height + requisition.height < height) - y = rect.y + rect.height; - else - y = height - requisition.height; - - gtk_window_move (GTK_WINDOW (status_window->window), rect.x, y); - } - } - - return GDK_EVENT_PROPAGATE; -} - /* Frees a status window and removes its link from the status_windows list */ static void @@ -1630,9 +1596,6 @@ status_window_free (StatusWindow *status_window) g_signal_handlers_disconnect_by_func (status_window->toplevel, G_CALLBACK (on_status_toplevel_notify_display), status_window); - g_signal_handlers_disconnect_by_func (status_window->toplevel, - G_CALLBACK (on_status_toplevel_configure), - status_window); if (status_window->window) gtk_widget_destroy (status_window->window); @@ -1661,9 +1624,6 @@ status_window_get (GtkWidget *toplevel) g_signal_connect (toplevel, "destroy", G_CALLBACK (on_status_toplevel_destroy), status_window); - g_signal_connect (toplevel, "event", - G_CALLBACK (on_status_toplevel_configure), - status_window); g_signal_connect (toplevel, "notify::display", G_CALLBACK (on_status_toplevel_notify_display), status_window); @@ -1695,8 +1655,6 @@ status_window_make_window (StatusWindow *status_window) gtk_window_set_display (GTK_WINDOW (status_window->window), gtk_widget_get_display (status_window->toplevel)); - - on_status_toplevel_configure (status_window->toplevel, NULL, status_window); } /* Updates the text in the status window, hiding or diff --git a/gtk/gtkinfobar.c b/gtk/gtkinfobar.c index 2631fbc624..a396264e89 100644 --- a/gtk/gtkinfobar.c +++ b/gtk/gtkinfobar.c @@ -45,6 +45,7 @@ #include "gtkintl.h" #include "gtkprivate.h" #include "gtkorientable.h" +#include "gtkstylecontext.h" #include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 86442d16a1..859fa5059a 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -425,6 +425,8 @@ static void gtk_label_motion (GtkEventControllerMotion *controller, double y, gpointer data); static void gtk_label_leave (GtkEventControllerMotion *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer data); static void gtk_label_grab_focus (GtkWidget *widget); @@ -4870,6 +4872,8 @@ gtk_label_motion (GtkEventControllerMotion *controller, static void gtk_label_leave (GtkEventControllerMotion *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer data) { GtkLabel *label = GTK_LABEL (data); @@ -6222,7 +6226,7 @@ gtk_label_activate_current_link (GtkLabel *label) if (window) { default_widget = gtk_window_get_default_widget (window); - focus_widget = gtk_window_get_focus (window); + focus_widget = gtk_root_get_focus (GTK_ROOT (window)); if (default_widget != widget && !(widget == focus_widget && (!default_widget || !gtk_widget_is_sensitive (default_widget)))) diff --git a/gtk/gtklinkbutton.c b/gtk/gtklinkbutton.c index ee5468aa55..50f4dfb6da 100644 --- a/gtk/gtklinkbutton.c +++ b/gtk/gtklinkbutton.c @@ -65,6 +65,7 @@ #include "gtkprivate.h" #include "gtkshow.h" #include "gtksizerequest.h" +#include "gtkstylecontext.h" #include "gtktooltip.h" #include "gtkwidgetprivate.h" diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 8aa278e9eb..250a2063c7 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1407,63 +1407,85 @@ static void synth_crossing (GtkWidget *widget, GtkWidget *toplevel, gboolean enter, - GtkWidget *other_widget, + GtkWidget *target, + GtkWidget *related_target, GdkEvent *source, GdkNotifyType notify_type, GdkCrossingMode crossing_mode) { GdkEvent *event; - gdouble x, y; + GtkStateFlags flags; - event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); - gdk_event_set_user_data (event, G_OBJECT (widget)); + if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE) + { +g_print ("focus %s: %s\n", enter ? "in" : "out", G_OBJECT_TYPE_NAME (widget)); + event = gdk_event_new (GDK_FOCUS_CHANGE); + event->focus_change.in = enter; + event->focus_change.mode = crossing_mode; + event->focus_change.detail = notify_type; + + flags = GTK_STATE_FLAG_FOCUSED; + if (!GTK_IS_WINDOW (toplevel) || gtk_window_get_focus_visible (GTK_WINDOW (toplevel))) + flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; + } + else + { + gdouble x, y; + event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); + if (related_target) + event->crossing.child_surface = g_object_ref (gtk_widget_get_surface (related_target)); + gdk_event_get_coords (source, &x, &y); + event->crossing.x = x; + event->crossing.y = y; + event->crossing.mode = crossing_mode; + event->crossing.detail = notify_type; + + flags = GTK_STATE_FLAG_PRELIGHT; + } + + gdk_event_set_target (event, G_OBJECT (target)); + gdk_event_set_related_target (event, G_OBJECT (related_target)); gdk_event_set_device (event, gdk_event_get_device (source)); gdk_event_set_source_device (event, gdk_event_get_source_device (source)); - event->any.surface = g_object_ref (gtk_widget_get_surface (toplevel)); - if (other_widget) - event->crossing.child_surface = g_object_ref (gtk_widget_get_surface (other_widget)); + event->any.surface = gtk_widget_get_surface (toplevel); + if (event->any.surface) + g_object_ref (event->any.surface); if (enter) - gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE); + gtk_widget_set_state_flags (widget, flags, FALSE); else - gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT); + gtk_widget_unset_state_flags (widget, flags); - gdk_event_get_coords (source, &x, &y); - event->crossing.x = x; - event->crossing.y = y; - event->crossing.mode = crossing_mode; - event->crossing.detail = notify_type; + if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE) + { + /* maintain focus chain */ + if (enter || notify_type == GDK_NOTIFY_INFERIOR) + { + GtkWidget *parent = gtk_widget_get_parent (widget); + if (parent) + gtk_widget_set_focus_child (parent, widget); + } + else if (!enter && notify_type != GDK_NOTIFY_INFERIOR) + { + GtkWidget *parent = gtk_widget_get_parent (widget); + if (parent) + gtk_widget_set_focus_child (parent, NULL); + } + /* maintain widget state */ + if (notify_type == GDK_NOTIFY_ANCESTOR || + notify_type == GDK_NOTIFY_INFERIOR || + notify_type == GDK_NOTIFY_NONLINEAR) + gtk_widget_set_has_focus (widget, enter); + } + gtk_widget_event (widget, event); g_object_unref (event); } -static GtkWidget * -update_pointer_focus_state (GtkWindow *toplevel, - GdkEvent *event, - GtkWidget *new_target) -{ - GtkWidget *old_target = NULL; - GdkEventSequence *sequence; - GdkDevice *device; - gdouble x, y; - - device = gdk_event_get_device (event); - sequence = gdk_event_get_event_sequence (event); - old_target = gtk_window_lookup_pointer_focus_widget (toplevel, device, sequence); - if (old_target == new_target) - return old_target; - - gdk_event_get_coords (event, &x, &y); - gtk_window_update_pointer_focus (toplevel, device, sequence, - new_target, x, y); - - return old_target; -} - -static void -gtk_synthesize_crossing_events (GtkWindow *toplevel, +void +gtk_synthesize_crossing_events (GtkRoot *toplevel, GtkWidget *old_target, GtkWidget *new_target, GdkEvent *event, @@ -1492,13 +1514,16 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, { widget = old_target; - while (widget != ancestor) + while (widget) { notify_type = (widget == old_target) ? leave_type : get_virtual_notify_type (leave_type); - synth_crossing (widget, GTK_WIDGET (toplevel), FALSE, - new_target, event, notify_type, mode); + if (widget != ancestor || widget == old_target) + synth_crossing (widget, GTK_WIDGET (toplevel), FALSE, + old_target, new_target, event, notify_type, mode); + if (widget == ancestor || widget == GTK_WIDGET (toplevel)) + break; widget = gtk_widget_get_parent (widget); } } @@ -1509,9 +1534,11 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, widget = new_target; - while (widget != ancestor) + while (widget) { widgets = g_slist_prepend (widgets, widget); + if (widget == ancestor || widget == GTK_WIDGET (toplevel)) + break; widget = gtk_widget_get_parent (widget); } @@ -1522,12 +1549,37 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, notify_type = (widget == new_target) ? enter_type : get_virtual_notify_type (enter_type); - synth_crossing (widget, GTK_WIDGET (toplevel), TRUE, - old_target, event, notify_type, mode); + if (widget != ancestor || widget == new_target) + synth_crossing (widget, GTK_WIDGET (toplevel), TRUE, + new_target, old_target, event, notify_type, mode); } } } + +static GtkWidget * +update_pointer_focus_state (GtkWindow *toplevel, + GdkEvent *event, + GtkWidget *new_target) +{ + GtkWidget *old_target = NULL; + GdkEventSequence *sequence; + GdkDevice *device; + gdouble x, y; + + device = gdk_event_get_device (event); + sequence = gdk_event_get_event_sequence (event); + old_target = gtk_window_lookup_pointer_focus_widget (toplevel, device, sequence); + if (old_target == new_target) + return old_target; + + gdk_event_get_coords (event, &x, &y); + gtk_window_update_pointer_focus (toplevel, device, sequence, + new_target, x, y); + + return old_target; +} + static gboolean is_pointing_event (GdkEvent *event) { @@ -1604,7 +1656,7 @@ handle_pointing_event (GdkEvent *event) old_target = update_pointer_focus_state (toplevel, event, NULL); if (event->any.type == GDK_LEAVE_NOTIFY) - gtk_synthesize_crossing_events (toplevel, old_target, NULL, + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, NULL, event, event->crossing.mode); break; case GDK_ENTER_NOTIFY: @@ -1629,7 +1681,7 @@ handle_pointing_event (GdkEvent *event) if (!gtk_window_lookup_pointer_focus_implicit_grab (toplevel, device, sequence)) { - gtk_synthesize_crossing_events (toplevel, old_target, target, + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, target, event, GDK_CROSSING_NORMAL); } @@ -1659,7 +1711,7 @@ handle_pointing_event (GdkEvent *event) new_target = gtk_widget_pick (GTK_WIDGET (toplevel), x, y); if (new_target == NULL) new_target = GTK_WIDGET (toplevel); - gtk_synthesize_crossing_events (toplevel, target, new_target, event, + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), target, new_target, event, GDK_CROSSING_UNGRAB); gtk_window_maybe_update_cursor (toplevel, NULL, device); } @@ -1761,7 +1813,7 @@ gtk_main_do_event (GdkEvent *event) if (is_pointing_event (event)) target_widget = handle_pointing_event (event); - else if (GTK_IS_WINDOW (target_widget) && + else if (GTK_IS_ROOT (target_widget) && (event->any.type == GDK_KEY_PRESS || event->any.type == GDK_KEY_RELEASE)) { @@ -1771,7 +1823,7 @@ gtk_main_do_event (GdkEvent *event) gtk_window_activate_key (GTK_WINDOW (target_widget), (GdkEventKey *) event)) goto cleanup; - focus_widget = gtk_window_get_focus (GTK_WINDOW (target_widget)); + focus_widget = gtk_root_get_focus (GTK_ROOT (target_widget)); if (focus_widget) target_widget = focus_widget; } @@ -1779,7 +1831,7 @@ gtk_main_do_event (GdkEvent *event) if (!target_widget) goto cleanup; - gdk_event_set_user_data (event, G_OBJECT (target_widget)); + gdk_event_set_target (event, G_OBJECT (target_widget)); window_group = gtk_main_get_window_group (target_widget); device = gdk_event_get_device (event); @@ -2398,7 +2450,7 @@ gtk_get_event_widget (const GdkEvent *event) GtkWidget * gtk_get_event_target (const GdkEvent *event) { - return GTK_WIDGET (gdk_event_get_user_data (event)); + return GTK_WIDGET (gdk_event_get_target (event)); } /** diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 247dd4f12e..ad0209367f 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -215,8 +215,12 @@ static void gtk_menu_motion (GtkEventController *controller, static void gtk_menu_enter (GtkEventController *controller, double x, double y, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data); static void gtk_menu_leave (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data); static gboolean gtk_menu_key_pressed (GtkEventControllerKey *controller, guint keyval, @@ -3165,6 +3169,8 @@ static void gtk_menu_enter (GtkEventController *controller, double x, double y, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data) { GdkDevice *source_device; @@ -3191,6 +3197,8 @@ gtk_menu_enter (GtkEventController *controller, static void gtk_menu_leave (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data) { GtkMenu *menu; diff --git a/gtk/gtkmenubutton.c b/gtk/gtkmenubutton.c index 68eaa1c50b..60b5a2b034 100644 --- a/gtk/gtkmenubutton.c +++ b/gtk/gtkmenubutton.c @@ -110,18 +110,19 @@ #include "config.h" -#include "gtkmenubutton.h" -#include "gtkmenubuttonprivate.h" -#include "gtktypebuiltins.h" -#include "gtkimage.h" +#include "gtkaccessible.h" #include "gtkactionable.h" +#include "gtkimage.h" +#include "gtkintl.h" #include "gtkmain.h" -#include "gtkaccessible.h" +#include "gtkmenubutton.h" +#include "gtkmenubuttonprivate.h" #include "gtkpopover.h" -#include "a11y/gtkmenubuttonaccessible.h" - #include "gtkprivate.h" -#include "gtkintl.h" +#include "gtkstylecontext.h" +#include "gtktypebuiltins.h" + +#include "a11y/gtkmenubuttonaccessible.h" struct _GtkMenuButtonPrivate { diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c index f516c38d6d..e7213ebe58 100644 --- a/gtk/gtkmenuitem.c +++ b/gtk/gtkmenuitem.c @@ -141,8 +141,12 @@ static void gtk_menu_item_destroy (GtkWidget *widget); static void gtk_menu_item_enter (GtkEventController *controller, double x, double y, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data); static void gtk_menu_item_leave (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data); static void gtk_menu_item_parent_cb (GObject *object, GParamSpec *pspec, @@ -1117,22 +1121,20 @@ static void gtk_menu_item_enter (GtkEventController *controller, double x, double y, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data) { GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data); GtkWidget *menu_shell; - GdkCrossingMode mode; GdkEvent *event; event = gtk_get_current_event (); /* FIXME controller event */ - if (gdk_event_get_crossing_mode ((GdkEvent *)event, &mode)) - { - if (mode == GDK_CROSSING_GTK_GRAB || - mode == GDK_CROSSING_GTK_UNGRAB || - mode == GDK_CROSSING_STATE_CHANGED) - return; - } + if (mode == GDK_CROSSING_GTK_GRAB || + mode == GDK_CROSSING_GTK_UNGRAB || + mode == GDK_CROSSING_STATE_CHANGED) + return; if (gdk_event_get_device ((GdkEvent*) event) == gdk_event_get_source_device ((GdkEvent*) event)) @@ -1147,6 +1149,8 @@ gtk_menu_item_enter (GtkEventController *controller, static void gtk_menu_item_leave (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, gpointer user_data) { GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data); diff --git a/gtk/gtkmessagedialog.c b/gtk/gtkmessagedialog.c index e98a0ffb99..153616831f 100644 --- a/gtk/gtkmessagedialog.c +++ b/gtk/gtkmessagedialog.c @@ -25,18 +25,20 @@ #include "config.h" -#include <string.h> - #include "gtkmessagedialog.h" -#include "gtkdialogprivate.h" + #include "gtkaccessible.h" -#include "gtkbuildable.h" -#include "gtklabel.h" #include "gtkbox.h" +#include "gtkbuildable.h" +#include "gtkdialogprivate.h" #include "gtkintl.h" +#include "gtklabel.h" #include "gtkprivate.h" +#include "gtkstylecontext.h" #include "gtktypebuiltins.h" +#include <string.h> + /** * SECTION:gtkmessagedialog * @Short_description: A convenient message window diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c index 8f32b457d0..a23f9c41b7 100644 --- a/gtk/gtknotebook.c +++ b/gtk/gtknotebook.c @@ -5426,7 +5426,13 @@ gtk_notebook_real_switch_page (GtkNotebook *notebook, child_has_focus = priv->child_has_focus; if (priv->cur_page) - gtk_widget_unset_state_flags (priv->cur_page->tab_widget, GTK_STATE_FLAG_CHECKED); + { + GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (notebook)); + GtkWidget *focus = gtk_root_get_focus (root); + if (focus) + child_has_focus = gtk_widget_is_ancestor (focus, priv->cur_page->child); + gtk_widget_unset_state_flags (priv->cur_page->tab_widget, GTK_STATE_FLAG_CHECKED); + } priv->cur_page = page; gtk_widget_set_state_flags (page->tab_widget, GTK_STATE_FLAG_CHECKED, FALSE); @@ -6634,7 +6640,7 @@ gtk_notebook_set_tab_label (GtkNotebook *notebook, if (priv->menu) gtk_notebook_menu_item_recreate (notebook, list); - g_object_notify (G_OBJECT (child), "tab-label"); + g_object_notify (G_OBJECT (page), "tab-label"); } /** @@ -6764,7 +6770,7 @@ gtk_notebook_set_menu_label (GtkNotebook *notebook, if (priv->menu) gtk_notebook_menu_item_create (notebook, page); - g_object_notify (G_OBJECT (child), "menu-label"); + g_object_notify (G_OBJECT (page), "menu-label"); } /** @@ -6791,7 +6797,6 @@ gtk_notebook_set_menu_label_text (GtkNotebook *notebook, gtk_widget_set_valign (menu_label, GTK_ALIGN_CENTER); } gtk_notebook_set_menu_label (notebook, child, menu_label); - g_object_notify (G_OBJECT (child), "menu-label"); } /** @@ -7031,7 +7036,7 @@ gtk_notebook_set_tab_reorderable (GtkNotebook *notebook, else gtk_style_context_remove_class (gtk_widget_get_style_context (page->tab_widget), "reorderable-page"); - g_object_notify (G_OBJECT (child), "reorderable"); + g_object_notify (G_OBJECT (page), "reorderable"); } } @@ -7114,6 +7119,7 @@ gtk_notebook_set_tab_detachable (GtkNotebook *notebook, gboolean detachable) { GList *list; + GtkNotebookPage *page; g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); g_return_if_fail (GTK_IS_WIDGET (child)); @@ -7121,12 +7127,13 @@ gtk_notebook_set_tab_detachable (GtkNotebook *notebook, list = gtk_notebook_find_child (notebook, child); g_return_if_fail (list != NULL); + page = GTK_NOTEBOOK_PAGE_FROM_LIST (list); detachable = detachable != FALSE; - if (GTK_NOTEBOOK_PAGE_FROM_LIST (list)->detachable != detachable) + if (page->detachable != detachable) { - GTK_NOTEBOOK_PAGE_FROM_LIST (list)->detachable = detachable; - g_object_notify (G_OBJECT (child), "detachable"); + page->detachable = detachable; + g_object_notify (G_OBJECT (page), "detachable"); } } diff --git a/gtk/gtkorientable.c b/gtk/gtkorientable.c index 9612e544e5..70b8e60ff7 100644 --- a/gtk/gtkorientable.c +++ b/gtk/gtkorientable.c @@ -22,7 +22,9 @@ #include "config.h" #include "gtkorientableprivate.h" + #include "gtkprivate.h" +#include "gtkstylecontext.h" #include "gtktypebuiltins.h" #include "gtkintl.h" diff --git a/gtk/gtkoverlay.c b/gtk/gtkoverlay.c index 643ca00d2e..0b3c8932c3 100644 --- a/gtk/gtkoverlay.c +++ b/gtk/gtkoverlay.c @@ -21,14 +21,15 @@ #include "config.h" #include "gtkoverlay.h" + #include "gtkbuildable.h" -#include "gtkscrolledwindow.h" -#include "gtkwidgetprivate.h" +#include "gtkintl.h" #include "gtkmarshalers.h" -#include "gtksnapshot.h" - #include "gtkprivate.h" -#include "gtkintl.h" +#include "gtkscrolledwindow.h" +#include "gtksnapshot.h" +#include "gtkstylecontext.h" +#include "gtkwidgetprivate.h" /** * SECTION:gtkoverlay diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c index 9fc18c9667..cf2e39a26e 100644 --- a/gtk/gtkpaned.c +++ b/gtk/gtkpaned.c @@ -35,7 +35,6 @@ #include "gtkgesturesingle.h" #include "gtkgizmoprivate.h" #include "gtkintl.h" -#include "gtkmain.h" #include "gtkmarshalers.h" #include "gtkorientableprivate.h" #include "gtkprivate.h" @@ -768,7 +767,6 @@ gesture_drag_begin_cb (GtkGestureDrag *gesture, priv->drag_pos = start_y - handle_area.origin.y; priv->panning = TRUE; - gtk_grab_add (GTK_WIDGET (paned)); gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); @@ -804,7 +802,6 @@ gesture_drag_end_cb (GtkGestureDrag *gesture, if (!priv->panning) gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED); - gtk_grab_remove (GTK_WIDGET (paned)); priv->panning = FALSE; } @@ -1185,22 +1182,6 @@ flip_child (int width, } static void -gtk_paned_set_child_visible (GtkPaned *paned, - guint id, - gboolean visible) -{ - GtkPanedPrivate *priv = gtk_paned_get_instance_private (paned); - GtkWidget *child; - - child = id == CHILD1 ? priv->child1 : priv->child2; - - if (child == NULL) - return; - - gtk_widget_set_child_visible (child, visible); -} - -static void gtk_paned_size_allocate (GtkWidget *widget, int width, int height, @@ -1316,6 +1297,8 @@ gtk_paned_size_allocate (GtkWidget *widget, child2_allocation.height = child2_height; } + gtk_widget_set_child_visible (priv->handle_widget, TRUE); + gtk_widget_size_allocate (priv->handle_widget, &handle_allocation, -1); gtk_widget_size_allocate (priv->child1, &child1_allocation, -1); gtk_widget_size_allocate (priv->child2, &child2_allocation, -1); @@ -1324,26 +1307,21 @@ gtk_paned_size_allocate (GtkWidget *widget, { if (priv->child1 && gtk_widget_get_visible (priv->child1)) { - gtk_paned_set_child_visible (paned, CHILD1, TRUE); - gtk_paned_set_child_visible (paned, CHILD2, FALSE); + gtk_widget_set_child_visible (priv->child1, TRUE); gtk_widget_size_allocate (priv->child1, &(GtkAllocation) {0, 0, width, height}, -1); } else if (priv->child2 && gtk_widget_get_visible (priv->child2)) { - gtk_paned_set_child_visible (paned, CHILD1, FALSE); - gtk_paned_set_child_visible (paned, CHILD2, TRUE); + gtk_widget_set_child_visible (priv->child2, TRUE); gtk_widget_size_allocate (priv->child2, &(GtkAllocation) {0, 0, width, height}, -1); } - else - { - gtk_paned_set_child_visible (paned, CHILD1, FALSE); - gtk_paned_set_child_visible (paned, CHILD2, FALSE); - } + + gtk_widget_set_child_visible (priv->handle_widget, FALSE); } } @@ -1813,8 +1791,8 @@ gtk_paned_calc_position (GtkPaned *paned, &priv->min_position, &priv->max_position, &priv->child1_size); - gtk_paned_set_child_visible (paned, CHILD1, priv->child1_size != 0); - gtk_paned_set_child_visible (paned, CHILD2, priv->child1_size != allocation); + gtk_widget_set_child_visible (priv->child1, priv->child1_size != 0); + gtk_widget_set_child_visible (priv->child2, priv->child1_size != allocation); g_object_freeze_notify (G_OBJECT (paned)); if (priv->child1_size != old_position) @@ -2256,10 +2234,8 @@ gtk_paned_restore_focus (GtkPaned *paned) if (!gtk_widget_child_focus (GTK_WIDGET (paned), GTK_DIR_TAB_FORWARD)) { - GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned)); - - if (GTK_IS_WINDOW (toplevel)) - gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); + GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (paned)); + gtk_root_set_focus (root, NULL); } } @@ -2364,7 +2340,6 @@ gtk_paned_cycle_handle_focus (GtkPaned *paned, { GtkPaned *focus; GtkPaned *first; - GtkWidget *toplevel; GtkWidget *focus_child; gtk_paned_find_neighbours (paned, &next, &prev); @@ -2410,10 +2385,7 @@ gtk_paned_cycle_handle_focus (GtkPaned *paned, first = next; } - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned)); - - if (GTK_IS_WINDOW (toplevel)) - gtk_paned_set_saved_focus (focus, gtk_window_get_focus (GTK_WINDOW (toplevel))); + gtk_paned_set_saved_focus (focus, gtk_root_get_focus (gtk_widget_get_root (GTK_WIDGET (paned)))); gtk_paned_set_first_paned (focus, first); priv->original_position = gtk_paned_get_position (focus); diff --git a/gtk/gtkpasswordentry.c b/gtk/gtkpasswordentry.c index 8b2a022e88..7a4019115a 100644 --- a/gtk/gtkpasswordentry.c +++ b/gtk/gtkpasswordentry.c @@ -26,9 +26,12 @@ #include "gtkbindings.h" #include "gtktextprivate.h" #include "gtkeditable.h" +#include "gtkgesturemultipress.h" #include "gtkbox.h" #include "gtkimage.h" +#include "gtkcheckmenuitem.h" #include "gtkintl.h" +#include "gtkprivate.h" #include "gtkmarshalers.h" #include "gtkstylecontext.h" #include "gtkeventcontrollerkey.h" @@ -40,13 +43,14 @@ * @Short_description: An entry for secrets * @Title: GtkPasswordEntry * - * #GtkPasswordEntry is entry that has been tailored for - * entering secrets. It does not show its contents in clear text, - * does not allow to copy it to the clipboard, and it shows a - * warning when Caps-Lock is engaged. + * #GtkPasswordEntry is entry that has been tailored for entering secrets. + * It does not show its contents in clear text, does not allow to copy it + * to the clipboard, and it shows a warning when Caps Lock is engaged. * - * GtkPasswordEntry provides no API of its own and should be used - * with the #GtkEditable API. + * Optionally, it can offer a way to reveal the contents in clear text. + * + * GtkPasswordEntry provides only minimal API and should be used with the + * #GtkEditable API. */ typedef struct { @@ -54,8 +58,18 @@ typedef struct { GtkWidget *entry; GtkWidget *icon; GdkKeymap *keymap; + GtkWidget *peek_icon; } GtkPasswordEntryPrivate; +enum { + PROP_PLACEHOLDER_TEXT = 1, + PROP_ACTIVATES_DEFAULT, + PROP_SHOW_PEEK_ICON, + NUM_PROPERTIES +}; + +static GParamSpec *props[NUM_PROPERTIES] = { NULL, }; + static void gtk_password_entry_editable_init (GtkEditableInterface *iface); G_DEFINE_TYPE_WITH_CODE (GtkPasswordEntry, gtk_password_entry, GTK_TYPE_WIDGET, @@ -71,7 +85,8 @@ keymap_state_changed (GdkKeymap *keymap, if (gtk_editable_get_editable (GTK_EDITABLE (entry)) && gtk_widget_has_focus (priv->entry) && - gdk_keymap_get_caps_lock_state (priv->keymap)) + gdk_keymap_get_caps_lock_state (priv->keymap) && + !priv->peek_icon) gtk_widget_show (priv->icon); else gtk_widget_hide (priv->icon); @@ -88,13 +103,53 @@ focus_changed (GtkWidget *widget) } static void +gtk_password_entry_toggle_peek (GtkPasswordEntry *entry) +{ + GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); + + if (gtk_text_get_visibility (GTK_TEXT (priv->entry))) + { + gtk_text_set_visibility (GTK_TEXT (priv->entry), FALSE); + gtk_image_set_from_icon_name (GTK_IMAGE (priv->peek_icon), "eye-not-looking-symbolic"); + gtk_widget_set_tooltip_text (priv->peek_icon, _("Show text")); + } + else + { + gtk_text_set_visibility (GTK_TEXT (priv->entry), TRUE); + gtk_image_set_from_icon_name (GTK_IMAGE (priv->peek_icon), "eye-open-negative-filled-symbolic"); + gtk_widget_set_tooltip_text (priv->peek_icon, _("Hide text")); + } +} + +static void +populate_popup (GtkText *text, + GtkWidget *popup, + GtkPasswordEntry *entry) +{ + GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); + + if (priv->peek_icon != NULL) + { + GtkWidget *item; + + item = gtk_check_menu_item_new_with_mnemonic (_("_Show text")); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), + gtk_text_get_visibility (text)); + g_signal_connect_swapped (item, "activate", + G_CALLBACK (gtk_password_entry_toggle_peek), entry); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); + } +} + +static void gtk_password_entry_init (GtkPasswordEntry *entry) { GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); gtk_widget_set_has_surface (GTK_WIDGET (entry), FALSE); - priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); gtk_widget_set_hexpand (priv->box, FALSE); gtk_widget_set_vexpand (priv->box, FALSE); gtk_widget_set_parent (priv->box, GTK_WIDGET (entry)); @@ -106,9 +161,12 @@ gtk_password_entry_init (GtkPasswordEntry *entry) gtk_container_add (GTK_CONTAINER (priv->box), priv->entry); gtk_editable_init_delegate (GTK_EDITABLE (entry)); g_signal_connect_swapped (priv->entry, "notify::has-focus", G_CALLBACK (focus_changed), entry); + g_signal_connect (priv->entry, "populate-popup", G_CALLBACK (populate_popup), entry); - priv->icon = gtk_image_new_from_icon_name ("dialog-warning-symbolic"); + priv->icon = gtk_image_new_from_icon_name ("caps-lock-symbolic"); gtk_widget_set_tooltip_text (priv->icon, _("Caps Lock is on")); + gtk_style_context_add_class (gtk_widget_get_style_context (priv->icon), "caps-lock-indicator"); + gtk_widget_set_cursor (priv->icon, gtk_widget_get_cursor (priv->entry)); gtk_container_add (GTK_CONTAINER (priv->box), priv->icon); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (entry)), I_("password")); @@ -124,6 +182,7 @@ gtk_password_entry_realize (GtkWidget *widget) priv->keymap = gdk_display_get_keymap (gtk_widget_get_display (widget)); g_signal_connect (priv->keymap, "state-changed", G_CALLBACK (keymap_state_changed), entry); + keymap_state_changed (priv->keymap, widget); } static void @@ -140,6 +199,7 @@ gtk_password_entry_dispose (GObject *object) g_clear_pointer (&priv->entry, gtk_widget_unparent); g_clear_pointer (&priv->icon, gtk_widget_unparent); + g_clear_pointer (&priv->peek_icon, gtk_widget_unparent); g_clear_pointer (&priv->box, gtk_widget_unparent); G_OBJECT_CLASS (gtk_password_entry_parent_class)->dispose (object); @@ -157,10 +217,34 @@ gtk_password_entry_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { + GtkPasswordEntry *entry = GTK_PASSWORD_ENTRY (object); + GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); + if (gtk_editable_delegate_set_property (object, prop_id, value, pspec)) return; - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + switch (prop_id) + { + case PROP_PLACEHOLDER_TEXT: + gtk_text_set_placeholder_text (GTK_TEXT (priv->entry), g_value_get_string (value)); + break; + + case PROP_ACTIVATES_DEFAULT: + if (gtk_text_get_activates_default (GTK_TEXT (priv->entry)) != g_value_get_boolean (value)) + { + gtk_text_set_activates_default (GTK_TEXT (priv->entry), g_value_get_boolean (value)); + g_object_notify_by_pspec (object, pspec); + } + break; + + case PROP_SHOW_PEEK_ICON: + gtk_password_entry_set_show_peek_icon (entry, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void @@ -169,10 +253,29 @@ gtk_password_entry_get_property (GObject *object, GValue *value, GParamSpec *pspec) { + GtkPasswordEntry *entry = GTK_PASSWORD_ENTRY (object); + GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); + if (gtk_editable_delegate_get_property (object, prop_id, value, pspec)) return; - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + switch (prop_id) + { + case PROP_PLACEHOLDER_TEXT: + g_value_set_string (value, gtk_text_get_placeholder_text (GTK_TEXT (priv->entry))); + break; + + case PROP_ACTIVATES_DEFAULT: + g_value_set_boolean (value, gtk_text_get_activates_default (GTK_TEXT (priv->entry))); + + case PROP_SHOW_PEEK_ICON: + g_value_set_boolean (value, gtk_password_entry_get_show_peek_icon (entry)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void @@ -226,6 +329,18 @@ gtk_password_entry_grab_focus (GtkWidget *widget) gtk_widget_grab_focus (priv->entry); } +static gboolean +gtk_password_entry_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling) +{ + GtkPasswordEntry *entry = GTK_PASSWORD_ENTRY (widget); + GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); + + gtk_widget_grab_focus (priv->entry); + + return TRUE; +} + static void gtk_password_entry_class_init (GtkPasswordEntryClass *klass) { @@ -242,8 +357,31 @@ gtk_password_entry_class_init (GtkPasswordEntryClass *klass) widget_class->size_allocate = gtk_password_entry_size_allocate; widget_class->get_accessible = gtk_password_entry_get_accessible; widget_class->grab_focus = gtk_password_entry_grab_focus; + widget_class->mnemonic_activate = gtk_password_entry_mnemonic_activate; - gtk_editable_install_properties (object_class, 1); + props[PROP_PLACEHOLDER_TEXT] = + g_param_spec_string ("placeholder-text", + P_("Placeholder text"), + P_("Show text in the entry when it’s empty and unfocused"), + NULL, + GTK_PARAM_READWRITE); + + props[PROP_ACTIVATES_DEFAULT] = + g_param_spec_boolean ("activates-default", + P_("Activates default"), + P_("Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed"), + FALSE, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + + props[PROP_SHOW_PEEK_ICON] = + g_param_spec_boolean ("show-peek-icon", + P_("Show Peek Icon"), + P_("Whether to show an icon for revealing the content"), + FALSE, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties (object_class, NUM_PROPERTIES, props); + gtk_editable_install_properties (object_class, NUM_PROPERTIES); gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE); gtk_widget_class_set_css_name (widget_class, I_("entry")); @@ -276,3 +414,67 @@ gtk_password_entry_new (void) { return GTK_WIDGET (g_object_new (GTK_TYPE_PASSWORD_ENTRY, NULL)); } + +/** + * gtk_password_entry_set_show_peek_icon: + * @entry: a #GtkPasswordEntry + * show_peek_icon: whether to show the peek icon + * + * Sets whether the entry should have a clickable icon + * to show the contents of the entry in clear text. + * + * Setting this to %FALSE also hides the text again. + */ +void +gtk_password_entry_set_show_peek_icon (GtkPasswordEntry *entry, + gboolean show_peek_icon) +{ + GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); + + g_return_if_fail (GTK_IS_PASSWORD_ENTRY (entry)); + + if (show_peek_icon == (priv->peek_icon != NULL)) + return; + + if (show_peek_icon) + { + GtkGesture *press; + + priv->peek_icon = gtk_image_new_from_icon_name ("eye-not-looking-symbolic"); + gtk_widget_set_tooltip_text (priv->peek_icon, _("Show text")); + gtk_container_add (GTK_CONTAINER (priv->box), priv->peek_icon); + + press = gtk_gesture_multi_press_new (); + g_signal_connect_swapped (press, "released", + G_CALLBACK (gtk_password_entry_toggle_peek), entry); + gtk_widget_add_controller (priv->peek_icon, GTK_EVENT_CONTROLLER (press)); + } + else + { + g_clear_pointer (&priv->peek_icon, gtk_widget_unparent); + gtk_text_set_visibility (GTK_TEXT (priv->entry), FALSE); + } + + keymap_state_changed (priv->keymap, GTK_WIDGET (entry)); + + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_SHOW_PEEK_ICON]); +} + +/** + * gtk_password_entry_get_show_peek_icon: + * @entry: a #GtkPasswordEntry + * + * Returns whether the entry is showing a clickable icon + * to reveal the contents of the entry in clear text. + * + * Returns: %TRUE if an icon is shown + */ +gboolean +gtk_password_entry_get_show_peek_icon (GtkPasswordEntry *entry) +{ + GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry); + + g_return_val_if_fail (GTK_IS_PASSWORD_ENTRY (entry), FALSE); + + return priv->peek_icon != NULL; +} diff --git a/gtk/gtkpasswordentry.h b/gtk/gtkpasswordentry.h index 66de3ee961..2527c58ca2 100644 --- a/gtk/gtkpasswordentry.h +++ b/gtk/gtkpasswordentry.h @@ -55,6 +55,12 @@ GType gtk_password_entry_get_type (void) G_GNUC_CONST; GDK_AVAILABLE_IN_ALL GtkWidget * gtk_password_entry_new (void); +GDK_AVAILABLE_IN_ALL +void gtk_password_entry_set_show_peek_icon (GtkPasswordEntry *entry, + gboolean show_peek_icon); +GDK_AVAILABLE_IN_ALL +gboolean gtk_password_entry_get_show_peek_icon (GtkPasswordEntry *entry); + G_END_DECLS #endif /* __GTK_PASSWORD_ENTRY_H__ */ diff --git a/gtk/gtkplacesview.c b/gtk/gtkplacesview.c index bb03ef9d01..dabb486046 100644 --- a/gtk/gtkplacesview.c +++ b/gtk/gtkplacesview.c @@ -1766,7 +1766,7 @@ on_key_press_event (GtkEventController *controller, if (!toplevel) return FALSE; - focus_widget = gtk_window_get_focus (toplevel); + focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel)); if (!GTK_IS_PLACES_VIEW_ROW (focus_widget)) return FALSE; diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c index cfd697a234..c77ddc3f25 100644 --- a/gtk/gtkpopover.c +++ b/gtk/gtkpopover.c @@ -614,10 +614,11 @@ window_active_changed (GtkWindow *window, static void window_set_focus (GtkWindow *window, - GtkWidget *widget, + GParamSpec *pspec, GtkPopover *popover) { GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); + GtkWidget *widget = gtk_root_get_focus (GTK_ROOT (window)); if (!priv->modal || !widget || !gtk_widget_is_drawable (GTK_WIDGET (popover))) return; @@ -673,7 +674,7 @@ gtk_popover_apply_modality (GtkPopover *popover, g_signal_connect (priv->window, "notify::is-active", G_CALLBACK (window_active_changed), popover); - g_signal_connect (priv->window, "set-focus", + g_signal_connect (priv->window, "notify::focus-widget", G_CALLBACK (window_set_focus), popover); } else diff --git a/gtk/gtkrendericon.c b/gtk/gtkrendericon.c index df855a853c..aa2368b4ab 100644 --- a/gtk/gtkrendericon.c +++ b/gtk/gtkrendericon.c @@ -29,7 +29,7 @@ #include "gtkcsstransformvalueprivate.h" #include "gtkiconthemeprivate.h" #include "gtksnapshot.h" -#include "gtktransform.h" +#include "gsktransform.h" #include <math.h> @@ -41,7 +41,7 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style, GtkCssImageBuiltinType builtin_type) { const GtkCssValue *shadows_value, *transform_value, *filter_value; - GtkTransform *transform; + GskTransform *transform; GtkCssImage *image; gboolean has_shadow; @@ -92,7 +92,7 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style, gtk_snapshot_pop (snapshot); - gtk_transform_unref (transform); + gsk_transform_unref (transform); } void @@ -104,7 +104,7 @@ gtk_css_style_snapshot_icon_paintable (GtkCssStyle *style, gboolean recolor) { const GtkCssValue *shadows_value, *transform_value, *filter_value; - GtkTransform *transform; + GskTransform *transform; gboolean has_shadow; g_return_if_fail (GTK_IS_CSS_STYLE (style)); @@ -172,5 +172,5 @@ gtk_css_style_snapshot_icon_paintable (GtkCssStyle *style, transparent: gtk_css_filter_value_pop_snapshot (filter_value, snapshot); - gtk_transform_unref (transform); + gsk_transform_unref (transform); } diff --git a/gtk/gtkrevealer.c b/gtk/gtkrevealer.c index 3f521baa4c..6dc84603c8 100644 --- a/gtk/gtkrevealer.c +++ b/gtk/gtkrevealer.c @@ -66,6 +66,10 @@ * @GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT: Slide in from the right * @GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP: Slide in from the bottom * @GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN: Slide in from the top + * @GTK_REVEALER_TRANSITION_TYPE_SWING_RIGHT: Floop in from the left + * @GTK_REVEALER_TRANSITION_TYPE_SWING_LEFT: Floop in from the right + * @GTK_REVEALER_TRANSITION_TYPE_SWING_UP: Floop in from the bottom + * @GTK_REVEALER_TRANSITION_TYPE_SWING_DOWN: Floop in from the top * * These enumeration values describe the possible transitions * when the child of a #GtkRevealer widget is shown or hidden. @@ -287,6 +291,10 @@ effective_transition (GtkRevealer *revealer) return GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT; else if (priv->transition_type == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT) return GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT; + if (priv->transition_type == GTK_REVEALER_TRANSITION_TYPE_SWING_LEFT) + return GTK_REVEALER_TRANSITION_TYPE_SWING_RIGHT; + else if (priv->transition_type == GTK_REVEALER_TRANSITION_TYPE_SWING_RIGHT) + return GTK_REVEALER_TRANSITION_TYPE_SWING_LEFT; } return priv->transition_type; @@ -328,6 +336,20 @@ get_child_size_scale (GtkRevealer *revealer, else return 1.0; + case GTK_REVEALER_TRANSITION_TYPE_SWING_RIGHT: + case GTK_REVEALER_TRANSITION_TYPE_SWING_LEFT: + if (orientation == GTK_ORIENTATION_HORIZONTAL) + return sin (G_PI * priv->current_pos / 2); + else + return 1.0; + + case GTK_REVEALER_TRANSITION_TYPE_SWING_DOWN: + case GTK_REVEALER_TRANSITION_TYPE_SWING_UP: + if (orientation == GTK_ORIENTATION_VERTICAL) + return sin (G_PI * priv->current_pos / 2); + else + return 1.0; + case GTK_REVEALER_TRANSITION_TYPE_NONE: case GTK_REVEALER_TRANSITION_TYPE_CROSSFADE: default: @@ -342,38 +364,91 @@ gtk_revealer_real_size_allocate (GtkWidget *widget, int baseline) { GtkRevealer *revealer = GTK_REVEALER (widget); + GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer); GtkWidget *child; + GskTransform *transform; + double hscale, vscale; + int child_width, child_height; child = gtk_bin_get_child (GTK_BIN (revealer)); - if (child != NULL && gtk_widget_get_visible (child)) + if (child == NULL || !gtk_widget_get_visible (child)) + return; + + if (priv->current_pos >= 1.0) { - GtkAllocation child_allocation = {0, 0, width, height}; - double hscale, vscale; - - hscale = get_child_size_scale (revealer, GTK_ORIENTATION_HORIZONTAL); - vscale = get_child_size_scale (revealer, GTK_ORIENTATION_VERTICAL); - - if (hscale <= 0 || vscale <= 0) - { - /* don't allocate anything, the child is invisible and the numbers - * don't make sense. */ - return; - } - else if (hscale < 1.0) - { - g_assert (vscale == 1.0); - child_allocation.width = MIN (G_MAXINT, ceil (width / hscale)); - if (effective_transition (revealer) == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT) - child_allocation.x = width - child_allocation.width; - } - else if (vscale < 1.0) - { - child_allocation.height = MIN (G_MAXINT, ceil (height / vscale)); - if (effective_transition (revealer) == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN) - child_allocation.y = height - child_allocation.height; - } - gtk_widget_size_allocate (child, &child_allocation, -1); + gtk_widget_allocate (child, width, height, baseline, NULL); + return; } + + child_width = width; + child_height = height; + hscale = get_child_size_scale (revealer, GTK_ORIENTATION_HORIZONTAL); + vscale = get_child_size_scale (revealer, GTK_ORIENTATION_VERTICAL); + if (hscale <= 0 || vscale <= 0) + { + /* don't allocate anything, the child is invisible and the numbers + * don't make sense. */ + return; + } + + if (hscale < 1.0) + { + g_assert (vscale == 1.0); + child_width = MIN (G_MAXINT, ceil (width / hscale)); + } + else if (vscale < 1.0) + { + child_height = MIN (G_MAXINT, ceil (height / vscale)); + } + + transform = NULL; + switch (effective_transition (revealer)) + { + case GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT: + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (width - child_width, 0)); + break; + + case GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN: + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (0, height - child_height)); + + case GTK_REVEALER_TRANSITION_TYPE_SWING_LEFT: + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (width, height / 2)); + transform = gsk_transform_perspective (transform, 2 * MAX (width, height)); + transform = gsk_transform_rotate_3d (transform, -90 * (1.0 - priv->current_pos), graphene_vec3_y_axis ()); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (- child_width, - child_height / 2)); + break; + + case GTK_REVEALER_TRANSITION_TYPE_SWING_RIGHT: + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (0, height / 2)); + transform = gsk_transform_perspective (transform, 2 * MAX (width, height)); + transform = gsk_transform_rotate_3d (transform, 90 * (1.0 - priv->current_pos), graphene_vec3_y_axis ()); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (0, - child_height / 2)); + break; + + case GTK_REVEALER_TRANSITION_TYPE_SWING_DOWN: + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (width / 2, 0)); + transform = gsk_transform_perspective (transform, 2 * MAX (width, height)); + transform = gsk_transform_rotate_3d (transform, -90 * (1.0 - priv->current_pos), graphene_vec3_x_axis ()); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (- child_width / 2, 0)); + break; + + case GTK_REVEALER_TRANSITION_TYPE_SWING_UP: + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (width / 2, height)); + transform = gsk_transform_perspective (transform, 2 * MAX (width, height)); + transform = gsk_transform_rotate_3d (transform, 90 * (1.0 - priv->current_pos), graphene_vec3_x_axis ()); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (- child_width / 2, - child_height)); + break; + + case GTK_REVEALER_TRANSITION_TYPE_NONE: + case GTK_REVEALER_TRANSITION_TYPE_CROSSFADE: + case GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT: + case GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP: + default: + break; + } + + gtk_widget_allocate (child, child_width, child_height, -1, transform); + gsk_transform_unref (transform); } static void diff --git a/gtk/gtkrevealer.h b/gtk/gtkrevealer.h index 4faffabfea..8fad1b4f14 100644 --- a/gtk/gtkrevealer.h +++ b/gtk/gtkrevealer.h @@ -43,7 +43,11 @@ typedef enum { GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT, GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT, GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP, - GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN + GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN, + GTK_REVEALER_TRANSITION_TYPE_SWING_RIGHT, + GTK_REVEALER_TRANSITION_TYPE_SWING_LEFT, + GTK_REVEALER_TRANSITION_TYPE_SWING_UP, + GTK_REVEALER_TRANSITION_TYPE_SWING_DOWN } GtkRevealerTransitionType; struct _GtkRevealer { diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c index ad93f8791a..249d7405b1 100644 --- a/gtk/gtkroot.c +++ b/gtk/gtkroot.c @@ -21,6 +21,8 @@ #include "gtkrootprivate.h" #include "gdk/gdk-private.h" +#include "gtkprivate.h" +#include "gtkintl.h" /** * SECTION:gtkroot @@ -65,6 +67,13 @@ gtk_root_default_init (GtkRootInterface *iface) iface->get_display = gtk_root_default_get_display; iface->get_renderer = gtk_root_default_get_renderer; iface->get_surface_transform = gtk_root_default_get_surface_transform; + + g_object_interface_install_property (iface, + g_param_spec_object ("focus-widget", + P_("Focus widget"), + P_("The focus widget"), + GTK_TYPE_WIDGET, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); } GdkDisplay * @@ -124,3 +133,63 @@ gtk_root_get_for_surface (GdkSurface *surface) return NULL; } + +/** + * gtk_root_set_focus: + * @self: a #GtkRoot + * @focus: (allow-none): widget to be the new focus widget, or %NULL + * to unset the focus widget + * + * If @focus is not the current focus widget, and is focusable, sets + * it as the focus widget for the root. If @focus is %NULL, unsets + * the focus widget for the root. + * + * To set the focus to a particular widget in the root, it is usually + * more convenient to use gtk_widget_grab_focus() instead of this function. + */ +void +gtk_root_set_focus (GtkRoot *self, + GtkWidget *focus) +{ + g_return_if_fail (GTK_IS_ROOT (self)); + g_return_if_fail (focus == NULL || GTK_IS_WIDGET (focus)); + + g_object_set (self, "focus-widget", focus, NULL); +} + +/** + * gtk_root_get_focus: + * @self: a #GtkRoot + * + * Retrieves the current focused widget within the root. + * + * Note that this is the widget that would have the focus + * if the root is active; if the root is not focused then + * `gtk_widget_has_focus (widget)` will be %FALSE for the + * widget. + * + * Returns: (nullable) (transfer none): the currently focused widget, + * or %NULL if there is none. + */ +GtkWidget * +gtk_root_get_focus (GtkRoot *self) +{ + GtkWidget *focus; + + g_return_val_if_fail (GTK_IS_ROOT (self), NULL); + + g_object_get (self, "focus-widget", &focus, NULL); + + if (focus) + g_object_unref (focus); + + return focus; +} + +guint +gtk_root_install_properties (GObjectClass *object_class, + guint first_prop) +{ + g_object_class_override_property (object_class, first_prop + GTK_ROOT_PROP_FOCUS_WIDGET, "focus-widget"); + return GTK_ROOT_NUM_PROPERTIES; +} diff --git a/gtk/gtkroot.h b/gtk/gtkroot.h index 45e777ba68..4c7ae89e37 100644 --- a/gtk/gtkroot.h +++ b/gtk/gtkroot.h @@ -56,6 +56,12 @@ struct _GtkRootInterface GDK_AVAILABLE_IN_ALL GtkWidget * gtk_root_get_for_surface (GdkSurface *surface); +GDK_AVAILABLE_IN_ALL +void gtk_root_set_focus (GtkRoot *self, + GtkWidget *focus); +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_root_get_focus (GtkRoot *self); + G_END_DECLS #endif /* __GTK_ROOT_H__ */ diff --git a/gtk/gtkrootprivate.h b/gtk/gtkrootprivate.h index 07ddc380e5..357bc6441f 100644 --- a/gtk/gtkrootprivate.h +++ b/gtk/gtkrootprivate.h @@ -11,6 +11,14 @@ GskRenderer * gtk_root_get_renderer (GtkRoot void gtk_root_get_surface_transform (GtkRoot *self, int *x, int *y); +enum { + GTK_ROOT_PROP_FOCUS_WIDGET, + GTK_ROOT_NUM_PROPERTIES +} GtkRootProperties; + +guint gtk_root_install_properties (GObjectClass *object_class, + guint first_prop); + G_END_DECLS #endif /* __GTK_ROOT_PRIVATE_H__ */ diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c index ea1b402c4b..2ba312e741 100644 --- a/gtk/gtkscrolledwindow.c +++ b/gtk/gtkscrolledwindow.c @@ -423,6 +423,8 @@ add_tab_bindings (GtkBindingSet *binding_set, static void motion_controller_leave (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, GtkScrolledWindow *scrolled_window) { GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window); diff --git a/gtk/gtksearchbar.c b/gtk/gtksearchbar.c index 7c0222ef60..e774955d3f 100644 --- a/gtk/gtksearchbar.c +++ b/gtk/gtksearchbar.c @@ -32,12 +32,13 @@ #include "gtkbutton.h" #include "gtkcenterbox.h" #include "gtkentryprivate.h" +#include "gtkeventcontrollerkey.h" #include "gtkintl.h" #include "gtkprivate.h" #include "gtkrevealer.h" #include "gtksearchentryprivate.h" #include "gtksnapshot.h" -#include "gtkeventcontrollerkey.h" +#include "gtkstylecontext.h" /** * SECTION:gtksearchbar diff --git a/gtk/gtksearchentry.c b/gtk/gtksearchentry.c index a227956e93..45ace300e7 100644 --- a/gtk/gtksearchentry.c +++ b/gtk/gtksearchentry.c @@ -172,7 +172,11 @@ gtk_search_entry_set_property (GObject *object, break; case PROP_ACTIVATES_DEFAULT: - gtk_text_set_activates_default (GTK_TEXT (priv->entry), g_value_get_boolean (value)); + if (gtk_text_get_activates_default (GTK_TEXT (priv->entry)) != g_value_get_boolean (value)) + { + gtk_text_set_activates_default (GTK_TEXT (priv->entry), g_value_get_boolean (value)); + g_object_notify_by_pspec (object, pspec); + } break; default: @@ -258,6 +262,18 @@ gtk_search_entry_grab_focus (GtkWidget *widget) gtk_text_grab_focus_without_selecting (GTK_TEXT (priv->entry)); } +static gboolean +gtk_search_entry_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling) +{ + GtkSearchEntry *entry = GTK_SEARCH_ENTRY (widget); + GtkSearchEntryPrivate *priv = gtk_search_entry_get_instance_private (entry); + + gtk_widget_grab_focus (priv->entry); + + return TRUE; +} + static void gtk_search_entry_class_init (GtkSearchEntryClass *klass) { @@ -273,6 +289,7 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass) widget_class->size_allocate = gtk_search_entry_size_allocate; widget_class->get_accessible = gtk_search_entry_get_accessible; widget_class->grab_focus = gtk_search_entry_grab_focus; + widget_class->mnemonic_activate = gtk_search_entry_mnemonic_activate; klass->stop_search = gtk_search_entry_stop_search; @@ -281,7 +298,7 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass) P_("Placeholder text"), P_("Show text in the entry when it’s empty and unfocused"), NULL, - GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + GTK_PARAM_READWRITE); props[PROP_ACTIVATES_DEFAULT] = g_param_spec_boolean ("activates-default", diff --git a/gtk/gtkseparatortoolitem.c b/gtk/gtkseparatortoolitem.c index 3cdc517c19..86cb818fd2 100644 --- a/gtk/gtkseparatortoolitem.c +++ b/gtk/gtkseparatortoolitem.c @@ -18,11 +18,14 @@ */ #include "config.h" -#include "gtkseparatormenuitem.h" + #include "gtkseparatortoolitem.h" + #include "gtkintl.h" -#include "gtktoolbarprivate.h" #include "gtkprivate.h" +#include "gtkseparatormenuitem.h" +#include "gtkstylecontext.h" +#include "gtktoolbarprivate.h" #include "gtkwidgetprivate.h" /** diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 0b70835bbf..354e70a083 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -18,22 +18,23 @@ #include "config.h" -#include <string.h> - -#include "gtksettings.h" - #include "gtksettingsprivate.h" -#include "gtkintl.h" -#include "gtkwidget.h" -#include "gtkprivate.h" + #include "gtkcssproviderprivate.h" #include "gtkhslaprivate.h" +#include "gtkintl.h" +#include "gtkprivate.h" +#include "gtkscrolledwindow.h" +#include "gtkstylecontext.h" #include "gtkstyleproviderprivate.h" #include "gtktypebuiltins.h" #include "gtkversion.h" -#include "gtkscrolledwindow.h" +#include "gtkwidget.h" + #include "gdk/gdk-private.h" +#include <string.h> + #ifdef GDK_WINDOWING_X11 #include "x11/gdkx.h" #include <pango/pangofc-fontmap.h> diff --git a/gtk/gtkshortcutsshortcut.c b/gtk/gtkshortcutsshortcut.c index 3e923a34e1..1cbd8e0bf8 100644 --- a/gtk/gtkshortcutsshortcut.c +++ b/gtk/gtkshortcutsshortcut.c @@ -27,6 +27,7 @@ #include "gtkshortcutlabel.h" #include "gtkshortcutswindowprivate.h" #include "gtksizegroup.h" +#include "gtkstylecontext.h" #include "gtktypebuiltins.h" /** diff --git a/gtk/gtkshortcutswindow.c b/gtk/gtkshortcutswindow.c index 77f7d297e7..1728736541 100644 --- a/gtk/gtkshortcutswindow.c +++ b/gtk/gtkshortcutswindow.c @@ -22,11 +22,13 @@ #include "gtkbindings.h" #include "gtkbox.h" +#include "gtkeventcontrollerkey.h" #include "gtkgrid.h" #include "gtkheaderbar.h" #include "gtkintl.h" #include "gtklabel.h" #include "gtklistbox.h" +#include "gtkmain.h" #include "gtkmenubutton.h" #include "gtkpopover.h" #include "gtkprivate.h" @@ -38,13 +40,10 @@ #include "gtkshortcutsshortcutprivate.h" #include "gtksizegroup.h" #include "gtkstack.h" +#include "gtkstylecontext.h" #include "gtktogglebutton.h" #include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" -#include "gtkeventcontrollerkey.h" -#include "gtkprivate.h" -#include "gtkintl.h" -#include "gtkmain.h" /** * SECTION:gtkshortcutswindow diff --git a/gtk/gtksingleselection.c b/gtk/gtksingleselection.c index ce25eb91d1..5f9517fbed 100644 --- a/gtk/gtksingleselection.c +++ b/gtk/gtksingleselection.c @@ -451,10 +451,15 @@ gtk_single_selection_class_init (GtkSingleSelectionClass *klass) G_TYPE_OBJECT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** + * GtkSingleSelection:model: + * + * The model being managed + */ properties[PROP_MODEL] = g_param_spec_object ("model", P_("The model"), - P_("The model"), + P_("The model being managed"), G_TYPE_LIST_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); @@ -548,7 +553,9 @@ gtk_single_selection_set_selected (GtkSingleSelection *self, gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), position, old_position - position + 1); else gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), old_position, position - old_position + 1); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]); } /** diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index 0f2973d4a3..dde973a867 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -28,7 +28,7 @@ #include "gtkrendericonprivate.h" #include "gtkrendernodepaintableprivate.h" #include "gtkstylecontextprivate.h" -#include "gtktransformprivate.h" +#include "gsktransformprivate.h" #include "gsk/gskrendernodeprivate.h" @@ -109,7 +109,7 @@ gtk_snapshot_collect_default (GtkSnapshot *snapshot, static GtkSnapshotState * gtk_snapshot_push_state (GtkSnapshot *snapshot, - GtkTransform *transform, + GskTransform *transform, GtkSnapshotCollectFunc collect_func) { const gsize n_states = snapshot->state_stack->len; @@ -118,7 +118,7 @@ gtk_snapshot_push_state (GtkSnapshot *snapshot, g_array_set_size (snapshot->state_stack, n_states + 1); state = &g_array_index (snapshot->state_stack, GtkSnapshotState, n_states); - state->transform = gtk_transform_ref (transform); + state->transform = gsk_transform_ref (transform); state->collect_func = collect_func; state->start_node_index = snapshot->nodes->len; state->n_nodes = 0; @@ -145,7 +145,7 @@ gtk_snapshot_get_previous_state (const GtkSnapshot *snapshot) static void gtk_snapshot_state_clear (GtkSnapshotState *state) { - gtk_transform_unref (state->transform); + gsk_transform_unref (state->transform); } /** @@ -242,14 +242,15 @@ gtk_snapshot_collect_autopush_transform (GtkSnapshot *snapshot, guint n_nodes) { GskRenderNode *node, *transform_node; + GtkSnapshotState *previous_state; + + previous_state = gtk_snapshot_get_previous_state (snapshot); node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes); if (node == NULL) return NULL; - transform_node = gsk_transform_node_new_with_category (node, - &state->data.transform.transform, - state->data.transform.category); + transform_node = gsk_transform_node_new (node, previous_state->transform); gsk_render_node_unref (node); @@ -259,17 +260,9 @@ gtk_snapshot_collect_autopush_transform (GtkSnapshot *snapshot, static void gtk_snapshot_autopush_transform (GtkSnapshot *snapshot) { - GtkSnapshotState *previous_state; - GtkSnapshotState *state; - - state = gtk_snapshot_push_state (snapshot, - NULL, - gtk_snapshot_collect_autopush_transform); - - previous_state = gtk_snapshot_get_previous_state (snapshot); - - gtk_transform_to_matrix (previous_state->transform, &state->data.transform.transform); - state->data.transform.category = gtk_transform_categorize (previous_state->transform); + gtk_snapshot_push_state (snapshot, + NULL, + gtk_snapshot_collect_autopush_transform); } static gboolean @@ -582,15 +575,15 @@ gtk_snapshot_ensure_affine (GtkSnapshot *snapshot, float *dx, float *dy) { - const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot); - - if (gtk_transform_to_affine (current_state->transform, scale_x, scale_y, dx, dy)) - return; - - gtk_snapshot_autopush_transform (snapshot); + const GtkSnapshotState *state = gtk_snapshot_get_current_state (snapshot); - *scale_x = *scale_y = 1; - *dx = *dy = 0; + if (gsk_transform_get_category (state->transform) < GSK_TRANSFORM_CATEGORY_2D_AFFINE) + { + gtk_snapshot_autopush_transform (snapshot); + state = gtk_snapshot_get_current_state (snapshot); + } + + gsk_transform_to_affine (state->transform, scale_x, scale_y, dx, dy); } static void @@ -598,16 +591,15 @@ gtk_snapshot_ensure_translate (GtkSnapshot *snapshot, float *dx, float *dy) { - const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot); - float scale_x, scale_y; - - if (gtk_transform_to_affine (current_state->transform, &scale_x, &scale_y, dx, dy) && - scale_x == 1.0f && scale_y == 1.0f) - return; - - gtk_snapshot_autopush_transform (snapshot); + const GtkSnapshotState *state = gtk_snapshot_get_current_state (snapshot); - *dx = *dy = 0; + if (gsk_transform_get_category (state->transform) < GSK_TRANSFORM_CATEGORY_2D_TRANSLATE) + { + gtk_snapshot_autopush_transform (snapshot); + state = gtk_snapshot_get_current_state (snapshot); + } + + gsk_transform_to_translate (state->transform, dx, dy); } static void @@ -615,10 +607,8 @@ gtk_snapshot_ensure_identity (GtkSnapshot *snapshot) { const GtkSnapshotState *state = gtk_snapshot_get_current_state (snapshot); - if (state->transform == NULL) - return; - - gtk_snapshot_autopush_transform (snapshot); + if (gsk_transform_get_category (state->transform) < GSK_TRANSFORM_CATEGORY_IDENTITY) + gtk_snapshot_autopush_transform (snapshot); } void @@ -1244,14 +1234,14 @@ gtk_snapshot_restore (GtkSnapshot *snapshot) **/ void gtk_snapshot_transform (GtkSnapshot *snapshot, - GtkTransform *transform) + GskTransform *transform) { GtkSnapshotState *state; g_return_if_fail (GTK_IS_SNAPSHOT (snapshot)); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_transform (state->transform, transform); + state->transform = gsk_transform_transform (state->transform, transform); } /** @@ -1271,21 +1261,7 @@ gtk_snapshot_transform_matrix (GtkSnapshot *snapshot, g_return_if_fail (matrix != NULL); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_matrix (state->transform, matrix); -} - -void -gtk_snapshot_transform_matrix_with_category (GtkSnapshot *snapshot, - const graphene_matrix_t *matrix, - GskMatrixCategory category) -{ - GtkSnapshotState *state; - - g_return_if_fail (GTK_IS_SNAPSHOT (snapshot)); - g_return_if_fail (matrix != NULL); - - state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_matrix_with_category (state->transform, matrix, category); + state->transform = gsk_transform_matrix (state->transform, matrix); } /** @@ -1305,7 +1281,7 @@ gtk_snapshot_translate (GtkSnapshot *snapshot, g_return_if_fail (point != NULL); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_translate (state->transform, point); + state->transform = gsk_transform_translate (state->transform, point); } /** @@ -1325,7 +1301,7 @@ gtk_snapshot_translate_3d (GtkSnapshot *snapshot, g_return_if_fail (point != NULL); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_translate_3d (state->transform, point); + state->transform = gsk_transform_translate_3d (state->transform, point); } /** @@ -1345,7 +1321,7 @@ gtk_snapshot_rotate (GtkSnapshot *snapshot, g_return_if_fail (GTK_IS_SNAPSHOT (snapshot)); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_rotate (state->transform, angle); + state->transform = gsk_transform_rotate (state->transform, angle); } /** @@ -1356,7 +1332,7 @@ gtk_snapshot_rotate (GtkSnapshot *snapshot, * * Rotates @snapshot's coordinate system by @angle degrees around @axis. * - * For a rotation in 2D space, use gtk_transform_rotate(). + * For a rotation in 2D space, use gsk_transform_rotate(). */ void gtk_snapshot_rotate_3d (GtkSnapshot *snapshot, @@ -1369,7 +1345,7 @@ gtk_snapshot_rotate_3d (GtkSnapshot *snapshot, g_return_if_fail (axis != NULL); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_rotate_3d (state->transform, angle, axis); + state->transform = gsk_transform_rotate_3d (state->transform, angle, axis); } /** @@ -1378,7 +1354,7 @@ gtk_snapshot_rotate_3d (GtkSnapshot *snapshot, * @factor_x: scaling factor on the X axis * @factor_y: scaling factor on the Y axis * - * Scales @@snapshot's coordinate system in 2-dimensional space by + * Scales @snapshot's coordinate system in 2-dimensional space by * the given factors. * * Use gtk_snapshot_scale_3d() to scale in all 3 dimensions. @@ -1393,7 +1369,7 @@ gtk_snapshot_scale (GtkSnapshot *snapshot, g_return_if_fail (GTK_IS_SNAPSHOT (snapshot)); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_scale (state->transform, factor_x, factor_y); + state->transform = gsk_transform_scale (state->transform, factor_x, factor_y); } /** @@ -1403,7 +1379,7 @@ gtk_snapshot_scale (GtkSnapshot *snapshot, * @factor_y: scaling factor on the Y axis * @factor_z: scaling factor on the Z axis * - * Scales @@snapshot's coordinate system by the given factors. + * Scales @snapshot's coordinate system by the given factors. */ void gtk_snapshot_scale_3d (GtkSnapshot *snapshot, @@ -1416,7 +1392,28 @@ gtk_snapshot_scale_3d (GtkSnapshot *snapshot, g_return_if_fail (GTK_IS_SNAPSHOT (snapshot)); state = gtk_snapshot_get_current_state (snapshot); - state->transform = gtk_transform_scale_3d (state->transform, factor_x, factor_y, factor_z); + state->transform = gsk_transform_scale_3d (state->transform, factor_x, factor_y, factor_z); +} + +/** + * gtk_snapshot_perspective: + * @snapshot: a #GtkSnapshot + * @depth: distance of the z=0 plane + * + * Applies a perspective projection transform. + * + * See gsk_transform_perspective() for a discussion on the details. + */ +void +gtk_snapshot_perspective (GtkSnapshot *snapshot, + float depth) +{ + GtkSnapshotState *state; + + g_return_if_fail (GTK_IS_SNAPSHOT (snapshot)); + + state = gtk_snapshot_get_current_state (snapshot); + state->transform = gsk_transform_perspective (state->transform, depth); } void diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h index 162addf28e..91c050d048 100644 --- a/gtk/gtksnapshot.h +++ b/gtk/gtksnapshot.h @@ -107,7 +107,7 @@ GDK_AVAILABLE_IN_ALL void gtk_snapshot_restore (GtkSnapshot *snapshot); GDK_AVAILABLE_IN_ALL void gtk_snapshot_transform (GtkSnapshot *snapshot, - GtkTransform *transform); + GskTransform *transform); GDK_AVAILABLE_IN_ALL void gtk_snapshot_transform_matrix (GtkSnapshot *snapshot, const graphene_matrix_t*matrix); @@ -134,6 +134,9 @@ void gtk_snapshot_scale_3d (GtkSnapshot float factor_y, float factor_z); GDK_AVAILABLE_IN_ALL +void gtk_snapshot_perspective (GtkSnapshot *snapshot, + float depth); +GDK_AVAILABLE_IN_ALL void gtk_snapshot_append_node (GtkSnapshot *snapshot, GskRenderNode *node); GDK_AVAILABLE_IN_ALL diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h index f43f6a3c5d..5bee5e21dc 100644 --- a/gtk/gtksnapshotprivate.h +++ b/gtk/gtksnapshotprivate.h @@ -35,19 +35,15 @@ struct _GtkSnapshotState { guint start_node_index; guint n_nodes; - GtkTransform * transform; + GskTransform * transform; GtkSnapshotCollectFunc collect_func; union { struct { - graphene_matrix_t transform; - GskMatrixCategory category; - } transform; - struct { - double opacity; + double opacity; } opacity; struct { - double radius; + double radius; } blur; struct { graphene_matrix_t matrix; @@ -105,10 +101,6 @@ void gtk_snapshot_append_node_internal (GtkSnapshot GtkSnapshot * gtk_snapshot_new_with_parent (GtkSnapshot *parent_snapshot); -void gtk_snapshot_transform_matrix_with_category - (GtkSnapshot *snapshot, - const graphene_matrix_t*matrix, - GskMatrixCategory category); void gtk_snapshot_append_text (GtkSnapshot *snapshot, PangoFont *font, PangoGlyphString *glyphs, diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c index 2f99cf6a00..b273b2e30d 100644 --- a/gtk/gtkspinbutton.c +++ b/gtk/gtkspinbutton.c @@ -304,6 +304,28 @@ G_DEFINE_TYPE_WITH_CODE (GtkSpinButton, gtk_spin_button, GTK_TYPE_WIDGET, "change-value", 1, \ GTK_TYPE_SCROLL_TYPE, scroll) + +static void +gtk_spin_button_grab_focus (GtkWidget *widget) +{ + GtkSpinButton *spin_button = GTK_SPIN_BUTTON (widget); + GtkSpinButtonPrivate *priv = gtk_spin_button_get_instance_private (spin_button); + + gtk_widget_grab_focus (priv->entry); +} + +static gboolean +gtk_spin_button_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling) +{ + GtkSpinButton *spin_button = GTK_SPIN_BUTTON (widget); + GtkSpinButtonPrivate *priv = gtk_spin_button_get_instance_private (spin_button); + + gtk_widget_grab_focus (priv->entry); + + return TRUE; +} + static void gtk_spin_button_class_init (GtkSpinButtonClass *class) { @@ -321,6 +343,8 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class) widget_class->size_allocate = gtk_spin_button_size_allocate; widget_class->grab_notify = gtk_spin_button_grab_notify; widget_class->state_flags_changed = gtk_spin_button_state_flags_changed; + widget_class->grab_focus = gtk_spin_button_grab_focus; + widget_class->mnemonic_activate = gtk_spin_button_mnemonic_activate; class->input = NULL; class->output = NULL; @@ -800,6 +824,8 @@ key_controller_key_released (GtkEventControllerKey *key, static void key_controller_focus_out (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkSpinButton *spin_button) { GtkSpinButtonPrivate *priv = gtk_spin_button_get_instance_private (spin_button); diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c index f9a7723448..d7222f9e5e 100644 --- a/gtk/gtkstack.c +++ b/gtk/gtkstack.c @@ -1123,7 +1123,6 @@ set_visible_child (GtkStack *stack, GtkStackPage *info; GtkWidget *widget = GTK_WIDGET (stack); GList *l; - GtkWidget *toplevel; GtkWidget *focus; gboolean contains_focus = FALSE; guint old_pos = GTK_INVALID_LIST_POSITION; @@ -1165,24 +1164,23 @@ set_visible_child (GtkStack *stack, } } - toplevel = gtk_widget_get_toplevel (widget); - if (GTK_IS_WINDOW (toplevel)) + if (gtk_widget_get_root (widget)) + focus = gtk_root_get_focus (gtk_widget_get_root (widget)); + else + focus = NULL; + if (focus && + priv->visible_child && + priv->visible_child->widget && + gtk_widget_is_ancestor (focus, priv->visible_child->widget)) { - focus = gtk_window_get_focus (GTK_WINDOW (toplevel)); - if (focus && - priv->visible_child && - priv->visible_child->widget && - gtk_widget_is_ancestor (focus, priv->visible_child->widget)) - { - contains_focus = TRUE; - - if (priv->visible_child->last_focus) - g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus), - (gpointer *)&priv->visible_child->last_focus); - priv->visible_child->last_focus = focus; - g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus), - (gpointer *)&priv->visible_child->last_focus); - } + contains_focus = TRUE; + + if (priv->visible_child->last_focus) + g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus), + (gpointer *)&priv->visible_child->last_focus); + priv->visible_child->last_focus = focus; + g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus), + (gpointer *)&priv->visible_child->last_focus); } if (priv->last_visible_child) diff --git a/gtk/gtkstackswitcher.c b/gtk/gtkstackswitcher.c index e088ba1cca..b2fa29307d 100644 --- a/gtk/gtkstackswitcher.c +++ b/gtk/gtkstackswitcher.c @@ -18,18 +18,21 @@ */ #include "config.h" + #include "gtkstackswitcher.h" -#include "gtkradiobutton.h" -#include "gtklabel.h" + #include "gtkdnd.h" #include "gtkdragdest.h" +#include "gtkimage.h" +#include "gtkintl.h" +#include "gtklabel.h" #include "gtkorientable.h" #include "gtkprivate.h" -#include "gtkintl.h" -#include "gtkwidgetprivate.h" -#include "gtktypebuiltins.h" -#include "gtkimage.h" +#include "gtkradiobutton.h" #include "gtkselectionmodel.h" +#include "gtkstylecontext.h" +#include "gtktypebuiltins.h" +#include "gtkwidgetprivate.h" /** * SECTION:gtkstackswitcher diff --git a/gtk/gtkstylecontext.h b/gtk/gtkstylecontext.h index 0f349ff368..13de1f1035 100644 --- a/gtk/gtkstylecontext.h +++ b/gtk/gtkstylecontext.h @@ -26,7 +26,6 @@ #include <gtk/gtkcsssection.h> #include <gtk/gtkstyleprovider.h> #include <gtk/gtktypes.h> -#include <atk/atk.h> G_BEGIN_DECLS diff --git a/gtk/gtkstylecontextprivate.h b/gtk/gtkstylecontextprivate.h index 3973215abb..81a2e2e3f1 100644 --- a/gtk/gtkstylecontextprivate.h +++ b/gtk/gtkstylecontextprivate.h @@ -26,6 +26,8 @@ #include "gtkbitmaskprivate.h" #include "gtkcssvalueprivate.h" +#include <atk/atk.h> + G_BEGIN_DECLS GtkStyleContext *gtk_style_context_new_for_node (GtkCssNode *node); diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 2ee20ffce7..7a4d6cc2b9 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -172,9 +172,6 @@ struct _GtkTextPrivate GtkCssNode *block_cursor_node; GtkCssNode *undershoot_node[2]; - int text_x; - int text_width; - float xalign; int ascent; /* font ascent in pango units */ @@ -187,8 +184,6 @@ struct _GtkTextPrivate int insert_pos; int selection_bound; int scroll_offset; - int start_x; - int start_y; int width_chars; int max_width_chars; @@ -1647,6 +1642,7 @@ gtk_text_init (GtkText *self) gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE); gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE); + gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN); priv->editable = TRUE; priv->visible = TRUE; @@ -2058,9 +2054,7 @@ gtk_text_measure (GtkWidget *widget, PangoFontMetrics *metrics; context = gtk_widget_get_pango_context (widget); - metrics = pango_context_get_metrics (context, - pango_context_get_font_description (context), - pango_context_get_language (context)); + metrics = pango_context_get_metrics (context, NULL, NULL); if (orientation == GTK_ORIENTATION_HORIZONTAL) { @@ -2145,8 +2139,6 @@ gtk_text_size_allocate (GtkWidget *widget, GtkTextPrivate *priv = gtk_text_get_instance_private (self); priv->text_baseline = baseline; - priv->text_x = 0; - priv->text_width = width; if (priv->placeholder) { @@ -2201,13 +2193,6 @@ gtk_text_snapshot (GtkWidget *widget, GtkText *self = GTK_TEXT (widget); GtkTextPrivate *priv = gtk_text_get_instance_private (self); - gtk_snapshot_push_clip (snapshot, - &GRAPHENE_RECT_INIT ( - priv->text_x, - 0, - priv->text_width, - gtk_widget_get_height (widget))); - /* Draw text and cursor */ if (priv->dnd_position != -1) gtk_text_draw_cursor (GTK_TEXT (widget), snapshot, CURSOR_DND); @@ -2223,8 +2208,6 @@ gtk_text_snapshot (GtkWidget *widget, priv->selection_bound == priv->current_pos && priv->cursor_visible) gtk_text_draw_cursor (GTK_TEXT (widget), snapshot, CURSOR_STANDARD); - gtk_snapshot_pop (snapshot); - gtk_text_draw_undershoot (self, snapshot); } @@ -3827,7 +3810,7 @@ gtk_text_real_activate (GtkText *self) if (window) { default_widget = gtk_window_get_default_widget (window); - focus_widget = gtk_window_get_focus (window); + focus_widget = gtk_root_get_focus (GTK_ROOT (window)); if (widget != default_widget && !(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget)))) gtk_window_activate_default (window); @@ -4234,7 +4217,7 @@ get_layout_position (GtkText *self, y_pos = y_pos / PANGO_SCALE; if (x) - *x = priv->text_x - priv->scroll_offset; + *x = - priv->scroll_offset; if (y) *y = y_pos; @@ -4603,7 +4586,7 @@ gtk_text_get_scroll_limits (GtkText *self, PangoLayout *layout; PangoLayoutLine *line; PangoRectangle logical_rect; - int text_width; + int text_width, width; layout = gtk_text_ensure_layout (self, TRUE); line = pango_layout_get_lines_readonly (layout)->data; @@ -4618,15 +4601,16 @@ gtk_text_get_scroll_limits (GtkText *self, xalign = 1.0 - priv->xalign; text_width = PANGO_PIXELS(logical_rect.width); + width = gtk_widget_get_width (GTK_WIDGET (self)); - if (text_width > priv->text_width) + if (text_width > width) { *min_offset = 0; - *max_offset = text_width - priv->text_width; + *max_offset = text_width - width; } else { - *min_offset = (text_width - priv->text_width) * xalign; + *min_offset = (text_width - width) * xalign; *max_offset = *min_offset; } } diff --git a/gtk/gtktogglebutton.c b/gtk/gtktogglebutton.c index 2f3b0900b7..c482a19da0 100644 --- a/gtk/gtktogglebutton.c +++ b/gtk/gtktogglebutton.c @@ -24,15 +24,16 @@ #include "config.h" -#include "gtktogglebutton.h" +#include "gtktogglebuttonprivate.h" #include "gtkbuttonprivate.h" -#include "gtktogglebuttonprivate.h" +#include "gtkintl.h" #include "gtklabel.h" #include "gtkmain.h" #include "gtkmarshalers.h" #include "gtkprivate.h" -#include "gtkintl.h" +#include "gtkstylecontext.h" + #include "a11y/gtktogglebuttonaccessible.h" diff --git a/gtk/gtktransform.c b/gtk/gtktransform.c deleted file mode 100644 index db15668d37..0000000000 --- a/gtk/gtktransform.c +++ /dev/null @@ -1,1113 +0,0 @@ -/* - * Copyright © 2019 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Authors: Benjamin Otte <otte@gnome.org> - */ - - -/** - * SECTION:gtktransform - * @Title: GtkTransform - * @Short_description: A description for transform operations - * - * #GtkTransform is an object to describe transform matrices. Unlike - * #graphene_matrix_t, #GtkTransform retains the steps in how a transform was - * constructed, and allows inspecting them. It is modeled after the way - * CSS describes transforms. - * - * #GtkTransform objects are immutable and cannot be changed after creation. - * This means code can safely expose them as properties of objects without - * having to worry about others changing them. - */ - -#include "config.h" - -#include "gtktransformprivate.h" - -typedef struct _GtkTransformClass GtkTransformClass; - -#define GTK_IS_TRANSFORM_TYPE(self,type) ((self) == NULL ? (type) == GTK_TRANSFORM_TYPE_IDENTITY : (self)->transform_class->transform_type == (type)) - -struct _GtkTransform -{ - const GtkTransformClass *transform_class; - - volatile int ref_count; - GtkTransform *next; -}; - -struct _GtkTransformClass -{ - GtkTransformType transform_type; - gsize struct_size; - const char *type_name; - - void (* finalize) (GtkTransform *transform); - GskMatrixCategory (* categorize) (GtkTransform *transform); - void (* to_matrix) (GtkTransform *transform, - graphene_matrix_t *out_matrix); - gboolean (* apply_affine) (GtkTransform *transform, - float *out_scale_x, - float *out_scale_y, - float *out_dx, - float *out_dy); - void (* print) (GtkTransform *transform, - GString *string); - GtkTransform * (* apply) (GtkTransform *transform, - GtkTransform *apply_to); - /* both matrices have the same type */ - gboolean (* equal) (GtkTransform *first_transform, - GtkTransform *second_transform); -}; - -/** - * GtkTransform: (ref-func gtk_transform_ref) (unref-func gtk_transform_unref) - * - * The `GtkTransform` structure contains only private data. - */ - -G_DEFINE_BOXED_TYPE (GtkTransform, gtk_transform, - gtk_transform_ref, - gtk_transform_unref) - -/*<private> - * gtk_transform_is_identity: - * @transform: (allow-none): A transform or %NULL - * - * Checks if the transform is a representation of the identity - * transform. - * - * This is different from a transform like `scale(2) scale(0.5)` - * which just results in an identity transform when simplified. - * - * Returns: %TRUE if this transform is a representation of - * the identity transform - **/ -static gboolean -gtk_transform_is_identity (GtkTransform *self) -{ - return self == NULL || - (GTK_IS_TRANSFORM_TYPE (self, GTK_TRANSFORM_TYPE_IDENTITY) && gtk_transform_is_identity (self->next)); -} - -/*< private > - * gtk_transform_alloc: - * @transform_class: class structure for this self - * @next: (transfer full) Next matrix to multiply with or %NULL if none - * - * Returns: (transfer full): the newly created #GtkTransform - */ -static gpointer -gtk_transform_alloc (const GtkTransformClass *transform_class, - GtkTransform *next) -{ - GtkTransform *self; - - g_return_val_if_fail (transform_class != NULL, NULL); - - self = g_malloc0 (transform_class->struct_size); - - self->transform_class = transform_class; - self->ref_count = 1; - self->next = gtk_transform_is_identity (next) ? NULL : next; - - return self; -} - -/*** IDENTITY ***/ - -static void -gtk_identity_transform_finalize (GtkTransform *transform) -{ -} - -static GskMatrixCategory -gtk_identity_transform_categorize (GtkTransform *transform) -{ - return GSK_MATRIX_CATEGORY_IDENTITY; -} - -static void -gtk_identity_transform_to_matrix (GtkTransform *transform, - graphene_matrix_t *out_matrix) -{ - graphene_matrix_init_identity (out_matrix); -} - -static gboolean -gtk_identity_transform_apply_affine (GtkTransform *transform, - float *out_scale_x, - float *out_scale_y, - float *out_dx, - float *out_dy) -{ - return TRUE; -} - -static void -gtk_identity_transform_print (GtkTransform *transform, - GString *string) -{ - g_string_append (string, "identity"); -} - -static GtkTransform * -gtk_identity_transform_apply (GtkTransform *transform, - GtkTransform *apply_to) -{ - return gtk_transform_identity (apply_to); -} - -static gboolean -gtk_identity_transform_equal (GtkTransform *first_transform, - GtkTransform *second_transform) -{ - return TRUE; -} - -static const GtkTransformClass GTK_IDENTITY_TRANSFORM_CLASS = -{ - GTK_TRANSFORM_TYPE_IDENTITY, - sizeof (GtkTransform), - "GtkIdentityMatrix", - gtk_identity_transform_finalize, - gtk_identity_transform_categorize, - gtk_identity_transform_to_matrix, - gtk_identity_transform_apply_affine, - gtk_identity_transform_print, - gtk_identity_transform_apply, - gtk_identity_transform_equal, -}; - -/** - * gtk_transform_identity: - * @next: (allow-none): the next transform operation or %NULL - * - * Adds an identity multiplication into the list of matrix operations. - * - * This operation is generally useless, but may be useful when interpolating - * matrices, because the identity matrix can be interpolated to and from - * everything, so an identity matrix can be used as a keyframe between two - * different types of matrices. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_identity (GtkTransform *next) -{ - if (gtk_transform_is_identity (next)) - return next; - - return gtk_transform_alloc (>K_IDENTITY_TRANSFORM_CLASS, next); -} - -/*** MATRIX ***/ - -typedef struct _GtkMatrixTransform GtkMatrixTransform; - -struct _GtkMatrixTransform -{ - GtkTransform parent; - - graphene_matrix_t matrix; - GskMatrixCategory category; -}; - -static void -gtk_matrix_transform_finalize (GtkTransform *self) -{ -} - -static GskMatrixCategory -gtk_matrix_transform_categorize (GtkTransform *transform) -{ - GtkMatrixTransform *self = (GtkMatrixTransform *) transform; - - return self->category; -} - -static void -gtk_matrix_transform_to_matrix (GtkTransform *transform, - graphene_matrix_t *out_matrix) -{ - GtkMatrixTransform *self = (GtkMatrixTransform *) transform; - - graphene_matrix_init_from_matrix (out_matrix, &self->matrix); -} - -static gboolean -gtk_matrix_transform_apply_affine (GtkTransform *transform, - float *out_scale_x, - float *out_scale_y, - float *out_dx, - float *out_dy) -{ - GtkMatrixTransform *self = (GtkMatrixTransform *) transform; - - switch (self->category) - { - case GSK_MATRIX_CATEGORY_UNKNOWN: - case GSK_MATRIX_CATEGORY_ANY: - case GSK_MATRIX_CATEGORY_INVERTIBLE: - default: - return FALSE; - - case GSK_MATRIX_CATEGORY_2D_AFFINE: - *out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0); - *out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1); - *out_scale_x *= graphene_matrix_get_value (&self->matrix, 0, 0); - *out_scale_y *= graphene_matrix_get_value (&self->matrix, 1, 1); - return TRUE; - - case GSK_MATRIX_CATEGORY_2D_TRANSLATE: - *out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0); - *out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1); - return TRUE; - - case GSK_MATRIX_CATEGORY_IDENTITY: - return TRUE; - } -} - -static void -string_append_double (GString *string, - double d) -{ - char buf[G_ASCII_DTOSTR_BUF_SIZE]; - - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%g", d); - g_string_append (string, buf); -} - -static void -gtk_matrix_transform_print (GtkTransform *transform, - GString *string) -{ - GtkMatrixTransform *self = (GtkMatrixTransform *) transform; - guint i; - float f[16]; - - g_string_append (string, "matrix3d("); - graphene_matrix_to_float (&self->matrix, f); - for (i = 0; i < 16; i++) - { - if (i > 0) - g_string_append (string, ", "); - string_append_double (string, f[i]); - } - g_string_append (string, ")"); -} - -static GtkTransform * -gtk_matrix_transform_apply (GtkTransform *transform, - GtkTransform *apply_to) -{ - GtkMatrixTransform *self = (GtkMatrixTransform *) transform; - - return gtk_transform_matrix_with_category (apply_to, - &self->matrix, - self->category); -} - -static gboolean -gtk_matrix_transform_equal (GtkTransform *first_transform, - GtkTransform *second_transform) -{ - GtkMatrixTransform *first = (GtkMatrixTransform *) first_transform; - GtkMatrixTransform *second = (GtkMatrixTransform *) second_transform; - - /* Crude, but better than just returning FALSE */ - return memcmp (&first->matrix, &second->matrix, sizeof (graphene_matrix_t)) == 0; -} - -static const GtkTransformClass GTK_TRANSFORM_TRANSFORM_CLASS = -{ - GTK_TRANSFORM_TYPE_TRANSFORM, - sizeof (GtkMatrixTransform), - "GtkMatrixTransform", - gtk_matrix_transform_finalize, - gtk_matrix_transform_categorize, - gtk_matrix_transform_to_matrix, - gtk_matrix_transform_apply_affine, - gtk_matrix_transform_print, - gtk_matrix_transform_apply, - gtk_matrix_transform_equal, -}; - -GtkTransform * -gtk_transform_matrix_with_category (GtkTransform *next, - const graphene_matrix_t *matrix, - GskMatrixCategory category) -{ - GtkMatrixTransform *result = gtk_transform_alloc (>K_TRANSFORM_TRANSFORM_CLASS, next); - - graphene_matrix_init_from_matrix (&result->matrix, matrix); - result->category = category; - - return &result->parent; -} - -/** - * gtk_transform_matrix: - * @next: (allow-none): the next transform - * @matrix: the matrix to multiply @next with - * - * Multiplies @next with the given @matrix. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_matrix (GtkTransform *next, - const graphene_matrix_t *matrix) -{ - return gtk_transform_matrix_with_category (next, matrix, GSK_MATRIX_CATEGORY_UNKNOWN); -} - -/*** TRANSLATE ***/ - -typedef struct _GtkTranslateTransform GtkTranslateTransform; - -struct _GtkTranslateTransform -{ - GtkTransform parent; - - graphene_point3d_t point; -}; - -static void -gtk_translate_transform_finalize (GtkTransform *self) -{ -} - -static GskMatrixCategory -gtk_translate_transform_categorize (GtkTransform *transform) -{ - GtkTranslateTransform *self = (GtkTranslateTransform *) transform; - - if (self->point.z != 0.0) - return GSK_MATRIX_CATEGORY_INVERTIBLE; - - return GSK_MATRIX_CATEGORY_2D_TRANSLATE; -} - -static void -gtk_translate_transform_to_matrix (GtkTransform *transform, - graphene_matrix_t *out_matrix) -{ - GtkTranslateTransform *self = (GtkTranslateTransform *) transform; - - graphene_matrix_init_translate (out_matrix, &self->point); -} - -static gboolean -gtk_translate_transform_apply_affine (GtkTransform *transform, - float *out_scale_x, - float *out_scale_y, - float *out_dx, - float *out_dy) -{ - GtkTranslateTransform *self = (GtkTranslateTransform *) transform; - - if (self->point.z != 0.0) - return FALSE; - - *out_dx += *out_scale_x * self->point.x; - *out_dy += *out_scale_y * self->point.y; - - return TRUE; -} - -static GtkTransform * -gtk_translate_transform_apply (GtkTransform *transform, - GtkTransform *apply_to) -{ - GtkTranslateTransform *self = (GtkTranslateTransform *) transform; - - return gtk_transform_translate_3d (apply_to, &self->point); -} - -static gboolean -gtk_translate_transform_equal (GtkTransform *first_transform, - GtkTransform *second_transform) -{ - GtkTranslateTransform *first = (GtkTranslateTransform *) first_transform; - GtkTranslateTransform *second = (GtkTranslateTransform *) second_transform; - - return graphene_point3d_equal (&first->point, &second->point); -} - -static void -gtk_translate_transform_print (GtkTransform *transform, - GString *string) -{ - GtkTranslateTransform *self = (GtkTranslateTransform *) transform; - - if (self->point.z == 0) - g_string_append (string, "translate("); - else - g_string_append (string, "translate3d("); - - string_append_double (string, self->point.x); - g_string_append (string, ", "); - string_append_double (string, self->point.y); - if (self->point.z != 0) - { - g_string_append (string, ", "); - string_append_double (string, self->point.y); - } - g_string_append (string, ")"); -} - -static const GtkTransformClass GTK_TRANSLATE_TRANSFORM_CLASS = -{ - GTK_TRANSFORM_TYPE_TRANSLATE, - sizeof (GtkTranslateTransform), - "GtkTranslateTransform", - gtk_translate_transform_finalize, - gtk_translate_transform_categorize, - gtk_translate_transform_to_matrix, - gtk_translate_transform_apply_affine, - gtk_translate_transform_print, - gtk_translate_transform_apply, - gtk_translate_transform_equal, -}; - -/** - * gtk_transform_translate: - * @next: (allow-none): the next transform - * @point: the point to translate the matrix by - * - * Translates @next in 2dimensional space by @point. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_translate (GtkTransform *next, - const graphene_point_t *point) -{ - graphene_point3d_t point3d; - - graphene_point3d_init (&point3d, point->x, point->y, 0); - - return gtk_transform_translate_3d (next, &point3d); -} - -/** - * gtk_transform_translate_3d: - * @next: (allow-none): the next transform - * @point: the point to translate the matrix by - * - * Translates @next by @point. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_translate_3d (GtkTransform *next, - const graphene_point3d_t *point) -{ - GtkTranslateTransform *result = gtk_transform_alloc (>K_TRANSLATE_TRANSFORM_CLASS, next); - - graphene_point3d_init_from_point (&result->point, point); - - return &result->parent; -} - -/*** ROTATE ***/ - -typedef struct _GtkRotateTransform GtkRotateTransform; - -struct _GtkRotateTransform -{ - GtkTransform parent; - - float angle; - graphene_vec3_t axis; -}; - -static void -gtk_rotate_transform_finalize (GtkTransform *self) -{ -} - -static GskMatrixCategory -gtk_rotate_transform_categorize (GtkTransform *transform) -{ - return GSK_MATRIX_CATEGORY_INVERTIBLE; -} - -static void -gtk_rotate_transform_to_matrix (GtkTransform *transform, - graphene_matrix_t *out_matrix) -{ - GtkRotateTransform *self = (GtkRotateTransform *) transform; - - graphene_matrix_init_rotate (out_matrix, self->angle, &self->axis); -} - -static gboolean -gtk_rotate_transform_apply_affine (GtkTransform *transform, - float *out_scale_x, - float *out_scale_y, - float *out_dx, - float *out_dy) -{ - return FALSE; -} - -static GtkTransform * -gtk_rotate_transform_apply (GtkTransform *transform, - GtkTransform *apply_to) -{ - GtkRotateTransform *self = (GtkRotateTransform *) transform; - - return gtk_transform_rotate_3d (apply_to, self->angle, &self->axis); -} - -static gboolean -gtk_rotate_transform_equal (GtkTransform *first_transform, - GtkTransform *second_transform) -{ - GtkRotateTransform *first = (GtkRotateTransform *) first_transform; - GtkRotateTransform *second = (GtkRotateTransform *) second_transform; - - return first->angle == second->angle - && graphene_vec3_equal (&first->axis, &second->axis); -} - -static void -gtk_rotate_transform_print (GtkTransform *transform, - GString *string) -{ - GtkRotateTransform *self = (GtkRotateTransform *) transform; - graphene_vec3_t default_axis; - - graphene_vec3_init_from_vec3 (&default_axis, graphene_vec3_z_axis ()); - if (graphene_vec3_equal (&default_axis, &self->axis)) - { - g_string_append (string, "rotate("); - string_append_double (string, self->angle); - g_string_append (string, ")"); - } - else - { - float f[3]; - guint i; - - g_string_append (string, "rotate3d("); - graphene_vec3_to_float (&self->axis, f); - for (i = 0; i < 3; i++) - { - string_append_double (string, f[i]); - g_string_append (string, ", "); - } - string_append_double (string, self->angle); - g_string_append (string, ")"); - } -} - -static const GtkTransformClass GTK_ROTATE_TRANSFORM_CLASS = -{ - GTK_TRANSFORM_TYPE_ROTATE, - sizeof (GtkRotateTransform), - "GtkRotateTransform", - gtk_rotate_transform_finalize, - gtk_rotate_transform_categorize, - gtk_rotate_transform_to_matrix, - gtk_rotate_transform_apply_affine, - gtk_rotate_transform_print, - gtk_rotate_transform_apply, - gtk_rotate_transform_equal, -}; - -/** - * gtk_transform_rotate: - * @next: (allow-none): the next transform - * @angle: the rotation angle, in degrees (clockwise) - * - * Rotates @next @angle degrees in 2D - or in 3Dspeak, around the z axis. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_rotate (GtkTransform *next, - float angle) -{ - return gtk_transform_rotate_3d (next, angle, graphene_vec3_z_axis ()); -} - -/** - * gtk_transform_rotate_3d: - * @next: (allow-none): the next transform - * @angle: the rotation angle, in degrees (clockwise) - * @axis: The rotation axis - * - * Rotates @next @angle degrees around @axis. - * - * For a rotation in 2D space, use gtk_transform_rotate(). - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_rotate_3d (GtkTransform *next, - float angle, - const graphene_vec3_t *axis) -{ - GtkRotateTransform *result = gtk_transform_alloc (>K_ROTATE_TRANSFORM_CLASS, next); - - result->angle = angle; - graphene_vec3_init_from_vec3 (&result->axis, axis); - - return &result->parent; -} - -/*** SCALE ***/ - -typedef struct _GtkScaleTransform GtkScaleTransform; - -struct _GtkScaleTransform -{ - GtkTransform parent; - - float factor_x; - float factor_y; - float factor_z; -}; - -static void -gtk_scale_transform_finalize (GtkTransform *self) -{ -} - -static GskMatrixCategory -gtk_scale_transform_categorize (GtkTransform *transform) -{ - GtkScaleTransform *self = (GtkScaleTransform *) transform; - - if (self->factor_z != 1.0) - return GSK_MATRIX_CATEGORY_INVERTIBLE; - - return GSK_MATRIX_CATEGORY_2D_AFFINE; -} - -static void -gtk_scale_transform_to_matrix (GtkTransform *transform, - graphene_matrix_t *out_matrix) -{ - GtkScaleTransform *self = (GtkScaleTransform *) transform; - - graphene_matrix_init_scale (out_matrix, self->factor_x, self->factor_y, self->factor_z); -} - -static gboolean -gtk_scale_transform_apply_affine (GtkTransform *transform, - float *out_scale_x, - float *out_scale_y, - float *out_dx, - float *out_dy) -{ - GtkScaleTransform *self = (GtkScaleTransform *) transform; - - if (self->factor_z != 1.0) - return FALSE; - - *out_scale_x *= self->factor_x; - *out_scale_y *= self->factor_y; - - return TRUE; -} - -static GtkTransform * -gtk_scale_transform_apply (GtkTransform *transform, - GtkTransform *apply_to) -{ - GtkScaleTransform *self = (GtkScaleTransform *) transform; - - return gtk_transform_scale_3d (apply_to, self->factor_x, self->factor_y, self->factor_z); -} - -static gboolean -gtk_scale_transform_equal (GtkTransform *first_transform, - GtkTransform *second_transform) -{ - GtkScaleTransform *first = (GtkScaleTransform *) first_transform; - GtkScaleTransform *second = (GtkScaleTransform *) second_transform; - - return first->factor_x == second->factor_x - && first->factor_y == second->factor_y - && first->factor_z == second->factor_z; -} - -static void -gtk_scale_transform_print (GtkTransform *transform, - GString *string) -{ - GtkScaleTransform *self = (GtkScaleTransform *) transform; - - if (self->factor_z == 1.0) - { - g_string_append (string, "scale("); - string_append_double (string, self->factor_x); - if (self->factor_x != self->factor_y) - { - g_string_append (string, ", "); - string_append_double (string, self->factor_y); - } - g_string_append (string, ")"); - } - else - { - g_string_append (string, "scale3d("); - string_append_double (string, self->factor_x); - g_string_append (string, ", "); - string_append_double (string, self->factor_y); - g_string_append (string, ", "); - string_append_double (string, self->factor_z); - g_string_append (string, ")"); - } -} - -static const GtkTransformClass GTK_SCALE_TRANSFORM_CLASS = -{ - GTK_TRANSFORM_TYPE_SCALE, - sizeof (GtkScaleTransform), - "GtkScaleTransform", - gtk_scale_transform_finalize, - gtk_scale_transform_categorize, - gtk_scale_transform_to_matrix, - gtk_scale_transform_apply_affine, - gtk_scale_transform_print, - gtk_scale_transform_apply, - gtk_scale_transform_equal, -}; - -/** - * gtk_transform_scale: - * @next: (allow-none): the next transform - * @factor_x: scaling factor on the X axis - * @factor_y: scaling factor on the Y axis - * - * Scales @next in 2-dimensional space by the given factors. - * Use gtk_transform_scale_3d() to scale in all 3 dimensions. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_scale (GtkTransform *next, - float factor_x, - float factor_y) -{ - return gtk_transform_scale_3d (next, factor_x, factor_y, 1.0); -} - -/** - * gtk_transform_scale_3d: - * @next: (allow-none): the next transform - * @factor_x: scaling factor on the X axis - * @factor_y: scaling factor on the Y axis - * @factor_z: scaling factor on the Z axis - * - * Scales @next by the given factors. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_scale_3d (GtkTransform *next, - float factor_x, - float factor_y, - float factor_z) -{ - GtkScaleTransform *result = gtk_transform_alloc (>K_SCALE_TRANSFORM_CLASS, next); - - result->factor_x = factor_x; - result->factor_y = factor_y; - result->factor_z = factor_z; - - return &result->parent; -} - -/*** PUBLIC API ***/ - -static void -gtk_transform_finalize (GtkTransform *self) -{ - self->transform_class->finalize (self); - - gtk_transform_unref (self->next); - - g_free (self); -} - -/** - * gtk_transform_ref: - * @self: (allow-none): a #GtkTransform - * - * Acquires a reference on the given #GtkTransform. - * - * Returns: (transfer none): the #GtkTransform with an additional reference - */ -GtkTransform * -gtk_transform_ref (GtkTransform *self) -{ - if (self == NULL) - return NULL; - - g_atomic_int_inc (&self->ref_count); - - return self; -} - -/** - * gtk_transform_unref: - * @self: (allow-none): a #GtkTransform - * - * Releases a reference on the given #GtkTransform. - * - * If the reference was the last, the resources associated to the @self are - * freed. - */ -void -gtk_transform_unref (GtkTransform *self) -{ - if (self == NULL) - return; - - if (g_atomic_int_dec_and_test (&self->ref_count)) - gtk_transform_finalize (self); -} - -/** - * gtk_transform_print: - * @self: (allow-none): a #GtkTransform - * @string: The string to print into - * - * Converts @self into a string representation suitable for printing that - * can later be parsed with gtk_transform_parse(). - **/ -void -gtk_transform_print (GtkTransform *self, - GString *string) -{ - g_return_if_fail (string != NULL); - - if (self == NULL) - { - g_string_append (string, "none"); - return; - } - - if (self->next != NULL) - { - gtk_transform_print (self->next, string); - g_string_append (string, " "); - } - - self->transform_class->print (self, string); -} - -/** - * gtk_transform_to_string: - * @self: (allow-none): a #GtkTransform - * - * Converts a matrix into a string that is suitable for - * printing and can later be parsed with gtk_transform_parse(). - * - * This is a wrapper around gtk_transform_print(), see that function - * for details. - * - * Returns: A new string for @self - **/ -char * -gtk_transform_to_string (GtkTransform *self) -{ - GString *string; - - string = g_string_new (""); - - gtk_transform_print (self, string); - - return g_string_free (string, FALSE); -} - -/** - * gtk_transform_get_transform_type: - * @self: (allow-none): a #GtkTransform - * - * Returns the type of the @self. - * - * Returns: the type of the #GtkTransform - */ -GtkTransformType -gtk_transform_get_transform_type (GtkTransform *self) -{ - if (self == NULL) - return GTK_TRANSFORM_TYPE_IDENTITY; - - return self->transform_class->transform_type; -} - -/** - * gtk_transform_get_next: - * @self: (allow-none): a #GtkTransform - * - * Gets the rest of the matrix in the chain of operations. - * - * Returns: (transfer none) (nullable): The next transform or - * %NULL if this was the last operation. - **/ -GtkTransform * -gtk_transform_get_next (GtkTransform *self) -{ - if (self == NULL) - return NULL; - - return self->next; -} - -/** - * gtk_transform_to_matrix: - * @self: (allow-none): a #GtkTransform - * @out_matrix: (out caller-allocates): The matrix to set - * - * Computes the actual value of @self and stores it in @out_matrix. - * The previous value of @out_matrix will be ignored. - **/ -void -gtk_transform_to_matrix (GtkTransform *self, - graphene_matrix_t *out_matrix) -{ - graphene_matrix_t m; - - if (self == NULL) - { - graphene_matrix_init_identity (out_matrix); - return; - } - - gtk_transform_to_matrix (self->next, out_matrix); - self->transform_class->to_matrix (self, &m); - graphene_matrix_multiply (&m, out_matrix, out_matrix); -} - -gboolean -gtk_transform_to_affine (GtkTransform *self, - float *out_scale_x, - float *out_scale_y, - float *out_dx, - float *out_dy) -{ - if (self == NULL) - { - *out_scale_x = 1.0f; - *out_scale_y = 1.0f; - *out_dx = 0.0f; - *out_dy = 0.0f; - return TRUE; - } - - if (!gtk_transform_to_affine (self->next, - out_scale_x, out_scale_y, - out_dx, out_dy)) - return FALSE; - - return self->transform_class->apply_affine (self, - out_scale_x, out_scale_y, - out_dx, out_dy); -} - -/** - * gtk_transform_transform: - * @next: (allow-none) (transfer full): Transform to apply @other to - * @other: (allow-none): Transform to apply - * - * Applies all the operations from @other to @next. - * - * Returns: The new matrix - **/ -GtkTransform * -gtk_transform_transform (GtkTransform *next, - GtkTransform *other) -{ - if (other == NULL) - return next; - - next = gtk_transform_transform (next, other->next); - return other->transform_class->apply (other, next); -} - -/** - * gtk_transform_equal: - * @first: the first matrix - * @second: the second matrix - * - * Checks two matrices for equality. Note that matrices need to be literally - * identical in their operations, it is not enough that they return the - * same result in gtk_transform_to_matrix(). - * - * Returns: %TRUE if the two matrices can be proven to be equal - **/ -gboolean -gtk_transform_equal (GtkTransform *first, - GtkTransform *second) -{ - if (first == second) - return TRUE; - - if (first == NULL || second == NULL) - return FALSE; - - if (!gtk_transform_equal (first->next, second->next)) - return FALSE; - - if (first->transform_class != second->transform_class) - return FALSE; - - return first->transform_class->equal (first, second); -} - -/*<private> - * gtk_transform_categorize: - * @self: (allow-none): A matrix - * - * - * - * Returns: The category this matrix belongs to - **/ -GskMatrixCategory -gtk_transform_categorize (GtkTransform *self) -{ - if (self == NULL) - return GSK_MATRIX_CATEGORY_IDENTITY; - - return MIN (gtk_transform_categorize (self->next), - self->transform_class->categorize (self)); -} - -/* - * gtk_transform_new: (constructor): - * - * Creates a new identity matrix. This function is meant to be used by language - * bindings. For C code, this equivalent to using %NULL. - * - * See also gtk_transform_identity() for inserting identity matrix operations - * when constructing matrices. - * - * Returns: A new identity matrix - **/ -GtkTransform * -gtk_transform_new (void) -{ - return gtk_transform_alloc (>K_IDENTITY_TRANSFORM_CLASS, NULL); -} diff --git a/gtk/gtktransform.h b/gtk/gtktransform.h deleted file mode 100644 index b62b044978..0000000000 --- a/gtk/gtktransform.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright © 2019 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Authors: Benjamin Otte <otte@gnome.org> - */ - - -#ifndef __GTK_TRANSFORM_H__ -#define __GTK_TRANSFORM_H__ - -#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) -#error "Only <gtk/gtk.h> can be included directly." -#endif - -#include <graphene.h> -#include <gtk/gtktypes.h> - -G_BEGIN_DECLS - -#define GTK_TYPE_MATRIX (gtk_transform_get_type ()) - -typedef enum -{ - GTK_TRANSFORM_TYPE_IDENTITY, - GTK_TRANSFORM_TYPE_TRANSFORM, - GTK_TRANSFORM_TYPE_TRANSLATE, - GTK_TRANSFORM_TYPE_ROTATE, - GTK_TRANSFORM_TYPE_SCALE -} GtkTransformType; - -GDK_AVAILABLE_IN_ALL -GType gtk_transform_get_type (void) G_GNUC_CONST; - -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_ref (GtkTransform *self); -GDK_AVAILABLE_IN_ALL -void gtk_transform_unref (GtkTransform *self); - -GDK_AVAILABLE_IN_ALL -void gtk_transform_print (GtkTransform *self, - GString *string); -GDK_AVAILABLE_IN_ALL -char * gtk_transform_to_string (GtkTransform *self); -GDK_AVAILABLE_IN_ALL -void gtk_transform_to_matrix (GtkTransform *self, - graphene_matrix_t *out_matrix); -GDK_AVAILABLE_IN_ALL -gboolean gtk_transform_equal (GtkTransform *first, - GtkTransform *second) G_GNUC_PURE; - -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_new (void); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_identity (GtkTransform *next); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_transform (GtkTransform *next, - GtkTransform *other); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_matrix (GtkTransform *next, - const graphene_matrix_t *matrix); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_translate (GtkTransform *next, - const graphene_point_t *point); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_translate_3d (GtkTransform *next, - const graphene_point3d_t *point); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_rotate (GtkTransform *next, - float angle); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_rotate_3d (GtkTransform *next, - float angle, - const graphene_vec3_t *axis); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_scale (GtkTransform *next, - float factor_x, - float factor_y); -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_scale_3d (GtkTransform *next, - float factor_x, - float factor_y, - float factor_z); - -GDK_AVAILABLE_IN_ALL -GtkTransformType gtk_transform_get_transform_type (GtkTransform *self) G_GNUC_PURE; -GDK_AVAILABLE_IN_ALL -GtkTransform * gtk_transform_get_next (GtkTransform *self) G_GNUC_PURE; - -G_END_DECLS - -#endif /* __GTK_TRANSFORM_H__ */ diff --git a/gtk/gtktransformprivate.h b/gtk/gtktransformprivate.h deleted file mode 100644 index 5aef0b001d..0000000000 --- a/gtk/gtktransformprivate.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright © 2019 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Authors: Benjamin Otte <otte@gnome.org> - */ - - -#ifndef __GTK_TRANSFORM_PRIVATE_H__ -#define __GTK_TRANSFORM_PRIVATE_H__ - -#include "gtktransform.h" - -#include <gsk/gsk.h> -#include "gsk/gskrendernodeprivate.h" - -G_BEGIN_DECLS - -GskMatrixCategory gtk_transform_categorize (GtkTransform *self); - -gboolean gtk_transform_to_affine (GtkTransform *self, - float *scale_x, - float *scale_y, - float *dx, - float *dy) G_GNUC_WARN_UNUSED_RESULT; - -GtkTransform * gtk_transform_matrix_with_category (GtkTransform *next, - const graphene_matrix_t*matrix, - GskMatrixCategory category); - -G_END_DECLS - -#endif /* __GTK_TRANSFORM_PRIVATE_H__ */ - diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index e8191a9fef..58ff31bd05 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -614,6 +614,8 @@ static void gtk_tree_view_key_controller_key_released (GtkEventControllerKey GdkModifierType state, GtkTreeView *tree_view); static void gtk_tree_view_key_controller_focus_out (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view); static gint gtk_tree_view_focus (GtkWidget *widget, @@ -927,8 +929,12 @@ static void gtk_tree_view_drag_gesture_end (GtkGestureDrag *ges static void gtk_tree_view_motion_controller_enter (GtkEventControllerMotion *controller, double x, double y, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view); static void gtk_tree_view_motion_controller_leave (GtkEventControllerMotion *controller, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view); static void gtk_tree_view_motion_controller_motion (GtkEventControllerMotion *controller, double x, @@ -5435,6 +5441,8 @@ static void gtk_tree_view_motion_controller_enter (GtkEventControllerMotion *controller, double x, double y, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view) { GtkTreeRBTree *tree; @@ -5460,6 +5468,8 @@ gtk_tree_view_motion_controller_enter (GtkEventControllerMotion *controller, static void gtk_tree_view_motion_controller_leave (GtkEventControllerMotion *controller, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view) { if (tree_view->priv->prelight_node) @@ -5475,6 +5485,8 @@ gtk_tree_view_motion_controller_leave (GtkEventControllerMotion *controller, static void gtk_tree_view_key_controller_focus_out (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view) { gtk_widget_queue_draw (GTK_WIDGET (tree_view)); @@ -5614,6 +5626,8 @@ validate_row (GtkTreeView *tree_view, if (is_separator) { height = separator_height; + /* gtk_tree_view_get_row_height() assumes separator nodes are > 0 */ + height = MAX (height, 1); } else { @@ -10149,7 +10163,8 @@ send_focus_change (GtkWidget *widget, fevent->focus_change.in = in; gdk_event_set_device (fevent, device); - gtk_widget_send_focus_change (widget, fevent); + gtk_widget_set_has_focus (widget, in); + gtk_widget_event (widget, fevent); g_object_unref (fevent); } diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 5817a5f2f8..78e22c5ef2 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -814,6 +814,8 @@ gtk_tree_view_column_cell_layout_get_area (GtkCellLayout *cell_layout) static void focus_in (GtkEventControllerKey *controller, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeViewColumn *column) { _gtk_tree_view_set_focus_column (GTK_TREE_VIEW (column->priv->tree_view), column); @@ -1016,11 +1018,8 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column) gtk_widget_set_can_focus (priv->button, FALSE); if (gtk_widget_has_focus (priv->button)) { - GtkWidget *toplevel = gtk_widget_get_toplevel (priv->tree_view); - if (gtk_widget_is_toplevel (toplevel)) - { - gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); - } + GtkRoot *root = gtk_widget_get_root (priv->tree_view); + gtk_root_set_focus (root, NULL); } } /* Queue a resize on the assumption that we always want to catch all changes diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h index 9876bed3a5..5d1218f189 100644 --- a/gtk/gtktypes.h +++ b/gtk/gtktypes.h @@ -45,7 +45,6 @@ typedef struct _GtkSettings GtkSettings; typedef GdkSnapshot GtkSnapshot; typedef struct _GtkStyleContext GtkStyleContext; typedef struct _GtkTooltip GtkTooltip; -typedef struct _GtkTransform GtkTransform; typedef struct _GtkWidget GtkWidget; typedef struct _GtkWidgetPath GtkWidgetPath; typedef struct _GtkWindow GtkWindow; diff --git a/gtk/gtkviewport.c b/gtk/gtkviewport.c index 8a8f7e032a..123227405d 100644 --- a/gtk/gtkviewport.c +++ b/gtk/gtkviewport.c @@ -31,6 +31,7 @@ #include "gtkmarshalers.h" #include "gtkprivate.h" #include "gtkscrollable.h" +#include "gtkstylecontext.h" #include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 80f8dcc099..7b5e2ed1e5 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -62,7 +62,7 @@ #include "gtksnapshotprivate.h" #include "gtkstylecontextprivate.h" #include "gtktooltipprivate.h" -#include "gtktransformprivate.h" +#include "gsktransformprivate.h" #include "gtktypebuiltins.h" #include "gtkversion.h" #include "gtkwidgetpaintableprivate.h" @@ -484,7 +484,6 @@ enum { GRAB_NOTIFY, CHILD_NOTIFY, MNEMONIC_ACTIVATE, - FOCUS, MOVE_FOCUS, KEYNAV_FAILED, DRAG_BEGIN, @@ -820,15 +819,33 @@ gtk_widget_real_pick (GtkWidget *widget, child = _gtk_widget_get_prev_sibling (child)) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (child); + GskTransform *transform; graphene_matrix_t inv; GtkWidget *picked; - graphene_point_t p; + graphene_point3d_t p0, p1, res; - graphene_matrix_inverse (&priv->transform, &inv); - graphene_point_init (&p, x, y); - graphene_matrix_transform_point (&inv, &p, &p); + if (priv->transform) + { + transform = gsk_transform_invert (gsk_transform_ref (priv->transform)); + if (transform == NULL) + continue; + } + else + { + transform = NULL; + } + gsk_transform_to_matrix (transform, &inv); + gsk_transform_unref (transform); + graphene_point3d_init (&p0, x, y, 0); + graphene_point3d_init (&p1, x, y, 1); + graphene_matrix_transform_point3d (&inv, &p0, &p0); + graphene_matrix_transform_point3d (&inv, &p1, &p1); + if (fabs (p0.z - p1.z) < 1.f / 4096) + continue; + + graphene_point3d_interpolate (&p0, &p1, p0.z / (p0.z - p1.z), &res); - picked = gtk_widget_pick (child, p.x, p.y); + picked = gtk_widget_pick (child, res.x, res.y); if (picked) return picked; } @@ -1653,23 +1670,6 @@ gtk_widget_class_init (GtkWidgetClass *klass) G_TYPE_BOOLEAN); /** - * GtkWidget::focus: - * @widget: the object which received the signal. - * @direction: - * - * Returns: %TRUE to stop other handlers from being invoked for the event. %FALSE to propagate the event further. - */ - widget_signals[FOCUS] = - g_signal_new (I_("focus"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkWidgetClass, focus), - _gtk_boolean_handled_accumulator, NULL, - _gtk_marshal_BOOLEAN__ENUM, - G_TYPE_BOOLEAN, 1, - GTK_TYPE_DIRECTION_TYPE); - - /** * GtkWidget::move-focus: * @widget: the object which received the signal. * @direction: @@ -2878,8 +2878,6 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class) priv->width_request = -1; priv->height_request = -1; - graphene_matrix_init_identity (&priv->transform); - _gtk_size_request_cache_init (&priv->requests); priv->cssnode = gtk_css_widget_node_new (widget); @@ -4129,10 +4127,10 @@ gtk_widget_size_allocate (GtkWidget *widget, const GtkAllocation *allocation, int baseline) { - GtkTransform *transform; + GskTransform *transform; if (allocation->x || allocation->y) - transform = gtk_transform_translate (NULL, &GRAPHENE_POINT_INIT (allocation->x, allocation->y)); + transform = gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (allocation->x, allocation->y)); else transform = NULL; @@ -4142,7 +4140,7 @@ gtk_widget_size_allocate (GtkWidget *widget, baseline, transform); - gtk_transform_unref (transform); + gsk_transform_unref (transform); } /** @@ -4167,7 +4165,7 @@ gtk_widget_allocate (GtkWidget *widget, int width, int height, int baseline, - GtkTransform *transform) + GskTransform *transform) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GdkRectangle adjusted; @@ -4179,8 +4177,7 @@ gtk_widget_allocate (GtkWidget *widget, gint min_width, min_height; GtkCssStyle *style; GtkBorder margin, border, padding; - graphene_matrix_t transform_matrix; - GtkTransform *css_transform; + GskTransform *css_transform; #ifdef G_ENABLE_DEBUG GdkDisplay *display; #endif @@ -4216,11 +4213,11 @@ gtk_widget_allocate (GtkWidget *widget, baseline_changed = priv->allocated_size_baseline != baseline; size_changed = (priv->allocated_width != width || priv->allocated_height != height); - transform_changed = !gtk_transform_equal (priv->allocated_transform, transform); + transform_changed = !gsk_transform_equal (priv->allocated_transform, transform); /* order is important, sometimes priv->allocated_transform == transform */ - gtk_transform_ref (transform); - gtk_transform_unref (priv->allocated_transform); + gsk_transform_ref (transform); + gsk_transform_unref (priv->allocated_transform); priv->allocated_transform = transform; priv->allocated_width = width; priv->allocated_height = height; @@ -4301,12 +4298,12 @@ gtk_widget_allocate (GtkWidget *widget, if (css_transform) { - transform = gtk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.x, adjusted.y)); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.x, adjusted.y)); adjusted.x = adjusted.y = 0; - transform = gtk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.width / 2, adjusted.height / 2)); - transform = gtk_transform_transform (transform, css_transform); - transform = gtk_transform_translate (transform, &GRAPHENE_POINT_INIT (- adjusted.width / 2, - adjusted.height / 2)); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.width / 2, adjusted.height / 2)); + transform = gsk_transform_transform (transform, css_transform); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (- adjusted.width / 2, - adjusted.height / 2)); } get_box_margin (style, &margin); @@ -4323,13 +4320,10 @@ gtk_widget_allocate (GtkWidget *widget, margin.bottom + border.bottom + padding.bottom; if (baseline >= 0) baseline -= margin.top + border.top + padding.top; - - graphene_matrix_init_translate (&priv->transform, &GRAPHENE_POINT3D_INIT (adjusted.x, adjusted.y, 0)); - gtk_transform_to_matrix (transform, &transform_matrix); - graphene_matrix_multiply (&priv->transform, &transform_matrix, &priv->transform); - priv->transform_category = gtk_transform_categorize (transform); if (adjusted.x || adjusted.y) - priv->transform_category = MIN (priv->transform_category, GSK_MATRIX_CATEGORY_2D_TRANSLATE); + transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.x, adjusted.y)); + + priv->transform = transform; if (!alloc_needed && !size_changed && !baseline_changed) { @@ -5309,107 +5303,25 @@ _gtk_widget_grab_notify (GtkWidget *widget, * gtk_widget_grab_focus: * @widget: a #GtkWidget * - * Causes @widget to have the keyboard focus for the #GtkWindow it's - * inside. @widget must be a focusable widget, such as a #GtkEntry; - * something like #GtkFrame won’t work. - * - * More precisely, it must have the %GTK_CAN_FOCUS flag set. Use - * gtk_widget_set_can_focus() to modify that flag. + * Causes @widget (or one of its descendents) to have the keyboard focus + * for the #GtkWindow it's inside. * - * The widget also needs to be realized and mapped. This is indicated by the - * related signals. Grabbing the focus immediately after creating the widget - * will likely fail and cause critical warnings. + * @widget must be focusable, or have a ::grab_focus implementation that + * transfers the focus to a descendant of @widget that is focusable. **/ void gtk_widget_grab_focus (GtkWidget *widget) { g_return_if_fail (GTK_IS_WIDGET (widget)); - if (!gtk_widget_is_sensitive (widget)) - return; - - g_object_ref (widget); GTK_WIDGET_GET_CLASS (widget)->grab_focus (widget); - g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]); - g_object_unref (widget); -} - -static void -reset_focus_recurse (GtkWidget *widget, - gpointer data) -{ - gtk_widget_set_focus_child (widget, NULL); - - gtk_widget_forall (widget, - reset_focus_recurse, - NULL); } static void gtk_widget_real_grab_focus (GtkWidget *focus_widget) { - GtkWidget *toplevel; - GtkWidget *widget; - - /* clear the current focus setting, break if the current widget - * is the focus widget's parent, since containers above that will - * be set by the next loop. - */ - toplevel = _gtk_widget_get_toplevel (focus_widget); - if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel)) - { - widget = gtk_window_get_focus (GTK_WINDOW (toplevel)); - - if (widget == focus_widget) - { - /* We call _gtk_window_internal_set_focus() here so that the - * toplevel window can request the focus if necessary. - * This is needed when the toplevel is a GtkPlug - */ - if (!gtk_widget_has_focus (widget)) - _gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget); - - return; - } - - if (widget) - { - GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget); - - if (widget != common_ancestor) - { - while (widget->priv->parent) - { - widget = widget->priv->parent; - gtk_widget_set_focus_child (widget, NULL); - if (widget == common_ancestor) - break; - } - } - } - } - else if (toplevel != focus_widget) - { - /* gtk_widget_grab_focus() operates on a tree without window... - * actually, this is very questionable behavior. - */ - - gtk_widget_forall (toplevel, - reset_focus_recurse, - NULL); - } - - /* now propagate the new focus up the widget tree and finally - * set it on the window - */ - widget = focus_widget; - while (widget->priv->parent) - { - gtk_widget_set_focus_child (widget->priv->parent, widget); - widget = widget->priv->parent; - } - if (GTK_IS_WINDOW (widget)) - _gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget); + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (focus_widget); + gtk_root_set_focus (priv->root, focus_widget); } static gboolean @@ -5524,17 +5436,8 @@ gtk_widget_real_focus (GtkWidget *widget, } else { - GPtrArray *focus_order = g_ptr_array_new (); - gboolean ret = FALSE; - - /* Try focusing any of the child widgets, depending on the given @direction */ - - gtk_widget_focus_sort (widget, direction, focus_order); - ret = gtk_widget_focus_move (widget, direction, focus_order); - - g_ptr_array_unref (focus_order); - - if (ret) + /* Try focusing any of the child widgets, depending on the given direction */ + if (gtk_widget_focus_move (widget, direction)) return TRUE; } @@ -5548,10 +5451,7 @@ gtk_widget_real_move_focus (GtkWidget *widget, GtkWidget *toplevel = _gtk_widget_get_toplevel (widget); if (widget != toplevel && GTK_IS_WINDOW (toplevel)) - { - g_signal_emit (toplevel, widget_signals[MOVE_FOCUS], 0, - direction); - } + g_signal_emit (toplevel, widget_signals[MOVE_FOCUS], 0, direction); } static gboolean @@ -5582,9 +5482,15 @@ gtk_widget_real_keynav_failed (GtkWidget *widget, * @widget: a #GtkWidget * @can_focus: whether or not @widget can own the input focus. * - * Specifies whether @widget can own the input focus. See - * gtk_widget_grab_focus() for actually setting the input focus on a - * widget. + * Specifies whether @widget can own the input focus. + * + * Note that having @can_focus be %TRUE is only one of the + * necessary conditions for being focusable. A widget must + * also be sensitive and not have a ancestor that is marked + * as not child-focusable in order to receive input focus. + * + * See gtk_widget_grab_focus() for actually setting the input + * focus on a widget. **/ void gtk_widget_set_can_focus (GtkWidget *widget, @@ -5697,16 +5603,14 @@ gtk_widget_has_visible_focus (GtkWidget *widget) gboolean gtk_widget_is_focus (GtkWidget *widget) { - GtkWidget *toplevel; + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); - toplevel = _gtk_widget_get_toplevel (widget); + if (priv->root) + return widget == gtk_root_get_focus (priv->root); - if (GTK_IS_WINDOW (toplevel)) - return widget == gtk_window_get_focus (GTK_WINDOW (toplevel)); - else - return FALSE; + return FALSE; } /** @@ -6213,11 +6117,11 @@ _gtk_widget_set_visible_flag (GtkWidget *widget, if (!visible) { - g_clear_pointer (&priv->allocated_transform, gtk_transform_unref); + g_clear_pointer (&priv->allocated_transform, gsk_transform_unref); priv->allocated_width = 0; priv->allocated_height = 0; priv->allocated_size_baseline = 0; - graphene_matrix_init_identity (&priv->transform); + g_clear_pointer (&priv->transform, gsk_transform_unref); priv->width = 0; priv->height = 0; gtk_widget_update_paintables (widget); @@ -7568,8 +7472,6 @@ gboolean gtk_widget_child_focus (GtkWidget *widget, GtkDirectionType direction) { - gboolean return_val; - g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); if (!_gtk_widget_get_visible (widget) || @@ -7581,12 +7483,7 @@ gtk_widget_child_focus (GtkWidget *widget, * focus */ - g_signal_emit (widget, - widget_signals[FOCUS], - 0, - direction, &return_val); - - return return_val; + return GTK_WIDGET_GET_CLASS (widget)->focus (widget, direction); } /** @@ -8912,14 +8809,7 @@ gtk_widget_propagate_state (GtkWidget *widget, priv->state_flags |= GTK_STATE_FLAG_INSENSITIVE; if (gtk_widget_is_focus (widget) && !gtk_widget_is_sensitive (widget)) - { - GtkWidget *window; - - window = _gtk_widget_get_toplevel (widget); - - if (window && _gtk_widget_is_toplevel (window)) - gtk_window_set_focus (GTK_WINDOW (window), NULL); - } + gtk_root_set_focus (priv->root, NULL); new_flags = priv->state_flags; @@ -11068,6 +10958,7 @@ gtk_widget_get_allocation (GtkWidget *widget, { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); const graphene_rect_t *margin_rect; + float dx, dy; GtkCssBoxes boxes; g_return_if_fail (GTK_IS_WIDGET (widget)); @@ -11076,10 +10967,13 @@ gtk_widget_get_allocation (GtkWidget *widget, gtk_css_boxes_init (&boxes, widget); margin_rect = gtk_css_boxes_get_margin_rect (&boxes); - allocation->x = graphene_matrix_get_value (&priv->transform, 3, 0) + - ceil (margin_rect->origin.x); - allocation->y = graphene_matrix_get_value (&priv->transform, 3, 1) + - ceil (margin_rect->origin.y); + if (gsk_transform_get_category (priv->transform) >= GSK_TRANSFORM_CATEGORY_2D_TRANSLATE) + gsk_transform_to_translate (priv->transform, &dx, &dy); + else + dx = dy = 0; + + allocation->x = dx + ceil (margin_rect->origin.x); + allocation->y = dy + ceil (margin_rect->origin.y); allocation->width = ceil (margin_rect->size.width); allocation->height = ceil (margin_rect->size.height); } @@ -11167,8 +11061,8 @@ gtk_widget_pick (GtkWidget *widget, gtk_css_boxes_init (&boxes, widget); - if (!graphene_rect_contains_point (gtk_css_boxes_get_padding_rect (&boxes), - &GRAPHENE_POINT_INIT (x, y))) + if (!gsk_rounded_rect_contains_point (gtk_css_boxes_get_padding_box (&boxes), + &GRAPHENE_POINT_INIT (x, y))) return NULL; } break; @@ -11198,7 +11092,7 @@ gtk_widget_compute_transform (GtkWidget *widget, graphene_matrix_t *out_transform) { GtkWidget *ancestor, *iter; - graphene_matrix_t transform, inverse; + graphene_matrix_t transform, inverse, tmp; g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (GTK_IS_WIDGET (target), FALSE); @@ -11207,7 +11101,7 @@ gtk_widget_compute_transform (GtkWidget *widget, /* optimization for common case: parent wants coordinates of a direct child */ if (target == widget->priv->parent) { - graphene_matrix_init_from_matrix (out_transform, &widget->priv->transform); + gsk_transform_to_matrix (widget->priv->transform, out_transform); return TRUE; } @@ -11222,8 +11116,9 @@ gtk_widget_compute_transform (GtkWidget *widget, for (iter = widget; iter != ancestor; iter = iter->priv->parent) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (iter); + gsk_transform_to_matrix (priv->transform, &tmp); - graphene_matrix_multiply (&transform, &priv->transform, &transform); + graphene_matrix_multiply (&transform, &tmp, &transform); } /* optimization for common case: parent wants coordinates of a non-direct child */ @@ -11237,8 +11132,9 @@ gtk_widget_compute_transform (GtkWidget *widget, for (iter = target; iter != ancestor; iter = iter->priv->parent) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (iter); + gsk_transform_to_matrix (priv->transform, &tmp); - graphene_matrix_multiply (&inverse, &priv->transform, &inverse); + graphene_matrix_multiply (&inverse, &tmp, &inverse); } if (!graphene_matrix_inverse (&inverse, &inverse)) { @@ -11678,59 +11574,17 @@ gtk_widget_get_overflow (GtkWidget *widget) return priv->overflow; } -/** - * gtk_widget_send_focus_change: - * @widget: a #GtkWidget - * @event: a #GdkEvent of type GDK_FOCUS_CHANGE - * - * Sends the focus change @event to @widget - * - * This function is not meant to be used by applications. The only time it - * should be used is when it is necessary for a #GtkWidget to assign focus - * to a widget that is semantically owned by the first widget even though - * it’s not a direct child - for instance, a search entry in a floating - * window similar to the quick search in #GtkTreeView. - * - * An example of its usage is: - * - * |[<!-- language="C" --> - * GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE); - * - * fevent->focus_change.type = GDK_FOCUS_CHANGE; - * fevent->focus_change.in = TRUE; - * fevent->focus_change.surface = _gtk_widget_get_surface (widget); - * if (fevent->focus_change.surface != NULL) - * g_object_ref (fevent->focus_change.surface); - * - * gtk_widget_send_focus_change (widget, fevent); - * - * g_object_unref (event); - * ]| - * - * Returns: the return value from the event signal emission: %TRUE - * if the event was handled, and %FALSE otherwise - */ -gboolean -gtk_widget_send_focus_change (GtkWidget *widget, - GdkEvent *event) +void +gtk_widget_set_has_focus (GtkWidget *widget, + gboolean has_focus) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); - gboolean res; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); - g_return_val_if_fail (event != NULL && event->any.type == GDK_FOCUS_CHANGE, FALSE); - - g_object_ref (widget); - - priv->has_focus = event->focus_change.in; - res = gtk_widget_event (widget, event); + if (priv->has_focus == has_focus) + return; + priv->has_focus = has_focus; g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]); - - g_object_unref (widget); - - return res; } /** @@ -12069,7 +11923,7 @@ gtk_widget_class_set_css_name (GtkWidgetClass *widget_class, static gboolean gtk_widget_class_get_visible_by_default (GtkWidgetClass *widget_class) { - return !(GTK_IS_WINDOW_CLASS (widget_class) || + return !(g_type_is_a (G_TYPE_FROM_CLASS (widget_class), GTK_TYPE_ROOT) || GTK_IS_POPOVER_CLASS (widget_class)); } @@ -13016,7 +12870,7 @@ gtk_widget_create_render_node (GtkWidget *widget, } if (priv->overflow == GTK_OVERFLOW_HIDDEN) - gtk_snapshot_push_clip (snapshot, gtk_css_boxes_get_padding_rect (&boxes)); + gtk_snapshot_push_rounded_clip (snapshot, gtk_css_boxes_get_padding_box (&boxes)); klass->snapshot (widget, snapshot); @@ -13418,7 +13272,7 @@ gtk_widget_snapshot_child (GtkWidget *widget, g_return_if_fail (snapshot != NULL); gtk_snapshot_save (snapshot); - gtk_snapshot_transform_matrix_with_category (snapshot, &priv->transform, priv->transform_category); + gtk_snapshot_transform (snapshot, priv->transform); gtk_widget_snapshot (child, snapshot); @@ -13452,26 +13306,7 @@ gtk_widget_set_focus_child (GtkWidget *widget, g_return_if_fail (gtk_widget_get_parent (child) == widget); } - if (priv->focus_child) - gtk_widget_unset_state_flags (priv->focus_child, - GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_FOCUS_VISIBLE); - - if (child) - { - GtkWidget *toplevel; - GtkStateFlags flags = GTK_STATE_FLAG_FOCUSED; - - toplevel = _gtk_widget_get_toplevel (widget); - if (!GTK_IS_WINDOW (toplevel) || gtk_window_get_focus_visible (GTK_WINDOW (toplevel))) - flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; - - gtk_widget_set_state_flags (child, flags, FALSE); - } - g_set_object (&priv->focus_child, child); - - if (GTK_IS_CONTAINER (widget)) - gtk_container_set_focus_child (GTK_CONTAINER (widget), child); } /** @@ -13480,7 +13315,7 @@ gtk_widget_set_focus_child (GtkWidget *widget, * * Returns the current focus child of @widget. * - * Returns: (nullable): The current focus child of @widget, + * Returns: (nullable): (transfer none): The current focus child of @widget, * or %NULL in case the focus child is unset. */ GtkWidget * diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index db4a81272c..97848c698e 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -407,7 +407,7 @@ void gtk_widget_allocate (GtkWidget *widget, int width, int height, int baseline, - GtkTransform *transform); + GskTransform *transform); GDK_AVAILABLE_IN_ALL GtkSizeRequestMode gtk_widget_get_request_mode (GtkWidget *widget); @@ -451,9 +451,6 @@ gboolean gtk_widget_mnemonic_activate (GtkWidget *widget, GDK_AVAILABLE_IN_ALL gboolean gtk_widget_event (GtkWidget *widget, const GdkEvent *event); -GDK_AVAILABLE_IN_ALL -gboolean gtk_widget_send_focus_change (GtkWidget *widget, - GdkEvent *event); GDK_AVAILABLE_IN_ALL gboolean gtk_widget_activate (GtkWidget *widget); @@ -1063,6 +1060,9 @@ GDK_AVAILABLE_IN_ALL void gtk_widget_set_focus_child (GtkWidget *widget, GtkWidget *child); GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_widget_get_focus_child (GtkWidget *widget); + +GDK_AVAILABLE_IN_ALL void gtk_widget_snapshot_child (GtkWidget *widget, GtkWidget *child, GtkSnapshot *snapshot); diff --git a/gtk/gtkwidgetfocus.c b/gtk/gtkwidgetfocus.c index af68bd7a56..26f7f8ae24 100644 --- a/gtk/gtkwidgetfocus.c +++ b/gtk/gtkwidgetfocus.c @@ -155,15 +155,11 @@ static gboolean old_focus_coords (GtkWidget *widget, graphene_rect_t *old_focus_bounds) { - GtkWidget *toplevel = _gtk_widget_get_toplevel (widget); GtkWidget *old_focus; - if (GTK_IS_WINDOW (toplevel)) - { - old_focus = gtk_window_get_focus (GTK_WINDOW (toplevel)); - if (old_focus) - return gtk_widget_compute_bounds (old_focus, widget, old_focus_bounds); - } + old_focus = gtk_root_get_focus (gtk_widget_get_root (widget)); + if (old_focus) + return gtk_widget_compute_bounds (old_focus, widget, old_focus_bounds); return FALSE; } @@ -426,7 +422,9 @@ gtk_widget_focus_sort (GtkWidget *widget, child != NULL; child = _gtk_widget_get_next_sibling (child)) { - if (_gtk_widget_get_realized (child)) + if (_gtk_widget_get_realized (child) && + _gtk_widget_is_drawable (child) && + gtk_widget_get_sensitive (child)) g_ptr_array_add (focus_order, child); } } @@ -454,13 +452,17 @@ gtk_widget_focus_sort (GtkWidget *widget, gboolean gtk_widget_focus_move (GtkWidget *widget, - GtkDirectionType direction, - GPtrArray *focus_order) + GtkDirectionType direction) { + GPtrArray *focus_order; GtkWidget *focus_child = gtk_widget_get_focus_child (widget); int i; + gboolean ret = FALSE; - for (i = 0; i < focus_order->len; i ++) + focus_order = g_ptr_array_new (); + gtk_widget_focus_sort (widget, direction, focus_order); + + for (i = 0; i < focus_order->len && !ret; i++) { GtkWidget *child = g_ptr_array_index (focus_order, i); @@ -469,18 +471,17 @@ gtk_widget_focus_move (GtkWidget *widget, if (focus_child == child) { focus_child = NULL; - - if (gtk_widget_child_focus (child, direction)) - return TRUE; + ret = gtk_widget_child_focus (child, direction); } } else if (_gtk_widget_is_drawable (child) && gtk_widget_is_ancestor (child, widget)) { - if (gtk_widget_child_focus (child, direction)) - return TRUE; + ret = gtk_widget_child_focus (child, direction); } } - return FALSE; + g_ptr_array_unref (focus_order); + + return ret; } diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 49c4d19de0..9ede6b8b79 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -144,13 +144,12 @@ struct _GtkWidgetPrivate GtkStyleContext *context; /* The widget's allocated size */ - GtkTransform *allocated_transform; + GskTransform *allocated_transform; int allocated_width; int allocated_height; gint allocated_size_baseline; - graphene_matrix_t transform; - GskMatrixCategory transform_category; + GskTransform *transform; int width; int height; int baseline; @@ -243,6 +242,12 @@ GdkSurface * _gtk_widget_get_device_surface (GtkWidget *widget, GdkDevice *device); GList * _gtk_widget_list_devices (GtkWidget *widget); +void gtk_synthesize_crossing_events (GtkRoot *toplevel, + GtkWidget *from, + GtkWidget *to, + GdkEvent *event, + GdkCrossingMode mode); + void _gtk_widget_synthesize_crossing (GtkWidget *from, GtkWidget *to, GdkDevice *device, @@ -312,14 +317,13 @@ void gtk_widget_forall (GtkWidget GtkCallback callback, gpointer user_data); -GtkWidget *gtk_widget_get_focus_child (GtkWidget *widget); - void gtk_widget_focus_sort (GtkWidget *widget, GtkDirectionType direction, GPtrArray *focus_order); gboolean gtk_widget_focus_move (GtkWidget *widget, - GtkDirectionType direction, - GPtrArray *focus_order); + GtkDirectionType direction); +void gtk_widget_set_has_focus (GtkWidget *widget, + gboolean has_focus); void gtk_widget_get_surface_allocation (GtkWidget *widget, GtkAllocation *allocation); @@ -336,6 +340,7 @@ gboolean gtk_widget_run_controllers (GtkWidget const GdkEvent *event, GtkPropagationPhase phase); + /* inline getters */ static inline GtkWidget * diff --git a/gtk/gtkwin32themeprivate.h b/gtk/gtkwin32themeprivate.h index 9ea7777366..056e098062 100644 --- a/gtk/gtkwin32themeprivate.h +++ b/gtk/gtkwin32themeprivate.h @@ -20,6 +20,7 @@ #ifndef __GTK_WIN32_THEME_PART_H__ #define __GTK_WIN32_THEME_PART_H__ +#include "gtkborder.h" #include "gtkcssparserprivate.h" G_BEGIN_DECLS diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 600e96e515..091a432e81 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -122,16 +122,12 @@ * elements representing the #GtkAccelGroup objects you want to add to * your window (synonymous with gtk_window_add_accel_group(). * - * It also supports the <initial-focus> element, whose name property names - * the widget to receive the focus when the window is mapped. - * * An example of a UI definition fragment with accel groups: * |[ * <object class="GtkWindow"> * <accel-groups> * <group name="accelgroup1"/> * </accel-groups> - * <initial-focus name="thunderclap"/> * </object> * * ... @@ -440,8 +436,6 @@ static gint gtk_window_focus (GtkWidget *widget, GtkDirectionType direction); static void gtk_window_move_focus (GtkWidget *widget, GtkDirectionType dir); -static void gtk_window_real_set_focus (GtkWindow *window, - GtkWidget *focus); static void gtk_window_real_activate_default (GtkWindow *window); static void gtk_window_real_activate_focus (GtkWindow *window); @@ -816,8 +810,6 @@ gtk_window_class_init (GtkWindowClass *klass) container_class->remove = gtk_window_remove; container_class->forall = gtk_window_forall; - klass->set_focus = gtk_window_real_set_focus; - klass->activate_default = gtk_window_real_activate_default; klass->activate_focus = gtk_window_real_activate_focus; klass->keys_changed = gtk_window_keys_changed; @@ -1118,24 +1110,7 @@ gtk_window_class_init (GtkWindowClass *klass) GTK_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (gobject_class, LAST_ARG, window_props); - - /** - * GtkWindow:set-focus: - * @window: the window which received the signal - * @widget: (nullable): the newly focused widget (or %NULL for no focus) - * - * This signal is emitted whenever the currently focused widget in - * this window changes. - */ - window_signals[SET_FOCUS] = - g_signal_new (I_("set-focus"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkWindowClass, set_focus), - NULL, NULL, - NULL, - G_TYPE_NONE, 1, - GTK_TYPE_WIDGET); + gtk_root_install_properties (gobject_class, LAST_ARG); /** * GtkWindow::activate-focus: @@ -2095,6 +2070,9 @@ gtk_window_set_property (GObject *object, case PROP_FOCUS_VISIBLE: gtk_window_set_focus_visible (window, g_value_get_boolean (value)); break; + case LAST_ARG + GTK_ROOT_PROP_FOCUS_WIDGET: + gtk_window_set_focus (window, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2210,6 +2188,9 @@ gtk_window_get_property (GObject *object, case PROP_IS_MAXIMIZED: g_value_set_boolean (value, gtk_window_is_maximized (window)); break; + case LAST_ARG + GTK_ROOT_PROP_FOCUS_WIDGET: + g_value_set_object (value, gtk_window_get_focus (window)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2365,55 +2346,6 @@ static const GMarkupParser window_parser = window_start_element }; -typedef struct { - GObject *object; - GtkBuilder *builder; - gchar *name; - gint line; - gint col; -} NameSubParserData; - -static void -focus_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **names, - const gchar **values, - gpointer user_data, - GError **error) -{ - NameSubParserData *data = (NameSubParserData*)user_data; - - if (strcmp (element_name, "initial-focus") == 0) - { - const gchar *name; - - if (!_gtk_builder_check_parent (data->builder, context, "object", error)) - return; - - if (!g_markup_collect_attributes (element_name, names, values, error, - G_MARKUP_COLLECT_STRING, "name", &name, - G_MARKUP_COLLECT_INVALID)) - { - _gtk_builder_prefix_error (data->builder, context, error); - return; - } - - data->name = g_strdup (name); - g_markup_parse_context_get_position (context, &data->line, &data->col); - } - else - { - _gtk_builder_error_unhandled_tag (data->builder, context, - "GtkWindow", element_name, - error); - } -} - -static const GMarkupParser focus_parser = -{ - focus_start_element -}; - static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable, GtkBuilder *builder, @@ -2441,21 +2373,6 @@ gtk_window_buildable_custom_tag_start (GtkBuildable *buildable, return TRUE; } - if (strcmp (tagname, "initial-focus") == 0) - { - NameSubParserData *data; - - data = g_slice_new0 (NameSubParserData); - data->name = NULL; - data->object = G_OBJECT (buildable); - data->builder = builder; - - *parser = focus_parser; - *parser_data = data; - - return TRUE; - } - return FALSE; } @@ -2478,23 +2395,6 @@ gtk_window_buildable_custom_finished (GtkBuildable *buildable, g_slice_free (GSListSubParserData, data); } - - if (strcmp (tagname, "initial-focus") == 0) - { - NameSubParserData *data = (NameSubParserData*)user_data; - - if (data->name) - { - GObject *object; - - object = _gtk_builder_lookup_object (builder, data->name, data->line, data->col); - if (object) - gtk_window_set_focus (GTK_WINDOW (buildable), GTK_WIDGET (object)); - g_free (data->name); - } - - g_slice_free (NameSubParserData, data); - } } static GdkDisplay * @@ -2772,70 +2672,6 @@ gtk_window_get_role (GtkWindow *window) } /** - * gtk_window_set_focus: - * @window: a #GtkWindow - * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset - * any focus widget for the toplevel window. - * - * If @focus is not the current focus widget, and is focusable, sets - * it as the focus widget for the window. If @focus is %NULL, unsets - * the focus widget for this window. To set the focus to a particular - * widget in the toplevel, it is usually more convenient to use - * gtk_widget_grab_focus() instead of this function. - **/ -void -gtk_window_set_focus (GtkWindow *window, - GtkWidget *focus) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *parent; - - g_return_if_fail (GTK_IS_WINDOW (window)); - - if (focus) - { - g_return_if_fail (GTK_IS_WIDGET (focus)); - g_return_if_fail (gtk_widget_get_can_focus (focus)); - - if (!gtk_widget_get_visible (GTK_WIDGET (window))) - priv->initial_focus = focus; - else - gtk_widget_grab_focus (focus); - } - else - { - /* Clear the existing focus chain, so that when we focus into - * the window again, we start at the beginnning. - */ - GtkWidget *widget = priv->focus_widget; - if (widget) - { - while ((parent = _gtk_widget_get_parent (widget))) - { - widget = parent; - gtk_widget_set_focus_child (widget, NULL); - } - } - - _gtk_window_internal_set_focus (window, NULL); - } -} - -void -_gtk_window_internal_set_focus (GtkWindow *window, - GtkWidget *focus) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - - g_return_if_fail (GTK_IS_WINDOW (window)); - - priv->initial_focus = NULL; - if ((priv->focus_widget != focus) || - (focus && !gtk_widget_has_focus (focus))) - g_signal_emit (window, window_signals[SET_FOCUS], 0, focus); -} - -/** * gtk_window_set_default: * @window: a #GtkWindow * @default_widget: (allow-none): widget to be the default, or %NULL @@ -7072,42 +6908,43 @@ gtk_window_real_activate_focus (GtkWindow *window) static void do_focus_change (GtkWidget *widget, - gboolean in) + gboolean in) { GdkSeat *seat; - GList *devices, *d; - - g_object_ref (widget); + GdkDevice *device; + GdkEvent *event; + GtkRoot *root; + GtkStateFlags flags; seat = gdk_display_get_default_seat (gtk_widget_get_display (widget)); - devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_KEYBOARD); - devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat)); - - for (d = devices; d; d = d->next) - { - GdkDevice *dev = d->data; - GdkEvent *fevent; - GdkSurface *surface; - - surface = _gtk_widget_get_surface (widget); - - fevent = gdk_event_new (GDK_FOCUS_CHANGE); - gdk_event_set_display (fevent, gtk_widget_get_display (widget)); - - fevent->any.type = GDK_FOCUS_CHANGE; - fevent->any.surface = surface; - if (surface) - g_object_ref (surface); - fevent->focus_change.in = in; - gdk_event_set_device (fevent, dev); - - gtk_widget_send_focus_change (widget, fevent); + device = gdk_seat_get_keyboard (seat); + + event = gdk_event_new (GDK_FOCUS_CHANGE); + gdk_event_set_display (event, gtk_widget_get_display (widget)); + gdk_event_set_device (event, device); + + event->any.type = GDK_FOCUS_CHANGE; + event->any.surface = _gtk_widget_get_surface (widget); + if (event->any.surface) + g_object_ref (event->any.surface); + event->focus_change.in = in; + event->focus_change.mode = GDK_CROSSING_STATE_CHANGED; + event->focus_change.detail = GDK_NOTIFY_ANCESTOR; + + flags = GTK_STATE_FLAG_FOCUSED; + root = gtk_widget_get_root (widget); + if (!GTK_IS_WINDOW (root) || gtk_window_get_focus_visible (GTK_WINDOW (root))) + flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; + + if (in) + gtk_widget_set_state_flags (widget, flags, FALSE); + else + gtk_widget_unset_state_flags (widget, flags); - g_object_unref (fevent); - } + gtk_widget_set_has_focus (widget, in); + gtk_widget_event (widget, event); - g_list_free (devices); - g_object_unref (widget); + g_object_unref (event); } static gboolean @@ -7325,80 +7162,56 @@ gtk_window_move_focus (GtkWidget *widget, gtk_window_set_focus (GTK_WINDOW (widget), NULL); } -static void -gtk_window_real_set_focus (GtkWindow *window, - GtkWidget *focus) +/** + * gtk_window_set_focus: + * @window: a #GtkWindow + * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset + * any focus widget for the toplevel window. + * + * If @focus is not the current focus widget, and is focusable, sets + * it as the focus widget for the window. If @focus is %NULL, unsets + * the focus widget for this window. To set the focus to a particular + * widget in the toplevel, it is usually more convenient to use + * gtk_widget_grab_focus() instead of this function. + **/ +void +gtk_window_set_focus (GtkWindow *window, + GtkWidget *focus) { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *old_focus = priv->focus_widget; - - if (old_focus) - { - g_object_ref (old_focus); - g_object_freeze_notify (G_OBJECT (old_focus)); - } - if (focus) - { - g_object_ref (focus); - g_object_freeze_notify (G_OBJECT (focus)); - } - - if (priv->focus_widget) - { - if (gtk_widget_get_receives_default (priv->focus_widget) && - (priv->focus_widget != priv->default_widget)) - { - _gtk_widget_set_has_default (priv->focus_widget, FALSE); + GtkWidget *old_focus = NULL; + GdkSeat *seat; + GdkDevice *device; + GdkEvent *event; - if (priv->default_widget) - _gtk_widget_set_has_default (priv->default_widget, TRUE); - } + g_return_if_fail (GTK_IS_WINDOW (window)); - priv->focus_widget = NULL; + if (focus && !gtk_widget_is_sensitive (focus)) + return; - if (priv->is_active) - do_focus_change (old_focus, FALSE); + if (priv->focus_widget) + old_focus = g_object_ref (priv->focus_widget); + g_set_object (&priv->focus_widget, NULL); - g_object_notify (G_OBJECT (old_focus), "is-focus"); - } + seat = gdk_display_get_default_seat (gtk_widget_get_display (GTK_WIDGET (window))); + device = gdk_seat_get_keyboard (seat); - /* The above notifications may have set a new focus widget, - * if so, we don't want to override it. - */ - if (focus && !priv->focus_widget) - { - priv->focus_widget = focus; + event = gdk_event_new (GDK_FOCUS_CHANGE); + gdk_event_set_display (event, gtk_widget_get_display (GTK_WIDGET (window))); + gdk_event_set_device (event, device); + event->any.surface = _gtk_widget_get_surface (GTK_WIDGET (window)); + if (event->any.surface) + g_object_ref (event->any.surface); - if (gtk_widget_get_receives_default (priv->focus_widget) && - (priv->focus_widget != priv->default_widget)) - { - if (gtk_widget_get_can_default (priv->focus_widget)) - _gtk_widget_set_has_default (priv->focus_widget, TRUE); + gtk_synthesize_crossing_events (GTK_ROOT (window), old_focus, focus, event, GDK_CROSSING_NORMAL); - if (priv->default_widget) - _gtk_widget_set_has_default (priv->default_widget, FALSE); - } + g_object_unref (event); - if (priv->is_active) - do_focus_change (priv->focus_widget, TRUE); + g_set_object (&priv->focus_widget, focus); - /* It's possible for do_focus_change() above to have callbacks - * that clear priv->focus_widget here. - */ - if (priv->focus_widget) - g_object_notify (G_OBJECT (priv->focus_widget), "is-focus"); - } + g_clear_object (&old_focus); - if (old_focus) - { - g_object_thaw_notify (G_OBJECT (old_focus)); - g_object_unref (old_focus); - } - if (focus) - { - g_object_thaw_notify (G_OBJECT (focus)); - g_object_unref (focus); - } + g_object_notify (G_OBJECT (window), "focus-widget"); } static void diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index fb30ab99b8..2b7a0078f5 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -57,7 +57,6 @@ struct _GtkWindow /** * GtkWindowClass: * @parent_class: The parent class. - * @set_focus: Sets child as the focus widget for the window. * @activate_focus: Activates the current focused widget within the window. * @activate_default: Activates the default widget for the window. * @keys_changed: Signal gets emitted when the set of accelerators or @@ -72,9 +71,6 @@ struct _GtkWindowClass /*< public >*/ - void (* set_focus) (GtkWindow *window, - GtkWidget *focus); - /* G_SIGNAL_ACTION signals for keybindings */ void (* activate_focus) (GtkWindow *window); diff --git a/gtk/icons/16x16/status/caps-lock-symbolic.symbolic.png b/gtk/icons/16x16/status/caps-lock-symbolic.symbolic.png Binary files differnew file mode 100644 index 0000000000..9951c0370d --- /dev/null +++ b/gtk/icons/16x16/status/caps-lock-symbolic.symbolic.png diff --git a/gtk/icons/16x16/status/eye-not-looking-symbolic.symbolic.png b/gtk/icons/16x16/status/eye-not-looking-symbolic.symbolic.png Binary files differnew file mode 100644 index 0000000000..3773d3cc30 --- /dev/null +++ b/gtk/icons/16x16/status/eye-not-looking-symbolic.symbolic.png diff --git a/gtk/icons/16x16/status/eye-open-negative-filled-symbolic.symbolic.png b/gtk/icons/16x16/status/eye-open-negative-filled-symbolic.symbolic.png Binary files differnew file mode 100644 index 0000000000..b642dd7566 --- /dev/null +++ b/gtk/icons/16x16/status/eye-open-negative-filled-symbolic.symbolic.png diff --git a/gtk/icons/scalable/status/caps-lock-symbolic.svg b/gtk/icons/scalable/status/caps-lock-symbolic.svg new file mode 100644 index 0000000000..dce3c0e41f --- /dev/null +++ b/gtk/icons/scalable/status/caps-lock-symbolic.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"> + <path d="M8.07.918L1 7.988h3v4h8v-4h3.143zM4 12.988v2h8v-2z" style="marker:none" color="#bebebe" fill="#2e3436"/> +</svg>
\ No newline at end of file diff --git a/gtk/icons/scalable/status/eye-not-looking-symbolic.svg b/gtk/icons/scalable/status/eye-not-looking-symbolic.svg new file mode 100644 index 0000000000..792a22ad8a --- /dev/null +++ b/gtk/icons/scalable/status/eye-not-looking-symbolic.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"> + <path d="M13.98 1.99a1 1 0 0 0-.687.303l-.984.984A8 8 0 0 0 8 2 8 8 0 0 0 .262 8.01a8 8 0 0 0 2.943 4.37l-.912.913a1 1 0 1 0 1.414 1.414l11-11a1 1 0 0 0-.727-1.717zM8 4a4 4 0 0 1 2.611.974l-1.42 1.42A2 2 0 0 0 8 6a2 2 0 0 0-2 2 2 2 0 0 0 .396 1.19l-1.42 1.42A4 4 0 0 1 4 8a4 4 0 0 1 4-4zm7.03 2.209l-3.344 3.343a4 4 0 0 1-2.127 2.127l-2.28 2.28a8 8 0 0 0 .721.04 8 8 0 0 0 7.738-6.01 8 8 0 0 0-.709-1.78zm-7.53.79a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5z" fill="#2e3436"/> +</svg>
\ No newline at end of file diff --git a/gtk/icons/scalable/status/eye-open-negative-filled-symbolic.svg b/gtk/icons/scalable/status/eye-open-negative-filled-symbolic.svg new file mode 100644 index 0000000000..f4e133a928 --- /dev/null +++ b/gtk/icons/scalable/status/eye-open-negative-filled-symbolic.svg @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns:osb="http://www.openswatchbook.org/uri/2009/osb" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="16" viewBox="0 0 16 16" version="1.1" id="svg7384" height="16"> + <metadata id="metadata90"> + <rdf:RDF> + <cc:Work rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <dc:title>Gnome Symbolic Icon Theme</dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <title id="title9167">Gnome Symbolic Icon Theme</title> + <defs id="defs7386"> + <linearGradient osb:paint="solid" id="linearGradient7212"> + <stop style="stop-color:#000000;stop-opacity:1;" offset="0" id="stop7214"/> + </linearGradient> + </defs> + <g transform="translate(-341.0002,-13.000323)" style="display:inline" id="layer9"/> + <g transform="translate(-100,-380.00032)" id="layer1"/> + <g transform="translate(-100,-380.00032)" style="display:inline" id="layer10"> + <path d="m 108,382 a 8,8 0 0 0 -7.73828,6.00977 A 8,8 0 0 0 108,394 8,8 0 0 0 115.73828,387.99023 8,8 0 0 0 108,382 Z m 0,2 a 4,4 0 0 1 4,4 4,4 0 0 1 -4,4 4,4 0 0 1 -4,-4 4,4 0 0 1 4,-4 z" id="path2314" style="opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"/> + <path id="path2318" d="m 110,388.00003 a 2,2 0 0 1 -2,2 2,2 0 0 1 -2,-2 2,2 0 0 1 2,-2 2,2 0 0 1 2,2 z" style="vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> + </g> + <g transform="translate(-100,-380.00032)" id="g6387"/> + <g transform="translate(-100,-380.00032)" id="layer11"/> +</svg>
\ No newline at end of file diff --git a/gtk/inspector/misc-info.c b/gtk/inspector/misc-info.c index 9c3b3ec05f..1d9d053d7d 100644 --- a/gtk/inspector/misc-info.c +++ b/gtk/inspector/misc-info.c @@ -46,9 +46,6 @@ struct _GtkInspectorMiscInfoPrivate { GtkWidget *default_widget_row; GtkWidget *default_widget; GtkWidget *default_widget_button; - GtkWidget *focus_widget_row; - GtkWidget *focus_widget; - GtkWidget *focus_widget_button; GtkWidget *mnemonic_label_row; GtkWidget *mnemonic_label; GtkWidget *request_mode_row; @@ -218,43 +215,6 @@ show_default_widget (GtkWidget *button, GtkInspectorMiscInfo *sl) } static void -update_focus_widget (GtkInspectorMiscInfo *sl) -{ - GtkWidget *widget; - - widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->object)); - if (widget) - { - gchar *tmp; - tmp = g_strdup_printf ("%p", widget); - gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), tmp); - g_free (tmp); - gtk_widget_set_sensitive (sl->priv->focus_widget_button, TRUE); - } - else - { - gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), "NULL"); - gtk_widget_set_sensitive (sl->priv->focus_widget_button, FALSE); - } -} - -static void -set_focus_cb (GtkWindow *window, GtkWidget *focus, GtkInspectorMiscInfo *sl) -{ - update_focus_widget (sl); -} - -static void -show_focus_widget (GtkWidget *button, GtkInspectorMiscInfo *sl) -{ - GtkWidget *widget; - - widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->object)); - if (widget) - show_object (sl, G_OBJECT (widget), "properties"); -} - -static void show_mnemonic_label (GtkWidget *button, GtkInspectorMiscInfo *sl) { GtkWidget *widget; @@ -358,7 +318,6 @@ update_info (gpointer data) if (GTK_IS_WINDOW (sl->priv->object)) { update_default_widget (sl); - update_focus_widget (sl); } if (GDK_IS_FRAME_CLOCK (sl->priv->object)) @@ -408,7 +367,6 @@ gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl, if (sl->priv->object) { g_signal_handlers_disconnect_by_func (sl->priv->object, state_flags_changed, sl); - g_signal_handlers_disconnect_by_func (sl->priv->object, set_focus_cb, sl); g_signal_handlers_disconnect_by_func (sl->priv->object, allocation_changed, sl); disconnect_each_other (sl->priv->object, G_OBJECT (sl)); disconnect_each_other (sl, sl->priv->object); @@ -475,14 +433,10 @@ gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl, if (GTK_IS_WINDOW (object)) { gtk_widget_show (sl->priv->default_widget_row); - gtk_widget_show (sl->priv->focus_widget_row); - - g_signal_connect_object (object, "set-focus", G_CALLBACK (set_focus_cb), sl, G_CONNECT_AFTER); } else { gtk_widget_hide (sl->priv->default_widget_row); - gtk_widget_hide (sl->priv->focus_widget_row); } if (GDK_IS_FRAME_CLOCK (object)) @@ -595,9 +549,6 @@ gtk_inspector_misc_info_class_init (GtkInspectorMiscInfoClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_row); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_button); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_row); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_button); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, mnemonic_label_row); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, mnemonic_label); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, request_mode_row); @@ -631,7 +582,6 @@ gtk_inspector_misc_info_class_init (GtkInspectorMiscInfoClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, child_visible); gtk_widget_class_bind_template_callback (widget_class, show_default_widget); - gtk_widget_class_bind_template_callback (widget_class, show_focus_widget); gtk_widget_class_bind_template_callback (widget_class, show_frame_clock); } diff --git a/gtk/inspector/misc-info.ui b/gtk/inspector/misc-info.ui index 0ee5082e24..cbb3ef65b4 100644 --- a/gtk/inspector/misc-info.ui +++ b/gtk/inspector/misc-info.ui @@ -158,42 +158,6 @@ </object> </child> <child> - <object class="GtkListBoxRow" id="focus_widget_row"> - <property name="activatable">0</property> - <child> - <object class="GtkBox"> - <property name="margin">10</property> - <property name="spacing">40</property> - <child> - <object class="GtkLabel" id="focus_widget_label"> - <property name="label" translatable="yes">Focus Widget</property> - <property name="halign">start</property> - <property name="valign">baseline</property> - <property name="xalign">0.0</property> - <property name="hexpand">1</property> - </object> - </child> - <child> - <object class="GtkLabel" id="focus_widget"> - <property name="selectable">1</property> - <property name="halign">end</property> - <property name="valign">baseline</property> - <property name="ellipsize">end</property> - </object> - </child> - <child> - <object class="GtkButton" id="focus_widget_button"> - <property name="halign">end</property> - <property name="valign">baseline</property> - <property name="label" translatable="yes">Properties</property> - <signal name="clicked" handler="show_focus_widget"/> - </object> - </child> - </object> - </child> - </object> - </child> - <child> <object class="GtkListBoxRow" id="mnemonic_label_row"> <property name="activatable">0</property> <child> @@ -616,7 +580,6 @@ <widget name="state_label"/> <widget name="buildable_id_label"/> <widget name="default_widget_label"/> - <widget name="focus_widget_label"/> <widget name="frame_clock_label"/> </widgets> </object> diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c index 7230b6bd74..788d96d72a 100644 --- a/gtk/inspector/recorder.c +++ b/gtk/inspector/recorder.c @@ -33,6 +33,7 @@ #include <gsk/gskrendererprivate.h> #include <gsk/gskrendernodeprivate.h> #include <gsk/gskroundedrectprivate.h> +#include <gsk/gsktransformprivate.h> #include <glib/gi18n-lib.h> #include <gdk/gdktextureprivate.h> @@ -889,26 +890,22 @@ populate_render_node_properties (GtkListStore *store, case GSK_TRANSFORM_NODE: { static const char * category_names[] = { - [GSK_MATRIX_CATEGORY_UNKNOWN] = "unknown", - [GSK_MATRIX_CATEGORY_ANY] = "any", - [GSK_MATRIX_CATEGORY_INVERTIBLE] = "invertible", - [GSK_MATRIX_CATEGORY_2D_AFFINE] = "2D affine", - [GSK_MATRIX_CATEGORY_2D_TRANSLATE] = "2D transform", - [GSK_MATRIX_CATEGORY_IDENTITY] = "identity" + [GSK_TRANSFORM_CATEGORY_UNKNOWN] = "unknown", + [GSK_TRANSFORM_CATEGORY_ANY] = "any", + [GSK_TRANSFORM_CATEGORY_3D] = "3D", + [GSK_TRANSFORM_CATEGORY_2D] = "2D", + [GSK_TRANSFORM_CATEGORY_2D_AFFINE] = "2D affine", + [GSK_TRANSFORM_CATEGORY_2D_TRANSLATE] = "2D translate", + [GSK_TRANSFORM_CATEGORY_IDENTITY] = "identity" }; - float f[16]; - guint i; - - graphene_matrix_to_float (gsk_transform_node_peek_transform (node), f); - for (i = 0; i < 4; i++) - { - char *row_string = g_strdup_printf ("%.2f, %.2f, %.2f, %.2f", - f[4 * i], f[4 * i + 1], - f[4 * i + 2], f[4 * i + 3]); - add_text_row (store, i == 0 ? "Matrix" : "", row_string); - g_free (row_string); - } - add_text_row (store, "Category", category_names[gsk_transform_node_get_category (node)]); + GskTransform *transform; + char *s; + + transform = gsk_transform_node_get_transform (node); + s = gsk_transform_to_string (transform); + add_text_row (store, "Matrix", s); + g_free (s); + add_text_row (store, "Category", category_names[gsk_transform_get_category (transform)]); } break; diff --git a/gtk/inspector/size-groups.c b/gtk/inspector/size-groups.c index 59ef51e7e6..0537edba00 100644 --- a/gtk/inspector/size-groups.c +++ b/gtk/inspector/size-groups.c @@ -28,6 +28,7 @@ #include "gtklabel.h" #include "gtklistbox.h" #include "gtksizegroup.h" +#include "gtkstylecontext.h" #include "gtkswitch.h" #include "gtkwidgetprivate.h" diff --git a/gtk/meson.build b/gtk/meson.build index 2c705982a9..714c0eab65 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -375,7 +375,6 @@ gtk_public_sources = files([ 'gtktoolshell.c', 'gtktooltip.c', 'gtktooltipwindow.c', - 'gtktransform.c', 'gtktreednd.c', 'gtktreelistmodel.c', 'gtktreemenu.c', @@ -606,7 +605,6 @@ gtk_public_headers = files([ 'gtktoolitem.h', 'gtktoolshell.h', 'gtktooltip.h', - 'gtktransform.h', 'gtktreednd.h', 'gtktreelistmodel.h', 'gtktreemodel.h', diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss index ff3a18f74b..8075197c41 100644 --- a/gtk/theme/Adwaita/_common.scss +++ b/gtk/theme/Adwaita/_common.scss @@ -32,7 +32,7 @@ flowboxchild:focus(visible) { outline-style: dashed; outline-offset: -3px; outline-width: 1px; - -gtk-outline-radius: 2px; + -gtk-outline-radius: $button-radius - 2; } @@ -338,6 +338,10 @@ entry { &:backdrop { color: mix($backdrop_fg_color, $backdrop_base_color, 80%); } } + &.password image.caps-lock-indicator { + color: mix($backdrop_fg_color, $backdrop_base_color, 80%); + } + &:drop(active) { &:focus, & { border-color: $drop_target_color; @@ -1710,8 +1714,8 @@ headerbar { margin-bottom: 6px; } switch { - margin-top: 9px; - margin-bottom: 9px; + margin-top: 10px; + margin-bottom: 10px; } &.titlebar headerbar:not(.titlebar) { @@ -3912,7 +3916,7 @@ filechooserbutton:drop(active) { border-left-style: none; } - @at-root %sidebar_right + @at-root %sidebar_right, &:dir(rtl), &.right { border-left: 1px solid $borders_color; diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css index e90b45e880..82d94cb3b2 100644 --- a/gtk/theme/Adwaita/gtk-contained-dark.css +++ b/gtk/theme/Adwaita/gtk-contained-dark.css @@ -1,6 +1,6 @@ * { padding: 0; -gtk-secondary-caret-color: #15539e; } -button:focus(visible), checkbutton:focus(visible), radiobutton:focus(visible), switch:focus(visible), scale:focus(visible), label:focus(visible), row:focus(visible), flowboxchild:focus(visible) { outline-color: alpha(currentColor,0.3); outline-style: dashed; outline-offset: -3px; outline-width: 1px; -gtk-outline-radius: 2px; } +button:focus(visible), checkbutton:focus(visible), radiobutton:focus(visible), switch:focus(visible), scale:focus(visible), label:focus(visible), row:focus(visible), flowboxchild:focus(visible) { outline-color: alpha(currentColor,0.3); outline-style: dashed; outline-offset: -3px; outline-width: 1px; -gtk-outline-radius: 3px; } /*************** Base States * */ .background { color: #eeeeec; background-color: #353535; } @@ -132,6 +132,8 @@ spinbutton:not(.vertical) image:active, spinbutton.vertical text image:active, e spinbutton:not(.vertical) image:backdrop, spinbutton.vertical text image:backdrop, entry image:backdrop { color: #7e7e7d; } +spinbutton.password:not(.vertical) image.caps-lock-indicator, spinbutton.vertical text.password image.caps-lock-indicator, entry.password image.caps-lock-indicator { color: #7e7e7d; } + spinbutton:drop(active):focus:not(.vertical), spinbutton.vertical text:drop(active):focus, spinbutton:drop(active):not(.vertical), spinbutton.vertical text:drop(active), entry:drop(active):focus, entry:drop(active) { border-color: #4e9a06; box-shadow: inset 0 0 0 1px #4e9a06; } .osd spinbutton:not(.vertical), .osd spinbutton.vertical text, spinbutton.vertical .osd text, .osd entry { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: rgba(0, 0, 0, 0.5); background-clip: padding-box; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; } @@ -692,7 +694,7 @@ searchbar > revealer > box { padding: 6px; border-width: 0 0 1px; } headerbar entry, headerbar spinbutton, headerbar separator:not(.sidebar), headerbar button { margin-top: 6px; margin-bottom: 6px; } -headerbar switch { margin-top: 9px; margin-bottom: 9px; } +headerbar switch { margin-top: 10px; margin-bottom: 10px; } headerbar.titlebar headerbar:not(.titlebar) { background: none; box-shadow: none; } @@ -1693,7 +1695,7 @@ filechooserbutton:drop(active) { box-shadow: none; border-color: transparent; } stacksidebar.sidebar:dir(ltr) list, stacksidebar.sidebar.left list, stacksidebar.sidebar.left:dir(rtl) list, .sidebar:not(separator):dir(ltr), .sidebar:not(separator).left, .sidebar:not(separator).left:dir(rtl) { border-right: 1px solid #1b1b1b; border-left-style: none; } -stacksidebar.sidebar:dir(rtl) list .sidebar:not(separator):dir(rtl), stacksidebar.sidebar.right list .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { border-left: 1px solid #1b1b1b; border-right-style: none; } +stacksidebar.sidebar:dir(rtl) list, stacksidebar.sidebar.right list, .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { border-left: 1px solid #1b1b1b; border-right-style: none; } .sidebar:backdrop { background-color: #323232; border-color: #202020; transition: 200ms ease-out; } diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css index 6365c872bf..c339a19bf4 100644 --- a/gtk/theme/Adwaita/gtk-contained.css +++ b/gtk/theme/Adwaita/gtk-contained.css @@ -1,6 +1,6 @@ * { padding: 0; -gtk-secondary-caret-color: #3584e4; } -button:focus(visible), checkbutton:focus(visible), radiobutton:focus(visible), switch:focus(visible), scale:focus(visible), label:focus(visible), row:focus(visible), flowboxchild:focus(visible) { outline-color: alpha(currentColor,0.3); outline-style: dashed; outline-offset: -3px; outline-width: 1px; -gtk-outline-radius: 2px; } +button:focus(visible), checkbutton:focus(visible), radiobutton:focus(visible), switch:focus(visible), scale:focus(visible), label:focus(visible), row:focus(visible), flowboxchild:focus(visible) { outline-color: alpha(currentColor,0.3); outline-style: dashed; outline-offset: -3px; outline-width: 1px; -gtk-outline-radius: 3px; } /*************** Base States * */ .background { color: #2e3436; background-color: #f6f5f4; } @@ -132,6 +132,8 @@ spinbutton:not(.vertical) image:active, spinbutton.vertical text image:active, e spinbutton:not(.vertical) image:backdrop, spinbutton.vertical text image:backdrop, entry image:backdrop { color: #a7aaaa; } +spinbutton.password:not(.vertical) image.caps-lock-indicator, spinbutton.vertical text.password image.caps-lock-indicator, entry.password image.caps-lock-indicator { color: #a7aaaa; } + spinbutton:drop(active):focus:not(.vertical), spinbutton.vertical text:drop(active):focus, spinbutton:drop(active):not(.vertical), spinbutton.vertical text:drop(active), entry:drop(active):focus, entry:drop(active) { border-color: #4e9a06; box-shadow: inset 0 0 0 1px #4e9a06; } .osd spinbutton:not(.vertical), .osd spinbutton.vertical text, spinbutton.vertical .osd text, .osd entry { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: rgba(0, 0, 0, 0.5); background-clip: padding-box; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; } @@ -700,7 +702,7 @@ searchbar > revealer > box { padding: 6px; border-width: 0 0 1px; } headerbar entry, headerbar spinbutton, headerbar separator:not(.sidebar), headerbar button { margin-top: 6px; margin-bottom: 6px; } -headerbar switch { margin-top: 9px; margin-bottom: 9px; } +headerbar switch { margin-top: 10px; margin-bottom: 10px; } headerbar.titlebar headerbar:not(.titlebar) { background: none; box-shadow: none; } @@ -1713,7 +1715,7 @@ filechooserbutton:drop(active) { box-shadow: none; border-color: transparent; } stacksidebar.sidebar:dir(ltr) list, stacksidebar.sidebar.left list, stacksidebar.sidebar.left:dir(rtl) list, .sidebar:not(separator):dir(ltr), .sidebar:not(separator).left, .sidebar:not(separator).left:dir(rtl) { border-right: 1px solid #cdc7c2; border-left-style: none; } -stacksidebar.sidebar:dir(rtl) list .sidebar:not(separator):dir(rtl), stacksidebar.sidebar.right list .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { border-left: 1px solid #cdc7c2; border-right-style: none; } +stacksidebar.sidebar:dir(rtl) list, stacksidebar.sidebar.right list, .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { border-left: 1px solid #cdc7c2; border-right-style: none; } .sidebar:backdrop { background-color: #f9f9f8; border-color: #d5d0cc; transition: 200ms ease-out; } |