summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'gtk')
-rw-r--r--gtk/a11y/gtkentryaccessible.c92
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkapplication-dbus.c2
-rw-r--r--gtk/gtkassistant.c7
-rw-r--r--gtk/gtkbutton.c1
-rw-r--r--gtk/gtkcalendar.c4
-rw-r--r--gtk/gtkcellarea.c1
-rw-r--r--gtk/gtkcellrenderer.c1
-rw-r--r--gtk/gtkcellrendererprogress.c1
-rw-r--r--gtk/gtkcellrenderertext.c1
-rw-r--r--gtk/gtkcolorbutton.c1
-rw-r--r--gtk/gtkcolorchooserwidget.c1
-rw-r--r--gtk/gtkcoloreditor.c3
-rw-r--r--gtk/gtkcolorswatch.c35
-rw-r--r--gtk/gtkcssboxesprivate.h1
-rw-r--r--gtk/gtkcssimageprivate.h1
-rw-r--r--gtk/gtkcssnodeprivate.h1
-rw-r--r--gtk/gtkcssparserprivate.h1
-rw-r--r--gtk/gtkcssshadowsvalueprivate.h1
-rw-r--r--gtk/gtkcssshadowvalueprivate.h1
-rw-r--r--gtk/gtkcsstransformvalue.c165
-rw-r--r--gtk/gtkcsstransformvalueprivate.h2
-rw-r--r--gtk/gtkcsstypesprivate.h1
-rw-r--r--gtk/gtkcssvalueprivate.h2
-rw-r--r--gtk/gtkdialog.c1
-rw-r--r--gtk/gtkdnd.c1
-rw-r--r--gtk/gtkeditable.c10
-rw-r--r--gtk/gtkemojichooser.c1
-rw-r--r--gtk/gtkemojicompletion.c1
-rw-r--r--gtk/gtkentry.c36
-rw-r--r--gtk/gtkeventcontrollerkey.c242
-rw-r--r--gtk/gtkeventcontrollerkey.h5
-rw-r--r--gtk/gtkeventcontrollermotion.c219
-rw-r--r--gtk/gtkeventcontrollermotion.h5
-rw-r--r--gtk/gtkfilechooserwidget.c23
-rw-r--r--gtk/gtkfontbutton.c13
-rw-r--r--gtk/gtkiconview.c4
-rw-r--r--gtk/gtkimcontextxim.c42
-rw-r--r--gtk/gtkinfobar.c1
-rw-r--r--gtk/gtklabel.c6
-rw-r--r--gtk/gtklinkbutton.c1
-rw-r--r--gtk/gtkmain.c156
-rw-r--r--gtk/gtkmenu.c8
-rw-r--r--gtk/gtkmenubutton.c17
-rw-r--r--gtk/gtkmenuitem.c20
-rw-r--r--gtk/gtkmessagedialog.c12
-rw-r--r--gtk/gtknotebook.c23
-rw-r--r--gtk/gtkorientable.c2
-rw-r--r--gtk/gtkoverlay.c11
-rw-r--r--gtk/gtkpaned.c50
-rw-r--r--gtk/gtkpasswordentry.c226
-rw-r--r--gtk/gtkpasswordentry.h6
-rw-r--r--gtk/gtkplacesview.c2
-rw-r--r--gtk/gtkpopover.c5
-rw-r--r--gtk/gtkrendericon.c10
-rw-r--r--gtk/gtkrevealer.c129
-rw-r--r--gtk/gtkrevealer.h6
-rw-r--r--gtk/gtkroot.c69
-rw-r--r--gtk/gtkroot.h6
-rw-r--r--gtk/gtkrootprivate.h8
-rw-r--r--gtk/gtkscrolledwindow.c2
-rw-r--r--gtk/gtksearchbar.c3
-rw-r--r--gtk/gtksearchentry.c21
-rw-r--r--gtk/gtkseparatortoolitem.c7
-rw-r--r--gtk/gtksettings.c17
-rw-r--r--gtk/gtkshortcutsshortcut.c1
-rw-r--r--gtk/gtkshortcutswindow.c7
-rw-r--r--gtk/gtksingleselection.c9
-rw-r--r--gtk/gtksnapshot.c127
-rw-r--r--gtk/gtksnapshot.h5
-rw-r--r--gtk/gtksnapshotprivate.h14
-rw-r--r--gtk/gtkspinbutton.c26
-rw-r--r--gtk/gtkstack.c34
-rw-r--r--gtk/gtkstackswitcher.c15
-rw-r--r--gtk/gtkstylecontext.h1
-rw-r--r--gtk/gtkstylecontextprivate.h2
-rw-r--r--gtk/gtktext.c34
-rw-r--r--gtk/gtktogglebutton.c7
-rw-r--r--gtk/gtktransform.c1113
-rw-r--r--gtk/gtktransform.h104
-rw-r--r--gtk/gtktransformprivate.h46
-rw-r--r--gtk/gtktreeview.c17
-rw-r--r--gtk/gtktreeviewcolumn.c9
-rw-r--r--gtk/gtktypes.h1
-rw-r--r--gtk/gtkviewport.c1
-rw-r--r--gtk/gtkwidget.c347
-rw-r--r--gtk/gtkwidget.h8
-rw-r--r--gtk/gtkwidgetfocus.c35
-rw-r--r--gtk/gtkwidgetprivate.h19
-rw-r--r--gtk/gtkwin32themeprivate.h1
-rw-r--r--gtk/gtkwindow.c339
-rw-r--r--gtk/gtkwindow.h4
-rw-r--r--gtk/icons/16x16/status/caps-lock-symbolic.symbolic.pngbin0 -> 154 bytes
-rw-r--r--gtk/icons/16x16/status/eye-not-looking-symbolic.symbolic.pngbin0 -> 324 bytes
-rw-r--r--gtk/icons/16x16/status/eye-open-negative-filled-symbolic.symbolic.pngbin0 -> 295 bytes
-rw-r--r--gtk/icons/scalable/status/caps-lock-symbolic.svg3
-rw-r--r--gtk/icons/scalable/status/eye-not-looking-symbolic.svg3
-rw-r--r--gtk/icons/scalable/status/eye-open-negative-filled-symbolic.svg26
-rw-r--r--gtk/inspector/misc-info.c50
-rw-r--r--gtk/inspector/misc-info.ui37
-rw-r--r--gtk/inspector/recorder.c35
-rw-r--r--gtk/inspector/size-groups.c1
-rw-r--r--gtk/meson.build2
-rw-r--r--gtk/theme/Adwaita/_common.scss12
-rw-r--r--gtk/theme/Adwaita/gtk-contained-dark.css8
-rw-r--r--gtk/theme/Adwaita/gtk-contained.css8
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)
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 62a3bb3d7f..34fff24a3f 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -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 == &GTK_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 (&GTK_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 (&GTK_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 (&GTK_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 (&GTK_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 (&GTK_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 (&GTK_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
new file mode 100644
index 0000000000..9951c0370d
--- /dev/null
+++ b/gtk/icons/16x16/status/caps-lock-symbolic.symbolic.png
Binary files differ
diff --git a/gtk/icons/16x16/status/eye-not-looking-symbolic.symbolic.png b/gtk/icons/16x16/status/eye-not-looking-symbolic.symbolic.png
new file mode 100644
index 0000000000..3773d3cc30
--- /dev/null
+++ b/gtk/icons/16x16/status/eye-not-looking-symbolic.symbolic.png
Binary files differ
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
new file mode 100644
index 0000000000..b642dd7566
--- /dev/null
+++ b/gtk/icons/16x16/status/eye-open-negative-filled-symbolic.symbolic.png
Binary files differ
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; }