[gnome-globalmenu] Global and Local settings.



commit 7990db946e88cc23e12cd4f610ada0130eeeefda
Author: Yu Feng <rainwoodman gmail com>
Date:   Wed Dec 9 15:36:37 2009 -0500

    Global and Local settings.
    
    Global settings are the settings that affect the entire
    desktop.
    Local settings are the settings that affect the window.
    
    They share the same schema, defined in settings.vala
    Local settings override global settings according to
    the logic defined in local-settings.vala
    
    globalmenu-settings accepts -w commandline argument,
    to specify the windwo for which the local setting is modifed.

 applet/applet.vala                         |    4 +-
 globalmenu-plugin/info.vala                |   22 +---
 libsettings/Makefile.am                    |    4 +-
 libsettings/global-settings.vala           |   20 ++++
 libsettings/local-settings.vala            |   45 +++++++++
 libsettings/settings.vala                  |  142 ++++++++++++++++++++++------
 libsettings/tests/test-watch-settings.vala |    2 +-
 tools/globalmenu-settings.vala             |   12 ++-
 8 files changed, 199 insertions(+), 52 deletions(-)
---
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());



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