Mercurial > audlegacy
comparison src/audacious/sync-menu.c @ 3430:91c27073aa13 trunk
Automated merge with ssh://hg.atheme.org//hg/audacious
| author | William Pitcock <nenolod@atheme.org> |
|---|---|
| date | Fri, 07 Sep 2007 00:18:50 -0500 |
| parents | db83b4a786ed |
| children |
comparison
equal
deleted
inserted
replaced
| 3429:05b732174e5f | 3430:91c27073aa13 |
|---|---|
| 1 /* GTK+ Integration for the Mac OS X Menubar. | |
| 2 * | |
| 3 * Copyright (C) 2007 Pioneer Research Center USA, Inc. | |
| 4 * | |
| 5 * This library is free software; you can redistribute it and/or | |
| 6 * modify it under the terms of the GNU Lesser General Public | |
| 7 * License as published by the Free Software Foundation; either | |
| 8 * version 2 of the License, or (at your option) any later version. | |
| 9 * | |
| 10 * This library 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 GNU | |
| 13 * Lesser General Public License for more details. | |
| 14 * | |
| 15 * You should have received a copy of the GNU Lesser General Public | |
| 16 * License along with this library; if not, write to the | |
| 17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 18 * Boston, MA 02111-1307, USA. | |
| 19 */ | |
| 20 | |
| 21 #include <gtk/gtk.h> | |
| 22 | |
| 23 #ifdef GDK_WINDOWING_QUARTZ | |
| 24 | |
| 25 #include <gdk/gdkkeysyms.h> | |
| 26 | |
| 27 #include <Carbon/Carbon.h> | |
| 28 | |
| 29 #include "sync-menu.h" | |
| 30 | |
| 31 | |
| 32 /* TODO | |
| 33 * | |
| 34 * - Setup shortcuts, possibly transforming ctrl->cmd | |
| 35 * - Sync menus | |
| 36 * - Create on demand? (can this be done with gtk+? ie fill in menu items when the menu is opened) | |
| 37 * - Figure out what to do per app/window... | |
| 38 * - Toggle/radio items | |
| 39 * | |
| 40 */ | |
| 41 | |
| 42 #define GTK_QUARTZ_MENU_CREATOR 'GTKC' | |
| 43 #define GTK_QUARTZ_ITEM_WIDGET 'GWID' | |
| 44 | |
| 45 | |
| 46 static void sync_menu_shell (GtkMenuShell *menu_shell, | |
| 47 MenuRef carbon_menu, | |
| 48 gboolean toplevel); | |
| 49 | |
| 50 | |
| 51 /* | |
| 52 * utility functions | |
| 53 */ | |
| 54 | |
| 55 static GtkWidget * | |
| 56 find_menu_label (GtkWidget *widget) | |
| 57 { | |
| 58 GtkWidget *label = NULL; | |
| 59 | |
| 60 if (GTK_IS_LABEL (widget)) | |
| 61 return widget; | |
| 62 | |
| 63 if (GTK_IS_CONTAINER (widget)) | |
| 64 { | |
| 65 GList *children; | |
| 66 GList *l; | |
| 67 | |
| 68 children = gtk_container_get_children (GTK_CONTAINER (widget)); | |
| 69 | |
| 70 for (l = children; l; l = l->next) | |
| 71 { | |
| 72 label = find_menu_label (l->data); | |
| 73 if (label) | |
| 74 break; | |
| 75 } | |
| 76 | |
| 77 g_list_free (children); | |
| 78 } | |
| 79 | |
| 80 return label; | |
| 81 } | |
| 82 | |
| 83 static const gchar * | |
| 84 get_menu_label_text (GtkWidget *menu_item, | |
| 85 GtkWidget **label) | |
| 86 { | |
| 87 *label = find_menu_label (menu_item); | |
| 88 if (!*label) | |
| 89 return NULL; | |
| 90 | |
| 91 return gtk_label_get_text (GTK_LABEL (*label)); | |
| 92 } | |
| 93 | |
| 94 static gboolean | |
| 95 accel_find_func (GtkAccelKey *key, | |
| 96 GClosure *closure, | |
| 97 gpointer data) | |
| 98 { | |
| 99 return (GClosure *) data == closure; | |
| 100 } | |
| 101 | |
| 102 | |
| 103 /* | |
| 104 * CarbonMenu functions | |
| 105 */ | |
| 106 | |
| 107 typedef struct | |
| 108 { | |
| 109 MenuRef menu; | |
| 110 } CarbonMenu; | |
| 111 | |
| 112 static GQuark carbon_menu_quark = 0; | |
| 113 | |
| 114 static CarbonMenu * | |
| 115 carbon_menu_new (void) | |
| 116 { | |
| 117 return g_slice_new0 (CarbonMenu); | |
| 118 } | |
| 119 | |
| 120 static void | |
| 121 carbon_menu_free (CarbonMenu *menu) | |
| 122 { | |
| 123 g_slice_free (CarbonMenu, menu); | |
| 124 } | |
| 125 | |
| 126 static CarbonMenu * | |
| 127 carbon_menu_get (GtkWidget *widget) | |
| 128 { | |
| 129 return g_object_get_qdata (G_OBJECT (widget), carbon_menu_quark); | |
| 130 } | |
| 131 | |
| 132 static void | |
| 133 carbon_menu_connect (GtkWidget *menu, | |
| 134 MenuRef menuRef) | |
| 135 { | |
| 136 CarbonMenu *carbon_menu = carbon_menu_get (menu); | |
| 137 | |
| 138 if (!carbon_menu) | |
| 139 { | |
| 140 carbon_menu = carbon_menu_new (); | |
| 141 | |
| 142 g_object_set_qdata_full (G_OBJECT (menu), carbon_menu_quark, | |
| 143 carbon_menu, | |
| 144 (GDestroyNotify) carbon_menu_free); | |
| 145 } | |
| 146 | |
| 147 carbon_menu->menu = menuRef; | |
| 148 } | |
| 149 | |
| 150 | |
| 151 /* | |
| 152 * CarbonMenuItem functions | |
| 153 */ | |
| 154 | |
| 155 typedef struct | |
| 156 { | |
| 157 MenuRef menu; | |
| 158 MenuItemIndex index; | |
| 159 MenuRef submenu; | |
| 160 GClosure *accel_closure; | |
| 161 } CarbonMenuItem; | |
| 162 | |
| 163 static GQuark carbon_menu_item_quark = 0; | |
| 164 | |
| 165 static CarbonMenuItem * | |
| 166 carbon_menu_item_new (void) | |
| 167 { | |
| 168 return g_slice_new0 (CarbonMenuItem); | |
| 169 } | |
| 170 | |
| 171 static void | |
| 172 carbon_menu_item_free (CarbonMenuItem *menu_item) | |
| 173 { | |
| 174 if (menu_item->accel_closure) | |
| 175 g_closure_unref (menu_item->accel_closure); | |
| 176 | |
| 177 g_slice_free (CarbonMenuItem, menu_item); | |
| 178 } | |
| 179 | |
| 180 static CarbonMenuItem * | |
| 181 carbon_menu_item_get (GtkWidget *widget) | |
| 182 { | |
| 183 return g_object_get_qdata (G_OBJECT (widget), carbon_menu_item_quark); | |
| 184 } | |
| 185 | |
| 186 static void | |
| 187 carbon_menu_item_update_state (CarbonMenuItem *carbon_item, | |
| 188 GtkWidget *widget) | |
| 189 { | |
| 190 gboolean sensitive; | |
| 191 gboolean visible; | |
| 192 UInt32 set_attrs = 0; | |
| 193 UInt32 clear_attrs = 0; | |
| 194 | |
| 195 g_object_get (widget, | |
| 196 "sensitive", &sensitive, | |
| 197 "visible", &visible, | |
| 198 NULL); | |
| 199 | |
| 200 if (!sensitive) | |
| 201 set_attrs |= kMenuItemAttrDisabled; | |
| 202 else | |
| 203 clear_attrs |= kMenuItemAttrDisabled; | |
| 204 | |
| 205 if (!visible) | |
| 206 set_attrs |= kMenuItemAttrHidden; | |
| 207 else | |
| 208 clear_attrs |= kMenuItemAttrHidden; | |
| 209 | |
| 210 ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index, | |
| 211 set_attrs, clear_attrs); | |
| 212 } | |
| 213 | |
| 214 static void | |
| 215 carbon_menu_item_update_active (CarbonMenuItem *carbon_item, | |
| 216 GtkWidget *widget) | |
| 217 { | |
| 218 gboolean active; | |
| 219 | |
| 220 g_object_get (widget, | |
| 221 "active", &active, | |
| 222 NULL); | |
| 223 | |
| 224 CheckMenuItem (carbon_item->menu, carbon_item->index, | |
| 225 active); | |
| 226 } | |
| 227 | |
| 228 static void | |
| 229 carbon_menu_item_update_submenu (CarbonMenuItem *carbon_item, | |
| 230 GtkWidget *widget) | |
| 231 { | |
| 232 GtkWidget *submenu; | |
| 233 | |
| 234 submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)); | |
| 235 | |
| 236 if (submenu) | |
| 237 { | |
| 238 GtkWidget *label = NULL; | |
| 239 const gchar *label_text; | |
| 240 CFStringRef cfstr = NULL; | |
| 241 | |
| 242 label_text = get_menu_label_text (widget, &label); | |
| 243 if (label_text) | |
| 244 cfstr = CFStringCreateWithCString (NULL, label_text, | |
| 245 kCFStringEncodingUTF8); | |
| 246 | |
| 247 CreateNewMenu (0, 0, &carbon_item->submenu); | |
| 248 SetMenuTitleWithCFString (carbon_item->submenu, cfstr); | |
| 249 SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index, | |
| 250 carbon_item->submenu); | |
| 251 | |
| 252 sync_menu_shell (GTK_MENU_SHELL (submenu), carbon_item->submenu, FALSE); | |
| 253 | |
| 254 if (cfstr) | |
| 255 CFRelease (cfstr); | |
| 256 } | |
| 257 else | |
| 258 { | |
| 259 SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index, | |
| 260 NULL); | |
| 261 carbon_item->submenu = NULL; | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 static void | |
| 266 carbon_menu_item_update_label (CarbonMenuItem *carbon_item, | |
| 267 GtkWidget *widget) | |
| 268 { | |
| 269 GtkWidget *label; | |
| 270 const gchar *label_text; | |
| 271 CFStringRef cfstr = NULL; | |
| 272 | |
| 273 label_text = get_menu_label_text (widget, &label); | |
| 274 if (label_text) | |
| 275 cfstr = CFStringCreateWithCString (NULL, label_text, | |
| 276 kCFStringEncodingUTF8); | |
| 277 | |
| 278 SetMenuItemTextWithCFString (carbon_item->menu, carbon_item->index, | |
| 279 cfstr); | |
| 280 | |
| 281 if (cfstr) | |
| 282 CFRelease (cfstr); | |
| 283 } | |
| 284 | |
| 285 static void | |
| 286 carbon_menu_item_update_accelerator (CarbonMenuItem *carbon_item, | |
| 287 GtkWidget *widget) | |
| 288 { | |
| 289 GtkWidget *label; | |
| 290 | |
| 291 get_menu_label_text (widget, &label); | |
| 292 | |
| 293 if (GTK_IS_ACCEL_LABEL (label) && | |
| 294 GTK_ACCEL_LABEL (label)->accel_closure) | |
| 295 { | |
| 296 GtkAccelKey *key; | |
| 297 | |
| 298 key = gtk_accel_group_find (GTK_ACCEL_LABEL (label)->accel_group, | |
| 299 accel_find_func, | |
| 300 GTK_ACCEL_LABEL (label)->accel_closure); | |
| 301 | |
| 302 if (key && | |
| 303 key->accel_key && | |
| 304 key->accel_flags & GTK_ACCEL_VISIBLE) | |
| 305 { | |
| 306 GdkDisplay *display = gtk_widget_get_display (widget); | |
| 307 GdkKeymap *keymap = gdk_keymap_get_for_display (display); | |
| 308 GdkKeymapKey *keys; | |
| 309 gint n_keys; | |
| 310 | |
| 311 if (gdk_keymap_get_entries_for_keyval (keymap, key->accel_key, | |
| 312 &keys, &n_keys)) | |
| 313 { | |
| 314 UInt8 modifiers = 0; | |
| 315 | |
| 316 SetMenuItemCommandKey (carbon_item->menu, carbon_item->index, | |
| 317 true, keys[0].keycode); | |
| 318 | |
| 319 g_free (keys); | |
| 320 | |
| 321 if (key->accel_mods) | |
| 322 { | |
| 323 if (key->accel_mods & GDK_SHIFT_MASK) | |
| 324 modifiers |= kMenuShiftModifier; | |
| 325 | |
| 326 if (key->accel_mods & GDK_MOD1_MASK) | |
| 327 modifiers |= kMenuOptionModifier; | |
| 328 } | |
| 329 | |
| 330 if (!(key->accel_mods & GDK_CONTROL_MASK)) | |
| 331 { | |
| 332 modifiers |= kMenuNoCommandModifier; | |
| 333 } | |
| 334 | |
| 335 SetMenuItemModifiers (carbon_item->menu, carbon_item->index, | |
| 336 modifiers); | |
| 337 | |
| 338 return; | |
| 339 } | |
| 340 } | |
| 341 } | |
| 342 | |
| 343 /* otherwise, clear the menu shortcut */ | |
| 344 SetMenuItemModifiers (carbon_item->menu, carbon_item->index, | |
| 345 kMenuNoModifiers | kMenuNoCommandModifier); | |
| 346 ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index, | |
| 347 0, kMenuItemAttrUseVirtualKey); | |
| 348 SetMenuItemCommandKey (carbon_item->menu, carbon_item->index, | |
| 349 false, 0); | |
| 350 } | |
| 351 | |
| 352 static void | |
| 353 carbon_menu_item_accel_changed (GtkAccelGroup *accel_group, | |
| 354 guint keyval, | |
| 355 GdkModifierType modifier, | |
| 356 GClosure *accel_closure, | |
| 357 GtkWidget *widget) | |
| 358 { | |
| 359 CarbonMenuItem *carbon_item = carbon_menu_item_get (widget); | |
| 360 GtkWidget *label; | |
| 361 | |
| 362 get_menu_label_text (widget, &label); | |
| 363 | |
| 364 if (GTK_IS_ACCEL_LABEL (label) && | |
| 365 GTK_ACCEL_LABEL (label)->accel_closure == accel_closure) | |
| 366 carbon_menu_item_update_accelerator (carbon_item, widget); | |
| 367 } | |
| 368 | |
| 369 static void | |
| 370 carbon_menu_item_update_accel_closure (CarbonMenuItem *carbon_item, | |
| 371 GtkWidget *widget) | |
| 372 { | |
| 373 GtkAccelGroup *group; | |
| 374 GtkWidget *label; | |
| 375 | |
| 376 get_menu_label_text (widget, &label); | |
| 377 | |
| 378 if (carbon_item->accel_closure) | |
| 379 { | |
| 380 group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure); | |
| 381 | |
| 382 g_signal_handlers_disconnect_by_func (group, | |
| 383 carbon_menu_item_accel_changed, | |
| 384 widget); | |
| 385 | |
| 386 g_closure_unref (carbon_item->accel_closure); | |
| 387 carbon_item->accel_closure = NULL; | |
| 388 } | |
| 389 | |
| 390 if (GTK_IS_ACCEL_LABEL (label)) | |
| 391 carbon_item->accel_closure = GTK_ACCEL_LABEL (label)->accel_closure; | |
| 392 | |
| 393 if (carbon_item->accel_closure) | |
| 394 { | |
| 395 g_closure_ref (carbon_item->accel_closure); | |
| 396 | |
| 397 group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure); | |
| 398 | |
| 399 g_signal_connect_object (group, "accel-changed", | |
| 400 G_CALLBACK (carbon_menu_item_accel_changed), | |
| 401 widget, 0); | |
| 402 } | |
| 403 | |
| 404 carbon_menu_item_update_accelerator (carbon_item, widget); | |
| 405 } | |
| 406 | |
| 407 static void | |
| 408 carbon_menu_item_notify (GObject *object, | |
| 409 GParamSpec *pspec, | |
| 410 CarbonMenuItem *carbon_item) | |
| 411 { | |
| 412 if (!strcmp (pspec->name, "sensitive") || | |
| 413 !strcmp (pspec->name, "visible")) | |
| 414 { | |
| 415 carbon_menu_item_update_state (carbon_item, GTK_WIDGET (object)); | |
| 416 } | |
| 417 else if (!strcmp (pspec->name, "active")) | |
| 418 { | |
| 419 carbon_menu_item_update_active (carbon_item, GTK_WIDGET (object)); | |
| 420 } | |
| 421 else if (!strcmp (pspec->name, "submenu")) | |
| 422 { | |
| 423 carbon_menu_item_update_submenu (carbon_item, GTK_WIDGET (object)); | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 static void | |
| 428 carbon_menu_item_notify_label (GObject *object, | |
| 429 GParamSpec *pspec, | |
| 430 gpointer data) | |
| 431 { | |
| 432 CarbonMenuItem *carbon_item = carbon_menu_item_get (GTK_WIDGET (object)); | |
| 433 | |
| 434 if (!strcmp (pspec->name, "label")) | |
| 435 { | |
| 436 carbon_menu_item_update_label (carbon_item, | |
| 437 GTK_WIDGET (object)); | |
| 438 } | |
| 439 else if (!strcmp (pspec->name, "accel-closure")) | |
| 440 { | |
| 441 carbon_menu_item_update_accel_closure (carbon_item, | |
| 442 GTK_WIDGET (object)); | |
| 443 } | |
| 444 } | |
| 445 | |
| 446 static CarbonMenuItem * | |
| 447 carbon_menu_item_connect (GtkWidget *menu_item, | |
| 448 GtkWidget *label, | |
| 449 MenuRef menu, | |
| 450 MenuItemIndex index) | |
| 451 { | |
| 452 CarbonMenuItem *carbon_item = carbon_menu_item_get (menu_item); | |
| 453 | |
| 454 if (!carbon_item) | |
| 455 { | |
| 456 carbon_item = carbon_menu_item_new (); | |
| 457 | |
| 458 g_object_set_qdata_full (G_OBJECT (menu_item), carbon_menu_item_quark, | |
| 459 carbon_item, | |
| 460 (GDestroyNotify) carbon_menu_item_free); | |
| 461 | |
| 462 g_signal_connect (menu_item, "notify", | |
| 463 G_CALLBACK (carbon_menu_item_notify), | |
| 464 carbon_item); | |
| 465 | |
| 466 if (label) | |
| 467 g_signal_connect_swapped (label, "notify::label", | |
| 468 G_CALLBACK (carbon_menu_item_notify_label), | |
| 469 menu_item); | |
| 470 } | |
| 471 | |
| 472 carbon_item->menu = menu; | |
| 473 carbon_item->index = index; | |
| 474 | |
| 475 return carbon_item; | |
| 476 } | |
| 477 | |
| 478 | |
| 479 /* | |
| 480 * carbon event handler | |
| 481 */ | |
| 482 | |
| 483 static OSStatus | |
| 484 menu_event_handler_func (EventHandlerCallRef event_handler_call_ref, | |
| 485 EventRef event_ref, | |
| 486 void *data) | |
| 487 { | |
| 488 UInt32 event_class = GetEventClass (event_ref); | |
| 489 UInt32 event_kind = GetEventKind (event_ref); | |
| 490 MenuRef menu_ref; | |
| 491 | |
| 492 switch (event_class) | |
| 493 { | |
| 494 case kEventClassCommand: | |
| 495 /* This is called when activating (is that the right GTK+ term?) | |
| 496 * a menu item. | |
| 497 */ | |
| 498 if (event_kind == kEventCommandProcess) | |
| 499 { | |
| 500 HICommand command; | |
| 501 OSStatus err; | |
| 502 | |
| 503 //g_print ("Menu: kEventClassCommand/kEventCommandProcess\n"); | |
| 504 | |
| 505 err = GetEventParameter (event_ref, kEventParamDirectObject, | |
| 506 typeHICommand, 0, | |
| 507 sizeof (command), 0, &command); | |
| 508 | |
| 509 if (err == noErr) | |
| 510 { | |
| 511 GtkWidget *widget = NULL; | |
| 512 | |
| 513 if (command.commandID == kHICommandQuit) | |
| 514 { | |
| 515 gtk_main_quit (); /* Just testing... */ | |
| 516 return noErr; | |
| 517 } | |
| 518 | |
| 519 /* Get any GtkWidget associated with the item. */ | |
| 520 err = GetMenuItemProperty (command.menu.menuRef, | |
| 521 command.menu.menuItemIndex, | |
| 522 GTK_QUARTZ_MENU_CREATOR, | |
| 523 GTK_QUARTZ_ITEM_WIDGET, | |
| 524 sizeof (widget), 0, &widget); | |
| 525 if (err == noErr && widget) | |
| 526 { | |
| 527 gtk_menu_item_activate (GTK_MENU_ITEM (widget)); | |
| 528 return noErr; | |
| 529 } | |
| 530 } | |
| 531 } | |
| 532 break; | |
| 533 | |
| 534 case kEventClassMenu: | |
| 535 GetEventParameter (event_ref, | |
| 536 kEventParamDirectObject, | |
| 537 typeMenuRef, | |
| 538 NULL, | |
| 539 sizeof (menu_ref), | |
| 540 NULL, | |
| 541 &menu_ref); | |
| 542 | |
| 543 switch (event_kind) | |
| 544 { | |
| 545 case kEventMenuTargetItem: | |
| 546 /* This is called when an item is selected (what is the | |
| 547 * GTK+ term? prelight?) | |
| 548 */ | |
| 549 //g_print ("kEventClassMenu/kEventMenuTargetItem\n"); | |
| 550 break; | |
| 551 | |
| 552 case kEventMenuOpening: | |
| 553 /* Is it possible to dynamically build the menu here? We | |
| 554 * can at least set visibility/sensitivity. | |
| 555 */ | |
| 556 //g_print ("kEventClassMenu/kEventMenuOpening\n"); | |
| 557 break; | |
| 558 | |
| 559 case kEventMenuClosed: | |
| 560 //g_print ("kEventClassMenu/kEventMenuClosed\n"); | |
| 561 break; | |
| 562 | |
| 563 default: | |
| 564 break; | |
| 565 } | |
| 566 | |
| 567 break; | |
| 568 | |
| 569 default: | |
| 570 break; | |
| 571 } | |
| 572 | |
| 573 return CallNextEventHandler (event_handler_call_ref, event_ref); | |
| 574 } | |
| 575 | |
| 576 static void | |
| 577 setup_menu_event_handler (void) | |
| 578 { | |
| 579 EventHandlerUPP menu_event_handler_upp; | |
| 580 EventHandlerRef menu_event_handler_ref; | |
| 581 const EventTypeSpec menu_events[] = { | |
| 582 { kEventClassCommand, kEventCommandProcess }, | |
| 583 { kEventClassMenu, kEventMenuTargetItem }, | |
| 584 { kEventClassMenu, kEventMenuOpening }, | |
| 585 { kEventClassMenu, kEventMenuClosed } | |
| 586 }; | |
| 587 | |
| 588 /* FIXME: We might have to install one per window? */ | |
| 589 | |
| 590 menu_event_handler_upp = NewEventHandlerUPP (menu_event_handler_func); | |
| 591 InstallEventHandler (GetApplicationEventTarget (), menu_event_handler_upp, | |
| 592 GetEventTypeCount (menu_events), menu_events, 0, | |
| 593 &menu_event_handler_ref); | |
| 594 | |
| 595 #if 0 | |
| 596 /* FIXME: Remove the handler with: */ | |
| 597 RemoveEventHandler(menu_event_handler_ref); | |
| 598 DisposeEventHandlerUPP(menu_event_handler_upp); | |
| 599 #endif | |
| 600 } | |
| 601 | |
| 602 static void | |
| 603 sync_menu_shell (GtkMenuShell *menu_shell, | |
| 604 MenuRef carbon_menu, | |
| 605 gboolean toplevel) | |
| 606 { | |
| 607 GList *children; | |
| 608 GList *l; | |
| 609 MenuItemIndex carbon_index = 1; | |
| 610 | |
| 611 carbon_menu_connect (GTK_WIDGET (menu_shell), carbon_menu); | |
| 612 | |
| 613 children = gtk_container_get_children (GTK_CONTAINER (menu_shell)); | |
| 614 | |
| 615 for (l = children; l; l = l->next) | |
| 616 { | |
| 617 GtkWidget *menu_item = l->data; | |
| 618 CarbonMenuItem *carbon_item; | |
| 619 | |
| 620 if (GTK_IS_TEAROFF_MENU_ITEM (menu_item)) | |
| 621 continue; | |
| 622 | |
| 623 if (toplevel && g_object_get_data (G_OBJECT (menu_item), "gtk-empty-menu-item")) | |
| 624 continue; | |
| 625 | |
| 626 carbon_item = carbon_menu_item_get (menu_item); | |
| 627 | |
| 628 if (carbon_item && carbon_item->index != carbon_index) | |
| 629 { | |
| 630 DeleteMenuItem (carbon_item->menu, | |
| 631 carbon_item->index); | |
| 632 carbon_item = NULL; | |
| 633 } | |
| 634 | |
| 635 if (!carbon_item) | |
| 636 { | |
| 637 GtkWidget *label = NULL; | |
| 638 const gchar *label_text; | |
| 639 CFStringRef cfstr = NULL; | |
| 640 MenuItemAttributes attributes = 0; | |
| 641 | |
| 642 label_text = get_menu_label_text (menu_item, &label); | |
| 643 if (label_text) | |
| 644 cfstr = CFStringCreateWithCString (NULL, label_text, | |
| 645 kCFStringEncodingUTF8); | |
| 646 | |
| 647 if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item)) | |
| 648 attributes |= kMenuItemAttrSeparator; | |
| 649 | |
| 650 if (!GTK_WIDGET_IS_SENSITIVE (menu_item)) | |
| 651 attributes |= kMenuItemAttrDisabled; | |
| 652 | |
| 653 if (!GTK_WIDGET_VISIBLE (menu_item)) | |
| 654 attributes |= kMenuItemAttrHidden; | |
| 655 | |
| 656 InsertMenuItemTextWithCFString (carbon_menu, cfstr, | |
| 657 carbon_index, | |
| 658 attributes, 0); | |
| 659 SetMenuItemProperty (carbon_menu, carbon_index, | |
| 660 GTK_QUARTZ_MENU_CREATOR, | |
| 661 GTK_QUARTZ_ITEM_WIDGET, | |
| 662 sizeof (menu_item), &menu_item); | |
| 663 | |
| 664 if (cfstr) | |
| 665 CFRelease (cfstr); | |
| 666 | |
| 667 carbon_item = carbon_menu_item_connect (menu_item, label, | |
| 668 carbon_menu, | |
| 669 carbon_index); | |
| 670 | |
| 671 if (GTK_IS_CHECK_MENU_ITEM (menu_item)) | |
| 672 carbon_menu_item_update_active (carbon_item, menu_item); | |
| 673 | |
| 674 carbon_menu_item_update_accel_closure (carbon_item, menu_item); | |
| 675 | |
| 676 if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item))) | |
| 677 carbon_menu_item_update_submenu (carbon_item, menu_item); | |
| 678 } | |
| 679 | |
| 680 carbon_index++; | |
| 681 } | |
| 682 | |
| 683 g_list_free (children); | |
| 684 } | |
| 685 | |
| 686 void | |
| 687 sync_menu_takeover_menu (GtkMenuShell *menu_shell) | |
| 688 { | |
| 689 MenuRef carbon_menubar; | |
| 690 | |
| 691 g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell)); | |
| 692 | |
| 693 if (carbon_menu_quark == 0) | |
| 694 carbon_menu_quark = g_quark_from_static_string ("CarbonMenu"); | |
| 695 | |
| 696 if (carbon_menu_item_quark == 0) | |
| 697 carbon_menu_item_quark = g_quark_from_static_string ("CarbonMenuItem"); | |
| 698 | |
| 699 CreateNewMenu (0 /*id*/, 0 /*options*/, &carbon_menubar); | |
| 700 SetRootMenu (carbon_menubar); | |
| 701 | |
| 702 setup_menu_event_handler (); | |
| 703 | |
| 704 sync_menu_shell (menu_shell, carbon_menubar, TRUE); | |
| 705 } | |
| 706 | |
| 707 #else | |
| 708 | |
| 709 void | |
| 710 sync_menu_takeover_menu (GtkMenuShell *menu_shell) | |
| 711 { | |
| 712 | |
| 713 } | |
| 714 | |
| 715 #endif |
