Merge branch 'widget-class-actions-2' into 'master'

Widget class action

See merge request GNOME/gtk!948
This commit is contained in:
Matthias Clasen 2019-06-18 19:10:45 +00:00
commit cdee8270e2
14 changed files with 837 additions and 476 deletions

View File

@ -258,9 +258,11 @@
</para>
<para>
Actions are added to their relevant scope (application or
window) either using the GActionMap interface, or by using
gtk_widget_insert_action_group().
Actions are added to their relevant scope (application,
window or widget) either using the GActionMap interface,
or by using gtk_widget_insert_action_group(). Actions that
will be the same for all instances of a widget class can
be added globally using gtk_widget_class_install_action().
</para>
</refsect2>
@ -317,8 +319,8 @@
</para>
<para>
Another of obtaining widgets that are connected to actions is
to create a menu using a GMenu menu model. GMenu provides an
Another way of obtaining widgets that are connected to actions
is to create a menu using a GMenu menu model. GMenu provides an
abstract way to describe typical menus: nested groups of items
where each item can have a label, and icon, and an action.
</para>
@ -364,6 +366,25 @@
(typically a GtkWindow, GtkDialog or GtkPopover)
</para></listitem>
</varlistentry>
<varlistentry>
<term>clipboard.cut, clipboard.copy, clipboard.paste</term>
<listitem><para>Clipboard operations on entries, text view
and labels, typically used in the context menu
</para></listitem>
</varlistentry>
<varlistentry>
<term>selection.delete, selection.select-all</term>
<listitem><para>Selection operations on entries, text view
and labels
</para></listitem>
</varlistentry>
<varlistentry>
<term>color.select, color.customize</term>
<listitem><para>Operations on colors in GtkColorChooserWidget.
These actions are unusual in that they have the non-trivial
parameter type (dddd).
</para></listitem>
</varlistentry>
</variablelist>
</para>

View File

@ -4549,10 +4549,6 @@ gtk_widget_get_opacity
gtk_widget_set_opacity
gtk_widget_get_overflow
gtk_widget_set_overflow
gtk_widget_insert_action_group
gtk_widget_list_action_prefixes
gtk_widget_activate_action
gtk_widget_activate_default
gtk_widget_measure
gtk_widget_snapshot_child
gtk_widget_get_next_sibling
@ -4629,6 +4625,18 @@ gtk_widget_class_set_connect_func
gtk_widget_observe_children
gtk_widget_observe_controllers
<SUBSECTION Actions>
gtk_widget_insert_action_group
gtk_widget_activate_action
gtk_widget_activate_default
GtkWidgetActionActivateFunc
GtkWidgetActionSetStateFunc
GtkWidgetActionGetStateFunc
gtk_widget_class_install_action
gtk_widget_class_install_stateful_action
gtk_widget_action_enabled_changed
gtk_widget_action_state_changed
<SUBSECTION Standard>
GTK_WIDGET
GTK_IS_WIDGET

View File

@ -25,6 +25,7 @@
#include "gtkactionobserverprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkwidget.h"
#include <string.h>
@ -69,6 +70,10 @@ struct _GtkActionMuxer
GHashTable *groups;
GHashTable *primary_accels;
GtkActionMuxer *parent;
GtkWidget *widget;
GPtrArray *widget_actions;
gboolean *widget_actions_enabled;
};
G_DEFINE_TYPE_WITH_CODE (GtkActionMuxer, gtk_action_muxer, G_TYPE_OBJECT,
@ -79,6 +84,8 @@ enum
{
PROP_0,
PROP_PARENT,
PROP_WIDGET,
PROP_WIDGET_ACTIONS,
NUM_PROPERTIES
};
@ -104,7 +111,7 @@ typedef struct
static void
gtk_action_muxer_append_group_actions (const char *prefix,
Group *group,
GArray *actions)
GHashTable *actions)
{
gchar **group_actions;
gchar **action;
@ -112,10 +119,8 @@ gtk_action_muxer_append_group_actions (const char *prefix,
group_actions = g_action_group_list_actions (group->group);
for (action = group_actions; *action; action++)
{
gchar *fullname;
fullname = g_strconcat (prefix, ".", *action, NULL);
g_array_append_val (actions, fullname);
char *name = g_strconcat (prefix, ".", *action, NULL);
g_hash_table_add (actions, name);
}
g_strfreev (group_actions);
@ -125,9 +130,11 @@ static gchar **
gtk_action_muxer_list_actions (GActionGroup *action_group)
{
GtkActionMuxer *muxer = GTK_ACTION_MUXER (action_group);
GArray *actions;
GHashTable *actions;
char **keys;
actions = g_array_new (TRUE, FALSE, sizeof (gchar *));
actions = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
for ( ; muxer != NULL; muxer = muxer->parent)
{
@ -135,12 +142,28 @@ gtk_action_muxer_list_actions (GActionGroup *action_group)
const char *prefix;
Group *group;
if (muxer->widget_actions)
{
int i;
for (i = 0; i < muxer->widget_actions->len; i++)
{
GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
g_hash_table_add (actions, g_strdup (action->name));
}
}
g_hash_table_iter_init (&iter, muxer->groups);
while (g_hash_table_iter_next (&iter, (gpointer *)&prefix, (gpointer *)&group))
gtk_action_muxer_append_group_actions (prefix, group, actions);
}
return (gchar **)(void *) g_array_free (actions, FALSE);
keys = (char **)g_hash_table_get_keys_as_array (actions, NULL);
g_hash_table_steal_all (actions);
g_hash_table_unref (actions);
return (char **)keys;
}
static Group *
@ -179,7 +202,7 @@ gtk_action_muxer_find (GtkActionMuxer *muxer,
return group->group;
}
static void
void
gtk_action_muxer_action_enabled_changed (GtkActionMuxer *muxer,
const gchar *action_name,
gboolean enabled)
@ -187,6 +210,19 @@ gtk_action_muxer_action_enabled_changed (GtkActionMuxer *muxer,
Action *action;
GSList *node;
if (muxer->widget_actions)
{
int i;
for (i = 0; i < muxer->widget_actions->len; i++)
{
GtkWidgetAction *a = g_ptr_array_index (muxer->widget_actions, i);
if (strcmp (a->name, action_name) == 0)
{
muxer->widget_actions_enabled[i] = enabled;
break;
}
}
}
action = g_hash_table_lookup (muxer->observed_actions, action_name);
for (node = action ? action->watchers : NULL; node; node = node->next)
gtk_action_observer_action_enabled_changed (node->data, GTK_ACTION_OBSERVABLE (muxer), action_name, enabled);
@ -219,7 +255,7 @@ gtk_action_muxer_parent_action_enabled_changed (GActionGroup *action_group,
gtk_action_muxer_action_enabled_changed (muxer, action_name, enabled);
}
static void
void
gtk_action_muxer_action_state_changed (GtkActionMuxer *muxer,
const gchar *action_name,
GVariant *state)
@ -397,6 +433,46 @@ gtk_action_muxer_query_action (GActionGroup *action_group,
Group *group;
const gchar *unprefixed_name;
if (muxer->widget_actions)
{
int i;
for (i = 0; i < muxer->widget_actions->len; i++)
{
GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
if (strcmp (action->name, action_name) == 0)
{
if (enabled)
*enabled = muxer->widget_actions_enabled[i];
if (parameter_type)
*parameter_type = action->parameter_type;
if (state_hint)
*state_hint = NULL;
if (state_type)
*state_type = NULL;
if (state)
*state = NULL;
if (action->get_state)
{
GVariant *s;
s = g_variant_ref_sink (action->get_state (muxer->widget, action->name));
if (state_type)
*state_type = g_variant_get_type (s);
if (state)
*state = g_variant_ref (s);
g_variant_unref (s);
}
return TRUE;
}
}
}
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
if (group)
@ -420,6 +496,22 @@ gtk_action_muxer_activate_action (GActionGroup *action_group,
Group *group;
const gchar *unprefixed_name;
if (muxer->widget_actions)
{
int i;
for (i = 0; i < muxer->widget_actions->len; i++)
{
GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
if (strcmp (action->name, action_name) == 0)
{
action->activate (muxer->widget, action->name, parameter);
return;
}
}
}
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
if (group)
@ -437,6 +529,23 @@ gtk_action_muxer_change_action_state (GActionGroup *action_group,
Group *group;
const gchar *unprefixed_name;
if (muxer->widget_actions)
{
int i;
for (i = 0; i < muxer->widget_actions->len; i++)
{
GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
if (strcmp (action->name, action_name) == 0)
{
if (action->set_state)
action->set_state (muxer->widget, action->name, state);
return;
}
}
}
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
if (group)
@ -592,6 +701,14 @@ gtk_action_muxer_get_property (GObject *object,
g_value_set_object (value, gtk_action_muxer_get_parent (muxer));
break;
case PROP_WIDGET:
g_value_set_object (value, muxer->widget);
break;
case PROP_WIDGET_ACTIONS:
g_value_set_boxed (value, muxer->widget_actions);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@ -611,6 +728,22 @@ gtk_action_muxer_set_property (GObject *object,
gtk_action_muxer_set_parent (muxer, g_value_get_object (value));
break;
case PROP_WIDGET:
muxer->widget = g_value_get_object (value);
break;
case PROP_WIDGET_ACTIONS:
muxer->widget_actions = g_value_get_boxed (value);
if (muxer->widget_actions)
{
int i;
muxer->widget_actions_enabled = g_new (gboolean, muxer->widget_actions->len);
for (i = 0; i < muxer->widget_actions->len; i++)
muxer->widget_actions_enabled[i] = TRUE;
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@ -664,6 +797,20 @@ gtk_action_muxer_class_init (GObjectClass *class)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
properties[PROP_WIDGET] = g_param_spec_object ("widget", "Widget",
"The widget that owns the muxer",
GTK_TYPE_WIDGET,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
properties[PROP_WIDGET_ACTIONS] = g_param_spec_boxed ("widget-actions", "Widget actions",
"Widget actions",
G_TYPE_PTR_ARRAY,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (class, NUM_PROPERTIES, properties);
}
@ -771,13 +918,19 @@ gtk_action_muxer_lookup (GtkActionMuxer *muxer,
/*< private >
* gtk_action_muxer_new:
* @widget: the widget to which the muxer belongs
* @actions: widget actions
*
* Creates a new #GtkActionMuxer.
*/
GtkActionMuxer *
gtk_action_muxer_new (void)
gtk_action_muxer_new (GtkWidget *widget,
GPtrArray *actions)
{
return g_object_new (GTK_TYPE_ACTION_MUXER, NULL);
return g_object_new (GTK_TYPE_ACTION_MUXER,
"widget", widget,
"widget-actions", actions,
NULL);
}
/*< private >

View File

@ -21,6 +21,7 @@
#define __GTK_ACTION_MUXER_H__
#include <gio/gio.h>
#include "gtkwidget.h"
G_BEGIN_DECLS
@ -30,10 +31,21 @@ G_BEGIN_DECLS
#define GTK_IS_ACTION_MUXER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
GTK_TYPE_ACTION_MUXER))
typedef struct {
char *name;
GVariantType *parameter_type;
GtkWidgetActionActivateFunc activate;
GtkWidgetActionSetStateFunc set_state;
GtkWidgetActionGetStateFunc get_state;
} GtkWidgetAction;
typedef struct _GtkActionMuxer GtkActionMuxer;
GType gtk_action_muxer_get_type (void);
GtkActionMuxer * gtk_action_muxer_new (void);
GtkActionMuxer * gtk_action_muxer_new (GtkWidget *widget,
GPtrArray *actions);
void gtk_action_muxer_insert (GtkActionMuxer *muxer,
const gchar *prefix,
@ -58,6 +70,16 @@ void gtk_action_muxer_set_primary_accel (GtkActi
const gchar * gtk_action_muxer_get_primary_accel (GtkActionMuxer *muxer,
const gchar *action_and_target);
void
gtk_action_muxer_action_enabled_changed (GtkActionMuxer *muxer,
const char *action_name,
gboolean enabled);
void
gtk_action_muxer_action_state_changed (GtkActionMuxer *muxer,
const gchar *action_name,
GVariant *state);
/* No better place for these... */
gchar * gtk_print_action_and_target (const gchar *action_namespace,
const gchar *action_name,

View File

@ -394,7 +394,7 @@ gtk_application_init (GtkApplication *application)
{
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
priv->muxer = gtk_action_muxer_new ();
priv->muxer = gtk_action_muxer_new (NULL, NULL);
priv->accels = gtk_application_accels_new ();
}

View File

@ -90,8 +90,6 @@ struct _GtkColorChooserWidgetPrivate
gboolean has_default_palette;
GSettings *settings;
GActionMap *context_actions;
};
enum
@ -493,11 +491,11 @@ add_default_palette (GtkColorChooserWidget *cc)
}
static void
customize_color (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_color_chooser_widget_activate_color_customize (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
GtkColorChooserWidget *cc = user_data;
GtkColorChooserWidget *cc = GTK_COLOR_CHOOSER_WIDGET (widget);
GtkColorChooserWidgetPrivate *priv = gtk_color_chooser_widget_get_instance_private (cc);
GdkRGBA color;
@ -511,11 +509,11 @@ customize_color (GSimpleAction *action,
}
static void
select_color (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_color_chooser_widget_activate_color_select (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
GtkColorChooserWidget *cc = user_data;
GtkColorChooserWidget *cc = GTK_COLOR_CHOOSER_WIDGET (widget);
GdkRGBA color;
g_variant_get (parameter, "(dddd)", &color.red, &color.green, &color.blue, &color.alpha);
@ -523,26 +521,6 @@ select_color (GSimpleAction *action,
_gtk_color_chooser_color_activated (GTK_COLOR_CHOOSER (cc), &color);
}
static void
gtk_color_chooser_widget_add_context_actions (GtkColorChooserWidget *cc)
{
GtkColorChooserWidgetPrivate *priv = gtk_color_chooser_widget_get_instance_private (cc);
GActionEntry entries[] = {
{ "select", select_color, "(dddd)", NULL, NULL },
{ "customize", customize_color, "(dddd)", NULL, NULL },
};
GSimpleActionGroup *actions = g_simple_action_group_new ();
priv->context_actions = G_ACTION_MAP (actions);
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), cc);
gtk_widget_insert_action_group (GTK_WIDGET (cc), "color", G_ACTION_GROUP (actions));
}
static void
gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
{
@ -634,8 +612,6 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
gtk_size_group_add_widget (priv->size_group, priv->palette);
gtk_size_group_add_widget (priv->size_group, box);
gtk_color_chooser_widget_add_context_actions (cc);
}
/* GObject implementation {{{1 */
@ -736,6 +712,13 @@ gtk_color_chooser_widget_class_init (GtkColorChooserWidgetClass *class)
FALSE, GTK_PARAM_READWRITE));
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), I_("colorchooser"));
gtk_widget_class_install_stateful_action (GTK_WIDGET_CLASS (class), "color.select",
gtk_color_chooser_widget_activate_color_select,
"(dddd)", NULL, NULL);
gtk_widget_class_install_stateful_action (GTK_WIDGET_CLASS (class), "color.customize",
gtk_color_chooser_widget_activate_color_customize,
"(dddd)", NULL, NULL);
}
/* GtkColorChooser implementation {{{1 */

View File

@ -285,7 +285,6 @@ struct _GtkLabelPrivate
PangoAttrList *markup_attrs;
PangoLayout *layout;
GActionMap *context_actions;
GtkWidget *popup_menu;
GMenuModel *extra_menu;
@ -575,8 +574,25 @@ static void gtk_label_drag_gesture_update (GtkGestureDrag *gesture,
gdouble offset_y,
GtkLabel *label);
static void gtk_label_add_context_actions (GtkLabel *label);
static void gtk_label_update_clipboard_actions (GtkLabel *label);
/* Actions */
static void gtk_label_activate_clipboard_copy (GtkWidget *label,
const char *name,
GVariant *parameter);
static void gtk_label_activate_selection_select_all (GtkWidget *label,
const char *name,
GVariant *parameter);
static void gtk_label_activate_link_open (GtkWidget *label,
const char *name,
GVariant *parameter);
static void gtk_label_activate_link_copy (GtkWidget *label,
const char *name,
GVariant *parameter);
static void gtk_label_nop (GtkWidget *label,
const char *name,
GVariant *parameter);
static void gtk_label_update_actions (GtkLabel *label);
static GtkSizeRequestMode gtk_label_get_request_mode (GtkWidget *widget);
static void gtk_label_measure (GtkWidget *widget,
@ -1143,6 +1159,21 @@ gtk_label_class_init (GtkLabelClass *class)
quark_mnemonics_visible_connected = g_quark_from_static_string ("gtk-label-mnemonics-visible-connected");
quark_gtk_signal = g_quark_from_static_string ("gtk-signal");
quark_link = g_quark_from_static_string ("link");
gtk_widget_class_install_action (widget_class, "clipboard.cut",
gtk_label_nop);
gtk_widget_class_install_action (widget_class, "clipboard.copy",
gtk_label_activate_clipboard_copy);
gtk_widget_class_install_action (widget_class, "clipboard.paste",
gtk_label_nop);
gtk_widget_class_install_action (widget_class, "selection.delete",
gtk_label_nop);
gtk_widget_class_install_action (widget_class, "selection.select-all",
gtk_label_activate_selection_select_all);
gtk_widget_class_install_action (widget_class, "link.open",
gtk_label_activate_link_open);
gtk_widget_class_install_action (widget_class, "link.copy",
gtk_label_activate_link_copy);
}
static void
@ -1330,8 +1361,6 @@ gtk_label_init (GtkLabel *label)
priv->mnemonic_window = NULL;
priv->mnemonics_visible = TRUE;
gtk_label_add_context_actions (label);
}
@ -3205,7 +3234,6 @@ gtk_label_finalize (GObject *object)
gtk_label_clear_links (label);
g_free (priv->select_info);
g_clear_object (&priv->context_actions);
g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
g_clear_object (&priv->extra_menu);
@ -4854,6 +4882,8 @@ gtk_label_update_active_link (GtkWidget *widget,
gtk_widget_queue_draw (widget);
}
}
gtk_label_update_actions (label);
}
}
@ -5295,6 +5325,8 @@ gtk_label_select_region_index (GtkLabel *label,
}
}
gtk_label_update_actions (label);
gtk_widget_queue_draw (GTK_WIDGET (label));
g_object_thaw_notify (G_OBJECT (label));
@ -5968,24 +6000,24 @@ gtk_label_select_all (GtkLabel *label)
}
static void
open_link_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_label_activate_link_open (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
GtkLabel *label = GTK_LABEL (user_data);
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GtkLabelLink *link = priv->select_info->context_link;
GtkLabelLink *link = priv->select_info->context_link;
if (link)
emit_activate_link (label, link);
}
static void
copy_link_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_label_activate_link_copy (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
GtkLabel *label = GTK_LABEL (user_data);
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GtkLabelLink *link = priv->select_info->context_link;
@ -5993,101 +6025,59 @@ copy_link_activated (GSimpleAction *action,
{
GdkClipboard *clipboard;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label));
clipboard = gtk_widget_get_clipboard (widget);
gdk_clipboard_set_text (clipboard, link->uri);
}
else
g_print ("no link ?!\n");
}
static void
copy_clipboard_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_label_activate_clipboard_copy (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
g_signal_emit_by_name (user_data, "copy-clipboard");
g_signal_emit_by_name (widget, "copy-clipboard");
}
static void
select_all_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_label_activate_selection_select_all (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
gtk_label_select_all (GTK_LABEL (user_data));
gtk_label_select_all (GTK_LABEL (widget));
}
static void
gtk_label_update_clipboard_actions (GtkLabel *label)
gtk_label_nop (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
}
static void
gtk_label_update_actions (GtkLabel *label)
{
GtkWidget *widget = GTK_WIDGET (label);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
gboolean have_selection = FALSE;
GAction *action;
if (priv->select_info)
have_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
action = g_action_map_lookup_action (priv->context_actions, "copy-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), have_selection);
action = g_action_map_lookup_action (priv->context_actions, "select-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), gtk_label_get_selectable (label));
}
static void
gtk_label_update_link_actions (GtkLabel *label)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
gboolean have_selection = FALSE;
GAction *action;
gboolean has_selection;
GtkLabelLink *link;
have_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
if (priv->select_info)
has_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
else
has_selection = FALSE;
if (priv->select_info->link_clicked)
link = priv->select_info->active_link;
else
link = gtk_label_get_focus_link (label);
action = g_action_map_lookup_action (priv->context_actions, "open-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !have_selection && link);
action = g_action_map_lookup_action (priv->context_actions, "copy-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !have_selection && link);
}
static void
gtk_label_add_context_actions (GtkLabel *label)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GActionEntry entries[] = {
{ "cut-clipboard", NULL, NULL, NULL, NULL },
{ "copy-clipboard", copy_clipboard_activated, NULL, NULL, NULL },
{ "paste-clipboard", NULL, NULL, NULL, NULL },
{ "delete-selection", NULL, NULL, NULL, NULL },
{ "select-all", select_all_activated, NULL, NULL, NULL },
{ "open-link", open_link_activated, NULL, NULL, NULL },
{ "copy-link", copy_link_activated, NULL, NULL, NULL },
};
GSimpleActionGroup *actions = g_simple_action_group_new ();
GAction *action;
priv->context_actions = G_ACTION_MAP (actions);
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), label);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "cut-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "paste-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "delete-selection");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "select-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "open-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
gtk_widget_insert_action_group (GTK_WIDGET (label), "context", G_ACTION_GROUP (actions));
gtk_widget_action_enabled_changed (widget, "clipboard.copy", has_selection);
gtk_widget_action_enabled_changed (widget, "selection.select-all",
gtk_label_get_selectable (label));
gtk_widget_action_enabled_changed (widget, "link.open", !has_selection && link);
gtk_widget_action_enabled_changed (widget, "link.copy", !has_selection && link);
}
static GMenuModel *
@ -6100,24 +6090,24 @@ gtk_label_get_menu_model (GtkLabel *label)
menu = g_menu_new ();
section = g_menu_new ();
g_menu_append (section, _("Cu_t"), "context.cut-clipboard");
g_menu_append (section, _("_Copy"), "context.copy-clipboard");
g_menu_append (section, _("_Paste"), "context.paste-clipboard");
g_menu_append (section, _("_Delete"), "context.delete-selection");
g_menu_append (section, _("Cu_t"), "clipboard.cut");
g_menu_append (section, _("_Copy"), "clipboard.copy");
g_menu_append (section, _("_Paste"), "clipboard.paste");
g_menu_append (section, _("_Delete"), "selection.delete");
g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
g_object_unref (section);
section = g_menu_new ();
g_menu_append (section, _("Select _All"), "context.select-all");
g_menu_append (section, _("Select _All"), "selection.select-all");
g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
g_object_unref (section);
section = g_menu_new ();
item = g_menu_item_new (_("_Open Link"), "context.open-link");
item = g_menu_item_new (_("_Open Link"), "link.open");
g_menu_item_set_attribute (item, "hidden-when", "s", "action-disabled");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new (_("Copy _Link Address"), "context.copy-link");
item = g_menu_item_new (_("Copy _Link Address"), "link.copy");
g_menu_item_set_attribute (item, "hidden-when", "s", "action-disabled");
g_menu_append_item (section, item);
g_object_unref (item);
@ -6137,8 +6127,15 @@ gtk_label_do_popup (GtkLabel *label,
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
gtk_label_update_clipboard_actions (label);
gtk_label_update_link_actions (label);
if (!priv->select_info)
return;
if (priv->select_info->link_clicked)
priv->select_info->context_link = priv->select_info->active_link;
else
priv->select_info->context_link = gtk_label_get_focus_link (label);
gtk_label_update_actions (label);
if (!priv->popup_menu)
{
@ -6169,15 +6166,6 @@ static gboolean
gtk_label_popup_menu (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
if (!priv->select_info)
return FALSE;
if (priv->select_info->link_clicked)
priv->select_info->context_link = priv->select_info->active_link;
else
priv->select_info->context_link = gtk_label_get_focus_link (label);
gtk_label_do_popup (label, -1, -1);
return TRUE;

View File

@ -96,7 +96,6 @@ struct _GtkLinkButtonPrivate
gboolean visited;
GActionMap *context_actions;
GtkWidget *popup_menu;
};
@ -152,6 +151,17 @@ static guint link_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE_WITH_PRIVATE (GtkLinkButton, gtk_link_button, GTK_TYPE_BUTTON)
static void
gtk_link_button_activate_clipboard_copy (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
GtkLinkButton *link_button = GTK_LINK_BUTTON (widget);
GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button);
gdk_clipboard_set_text (gtk_widget_get_clipboard (widget), priv->uri);
}
static void
gtk_link_button_class_init (GtkLinkButtonClass *klass)
{
@ -221,28 +231,9 @@ gtk_link_button_class_init (GtkLinkButtonClass *klass)
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LINK_BUTTON_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("button"));
}
static void copy_activate_cb (GSimpleAction *action,
GVariant *parameter,
gpointer user_data);
static void
gtk_link_button_add_context_actions (GtkLinkButton *link_button)
{
GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button);
GActionEntry entries[] = {
{ "copy-clipboard", copy_activate_cb, NULL, NULL, NULL },
};
GSimpleActionGroup *actions = g_simple_action_group_new ();
priv->context_actions = G_ACTION_MAP (actions);
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), link_button);
gtk_widget_insert_action_group (GTK_WIDGET (link_button), "context", G_ACTION_GROUP (actions));
gtk_widget_class_install_action (widget_class, "clipboard.copy",
gtk_link_button_activate_clipboard_copy);
}
static GMenuModel *
@ -298,7 +289,6 @@ gtk_link_button_init (GtkLinkButton *link_button)
gtk_style_context_add_class (context, "link");
gtk_widget_set_cursor_from_name (GTK_WIDGET (link_button), "pointer");
gtk_link_button_add_context_actions (link_button);
}
static void
@ -309,7 +299,6 @@ gtk_link_button_finalize (GObject *object)
g_free (priv->uri);
g_clear_object (&priv->context_actions);
g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
G_OBJECT_CLASS (gtk_link_button_parent_class)->finalize (object);
@ -360,18 +349,6 @@ gtk_link_button_set_property (GObject *object,
}
}
static void
copy_activate_cb (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkLinkButton *link_button = user_data;
GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button);
gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (link_button)),
priv->uri);
}
static void
gtk_link_button_do_popup (GtkLinkButton *link_button,
double x,

View File

@ -110,20 +110,30 @@ focus_changed (GtkWidget *widget)
static void
gtk_password_entry_toggle_peek (GtkPasswordEntry *entry)
{
GtkPasswordEntryPrivate *priv = gtk_password_entry_get_instance_private (entry);
gboolean visibility;
visibility = gtk_text_get_visibility (GTK_TEXT (priv->entry));
gtk_text_set_visibility (GTK_TEXT (priv->entry), !visibility);
}
static void
visibility_toggled (GObject *object,
GParamSpec *pspec,
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"));
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"));
}
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"));
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"));
}
}
@ -482,11 +492,18 @@ gtk_password_entry_set_show_peek_icon (GtkPasswordEntry *entry,
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));
g_signal_connect (priv->entry, "notify::visibility",
G_CALLBACK (visibility_toggled), entry);
visibility_toggled (G_OBJECT (priv->entry), NULL, entry);
}
else
{
g_clear_pointer (&priv->peek_icon, gtk_widget_unparent);
gtk_text_set_visibility (GTK_TEXT (priv->entry), FALSE);
g_signal_handlers_disconnect_by_func (priv->entry,
visibility_toggled,
entry);
}
keymap_state_changed (priv->keymap, GTK_WIDGET (entry));
@ -532,13 +549,17 @@ gtk_password_entry_set_extra_menu (GtkPasswordEntry *entry,
g_return_if_fail (GTK_IS_PASSWORD_ENTRY (entry));
if (!g_set_object (&priv->extra_menu, model))
return;
/* bypass this check for the initial call from init */
if (priv->extra_menu)
{
if (!g_set_object (&priv->extra_menu, model))
return;
}
menu = g_menu_new ();
section = g_menu_new ();
item = g_menu_item_new (_("_Show Text"), "context.toggle-visibility");
item = g_menu_item_new (_("_Show Text"), "misc.toggle-visibility");
g_menu_item_set_attribute (item, "touch-icon", "s", "eye-not-looking-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);

View File

@ -68,6 +68,7 @@
#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
#include "gtknative.h"
#include "gtkactionmuxerprivate.h"
#include "a11y/gtktextaccessible.h"
@ -174,7 +175,6 @@ struct _GtkTextPrivate
GtkCssNode *block_cursor_node;
GtkCssNode *undershoot_node[2];
GActionMap *context_actions;
GtkWidget *popup_menu;
GMenuModel *extra_menu;
@ -542,10 +542,36 @@ static void begin_change (GtkText *self);
static void end_change (GtkText *self);
static void emit_changed (GtkText *self);
static void gtk_text_add_context_actions (GtkText *self);
static void gtk_text_update_clipboard_actions (GtkText *self);
static void gtk_text_update_emoji_action (GtkText *self);
static void gtk_text_activate_clipboard_cut (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_activate_clipboard_copy (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_activate_clipboard_paste (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_activate_selection_delete (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_activate_selection_select_all (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_activate_misc_insert_emoji (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_activate_misc_toggle_visibility (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_set_misc_toggle_visibility (GtkWidget *widget,
const char *action_name,
GVariant *state);
static GVariant *gtk_text_get_misc_toggle_visibility (GtkWidget *widget,
const char *action_name);
/* GtkTextContent implementation
*/
@ -706,7 +732,7 @@ gtk_text_class_init (GtkTextClass *class)
class->toggle_overwrite = gtk_text_toggle_overwrite;
class->insert_emoji = gtk_text_insert_emoji;
class->activate = gtk_text_real_activate;
quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint");
quark_gtk_signal = g_quark_from_static_string ("gtk-signal");
@ -1336,6 +1362,24 @@ gtk_text_class_init (GtkTextClass *class)
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("text"));
gtk_widget_class_install_action (widget_class, "clipboard.cut",
gtk_text_activate_clipboard_cut);
gtk_widget_class_install_action (widget_class, "clipboard.copy",
gtk_text_activate_clipboard_copy);
gtk_widget_class_install_action (widget_class, "clipboard.paste",
gtk_text_activate_clipboard_paste);
gtk_widget_class_install_action (widget_class, "selection.delete",
gtk_text_activate_selection_delete);
gtk_widget_class_install_action (widget_class, "selection.select-all",
gtk_text_activate_selection_select_all);
gtk_widget_class_install_action (widget_class, "misc.insert-emoji",
gtk_text_activate_misc_insert_emoji);
gtk_widget_class_install_stateful_action (widget_class, "misc.toggle-visibility",
gtk_text_activate_misc_toggle_visibility,
NULL,
gtk_text_set_misc_toggle_visibility,
gtk_text_get_misc_toggle_visibility);
}
static void
@ -1720,7 +1764,6 @@ gtk_text_init (GtkText *self)
}
set_text_cursor (GTK_WIDGET (self));
gtk_text_add_context_actions (self);
}
static void
@ -1766,7 +1809,7 @@ gtk_text_dispose (GObject *object)
keymap = gdk_display_get_keymap (gtk_widget_get_display (GTK_WIDGET (object)));
g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, self);
g_clear_object (&priv->context_actions);
g_clear_pointer (&priv->selection_bubble, gtk_widget_unparent);
g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
g_clear_object (&priv->extra_menu);
@ -1783,7 +1826,6 @@ gtk_text_finalize (GObject *object)
g_clear_object (&priv->cached_layout);
g_clear_object (&priv->im_context);
g_clear_pointer (&priv->selection_bubble, gtk_widget_unparent);
g_clear_pointer (&priv->magnifier_popover, gtk_widget_destroy);
g_clear_object (&priv->text_handle);
g_free (priv->im_module);
@ -2176,6 +2218,9 @@ gtk_text_size_allocate (GtkWidget *widget,
if (priv->popup_menu)
gtk_native_check_resize (GTK_NATIVE (priv->popup_menu));
if (priv->selection_bubble)
gtk_native_check_resize (GTK_NATIVE (priv->selection_bubble));
}
static void
@ -4047,6 +4092,7 @@ gtk_text_set_positions (GtkText *self,
if (changed)
{
gtk_text_update_clipboard_actions (self);
gtk_text_recompute (self);
}
}
@ -5261,15 +5307,14 @@ gtk_text_set_visibility (GtkText *self,
if (priv->visible != visible)
{
GAction *action;
priv->visible = visible;
g_object_notify (G_OBJECT (self), "visibility");
gtk_text_recompute (self);
action = g_action_map_lookup_action (priv->context_actions, "toggle-visibility");
g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (visible));
gtk_text_update_clipboard_actions (self);
gtk_widget_action_state_changed (GTK_WIDGET (self), "misc.toggle-visibility",
g_variant_new_boolean (visible));
}
}
@ -5615,152 +5660,129 @@ hide_selection_bubble (GtkText *self)
}
static void
cut_clipboard_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_text_activate_clipboard_cut (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
g_signal_emit_by_name (user_data, "cut-clipboard");
hide_selection_bubble (GTK_TEXT (user_data));
GtkText *self = GTK_TEXT (widget);
g_signal_emit_by_name (self, "cut-clipboard");
hide_selection_bubble (self);
}
static void
copy_clipboard_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_text_activate_clipboard_copy (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
g_signal_emit_by_name (user_data, "copy-clipboard");
hide_selection_bubble (GTK_TEXT (user_data));
GtkText *self = GTK_TEXT (widget);
g_signal_emit_by_name (self, "copy-clipboard");
hide_selection_bubble (self);
}
static void
paste_clipboard_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_text_activate_clipboard_paste (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
g_signal_emit_by_name (user_data, "paste-clipboard");
hide_selection_bubble (GTK_TEXT (user_data));
GtkText *self = GTK_TEXT (widget);
g_signal_emit_by_name (self, "paste-clipboard");
hide_selection_bubble (self);
}
static void
delete_selection_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_text_activate_selection_delete (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
gtk_text_delete_cb (GTK_TEXT (user_data));
hide_selection_bubble (GTK_TEXT (user_data));
GtkText *self = GTK_TEXT (widget);
gtk_text_delete_cb (self);
hide_selection_bubble (self);
}
static void
select_all_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_text_activate_selection_select_all (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
gtk_text_select_all (GTK_TEXT (user_data));
GtkText *self = GTK_TEXT (widget);
gtk_text_select_all (self);
}
static void
insert_emoji_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_text_activate_misc_insert_emoji (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
gtk_text_insert_emoji (GTK_TEXT (user_data));
hide_selection_bubble (GTK_TEXT (user_data));
GtkText *self = GTK_TEXT (widget);
gtk_text_insert_emoji (self);
hide_selection_bubble (self);
}
static void
toggle_visibility (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
gtk_text_activate_misc_toggle_visibility (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GtkText *text = GTK_TEXT (user_data);
gtk_text_set_visibility (text, !gtk_text_get_visibility (text));
GtkText *self = GTK_TEXT (widget);
gtk_text_set_visibility (self, !gtk_text_get_visibility (self));
}
static GVariant *
gtk_text_get_misc_toggle_visibility (GtkWidget *widget,
const char *action_name)
{
GtkText *self = GTK_TEXT (widget);
DisplayMode mode = gtk_text_get_display_mode (self);
return g_variant_new_boolean (mode == DISPLAY_NORMAL);
}
static void
gtk_text_add_context_actions (GtkText *self)
gtk_text_set_misc_toggle_visibility (GtkWidget *widget,
const char *action_name,
GVariant *state)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GActionEntry entries[] = {
{ "cut-clipboard", cut_clipboard_activated, NULL, NULL, NULL },
{ "copy-clipboard", copy_clipboard_activated, NULL, NULL, NULL },
{ "paste-clipboard", paste_clipboard_activated, NULL, NULL, NULL },
{ "delete-selection", delete_selection_activated, NULL, NULL, NULL },
{ "select-all", select_all_activated, NULL, NULL, NULL },
{ "insert-emoji", insert_emoji_activated, NULL, NULL, NULL },
{ "toggle-visibility", toggle_visibility, NULL, "true", NULL },
};
GSimpleActionGroup *actions = g_simple_action_group_new ();
GAction *action;
priv->context_actions = G_ACTION_MAP (actions);
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), self);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "cut-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "paste-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "delete-selection");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "select-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "insert-emoji");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
gtk_widget_insert_action_group (GTK_WIDGET (self), "context", G_ACTION_GROUP (actions));
GtkText *self = GTK_TEXT (widget);
gboolean visible = g_variant_get_boolean (state);
gtk_text_set_visibility (self, visible);
}
static void
gtk_text_update_clipboard_actions (GtkText *self)
{
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
DisplayMode mode;
GdkClipboard *clipboard;
gboolean has_clipboard;
GAction *action;
gboolean has_selection;
gboolean has_content;
gboolean visible;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (self));
has_clipboard = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), G_TYPE_STRING);
mode = gtk_text_get_display_mode (self);
has_clipboard = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), G_TYPE_STRING);
has_selection = priv->current_pos != priv->selection_bound;
has_content = priv->buffer && (gtk_entry_buffer_get_length (priv->buffer) > 0);
visible = mode == DISPLAY_NORMAL;
action = g_action_map_lookup_action (priv->context_actions, "cut-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
mode == DISPLAY_NORMAL &&
priv->editable &&
priv->current_pos != priv->selection_bound);
gtk_widget_action_enabled_changed (GTK_WIDGET (self), "clipboard.cut",
visible && priv->editable && has_selection);
gtk_widget_action_enabled_changed (GTK_WIDGET (self), "clipboard.copy",
visible && has_selection);
gtk_widget_action_enabled_changed (GTK_WIDGET (self), "clipboard.paste",
priv->editable && has_clipboard);
action = g_action_map_lookup_action (priv->context_actions, "copy-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
mode == DISPLAY_NORMAL &&
priv->current_pos != priv->selection_bound);
action = g_action_map_lookup_action (priv->context_actions, "paste-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
priv->editable && has_clipboard);
action = g_action_map_lookup_action (priv->context_actions, "delete-selection");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
priv->editable &&
priv->current_pos != priv->selection_bound);
action = g_action_map_lookup_action (priv->context_actions, "select-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
priv->buffer && (gtk_entry_buffer_get_length (priv->buffer) > 0));
gtk_widget_action_enabled_changed (GTK_WIDGET (self), "selection.delete",
priv->editable && has_selection);
gtk_widget_action_enabled_changed (GTK_WIDGET (self), "selection.select-all",
has_content);
}
static void
gtk_text_update_emoji_action (GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GAction *action;
action = g_action_map_lookup_action (priv->context_actions, "insert-emoji");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
(gtk_text_get_input_hints (self) & GTK_INPUT_HINT_NO_EMOJI) == 0);
gtk_widget_action_enabled_changed (GTK_WIDGET (self), "misc.insert-emoji",
(gtk_text_get_input_hints (self) & GTK_INPUT_HINT_NO_EMOJI) == 0);
}
static GMenuModel *
@ -5773,19 +5795,19 @@ gtk_text_get_menu_model (GtkText *self)
menu = g_menu_new ();
section = g_menu_new ();
item = g_menu_item_new (_("Cu_t"), "context.cut-clipboard");
item = g_menu_item_new (_("Cu_t"), "clipboard.cut");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-cut-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new (_("_Copy"), "context.copy-clipboard");
item = g_menu_item_new (_("_Copy"), "clipboard.copy");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-copy-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new (_("_Paste"), "context.paste-clipboard");
item = g_menu_item_new (_("_Paste"), "clipboard.paste");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-paste-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new (_("_Delete"), "context.delete-selection");
item = g_menu_item_new (_("_Delete"), "selection.delete");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-delete-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
@ -5794,12 +5816,12 @@ gtk_text_get_menu_model (GtkText *self)
section = g_menu_new ();
item = g_menu_item_new (_("Select _All"), "context.select-all");
item = g_menu_item_new (_("Select _All"), "selection.select-all");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-select-all-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new ( _("Insert _Emoji"), "context.insert-emoji");
item = g_menu_item_new ( _("Insert _Emoji"), "misc.insert-emoji");
g_menu_item_set_attribute (item, "hidden-when", "s", "action-disabled");
g_menu_item_set_attribute (item, "touch-icon", "s", "face-smile-symbolic");
g_menu_append_item (section, item);
@ -5860,12 +5882,11 @@ append_bubble_item (GtkText *self,
GMenuModel *model,
int index)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GtkActionMuxer *muxer;
GtkWidget *item, *image;
GVariant *att;
const char *icon_name;
const char *action_name;
GAction *action;
GMenuModel *link;
link = g_menu_model_get_item_link (model, index, "section");
@ -5891,12 +5912,9 @@ append_bubble_item (GtkText *self,
action_name = g_variant_get_string (att, NULL);
g_variant_unref (att);
if (g_str_has_prefix (action_name, "context."))
{
action = g_action_map_lookup_action (priv->context_actions, action_name + strlen ("context."));
if (action && !g_action_get_enabled (action))
return;
}
muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (self), FALSE);
if (!g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), action_name))
return;
item = gtk_button_new ();
gtk_widget_set_focus_on_click (item, FALSE);
@ -5990,7 +6008,7 @@ gtk_text_selection_bubble_popup_show (gpointer user_data)
rect.height += 10;
gtk_popover_set_pointing_to (GTK_POPOVER (priv->selection_bubble), &rect);
gtk_widget_show (priv->selection_bubble);
gtk_popover_popup (GTK_POPOVER (priv->selection_bubble));
priv->selection_bubble_timeout_id = 0;

View File

@ -182,8 +182,6 @@ struct _GtkTextViewPrivate
GtkAdjustment *hadjustment;
GtkAdjustment *vadjustment;
GActionMap *context_actions;
/* X offset between widget coordinates and buffer coordinates
* taking left_padding in account
*/
@ -595,10 +593,28 @@ static void extend_selection (GtkTextView *text_view,
GtkTextIter *start,
GtkTextIter *end);
static void gtk_text_view_add_context_actions (GtkTextView *text_view);
static void gtk_text_view_update_clipboard_actions (GtkTextView *text_view);
static void gtk_text_view_update_emoji_action (GtkTextView *text_view);
static void gtk_text_view_activate_clipboard_cut (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_view_activate_clipboard_copy (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_view_activate_clipboard_paste (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_view_activate_selection_delete (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_view_activate_selection_select_all (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_text_view_activate_misc_insert_emoji (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
/* FIXME probably need the focus methods. */
@ -1585,6 +1601,19 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
quark_text_selection_data = g_quark_from_static_string ("gtk-text-view-text-selection-data");
quark_gtk_signal = g_quark_from_static_string ("gtk-signal");
quark_text_view_child = g_quark_from_static_string ("gtk-text-view-child");
gtk_widget_class_install_action (widget_class, "clipboard.cut",
gtk_text_view_activate_clipboard_cut);
gtk_widget_class_install_action (widget_class, "clipboard.copy",
gtk_text_view_activate_clipboard_copy);
gtk_widget_class_install_action (widget_class, "clipboard.paste",
gtk_text_view_activate_clipboard_paste);
gtk_widget_class_install_action (widget_class, "selection.delete",
gtk_text_view_activate_selection_delete);
gtk_widget_class_install_action (widget_class, "selection.select-all",
gtk_text_view_activate_selection_select_all);
gtk_widget_class_install_action (widget_class, "misc.insert-emoji",
gtk_text_view_activate_misc_insert_emoji);
}
static void
@ -1694,8 +1723,6 @@ gtk_text_view_init (GtkTextView *text_view)
gtk_css_node_get_state (priv->text_window->css_node) & ~GTK_STATE_FLAG_DROP_ACTIVE);
gtk_css_node_set_visible (priv->selection_node, FALSE);
g_object_unref (priv->selection_node);
gtk_text_view_add_context_actions (text_view);
}
GtkCssNode *
@ -3617,7 +3644,6 @@ gtk_text_view_finalize (GObject *object)
g_free (priv->im_module);
g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
g_clear_object (&priv->context_actions);
g_clear_object (&priv->extra_menu);
G_OBJECT_CLASS (gtk_text_view_parent_class)->finalize (object);
@ -8438,33 +8464,6 @@ hide_selection_bubble (GtkTextView *text_view)
gtk_widget_hide (priv->selection_bubble);
}
static void
cut_clipboard_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
g_signal_emit_by_name (user_data, "cut-clipboard");
hide_selection_bubble (GTK_TEXT_VIEW (user_data));
}
static void
copy_clipboard_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
g_signal_emit_by_name (user_data, "copy-clipboard");
hide_selection_bubble (GTK_TEXT_VIEW (user_data));
}
static void
paste_clipboard_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
g_signal_emit_by_name (user_data, "paste-clipboard");
hide_selection_bubble (GTK_TEXT_VIEW (user_data));
}
static void
gtk_text_view_select_all (GtkWidget *widget,
gboolean select)
@ -8487,34 +8486,6 @@ gtk_text_view_select_all (GtkWidget *widget,
}
}
static void
select_all_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkTextView *text_view = user_data;
gtk_text_view_select_all (GTK_WIDGET (text_view), TRUE);
}
static void
delete_selection_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkTextView *text_view = user_data;
gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE,
text_view->priv->editable);
}
static void
insert_emoji_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
gtk_text_view_insert_emoji (GTK_TEXT_VIEW (user_data));
}
static gboolean
range_contains_editable_text (const GtkTextIter *start,
@ -8535,40 +8506,60 @@ range_contains_editable_text (const GtkTextIter *start,
}
static void
gtk_text_view_add_context_actions (GtkTextView *text_view)
gtk_text_view_activate_clipboard_cut (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GtkTextViewPrivate *priv = text_view->priv;
GtkTextView *self = GTK_TEXT_VIEW (widget);
g_signal_emit_by_name (self, "cut-clipboard");
hide_selection_bubble (self);
}
GActionEntry entries[] = {
{ "cut-clipboard", cut_clipboard_activated, NULL, NULL, NULL },
{ "copy-clipboard", copy_clipboard_activated, NULL, NULL, NULL },
{ "paste-clipboard", paste_clipboard_activated, NULL, NULL, NULL },
{ "delete-selection", delete_selection_activated, NULL, NULL, NULL },
{ "select-all", select_all_activated, NULL, NULL, NULL },
{ "insert-emoji", insert_emoji_activated, NULL, NULL, NULL },
};
static void
gtk_text_view_activate_clipboard_copy (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GtkTextView *self = GTK_TEXT_VIEW (widget);
g_signal_emit_by_name (self, "copy-clipboard");
hide_selection_bubble (self);
}
GSimpleActionGroup *actions = g_simple_action_group_new ();
GAction *action;
static void
gtk_text_view_activate_clipboard_paste (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GtkTextView *self = GTK_TEXT_VIEW (widget);
g_signal_emit_by_name (self, "paste-clipboard");
hide_selection_bubble (self);
}
priv->context_actions = G_ACTION_MAP (actions);
static void
gtk_text_view_activate_selection_select_all (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
gtk_text_view_select_all (widget, TRUE);
}
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), text_view);
static void
gtk_text_view_activate_selection_delete (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "cut-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "paste-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "delete-selection");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "select-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "insert-emoji");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE,
text_view->priv->editable);
}
gtk_widget_insert_action_group (GTK_WIDGET (text_view), "context", G_ACTION_GROUP (actions));
static void
gtk_text_view_activate_misc_insert_emoji (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
gtk_text_view_insert_emoji (GTK_TEXT_VIEW (widget));
}
static void
@ -8578,7 +8569,6 @@ gtk_text_view_update_clipboard_actions (GtkTextView *text_view)
GdkClipboard *clipboard;
gboolean have_selection;
gboolean can_paste, can_insert;
GAction *action;
GtkTextIter iter, sel_start, sel_end;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view));
@ -8593,36 +8583,25 @@ gtk_text_view_update_clipboard_actions (GtkTextView *text_view)
can_insert = gtk_text_iter_can_insert (&iter, priv->editable);
action = g_action_map_lookup_action (priv->context_actions, "cut-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
have_selection &&
range_contains_editable_text (&sel_start, &sel_end, priv->editable));
action = g_action_map_lookup_action (priv->context_actions, "copy-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), have_selection);
action = g_action_map_lookup_action (priv->context_actions, "paste-clipboard");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_insert && can_paste);
action = g_action_map_lookup_action (priv->context_actions, "delete-selection");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
have_selection &&
range_contains_editable_text (&sel_start, &sel_end, priv->editable));
action = g_action_map_lookup_action (priv->context_actions, "select-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
gtk_text_buffer_get_char_count (priv->buffer) > 0);
gtk_widget_action_enabled_changed (GTK_WIDGET (text_view), "clipboard.cut",
have_selection &&
range_contains_editable_text (&sel_start, &sel_end, priv->editable));
gtk_widget_action_enabled_changed (GTK_WIDGET (text_view), "clipboard.copy",
have_selection);
gtk_widget_action_enabled_changed (GTK_WIDGET (text_view), "clipboard.paste",
can_insert && can_paste);
gtk_widget_action_enabled_changed (GTK_WIDGET (text_view), "selection.delete",
have_selection &&
range_contains_editable_text (&sel_start, &sel_end, priv->editable));
gtk_widget_action_enabled_changed (GTK_WIDGET (text_view), "selection.select-all",
gtk_text_buffer_get_char_count (priv->buffer) > 0);
}
static void
gtk_text_view_update_emoji_action (GtkTextView *text_view)
{
GtkTextViewPrivate *priv = text_view->priv;
GAction *action;
action = g_action_map_lookup_action (priv->context_actions, "insert-emoji");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
(gtk_text_view_get_input_hints (text_view) & GTK_INPUT_HINT_NO_EMOJI) == 0);
gtk_widget_action_enabled_changed (GTK_WIDGET (text_view), "misc.insert-emoji",
(gtk_text_view_get_input_hints (text_view) & GTK_INPUT_HINT_NO_EMOJI) == 0);
}
static GMenuModel *
@ -8635,19 +8614,19 @@ gtk_text_view_get_menu_model (GtkTextView *text_view)
menu = g_menu_new ();
section = g_menu_new ();
item = g_menu_item_new (_("Cu_t"), "context.cut-clipboard");
item = g_menu_item_new (_("Cu_t"), "clipboard.cut");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-cut-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new (_("_Copy"), "context.copy-clipboard");
item = g_menu_item_new (_("_Copy"), "clipboard.copy");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-copy-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new (_("_Paste"), "context.paste-clipboard");
item = g_menu_item_new (_("_Paste"), "clipboard.paste");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-paste-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new (_("_Delete"), "context.delete-selection");
item = g_menu_item_new (_("_Delete"), "selection.delete");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-delete-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
@ -8656,12 +8635,12 @@ gtk_text_view_get_menu_model (GtkTextView *text_view)
section = g_menu_new ();
item = g_menu_item_new (_("Select _All"), "context.select-all");
item = g_menu_item_new (_("Select _All"), "selection.select-all");
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-select-all-symbolic");
g_menu_append_item (section, item);
g_object_unref (item);
item = g_menu_item_new ( _("Insert _Emoji"), "context.insert-emoji");
item = g_menu_item_new ( _("Insert _Emoji"), "misc.insert-emoji");
g_menu_item_set_attribute (item, "hidden-when", "s", "action-disabled");
g_menu_item_set_attribute (item, "touch-icon", "s", "face-smile-symbolic");
g_menu_append_item (section, item);

View File

@ -501,6 +501,7 @@ struct _GtkWidgetClassPrivate
AtkRole accessible_role;
const char *css_name;
GType layout_manager_type;
GPtrArray *actions;
};
enum {
@ -11897,14 +11898,16 @@ _gtk_widget_get_action_muxer (GtkWidget *widget,
gboolean create)
{
GtkActionMuxer *muxer;
GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (widget);
GtkWidgetClassPrivate *priv = widget_class->priv;
muxer = (GtkActionMuxer*)g_object_get_qdata (G_OBJECT (widget), quark_action_muxer);
if (muxer)
return muxer;
if (create)
if (create || priv->actions)
{
muxer = gtk_action_muxer_new ();
muxer = gtk_action_muxer_new (widget, priv->actions);
g_object_set_qdata_full (G_OBJECT (widget),
quark_action_muxer,
muxer,
@ -13427,3 +13430,133 @@ gtk_widget_should_layout (GtkWidget *widget)
return TRUE;
}
/*
* gtk_widget_class_install_action:
* @widget_class: a #GtkWidgetClass
* @action_name: a prefixed action name, such as "clipboard.paste"
* @activate: callback to use when the action is activated
*
* This should be called at class initialization time to specify
* actions to be added for all instances of this class.
*
* Actions installed by this function are stateless. The only state
* they have is whether they are enabled or not. For more complicated
* actions, see gtk_widget_class_install_stateful_action().
*/
void
gtk_widget_class_install_action (GtkWidgetClass *widget_class,
const char *action_name,
GtkWidgetActionActivateFunc activate)
{
gtk_widget_class_install_stateful_action (widget_class, action_name, activate,
NULL, NULL, NULL);
}
/*
* gtk_widget_class_install_stateful_action:
* @widget_class: a #GtkWidgetClass
* @action_name: a prefixed action name, such as "clipboard.paste"
* @activate: callback to use when the action is activated
* @parameter_type: (allow-none): the parameter type, or %NULL
* @query: (allow-none): callback to use when the action properties
are queried, or %NULL for always-enabled stateless actions
* @query_state: (allow-none): callback to use when the action state
is queried, or %NULL for stateless actions
*
* This should be called at class initialization time to specify
* actions to be added for all instances of this class.
*
* Actions installed in this way can be simple or stateful.
* See the #GAction documentation for more information.
*/
void
gtk_widget_class_install_stateful_action (GtkWidgetClass *widget_class,
const char *action_name,
GtkWidgetActionActivateFunc activate,
const char *parameter_type,
GtkWidgetActionSetStateFunc set_state,
GtkWidgetActionGetStateFunc get_state)
{
GtkWidgetClassPrivate *priv = widget_class->priv;
GtkWidgetAction *action;
g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
if (priv->actions == NULL)
priv->actions = g_ptr_array_new ();
else if (GTK_IS_WIDGET_CLASS (&widget_class->parent_class))
{
GtkWidgetClass *parent_class = GTK_WIDGET_CLASS (&widget_class->parent_class);
GtkWidgetClassPrivate *parent_priv = parent_class->priv;
GPtrArray *parent_actions = parent_priv->actions;
if (priv->actions == parent_actions)
{
int i;
priv->actions = g_ptr_array_new ();
for (i = 0; i < parent_actions->len; i++)
g_ptr_array_add (priv->actions, g_ptr_array_index (parent_actions, i));
}
}
action = g_new0 (GtkWidgetAction, 1);
action->name = g_strdup (action_name);
action->activate = activate;
action->parameter_type = parameter_type ? g_variant_type_new (parameter_type) : NULL;
action->set_state = set_state;
action->get_state = get_state;
GTK_NOTE(ACTIONS,
g_message ("%sClass: Adding %s action\n",
g_type_name (G_TYPE_FROM_CLASS (widget_class)),
action_name));
g_ptr_array_add (priv->actions, action);
}
/**
* gtk_widget_action_enabled_changed:
* @widget: a #GtkWidget
* @action_name: action name, such as "clipboard.paste"
* @enabled: whether the action is now enabled
*
* Notify when an action installed with
* gtk_widget_class_install_action() changes its
* enabled state.
*/
void
gtk_widget_action_enabled_changed (GtkWidget *widget,
const char *action_name,
gboolean enabled)
{
GtkActionMuxer *muxer;
g_return_if_fail (GTK_IS_WIDGET (widget));
muxer = _gtk_widget_get_action_muxer (widget, TRUE);
gtk_action_muxer_action_enabled_changed (muxer, action_name, enabled);
}
/**
* gtk_widget_action_state_changed:
* @widget: a #GtkWidget
* @action_name: action name, such as "clipboard.paste"
* @state: the new state
*
* Notify when an action installed with
* gtk_widget_class_install_stateful_action() changes
* its state.
*/
void
gtk_widget_action_state_changed (GtkWidget *widget,
const char *action_name,
GVariant *state)
{
GtkActionMuxer *muxer;
g_return_if_fail (GTK_IS_WIDGET (widget));
muxer = _gtk_widget_get_action_muxer (widget, TRUE);
gtk_action_muxer_action_state_changed (muxer, action_name, state);
}

View File

@ -1023,6 +1023,76 @@ GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_should_layout (GtkWidget *widget);
/**
* GtkWidgetActionActivateFunc:
* @widget: the widget to which the action belongs
* @action_name: the action name
* @parameter: parameter for activation
*
* The type of the callback functions used for activating
* actions installed with gtk_widget_class_install_action().
*
* The @parameter must match the @parameter_type of the action.
*/
typedef void (* GtkWidgetActionActivateFunc) (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
/**
* GtkWidgetActionGetStateFunc:
* @widget: the widget to which the action belongs
* @action_name: the action name
*
* The type of the callback functions used to query the state
* of stateful actions installed with gtk_widget_class_install_action().
*
* See the #GAction documentation for more details about the
* meaning of these properties.
*/
typedef GVariant * (* GtkWidgetActionGetStateFunc) (GtkWidget *widget,
const char *action_name);
/**
* GtkWidgetActionSetStateFunc:
* @widget: the widget to which the action belongs
* @action_name: the action name
* @state: the new state
*
* The type of the callback functions used to change the
* state of actions installed with gtk_widget_class_install_action().
*
* The @state must match the @state_type of the action.
*
* This callback is used when the action state is
* changed via the #GActionGroup API.
*/
typedef void (*GtkWidgetActionSetStateFunc) (GtkWidget *widget,
const char *action_name,
GVariant *state);
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_install_action (GtkWidgetClass *widget_class,
const char *action_name,
GtkWidgetActionActivateFunc activate);
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_install_stateful_action (GtkWidgetClass *widget_class,
const char *action_name,
GtkWidgetActionActivateFunc activate,
const char *parameter_type,
GtkWidgetActionSetStateFunc set_state,
GtkWidgetActionGetStateFunc get_state);
GDK_AVAILABLE_IN_ALL
void gtk_widget_action_enabled_changed (GtkWidget *widget,
const char *action_name,
gboolean enabled);
GDK_AVAILABLE_IN_ALL
void gtk_widget_action_state_changed (GtkWidget *widget,
const char *action_name,
GVariant *state);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkWidget, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRequisition, gtk_requisition_free)

View File

@ -492,6 +492,10 @@ static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
#endif
static void gtk_window_set_theme_variant (GtkWindow *window);
static void gtk_window_activate_default_activate (GtkWidget *widget,
const char *action_name,
GVariant *parameter);
static void gtk_window_do_popup (GtkWindow *window,
GdkEventButton *event);
static void gtk_window_style_updated (GtkWidget *widget);
@ -1163,6 +1167,9 @@ gtk_window_class_init (GtkWindowClass *klass)
* Key bindings
*/
gtk_widget_class_install_action (widget_class, "default.activate",
gtk_window_activate_default_activate);
binding_set = gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
@ -1766,28 +1773,11 @@ gtk_window_capture_motion (GtkWidget *widget,
}
static void
activate_default_cb (GSimpleAction *action,
GVariant *parameter,
gpointer data)
gtk_window_activate_default_activate (GtkWidget *widget,
const char *name,
GVariant *parameter)
{
gtk_window_real_activate_default (GTK_WINDOW (data));
}
static void
add_actions (GtkWindow *window)
{
GActionEntry entries[] = {
{ "activate", activate_default_cb, NULL, NULL, NULL },
};
GActionGroup *actions;
actions = G_ACTION_GROUP (g_simple_action_group_new ());
g_action_map_add_action_entries (G_ACTION_MAP (actions),
entries, G_N_ELEMENTS (entries),
window);
gtk_widget_insert_action_group (GTK_WIDGET (window), "default", actions);
g_object_unref (actions);
gtk_window_real_activate_default (GTK_WINDOW (widget));
}
static void
@ -1879,8 +1869,6 @@ gtk_window_init (GtkWindow *window)
g_signal_connect_swapped (priv->key_controller, "focus-out",
G_CALLBACK (gtk_window_focus_out), window);
gtk_widget_add_controller (widget, priv->key_controller);
add_actions (window);
}
static GtkGesture *