global (MacOS Style) menubar applet [initial patch]



Hello,
    Attached is an initial patch for the gnome global menu. In addition
to patching gnome-core, gnome-libs, and control-center, you also have
add the following to gnome-core/panel:

global-menu.c
global-menu.gnorba

Also you need to add to gnome-libs/idl, the patched gnome-panel.idl from
gnome-core/idl.

To use the patch, you must change an option in the control center (ui
prefs), and add the global menu to one of your panels via panel->Add to
panel->Global Menu.

I'm mainly looking for some feedback and further direction. There are
some problems with the patch currently. Most notably:

* Closing a gnome-app can really mess up the menu applet, I think this
is related to the behavior of gtksocket which the menu applet uses to
capture the menubar.
* It doesn't take advantage of Fitts's Law, I believe this might be due
to some spacing added by the panel around the menu applet.
* After using the menu the "parent" window looses focus. This might not
be desireable, if not I think I know how I could fix it.

Let me know what you think.

Mark
? gnome-libs-patch.diff
Index: libgnomeui/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-libs/libgnomeui/Makefile.am,v
retrieving revision 1.165.4.11
diff -r1.165.4.11 Makefile.am
29a30,39
> CORBA_SRCLIST = gnome-panel-stubs.c gnome-panel-skels.c gnome-panel-common.c gnome-panel.h
> 
> # try to make these get cleaned properly
> CLEANFILES += $(CORBA_SRCLIST) my_gnome_panel_idl
> 
> $(CORBA_SRCLIST): my_gnome_panel_idl
> 
> my_gnome_panel_idl: $(top_srcdir)/idl/gnome-panel.idl $(ORBIT_IDL)
> 	if $(ORBIT_IDL) ` GNOME_CONFIG@ --cflags idl` $< ; then touch my_gnome_panel_idl; else /bin/false; fi
> 
30a41
> 	$(CORBA_SRCLIST)		\
107a119
> 
267,268c279,281
< libgnomeui_la_LDFLAGS = -version-info 44:1:12 -rpath $(libdir)
< libgnomeui_la_LIBADD = $(LIBGNOMEUI_LIBS)
---
> libgnomeui_la_LDFLAGS = -version-info 44:1:12 -rpath $(libdir) -export-dynamic
> libgnomeui_la_LIBADD = $(LIBGNOMEUI_LIBS) \
> 	-lgnorba $(ORBIT_LIBS)
Index: libgnomeui/gnome-app.c
===================================================================
RCS file: /cvs/gnome/gnome-libs/libgnomeui/gnome-app.c,v
retrieving revision 1.94.4.3
diff -r1.94.4.3 gnome-app.c
20a21
> #include <gdk/gdkx.h>
21a23,24
> #include <sched.h>
> #include <orb/orbit.h>
29a33
> #include "libgnorba/gnorba.h"
32a37,38
> #include "gnome-panel.h"
> 
45a52
> 
133a141
> 	
215a224
> 
316a326,362
> static GNOME_GlobalMenu global_menu = CORBA_OBJECT_NIL;
> static gboolean showing_menu = FALSE;
> 
> static void
> show_global_menu (GnomeApp *app)
> {
> 	CORBA_Environment ev;
> 	GtkWidget *menu;
> 
> 	if (showing_menu)
> 		return;
> 
> 	CORBA_exception_init(&ev);
> 	menu = gtk_object_get_data (GTK_OBJECT (app), "menu");
> 	showing_menu = TRUE;
> 
>         global_menu = goad_server_activate_with_repo_id(NULL,
> 							  "IDL:GNOME/GlobalMenu:1.0",
> 							  GOAD_ACTIVATE_EXISTING_ONLY, NULL);
> 
> 	if (global_menu != CORBA_OBJECT_NIL) {
> 		if (!GTK_WIDGET_REALIZED(menu)) {
> 		        gtk_widget_realize (menu);
> 			g_print ("realized\n");
> 		}
> 		GNOME_GlobalMenu_show_menu (global_menu, 
> 					    GDK_WINDOW_XWINDOW (menu->window),
> 					    &ev);
> 	}
> 
> 	gtk_widget_show (menu);
> 
> 	CORBA_exception_free(&ev);
> 	showing_menu = FALSE;
> }
> 
> 
328a375
> 	GtkWidget *prevbar;
329a377
> 	GtkWidget *menu;
331a380
> 	GnomeMenubarPlacement placement = gnome_preferences_get_menubar_placement();
338a388,413
> 	prevbar = app->menubar;
> 	app->menubar = GTK_WIDGET (menubar);
> 	gtk_widget_show (GTK_WIDGET (menubar));
> 
> 	ag = gtk_object_get_data(GTK_OBJECT(app), "GtkAccelGroup");
> 	if (ag && !g_slist_find(gtk_accel_groups_from_object (GTK_OBJECT (app)), ag))
> 	        gtk_window_add_accel_group(GTK_WINDOW(app), ag);
> 
> 	if (placement == GNOME_MENUBAR_PLACEMENT_GLOBAL) {
> 		menu = gtk_object_get_data (GTK_OBJECT (app), "menu"); 
> 		if (!menu) {
> 			menu = gtk_window_new (GTK_WINDOW_TOPLEVEL);
> 			gtk_object_set_data (GTK_OBJECT (app), "menu", menu);
> 			gtk_container_add (GTK_CONTAINER (menu), GTK_WIDGET(menubar));
> 			gtk_signal_connect_after (GTK_OBJECT(app),
> 						  "focus_in_event",
> 						  show_global_menu,
> 						  NULL);
> 		} else {
> 			gtk_container_remove (GTK_CONTAINER (menu), GTK_WIDGET(prevbar));
> 			gtk_container_add (GTK_CONTAINER (menu), GTK_WIDGET(menubar));
> 		}
> 		return;
> 	}
> 
> 
349,353c424,427
< 	app->menubar = GTK_WIDGET (menubar);
< 
< 	/* To have menubar relief agree with the toolbar (and have the relief outside of
< 	 * smaller handles), substitute the dock item's relief for the menubar's relief,
< 	 * but don't change the size of the menubar in the process. */
---
> 	/* To have menubar relief agree with the toolbar (and have the
> 	 * relief outside of smaller handles), substitute the dock
> 	 * item's relief for the menubar's relief, but don't change
> 	 * the size of the menubar in the process. */
378d451
< 	gtk_widget_show (GTK_WIDGET (menubar));
380,383d452
< 
< 	ag = gtk_object_get_data(GTK_OBJECT(app), "GtkAccelGroup");
< 	if (ag && !g_slist_find(gtk_accel_groups_from_object (GTK_OBJECT (app)), ag))
< 	        gtk_window_add_accel_group(GTK_WINDOW(app), ag);
Index: libgnomeui/gnome-init.c
===================================================================
RCS file: /cvs/gnome/gnome-libs/libgnomeui/gnome-init.c,v
retrieving revision 1.100.4.6
diff -r1.100.4.6 gnome-init.c
47a48
> #include "libgnorba/gnorba.h"
425a427
>         CORBA_Environment ev;
469a472,474
> 
>         CORBA_exception_init (&ev);
>         gnorba_CORBA_init (&argc, argv, 0, &ev);
Index: libgnomeui/gnome-preferences.c
===================================================================
RCS file: /cvs/gnome/gnome-libs/libgnomeui/gnome-preferences.c,v
retrieving revision 1.31
diff -r1.31 gnome-preferences.c
49a50
>   GNOME_MENUBAR_PLACEMENT_LOCAL, /* Menubar Placement */
120a122,130
> #define MENUBAR_PLACEMENT_KEY      "MenubarPlacement"
> 
> static const gchar * const menubar_placements [] = {
>   "Local",
>   "Global"
> };
> 
> #define NUM_MENUBAR_PLACEMENTS 2
> 
270a281,289
>   s = gnome_config_get_string(MENUBAR_PLACEMENT_KEY);
> 
>   if ( ! enum_from_strings((int*) &settings->menubar_placement, s,
> 			   menubar_placements, NUM_MENUBAR_PLACEMENTS) ) {
>     g_warning("Didn't recognize menubar placement in libgnomeui config");
>   }  
> 
>   g_free(s);
> 
377a397,398
>   gnome_config_set_string(MENUBAR_PLACEMENT_KEY, 
> 			  menubar_placements[settings->menubar_placement]);
554a576,589
> }
> 
> 
> /* Placement of the menu bars, either global (contained in an applet)
>    or local (contained the application window). */
> GnomeMenubarPlacement
>                   gnome_preferences_get_menubar_placement   (void)
> {
>   return prefs.menubar_placement;
> }
> 
> void              gnome_preferences_set_menubar_placement   (GnomeMenubarPlacement p)
> {
>   prefs.menubar_placement = p;
Index: libgnomeui/gnome-preferences.h
===================================================================
RCS file: /cvs/gnome/gnome-libs/libgnomeui/gnome-preferences.h,v
retrieving revision 1.22
diff -r1.22 gnome-preferences.h
17a18,23
> /* Menu Placement */
> typedef enum {
>   GNOME_MENUBAR_PLACEMENT_LOCAL,
>   GNOME_MENUBAR_PLACEMENT_GLOBAL
> }GnomeMenubarPlacement;
> 
41a48
>   GnomeMenubarPlacement menubar_placement;
72a80,84
> /* Placement of the menu bars, either global (contained in an applet)
>    or local (contained the application window). */
> GnomeMenubarPlacement
>                   gnome_preferences_get_menubar_placement   (void);
> void              gnome_preferences_set_menubar_placement   (GnomeMenubarPlacement p);

? control-center-patch.diff
Index: capplets/ui-properties/ui-properties.c
===================================================================
RCS file: /cvs/gnome/control-center/capplets/ui-properties/ui-properties.c,v
retrieving revision 1.19.2.4
diff -r1.19.2.4 ui-properties.c
26d25
< #include <locale.h>
101a101,107
> static gchar const *menubar_placement_name [] = {
>   N_("Menu placement"),
>   N_("Inside application window"),
>   N_("Inside panel applet"),
>   NULL
> };
> 
119a126,129
>   {menubar_placement_name, NULL,
>    gnome_preferences_get_menubar_placement,
>    gnome_preferences_set_menubar_placement,
>    NULL},
568d577
< 	setlocale(LC_ALL, "");

#include <config.h>
#include <string.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gnome.h>

#include <libgnorba/gnorba.h>
#include <libgnorba/gnome-factory.h>

#include "gnome-panel.h"


static GNOME_Panel panel_client = CORBA_OBJECT_NIL;
static POA_GNOME_GlobalMenu		servant;
static PortableServer_ObjectId		*objid;
static PortableServer_POA		poa;
static GNOME_PanelSpot			pspot;
static GNOME_GlobalMenu		obj;
static guint32				winid;

const char		       *goad_id = "gnome_global_menu";

static GtkWidget *panel_plug;
static GtkWidget *menu_socket;

static void
server_applet_change_orient(PortableServer_Servant _servant,
			    const GNOME_Panel_OrientType orient,
			    CORBA_Environment *ev)
{
}

static void
server_applet_change_size(PortableServer_Servant _servant,
			  const CORBA_short size,
			  CORBA_Environment *ev)
{
}

static void
server_applet_do_callback(PortableServer_Servant _servant,
			  const CORBA_char * callback_name,
			  CORBA_Environment *ev)
{
}

/* this is the new session saving call and the one which should be used */
static void
server_applet_save_session(PortableServer_Servant _servant,
			   const CORBA_char * cfgpath,
			   const CORBA_char * globcfgpath,
			   const CORBA_unsigned_long cookie,
			   CORBA_Environment *ev)
{
	/*return_val of true would mean that the applet handeled the
	  session saving itself, therefore we pass the reverse to the
	  corba function */
	GNOME_PanelSpot_done_session_save(pspot,
					  TRUE, cookie, ev);
}

/* this is here just that if an applet uses the new lib with the old
   panel it will still work */
static CORBA_boolean
server_applet_session_save(PortableServer_Servant _servant,
			   const CORBA_char * cfgpath,
			   const CORBA_char * globcfgpath,
			   CORBA_Environment *ev)
{
  return TRUE;
}

static void
server_applet_back_change(PortableServer_Servant _servant,
			  const GNOME_Panel_BackInfoType *backing,
			  CORBA_Environment *ev)
{
}

static void
server_applet_draw(PortableServer_Servant _servant,
		   CORBA_Environment *ev)
{
}

static void
server_applet_set_tooltips_state(PortableServer_Servant _servant,
				 const CORBA_boolean enabled,
				 CORBA_Environment *ev)
{
}

static void
server_applet_change_position(PortableServer_Servant _servant,
			      CORBA_short x,
			      CORBA_short y,
			      CORBA_Environment *ev)
{

}

static CORBA_char *
server_applet__get_goad_id(PortableServer_Servant _servant,
			   CORBA_Environment *ev)
{
	return CORBA_string_dup(goad_id);
}

static void
server_applet_freeze_changes(PortableServer_Servant _servant,
			     CORBA_Environment *ev)
{
}

static void
server_applet_thaw_changes(PortableServer_Servant _servant,
			   CORBA_Environment *ev)
{
}

static void
server_global_menu_show_menu(PortableServer_Servant _servant,
			     const CORBA_unsigned_long xwin,
			     CORBA_Environment *ev)
{
  if (GTK_OBJECT_DESTROYED (GTK_OBJECT (menu_socket))) {
    gtk_container_remove (GTK_CONTAINER (panel_plug), menu_socket);
	menu_socket = gtk_socket_new ();
	gtk_container_add (GTK_CONTAINER (panel_plug), menu_socket);
	gtk_widget_show (menu_socket);
  }

  gtk_socket_steal (GTK_SOCKET (menu_socket), xwin);
}

static PortableServer_ServantBase__epv base_epv = {
	NULL, NULL, NULL
};


static POA_GNOME_Applet__epv applet_epv = {
  NULL,
  server_applet_change_orient,
  server_applet_do_callback,
  server_applet_session_save,
  server_applet_back_change,
  server_applet_set_tooltips_state,
  server_applet__get_goad_id,
  server_applet_draw,
  server_applet_save_session,
  server_applet_change_size,
  server_applet_change_position,
  server_applet_freeze_changes,
  server_applet_thaw_changes
};

static POA_GNOME_GlobalMenu__epv global_menu_epv = {
  NULL,
  server_global_menu_show_menu
};

static POA_GNOME_GlobalMenu__vepv vepv = { &base_epv, &applet_epv, &global_menu_epv};

static int
init (int argc, char **argv)
{
	CORBA_Environment ev;
	CORBA_ORB orb;
	CORBA_char *privcfg;
	CORBA_char *globcfg;
	GdkWindow *win;

	gnome_client_disable_master_connection ();
	CORBA_exception_init(&ev);
	orb = gnome_CORBA_init_with_popt_table(goad_id, VERSION,
					       &argc, argv,
					       NULL, 0, NULL,
					       GNORBA_INIT_SERVER_FUNC, &ev);
	if(ev._major != CORBA_NO_EXCEPTION) {
		CORBA_exception_free(&ev);
		return FALSE;
	}

	servant.vepv = &vepv;

	POA_GNOME_GlobalMenu__init(&servant, &ev);
	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

	poa = (PortableServer_POA)
		CORBA_ORB_resolve_initial_references(orb, "RootPOA", &ev);

	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

	PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(poa, &ev), &ev);

	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

	objid = PortableServer_POA_activate_object(poa, &servant, &ev);

	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

        obj = PortableServer_POA_servant_to_reference(poa, &servant,
							&ev);
	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

	goad_server_register(CORBA_OBJECT_NIL, obj, goad_id,
			     "server", &ev);
	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

	if (panel_client == CORBA_OBJECT_NIL) {
		panel_client =
			goad_server_activate_with_repo_id(NULL,
							  "IDL:GNOME/Panel:1.0",
							  0, NULL);

		if(panel_client == CORBA_OBJECT_NIL) {
			g_warning(_("Cannot activate a panel object"));
			return FALSE;
		}
	}


	pspot = GNOME_Panel_add_applet(panel_client, obj,
				       (char *)goad_id,
				       &privcfg,&globcfg,
				       &winid, &ev);
	
	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

	panel_plug = gtk_plug_new (winid);
	menu_socket = gtk_socket_new ();
	gtk_container_add (GTK_CONTAINER (panel_plug), menu_socket);
	gtk_widget_show (menu_socket);
	gtk_widget_show (panel_plug);
  
	GNOME_PanelSpot_register_us(pspot, &ev);

	if(ev._major) {
		g_warning(_("CORBA Exception"));
		CORBA_exception_free(&ev);
		return FALSE;
	}

	CORBA_exception_free(&ev);

	return TRUE;
}

static void
shutdown ()
{
	CORBA_Environment ev;

	CORBA_exception_init(&ev);

	PortableServer_POA_deactivate_object(poa, objid, &ev);
	CORBA_free(objid);

	goad_server_unregister(CORBA_OBJECT_NIL, goad_id, "server", &ev);

	CORBA_Object_release(pspot, &ev);
	CORBA_Object_release(obj, &ev);
	POA_GNOME_GlobalMenu__fini((PortableServer_Servant) &servant, &ev);
	CORBA_Object_release((CORBA_Object)poa, &ev);
	CORBA_exception_free(&ev);
}

int
main (int argc, char **argv)
{
	/* Initialize i18n */
	bindtextdomain (PACKAGE, GNOMELOCALEDIR);
	textdomain (PACKAGE);

	if (!init (argc, argv))
	  return 0;

	gtk_main ();

	shutdown ();

	return 0;
}

[gnome_global_menu]
type=exe
repo_id=IDL:GNOME/GlobalMenu:1.0
description=GNOME Global Menu
location_info=global-menu

? gnome-core-patch.diff
? panel/global-menu.c
? panel/global-menu.gnorba
? panel/global-menu
Index: idl/gnome-panel.idl
===================================================================
RCS file: /cvs/gnome/gnome-core/idl/gnome-panel.idl,v
retrieving revision 1.52
diff -r1.52 gnome-panel.idl
173a174,177
> 
>         interface GlobalMenu : Applet {
> 	  oneway void show_menu (in unsigned long xwin);
> 	};
Index: panel/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-core/panel/Makefile.am,v
retrieving revision 1.168.4.1
diff -r1.168.4.1 Makefile.am
20c20
< bin_PROGRAMS = panel gnome-panel-properties-capplet
---
> bin_PROGRAMS = panel gnome-panel-properties-capplet global-menu
162a163,173
> 
> global_menu_SOURCES = \
> 	global-menu.c \
> 	$(CORBA_SRCLIST)
> 
> global_menu_LDADD = $(GNOME_LIBDIR) $(GNORBA_LIBS) $(ORB_LIBS) \
> 	$(GNOMEUI_LIBS) $(INTLLIBS) @PIXBUF_LIBS@
> 
> global_menu_LDFLAGS=-export-dynamic
> 
> 
194c205,206
< 	title-item.gob
---
> 	title-item.gob			\
> 	global-menu.gnorba
224c236
< panelgnorba_DATA = panel.gnorba
---
> panelgnorba_DATA = panel.gnorba global-menu.gnorba
Index: panel/menu.c
===================================================================
RCS file: /cvs/gnome/gnome-core/panel/menu.c,v
retrieving revision 1.331.4.3
diff -r1.331.4.3 menu.c
997a998,1005
> static void
> add_global_menu_to_panel (GtkWidget *widget, gpointer data)
> {
> 	load_extern_applet("gnome_global_menu", NULL,
> 			   get_panel_from_menu_data(widget),
> 			   0, FALSE, FALSE);
> }
> 
3808a3817,3826
> 
> 	menuitem = gtk_menu_item_new ();
> 	gtk_widget_lock_accelerators (menuitem);
> 	setup_menuitem_try_pixmap (menuitem, 
> 				   "gnome-gmenu.png",
> 				   _("Global Menu"), SMALL_ICON_SIZE);
> 	gtk_menu_append (GTK_MENU (menu), menuitem);
> 	gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
> 			   GTK_SIGNAL_FUNC(add_global_menu_to_panel),NULL);
> 	setup_internal_applet_drag(menuitem, "LAUNCHER:ASK");



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]