2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21
#include <cairo-dock.h>
22
#include <gdk/gdkkeysyms.h>
24
#include "applet-struct.h"
25
#include "applet-menu.h"
26
#include "applet-util.h"
27
#include "applet-recent.h"
28
#include "applet-menu-callbacks.h"
30
static guint load_icons_id = 0;
31
static GList *icons_to_load = NULL;
32
static GList *icons_to_add = NULL;
35
void handle_gmenu_tree_changed (GMenuTree *tree,
38
cd_message ("%s ()", __func__);
40
if (myData.pMenu != NULL)
42
gtk_widget_destroy (myData.pMenu);
46
if (myData.pMenu == NULL)
48
myData.pMenu = create_main_menu (NULL);
54
while (GTK_MENU_SHELL (menu)->children)
55
gtk_widget_destroy (GTK_MENU_SHELL (menu)->children->data);
57
g_object_set_data_full (G_OBJECT (menu),
58
"panel-menu-tree-directory",
61
g_object_set_data (G_OBJECT (menu),
62
"panel-menu-needs-loading",
63
GUINT_TO_POINTER (TRUE));
65
idle_id = g_idle_add_full (G_PRIORITY_LOW,
66
submenu_to_display_in_idle,
69
if (myData.iSidTreeChangeIdle != 0)
70
g_source_remove (myData.iSidTreeChangeIdle);
71
myData.iSidTreeChangeIdle = idle_id;
72
g_object_set_data_full (G_OBJECT (menu),
74
GUINT_TO_POINTER (idle_id),
75
remove_submenu_to_display_idle);
78
void remove_gmenu_tree_monitor (GtkWidget *menu,
81
cd_message ("%s (%x)", __func__, tree);
82
gmenu_tree_remove_monitor (tree,
83
(GMenuTreeChangedFunc) handle_gmenu_tree_changed,
88
gboolean menu_dummy_button_press_event (GtkWidget *menuitem,
89
GdkEventButton *event)
91
if (event->button == 3)
98
void remove_submenu_to_display_idle (gpointer data)
100
guint idle_id = GPOINTER_TO_UINT (data);
102
g_source_remove (idle_id);
106
gboolean submenu_to_display_in_idle (gpointer data)
108
GtkWidget *menu = GTK_WIDGET (data);
109
cd_message ("%s (%x)", __func__, menu);
111
g_object_set_data (G_OBJECT (menu), "panel-menu-idle-id", NULL);
113
submenu_to_display (menu);
118
void submenu_to_display (GtkWidget *menu)
120
cd_message ("%s (%x)", __func__, menu);
122
GMenuTreeDirectory *directory;
123
const char *menu_path;
124
void (*append_callback) (GtkWidget *, gpointer);
125
gpointer append_data;
127
if (!g_object_get_data (G_OBJECT (menu), "panel-menu-needs-loading"))
129
cd_debug ("needs no loading\n");
133
g_object_set_data (G_OBJECT (menu), "panel-menu-needs-loading", NULL);
135
directory = g_object_get_data (G_OBJECT (menu),
136
"panel-menu-tree-directory");
138
menu_path = g_object_get_data (G_OBJECT (menu),
139
"panel-menu-tree-path");
140
cd_debug ("n'est pas un directory, menu_path : %s\n", menu_path);
143
cd_warning ("menu_path is empty");
147
tree = g_object_get_data (G_OBJECT (menu), "panel-menu-tree");
150
cd_warning ("no tree found in datas");
153
directory = gmenu_tree_get_directory_from_path (tree,
156
g_object_set_data_full (G_OBJECT (menu),
157
"panel-menu-tree-directory",
159
(GDestroyNotify) gmenu_tree_item_unref);
161
//g_print ("%s ()\n", __func__);
163
populate_menu_from_directory (menu, directory);
165
append_callback = g_object_get_data (G_OBJECT (menu),
166
"panel-menu-append-callback");
167
append_data = g_object_get_data (G_OBJECT (menu),
168
"panel-menu-append-callback-data");
170
append_callback (menu, append_data);
174
void panel_desktop_menu_item_append_menu (GtkWidget *menu,
177
//g_print ("%s ()\n", __func__);
178
CairoDockModuleInstance *myApplet;
179
gboolean add_separator;
183
myApplet = (CairoDockModuleInstance *) data;
185
add_separator = FALSE;
186
children = gtk_container_get_children (GTK_CONTAINER (menu));
187
last = g_list_last (children);
190
/// add_separator = !GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
192
g_list_free (children);
195
add_menu_separator (menu);
197
//panel_menu_items_append_from_desktop (menu, "yelp.desktop", NULL);
198
//panel_menu_items_append_from_desktop (menu, "gnome-about.desktop", NULL);
200
//if (parent->priv->append_lock_logout)
201
// panel_menu_items_append_lock_logout (menu);
203
void main_menu_append (GtkWidget *main_menu,
206
//g_print ("%s ()\n", __func__);
207
CairoDockModuleInstance *myApplet;
209
gboolean add_separator;
213
myApplet = (CairoDockModuleInstance *) data;
215
add_separator = FALSE;
216
children = gtk_container_get_children (GTK_CONTAINER (main_menu));
217
last = g_list_last (children);
219
///add_separator = !GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
221
g_list_free (children);
224
add_menu_separator (main_menu);
227
GtkWidget *desktop_menu;
229
desktop_menu = create_applications_menu ("settings.menu", NULL, main_menu);
230
g_object_set_data_full (G_OBJECT (desktop_menu),
231
"panel-menu-tree-directory",
234
g_object_set_data (G_OBJECT (desktop_menu),
235
"panel-menu-append-callback",
236
panel_desktop_menu_item_append_menu);
237
g_object_set_data (G_OBJECT (desktop_menu),
238
"panel-menu-append-callback-data",
241
if (myConfig.bShowRecent)
243
cd_menu_append_recent_to_menu (main_menu, myApplet);
245
/*item = panel_place_menu_item_new (TRUE);
246
panel_place_menu_item_set_panel (item, panel);
247
gtk_menu_shell_append (GTK_MENU_SHELL (main_menu), item);
248
gtk_widget_show (item);
250
item = panel_desktop_menu_item_new (TRUE, FALSE);
251
panel_desktop_menu_item_set_panel (item, panel);
252
gtk_menu_shell_append (GTK_MENU_SHELL (main_menu), item);
253
gtk_widget_show (item);
255
panel_menu_items_append_lock_logout (main_menu);*/
258
/*gboolean show_item_menu (GtkWidget *item,
259
GdkEventButton *bevent)
261
CairoDockModuleInstance *myApplet;
264
if (panel_lockdown_get_locked_down ())
267
panel_widget = menu_get_panel (item);
269
menu = g_object_get_data (G_OBJECT (item), "panel-item-context-menu");
272
menu = create_item_context_menu (item, panel_widget);
277
gtk_menu_set_screen (GTK_MENU (menu),
278
gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel)));
280
gtk_menu_popup (GTK_MENU (menu),
281
NULL, NULL, NULL, NULL,
287
gboolean panel_menu_key_press_handler (GtkWidget *widget,
290
gboolean retval = FALSE;
292
if ((event->keyval == GDK_Menu) ||
293
(event->keyval == GDK_F10 &&
294
(event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_SHIFT_MASK)) {
295
GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
297
if (menu_shell->active_menu_item &&
298
GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu == NULL) {
299
GdkEventButton bevent;
302
bevent.time = GDK_CURRENT_TIME;
303
retval = show_item_menu (menu_shell->active_menu_item,
311
static void menu_item_style_set (GtkImage *image,
316
GtkIconSize icon_size = (GtkIconSize) GPOINTER_TO_INT (data);
320
if (!gtk_icon_size_lookup (icon_size, NULL, &icon_height))
323
pixbuf = gtk_image_get_pixbuf (image);
327
if (gdk_pixbuf_get_height (pixbuf) == icon_height)
330
widget = GTK_WIDGET (image);
332
is_mapped = GTK_WIDGET_MAPPED (widget);
334
gtk_widget_unmap (widget);
336
gtk_image_set_from_pixbuf (image, NULL);
339
gtk_widget_map (widget);
341
static void do_icons_to_add (void)
343
while (icons_to_add) {
344
IconToAdd *icon_to_add = icons_to_add->data;
346
icons_to_add = g_list_delete_link (icons_to_add, icons_to_add);
348
if (icon_to_add->stock_id)
349
gtk_image_set_from_stock (
350
GTK_IMAGE (icon_to_add->image),
351
icon_to_add->stock_id,
352
icon_to_add->icon_size);
354
g_assert (icon_to_add->pixbuf);
356
gtk_image_set_from_pixbuf (
357
GTK_IMAGE (icon_to_add->image),
358
icon_to_add->pixbuf);
360
g_signal_connect (icon_to_add->image, "style-set",
361
G_CALLBACK (menu_item_style_set),
362
GINT_TO_POINTER (icon_to_add->icon_size));
364
g_object_unref (icon_to_add->pixbuf);
367
g_object_unref (icon_to_add->image);
368
g_free (icon_to_add);
371
void icon_to_load_free (IconToLoad *icon)
377
g_object_unref (icon->pixmap);
381
g_object_unref (icon->gicon);
384
g_free (icon->image); icon->image = NULL;
385
g_free (icon->fallback_image); icon->fallback_image = NULL;
388
static gboolean load_icons_handler (gpointer data)
391
gboolean long_operation = FALSE;
393
load_icons_handler_again:
395
if (!icons_to_load) {
402
icon = icons_to_load->data;
403
icons_to_load->data = NULL;
405
icons_to_load = g_list_delete_link (icons_to_load, icons_to_load);
407
/* if not visible anymore, just ignore */
408
if ( ! GTK_WIDGET_VISIBLE (icon->pixmap)) {
409
icon_to_load_free (icon);
410
/* we didn't do anything long/hard, so just do this again,
411
* this is fun, don't go back to main loop */
412
goto load_icons_handler_again;
415
if (icon->stock_id) {
416
IconToAdd *icon_to_add;
418
icon_to_add = g_new (IconToAdd, 1);
419
icon_to_add->image = g_object_ref (icon->pixmap);
420
icon_to_add->stock_id = icon->stock_id;
421
icon_to_add->pixbuf = NULL;
422
icon_to_add->icon_size = icon->icon_size;
424
icons_to_add = g_list_prepend (icons_to_add, icon_to_add);
427
else if (icon->gicon) {
428
IconToAdd *icon_to_add;
431
int icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
433
gtk_icon_size_lookup (icon->icon_size, NULL, &icon_height);
435
icon_name = panel_util_get_icon_name_from_g_icon (icon->gicon);
438
pb = panel_make_menu_icon (icon->icon_theme,
440
icon->fallback_image,
445
pb = panel_util_get_pixbuf_from_g_loadable_icon (icon->gicon, icon_height);
446
if (!pb && icon->fallback_image) {
447
pb = panel_make_menu_icon (icon->icon_theme,
449
icon->fallback_image,
456
icon_to_load_free (icon);
458
/* this may have been a long operation so jump
459
* back to the main loop for a while */
462
/* we didn't do anything long/hard, so just do
463
* this again, this is fun, don't go back to
465
goto load_icons_handler_again;
468
icon_to_add = g_new (IconToAdd, 1);
469
icon_to_add->image = g_object_ref (icon->pixmap);
470
icon_to_add->stock_id = NULL;
471
icon_to_add->pixbuf = pb;
472
icon_to_add->icon_size = icon->icon_size;
474
icons_to_add = g_list_prepend (icons_to_add, icon_to_add);
478
IconToAdd *icon_to_add;
480
int icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
482
gtk_icon_size_lookup (icon->icon_size, NULL, &icon_height);
484
pb = panel_make_menu_icon (icon->icon_theme,
486
icon->fallback_image,
490
icon_to_load_free (icon);
492
/* this may have been a long operation so jump back to
493
* the main loop for a while */
496
/* we didn't do anything long/hard, so just do this again,
497
* this is fun, don't go back to main loop */
498
goto load_icons_handler_again;
501
icon_to_add = g_new (IconToAdd, 1);
502
icon_to_add->image = g_object_ref (icon->pixmap);
503
icon_to_add->stock_id = NULL;
504
icon_to_add->pixbuf = pb;
505
icon_to_add->icon_size = icon->icon_size;
507
icons_to_add = g_list_prepend (icons_to_add, icon_to_add);
510
icon_to_load_free (icon);
513
/* we didn't do anything long/hard, so just do this again,
514
* this is fun, don't go back to main loop */
515
goto load_icons_handler_again;
517
/* if still more we'll come back */
520
static GList * find_in_load_list (GtkWidget *image)
523
for (li = icons_to_load; li != NULL; li = li->next) {
524
IconToLoad *icon = li->data;
525
if (icon->pixmap == image)
530
static IconToLoad * icon_to_load_copy (IconToLoad *icon)
537
retval = g_new0 (IconToLoad, 1);
539
retval->pixmap = g_object_ref (icon->pixmap);
541
retval->gicon = g_object_ref (icon->gicon);
543
retval->gicon = NULL;
544
retval->image = g_strdup (icon->image);
545
retval->fallback_image = g_strdup (icon->fallback_image);
546
retval->stock_id = icon->stock_id;
547
retval->icon_size = icon->icon_size;
551
void image_menu_shown (GtkWidget *image, gpointer data)
553
IconToLoad *new_icon;
556
icon = (IconToLoad *) data;
558
/* if we've already handled this */
559
if (gtk_image_get_storage_type (GTK_IMAGE (image)) != GTK_IMAGE_EMPTY)
562
if (find_in_load_list (image) == NULL) {
563
new_icon = icon_to_load_copy (icon);
564
new_icon->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (image));
565
icons_to_load = g_list_append (icons_to_load, new_icon);
567
if (load_icons_id == 0)
568
load_icons_id = g_idle_add (load_icons_handler, NULL);
571
void activate_app_def (GtkWidget *menuitem,
572
GMenuTreeEntry *entry)
576
path = gmenu_tree_entry_get_desktop_file_path (entry);
577
panel_menu_item_activate_desktop_file (menuitem, path);
582
void drag_begin_menu_cb (GtkWidget *widget, GdkDragContext *context)
584
/* FIXME: workaround for a possible gtk+ bug
585
* See bugs #92085(gtk+) and #91184(panel) for details.
586
* Maybe it's not needed with GtkTooltip?
588
g_object_set (widget, "has-tooltip", FALSE, NULL);
591
/* This is a _horrible_ hack to have this here. This needs to be added to the
592
* GTK+ menuing code in some manner.
594
void drag_end_menu_cb (GtkWidget *widget, GdkDragContext *context)
596
GtkWidget *xgrab_shell;
599
/* Find the last viewable ancestor, and make an X grab on it
601
parent = widget->parent;
604
/* FIXME: workaround for a possible gtk+ bug
605
* See bugs #92085(gtk+) and #91184(panel) for details.
607
g_object_set (widget, "has-tooltip", TRUE, NULL);
611
gboolean viewable = TRUE;
612
GtkWidget *tmp = parent;
616
if (!GTK_WIDGET_MAPPED (tmp))
625
xgrab_shell = parent;
627
parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
630
if (xgrab_shell && !GTK_MENU(xgrab_shell)->torn_off)
632
GdkCursor *cursor = gdk_cursor_new (GDK_ARROW);
634
if ((gdk_pointer_grab (xgrab_shell->window, TRUE,
635
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
636
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
637
GDK_POINTER_MOTION_MASK,
638
NULL, cursor, GDK_CURRENT_TIME) == 0))
640
if (gdk_keyboard_grab (xgrab_shell->window, TRUE,
641
GDK_CURRENT_TIME) == 0)
642
GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
645
gdk_pointer_ungrab (GDK_CURRENT_TIME);
649
gdk_cursor_unref (cursor);
653
void drag_data_get_menu_cb (GtkWidget *widget,
654
GdkDragContext *context,
655
GtkSelectionData *selection_data,
658
GMenuTreeEntry *entry)
664
path = gmenu_tree_entry_get_desktop_file_path (entry);
665
uri = g_filename_to_uri (path, NULL, NULL);
666
uri_list = g_strconcat (uri, "\r\n", NULL);
669
gtk_selection_data_set (selection_data,
670
selection_data->target, 8, (guchar *)uri_list,
675
/*gboolean menuitem_button_press_event (GtkWidget *menuitem,
676
GdkEventButton *event)
678
if (event->button == 3)
679
return show_item_menu (menuitem, event);