From c2e94e1925f3c7acfa3fd3352dc8fdafe6375adc Mon Sep 17 00:00:00 2001 From: zhuyaliang <15132211195@163.com> Date: Wed, 25 Oct 2023 21:43:03 +0800 Subject: Remove libslab library libslab is only used in mate-c-c and there is no need to provide a library --- shell/tile.c | 529 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 529 insertions(+) create mode 100644 shell/tile.c (limited to 'shell/tile.c') diff --git a/shell/tile.c b/shell/tile.c new file mode 100644 index 00000000..96ff2120 --- /dev/null +++ b/shell/tile.c @@ -0,0 +1,529 @@ +/* + * This file is part of libtile. + * + * Copyright (c) 2006 Novell, Inc. + * + * Libtile 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 of the License, or (at your option) + * any later version. + * + * Libtile 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 libslab; if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tile.h" + +#include +#include + +#include "double-click-detector.h" + +typedef struct +{ + DoubleClickDetector *double_click_detector; + + gboolean is_dragging; +} TilePrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (Tile, tile, GTK_TYPE_BUTTON) + +static void tile_finalize (GObject *); +static void tile_dispose (GObject *); +static void tile_get_property (GObject *, guint, GValue *, GParamSpec *); +static void tile_set_property (GObject *, guint, const GValue *, GParamSpec *); +static GObject *tile_constructor (GType, guint, GObjectConstructParam *); + +static void tile_setup (Tile *); + +static void tile_enter (GtkButton * widget); +static void tile_leave (GtkButton * widget); +static void tile_clicked (GtkButton *widget); + +static gboolean tile_focus_in (GtkWidget *, GdkEventFocus *); +static gboolean tile_focus_out (GtkWidget *, GdkEventFocus *); +static gboolean tile_draw (GtkWidget *, cairo_t *); +static gboolean tile_button_release (GtkWidget *, GdkEventButton *); +static gboolean tile_key_release (GtkWidget *, GdkEventKey *); +static gboolean tile_popup_menu (GtkWidget *); + +static void tile_drag_begin (GtkWidget *, GdkDragContext *); +static void tile_drag_data_get (GtkWidget *, GdkDragContext *, GtkSelectionData *, guint, +guint); + +static void tile_tile_action_triggered (Tile *, TileEvent *, TileAction *); +static void tile_action_triggered_event_marshal (GClosure *, GValue *, guint, const GValue *, +gpointer, gpointer); + +typedef void (*marshal_func_VOID__POINTER_POINTER) (gpointer, gpointer, gpointer, gpointer); + +enum +{ + TILE_ACTIVATED_SIGNAL, + TILE_ACTION_TRIGGERED_SIGNAL, + LAST_SIGNAL +}; + +static guint tile_signals[LAST_SIGNAL] = { 0 }; + +enum +{ + PROP_0, + PROP_TILE_URI, + PROP_TILE_CONTEXT_MENU, + PROP_TILE_ACTIONS +}; + +static void +tile_class_init (TileClass * this_class) +{ + GObjectClass *g_obj_class = G_OBJECT_CLASS (this_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (this_class); + GtkButtonClass *button_class = GTK_BUTTON_CLASS (this_class); + + g_obj_class->constructor = tile_constructor; + g_obj_class->get_property = tile_get_property; + g_obj_class->set_property = tile_set_property; + g_obj_class->finalize = tile_finalize; + g_obj_class->dispose = tile_dispose; + + widget_class->focus_in_event = tile_focus_in; + widget_class->focus_out_event = tile_focus_out; + widget_class->draw = tile_draw; + widget_class->button_release_event = tile_button_release; + widget_class->key_release_event = tile_key_release; + widget_class->drag_begin = tile_drag_begin; + widget_class->drag_data_get = tile_drag_data_get; + widget_class->popup_menu = tile_popup_menu; + + button_class->enter = tile_enter; + button_class->leave = tile_leave; + button_class->clicked = tile_clicked; + + this_class->tile_activated = NULL; + this_class->tile_action_triggered = tile_tile_action_triggered; + + g_object_class_install_property (g_obj_class, PROP_TILE_URI, + g_param_spec_string ("tile-uri", "tile-uri", "the uri of the tile", NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (g_obj_class, PROP_TILE_CONTEXT_MENU, + g_param_spec_object ("context-menu", "context-menu", + "the context menu for the tile", GTK_TYPE_MENU, G_PARAM_READWRITE)); + + tile_signals[TILE_ACTIVATED_SIGNAL] = g_signal_new ("tile-activated", + G_TYPE_FROM_CLASS (this_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (TileClass, tile_activated), + NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + + tile_signals[TILE_ACTION_TRIGGERED_SIGNAL] = g_signal_new ("tile-action-triggered", + G_TYPE_FROM_CLASS (this_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (TileClass, tile_action_triggered), + NULL, NULL, tile_action_triggered_event_marshal, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); +} + +static GObject * +tile_constructor (GType type, guint n_param, GObjectConstructParam * param) +{ + GObject *g_obj; + TilePrivate *priv; + + g_obj = (*G_OBJECT_CLASS (tile_parent_class)->constructor) (type, n_param, param); + + priv = tile_get_instance_private (TILE(g_obj)); + priv->double_click_detector = double_click_detector_new (); + + tile_setup (TILE (g_obj)); + + return g_obj; +} + +static void +tile_init (Tile * tile) +{ + TilePrivate *priv = tile_get_instance_private (tile); + + tile->uri = NULL; + tile->context_menu = NULL; + tile->entered = FALSE; + tile->enabled = TRUE; + + tile->actions = NULL; + tile->n_actions = 0; + + tile->default_action = NULL; + + priv->double_click_detector = NULL; + priv->is_dragging = FALSE; +} + +static void +tile_finalize (GObject * g_object) +{ + Tile *tile = TILE (g_object); + TilePrivate *priv = tile_get_instance_private (TILE(tile)); + + if (tile->n_actions) /* this will also free "default_action" entry */ + { + g_free (tile->actions); + } + + if (tile->uri) + g_free (tile->uri); + + g_object_unref (priv->double_click_detector); + + (*G_OBJECT_CLASS (tile_parent_class)->finalize) (g_object); +} + +static void +tile_dispose (GObject * g_object) +{ + Tile *tile = TILE (g_object); + + /* free the TileAction object */ + if (tile->n_actions) + { + gint x; + for (x = 0; x < tile->n_actions; x++) + { + if (tile->actions[x] != NULL) { + g_object_unref (tile->actions[x]); + tile->actions[x] = NULL; + } + } + } + + /* free the GtkMenu object */ + if (tile->context_menu != NULL) { + gtk_widget_destroy (GTK_WIDGET (tile->context_menu)); + tile->context_menu = NULL; + } + + (*G_OBJECT_CLASS (tile_parent_class)->dispose) (g_object); +} + +static void +tile_get_property (GObject * g_obj, guint prop_id, GValue * value, GParamSpec * param_spec) +{ + if (!IS_TILE (g_obj)) + return; + + switch (prop_id) + { + case PROP_TILE_URI: + g_value_set_string (value, TILE (g_obj)->uri); + break; + + case PROP_TILE_CONTEXT_MENU: + g_value_set_object (value, TILE (g_obj)->context_menu); + break; + + default: + break; + } +} + +static void +tile_set_property (GObject * g_obj, guint prop_id, const GValue * value, GParamSpec * param_spec) +{ + Tile *tile; + GtkMenu *menu; + + if (!IS_TILE (g_obj)) + return; + + tile = TILE (g_obj); + + switch (prop_id) + { + case PROP_TILE_URI: + tile->uri = g_strdup (g_value_get_string (value)); + break; + + case PROP_TILE_CONTEXT_MENU: + menu = g_value_get_object (value); + + if (menu == tile->context_menu) + break; + + if (tile->context_menu) + gtk_menu_detach (tile->context_menu); + + tile->context_menu = menu; + + if (tile->context_menu) + gtk_menu_attach_to_widget (tile->context_menu, GTK_WIDGET (tile), NULL); + + break; + + default: + break; + } +} + +static void +tile_setup (Tile * tile) +{ + gtk_button_set_relief (GTK_BUTTON (tile), GTK_RELIEF_NONE); + + if (tile->uri) + { + gtk_drag_source_set (GTK_WIDGET (tile), GDK_BUTTON1_MASK, NULL, 0, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + + gtk_drag_source_add_uri_targets (GTK_WIDGET (tile)); + } +} + +static void +tile_enter (GtkButton * widget) +{ + gtk_widget_set_state_flags (GTK_WIDGET (widget), TILE_STATE_ENTERED, TRUE); + + TILE (widget)->entered = TRUE; +} + +static void +tile_leave (GtkButton * widget) +{ + if (gtk_widget_has_focus (GTK_WIDGET (widget))) + gtk_widget_set_state_flags (GTK_WIDGET (widget), TILE_STATE_FOCUSED, TRUE); + else + gtk_widget_set_state_flags (GTK_WIDGET (widget), GTK_STATE_FLAG_NORMAL, TRUE); + + TILE (widget)->entered = FALSE; +} + +static void +tile_clicked (GtkButton * widget) +{ + TileEvent *tile_event; + GdkEvent *event; + gboolean handled; + + tile_event = g_new0 (TileEvent, 1); + tile_event->type = TILE_EVENT_ACTIVATED_DOUBLE_CLICK; + tile_event->time = gtk_get_current_event_time (); + + g_signal_emit (widget, tile_signals[TILE_ACTIVATED_SIGNAL], 0, tile_event); + g_signal_emit_by_name (widget, "button-release-event", &event, &handled); + + g_free (tile_event); +} + +static gboolean +tile_focus_in (GtkWidget * widget, GdkEventFocus * event) +{ + gtk_widget_set_state_flags (widget, TILE_STATE_FOCUSED, TRUE); + + return FALSE; +} + +static gboolean +tile_focus_out (GtkWidget * widget, GdkEventFocus * event) +{ + if (TILE (widget)->entered) + gtk_widget_set_state_flags (widget, TILE_STATE_ENTERED, TRUE); + else + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_NORMAL, TRUE); + + return FALSE; +} + +static gboolean +tile_draw (GtkWidget * widget, cairo_t * cr) +{ + /* FIXME: there ought to be a better way to prevent the focus from being rendered. */ + + gboolean has_focus; + gboolean retval; + + if ((has_focus = gtk_widget_has_focus (widget))) + gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_FOCUSED); + + retval = (*GTK_WIDGET_CLASS (tile_parent_class)->draw) (widget, cr); + + if (has_focus) + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_FOCUSED, TRUE); + + return retval; +} + +static gboolean +tile_button_release (GtkWidget * widget, GdkEventButton * event) +{ + Tile *tile = TILE (widget); + TilePrivate *priv = tile_get_instance_private (tile); + + TileEvent *tile_event; + gboolean handled; + + if (priv->is_dragging) + { + priv->is_dragging = FALSE; + + return TRUE; + } + + switch (event->button) + { + case 1: + tile_event = g_new0 (TileEvent, 1); + tile_event->time = event->time; + + if (double_click_detector_is_double_click (priv->double_click_detector, event->time, + TRUE)) + tile_event->type = TILE_EVENT_ACTIVATED_DOUBLE_CLICK; + else + tile_event->type = TILE_EVENT_ACTIVATED_SINGLE_CLICK; + + g_signal_emit (tile, tile_signals[TILE_ACTIVATED_SIGNAL], 0, tile_event); + g_signal_emit_by_name (GTK_BUTTON (widget), "button-release-event", &event, &handled); + + g_free (tile_event); + + break; + + case 3: + if (GTK_IS_MENU (tile->context_menu)) + gtk_menu_popup_at_widget (GTK_MENU (tile->context_menu), + widget, + GDK_GRAVITY_SOUTH_WEST, + GDK_GRAVITY_NORTH_WEST, + (const GdkEvent*) event); + + break; + + default: + break; + } + + return TRUE; +} + +static gboolean +tile_key_release (GtkWidget * widget, GdkEventKey * event) +{ + TileEvent *tile_event; + + if (event->keyval == GDK_KEY_Return) + { + tile_event = g_new0 (TileEvent, 1); + tile_event->type = TILE_EVENT_ACTIVATED_KEYBOARD; + tile_event->time = event->time; + + g_signal_emit (widget, tile_signals[TILE_ACTIVATED_SIGNAL], 0, tile_event); + + return TRUE; + } + + return FALSE; +} + +static gboolean +tile_popup_menu (GtkWidget * widget) +{ + Tile *tile = TILE (widget); + + if (GTK_IS_MENU (tile->context_menu)) + { + gtk_menu_popup_at_widget (GTK_MENU (tile->context_menu), + widget, + GDK_GRAVITY_SOUTH_WEST, + GDK_GRAVITY_NORTH_WEST, + NULL); + + return TRUE; + } + + else + return FALSE; +} + +static void +tile_drag_begin (GtkWidget * widget, GdkDragContext * context) +{ + TilePrivate *priv; + + priv = tile_get_instance_private (TILE(widget)); + priv->is_dragging = TRUE; +} + +static void +tile_drag_data_get (GtkWidget * widget, GdkDragContext * context, GtkSelectionData * data, + guint info, guint time) +{ + gchar *uris[2]; + + if (TILE (widget)->uri) + { + uris[0] = TILE (widget)->uri; + uris[1] = NULL; + + gtk_selection_data_set_uris (data, uris); + } +} + +static void +tile_tile_action_triggered (Tile * tile, TileEvent * event, TileAction * action) +{ + if (action && action->func) + (*action->func) (tile, event, action); +} + +void +tile_trigger_action (Tile * tile, TileAction * action) +{ + tile_trigger_action_with_time (tile, action, GDK_CURRENT_TIME); +} + +void +tile_trigger_action_with_time (Tile * tile, TileAction * action, guint32 time) +{ + TileEvent *event = g_new0 (TileEvent, 1); + + event->type = TILE_EVENT_ACTION_TRIGGERED; + event->time = time; + + g_signal_emit (tile, tile_signals[TILE_ACTION_TRIGGERED_SIGNAL], 0, event, action); + g_free (event); +} + +static void +tile_action_triggered_event_marshal (GClosure * closure, GValue * retval, guint n_param, + const GValue * param, gpointer invocation_hint, gpointer marshal_data) +{ + marshal_func_VOID__POINTER_POINTER callback; + GCClosure *cc = (GCClosure *) closure; + gpointer data_0, data_1; + + g_return_if_fail (n_param == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data_0 = closure->data; + data_1 = g_value_peek_pointer (param); + } + else + { + data_0 = g_value_peek_pointer (param); + data_1 = closure->data; + } + + if (marshal_data) + callback = (marshal_func_VOID__POINTER_POINTER) marshal_data; + else + callback = (marshal_func_VOID__POINTER_POINTER) cc->callback; + + callback (data_0, g_value_peek_pointer (param + 1), g_value_peek_pointer (param + 2), + data_1); +} -- cgit v1.2.1