Skip to content

Commit

Permalink
Support multiple instances of menus with one registrar
Browse files Browse the repository at this point in the history
  • Loading branch information
rilian-la-te committed Apr 3, 2015
1 parent 8adea17 commit 47cc854
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 197 deletions.
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ vala_precompile(VALA_C appmenu
appmenu-desktop.vala
registrar.vala
menubar.vala
menu-widget.vala
menu-widget-dbusmenu.vala
menu-widget-menumodel.vala
${CMAKE_BINARY_DIR}/vapi/config.vala
Expand Down
44 changes: 44 additions & 0 deletions lib/menu-widget.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using GLib;

namespace Appmenu
{
public abstract class MenuWidget: Gtk.Box
{
public uint window_id {get; protected set construct;}
public Gtk.MenuBar menubar {get; protected set construct;}
public Gtk.MenuBar appmenu {get; internal set construct;}
private Gtk.CssProvider provider;
construct
{
provider = new Gtk.CssProvider();
File ruri = File.new_for_uri("resource://org/vala-panel/appmenu/appmenu.css");
try
{
provider.load_from_file(ruri);
this.notify.connect((pspec)=>{
if (pspec.name == "appmenu" && appmenu != null)
{
var context = appmenu.get_style_context();
context.add_provider(provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
context.add_class("-vala-panel-appmenu-private");
}
if (pspec.name == "menubar" && menubar != null)
{
var context = menubar.get_style_context();
context.add_provider(provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
context.add_class("-vala-panel-appmenu-private");
}
});
} catch (GLib.Error e) {}
}
}
public class MenuWidgetAny : MenuWidget
{
public MenuWidgetAny(Bamf.Application app)
{
appmenu = new BamfAppmenu(app);
this.add(appmenu);
this.show_all();
}
}
}
182 changes: 152 additions & 30 deletions lib/menubar.vala
Original file line number Diff line number Diff line change
@@ -1,48 +1,170 @@
using GLib;
using Gtk;

namespace Appmenu
{
public class ActiveMenu : Gtk.EventBox
public class AppMenuBar : Gtk.EventBox
{
private Registrar registrar;
private void on_bus_aquired (DBusConnection conn)
{
try {
registrar = new Registrar();
conn.register_object (REG_OBJECT, registrar);
connect_signals();
} catch (IOError e) {
stderr.printf ("Could not register service\n");
}
private static DBusMenuRegistrarProxy proxy;
private HashTable<uint,MenuWidget> menus;
private GenericSet<uint> desktop_menus;
private Bamf.Matcher matcher;
private ulong active_handler;
private ulong open_handler;
private ulong close_handler;
private ulong registered_handler;
private ulong unregistered_handler;
static construct
{
proxy = new DBusMenuRegistrarProxy();
}
public AppMenuBar()
{
Object();
}
construct
{
var gtksettings = this.get_settings();
gtksettings.gtk_shell_shows_app_menu = false;
gtksettings.gtk_shell_shows_menubar = false;
menus = new HashTable<uint,MenuWidget>(direct_hash,direct_equal);
desktop_menus = new GenericSet<uint>(direct_hash,direct_equal);
matcher = Bamf.Matcher.get_default();
registered_handler = proxy.window_registered.connect(register_menu_window);
unregistered_handler = proxy.window_unregistered.connect(unregister_menu_window);
active_handler = matcher.active_window_changed.connect(on_active_window_changed);
open_handler = matcher.view_opened.connect(on_window_opened);
close_handler = matcher.view_closed.connect(on_window_closed);
on_active_window_changed(matcher.get_active_window(),null);
foreach (var window in matcher.get_windows())
on_window_opened(window);
foreach (var app in matcher.get_running_applications())
on_window_opened(app);
}
private void on_name_lost(DBusConnection conn,string name)
~AppMenuBar()
{
print("Name is lost\n");
remove_menu();
proxy.disconnect(registered_handler);
proxy.disconnect(unregistered_handler);
matcher.disconnect(active_handler);
matcher.disconnect(open_handler);
matcher.disconnect(close_handler);
}
public void register_menu_window(uint window_id, string sender, ObjectPath menu_object_path)
{
Bamf.Application app = matcher.get_application_for_xid(window_id);
MenuWidget menu = new MenuWidgetDbusmenu(window_id,sender,menu_object_path,app);
if (menus.contains(window_id))
unregister_menu_window(window_id);
menus.insert(window_id,menu);
if (window_id == matcher.get_active_window().get_xid())
replace_menu(menu);
}
public void unregister_menu_window(uint window_id)
{
var menu = menus.lookup(window_id);
if (menu == null)
return;
if (this.get_child() == menu)
{
this.remove(menu);
this.child = show_dummy_menu();
}
desktop_menus.remove(window_id);
menus.remove(window_id);
menu.destroy();
}
private void remove_menu()
private void replace_menu(MenuWidget menu)
{
if (this.get_child() != null)
this.remove(this.get_child());
this.add(menu);
}
private void connect_signals()
private MenuWidget? show_dummy_menu()
{
this.add(registrar.active_menu);
this.registrar.notify["active-menu"].connect(()=>{
this.remove_menu();
if (registrar.active_menu != null)
this.add(registrar.active_menu);
});
MenuWidget? menu = null;
if (desktop_menus.length > 0)
{
desktop_menus.foreach((k)=>{
menu = menus.lookup(k);
if (menu != null)
return;
});
}
return menu;
}
private void on_window_opened(Bamf.View view)
{
if(view is Bamf.Window)
{
unowned Bamf.Window window = view as Bamf.Window;
if (window.get_window_type() == Bamf.WindowType.DESKTOP)
{
lookup_menu(window);
desktop_menus.add(window.get_xid());
}
}
}
private void on_window_closed(Bamf.View view)
{
if (view is Bamf.Window)
unregister_menu_window((view as Bamf.Window).get_xid());
}
public ActiveMenu()
private void on_active_window_changed(Bamf.Window? prev, Bamf.Window? next)
{
Gtk.Settings.get_default().gtk_shell_shows_app_menu = false;
Gtk.Settings.get_default().gtk_shell_shows_menubar = false;
Bus.own_name(BusType.SESSION, REG_IFACE, BusNameOwnerFlags.NONE,
on_bus_aquired,
()=>{},
on_name_lost);
if (this.get_child() != null)
this.get_child().hide();
unowned Bamf.Window win = next != null ? next : matcher.get_active_window();
replace_menu(lookup_menu(win));
if (this.get_child() != null)
this.get_child().show();
}
private MenuWidget lookup_menu(Bamf.Window? window)
{
MenuWidget? menu = null;
uint xid = 0;
while (window != null && menu == null)
{
xid = window.get_xid();
menu = menus.lookup(xid);
var app = matcher.get_application_for_window(window);
/* Appmenu hack, because BAMF does not always send a correct Application
* DBusMenu registration always happened BEFORE a BAMF register application.
*/
if (menu != null && menu.appmenu == null && app != null)
{
menu.appmenu = new BamfAppmenu(app);
menu.add(menu.appmenu);
menu.reorder_child(menu.appmenu,0);
menu.appmenu.show();
}
/* First look to see if we can get these from the
GMenuModel access */
if (menu == null)
{
var uniquename = window.get_utf8_prop ("_GTK_UNIQUE_BUS_NAME");
if (uniquename != null)
{
if (window.get_window_type() == Bamf.WindowType.DESKTOP)
menu = new MenuWidgetDesktop(app,window);
else
menu = new MenuWidgetMenumodel(app,window);
menus.insert(xid,menu);
return menu;
}
}
if (menu == null)
{
debug("Looking for parent window on XID %u", xid);
if (window.get_transient() == null && app != null)
{
menu = new MenuWidgetAny(app);
menus.insert(window.get_xid(),menu);
}
window = window.get_transient();
}
}
if (menu == null)
menu = show_dummy_menu();
return menu;
}
}
}
Loading

0 comments on commit 47cc854

Please sign in to comment.