xfdesktop-icon-view.c 164 KB
Newer Older
1
2
3
/*
 *  xfdesktop - xfce4's desktop manager
 *
Brian Tarricone's avatar
Brian Tarricone committed
4
 *  Copyright (c) 2006-2009 Brian Tarricone, <bjt23@cornell.edu>
5
6
7
8
9
10
11
12
13
14
15
16
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
Eric Koegel's avatar
Eric Koegel committed
17
18
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
19
20
21
22
23
24
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

25
26
27
28
#ifdef HAVE_STRING_H
#include <string.h>
#endif

29
30
31
32
#ifdef HAVE_MATH_H
#include <math.h>
#endif

33
34
#include <glib-object.h>

35
36
37
#include <X11/Xlib.h>
#include <X11/Xatom.h>

38
39
40
41
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
42
43
#include <exo/exo.h>

44
#include "xfdesktop-icon-view.h"
45
#include "xfdesktop-file-icon-manager.h"
Thaddaeus Tintenfisch's avatar
Thaddaeus Tintenfisch committed
46
#include "xfdesktop-window-icon-manager.h"
47
#include "xfdesktop-marshal.h"
Eric Koegel's avatar
Eric Koegel committed
48
#include "xfce-desktop.h"
Eric Koegel's avatar
Eric Koegel committed
49
#include "xfdesktop-volume-icon.h"
50
#include "xfdesktop-common.h"
51
#include "gtkcairoblurprivate.h"
52

53
#include <libwnck/libwnck.h>
54
#include <libxfce4ui/libxfce4ui.h>
55
#include <xfconf/xfconf.h>
Benedikt Meurer's avatar
Benedikt Meurer committed
56

57
58
59
#define DEFAULT_FONT_SIZE     12
#define DEFAULT_TOOLTIP_SIZE 128
#define MAX_TOOLTIP_SIZE     512
60
61

#define ICON_SIZE         (icon_view->priv->icon_size)
62
#define TEXT_WIDTH        ((icon_view->priv->cell_text_width_proportion) * ICON_SIZE)
Eric Koegel's avatar
Eric Koegel committed
63
#define ICON_WIDTH        (TEXT_WIDTH)
64
#define CELL_PADDING      (icon_view->priv->cell_padding)
65
#define CELL_SIZE         (TEXT_WIDTH + CELL_PADDING * 2)
66
#define SPACING           (icon_view->priv->cell_spacing)
Eric Koegel's avatar
Eric Koegel committed
67
#define LABEL_RADIUS      (icon_view->priv->label_radius)
68
69
70
#define SHADOW_EXTENTS    (icon_view->priv->shadow_extents)
#define SHADOW_X_OFFSET   MAX(icon_view->priv->shadow_x_offset, icon_view->priv->selected_shadow_x_offset)
#define SHADOW_Y_OFFSET   MAX(icon_view->priv->shadow_y_offset, icon_view->priv->selected_shadow_y_offset)
Eric Koegel's avatar
Eric Koegel committed
71
#define TEXT_HEIGHT       (CELL_SIZE - ICON_SIZE - SPACING - (CELL_PADDING * 2) - LABEL_RADIUS)
72
#define MIN_MARGIN        8
73
#define DEFAULT_RUBBERBAND_ALPHA  64
74
75
76
77
78
79

#if defined(DEBUG) && DEBUG > 0
#define DUMP_GRID_LAYOUT(icon_view) \
{\
    gint my_i, my_maxi;\
    \
80
    DBG("grid layout dump:"); \
81
82
83
84
85
86
87
88
89
    my_maxi = icon_view->priv->nrows * icon_view->priv->ncols;\
    for(my_i = 0; my_i < my_maxi; my_i++)\
        g_printerr("%c ", icon_view->priv->grid_layout[my_i] ? '1' : '0');\
    g_printerr("\n\n");\
}
#else
#define DUMP_GRID_LAYOUT(icon_view)
#endif

90
91
enum
{
92
    SIG_ICON_SELECTION_CHANGED = 0,
93
    SIG_ICON_ACTIVATED,
94
95
96
97
98
99
    SIG_SELECT_ALL,
    SIG_UNSELECT_ALL,
    SIG_SELECT_CURSOR_ITEM,
    SIG_TOGGLE_CURSOR_ITEM,
    SIG_MOVE_CURSOR,
    SIG_ACTIVATE_CURSOR_ITEM,
100
    SIG_RESIZE_EVENT,
101
102
103
    SIG_N_SIGNALS,
};

104
105
106
typedef struct
{
    XfdesktopIconView *icon_view;
107
    XfdesktopIcon *icon;
108
    GdkRectangle area;
109
    guint source_id;
110
111
} XfdesktopIdleRepaintData;

112
113
struct _XfdesktopIconViewPrivate
{
114
    XfdesktopIconViewManager *manager;
115
    
116
117
    GtkWidget *parent_window;
    
118
    guint icon_size;
119
    gdouble font_size;
120
    gboolean center_text;
121
    
122
    WnckScreen *wnck_screen;
123
124
    PangoLayout *playout;
    
125
126
    GList *pending_icons;
    GList *icons;
127
128
129
130
131
132
    GList *selected_icons;
    
    gint xorigin;
    gint yorigin;
    gint width;
    gint height;
133
134
135
136
137

    gint xmargin;
    gint ymargin;
    gint xspacing;
    gint yspacing;
138
    
Eric Koegel's avatar
Eric Koegel committed
139
140
    gint16 nrows;
    gint16 ncols;
141
142
143
    XfdesktopIcon **grid_layout;
    
    guint grid_resize_timeout;
144
    
145
    GtkSelectionMode sel_mode;
146
147
148
    guint maybe_begin_drag:1,
          definitely_dragging:1,
          allow_rubber_banding:1,
149
          definitely_rubber_banding:1,
150
151
          control_click:1,
          double_click:1;
152
153
    gint press_start_x;
    gint press_start_y;
154
155
    GdkRectangle band_rect;

156
157
    XfconfChannel *channel;

158
159
    GdkColor *selection_box_color;
    guchar selection_box_alpha;
160
    
161
    XfdesktopIcon *cursor;
162
    XfdesktopIcon *first_clicked_item;
163
    XfdesktopIcon *item_under_pointer;
164
165
    
    GtkTargetList *native_targets;
166
    GtkTargetList *source_targets;
167
    GtkTargetList *dest_targets;
168
    
169
    gboolean drag_source_set;
170
171
172
    GdkDragAction foreign_source_actions;
    GdkModifierType foreign_source_mask;
    
173
    gboolean drag_dest_set;
174
    GdkDragAction foreign_dest_actions;
175
176
177

    gboolean dropped;
    GdkDragAction proposed_drop_action;
Eric Koegel's avatar
Eric Koegel committed
178
    gint16 hover_row, hover_col;
179
    
180
181
182
183
184
185
186
187
188
    guchar    label_alpha;
    guchar    selected_label_alpha;

    gchar     shadow_x_offset;
    gchar     shadow_y_offset;
    GdkColor *shadow_color;
    gchar     selected_shadow_x_offset;
    gchar     selected_shadow_y_offset;
    GdkColor *selected_shadow_color;
189
    gchar     shadow_blur_radius;
190

191
192
    gint cell_padding;
    gint cell_spacing;
Eric Koegel's avatar
Eric Koegel committed
193
    gdouble label_radius;
194
    gdouble cell_text_width_proportion;
195
    gint shadow_extents;
196
197

    gboolean ellipsize_icon_labels;
198
199
200
201
202
203

    /* tooltip options - There's a style and an xfconf property.
     * The order is xfconf, style, with a fall back of DEFAULT_TOOLTIP_SIZE.
     * xfdesktop_icon_view_get_tooltip_size will return the correct size. */
    gboolean show_tooltips;
    gint   tooltip_size_from_style;
204
    double tooltip_size_from_xfconf;
205
206

    gboolean single_click;
207
208
};

209
210
211
212
213
214
215
216
217
static void xfce_icon_view_set_property(GObject *object,
                                        guint property_id,
                                        const GValue *value,
                                        GParamSpec *pspec);
static void xfce_icon_view_get_property(GObject *object,
                                        guint property_id,
                                        GValue *value,
                                        GParamSpec *pspec);

218
static gboolean xfdesktop_icon_view_button_press(GtkWidget *widget,
219
220
                                                 GdkEventButton *evt,
                                                 gpointer user_data);
221
static gboolean xfdesktop_icon_view_button_release(GtkWidget *widget,
222
223
                                                   GdkEventButton *evt,
                                                   gpointer user_data);
224
static gboolean xfdesktop_icon_view_key_press(GtkWidget *widget,
225
226
                                              GdkEventKey *evt,
                                              gpointer user_data);
227
static gboolean xfdesktop_icon_view_focus_in(GtkWidget *widget,
228
229
                                             GdkEventFocus *evt,
                                             gpointer user_data);
230
static gboolean xfdesktop_icon_view_focus_out(GtkWidget *widget,
231
232
                                              GdkEventFocus *evt,
                                              gpointer user_data);
233
static gboolean xfdesktop_icon_view_motion_notify(GtkWidget *widget,
234
235
                                                  GdkEventMotion *evt,
                                                  gpointer user_data);
236
237
238
static gboolean xfdesktop_icon_view_leave_notify(GtkWidget *widget,
                                                 GdkEventCrossing *evt,
                                                 gpointer user_data);
239
240
static void xfdesktop_icon_view_style_set(GtkWidget *widget,
                                          GtkStyle *previous_style);
241
242
243
static void xfdesktop_icon_view_realize(GtkWidget *widget);
static void xfdesktop_icon_view_unrealize(GtkWidget *widget);
static gboolean xfdesktop_icon_view_expose(GtkWidget *widget,
244
                                           GdkEventExpose *evt);
245
246
247
248
249
250
static void xfdesktop_icon_view_drag_begin(GtkWidget *widget,
                                           GdkDragContext *contest);
static gboolean xfdesktop_icon_view_drag_motion(GtkWidget *widget,
                                                GdkDragContext *context,
                                                gint x,
                                                gint y,
251
                                                guint time_);
252
253
254
255
static gboolean xfdesktop_icon_view_drag_drop(GtkWidget *widget,
                                              GdkDragContext *context,
                                              gint x,
                                              gint y,
256
                                              guint time_);
257
258
259
260
static void xfdesktop_icon_view_drag_data_get(GtkWidget *widget,
                                              GdkDragContext *context,
                                              GtkSelectionData *data,
                                              guint info,
261
                                              guint time_);
262
263
264
265
266
267
static void xfdesktop_icon_view_drag_data_received(GtkWidget *widget,
                                                   GdkDragContext *context,
                                                   gint x,
                                                   gint y,
                                                   GtkSelectionData *data,
                                                   guint info,
268
                                                   guint time_);
269
270
271
                                                      
static void xfdesktop_icon_view_finalize(GObject *obj);

272
273
274
275
276
static void xfdesktop_icon_view_add_move_binding(GtkBindingSet *binding_set,
                                                 guint keyval,
                                                 guint modmask,
                                                 GtkMovementStep step,
                                                 gint count);
Brian Tarricone's avatar
Brian Tarricone committed
277
278
279
280
281

static gboolean xfdesktop_icon_view_update_icon_extents(XfdesktopIconView *icon_view,
                                                        XfdesktopIcon *icon,
                                                        GdkRectangle *pixbuf_extents,
                                                        GdkRectangle *text_extents,
Thaddaeus Tintenfisch's avatar
Thaddaeus Tintenfisch committed
282
283
                                                        GdkRectangle *box_extents,
                                                        GdkRectangle *total_extents);
284
static void xfdesktop_icon_view_invalidate_icon(XfdesktopIconView *icon_view,
Brian Tarricone's avatar
Brian Tarricone committed
285
286
287
288
                                                XfdesktopIcon *icon,
                                                gboolean recalc_extents);
static void xfdesktop_icon_view_icon_changed(XfdesktopIcon *icon,
                                             gpointer user_data);
289

290
291
static void xfdesktop_icon_view_invalidate_icon_pixbuf(XfdesktopIconView *icon_view,
                                                       XfdesktopIcon *icon);
292

293
static void xfdesktop_icon_view_paint_icon(XfdesktopIconView *icon_view,
294
295
296
297
                                           XfdesktopIcon *icon,
                                           GdkRectangle *area);
static void xfdesktop_icon_view_repaint_icons(XfdesktopIconView *icon_view,
                                              GdkRectangle *area);
298
                                  
299
300
static void xfdesktop_setup_grids(XfdesktopIconView *icon_view);
static gboolean xfdesktop_grid_get_next_free_position(XfdesktopIconView *icon_view,
Eric Koegel's avatar
Eric Koegel committed
301
302
                                                      gint16 *row,
                                                      gint16 *col);
303
static inline gboolean xfdesktop_grid_is_free_position(XfdesktopIconView *icon_view,
Eric Koegel's avatar
Eric Koegel committed
304
305
                                                       gint16 row,
                                                       gint16 col);
306
static inline void xfdesktop_grid_set_position_free(XfdesktopIconView *icon_view,
Eric Koegel's avatar
Eric Koegel committed
307
308
                                                    gint16 row,
                                                    gint16 col);
309
static inline gboolean xfdesktop_grid_unset_position_free_raw(XfdesktopIconView *icon_view,
Eric Koegel's avatar
Eric Koegel committed
310
311
                                                              gint16 row,
                                                              gint16 col,
312
313
314
315
316
317
                                                              gpointer data);
static inline gboolean xfdesktop_grid_unset_position_free(XfdesktopIconView *icon_view,
                                                          XfdesktopIcon *icon);
static inline XfdesktopIcon *xfdesktop_icon_view_icon_in_cell_raw(XfdesktopIconView *icon_view,
                                                                  gint idx);
static inline XfdesktopIcon *xfdesktop_icon_view_icon_in_cell(XfdesktopIconView *icon_view,
Eric Koegel's avatar
Eric Koegel committed
318
319
                                                              gint16 row,
                                                              gint16 col);
320
321
static gint xfdesktop_check_icon_clicked(gconstpointer data,
                                         gconstpointer user_data);
322
323
static void xfdesktop_list_foreach_invalidate(gpointer data,
                                              gpointer user_data);
324

325
326
327
static inline void xfdesktop_xy_to_rowcol(XfdesktopIconView *icon_view,
                                          gint x,
                                          gint y,
Eric Koegel's avatar
Eric Koegel committed
328
329
                                          gint16 *row,
                                          gint16 *col);
330
331
332
333
334
335
static gboolean xfdesktop_grid_resize_timeout(gpointer user_data);
static void xfdesktop_screen_size_changed_cb(GdkScreen *gscreen,
                                             gpointer user_data);
static GdkFilterReturn xfdesktop_rootwin_watch_workarea(GdkXEvent *gxevent,
                                                        GdkEvent *event,
                                                        gpointer user_data);
336
337
static void xfdesktop_move_all_icons_to_pending_icons_list(XfdesktopIconView *icon_view);
static void xfdesktop_move_all_pending_icons_to_desktop(XfdesktopIconView* icon_view);
338
static void xfdesktop_grid_do_resize(XfdesktopIconView *icon_view);
339
340
341
static inline gboolean xfdesktop_rectangle_contains_point(GdkRectangle *rect,
                                                          gint x,
                                                          gint y);
342
static void xfdesktop_icon_view_modify_font_size(XfdesktopIconView *icon_view,
343
                                                 gdouble size);
344
345
346
347
static void xfdesktop_icon_view_add_item_internal(XfdesktopIconView *icon_view,
                                                  XfdesktopIcon *icon);
static gboolean xfdesktop_icon_view_icon_find_position(XfdesktopIconView *icon_view,
                                                       XfdesktopIcon *icon);
Brian Tarricone's avatar
Brian Tarricone committed
348
349
350
static gboolean xfdesktop_icon_view_shift_area_to_cell(XfdesktopIconView *icon_view,
                                                       XfdesktopIcon *icon,
                                                       GdkRectangle *text_area);
351
static gint xfdesktop_icon_view_get_tooltip_size(XfdesktopIconView *icon_view);
352
353
354
355
356
357
static gboolean xfdesktop_icon_view_show_tooltip(GtkWidget *widget,
                                                 gint x,
                                                 gint y,
                                                 gboolean keyboard_tooltip,
                                                 GtkTooltip *tooltip,
                                                 gpointer user_data);
358

359
360
static gboolean xfdesktop_icon_view_is_icon_selected(XfdesktopIconView *icon_view,
                                                     XfdesktopIcon *icon);
361
362
363
364
365
366
367
368
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);
369

Brian Tarricone's avatar
Brian Tarricone committed
370
371
372
373
374
375
376
static void xfdesktop_icon_view_move_cursor_left_right(XfdesktopIconView *icon_view,
                                                       gint count,
                                                       GdkModifierType modmask);
static void xfdesktop_icon_view_select_between(XfdesktopIconView *icon_view,
                                               XfdesktopIcon *start_icon,
                                               XfdesktopIcon *end_icon);

377
378
379
380
enum
{
    TARGET_XFDESKTOP_ICON = 9999,
};
381

382
383
384
385
enum
{
    PROP_0 = 0,
    PROP_SINGLE_CLICK,
386
387
    PROP_SHOW_TOOLTIPS,
    PROP_TOOLTIP_SIZE,
388
389
390
};


391
392
static const GtkTargetEntry icon_view_targets[] = {
    { "XFDESKTOP_ICON", GTK_TARGET_SAME_APP, TARGET_XFDESKTOP_ICON }
393
};
394
static const gint icon_view_n_targets = 1;
395

396
static guint __signals[SIG_N_SIGNALS] = { 0, };
397

398
399
static GQuark xfdesktop_cell_highlight_quark = 0;

400

401
G_DEFINE_TYPE(XfdesktopIconView, xfdesktop_icon_view, GTK_TYPE_WIDGET)
402
403
404
405
406
407
408


static void
xfdesktop_icon_view_class_init(XfdesktopIconViewClass *klass)
{
    GObjectClass *gobject_class = (GObjectClass *)klass;
    GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
409
410
    GtkBindingSet *binding_set;

411
    binding_set = gtk_binding_set_by_class(klass);
412
    
413
414
    g_type_class_add_private(klass, sizeof(XfdesktopIconViewPrivate));
    
415
    gobject_class->finalize = xfdesktop_icon_view_finalize;
416
417
    gobject_class->set_property = xfce_icon_view_set_property;
    gobject_class->get_property = xfce_icon_view_get_property;
418
    
419
    widget_class->style_set = xfdesktop_icon_view_style_set;
420
421
    widget_class->realize = xfdesktop_icon_view_realize;
    widget_class->unrealize = xfdesktop_icon_view_unrealize;
422
    widget_class->expose_event = xfdesktop_icon_view_expose;
423
424
425
    widget_class->drag_begin = xfdesktop_icon_view_drag_begin;
    widget_class->drag_motion = xfdesktop_icon_view_drag_motion;
    widget_class->drag_drop = xfdesktop_icon_view_drag_drop;
426
427
    widget_class->drag_data_get = xfdesktop_icon_view_drag_data_get;
    widget_class->drag_data_received = xfdesktop_icon_view_drag_data_received;
428
    
429
430
431
432
433
434
435
    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;

436
437
438
439
440
441
442
443
    __signals[SIG_ICON_SELECTION_CHANGED] = g_signal_new("icon-selection-changed",
                                                         XFDESKTOP_TYPE_ICON_VIEW,
                                                         G_SIGNAL_RUN_LAST,
                                                         G_STRUCT_OFFSET(XfdesktopIconViewClass,
                                                                         icon_selection_changed),
                                                         NULL, NULL,
                                                         g_cclosure_marshal_VOID__VOID,
                                                         G_TYPE_NONE, 0);
444
    
445
446
447
448
449
450
451
452
    __signals[SIG_ICON_ACTIVATED] = g_signal_new("icon-activated",
                                                 XFDESKTOP_TYPE_ICON_VIEW,
                                                 G_SIGNAL_RUN_LAST,
                                                 G_STRUCT_OFFSET(XfdesktopIconViewClass,
                                                                 icon_activated),
                                                 NULL, NULL,
                                                 g_cclosure_marshal_VOID__VOID,
                                                 G_TYPE_NONE, 0);
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509

    __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);

510
511
512
513
514
515
516
517
518
    __signals[SIG_RESIZE_EVENT] = g_signal_new(I_("resize-event"),
                                               XFDESKTOP_TYPE_ICON_VIEW,
                                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                               G_STRUCT_OFFSET(XfdesktopIconViewClass,
                                                               resize_event),
                                               NULL, NULL,
                                               g_cclosure_marshal_VOID__VOID,
                                               G_TYPE_NONE, 0);

519
    gtk_widget_class_install_style_property(widget_class,
520
521
522
523
524
525
                                            g_param_spec_uchar("label-alpha",
                                                               "Label alpha",
                                                               "Alpha value for the text label's background",
                                                               0, 255, 155,
                                                               G_PARAM_READABLE));

526
    gtk_widget_class_install_style_property(widget_class,
527
528
529
530
531
532
                                            g_param_spec_uchar("selected-label-alpha",
                                                               "Selected label alpha",
                                                               "Alpha value for the selected text label's background",
                                                               0, 255, 155,
                                                               G_PARAM_READABLE));

533
    gtk_widget_class_install_style_property(widget_class,
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
                                            g_param_spec_char("shadow-x-offset",
                                                               "Shadow X offset",
                                                               "Shadow X offset for label text",
                                                               G_MININT8, G_MAXINT8, 0,
                                                               G_PARAM_READABLE));

    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_char("shadow-y-offset",
                                                               "Shadow Y offset",
                                                               "Shadow Y offset for label text",
                                                               G_MININT8, G_MAXINT8, 0,
                                                               G_PARAM_READABLE));

    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_char("selected-shadow-x-offset",
                                                               "Selected shadow X offset",
                                                               "Shadow X offset for selected label text",
                                                               G_MININT8, G_MAXINT8, 0,
                                                               G_PARAM_READABLE));

    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_char("selected-shadow-y-offset",
                                                               "Selected shadow Y offset",
                                                               "Shadow Y offset for selected label text",
                                                               G_MININT8, G_MAXINT8, 0,
                                                               G_PARAM_READABLE));

561
562
563
564
565
566
567
    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_char("shadow-blur-radius",
                                                              "shadow blur radius",
                                                              "Blur radius for label text",
                                                              G_MININT8, G_MAXINT8, 0,
                                                              G_PARAM_READABLE));

568
569
570
571
572
573
574
575
576
577
578
579
580
581
    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_boxed("shadow-color",
                                                               "Shadow color",
                                                               "Color for label text shadows",
                                                               GDK_TYPE_COLOR,
                                                               G_PARAM_READABLE));

    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_boxed("selected-shadow-color",
                                                               "Selected shadow color",
                                                               "Color for selected label text shadows",
                                                               GDK_TYPE_COLOR,
                                                               G_PARAM_READABLE));

582
583
584
585
    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_int("cell-spacing",
                                                             "Cell spacing",
                                                             "Spacing between desktop icon cells",
586
                                                             0, 255, 2,
587
588
589
590
591
592
593
594
595
596
597
598
599
600
                                                             G_PARAM_READABLE));
    
    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_int("cell-padding",
                                                             "Cell padding",
                                                             "Padding in desktop icon cell",
                                                             0, 255, 6,
                                                             G_PARAM_READABLE));
    
    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_double("cell-text-width-proportion",
                                                                "Cell text width proportion",
                                                                "Width of text in desktop icon cell, "
                                                                "calculated as multiplier of the icon size",
601
                                                                1.0, 10.0, 1.9,
602
                                                                G_PARAM_READABLE));
603
604
605
606
607
608
    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_boolean("ellipsize-icon-labels",
                                                                 "Ellipsize Icon Labels",
                                                                 "Ellipzize labels of unselected icons on desktop",
                                                                 TRUE,
                                                                 G_PARAM_READABLE));
609
610
611
612
613
614
    gtk_widget_class_install_style_property(widget_class,
                                            g_param_spec_double("label-radius",
                                                                "Label radius",
                                                                "The radius of the rounded corners of the text background",
                                                                0.0, 50.0, 4.0,
                                                                G_PARAM_READABLE));
615

616
    gtk_widget_class_install_style_property(widget_class,
617
618
619
620
621
                                            g_param_spec_int("tooltip-size",
                                                             "Tooltip Image Size",
                                                             "The size of the tooltip image preview",
                                                             -1, MAX_TOOLTIP_SIZE, -1,
                                                             G_PARAM_READABLE));
622

623
624
625
626
627
628
629
630
631
632
633
634
635
#define XFDESKTOP_PARAM_FLAGS  (G_PARAM_READWRITE \
                                | G_PARAM_CONSTRUCT \
                                | G_PARAM_STATIC_NAME \
                                | G_PARAM_STATIC_NICK \
                                | G_PARAM_STATIC_BLURB)

    g_object_class_install_property(gobject_class, PROP_SINGLE_CLICK,
                                    g_param_spec_boolean("single-click",
                                                         "single-click",
                                                         "single-click",
                                                         FALSE,
                                                         XFDESKTOP_PARAM_FLAGS));

636
637
638
639
640
641
642
643
644
645
646
647
648
649
    g_object_class_install_property(gobject_class, PROP_SHOW_TOOLTIPS,
                                    g_param_spec_boolean("show-tooltips",
                                                         "show tooltips",
                                                         "show tooltips for icons on the desktop",
                                                         TRUE,
                                                         XFDESKTOP_PARAM_FLAGS));

    g_object_class_install_property(gobject_class, PROP_TOOLTIP_SIZE,
                                    g_param_spec_double("tooltip-size",
                                                        "tooltip size",
                                                        "size of the tooltip image preview",
                                                        -1, MAX_TOOLTIP_SIZE, -1,
                                                        XFDESKTOP_PARAM_FLAGS));

650
651
#undef XFDESKTOP_PARAM_FLAGS

652
    /* same binding entries as GtkIconView */
653
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
654
                                 "select-all", 0);
655
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_a,
656
657
                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                 "unselect-all", 0);
658
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
659
                                 "toggle-cursor-item", 0);
660
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
661
662
                                 "toggle-cursor-item", 0);

663
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_space, 0,
664
                                 "activate-cursor-item", 0);
665
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_KP_Space, 0,
666
                                 "activate-cursor-item", 0);
667
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_Return, 0,
668
                                 "activate-cursor-item", 0);
669
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_ISO_Enter, 0,
670
                                 "activate-cursor-item", 0);
671
    gtk_binding_entry_add_signal(binding_set, GDK_KEY_KP_Enter, 0,
672
673
                                 "activate-cursor-item", 0);

674
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_Up, 0,
675
                                         GTK_MOVEMENT_DISPLAY_LINES, -1);
676
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_KP_Up, 0,
677
678
                                         GTK_MOVEMENT_DISPLAY_LINES, -1);

679
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_Down, 0,
680
                                         GTK_MOVEMENT_DISPLAY_LINES, 1);
681
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_KP_Down, 0,
682
683
                                         GTK_MOVEMENT_DISPLAY_LINES, 1);

684
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_p, GDK_CONTROL_MASK,
685
686
                                         GTK_MOVEMENT_DISPLAY_LINES, -1);

687
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_n, GDK_CONTROL_MASK,
688
689
                                         GTK_MOVEMENT_DISPLAY_LINES, 1);

690
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_Home, 0,
691
692
693
694
                                         GTK_MOVEMENT_BUFFER_ENDS, -1);
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KP_Home, 0,
                                         GTK_MOVEMENT_BUFFER_ENDS, -1);

695
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_End, 0,
696
                                         GTK_MOVEMENT_BUFFER_ENDS, 1);
697
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_KP_End, 0,
698
699
                                         GTK_MOVEMENT_BUFFER_ENDS, 1);

700
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_Right, 0,
701
                                         GTK_MOVEMENT_VISUAL_POSITIONS, 1);
702
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_Left, 0,
703
704
                                         GTK_MOVEMENT_VISUAL_POSITIONS, -1);

705
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_KP_Right, 0,
706
                                         GTK_MOVEMENT_VISUAL_POSITIONS, 1);
707
    xfdesktop_icon_view_add_move_binding(binding_set, GDK_KEY_KP_Left, 0,
708
709
                                         GTK_MOVEMENT_VISUAL_POSITIONS, -1);

710
    xfdesktop_cell_highlight_quark = g_quark_from_static_string("xfdesktop-icon-view-cell-highlight");
711
712
713
714
715
}

static void
xfdesktop_icon_view_init(XfdesktopIconView *icon_view)
{
716
717
718
    icon_view->priv = G_TYPE_INSTANCE_GET_PRIVATE(icon_view,
                                                  XFDESKTOP_TYPE_ICON_VIEW,
                                                  XfdesktopIconViewPrivate);
719
    
720
    icon_view->priv->icon_size = DEFAULT_ICON_SIZE;
721
    icon_view->priv->font_size = DEFAULT_FONT_SIZE;
722
723
724

    icon_view->priv->allow_rubber_banding = TRUE;
    icon_view->priv->selection_box_alpha = DEFAULT_RUBBERBAND_ALPHA;
725
726
727
728
    
    icon_view->priv->native_targets = gtk_target_list_new(icon_view_targets,
                                                          icon_view_n_targets);
    
729
730
    icon_view->priv->source_targets = gtk_target_list_new(icon_view_targets,
                                                          icon_view_n_targets);
731
732
733
734
    gtk_drag_source_set(GTK_WIDGET(icon_view), 0, NULL, 0, GDK_ACTION_MOVE);
    
    icon_view->priv->dest_targets = gtk_target_list_new(icon_view_targets,
                                                        icon_view_n_targets);
735
    gtk_drag_dest_set(GTK_WIDGET(icon_view), 0, NULL, 0, GDK_ACTION_MOVE);
736
    
737
738
739
    g_object_set(G_OBJECT(icon_view), "has-tooltip", TRUE, NULL);
    g_signal_connect(G_OBJECT(icon_view), "query-tooltip",
                     G_CALLBACK(xfdesktop_icon_view_show_tooltip), NULL);
740
    
741
    gtk_widget_set_has_window(GTK_WIDGET(icon_view), FALSE);
742
    gtk_widget_set_can_focus(GTK_WIDGET(icon_view), TRUE);
743
744
745
746
747
748
749
}

static void
xfdesktop_icon_view_finalize(GObject *obj)
{
    XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(obj);
    
750
    if(icon_view->priv->manager) {
751
        xfdesktop_icon_view_manager_fini(icon_view->priv->manager);
752
753
        g_object_unref(G_OBJECT(icon_view->priv->manager));
    }
754
    
755
    gtk_target_list_unref(icon_view->priv->native_targets);
756
    gtk_target_list_unref(icon_view->priv->source_targets);
757
    gtk_target_list_unref(icon_view->priv->dest_targets);
758
    
759
    g_list_foreach(icon_view->priv->pending_icons, (GFunc)g_object_unref, NULL);
760
    g_list_free(icon_view->priv->pending_icons);
761
    /* icon_view->priv->icons should be cleared in _unrealize() */
762

763
    if (icon_view->priv->channel)
764
        icon_view->priv->channel = NULL;
765

766
767
768
    G_OBJECT_CLASS(xfdesktop_icon_view_parent_class)->finalize(obj);
}

769
770
771
772
773
774
775
776
777
778
779
780
781
static void
xfce_icon_view_set_property(GObject *object,
                            guint property_id,
                            const GValue *value,
                            GParamSpec *pspec)
{
    XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(object);

    switch(property_id) {
        case PROP_SINGLE_CLICK:
            icon_view->priv->single_click = g_value_get_boolean (value);
            break;

782
783
784
785
786
        case PROP_SHOW_TOOLTIPS:
            icon_view->priv->show_tooltips = g_value_get_boolean(value);
            break;

        case PROP_TOOLTIP_SIZE:
787
            icon_view->priv->tooltip_size_from_xfconf = g_value_get_double(value);
788
789
            break;

790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
            break;
    }
}

static void
xfce_icon_view_get_property(GObject *object,
                           guint property_id,
                           GValue *value,
                           GParamSpec *pspec)
{
    XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(object);

    switch(property_id) {
        case PROP_SINGLE_CLICK:
            g_value_set_boolean(value, icon_view->priv->single_click);
            break;

809
810
811
812
813
        case PROP_SHOW_TOOLTIPS:
            g_value_set_boolean(value, icon_view->priv->show_tooltips);
            break;

        case PROP_TOOLTIP_SIZE:
814
            g_value_set_double(value, icon_view->priv->tooltip_size_from_xfconf);
815
816
            break;

817
818
819
820
821
822
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
            break;
    }
}

823
824
825
826
827
828
829
830
831
832
833
834
835
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,
836
                                 I_("move-cursor"), 2,
837
838
839
840
841
842
843
844
                                 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,
845
                                 I_("move-cursor"), 2,
846
847
848
849
                                 G_TYPE_ENUM, step,
                                 G_TYPE_INT, count);

    gtk_binding_entry_add_signal(binding_set, keyval, GDK_CONTROL_MASK,
850
                                 I_("move-cursor"), 2,
851
852
853
854
                                 G_TYPE_ENUM, step,
                                 G_TYPE_INT, count);
}

855
856
857
858
859
860
861
862
static gboolean
xfdesktop_icon_view_get_single_click(XfdesktopIconView *icon_view)
{
    g_return_val_if_fail(XFDESKTOP_IS_ICON_VIEW(icon_view), FALSE);

    return icon_view->priv->single_click;
}

863
864
static gboolean
xfdesktop_icon_view_button_press(GtkWidget *widget,
865
866
                                 GdkEventButton *evt,
                                 gpointer user_data)
867
{
868
    XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(user_data);
869
    XfdesktopIcon *icon;
870
871
872

    TRACE("entering");

873
    if(evt->type == GDK_BUTTON_PRESS) {
874
        GList *icon_l;
875
876
877
878
879
880
881
882
883
884
885
886
887
888

        /* Let xfce-desktop handle button 2 */
        if(evt->button == 2) {
            /* If we had the grab release it so the desktop gets the event */
            if(gtk_widget_has_grab(widget))
                gtk_grab_remove(widget);

            return FALSE;
        }

        /* Grab the focus, release on button release */
        if(!gtk_widget_has_grab(widget))
            gtk_grab_add(widget);

889
890
        icon_l = g_list_find_custom(icon_view->priv->icons, evt,
                                    (GCompareFunc)xfdesktop_check_icon_clicked);
891
        if(icon_l && (icon = icon_l->data)) {
892
            if(xfdesktop_icon_view_is_icon_selected(icon_view, icon)) {
893
894
                /* clicked an already-selected icon */
                
895
896
                if(evt->state & GDK_CONTROL_MASK)
                    icon_view->priv->control_click = TRUE;
Brian Tarricone's avatar
Brian Tarricone committed
897
898

                icon_view->priv->cursor = icon;
899
            } else {
900
901
                /* clicked a non-selected icon */
                if(icon_view->priv->sel_mode != GTK_SELECTION_MULTIPLE
902
                   || !(evt->state & GDK_CONTROL_MASK))
903
                {
904
905
906
                    /* unselect all of the other icons if we haven't held
                     * down the ctrl key.  we'll handle shift in the next block,
                     * but for shift we do need to unselect everything */
Brian Tarricone's avatar
Brian Tarricone committed
907
                    xfdesktop_icon_view_unselect_all(icon_view);
908
909
910
                    
                    if(!(evt->state & GDK_SHIFT_MASK))
                        icon_view->priv->first_clicked_item = NULL;
911
912
                }
                
913
                icon_view->priv->cursor = icon;
914
                
915
916
917
918
919
920
921
922
                if(!icon_view->priv->first_clicked_item)
                    icon_view->priv->first_clicked_item = icon;
                
                if(icon_view->priv->sel_mode == GTK_SELECTION_MULTIPLE
                   && evt->state & GDK_SHIFT_MASK
                   && icon_view->priv->first_clicked_item
                   && icon_view->priv->first_clicked_item != icon)
                {
Brian Tarricone's avatar
Brian Tarricone committed
923
924
925
926
927
                    xfdesktop_icon_view_select_between(icon_view,
                                                       icon_view->priv->first_clicked_item,
                                                       icon);
                } else
                    xfdesktop_icon_view_select_item(icon_view, icon);
928
            }
929
            
Eric Koegel's avatar
Eric Koegel committed
930
            if(evt->button == 1 || evt->button == 3) {
931
932
933
934
                /* we might be the start of a drag */
                DBG("setting stuff");
                icon_view->priv->maybe_begin_drag = TRUE;
                icon_view->priv->definitely_dragging = FALSE;
935
                icon_view->priv->definitely_rubber_banding = FALSE;
936
937
938
                icon_view->priv->press_start_x = evt->x;
                icon_view->priv->press_start_y = evt->y;
            }
939
940
            
            return TRUE;
941
        } else {
942
            /* Button press wasn't over any icons */
943
944
            /* unselect previously selected icons if we didn't click one */
            if(icon_view->priv->sel_mode != GTK_SELECTION_MULTIPLE
945
946
               || !(evt->state & GDK_CONTROL_MASK))
            {
Brian Tarricone's avatar
Brian Tarricone committed
947
                xfdesktop_icon_view_unselect_all(icon_view);
948
            }
949
            
950
            icon_view->priv->cursor = NULL;
951
            icon_view->priv->first_clicked_item = NULL;
952

953
954
955
            if(icon_view->priv->allow_rubber_banding && evt->button == 1
               && !(evt->state & GDK_SHIFT_MASK))
            {
956
957
958
959
960
                icon_view->priv->maybe_begin_drag = TRUE;
                icon_view->priv->definitely_dragging = FALSE;
                icon_view->priv->press_start_x = evt->x;
                icon_view->priv->press_start_y = evt->y;
            }
961
962
963
964
965
966
967

            /* Since we're not over any icons this won't be the start of a
             * drag so we can pop up menu */
            if(evt->button == 3 || (evt->button == 1 && (evt->state & GDK_SHIFT_MASK))) {
                xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), evt->button, evt->time);
                return TRUE;
            }
968
        }
969
    } else if(evt->type == GDK_2BUTTON_PRESS) {
970
971
972
973
974
975
976
        /* filter this event in single click mode */
        if(xfdesktop_icon_view_get_single_click(icon_view)) {
            icon_view->priv->double_click = TRUE;
            xfdesktop_icon_view_unselect_all(icon_view);
            return TRUE;
        }

977
        /* be sure to cancel any pending drags that might have snuck through.
978
         * this shouldn't happen, but it does sometimes (bug 3426).  */
979
        icon_view->priv->maybe_begin_drag = FALSE;
980
        icon_view->priv->definitely_dragging = FALSE;
981
        icon_view->priv->definitely_rubber_banding = FALSE;
982
        
983
984
985
986
        if(evt->button == 1) {
            GList *icon_l = g_list_find_custom(icon_view->priv->icons, evt,
                                               (GCompareFunc)xfdesktop_check_icon_clicked);
            if(icon_l && (icon = icon_l->data)) {
987
                icon_view->priv->cursor = icon;
988
989
990
                g_signal_emit(G_OBJECT(icon_view), __signals[SIG_ICON_ACTIVATED],
                              0, NULL);
                xfdesktop_icon_activated(icon);
991
992
                //xfdesktop_icon_view_unselect_item(icon_view, icon);
                xfdesktop_icon_view_unselect_all(icon_view);
993
            }
994
        }
995
996
        
        return TRUE;
997
998
999
1000
1001
    }
    
    return FALSE;
}

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
static gint
xfdesktop_icon_view_get_tooltip_size(XfdesktopIconView *icon_view)
{
    g_return_val_if_fail(XFDESKTOP_IS_ICON_VIEW(icon_view), DEFAULT_TOOLTIP_SIZE);

    /* Check if we're showing tooltips at all */
    if(!icon_view->priv->show_tooltips)
        return 0;

    /* If the xfconf size is set and sane, use it */
1012
1013
    if(icon_view->priv->tooltip_size_from_xfconf >= 0)
        return icon_view->priv->tooltip_size_from_xfconf;
1014
1015
1016
1017
1018
1019
1020
1021
1022

    /* if the style size is set and sane, use it */
    if(icon_view->priv->tooltip_size_from_style >= 0)
        return icon_view->priv->tooltip_size_from_style;

    /* Fall back */
    return DEFAULT_TOOLTIP_SIZE;
}

1023
1024
static gboolean
xfdesktop_icon_view_button_release(GtkWidget *widget,
1025
1026
                                   GdkEventButton *evt,
                                   gpointer user_data)
1027
{
1028
    XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(user_data);
1029
1030
1031
    XfdesktopIcon *icon;
    GList *icon_l = NULL;

1032
    TRACE("entering btn=%d", evt->button);
Eric Koegel's avatar
Eric Koegel committed
1033

1034
1035
1036
1037
1038
1039
    /* single-click */
    if(xfdesktop_icon_view_get_single_click(icon_view)
       && evt->button == 1
       && !(evt->state & GDK_SHIFT_MASK)
       && !(evt->state & GDK_CONTROL_MASK)
       && !icon_view->priv->definitely_dragging
1040
1041
       && !icon_view->priv->definitely_rubber_banding
       && !icon_view->priv->double_click) {
1042
1043
1044
        /* Find out if we clicked on an icon */
        icon_l = g_list_find_custom(icon_view->priv->icons, evt,
                                    (GCompareFunc)xfdesktop_check_icon_clicked);
1045
        if(icon_l && (icon = icon_l->data)) {
1046
            /* We did, activate it */
1047
1048
1049
1050
            icon_view->priv->cursor = icon;
            g_signal_emit(G_OBJECT(icon_view), __signals[SIG_ICON_ACTIVATED],
                          0, NULL);
            xfdesktop_icon_activated(icon);
1051
            xfdesktop_icon_view_unselect_item(icon_view, icon);
1052
1053
1054
        }
    }

Eric Koegel's avatar
Eric Koegel committed
1055
1056
1057
1058
    if((evt->button == 3 || (evt->button == 1 && (evt->state & GDK_SHIFT_MASK))) &&
       icon_view->priv->definitely_dragging == FALSE &&
       icon_view->priv->definitely_rubber_banding == FALSE)
    {
1059
1060
1061
1062
1063
1064
1065
1066
1067
        /* If we're in single click mode we may already have the icon, don't
         * find it again. */
        if(icon_l == NULL) {
            icon_l = g_list_find_custom(icon_view->priv->icons, evt,
                                        (GCompareFunc)xfdesktop_check_icon_clicked);
        }

        /* If we clicked an icon then we didn't pop up the menu during the
         * button press in order to support right click DND, pop up the menu
1068
1069
1070
         * now.
         * We pass 0 as the button because the docs say that you must use 0
         * for pop ups other than button press events. */
1071
        if(icon_l && (icon = icon_l->data))
1072
            xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), 0, evt->time);
Eric Koegel's avatar
Eric Koegel committed
1073
    }
Eric Koegel's avatar
Eric Koegel committed
1074

1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
    if(evt->button == 1 && evt->state & GDK_CONTROL_MASK
       && icon_view->priv->control_click)
    {
        icon_l = g_list_find_custom(icon_view->priv->icons, evt,
                                    (GCompareFunc)xfdesktop_check_icon_clicked);
        if(icon_l && (icon = icon_l->data)) {
            if(xfdesktop_icon_view_is_icon_selected(icon_view, icon)) {
                /* clicked an already-selected icon */

                /* unselect */
                xfdesktop_icon_view_unselect_item(icon_view, icon);
            }
        }
    }

Eric Koegel's avatar
Eric Koegel committed
1090
    if(evt->button == 1 || evt->button == 3) {
1091
        DBG("unsetting stuff");
1092
        icon_view->priv->control_click = FALSE;
1093
        icon_view->priv->double_click = FALSE;
1094
        icon_view->priv->maybe_begin_drag = FALSE;
1095
        icon_view->priv->definitely_dragging = FALSE;
1096
        if(icon_view->priv->definitely_rubber_banding) {
1097
            /* Remove the rubber band selection box */
1098
1099
1100
1101
1102
1103
            icon_view->priv->definitely_rubber_banding = FALSE;
            gtk_widget_queue_draw_area(widget, icon_view->priv->band_rect.x,
                                       icon_view->priv->band_rect.y,
                                       icon_view->priv->band_rect.width,
                                       icon_view->priv->band_rect.height);
        }