~ubuntu-branches/ubuntu/precise/xfce4-panel/precise

« back to all changes in this revision

Viewing changes to panel/panel.c

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Le Folgoc
  • Date: 2010-12-04 15:45:53 UTC
  • mto: (4.1.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 50.
  • Revision ID: james.westby@ubuntu.com-20101204154553-f452gq02eiksf09f
Tags: upstream-4.7.5
ImportĀ upstreamĀ versionĀ 4.7.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  $Id$
2
 
 *
3
 
 *  Copyright (c) 2005 Jasper Huijsmans <jasper@xfce.org>
4
 
 *
5
 
 *  This program is free software; you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published
7
 
 *  by the Free Software Foundation; either version 2 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU Library General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
 */
19
 
 
20
 
#ifdef HAVE_CONFIG_H
21
 
#include <config.h>
22
 
#endif
23
 
 
24
 
#include <string.h>
25
 
#include <time.h>
26
 
#include <gtk/gtk.h>
27
 
 
28
 
#include <libxfcegui4/libxfcegui4.h>
29
 
#include <libxfce4panel/xfce-panel-window.h>
30
 
#include <libxfce4panel/xfce-itembar.h>
31
 
#include <libxfce4panel/xfce-panel-item-iface.h>
32
 
 
33
 
#include <libxfce4panel/libxfce4panel-enum-types.h>
34
 
#include <libxfce4panel/xfce-panel-convenience.h>
35
 
#include <libxfce4panel/xfce-panel-macros.h>
36
 
 
37
 
#include "panel.h"
38
 
#include "panel-app.h"
39
 
#include "panel-properties.h"
40
 
#include "panel-item-manager.h"
41
 
#include "panel-dnd.h"
42
 
 
43
 
/* PanelPrivate struct */
44
 
#include "panel-private.h"
45
 
 
46
 
#ifndef _
47
 
#define _(x) x
48
 
#endif
49
 
 
50
 
enum
51
 
{
52
 
    PROP_0,
53
 
    PROP_SIZE,
54
 
    PROP_MONITOR,
55
 
    PROP_SCREEN_POSITION,
56
 
    PROP_XOFFSET,
57
 
    PROP_YOFFSET,
58
 
    PROP_AUTOHIDE,
59
 
    PROP_FULL_WIDTH,
60
 
    PROP_TRANSPARENCY,
61
 
    PROP_ACTIVE_TRANS
62
 
};
63
 
 
64
 
 
65
 
/* GObject */
66
 
static void panel_finalize     (GObject * object);
67
 
 
68
 
static void panel_get_property (GObject    *object,
69
 
                                guint       prop_id,
70
 
                                GValue     *value,
71
 
                                GParamSpec *pspec);
72
 
 
73
 
static void panel_set_property (GObject      *object,
74
 
                                guint         prop_id,
75
 
                                const GValue *value,
76
 
                                GParamSpec   *pspec);
77
 
 
78
 
/* GtkWidget */
79
 
static void panel_size_request  (GtkWidget      *widget,
80
 
                                 GtkRequisition *requisition);
81
 
 
82
 
static gboolean panel_button_pressed (GtkWidget      *widget,
83
 
                                      GdkEventButton *ev);
84
 
 
85
 
/* plugin menu */
86
 
static void panel_menu_deactivated (GtkWidget *item);
87
 
 
88
 
static void panel_menu_opened (GtkWidget *item);
89
 
static void _item_start_move (GtkWidget *item, Panel     *panel);
90
 
 
91
 
/* DND dest */
92
 
static void _panel_drag_data_received (GtkWidget        *widget,
93
 
                                       GdkDragContext   *context,
94
 
                                       gint              x,
95
 
                                       gint              y,
96
 
                                       GtkSelectionData *data,
97
 
                                       guint             info,
98
 
                                       guint             time_,
99
 
                                       Panel            *panel);
100
 
 
101
 
static gboolean _panel_drag_drop (GtkWidget      *widget,
102
 
                                  GdkDragContext *context,
103
 
                                  gint            x,
104
 
                                  gint            y,
105
 
                                  guint           time_,
106
 
                                  Panel          *panel);
107
 
 
108
 
/* DND source */
109
 
static void _panel_drag_begin (GtkWidget      *widget,
110
 
                               GdkDragContext *drag_context,
111
 
                               Panel          *panel);
112
 
 
113
 
/* pass through button press events */
114
 
static gboolean _panel_itembar_button_pressed (GtkWidget      *widget,
115
 
                                               GdkEventButton *ev,
116
 
                                               Panel          *panel);
117
 
 
118
 
/* menu */
119
 
static GtkWidget *_panel_create_menu (Panel *panel);
120
 
 
121
 
 
122
 
/* this sets up a lot of stuff, see GObject API reference */
123
 
G_DEFINE_TYPE (Panel, panel, XFCE_TYPE_PANEL_WINDOW);
124
 
 
125
 
static void
126
 
panel_class_init (PanelClass * klass)
127
 
{
128
 
    GObjectClass   *object_class;
129
 
    GtkWidgetClass *widget_class;
130
 
    GParamSpec     *pspec;
131
 
 
132
 
    g_type_class_add_private (klass, sizeof (PanelPrivate));
133
 
 
134
 
    object_class = (GObjectClass *) klass;
135
 
    widget_class = (GtkWidgetClass *) klass;
136
 
 
137
 
    object_class->finalize           = panel_finalize;
138
 
    object_class->get_property       = panel_get_property;
139
 
    object_class->set_property       = panel_set_property;
140
 
 
141
 
    widget_class->button_press_event = panel_button_pressed;
142
 
    widget_class->size_request       = panel_size_request;
143
 
 
144
 
    /* properties */
145
 
 
146
 
    pspec = g_param_spec_int ("size",
147
 
                              "Size",
148
 
                              "The size of the panel",
149
 
                              MIN_SIZE, MAX_SIZE,
150
 
                              DEFAULT_SIZE, G_PARAM_READWRITE);
151
 
 
152
 
    g_object_class_install_property (object_class, PROP_SIZE, pspec);
153
 
 
154
 
    pspec = g_param_spec_int ("monitor",
155
 
                              "Monitor",
156
 
                              "The monitor number of the panel",
157
 
                              0, G_MAXINT,
158
 
                              DEFAULT_MONITOR, G_PARAM_READWRITE);
159
 
 
160
 
    g_object_class_install_property (object_class, PROP_MONITOR, pspec);
161
 
 
162
 
    pspec = g_param_spec_enum ("screen-position",
163
 
                               "Screen position",
164
 
                               "The screen position of the panel",
165
 
                               XFCE_TYPE_SCREEN_POSITION,
166
 
                               DEFAULT_SCREEN_POSITION, G_PARAM_READWRITE);
167
 
 
168
 
    g_object_class_install_property (object_class, PROP_SCREEN_POSITION,
169
 
                                     pspec);
170
 
 
171
 
    pspec = g_param_spec_int ("xoffset",
172
 
                              "Offset in x direction",
173
 
                              "Offset in x direction",
174
 
                              0, G_MAXINT,
175
 
                              DEFAULT_XOFFSET, G_PARAM_READWRITE);
176
 
 
177
 
    g_object_class_install_property (object_class, PROP_XOFFSET, pspec);
178
 
 
179
 
    pspec = g_param_spec_int ("yoffset",
180
 
                              "Offset in y direction",
181
 
                              "Offset in y direction",
182
 
                              0, G_MAXINT,
183
 
                              DEFAULT_YOFFSET, G_PARAM_READWRITE);
184
 
 
185
 
    g_object_class_install_property (object_class, PROP_YOFFSET, pspec);
186
 
 
187
 
    pspec = g_param_spec_boolean ("autohide",
188
 
                                  "panel_autohide",
189
 
                                  "Automatically hide the panel",
190
 
                                  DEFAULT_AUTOHIDE, G_PARAM_READWRITE);
191
 
 
192
 
    g_object_class_install_property (object_class, PROP_AUTOHIDE, pspec);
193
 
 
194
 
    pspec = g_param_spec_int ("fullwidth",
195
 
                              "panel_fullwidth",
196
 
                              "Use the full screen width",
197
 
                              XFCE_PANEL_NORMAL_WIDTH,
198
 
                              XFCE_PANEL_SPAN_MONITORS,
199
 
                              DEFAULT_FULL_WIDTH, G_PARAM_READWRITE);
200
 
 
201
 
    g_object_class_install_property (object_class, PROP_FULL_WIDTH, pspec);
202
 
 
203
 
    pspec = g_param_spec_int ("transparency",
204
 
                              "panel_transparency",
205
 
                              "Transparency of the panel",
206
 
                              0, 100,
207
 
                              DEFAULT_TRANSPARENCY, G_PARAM_READWRITE);
208
 
 
209
 
    g_object_class_install_property (object_class, PROP_TRANSPARENCY, pspec);
210
 
 
211
 
    pspec = g_param_spec_boolean ("activetrans",
212
 
                                  "panel_activetrans",
213
 
                                  "Keep the active panel transparent",
214
 
                                  DEFAULT_ACTIVE_TRANS, G_PARAM_READWRITE);
215
 
 
216
 
    g_object_class_install_property (object_class, PROP_ACTIVE_TRANS, pspec);
217
 
}
218
 
 
219
 
static void
220
 
panel_init (Panel * panel)
221
 
{
222
 
    PanelPrivate *priv;
223
 
 
224
 
    priv = panel->priv    = G_TYPE_INSTANCE_GET_PRIVATE (panel,
225
 
                                                         PANEL_TYPE_PANEL,
226
 
                                                         PanelPrivate);
227
 
 
228
 
    priv->size            = DEFAULT_SIZE;
229
 
    priv->monitor         = DEFAULT_MONITOR;
230
 
    priv->screen_position = DEFAULT_SCREEN_POSITION;
231
 
    priv->xoffset         = DEFAULT_XOFFSET;
232
 
    priv->yoffset         = DEFAULT_YOFFSET;
233
 
    priv->autohide        = DEFAULT_AUTOHIDE;
234
 
    priv->full_width      = DEFAULT_FULL_WIDTH;
235
 
    priv->transparency    = DEFAULT_TRANSPARENCY;
236
 
    priv->activetrans     = DEFAULT_ACTIVE_TRANS;
237
 
 
238
 
    priv->itembar = xfce_itembar_new (GTK_ORIENTATION_HORIZONTAL);
239
 
    gtk_widget_show (priv->itembar);
240
 
    gtk_container_add (GTK_CONTAINER (panel), priv->itembar);
241
 
 
242
 
    panel_dnd_set_dest_name_and_widget (priv->itembar);
243
 
    panel_dnd_set_source_widget (priv->itembar);
244
 
 
245
 
    /* don't allow the wm to close the panel window */
246
 
    g_signal_connect (panel, "delete-event", G_CALLBACK (gtk_true), NULL);
247
 
 
248
 
    /* DND */
249
 
    g_signal_connect (priv->itembar, "drag-data-received",
250
 
                      G_CALLBACK (_panel_drag_data_received), panel);
251
 
 
252
 
    g_signal_connect (priv->itembar, "drag-drop",
253
 
                      G_CALLBACK (_panel_drag_drop), panel);
254
 
 
255
 
    g_signal_connect (priv->itembar, "drag-begin",
256
 
                      G_CALLBACK (_panel_drag_begin), panel);
257
 
 
258
 
    /* mouse click */
259
 
    g_signal_connect (priv->itembar, "button-press-event",
260
 
                      G_CALLBACK (_panel_itembar_button_pressed), panel);
261
 
 
262
 
    /* menu */
263
 
    priv->menu = _panel_create_menu (PANEL (panel));
264
 
 
265
 
    priv->opacity = priv->saved_opacity = 0;
266
 
}
267
 
 
268
 
static void
269
 
panel_finalize (GObject * object)
270
 
{
271
 
    /* TODO: properly ref and unref private widgets  */
272
 
 
273
 
    G_OBJECT_CLASS (panel_parent_class)->finalize (object);
274
 
}
275
 
 
276
 
static void
277
 
panel_get_property (GObject    *object,
278
 
                    guint       prop_id,
279
 
                    GValue     *value,
280
 
                    GParamSpec *pspec)
281
 
{
282
 
    PanelPrivate *priv = PANEL(object)->priv;
283
 
 
284
 
    switch (prop_id)
285
 
    {
286
 
        case PROP_SIZE:
287
 
            g_value_set_int (value, priv->size);
288
 
            break;
289
 
        case PROP_MONITOR:
290
 
            g_value_set_int (value, priv->monitor);
291
 
            break;
292
 
        case PROP_SCREEN_POSITION:
293
 
            g_value_set_enum (value, priv->screen_position);
294
 
            break;
295
 
        case PROP_XOFFSET:
296
 
            g_value_set_int (value, priv->xoffset);
297
 
            break;
298
 
        case PROP_YOFFSET:
299
 
            g_value_set_int (value, priv->yoffset);
300
 
            break;
301
 
        case PROP_AUTOHIDE:
302
 
            g_value_set_boolean (value, priv->autohide);
303
 
            break;
304
 
        case PROP_FULL_WIDTH:
305
 
            g_value_set_int (value, priv->full_width);
306
 
            break;
307
 
        case PROP_TRANSPARENCY:
308
 
            g_value_set_int (value, priv->transparency);
309
 
            break;
310
 
        case PROP_ACTIVE_TRANS:
311
 
            g_value_set_boolean (value, priv->activetrans);
312
 
            break;
313
 
        default:
314
 
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
315
 
            break;
316
 
    }
317
 
}
318
 
 
319
 
static void
320
 
panel_set_property (GObject      *object,
321
 
                    guint         prop_id,
322
 
                    const GValue *value,
323
 
                    GParamSpec   *pspec)
324
 
{
325
 
    Panel *panel = PANEL (object);
326
 
 
327
 
    switch (prop_id)
328
 
    {
329
 
        case PROP_SIZE:
330
 
            panel_set_size (panel, g_value_get_int (value));
331
 
            break;
332
 
        case PROP_MONITOR:
333
 
            panel_set_monitor (panel, g_value_get_int (value));
334
 
            break;
335
 
        case PROP_SCREEN_POSITION:
336
 
            panel_set_screen_position (panel, g_value_get_enum (value));
337
 
            break;
338
 
        case PROP_XOFFSET:
339
 
            panel_set_xoffset (panel, g_value_get_int (value));
340
 
            break;
341
 
        case PROP_YOFFSET:
342
 
            panel_set_yoffset (panel, g_value_get_int (value));
343
 
            break;
344
 
        case PROP_AUTOHIDE:
345
 
            panel_set_autohide (panel, g_value_get_boolean (value));
346
 
            break;
347
 
        case PROP_FULL_WIDTH:
348
 
            panel_set_full_width (panel, g_value_get_int (value));
349
 
            break;
350
 
        case PROP_TRANSPARENCY:
351
 
            panel_set_transparency (panel, g_value_get_int (value));
352
 
            break;
353
 
        case PROP_ACTIVE_TRANS:
354
 
            panel_set_activetrans (panel, g_value_get_boolean (value));
355
 
            break;
356
 
        default:
357
 
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
358
 
            break;
359
 
    }
360
 
}
361
 
 
362
 
static void
363
 
panel_size_request  (GtkWidget      *widget,
364
 
                     GtkRequisition *requisition)
365
 
{
366
 
    PanelPrivate *priv = PANEL(widget)->priv;
367
 
 
368
 
    GTK_WIDGET_CLASS (panel_parent_class)->size_request (widget, requisition);
369
 
 
370
 
    if (panel_is_horizontal (PANEL (widget)))
371
 
    {
372
 
        requisition->width  = MAX (MIN_SIZE,   requisition->width);
373
 
        requisition->height = MAX (priv->size, requisition->height);
374
 
    }
375
 
    else
376
 
    {
377
 
        requisition->width  = MAX (priv->size, requisition->width);
378
 
        requisition->height = MAX (MIN_SIZE,   requisition->height);
379
 
    }
380
 
}
381
 
 
382
 
static gboolean
383
 
panel_button_pressed (GtkWidget      *widget,
384
 
                      GdkEventButton *ev)
385
 
{
386
 
    guint modifiers;
387
 
 
388
 
    modifiers = gtk_accelerator_get_default_mod_mask ();
389
 
 
390
 
    if (ev->button == 3 || (ev->button == 1 &&
391
 
        (ev->state & modifiers) == GDK_CONTROL_MASK))
392
 
    {
393
 
        PanelPrivate *priv;
394
 
 
395
 
        priv = PANEL (widget)->priv;
396
 
 
397
 
        gtk_menu_set_screen (GTK_MENU (priv->menu),
398
 
                             gtk_widget_get_screen (widget));
399
 
 
400
 
        gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, NULL, NULL,
401
 
                        ev->button, ev->time);
402
 
 
403
 
        return TRUE;
404
 
    }
405
 
 
406
 
    return
407
 
        GTK_WIDGET_CLASS (panel_parent_class)->button_press_event (widget, ev);
408
 
}
409
 
 
410
 
/* DND dest */
411
 
static void
412
 
_panel_drag_data_received (GtkWidget        *widget,
413
 
                           GdkDragContext   *context,
414
 
                           gint              x,
415
 
                           gint              y,
416
 
                           GtkSelectionData *data,
417
 
                           guint             info,
418
 
                           guint             time_,
419
 
                           Panel            *panel)
420
 
{
421
 
    XfceItembar   *itembar = XFCE_ITEMBAR (widget);
422
 
    PanelPrivate  *priv = panel->priv;
423
 
    XfcePanelItem *item;
424
 
    GtkWidget     *plugin;
425
 
    gint           index_;
426
 
    gint           oldindex;
427
 
    gboolean       expand;
428
 
    gboolean       succeed = FALSE;
429
 
 
430
 
    DBG (" + drag data received: %d", info);
431
 
 
432
 
    /* get the drop index */
433
 
    index_ = xfce_itembar_get_drop_index (itembar, x, y);
434
 
 
435
 
    switch (info)
436
 
    {
437
 
        case TARGET_PLUGIN_NAME:
438
 
            if (data->length > 0)
439
 
            {
440
 
                /* insert the new plugin */
441
 
                panel_insert_item (panel, (const gchar *) data->data, index_);
442
 
 
443
 
                /* succeeded */
444
 
                succeed = TRUE;
445
 
            }
446
 
            break;
447
 
 
448
 
        case TARGET_PLUGIN_WIDGET:
449
 
            /* get the plugin from the drag context */
450
 
            plugin = gtk_drag_get_source_widget (context);
451
 
 
452
 
            /* try the drag_widget or leave */
453
 
            if (!plugin || !XFCE_IS_PANEL_ITEM (plugin))
454
 
                break;
455
 
 
456
 
            if (gtk_widget_get_parent (plugin) != widget)
457
 
            {
458
 
                /* get the plugin and information */
459
 
                item   = XFCE_PANEL_ITEM (plugin);
460
 
                expand = xfce_panel_item_get_expand (item);
461
 
 
462
 
                /* freeze plugin notifications */
463
 
                g_object_freeze_notify (G_OBJECT (widget));
464
 
 
465
 
                /* move the plugin from the old panel to the new one */
466
 
                gtk_widget_reparent (GTK_WIDGET (plugin), widget);
467
 
 
468
 
                /* update the plugin */
469
 
                xfce_panel_item_set_size (item, priv->size);
470
 
                xfce_panel_item_set_screen_position (item, priv->screen_position);
471
 
 
472
 
                /* update the itembar */
473
 
                xfce_itembar_reorder_child (itembar, plugin, index_);
474
 
                xfce_itembar_set_child_expand (itembar, plugin, expand);
475
 
 
476
 
                /* thaw update notifications */
477
 
                g_object_thaw_notify (G_OBJECT (widget));
478
 
            }
479
 
            else /* move on same panel */
480
 
            {
481
 
                /* get the old index */
482
 
                oldindex = xfce_itembar_get_item_index (itembar, plugin);
483
 
 
484
 
                if (index_ > oldindex)
485
 
                    index_--;
486
 
 
487
 
                if (index_ != oldindex)
488
 
                    xfce_itembar_reorder_child (itembar, plugin, index_);
489
 
            }
490
 
 
491
 
            /* properly handled */
492
 
            succeed = TRUE;
493
 
 
494
 
            break;
495
 
 
496
 
        default:
497
 
            break;
498
 
    }
499
 
 
500
 
    /* finish the drag */
501
 
    gtk_drag_finish (context, succeed, FALSE, time_);
502
 
}
503
 
 
504
 
static gboolean
505
 
_panel_drag_drop (GtkWidget      *widget,
506
 
                  GdkDragContext *context,
507
 
                  gint            x,
508
 
                  gint            y,
509
 
                  guint           time_,
510
 
                  Panel          *panel)
511
 
{
512
 
    GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
513
 
 
514
 
    /* we cannot handle the drag data */
515
 
    if (G_UNLIKELY (target == GDK_NONE))
516
 
        return FALSE;
517
 
 
518
 
    /* request the drag data */
519
 
    gtk_drag_get_data (widget, context, target, time_);
520
 
 
521
 
    /* we call gtk_drag_finish later */
522
 
    return TRUE;
523
 
}
524
 
 
525
 
/* DND source */
526
 
static void
527
 
_panel_drag_begin (GtkWidget      *widget,
528
 
                   GdkDragContext *drag_context,
529
 
                   Panel          *panel)
530
 
{
531
 
    gint         x, y, rootx, rooty;
532
 
    GtkWidget   *plugin;
533
 
 
534
 
    DBG (" + drag begin");
535
 
 
536
 
    /* get the pointer position */
537
 
    gdk_display_get_pointer (gtk_widget_get_display (widget), NULL, &x, &y, NULL);
538
 
 
539
 
    /* get the window root coordinates */
540
 
    gdk_window_get_root_origin (widget->window, &rootx, &rooty);
541
 
 
542
 
    /* calc the position inside the panel */
543
 
    x -= rootx;
544
 
    y -= rooty;
545
 
 
546
 
    /* get the plugin on the itembar at this position */
547
 
    plugin = xfce_itembar_get_item_at_point (XFCE_ITEMBAR (widget), x, y);
548
 
 
549
 
    /* start an item move */
550
 
    if (G_LIKELY (plugin))
551
 
        _item_start_move (plugin, panel);
552
 
}
553
 
 
554
 
/* pass through right-click events when the event window of itembar is raised
555
 
 */
556
 
static gboolean
557
 
_panel_itembar_button_pressed (GtkWidget      *widget,
558
 
                               GdkEventButton *ev,
559
 
                               Panel          *panel)
560
 
{
561
 
    GtkWidget *plugin;
562
 
    guint      modifiers;
563
 
 
564
 
    if (xfce_itembar_event_window_is_raised (XFCE_ITEMBAR (widget)))
565
 
    {
566
 
        modifiers = gtk_accelerator_get_default_mod_mask ();
567
 
 
568
 
        if (ev->button == 3 || (ev->button == 1 &&
569
 
            (ev->state & modifiers) == GDK_CONTROL_MASK))
570
 
        {
571
 
            plugin = xfce_itembar_get_item_at_point (XFCE_ITEMBAR (widget),
572
 
                                                     ev->x, ev->y);
573
 
            if (plugin)
574
 
            {
575
 
                gtk_widget_event (plugin, (GdkEvent *)ev);
576
 
                return TRUE;
577
 
            }
578
 
        }
579
 
    }
580
 
 
581
 
    return FALSE;
582
 
}
583
 
 
584
 
/* menu */
585
 
 
586
 
static GtkWidget *
587
 
_panel_create_menu (Panel *panel)
588
 
{
589
 
    GtkWidget *menu, *mi, *img;
590
 
 
591
 
    menu = gtk_menu_new ();
592
 
 
593
 
    if (xfce_allow_panel_customization ())
594
 
    {
595
 
        mi = gtk_image_menu_item_new_with_label (_("Customize Panel..."));
596
 
        gtk_widget_show (mi);
597
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
598
 
 
599
 
        img = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
600
 
        gtk_widget_show (img);
601
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
602
 
 
603
 
        g_signal_connect (mi, "activate", G_CALLBACK (panel_app_customize),
604
 
                          NULL);
605
 
 
606
 
        mi = gtk_image_menu_item_new_with_label (_("Add New Items..."));
607
 
        gtk_widget_show (mi);
608
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
609
 
 
610
 
        img = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
611
 
        gtk_widget_show (img);
612
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
613
 
 
614
 
        g_signal_connect_swapped (mi, "activate",
615
 
                                  G_CALLBACK (panel_app_customize_items), NULL);
616
 
 
617
 
        mi = gtk_separator_menu_item_new ();
618
 
        gtk_widget_show (mi);
619
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
620
 
 
621
 
        mi = gtk_image_menu_item_new_with_label (_("Quit"));
622
 
        gtk_widget_show (mi);
623
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
624
 
 
625
 
        img = gtk_image_new_from_stock (GTK_STOCK_QUIT, GTK_ICON_SIZE_MENU);
626
 
        gtk_widget_show (img);
627
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
628
 
 
629
 
        g_signal_connect (mi, "activate", G_CALLBACK (panel_app_quit), NULL);
630
 
 
631
 
        mi = gtk_image_menu_item_new_with_label (_("Restart"));
632
 
        gtk_widget_show (mi);
633
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
634
 
 
635
 
        img = gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU);
636
 
        gtk_widget_show (img);
637
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
638
 
 
639
 
        g_signal_connect (mi, "activate", G_CALLBACK (panel_app_restart), NULL);
640
 
 
641
 
        mi = gtk_separator_menu_item_new ();
642
 
        gtk_widget_show (mi);
643
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
644
 
    }
645
 
 
646
 
    mi = gtk_image_menu_item_new_with_label (_("About the Xfce Panel"));
647
 
    gtk_widget_show (mi);
648
 
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
649
 
 
650
 
    img = gtk_image_new_from_stock (GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU);
651
 
    gtk_widget_show (img);
652
 
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
653
 
 
654
 
    g_signal_connect_swapped (mi, "activate", G_CALLBACK (panel_app_about),
655
 
                              panel);
656
 
 
657
 
    return menu;
658
 
}
659
 
 
660
 
/* public API */
661
 
 
662
 
Panel *
663
 
panel_new (void)
664
 
{
665
 
    return PANEL (g_object_new (PANEL_TYPE_PANEL, NULL));
666
 
}
667
 
 
668
 
void
669
 
panel_free_data (Panel *panel)
670
 
{
671
 
    PanelPrivate *priv;
672
 
    GList        *l;
673
 
    int           i;
674
 
 
675
 
    _panel_return_if_fail (PANEL_IS_PANEL (panel));
676
 
 
677
 
    priv = panel->priv;
678
 
 
679
 
    /* try and prevent some race conditions */
680
 
    priv->block_autohide++;
681
 
    xfce_panel_window_set_move_function (XFCE_PANEL_WINDOW (panel),
682
 
                                         NULL, NULL);
683
 
    xfce_panel_window_set_resize_function (XFCE_PANEL_WINDOW (panel),
684
 
                                           NULL, NULL);
685
 
 
686
 
    for (l = gtk_container_get_children (GTK_CONTAINER (priv->itembar));
687
 
         l != NULL;
688
 
         l = l->next)
689
 
    {
690
 
        XfcePanelItem *item = l->data;
691
 
 
692
 
        xfce_panel_item_free_data (item);
693
 
    }
694
 
 
695
 
    g_list_free (l);
696
 
 
697
 
    /* give plugins the chance to quit */
698
 
    for (i = 0;  i < 10 &&
699
 
         xfce_itembar_get_n_items (XFCE_ITEMBAR (priv->itembar)) != 0; ++i)
700
 
    {
701
 
        DBG (" + %d item(s) on the panel",
702
 
             xfce_itembar_get_n_items (XFCE_ITEMBAR (priv->itembar)));
703
 
        g_usleep (200000); /* 0.2 sec */
704
 
 
705
 
        while (gtk_events_pending ())
706
 
            gtk_main_iteration ();
707
 
    }
708
 
 
709
 
}
710
 
 
711
 
/* items */
712
 
 
713
 
static void
714
 
panel_menu_deactivated (GtkWidget *item)
715
 
{
716
 
    int    x, y, w, h, px, py;
717
 
    Panel *panel = PANEL (item->parent->parent);
718
 
 
719
 
    _panel_return_if_fail (PANEL_IS_PANEL (panel));
720
 
 
721
 
    panel_unblock_autohide (panel);
722
 
 
723
 
    gdk_display_get_pointer (gdk_display_get_default (), NULL, &px, &py, NULL);
724
 
 
725
 
    gtk_window_get_position (GTK_WINDOW (panel), &x, &y);
726
 
    gtk_window_get_size (GTK_WINDOW (panel), &w, &h);
727
 
 
728
 
    if (px < x || px > x + w || py < y || py > y + h)
729
 
    {
730
 
        GdkEvent *ev = gdk_event_new (GDK_LEAVE_NOTIFY);
731
 
 
732
 
        ((GdkEventCrossing *) ev)->time = GDK_CURRENT_TIME;
733
 
        ((GdkEventCrossing *) ev)->detail = GDK_NOTIFY_NONLINEAR;
734
 
 
735
 
        gtk_widget_event (GTK_WIDGET (panel), ev);
736
 
 
737
 
        gdk_event_free (ev);
738
 
    }
739
 
}
740
 
 
741
 
static void
742
 
panel_menu_opened (GtkWidget *item)
743
 
{
744
 
    _panel_return_if_fail (PANEL_IS_PANEL (item->parent->parent));
745
 
 
746
 
    panel_block_autohide (PANEL (item->parent->parent));
747
 
}
748
 
 
749
 
static void
750
 
_item_expand_changed (GtkWidget *item,
751
 
                      gboolean   expand,
752
 
                      Panel     *panel)
753
 
{
754
 
    PanelPrivate *priv;
755
 
 
756
 
    _panel_return_if_fail (PANEL_IS_PANEL (panel));
757
 
 
758
 
    priv = panel->priv;
759
 
 
760
 
    xfce_itembar_set_child_expand (XFCE_ITEMBAR (priv->itembar), item, expand);
761
 
}
762
 
 
763
 
 
764
 
 
765
 
static void
766
 
_item_start_move_end (GtkWidget      *item,
767
 
                      GdkDragContext *context,
768
 
                      Panel          *panel)
769
 
{
770
 
    PanelPrivate *priv = panel->priv;
771
 
    Panel        *p;
772
 
 
773
 
    DBG ("+ finish item drag");
774
 
 
775
 
    /* disconnect drag end signal */
776
 
    g_signal_handlers_disconnect_by_func (G_OBJECT (item), G_CALLBACK (_item_start_move_end), panel);
777
 
 
778
 
    if (!priv->edit_mode)
779
 
    {
780
 
        const GPtrArray *panels = panel_app_get_panel_list ();
781
 
        guint i;
782
 
 
783
 
        for (i = 0; i < panels->len; ++i)
784
 
        {
785
 
            p = g_ptr_array_index (panels, i);
786
 
            priv = p->priv;
787
 
 
788
 
            xfce_itembar_lower_event_window (XFCE_ITEMBAR (priv->itembar));
789
 
            panel_set_items_sensitive (p, TRUE);
790
 
 
791
 
            panel_unblock_autohide (p);
792
 
        }
793
 
    }
794
 
}
795
 
 
796
 
 
797
 
 
798
 
static void
799
 
_item_start_move (GtkWidget *item,
800
 
                  Panel     *panel)
801
 
{
802
 
    const GPtrArray *panels = panel_app_get_panel_list ();
803
 
    PanelPrivate    *priv;
804
 
    Panel           *p;
805
 
    guint             i;
806
 
 
807
 
    for (i = 0; i < panels->len; ++i)
808
 
    {
809
 
        p    = g_ptr_array_index (panels, i);
810
 
        priv = p->priv;
811
 
 
812
 
        if (!priv->edit_mode)
813
 
        {
814
 
            panel_set_items_sensitive (p, FALSE);
815
 
            xfce_itembar_raise_event_window (XFCE_ITEMBAR (priv->itembar));
816
 
            panel_block_autohide (p);
817
 
        }
818
 
    }
819
 
 
820
 
    /* start the drag */
821
 
    panel_dnd_begin_drag (item);
822
 
 
823
 
    /* signal to make panels sensitive after a drop */
824
 
    g_signal_connect (G_OBJECT (item), "drag-end", G_CALLBACK (_item_start_move_end), panel);
825
 
}
826
 
 
827
 
 
828
 
 
829
 
static void
830
 
_item_set_panel_hidden (GtkWidget *item,
831
 
                        gboolean   hidden,
832
 
                        Panel     *panel)
833
 
{
834
 
    PanelPrivate *priv;
835
 
 
836
 
    _panel_return_if_fail (PANEL_IS_PANEL (panel));
837
 
 
838
 
    priv = panel->priv;
839
 
 
840
 
    if (priv->autohide)
841
 
        panel_set_hidden (panel, hidden);
842
 
}
843
 
 
844
 
static void
845
 
panel_insert_widget (Panel     *panel,
846
 
                     GtkWidget *item,
847
 
                     int        position)
848
 
{
849
 
    PanelPrivate *priv = panel->priv;
850
 
 
851
 
    gtk_widget_show (item);
852
 
 
853
 
    if (position == -1)
854
 
        xfce_itembar_append (XFCE_ITEMBAR (priv->itembar), item);
855
 
    else
856
 
        xfce_itembar_insert (XFCE_ITEMBAR (priv->itembar), item, position);
857
 
 
858
 
    xfce_itembar_set_child_expand (XFCE_ITEMBAR (priv->itembar), item,
859
 
            xfce_panel_item_get_expand (XFCE_PANEL_ITEM (item)));
860
 
 
861
 
    if (xfce_itembar_event_window_is_raised (XFCE_ITEMBAR (priv->itembar)))
862
 
        xfce_panel_item_set_sensitive (XFCE_PANEL_ITEM (item), FALSE);
863
 
 
864
 
    g_signal_connect (item, "destroy", G_CALLBACK (panel_app_queue_save),
865
 
                      NULL);
866
 
}
867
 
 
868
 
static GtkWidget *
869
 
panel_create_item (Panel      *panel,
870
 
                   const char *name,
871
 
                   const char *id)
872
 
{
873
 
    PanelPrivate *priv;
874
 
    GtkWidget    *item = NULL;
875
 
    XfceMonitor  *xmon;
876
 
 
877
 
    priv = panel->priv;
878
 
    xmon = panel_app_get_monitor (priv->monitor);
879
 
 
880
 
    item = xfce_panel_item_manager_create_item (xmon->screen,
881
 
                                                name,
882
 
                                                id,
883
 
                                                priv->size,
884
 
                                                priv->screen_position);
885
 
 
886
 
    if (item != NULL)
887
 
    {
888
 
        g_signal_connect (item, "menu-deactivated",
889
 
                          G_CALLBACK (panel_menu_deactivated), panel);
890
 
 
891
 
        g_signal_connect (item, "menu-opened",
892
 
                          G_CALLBACK (panel_menu_opened), panel);
893
 
 
894
 
        g_signal_connect (item, "expand-changed",
895
 
                          G_CALLBACK (_item_expand_changed), panel);
896
 
 
897
 
        g_signal_connect (item, "customize-panel",
898
 
                          G_CALLBACK (panel_app_customize), NULL);
899
 
 
900
 
        g_signal_connect (item, "customize-items",
901
 
                          G_CALLBACK (panel_app_customize_items), NULL);
902
 
 
903
 
        g_signal_connect (item, "move",
904
 
                          G_CALLBACK (_item_start_move), panel);
905
 
 
906
 
        g_signal_connect (item, "set-hidden",
907
 
                          G_CALLBACK (_item_set_panel_hidden), panel);
908
 
    }
909
 
 
910
 
    return item;
911
 
}
912
 
 
913
 
static char *
914
 
_panel_get_new_id (void)
915
 
{
916
 
    static int  counter = 0;
917
 
    static char id[30];
918
 
 
919
 
    /* unique number: pseudo-random time() + counter */
920
 
    g_snprintf (id, sizeof(id), "%ld%d", (glong) time (NULL), counter++);
921
 
 
922
 
    return id;
923
 
}
924
 
 
925
 
GtkWidget *
926
 
panel_add_item_with_id (Panel      *panel,
927
 
                        const char *name,
928
 
                        const char *id)
929
 
{
930
 
    GtkWidget *item;
931
 
 
932
 
    item = panel_create_item (panel, name, id);
933
 
 
934
 
    if (item != NULL)
935
 
    {
936
 
        panel_insert_widget (panel, item, -1);
937
 
    }
938
 
 
939
 
    return item;
940
 
}
941
 
 
942
 
GtkWidget *
943
 
panel_add_item (Panel      *panel,
944
 
                const char *name)
945
 
{
946
 
    return panel_add_item_with_id (panel, name, _panel_get_new_id ());
947
 
}
948
 
 
949
 
GtkWidget *
950
 
panel_insert_item (Panel      *panel,
951
 
                   const char *name,
952
 
                   int         position)
953
 
{
954
 
    GtkWidget *item;
955
 
 
956
 
    item = panel_create_item (panel, name, _panel_get_new_id ());
957
 
 
958
 
    if (item != NULL)
959
 
    {
960
 
        panel_insert_widget (panel, item, position);
961
 
    }
962
 
 
963
 
    return item;
964
 
}
965
 
 
966
 
/* configuration */
967
 
 
968
 
GList *
969
 
panel_get_item_list (Panel * panel)
970
 
{
971
 
    PanelPrivate *priv;
972
 
 
973
 
    priv = panel->priv;
974
 
 
975
 
    return gtk_container_get_children (GTK_CONTAINER (priv->itembar));
976
 
}
977
 
 
978
 
void
979
 
panel_save_items (Panel *panel)
980
 
{
981
 
    PanelPrivate *priv;
982
 
 
983
 
    _panel_return_if_fail (PANEL_IS_PANEL (panel));
984
 
 
985
 
    priv = panel->priv;
986
 
 
987
 
    gtk_container_foreach (GTK_CONTAINER (priv->itembar),
988
 
                           (GtkCallback)xfce_panel_item_save, NULL);
989
 
}
990
 
 
991
 
/* convenience */
992
 
 
993
 
gboolean
994
 
panel_is_horizontal (Panel *panel)
995
 
{
996
 
    return (GTK_ORIENTATION_HORIZONTAL ==
997
 
            xfce_panel_window_get_orientation (XFCE_PANEL_WINDOW (panel)));
998
 
}
999
 
 
1000
 
void
1001
 
panel_set_items_sensitive (Panel    *panel,
1002
 
                           gboolean  sensitive)
1003
 
{
1004
 
    PanelPrivate *priv = panel->priv;
1005
 
    GList        *l, *children;
1006
 
 
1007
 
    children = gtk_container_get_children (GTK_CONTAINER (priv->itembar));
1008
 
 
1009
 
    for (l = children; l != NULL; l = l->next)
1010
 
    {
1011
 
        xfce_panel_item_set_sensitive (XFCE_PANEL_ITEM (l->data), sensitive);
1012
 
    }
1013
 
 
1014
 
    g_list_free (children);
1015
 
}