diff --git a/applet/applet.vala b/applet/applet.vala index 3669b0a..6759f98 100644 --- a/applet/applet.vala +++ b/applet/applet.vala @@ -88,11 +88,11 @@ public class Applet : Panel.Applet { bgtype = get_background(out color, out pixmap); on_change_background(bgtype, color, pixmap); this.screen_changed += () => { - settings.attach(this.get_screen()); + settings.attach_to_screen(this.get_screen()); }; } - private Gnomenu.Settings settings = new Gnomenu.Settings(); + private Gnomenu.GlobalSettings settings = new Gnomenu.GlobalSettings(); private MenuBarBox menubars = new MenuBarBox(); private GlobalMenuBar main_menubar = new GlobalMenuBar(); private Gnomenu.MenuBar tiny_menubar = new Gnomenu.MenuBar(); diff --git a/globalmenu-plugin/info.vala b/globalmenu-plugin/info.vala index 64e5723..c7f5a7e 100644 --- a/globalmenu-plugin/info.vala +++ b/globalmenu-plugin/info.vala @@ -67,12 +67,14 @@ internal class MenuBarInfo { public MenuBarInfo (Gtk.MenuBar menubar) { this.menubar = menubar; MenuBarInfoFactory.get().associate(menubar, this); + settings = new Gnomenu.LocalSettings(); + settings.notify["show-local-menu"] += show_local_menu_changed; + settings.notify["show-menu-icons"] += show_menu_icons_changed; + menubar.weak_ref(menubar_disposed, this); menubar.hierarchy_changed += sync_toplevel; menubar.hierarchy_changed += sync_quirks; - menubar.screen_changed += sync_settings; - this.quirks_changed += sync_settings; sync_quirks(); sync_toplevel(); @@ -93,7 +95,6 @@ internal class MenuBarInfo { if(menubar == null) return; menubar.hierarchy_changed -= sync_toplevel; menubar.hierarchy_changed -= sync_quirks; - menubar.screen_changed -= sync_settings; menubar.weak_unref(menubar_disposed, this); } @@ -108,6 +109,7 @@ internal class MenuBarInfo { if(event_window == null) return; event_window.remove_filter(event_filter); event_window.weak_unref(event_window_disposed, this); + settings.attach_to_window(null); } public void queue_changed() { @@ -156,19 +158,6 @@ internal class MenuBarInfo { this.quirks_changed(old_quirks); } - private void sync_settings() { - if(quirks.has(QuirkType.REGULAR_WIDGET)) return; - var screen = menubar.get_screen(); - - if(settings == null) { - settings = new Gnomenu.Settings(); settings.notify["show-local-menu"] += show_local_menu_changed; - settings.notify["show-menu-icons"] += show_menu_icons_changed; - } - - if(settings.screen == screen) return; - else settings.attach(screen); - } - private void sync_toplevel() { release_toplevel(); if(menubar == null) toplevel = null; @@ -189,6 +178,7 @@ internal class MenuBarInfo { event_window.add_filter(event_filter); event_window.weak_ref(event_window_disposed, this); } + settings.attach_to_window(event_window); } private bool has_parent_type_name(string typename_pattern) { diff --git a/libsettings/Makefile.am b/libsettings/Makefile.am index 0fcded5..74edb3e 100644 --- a/libsettings/Makefile.am +++ b/libsettings/Makefile.am @@ -7,7 +7,9 @@ DEPS_FILE = globalmenu-settings.deps HEADER_FILE = globalmenu-settings.h VALASOURCES = \ - settings.vala + settings.vala \ + global-settings.vala \ + local-settings.vala \ $(NULL) noinst_LTLIBRARIES = libsettings.la diff --git a/libsettings/global-settings.vala b/libsettings/global-settings.vala new file mode 100644 index 0000000..3c9bfe5 --- /dev/null +++ b/libsettings/global-settings.vala @@ -0,0 +1,20 @@ +public class Gnomenu.GlobalSettings : Gnomenu.Settings { + public Gdk.Screen screen {get; private set;} + public new static Gnomenu.GlobalSettings get(Gdk.Screen screen) { + Gnomenu.GlobalSettings * settings = screen.get_data("globalmenu-settings"); + if(settings != null) return settings; + return new GlobalSettings(screen); + } + public GlobalSettings(Gdk.Screen? screen = null) { + attach_to_screen(screen); + screen.set_data_full("globalmenu-settings", this.ref(), g_object_unref); + } + + public void attach_to_screen(Gdk.Screen? screen) { + this.screen = screen; + if(this.screen == null) + attach_to_window(null); + else + attach_to_window(this.screen.get_root_window()); + } +} diff --git a/libsettings/local-settings.vala b/libsettings/local-settings.vala new file mode 100644 index 0000000..bd0d0b4 --- /dev/null +++ b/libsettings/local-settings.vala @@ -0,0 +1,45 @@ +public class Gnomenu.LocalSettings : Gnomenu.Settings { + public Gnomenu.GlobalSettings global {get; private set;} + + public override bool show_local_menu { + get { + if(global == null) return base.show_local_menu; + return global.show_local_menu || base.show_local_menu; + } + set { + base.show_local_menu = value; + } + } + public override bool show_menu_icons { + get { + if(global == null) return base.show_menu_icons; + return global.show_menu_icons && base.show_menu_icons; + } + set { + base.show_menu_icons = value; + } + } + public override int changed_notify_timeout { + get { + if(global == null) return base.changed_notify_timeout; + if(global.changed_notify_timeout < base.changed_notify_timeout) { + return global.changed_notify_timeout; + } + return base.changed_notify_timeout; + } + set { + base.changed_notify_timeout = value; + } + } + + public LocalSettings(Gdk.Window? window = null) { + attach_to_window(window); + this.show_local_menu = false; + } + public override void attach_to_window(Gdk.Window? window = null) { + base.attach_to_window(window); + if(window != null) + global = Gnomenu.GlobalSettings.get(window.get_screen()); + + } +} diff --git a/libsettings/settings.vala b/libsettings/settings.vala index d2ee9f7..1556645 100644 --- a/libsettings/settings.vala +++ b/libsettings/settings.vala @@ -1,34 +1,38 @@ public class Gnomenu.Settings : Object { - public Gdk.Screen screen {get; private set;} - private Gdk.Window window; + public Gdk.Window window {get; private set;} private Gdk.Atom atom = Gdk.Atom.intern("_NET_GLOBALMENU_SETTINGS", false); public KeyFile keyfile = new KeyFile(); - public bool show_local_menu { get; set; default = true; } - public bool show_menu_icons { get; set; default = true; } - public int changed_notify_timeout { get; set; default = 500; } + public virtual bool show_local_menu { get; set; default = true; } + public virtual bool show_menu_icons { get; set; default = true; } + public virtual int changed_notify_timeout { get; set; default = 500; } - public Settings(Gdk.Screen? screen = null) { - attach(screen); - } - public void attach(Gdk.Screen? screen) { + public static const string[] KEYS = { + "show-local-menu", + "show-menu-icons", + "changed-notify-timeout" + }; + + public virtual void attach_to_window(Gdk.Window? window) { if(this.window != null) { window.remove_filter(this.event_filter); } - this.screen = screen; - if(this.screen == null) return; - this.window = this.screen.get_root_window(); - assert(this.window != null); + if(window == null) { + return; + } + + this.window = window; this.window.add_filter(this.event_filter); var events = this.window.get_events(); this.window.set_events(events | Gdk.EventMask.PROPERTY_CHANGE_MASK); pull(); } + ~Settings() { - attach(null); + attach_to_window(null); } [CCode (instance_pos = -1)] @@ -49,10 +53,99 @@ public class Gnomenu.Settings : Object { return Gdk.FilterReturn.CONTINUE; } + private static bool is_tristate(bool boolean) { + return boolean != true && boolean != false; + } + + private bool load_boolean(string key) { + try { + return keyfile.get_boolean("GlobalMenu:Client", key); + } catch{ + return (bool) 30; + } + } + + private int load_int(string key) { + try { + return keyfile.get_integer("GlobalMenu:Client", key); + } catch{ + return -1; + } + } + private string? load_string(string key) { + try { + return keyfile.get_string("GlobalMenu:Client", key); + } catch{ + return null; + } + } + + private void save_boolean(string key, bool value) { + try { + if(!is_tristate(value)) { + keyfile.set_boolean("GlobalMenu:Client", key, value); + } else { + keyfile.remove_key("GlobalMenu:Client", key); + } + } catch{} + } + private void save_string(string key, string? value) { + try { + if(value != null) { + keyfile.set_string("GlobalMenu:Client", key, value); + } else { + keyfile.remove_key("GlobalMenu:Client", key); + } + } catch{} + } + private void save_int(string key, int value) { + keyfile.set_integer("GlobalMenu:Client", key, value); + } + + private void save_property(string key) { + weak ObjectClass klass = (ObjectClass) (this.get_class()); + weak ParamSpec pspec = klass.find_property(key); + Value value = Value(pspec.value_type); + this.get_property(key, ref value); + if(pspec.value_type == typeof(bool)) { + save_boolean(key, value.get_boolean()); + } else + if(pspec.value_type == typeof(string)) { + save_string(key, value.get_string()); + } else + if(pspec.value_type == typeof(int)) { + save_int(key, value.get_int()); + } else { + stdout.printf("unsupported value type `%s'.\n", + pspec.value_type.name()); + return; + } + } + + private void load_property(string key) { + weak ObjectClass klass = (ObjectClass) (this.get_class()); + weak ParamSpec pspec = klass.find_property(key); + Value value = Value(pspec.value_type); + if(pspec.value_type == typeof(bool)) { + value.set_boolean(load_boolean(key)); + } else + if(pspec.value_type == typeof(string)) { + value.set_string(load_string(key)); + } else + if(pspec.value_type == typeof(int)) { + value.set_int(load_int(key)); + } else { + stdout.printf("unsupported value type `%s'.\n", + pspec.value_type.name()); + return; + } + this.set_property(key, value); + } + public string to_string() { - keyfile.set_boolean("GlobalMenu:Client", "show-local-menu", this.show_local_menu); - keyfile.set_boolean("GlobalMenu:Client", "show-menu-icons", this.show_menu_icons); - keyfile.set_integer("GlobalMenu:Client", "changed-notify-timeout", this.changed_notify_timeout); + foreach(var key in KEYS) { + save_property(key); + } return keyfile.to_data(null); } @@ -60,18 +153,9 @@ public class Gnomenu.Settings : Object { var data = get_by_atom(atom); if(data == null) return; keyfile.load_from_data(data, data.length, KeyFileFlags.NONE); - try { - var value = keyfile.get_boolean("GlobalMenu:Client", "show-local-menu"); - this.show_local_menu = value; - } catch {} - try { - var value = keyfile.get_boolean("GlobalMenu:Client", "show-menu-icons"); - this.show_menu_icons = value; - } catch {} - try { - var value = keyfile.get_integer("GlobalMenu:Client", "changed-notify-timeout"); - this.changed_notify_timeout = value; - } catch {} + foreach(var key in KEYS) { + load_property(key); + } } public void push() { diff --git a/libsettings/tests/test-watch-settings.vala b/libsettings/tests/test-watch-settings.vala index 9841138..f65381f 100644 --- a/libsettings/tests/test-watch-settings.vala +++ b/libsettings/tests/test-watch-settings.vala @@ -1,7 +1,7 @@ public int main(string[] args) { Gtk.init(ref args); - Gnomenu.Settings settings = new Gnomenu.Settings(Gdk.Screen.get_default()); + Gnomenu.GlobalSettings settings = new Gnomenu.GlobalSettings(Gdk.Screen.get_default()); settings.notify["use-global-menu"] += () => { message("use-global-menu changed"); diff --git a/tools/globalmenu-settings.vala b/tools/globalmenu-settings.vala index b1f7f0b..e8592a4 100644 --- a/tools/globalmenu-settings.vala +++ b/tools/globalmenu-settings.vala @@ -2,9 +2,11 @@ private string[] pairs; private bool show = false; private ObjectClass klass = null; private Gnomenu.Settings settings = null; +private ulong xid = 0; private const OptionEntry[] options = { {"show", 's', 0, OptionArg.NONE, ref show, N_("Show current settings"), null }, + {"window", 'w', 0, OptionArg.INT, ref xid, N_("Access local settings of the window(XWin ID)"), null }, {"", 0, 0, OptionArg.STRING_ARRAY, ref pairs, N_("key/setting pairs"), "[ key settings ] ..."}, {null} }; @@ -26,7 +28,11 @@ N_("""A tool to modify Global Menu settings.""") context.parse(ref args); - settings = new Gnomenu.Settings(Gdk.Screen.get_default()); + if(xid == 0) { + settings = new Gnomenu.GlobalSettings(Gdk.Screen.get_default()); + } else { + settings = new Gnomenu.LocalSettings(Gdk.Window.foreign_new((Gdk.NativeWindow)xid)); + } if(show) { list_settings(); @@ -51,8 +57,8 @@ N_("""A tool to modify Global Menu settings.""") } private void list_settings() { - weak ParamSpec[] pspecs = klass.list_properties(); - foreach(weak ParamSpec ps in pspecs) { + foreach(var key in Gnomenu.Settings.KEYS) { + weak ParamSpec ps = klass.find_property(key); Value value = Value(ps.value_type); settings.get_property(ps.name, ref value); stdout.printf("%s (%s) = %s\n", ps.name, ps.value_type.name(), value.strdup_contents());