Author: kelnos Date: 2009-06-14 00:59:41 +0000 (Sun, 14 Jun 2009) New Revision: 30015
Modified: xfdesktop/trunk/src/xfdesktop-icon-view.c xfdesktop/trunk/src/xfdesktop-icon-view.h xfdesktop/trunk/src/xfdesktop-marshal.list Log: use GtkBindingSet for keyboard handling on desktop this fixes a bunch of problems and ensures the keybindings are set correctly regardless of the keymap set. also as a side benefit it lets the user override the bindings in a gtkrc file Modified: xfdesktop/trunk/src/xfdesktop-icon-view.c =================================================================== --- xfdesktop/trunk/src/xfdesktop-icon-view.c 2009-06-13 23:17:28 UTC (rev 30014) +++ xfdesktop/trunk/src/xfdesktop-icon-view.c 2009-06-14 00:59:41 UTC (rev 30015) @@ -41,6 +41,7 @@ #endif #include "xfdesktop-icon-view.h" +#include "xfdesktop-marshal.h" #include <libwnck/libwnck.h> #include <libxfcegui4/libxfcegui4.h> @@ -72,18 +73,16 @@ #define DUMP_GRID_LAYOUT(icon_view) #endif -typedef enum -{ - XFDESKTOP_DIRECTION_UP = 0, - XFDESKTOP_DIRECTION_DOWN, - XFDESKTOP_DIRECTION_LEFT, - XFDESKTOP_DIRECTION_RIGHT, -} XfdesktopDirection; - enum { SIG_ICON_SELECTION_CHANGED = 0, SIG_ICON_ACTIVATED, + SIG_SELECT_ALL, + SIG_UNSELECT_ALL, + SIG_SELECT_CURSOR_ITEM, + SIG_TOGGLE_CURSOR_ITEM, + SIG_MOVE_CURSOR, + SIG_ACTIVATE_CURSOR_ITEM, SIG_N_SIGNALS, }; @@ -136,7 +135,7 @@ GdkColor *selection_box_color; guchar selection_box_alpha; - XfdesktopIcon *last_clicked_item; + XfdesktopIcon *cursor; XfdesktopIcon *first_clicked_item; XfdesktopIcon *item_under_pointer; @@ -228,6 +227,11 @@ static void xfdesktop_icon_view_finalize(GObject *obj); +static void xfdesktop_icon_view_add_move_binding(GtkBindingSet *binding_set, + guint keyval, + guint modmask, + GtkMovementStep step, + gint count); static void xfdesktop_icon_view_invalidate_icon(XfdesktopIconView *icon_view, XfdesktopIcon *icon); #ifdef HAVE_LIBEXO @@ -265,10 +269,7 @@ gconstpointer user_data); static void xfdesktop_list_foreach_invalidate(gpointer data, gpointer user_data); -static void xfdesktop_grid_find_nearest(XfdesktopIconView *icon_view, - XfdesktopIcon *icon, - XfdesktopDirection dir, - gboolean allow_multiple); + static inline void xfdesktop_xy_to_rowcol(XfdesktopIconView *icon_view, gint x, gint y, @@ -307,6 +308,14 @@ gpointer user_data); #endif +static void xfdesktop_icon_view_real_select_all(XfdesktopIconView *icon_view); +static void xfdesktop_icon_view_real_unselect_all(XfdesktopIconView *icon_view); +static void xfdesktop_icon_view_real_select_cursor_item(XfdesktopIconView *icon_view); +static void xfdesktop_icon_view_real_toggle_cursor_item(XfdesktopIconView *icon_view); +static gboolean xfdesktop_icon_view_real_activate_cursor_item(XfdesktopIconView *icon_view); +static gboolean xfdesktop_icon_view_real_move_cursor(XfdesktopIconView *icon_view, + GtkMovementStep step, + gint count); enum { @@ -331,6 +340,9 @@ { GObjectClass *gobject_class = (GObjectClass *)klass; GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + GtkBindingSet *binding_set; + + binding_set = gtk_binding_set_by_class(klass); //g_type_class_peek(g_type_from_name("XfceDesktop"))); g_type_class_add_private(klass, sizeof(XfdesktopIconViewPrivate)); @@ -347,6 +359,13 @@ widget_class->drag_data_get = xfdesktop_icon_view_drag_data_get; widget_class->drag_data_received = xfdesktop_icon_view_drag_data_received; + klass->select_all = xfdesktop_icon_view_real_select_all; + klass->unselect_all = xfdesktop_icon_view_real_unselect_all; + klass->select_cursor_item = xfdesktop_icon_view_real_select_cursor_item; + klass->toggle_cursor_item = xfdesktop_icon_view_real_toggle_cursor_item; + klass->activate_cursor_item = xfdesktop_icon_view_real_activate_cursor_item; + klass->move_cursor = xfdesktop_icon_view_real_move_cursor; + __signals[SIG_ICON_SELECTION_CHANGED] = g_signal_new("icon-selection-changed", XFDESKTOP_TYPE_ICON_VIEW, G_SIGNAL_RUN_LAST, @@ -364,15 +383,71 @@ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - gtk_widget_class_install_style_property(widget_class, + + __signals[SIG_SELECT_ALL] = g_signal_new(I_("select-all"), + XFDESKTOP_TYPE_ICON_VIEW, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(XfdesktopIconViewClass, + select_all), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + __signals[SIG_UNSELECT_ALL] = g_signal_new(I_("unselect-all"), + XFDESKTOP_TYPE_ICON_VIEW, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(XfdesktopIconViewClass, + unselect_all), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + __signals[SIG_SELECT_CURSOR_ITEM] = g_signal_new(I_("select-cursor-item"), + XFDESKTOP_TYPE_ICON_VIEW, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(XfdesktopIconViewClass, + select_cursor_item), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + __signals[SIG_TOGGLE_CURSOR_ITEM] = g_signal_new(I_("toggle-cursor-item"), + XFDESKTOP_TYPE_ICON_VIEW, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(XfdesktopIconViewClass, + toggle_cursor_item), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + __signals[SIG_ACTIVATE_CURSOR_ITEM] = g_signal_new(I_("activate-cursor-item"), + XFDESKTOP_TYPE_ICON_VIEW, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(XfdesktopIconViewClass, + activate_cursor_item), + NULL, NULL, + xfdesktop_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + __signals[SIG_MOVE_CURSOR] = g_signal_new(I_("move-cursor"), + XFDESKTOP_TYPE_ICON_VIEW, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(XfdesktopIconViewClass, + move_cursor), + NULL, NULL, + xfdesktop_marshal_BOOLEAN__ENUM_INT, + G_TYPE_BOOLEAN, 2, + GTK_TYPE_MOVEMENT_STEP, + G_TYPE_INT); + + gtk_widget_class_install_style_property(widget_class, g_param_spec_uchar("label-alpha", "Label alpha", "Alpha value for the text label's background", 0, 255, 155, G_PARAM_READABLE)); - gtk_widget_class_install_style_property(widget_class, + gtk_widget_class_install_style_property(widget_class, g_param_spec_uchar("selected-label-alpha", "Selected label alpha", "Alpha value for the selected text label's background", @@ -449,6 +524,64 @@ TRUE, G_PARAM_READABLE)); + /* same binding entries as GtkIconView */ + gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK, + "select-all", 0); + gtk_binding_entry_add_signal(binding_set, GDK_a, + GDK_CONTROL_MASK | GDK_SHIFT_MASK, + "unselect-all", 0); + gtk_binding_entry_add_signal(binding_set, GDK_space, GDK_CONTROL_MASK, + "toggle-cursor-item", 0); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Space, GDK_CONTROL_MASK, + "toggle-cursor-item", 0); + + gtk_binding_entry_add_signal(binding_set, GDK_space, 0, + "activate-cursor-item", 0); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Space, 0, + "activate-cursor-item", 0); + gtk_binding_entry_add_signal(binding_set, GDK_Return, 0, + "activate-cursor-item", 0); + gtk_binding_entry_add_signal(binding_set, GDK_ISO_Enter, 0, + "activate-cursor-item", 0); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Enter, 0, + "activate-cursor-item", 0); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_Up, 0, + GTK_MOVEMENT_DISPLAY_LINES, -1); + xfdesktop_icon_view_add_move_binding(binding_set, GDK_KP_Up, 0, + GTK_MOVEMENT_DISPLAY_LINES, -1); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_Down, 0, + GTK_MOVEMENT_DISPLAY_LINES, 1); + xfdesktop_icon_view_add_move_binding(binding_set, GDK_KP_Down, 0, + GTK_MOVEMENT_DISPLAY_LINES, 1); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_p, GDK_CONTROL_MASK, + GTK_MOVEMENT_DISPLAY_LINES, -1); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_n, GDK_CONTROL_MASK, + GTK_MOVEMENT_DISPLAY_LINES, 1); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_Home, 0, + GTK_MOVEMENT_BUFFER_ENDS, -1); + xfdesktop_icon_view_add_move_binding(binding_set, GDK_KP_Home, 0, + GTK_MOVEMENT_BUFFER_ENDS, -1); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_End, 0, + GTK_MOVEMENT_BUFFER_ENDS, 1); + xfdesktop_icon_view_add_move_binding(binding_set, GDK_KP_End, 0, + GTK_MOVEMENT_BUFFER_ENDS, 1); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_Right, 0, + GTK_MOVEMENT_VISUAL_POSITIONS, 1); + xfdesktop_icon_view_add_move_binding(binding_set, GDK_Left, 0, + GTK_MOVEMENT_VISUAL_POSITIONS, -1); + + xfdesktop_icon_view_add_move_binding(binding_set, GDK_KP_Right, 0, + GTK_MOVEMENT_VISUAL_POSITIONS, 1); + xfdesktop_icon_view_add_move_binding(binding_set, GDK_KP_Left, 0, + GTK_MOVEMENT_VISUAL_POSITIONS, -1); + xfdesktop_cell_highlight_quark = g_quark_from_static_string("xfdesktop-icon-view-cell-highlight"); } @@ -513,6 +646,38 @@ G_OBJECT_CLASS(xfdesktop_icon_view_parent_class)->finalize(obj); } +static void +xfdesktop_icon_view_add_move_binding(GtkBindingSet *binding_set, + guint keyval, + guint modmask, + GtkMovementStep step, + gint count) +{ + gtk_binding_entry_add_signal(binding_set, keyval, modmask, + I_("move-cursor"), 2, + G_TYPE_ENUM, step, + G_TYPE_INT, count); + + gtk_binding_entry_add_signal(binding_set, keyval, GDK_SHIFT_MASK, + "move-cursor", 2, + G_TYPE_ENUM, step, + G_TYPE_INT, count); + + if(modmask & GDK_CONTROL_MASK) + return; + + gtk_binding_entry_add_signal(binding_set, keyval, + GDK_CONTROL_MASK | GDK_SHIFT_MASK, + "move-cursor", 2, + G_TYPE_ENUM, step, + G_TYPE_INT, count); + + gtk_binding_entry_add_signal(binding_set, keyval, GDK_CONTROL_MASK, + "move-cursor", 2, + G_TYPE_ENUM, step, + G_TYPE_INT, count); +} + static gboolean xfdesktop_icon_view_button_press(GtkWidget *widget, GdkEventButton *evt, @@ -535,11 +700,11 @@ icon_view->priv->selected_icons = g_list_remove(icon_view->priv->selected_icons, icon); xfdesktop_icon_view_invalidate_icon(icon_view, icon); - } else if(icon != icon_view->priv->last_clicked_item) { + } else if(icon != icon_view->priv->cursor) { /* expand the text */ - XfdesktopIcon *old_sel = icon_view->priv->last_clicked_item; + XfdesktopIcon *old_sel = icon_view->priv->cursor; - icon_view->priv->last_clicked_item = icon; + icon_view->priv->cursor = icon; if(old_sel) xfdesktop_icon_view_invalidate_icon(icon_view, old_sel); xfdesktop_icon_view_invalidate_icon(icon_view, icon); @@ -565,8 +730,8 @@ icon_view->priv->first_clicked_item = NULL; } - old_sel = icon_view->priv->last_clicked_item; - icon_view->priv->last_clicked_item = icon; + old_sel = icon_view->priv->cursor; + icon_view->priv->cursor = icon; if(old_sel) xfdesktop_icon_view_invalidate_icon(icon_view, old_sel); @@ -660,7 +825,7 @@ 0, NULL); } - icon_view->priv->last_clicked_item = NULL; + icon_view->priv->cursor = NULL; icon_view->priv->first_clicked_item = NULL; if(icon_view->priv->allow_rubber_banding && evt->button == 1) { @@ -681,7 +846,7 @@ GList *icon_l = g_list_find_custom(icon_view->priv->icons, evt, (GCompareFunc)xfdesktop_check_icon_clicked); if(icon_l && (icon = icon_l->data)) { - icon_view->priv->last_clicked_item = icon; + icon_view->priv->cursor = icon; g_signal_emit(G_OBJECT(icon_view), __signals[SIG_ICON_ACTIVATED], 0, NULL); xfdesktop_icon_activated(icon); @@ -726,57 +891,12 @@ gpointer user_data) { XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(user_data); - XfdesktopIcon *icon = NULL; - gboolean allow_multiple = (evt->state & GDK_CONTROL_MASK) - || (evt->state & GDK_SHIFT_MASK); - - if(icon_view->priv->last_clicked_item) - icon = icon_view->priv->last_clicked_item; - - switch(evt->keyval) { - case GDK_Up: - case GDK_KP_Up: - xfdesktop_grid_find_nearest(icon_view, icon, - XFDESKTOP_DIRECTION_UP, - allow_multiple); - break; - - case GDK_Down: - case GDK_KP_Down: - xfdesktop_grid_find_nearest(icon_view, icon, - XFDESKTOP_DIRECTION_DOWN, - allow_multiple); - break; - - case GDK_Left: - case GDK_KP_Left: - xfdesktop_grid_find_nearest(icon_view, icon, - XFDESKTOP_DIRECTION_LEFT, - allow_multiple); - break; - - case GDK_Right: - case GDK_KP_Right: - xfdesktop_grid_find_nearest(icon_view, icon, - XFDESKTOP_DIRECTION_RIGHT, - allow_multiple); - break; - - case GDK_Return: - case GDK_KP_Enter: - if(icon) { - g_list_foreach(icon_view->priv->selected_icons, - (GFunc)xfdesktop_icon_activated, NULL); - /* FIXME: really unselect? */ - xfdesktop_icon_view_unselect_all(icon_view); - } - break; - - default: - return FALSE; - } - - return TRUE; + + TRACE("entering"); + + /* since we're NO_WINDOW, events don't get delivered to us normally, + * so we have to activate the bindings manually */ + return gtk_bindings_activate_event(GTK_OBJECT(icon_view), evt); } static gboolean @@ -819,7 +939,7 @@ GdkDragAction actions; /* sanity check */ - g_return_val_if_fail(icon_view->priv->last_clicked_item, FALSE); + g_return_val_if_fail(icon_view->priv->cursor, FALSE); if(!gtk_drag_check_threshold(GTK_WIDGET(icon_view), icon_view->priv->press_start_x, @@ -1044,7 +1164,7 @@ XfdesktopIcon *icon; GdkRectangle extents; - icon = icon_view->priv->last_clicked_item; + icon = icon_view->priv->cursor; g_return_if_fail(icon); if(xfdesktop_icon_get_extents(icon, &extents)) { @@ -1196,7 +1316,7 @@ } } - allowed_actions &= xfdesktop_icon_get_allowed_drag_actions(icon_view->priv->last_clicked_item); + allowed_actions &= xfdesktop_icon_get_allowed_drag_actions(icon_view->priv->cursor); } /* #2 or #4 */ @@ -1288,7 +1408,7 @@ return ret; } - icon = icon_view->priv->last_clicked_item; + icon = icon_view->priv->cursor; g_return_val_if_fail(icon, FALSE); /* clear out old position */ @@ -1480,7 +1600,7 @@ GdkScreen *gscreen; GdkWindow *groot; GList *l, *leftovers = NULL; - + icon_view->priv->parent_window = gtk_widget_get_toplevel(widget); g_return_if_fail(icon_view->priv->parent_window); widget->window = icon_view->priv->parent_window->window; @@ -1714,6 +1834,330 @@ } static void +xfdesktop_icon_view_real_select_all(XfdesktopIconView *icon_view) +{ + TRACE("entering"); + + xfdesktop_icon_view_select_all(icon_view); +} + +static void +xfdesktop_icon_view_real_unselect_all(XfdesktopIconView *icon_view) +{ + TRACE("entering"); + + xfdesktop_icon_view_unselect_all(icon_view); +} + +static void +xfdesktop_icon_view_real_select_cursor_item(XfdesktopIconView *icon_view) +{ + TRACE("entering"); + + if(icon_view->priv->cursor) + xfdesktop_icon_view_select_item(icon_view, icon_view->priv->cursor); +} + +static void +xfdesktop_icon_view_real_toggle_cursor_item(XfdesktopIconView *icon_view) +{ + TRACE("entering"); + + if(!icon_view->priv->cursor) + return; + + if(g_list_find(icon_view->priv->selected_icons, icon_view->priv->cursor)) + xfdesktop_icon_view_unselect_item(icon_view, icon_view->priv->cursor); + else + xfdesktop_icon_view_select_item(icon_view, icon_view->priv->cursor); +} + +static gboolean +xfdesktop_icon_view_real_activate_cursor_item(XfdesktopIconView *icon_view) +{ + TRACE("entering"); + + if(!icon_view->priv->cursor) + return FALSE; + + g_signal_emit(G_OBJECT(icon_view), __signals[SIG_ICON_ACTIVATED], 0, NULL); + xfdesktop_icon_activated(icon_view->priv->cursor); + + return TRUE; +} + +static void +xfdesktop_icon_view_select_between(XfdesktopIconView *icon_view, + XfdesktopIcon *start_icon, + XfdesktopIcon *end_icon) +{ + guint16 start_row, start_col, end_row, end_col; + gint i, j; + XfdesktopIcon *icon; + + if(xfdesktop_icon_get_position(start_icon, &start_row, &start_col) + && xfdesktop_icon_get_position(end_icon, &end_row, &end_col)) + { + if(start_row > end_row || (start_row == end_row && start_col > end_col)) { + /* flip start and end */ + guint16 tmpr = start_row, tmpc = end_row; + + start_row = end_row; + start_col = end_col; + end_row = tmpr; + end_col = tmpc; + } + + for(i = start_row; i <= end_row; ++i) { + for(j = (i == start_row ? start_col : 0); + (i == end_row ? j <= end_col : j < icon_view->priv->ncols); + ++j) + { + icon = xfdesktop_icon_view_icon_in_cell(icon_view, i, j); + if(icon) + xfdesktop_icon_view_select_item(icon_view, icon); + } + } + } +} + +static XfdesktopIcon * +xfdesktop_icon_view_find_first_icon(XfdesktopIconView *icon_view) +{ + gint i, j; + XfdesktopIcon *icon = NULL; + + if(!icon_view->priv->icons) + return NULL; + + for(i = 0; i < icon_view->priv->nrows && !icon; ++i) { + for(j = 0; j < icon_view->priv->ncols; ++j) { + icon = xfdesktop_icon_view_icon_in_cell(icon_view, i, j); + if(icon) + break; + } + } + + return icon; +} + +static XfdesktopIcon * +xfdesktop_icon_view_find_last_icon(XfdesktopIconView *icon_view) +{ + XfdesktopIcon *icon = NULL; + gint i, j; + + if(!icon_view->priv->icons) + return NULL; + + for(i = icon_view->priv->nrows - 1; i >= 0 && !icon; --i) { + for(j = icon_view->priv->ncols - 1; j >= 0; --j) { + icon = xfdesktop_icon_view_icon_in_cell(icon_view, i, j); + if(icon) + break; + } + } + + return icon; +} + +static void +xfdesktop_icon_view_move_cursor_left_right(XfdesktopIconView *icon_view, + gint count, + GdkModifierType modmask) +{ + guint16 row, col; + gint i, j; + guint left = (count < 0 ? -count : count); + gint step = (count < 0 ? -1 : 1); + XfdesktopIcon *icon = NULL; + + if(!icon_view->priv->cursor) { + /* choose first or last item depending on left or right */ + if(count < 0) + icon = xfdesktop_icon_view_find_last_icon(icon_view); + else + icon = xfdesktop_icon_view_find_first_icon(icon_view); + + if(icon) { + if(!(modmask & GDK_CONTROL_MASK)) + xfdesktop_icon_view_unselect_all(icon_view); + icon_view->priv->cursor = icon; + xfdesktop_icon_view_select_item(icon_view, icon); + } + } else { + if(!xfdesktop_icon_get_position(icon_view->priv->cursor, &row, &col)) + return; + + if(!(modmask & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) + xfdesktop_icon_view_unselect_all(icon_view); + + for(i = row; + (count < 0 ? i >= 0 : i < icon_view->priv->nrows) && left > 0; + i += step) + { + for(j = (i == row ? col + step : (count < 0) ? icon_view->priv->ncols - 1 : 0); + (count < 0 ? j >= 0 : j < icon_view->priv->ncols) && left > 0; + j += step) + { + icon = xfdesktop_icon_view_icon_in_cell(icon_view, i, j); + if(icon) { + icon_view->priv->cursor = icon; + if((modmask & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) || left == 1) + xfdesktop_icon_view_select_item(icon_view, icon); + left--; + } + } + } + + if(!icon_view->priv->selected_icons) { + if(count < 0) + icon = xfdesktop_icon_view_find_first_icon(icon_view); + else + icon = xfdesktop_icon_view_find_last_icon(icon_view); + + if(icon) + xfdesktop_icon_view_select_item(icon_view, icon); + } + } +} + +static void +xfdesktop_icon_view_move_cursor_up_down(XfdesktopIconView *icon_view, + gint count, + GdkModifierType modmask) +{ + guint16 row, col; + gint i, j; + guint left = (count < 0 ? -count : count); + gint step = (count < 0 ? -1 : 1); + XfdesktopIcon *icon = NULL; + + if(!icon_view->priv->cursor) { + /* choose first or last item depending on up or down */ + if(count < 0) + icon = xfdesktop_icon_view_find_last_icon(icon_view); + else + icon = xfdesktop_icon_view_find_first_icon(icon_view); + + if(icon) { + if(!(modmask & GDK_CONTROL_MASK)) + xfdesktop_icon_view_unselect_all(icon_view); + icon_view->priv->cursor = icon; + xfdesktop_icon_view_select_item(icon_view, icon); + } + } else { + if(!xfdesktop_icon_get_position(icon_view->priv->cursor, &row, &col)) + return; + + if(!(modmask & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) + xfdesktop_icon_view_unselect_all(icon_view); + + for(j = col; + (count < 0 ? j >= 0 : j < icon_view->priv->ncols) && left > 0; + j += step) + { + for(i = (j == col ? row + step : (count < 0) ? icon_view->priv->nrows - 1 : 0); + (count < 0 ? i >= 0 : i < icon_view->priv->nrows) && left > 0; + i += step) + { + icon = xfdesktop_icon_view_icon_in_cell(icon_view, i, j); + if(icon) { + icon_view->priv->cursor = icon; + if((modmask & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) || left == 1) + xfdesktop_icon_view_select_item(icon_view, icon); + left--; + } + } + } + + if(!icon_view->priv->selected_icons) { + if(count < 0) + icon = xfdesktop_icon_view_find_first_icon(icon_view); + else + icon = xfdesktop_icon_view_find_last_icon(icon_view); + + if(icon) + xfdesktop_icon_view_select_item(icon_view, icon); + } + } +} + +static void +xfdesktop_icon_view_move_cursor_begin_end(XfdesktopIconView *icon_view, + gint count, + GdkModifierType modmask) +{ + XfdesktopIcon *icon = NULL, *old_cursor; + + if(count < 0) + icon = xfdesktop_icon_view_find_first_icon(icon_view); + else + icon = xfdesktop_icon_view_find_last_icon(icon_view); + + if(!icon) + return; + + old_cursor = icon_view->priv->cursor; + icon_view->priv->cursor = icon; + + if(!old_cursor || !(modmask & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) { + xfdesktop_icon_view_unselect_all(icon_view); + xfdesktop_icon_view_select_item(icon_view, icon); + } else if(old_cursor) { + if(modmask & GDK_SHIFT_MASK) { + /* select everything between the cursor and the old_cursor */ + xfdesktop_icon_view_select_between(icon_view, old_cursor, icon); + } else if(modmask & GDK_CONTROL_MASK) { + /* add the icon to the selection */ + xfdesktop_icon_view_select_item(icon_view, icon); + } + + } +} + +static gboolean +xfdesktop_icon_view_real_move_cursor(XfdesktopIconView *icon_view, + GtkMovementStep step, + gint count) +{ + GdkModifierType modmask = 0; + + g_return_val_if_fail(step == GTK_MOVEMENT_VISUAL_POSITIONS + || step == GTK_MOVEMENT_DISPLAY_LINES + || step == GTK_MOVEMENT_BUFFER_ENDS, FALSE); + + if(count == 0) + return FALSE; + + if(!GTK_WIDGET_HAS_FOCUS(GTK_WIDGET(icon_view))) + return FALSE; + + gtk_widget_grab_focus(GTK_WIDGET(icon_view)); + gtk_get_current_event_state(&modmask); + + switch(step) { + case GTK_MOVEMENT_VISUAL_POSITIONS: + xfdesktop_icon_view_move_cursor_left_right(icon_view, count, modmask); + break; + + case GTK_MOVEMENT_DISPLAY_LINES: + xfdesktop_icon_view_move_cursor_up_down(icon_view, count, modmask); + break; + + case GTK_MOVEMENT_BUFFER_ENDS: + xfdesktop_icon_view_move_cursor_begin_end(icon_view, count, modmask); + break; + + default: + g_assert_not_reached(); + } + + return TRUE; +} + + +static void xfdesktop_screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data) { @@ -2168,7 +2612,7 @@ pango_layout_set_text(playout, label, -1); pango_layout_get_size(playout, &text_area.width, &text_area.height); if(text_area.width > TEXT_WIDTH * PANGO_SCALE) { - if(icon != icon_view->priv->last_clicked_item && icon_view->priv->ellipsize_icon_labels) + if(icon != icon_view->priv->cursor && icon_view->priv->ellipsize_icon_labels) pango_layout_set_ellipsize(playout, PANGO_ELLIPSIZE_END); else { pango_layout_set_wrap(playout, PANGO_WRAP_WORD_CHAR); @@ -2526,135 +2970,6 @@ return xfdesktop_icon_view_icon_in_cell_raw(icon_view, idx); } -static void -xfdesktop_grid_find_nearest(XfdesktopIconView *icon_view, - XfdesktopIcon *icon, - XfdesktopDirection dir, - gboolean allow_multiple) -{ - XfdesktopIcon *grid_icon; - gint i, maxi; - guint16 row, col; - - if(icon && !xfdesktop_icon_get_position(icon, &row, &col)) - return; - - if((icon_view->priv->sel_mode != GTK_SELECTION_MULTIPLE - || !allow_multiple) - && icon_view->priv->selected_icons) - { - xfdesktop_icon_view_unselect_all(icon_view); - } - - if(!icon) { - maxi = icon_view->priv->nrows * icon_view->priv->ncols; - for(i = 0; i < maxi; ++i) { - grid_icon = xfdesktop_icon_view_icon_in_cell_raw(icon_view, i); - if(grid_icon) { - icon_view->priv->selected_icons = g_list_prepend(icon_view->priv->selected_icons, - grid_icon); - xfdesktop_icon_view_invalidate_icon(icon_view, - grid_icon); - return; - } - } - } else { - gint cur_i = col * icon_view->priv->nrows + row; - XfdesktopIcon *new_sel_icon = NULL; - - switch(dir) { - case XFDESKTOP_DIRECTION_UP: - for(i = cur_i - 1; i >= 0; --i) { - grid_icon = xfdesktop_icon_view_icon_in_cell_raw(icon_view, i); - if(grid_icon) { - new_sel_icon = grid_icon; - break; - } - } - break; - - case XFDESKTOP_DIRECTION_DOWN: - maxi = icon_view->priv->nrows * icon_view->priv->ncols; - for(i = cur_i + 1; i < maxi; ++i) { - grid_icon = xfdesktop_icon_view_icon_in_cell_raw(icon_view, i); - if(grid_icon) { - new_sel_icon = grid_icon; - break; - } - } - break; - - case XFDESKTOP_DIRECTION_LEFT: - if(cur_i == 0) - return; - - for(i = cur_i >= icon_view->priv->nrows - ? cur_i - icon_view->priv->nrows - : icon_view->priv->nrows * icon_view->priv->ncols - 1 - - (icon_view->priv->nrows - cur_i); - i >= 0; - i = i >= icon_view->priv->nrows - ? i - icon_view->priv->nrows - : icon_view->priv->nrows * icon_view->priv->ncols - 1 - - (icon_view->priv->nrows - i)) - { - grid_icon = xfdesktop_icon_view_icon_in_cell_raw(icon_view, i); - if(grid_icon) { - new_sel_icon = grid_icon; - break; - } - - if(i == 0) - break; - } - break; - - case XFDESKTOP_DIRECTION_RIGHT: - maxi = icon_view->priv->nrows * icon_view->priv->ncols; - if(cur_i == maxi - 1) - return; - - for(i = cur_i < icon_view->priv->nrows * (icon_view->priv->ncols - 1) - ? cur_i + icon_view->priv->nrows - : cur_i % icon_view->priv->nrows + 1; - i < maxi; - i = i < icon_view->priv->nrows * (icon_view->priv->ncols - 1) - ? i + icon_view->priv->nrows - : i % icon_view->priv->nrows + 1) - { - grid_icon = xfdesktop_icon_view_icon_in_cell_raw(icon_view, i); - if(grid_icon) { - new_sel_icon = grid_icon; - break; - } - - if(i == maxi - 1) - return; - } - break; - - default: - break; - } - - if(new_sel_icon) { - if(g_list_find(icon_view->priv->selected_icons, new_sel_icon)) { - icon_view->priv->selected_icons = g_list_remove(icon_view->priv->selected_icons, - icon); - } else { - icon_view->priv->selected_icons = g_list_prepend(icon_view->priv->selected_icons, - new_sel_icon); - } - - icon_view->priv->last_clicked_item = new_sel_icon; - - xfdesktop_icon_view_invalidate_icon(icon_view, new_sel_icon); - xfdesktop_icon_view_invalidate_icon(icon_view, icon); - } - } -} - - static inline gboolean xfdesktop_rectangle_contains_point(GdkRectangle *rect, gint x, gint y) { @@ -2840,10 +3155,10 @@ icon_view->priv->icons = g_list_remove(icon_view->priv->icons, icon); icon_view->priv->selected_icons = g_list_remove(icon_view->priv->selected_icons, icon); - if(icon_view->priv->last_clicked_item == icon) { - icon_view->priv->last_clicked_item = NULL; + if(icon_view->priv->cursor == icon) { + icon_view->priv->cursor = NULL; if(icon_view->priv->selected_icons) - icon_view->priv->last_clicked_item = icon_view->priv->selected_icons->data; + icon_view->priv->cursor = icon_view->priv->selected_icons->data; } if(icon_view->priv->first_clicked_item == icon) icon_view->priv->first_clicked_item = NULL; @@ -2902,7 +3217,7 @@ } icon_view->priv->item_under_pointer = NULL; - icon_view->priv->last_clicked_item = NULL; + icon_view->priv->cursor = NULL; icon_view->priv->first_clicked_item = NULL; if(GTK_WIDGET_REALIZED(icon_view)) @@ -3104,6 +3419,23 @@ } void +xfdesktop_icon_view_select_all(XfdesktopIconView *icon_view) +{ + GList *l; + + g_return_if_fail(XFDESKTOP_IS_ICON_VIEW(icon_view)); + + /* simplify: just free the entire list and repopulate it */ + g_list_free(icon_view->priv->selected_icons); + icon_view->priv->selected_icons = NULL; + + for(l = icon_view->priv->icons; l; l = l->next) { + icon_view->priv->selected_icons = g_list_prepend(icon_view->priv->selected_icons, l->data); + xfdesktop_icon_view_invalidate_icon(icon_view, l->data); + } +} + +void xfdesktop_icon_view_unselect_item(XfdesktopIconView *icon_view, XfdesktopIcon *icon) { Modified: xfdesktop/trunk/src/xfdesktop-icon-view.h =================================================================== --- xfdesktop/trunk/src/xfdesktop-icon-view.h 2009-06-13 23:17:28 UTC (rev 30014) +++ xfdesktop/trunk/src/xfdesktop-icon-view.h 2009-06-14 00:59:41 UTC (rev 30015) @@ -54,6 +54,18 @@ /*< signals >*/ void (*icon_selection_changed)(XfdesktopIconView *icon_view); void (*icon_activated)(XfdesktopIconView *icon_view); + + void (*select_all)(XfdesktopIconView *icon_view); + void (*unselect_all)(XfdesktopIconView *icon_view); + + void (*select_cursor_item)(XfdesktopIconView *icon_view); + void (*toggle_cursor_item)(XfdesktopIconView *icon_view); + + gboolean (*activate_cursor_item)(XfdesktopIconView *icon_view); + + gboolean (*move_cursor)(XfdesktopIconView *icon_view, + GtkMovementStep step, + gint count); }; GType xfdesktop_icon_view_get_type() G_GNUC_CONST; @@ -91,6 +103,7 @@ void xfdesktop_icon_view_select_item(XfdesktopIconView *icon_view, XfdesktopIcon *icon); +void xfdesktop_icon_view_select_all(XfdesktopIconView *icon_view); void xfdesktop_icon_view_unselect_item(XfdesktopIconView *icon_view, XfdesktopIcon *icon); void xfdesktop_icon_view_unselect_all(XfdesktopIconView *icon_view); Modified: xfdesktop/trunk/src/xfdesktop-marshal.list =================================================================== --- xfdesktop/trunk/src/xfdesktop-marshal.list 2009-06-13 23:17:28 UTC (rev 30014) +++ xfdesktop/trunk/src/xfdesktop-marshal.list 2009-06-14 00:59:41 UTC (rev 30015) @@ -1 +1,2 @@ BOOLEAN:VOID +BOOLEAN:ENUM,INT _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits