Skip to content

Commit

Permalink
Global and Local settings.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rainwoodman committed Dec 9, 2009
1 parent bf85f73 commit 7990db9
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 52 deletions.
4 changes: 2 additions & 2 deletions applet/applet.vala
Expand Up @@ -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();
Expand Down
22 changes: 6 additions & 16 deletions globalmenu-plugin/info.vala
Expand Up @@ -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();
Expand All @@ -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);
}

Expand All @@ -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() {
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
4 changes: 3 additions & 1 deletion libsettings/Makefile.am
Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions 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());
}
}
45 changes: 45 additions & 0 deletions 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());

}
}
142 changes: 113 additions & 29 deletions 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)]
Expand All @@ -49,29 +53,109 @@ 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);
}

public void pull() {
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() {
Expand Down
2 changes: 1 addition & 1 deletion 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");
Expand Down
12 changes: 9 additions & 3 deletions tools/globalmenu-settings.vala
Expand Up @@ -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}
};
Expand All @@ -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();
Expand All @@ -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());
Expand Down

0 comments on commit 7990db9

Please sign in to comment.