From a1c05d93bbb3c1bdb0c0fed9d7110804037cfd55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 3 May 2015 07:25:37 +0200 Subject: Imported Upstream version 0.6.2 --- src/CMakeLists.txt | 1 - src/actionGroups/devicesGroup.vala | 4 +- src/actionGroups/groupRegistry.vala | 5 + src/actionGroups/menuGroup.vala | 2 +- src/actionGroups/sessionGroup.vala | 12 +- src/actionGroups/windowListGroup.vala | 32 ++- src/actionGroups/workspaceWindowListGroup.vala | 145 +++++++++++ src/actions/action.vala | 2 +- src/actions/appAction.vala | 2 +- src/actions/keyAction.vala | 2 +- src/actions/pieAction.vala | 2 +- src/actions/sigAction.vala | 6 +- src/actions/uriAction.vala | 2 +- src/deamon.vala | 45 ++-- src/gui/aboutWindow.vala | 3 +- src/gui/newSliceWindow.vala | 2 + src/gui/pieList.vala | 14 +- src/gui/pieOptionsWindow.vala | 315 ++++++++++++++++++++++++ src/gui/piePreviewAddSign.vala | 2 +- src/gui/piePreviewDeleteSign.vala | 2 +- src/gui/preferencesWindow.vala | 325 ++++++++++++++++--------- src/gui/renameWindow.vala | 109 --------- src/gui/settingsWindow.vala | 222 ----------------- src/gui/sliceTypeList.vala | 9 +- src/gui/themeList.vala | 17 +- src/gui/triggerSelectButton.vala | 6 +- src/gui/triggerSelectWindow.vala | 248 ------------------- src/pies/defaultConfig.vala | 24 +- src/renderers/pieRenderer.vala | 4 +- src/renderers/pieWindow.vala | 16 +- src/renderers/sliceRenderer.vala | 4 +- src/utilities/bindingManager.vala | 84 +++++-- src/utilities/color.vala | 21 ++ src/utilities/config.vala | 2 +- src/utilities/key.vala | 12 +- src/utilities/trigger.vala | 2 +- 36 files changed, 892 insertions(+), 813 deletions(-) create mode 100644 src/actionGroups/workspaceWindowListGroup.vala create mode 100644 src/gui/pieOptionsWindow.vala delete mode 100644 src/gui/renameWindow.vala delete mode 100644 src/gui/settingsWindow.vala delete mode 100644 src/gui/triggerSelectWindow.vala (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index af412a6..4d1194f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,7 +23,6 @@ vala_precompile( PACKAGES ${VALA_PKGS} OPTIONS - --vapidir=${CMAKE_SOURCE_DIR}/vapi/ --thread ${DEFINES} ) diff --git a/src/actionGroups/devicesGroup.vala b/src/actionGroups/devicesGroup.vala index 1078296..e18f4c0 100644 --- a/src/actionGroups/devicesGroup.vala +++ b/src/actionGroups/devicesGroup.vala @@ -33,7 +33,7 @@ public class DevicesGroup : ActionGroup { public static GroupRegistry.TypeDescription register() { var description = new GroupRegistry.TypeDescription(); description.name = _("Group: Devices"); - description.icon = "harddrive"; + description.icon = "drive-harddisk"; description.description = _("Shows a Slice for each plugged in devices, like USB-Sticks."); description.id = "devices"; return description; @@ -82,7 +82,7 @@ public class DevicesGroup : ActionGroup { private void load() { // add root device - this.add_action(new UriAction(_("Root"), "harddrive", "file:///")); + this.add_action(new UriAction(_("Root"), "drive-harddisk", "file:///")); // add all other devices foreach(var mount in this.monitor.get_mounts()) { diff --git a/src/actionGroups/groupRegistry.vala b/src/actionGroups/groupRegistry.vala index ca0dc4d..ebf34ba 100644 --- a/src/actionGroups/groupRegistry.vala +++ b/src/actionGroups/groupRegistry.vala @@ -72,6 +72,10 @@ public class GroupRegistry : GLib.Object { type_description = WindowListGroup.register(); types.add(typeof(WindowListGroup).name()); descriptions.set(typeof(WindowListGroup).name(), type_description); + + type_description = WorkspaceWindowListGroup.register(); + types.add(typeof(WorkspaceWindowListGroup).name()); + descriptions.set(typeof(WorkspaceWindowListGroup).name(), type_description); } ///////////////////////////////////////////////////////////////////// @@ -85,6 +89,7 @@ public class GroupRegistry : GLib.Object { case "menu": return new MenuGroup(parent_id); case "session": return new SessionGroup(parent_id); case "window_list": return new WindowListGroup(parent_id); + case "workspace_window_list": return new WorkspaceWindowListGroup(parent_id); } return null; diff --git a/src/actionGroups/menuGroup.vala b/src/actionGroups/menuGroup.vala index 7a1e344..ccb5407 100644 --- a/src/actionGroups/menuGroup.vala +++ b/src/actionGroups/menuGroup.vala @@ -33,7 +33,7 @@ public class MenuGroup : ActionGroup { public static GroupRegistry.TypeDescription register() { var description = new GroupRegistry.TypeDescription(); description.name = _("Group: Main menu"); - description.icon = "gnome-main-menu"; + description.icon = "start-here"; description.description = _("Displays your main menu structure."); description.id = "menu"; return description; diff --git a/src/actionGroups/sessionGroup.vala b/src/actionGroups/sessionGroup.vala index 7b989a6..42afafc 100644 --- a/src/actionGroups/sessionGroup.vala +++ b/src/actionGroups/sessionGroup.vala @@ -33,7 +33,7 @@ public class SessionGroup : ActionGroup { public static GroupRegistry.TypeDescription register() { var description = new GroupRegistry.TypeDescription(); description.name = _("Group: Session Control"); - description.icon = "gnome-logout"; + description.icon = "system-log-out"; description.description = _("Shows a Slice for Shutdown, Reboot, and Hibernate."); description.id = "session"; return description; @@ -57,14 +57,14 @@ public class SessionGroup : ActionGroup { // iface = GLib.Bus.get_proxy_sync(GLib.BusType.SESSION, "org.kde.ksmserver", "/KSMServer"); // iface = GLib.Bus.get_proxy_sync(GLib.BusType.SESSION, "org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager"); - this.add_action(new AppAction(_("Shutdown"), "gnome-shutdown", - "dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.RequestShutdown")); + this.add_action(new AppAction(_("Shutdown"), "system-shutdown", + "dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.Shutdown")); - this.add_action(new AppAction(_("Logout"), "gnome-session-logout", + this.add_action(new AppAction(_("Logout"), "system-log-out", "dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.Logout uint32:1")); - this.add_action(new AppAction(_("Reboot"), "gnome-session-reboot", - "dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.RequestReboot")); + this.add_action(new AppAction(_("Reboot"), "view-refresh", + "dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.Reboot")); } // TODO: check for available interfaces --- these may work too: diff --git a/src/actionGroups/windowListGroup.vala b/src/actionGroups/windowListGroup.vala index a2dc19c..1560f5f 100644 --- a/src/actionGroups/windowListGroup.vala +++ b/src/actionGroups/windowListGroup.vala @@ -32,7 +32,7 @@ public class WindowListGroup : ActionGroup { public static GroupRegistry.TypeDescription register() { var description = new GroupRegistry.TypeDescription(); description.name = _("Group: Window List"); - description.icon = "gnome-window-manager"; + description.icon = "preferences-system-windows"; description.description = _("Shows a Slice for each of your opened Windows. Almost like Alt-Tab."); description.id = "window_list"; return description; @@ -94,21 +94,37 @@ public class WindowListGroup : ActionGroup { (bamf_app == null) ? application.get_icon_name().down() : bamf_app.get_icon(), "%lu".printf(window.get_xid()) ); - action.activated.connect(() => { + action.activated.connect((time_stamp) => { Wnck.Screen.get_default().force_update(); var xid = (X.Window)uint64.parse(action.real_command); var win = Wnck.Window.get(xid); - var time = Gtk.get_current_event_time(); - if (win.get_workspace() != null - && win.get_workspace() != win.get_screen().get_active_workspace()) - win.get_workspace().activate(time); + if (win.get_workspace() != null) { + //select the workspace + if (win.get_workspace() != win.get_screen().get_active_workspace()) + win.get_workspace().activate(time_stamp); + + //select the viewport inside the wprkspace + if (!win.is_in_viewport(win.get_workspace()) ) { + int xp, yp, widthp, heightp, scx, scy, nx, ny, wx, wy; + win.get_geometry (out xp, out yp, out widthp, out heightp); + scx= win.get_screen().get_width(); + scy= win.get_screen().get_height(); + wx= win.get_workspace().get_viewport_x(); + wy= win.get_workspace().get_viewport_y(); + if (scx > 0 && scy > 0) { + nx= ((wx+xp) / scx) * scx; + ny= ((wy+yp) / scy) * scy; + win.get_screen().move_viewport(nx, ny); + } + } + } if (win.is_minimized()) - win.unminimize(time); + win.unminimize(time_stamp); - win.activate_transient(time); + win.activate_transient(time_stamp); }); this.add_action(action); } diff --git a/src/actionGroups/workspaceWindowListGroup.vala b/src/actionGroups/workspaceWindowListGroup.vala new file mode 100644 index 0000000..42a4863 --- /dev/null +++ b/src/actionGroups/workspaceWindowListGroup.vala @@ -0,0 +1,145 @@ +///////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011-2015 by Simon Schneegans +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +///////////////////////////////////////////////////////////////////////// + +namespace GnomePie { + +///////////////////////////////////////////////////////////////////// +/// This group displays a list of all running application windows of +/// the current workspace. +///////////////////////////////////////////////////////////////////// + +public class WorkspaceWindowListGroup : ActionGroup { + + ///////////////////////////////////////////////////////////////////// + /// Used to register this type of ActionGroup. It sets the display + /// name for this ActionGroup, it's icon name and the string used in + /// the pies.conf file for this kind of ActionGroups. + ///////////////////////////////////////////////////////////////////// + + public static GroupRegistry.TypeDescription register() { + var description = new GroupRegistry.TypeDescription(); + description.name = _("Group: Window List for current workspace"); + description.icon = "preferences-system-windows"; + description.description = _("Shows a Slice for each of your opened windows on the current workspace."); + description.id = "workspace_window_list"; + return description; + } + + ///////////////////////////////////////////////////////////////////// + /// Two members needed to avoid useless, frequent changes of the + /// stored Actions. + ///////////////////////////////////////////////////////////////////// + + private bool changing = false; + private bool changed_again = false; + + private Wnck.Screen screen; + + ///////////////////////////////////////////////////////////////////// + /// C'tor, initializes all members. + ///////////////////////////////////////////////////////////////////// + + public WorkspaceWindowListGroup(string parent_id) { + GLib.Object(parent_id : parent_id); + } + + ///////////////////////////////////////////////////////////////////// + /// Loads all windows. + ///////////////////////////////////////////////////////////////////// + + construct { + this.screen = Wnck.Screen.get_default(); + + this.screen.window_opened.connect(reload); + this.screen.window_closed.connect(reload); + this.screen.active_workspace_changed.connect(reload); + + this.load(); + } + + ///////////////////////////////////////////////////////////////////// + /// Loads all currently opened windows and creates actions for them. + ///////////////////////////////////////////////////////////////////// + + private void load() { + unowned GLib.List windows = this.screen.get_windows(); + + var matcher = Bamf.Matcher.get_default(); + + foreach (var window in windows) { + if (window.get_window_type() == Wnck.WindowType.NORMAL + && !window.is_skip_pager() && !window.is_skip_tasklist() + && window.get_workspace() != null + && window.get_workspace() == this.screen.get_active_workspace()) { + + var application = window.get_application(); + var bamf_app = matcher.get_application_for_xid((uint32)window.get_xid()); + + string name = window.get_name(); + + if (name.length > 30) + name = name.substring(0, 30) + "..."; + + var action = new SigAction( + name, + (bamf_app == null) ? application.get_icon_name().down() : bamf_app.get_icon(), + "%lu".printf(window.get_xid()) + ); + action.activated.connect((time_stamp) => { + Wnck.Screen.get_default().force_update(); + + var xid = (X.Window)uint64.parse(action.real_command); + var win = Wnck.Window.get(xid); + + if (win.is_minimized()) + win.unminimize(time_stamp); + + win.activate_transient(time_stamp); + }); + this.add_action(action); + } + } + } + + ///////////////////////////////////////////////////////////////////// + /// Reloads all running applications. + ///////////////////////////////////////////////////////////////////// + + private void reload() { + // avoid too frequent changes... + if (!this.changing) { + this.changing = true; + Timeout.add(500, () => { + if (this.changed_again) { + this.changed_again = false; + return true; + } + + // reload + this.delete_all(); + this.load(); + + this.changing = false; + return false; + }); + } else { + this.changed_again = true; + } + } +} + +} diff --git a/src/actions/action.vala b/src/actions/action.vala index 91fc448..1e6437e 100644 --- a/src/actions/action.vala +++ b/src/actions/action.vala @@ -71,7 +71,7 @@ public abstract class Action : GLib.Object { /// This one is called, when the user activates the Slice. ///////////////////////////////////////////////////////////////////// - public abstract void activate(); + public abstract void activate(uint32 time_stamp); } } diff --git a/src/actions/appAction.vala b/src/actions/appAction.vala index 859baf8..e1ca3a2 100644 --- a/src/actions/appAction.vala +++ b/src/actions/appAction.vala @@ -63,7 +63,7 @@ public class AppAction : Action { /// Launches the desired command. ///////////////////////////////////////////////////////////////////// - public override void activate() { + public override void activate(uint32 time_stamp) { try{ var item = GLib.AppInfo.create_from_commandline(this.real_command, null, GLib.AppInfoCreateFlags.NONE); item.launch(null, null); diff --git a/src/actions/keyAction.vala b/src/actions/keyAction.vala index 68a2ec1..cbe8b6e 100644 --- a/src/actions/keyAction.vala +++ b/src/actions/keyAction.vala @@ -73,7 +73,7 @@ public class KeyAction : Action { /// Presses the desired key. ///////////////////////////////////////////////////////////////////// - public override void activate() { + public override void activate(uint32 time_stamp) { key.press(); } } diff --git a/src/actions/pieAction.vala b/src/actions/pieAction.vala index 8069ff3..931c9d3 100644 --- a/src/actions/pieAction.vala +++ b/src/actions/pieAction.vala @@ -95,7 +95,7 @@ public class PieAction : Action { /// Opens the desired Pie. ///////////////////////////////////////////////////////////////////// - public override void activate() { + public override void activate(uint32 time_stamp) { PieManager.open_pie(real_command); } } diff --git a/src/actions/sigAction.vala b/src/actions/sigAction.vala index 4eebbca..bf9374d 100644 --- a/src/actions/sigAction.vala +++ b/src/actions/sigAction.vala @@ -29,7 +29,7 @@ public class SigAction : Action { /// This signal is emitted on activation. ///////////////////////////////////////////////////////////////////// - public signal void activated(); + public signal void activated(uint32 time_stamp); ///////////////////////////////////////////////////////////////////// /// This may store something useful. @@ -55,8 +55,8 @@ public class SigAction : Action { /// Emits the signal on activation. ///////////////////////////////////////////////////////////////////// - public override void activate() { - this.activated(); + public override void activate(uint32 time_stamp) { + this.activated(time_stamp); } } diff --git a/src/actions/uriAction.vala b/src/actions/uriAction.vala index dfc1029..d0a41b8 100644 --- a/src/actions/uriAction.vala +++ b/src/actions/uriAction.vala @@ -65,7 +65,7 @@ public class UriAction : Action { /// Opens the default application for the URI. ///////////////////////////////////////////////////////////////////// - public override void activate() { + public override void activate(uint32 time_stamp) { try{ GLib.AppInfo.launch_default_for_uri(real_command, null); } catch (Error e) { diff --git a/src/deamon.vala b/src/deamon.vala index ff7e764..a35e666 100644 --- a/src/deamon.vala +++ b/src/deamon.vala @@ -31,12 +31,19 @@ public class Deamon : GLib.Object { public static string version; + ///////////////////////////////////////////////////////////////////// + /// Varaibles set by the commend line parser. + ///////////////////////////////////////////////////////////////////// + + public static bool header_bar = false; + public static bool stack_switcher = false; + ///////////////////////////////////////////////////////////////////// /// The beginning of everything. ///////////////////////////////////////////////////////////////////// public static int main(string[] args) { - version = "0.6.1"; + version = "0.6.2"; Logger.init(); Gtk.init(ref args); @@ -71,6 +78,10 @@ public class Deamon : GLib.Object { "Open the Pie with the given ID", "ID" }, { "reset", 'r', 0, GLib.OptionArg.NONE, out reset, "Reset all options to default values" }, + { "header-bar", 'b', 0, GLib.OptionArg.NONE, out header_bar, + "Uses the new GTK.HeaderBar" }, + { "stack-switcher", 's', 0, GLib.OptionArg.NONE, out stack_switcher, + "Uses the new GTK.StackSwitcher" }, { null } }; @@ -102,24 +113,25 @@ public class Deamon : GLib.Object { Intl.bindtextdomain ("gnomepie", Paths.locales); Intl.textdomain ("gnomepie"); - // init toolkits and static stuff - ActionRegistry.init(); - GroupRegistry.init(); + if (handle_command_line(args, false)) { + + // init toolkits and static stuff + ActionRegistry.init(); + GroupRegistry.init(); - PieManager.init(); - Icon.init(); + PieManager.init(); + Icon.init(); - // launch the indicator - this.indicator = new Indicator(); + // launch the indicator + this.indicator = new Indicator(); - // connect SigHandlers - Posix.signal(Posix.SIGINT, sig_handler); - Posix.signal(Posix.SIGTERM, sig_handler); + // connect SigHandlers + Posix.signal(Posix.SIGINT, sig_handler); + Posix.signal(Posix.SIGTERM, sig_handler); - // finished loading... so run the prog! - message("Started happily..."); + // finished loading... so run the prog! + message("Started happily..."); - if (handle_command_line(args, false)) { Gtk.main(); } }); @@ -143,10 +155,9 @@ public class Deamon : GLib.Object { private bool handle_command_line(string[] args, bool show_preferences) { // create command line options - var context = new GLib.OptionContext(""); - context.set_help_enabled(true); + var context = new GLib.OptionContext(" - the pie menu for linux"); context.add_main_entries(options, null); - context.add_group(Gtk.get_option_group (false)); + context.add_group(Gtk.get_option_group(false)); try { context.parse(ref args); diff --git a/src/gui/aboutWindow.vala b/src/gui/aboutWindow.vala index cf1ce8a..b4d1e5e 100644 --- a/src/gui/aboutWindow.vala +++ b/src/gui/aboutWindow.vala @@ -32,7 +32,8 @@ public class AboutWindow: Gtk.AboutDialog { string[] devs = { "Simon Schneegans ", "Gabriel Dubatti ", - "Francesco Piccinno " + "Francesco Piccinno ", + "György Balló " }; string[] artists = { "Simon Schneegans " diff --git a/src/gui/newSliceWindow.vala b/src/gui/newSliceWindow.vala index a17c819..6066e57 100644 --- a/src/gui/newSliceWindow.vala +++ b/src/gui/newSliceWindow.vala @@ -122,6 +122,7 @@ public class NewSliceWindow : GLib.Object { switch (type) { case "bookmarks": case "clipboard": case "devices": case "menu": case "session": case "window_list": + case "workspace_window_list": this.no_options_box.show(); this.set_icon(icon); break; @@ -318,6 +319,7 @@ public class NewSliceWindow : GLib.Object { case "menu": group = new MenuGroup(this.current_id); break; case "session": group = new SessionGroup(this.current_id); break; case "window_list": group = new WindowListGroup(this.current_id); break; + case "workspace_window_list": group = new WorkspaceWindowListGroup(this.current_id); break; case "app": group = new ActionGroup(this.current_id); diff --git a/src/gui/pieList.vala b/src/gui/pieList.vala index 29c0a1e..77f833b 100644 --- a/src/gui/pieList.vala +++ b/src/gui/pieList.vala @@ -28,6 +28,7 @@ class PieList : Gtk.TreeView { ///////////////////////////////////////////////////////////////////// public signal void on_select(string id); + public signal void on_activate(); ///////////////////////////////////////////////////////////////////// /// Stores the data internally. @@ -65,7 +66,7 @@ class PieList : Gtk.TreeView { this.data.set_sort_column_id(DataPos.NAME, Gtk.SortType.ASCENDING); this.set_model(this.data); - this.set_headers_visible(false); + this.set_headers_visible(true); this.set_grid_lines(Gtk.TreeViewGridLines.NONE); this.width_request = 170; this.set_enable_search(false); @@ -73,12 +74,14 @@ class PieList : Gtk.TreeView { this.set_events(Gdk.EventMask.POINTER_MOTION_MASK); var main_column = new Gtk.TreeViewColumn(); + main_column.title = _("Pies"); var icon_render = new Gtk.CellRendererPixbuf(); icon_render.xpad = 4; icon_render.ypad = 4; main_column.pack_start(icon_render, false); var name_render = new Gtk.CellRendererText(); + name_render.xpad = 6; name_render.ellipsize = Pango.EllipsizeMode.END; name_render.ellipsize_set = true; main_column.pack_start(name_render, true); @@ -86,7 +89,7 @@ class PieList : Gtk.TreeView { base.append_column(main_column); main_column.add_attribute(icon_render, "pixbuf", DataPos.ICON); - main_column.add_attribute(name_render, "text", DataPos.NAME); + main_column.add_attribute(name_render, "markup", DataPos.NAME); // setup drag'n'drop Gtk.TargetEntry uri_source = {"text/uri-list", 0, 0}; @@ -101,6 +104,10 @@ class PieList : Gtk.TreeView { this.last_hover = 0; }); + this.row_activated.connect(() => { + this.on_activate(); + }); + this.get_selection().changed.connect(() => { Gtk.TreeIter active; if (this.get_selection().get_selected(null, out active)) { @@ -177,7 +184,8 @@ class PieList : Gtk.TreeView { var icon = new Icon(pie.icon, 24); this.data.set(last, DataPos.ICON, icon.to_pixbuf(), DataPos.ICON_NAME, pie.icon, - DataPos.NAME, pie.name, + DataPos.NAME,GLib.Markup.escape_text(pie.name) + "\n" + + "" + PieManager.get_accelerator_label_of(pie.id) + "", DataPos.ID, pie.id); } } diff --git a/src/gui/pieOptionsWindow.vala b/src/gui/pieOptionsWindow.vala new file mode 100644 index 0000000..2f9cadf --- /dev/null +++ b/src/gui/pieOptionsWindow.vala @@ -0,0 +1,315 @@ +///////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011-2015 by Simon Schneegans +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +///////////////////////////////////////////////////////////////////////// + +namespace GnomePie { + +///////////////////////////////////////////////////////////////////////// +/// This window allows the selection of a hotkey. It is returned in form +/// of a Trigger. Therefore it can be either a keyboard driven hotkey or +/// a mouse based hotkey. +///////////////////////////////////////////////////////////////////////// + +public class PieOptionsWindow : GLib.Object { + + ///////////////////////////////////////////////////////////////////// + /// This signal is emitted when the user selects a new hot key. + ///////////////////////////////////////////////////////////////////// + + public signal void on_ok(Trigger trigger, string pie_name, string icon_name); + + ///////////////////////////////////////////////////////////////////// + /// Some private members which are needed by other methods. + ///////////////////////////////////////////////////////////////////// + + private Gtk.Dialog window; + private Gtk.CheckButton turbo; + private Gtk.CheckButton delayed; + private Gtk.CheckButton centered; + private Gtk.CheckButton warp; + private Gtk.RadioButton rshape[10]; + private TriggerSelectButton trigger_button; + private Gtk.Entry name_entry = null; + private Gtk.Button? icon_button = null; + private Gtk.Image? icon = null; + private Gtk.Label? pie_id = null; + + private IconSelectWindow? icon_window = null; + + ///////////////////////////////////////////////////////////////////// + /// The currently configured trigger. + ///////////////////////////////////////////////////////////////////// + + private Trigger trigger = null; + + ///////////////////////////////////////////////////////////////////// + /// The trigger which was active when this window was opened. It is + /// stored in order to check whether anything has changed when the + /// user clicks on OK. + ///////////////////////////////////////////////////////////////////// + + private Trigger original_trigger = null; + + ///////////////////////////////////////////////////////////////////// + /// Stores the current icon name of the pie. + ///////////////////////////////////////////////////////////////////// + + private string icon_name = ""; + + ///////////////////////////////////////////////////////////////////// + /// Stores the id of the current pie. + ///////////////////////////////////////////////////////////////////// + + private string id = ""; + + ///////////////////////////////////////////////////////////////////// + /// Radioboxes call toggled() twice per selection change. + /// This flag is used to discard one of the two notifications. + ///////////////////////////////////////////////////////////////////// + + private static int notify_toggle = 0; + + ///////////////////////////////////////////////////////////////////// + /// C'tor, constructs a new PieOptionsWindow. + ///////////////////////////////////////////////////////////////////// + + public PieOptionsWindow() { + try { + + Gtk.Builder builder = new Gtk.Builder(); + + builder.add_from_file (Paths.ui_files + "/pie_options.ui"); + + this.window = builder.get_object("window") as Gtk.Dialog; + this.trigger_button = new TriggerSelectButton(true); + this.trigger_button.show(); + + this.trigger_button.on_select.connect((trigger) => { + this.trigger = new Trigger.from_values( + trigger.key_sym, + trigger.modifiers, + trigger.with_mouse, + this.turbo.active, + this.delayed.active, + this.centered.active, + this.warp.active, + this.get_radio_shape() + ); + }); + + (builder.get_object("trigger-box") as Gtk.Box).pack_start(this.trigger_button, true, true); + + (builder.get_object("ok-button") as Gtk.Button).clicked.connect(this.on_ok_button_clicked); + (builder.get_object("cancel-button") as Gtk.Button).clicked.connect(this.on_cancel_button_clicked); + + this.turbo = builder.get_object("turbo-check") as Gtk.CheckButton; + this.turbo.toggled.connect(this.on_check_toggled); + + this.delayed = builder.get_object("delay-check") as Gtk.CheckButton; + this.delayed.toggled.connect(this.on_check_toggled); + + this.centered = builder.get_object("center-check") as Gtk.CheckButton; + this.centered.toggled.connect(this.on_check_toggled); + + this.warp = builder.get_object("warp-check") as Gtk.CheckButton; + this.warp.toggled.connect(this.on_check_toggled); + + for (int i= 0; i < 10; i++) { + this.rshape[i] = builder.get_object("rshape%d".printf(i)) as Gtk.RadioButton; + this.rshape[i].toggled.connect(this.on_radio_toggled); + } + + this.name_entry = builder.get_object("name-entry") as Gtk.Entry; + this.name_entry.activate.connect(this.on_ok_button_clicked); + + this.pie_id = builder.get_object("pie-id") as Gtk.Label; + + this.icon = builder.get_object("icon") as Gtk.Image; + this.icon_button = builder.get_object("icon-button") as Gtk.Button; + this.icon_button.clicked.connect(on_icon_button_clicked); + + this.window.delete_event.connect(this.window.hide_on_delete); + + } catch (GLib.Error e) { + error("Could not load UI: %s\n", e.message); + } + } + + ///////////////////////////////////////////////////////////////////// + /// Sets the parent window, in order to make this window stay in + /// front. + ///////////////////////////////////////////////////////////////////// + + public void set_parent(Gtk.Window parent) { + this.window.set_transient_for(parent); + } + + ///////////////////////////////////////////////////////////////////// + /// Displays the window on the screen. + ///////////////////////////////////////////////////////////////////// + + public void show() { + this.window.show_all(); + } + + ///////////////////////////////////////////////////////////////////// + /// Initilizes all members to match the Trigger of the Pie with the + /// given ID. + ///////////////////////////////////////////////////////////////////// + + public void set_pie(string id) { + var trigger = new Trigger.from_string(PieManager.get_accelerator_of(id)); + var pie = PieManager.all_pies[id]; + + this.id = id; + + this.turbo.active = trigger.turbo; + this.delayed.active = trigger.delayed; + this.centered.active = trigger.centered; + this.warp.active = trigger.warp; + this.set_radio_shape( trigger.shape ); + this.original_trigger = trigger; + this.trigger = trigger; + this.name_entry.text = PieManager.get_name_of(id); + this.pie_id.label = "Pie-ID: " + id; + this.trigger_button.set_trigger(trigger); + this.set_icon(pie.icon); + } + + ///////////////////////////////////////////////////////////////////// + /// Called when one of the checkboxes is toggled. + ///////////////////////////////////////////////////////////////////// + + private void on_check_toggled() { + if (this.trigger != null) { + this.trigger = new Trigger.from_values( + this.trigger.key_sym, this.trigger.modifiers, + this.trigger.with_mouse, this.turbo.active, + this.delayed.active, this.centered.active, + this.warp.active, + this.get_radio_shape() + ); + } + } + + ///////////////////////////////////////////////////////////////////// + /// Returns the current selected radio-button shape: 0= automatic + /// 5= full pie; 1,3,7,8= quarters; 2,4,6,8=halves + /// 1 | 4 | 7 + /// 2 | 5 | 8 + /// 3 | 6 | 9 + ///////////////////////////////////////////////////////////////////// + + private int get_radio_shape() { + int rs; + for (rs= 0; rs < 10; rs++) { + if (this.rshape[rs].active) { + break; + } + } + return rs; + } + + ///////////////////////////////////////////////////////////////////// + /// Sets the current selected radio-button shape: 0= automatic + /// 5= full pie; 1,3,7,8= quarters; 2,4,6,8=halves + ///////////////////////////////////////////////////////////////////// + + private void set_radio_shape(int rs) { + if (rs < 0 || rs > 9) { + rs= 5; //replace invalid value with default= full pie + } + this.rshape[rs].active= true; + } + + ///////////////////////////////////////////////////////////////////// + /// Called twice when one of the radioboxes is toggled. + ///////////////////////////////////////////////////////////////////// + + private void on_radio_toggled() { + notify_toggle= 1 - notify_toggle; + if (notify_toggle == 1) { + on_check_toggled(); //just call once + } + } + + ///////////////////////////////////////////////////////////////////// + /// Called when the icon button is clicked. + ///////////////////////////////////////////////////////////////////// + + private void on_icon_button_clicked(Gtk.Button button) { + if (this.icon_window == null) { + this.icon_window = new IconSelectWindow(this.window); + this.icon_window.on_ok.connect((icon) => { + set_icon(icon); + }); + } + + this.icon_window.show(); + this.icon_window.set_icon(this.icon_name); + } + + ///////////////////////////////////////////////////////////////////// + /// Called when the OK-button is pressed. + ///////////////////////////////////////////////////////////////////// + + private void on_ok_button_clicked() { + var assigned_id = PieManager.get_assigned_id(this.trigger); + + if (assigned_id != "" && assigned_id != this.id) { + // it's already assigned + var error = _("This hotkey is already assigned to the pie \"%s\"! \n\nPlease select " + + "another one or cancel your selection.").printf(PieManager.get_name_of(assigned_id)); + var dialog = new Gtk.MessageDialog((Gtk.Window)this.window.get_toplevel(), Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, Gtk.ButtonsType.CANCEL, error); + dialog.run(); + dialog.destroy(); + } else { + // a unused hot key has been chosen, great! + this.on_ok(this.trigger, this.name_entry.text, this.icon_name); + this.window.hide(); + } + } + + ///////////////////////////////////////////////////////////////////// + /// Sets the icon of the icon_button + ///////////////////////////////////////////////////////////////////// + + private void set_icon(string name) { + this.icon_name = name; + + if (name.contains("/")) { + try { + this.icon.pixbuf = new Gdk.Pixbuf.from_file_at_scale(name, + this.icon.get_pixel_size(), this.icon.get_pixel_size(), true); + } catch (GLib.Error error) { + warning(error.message); + } + } else { + this.icon.icon_name = name; + } + } + + ///////////////////////////////////////////////////////////////////// + /// Called when the cancel button is pressed. + ///////////////////////////////////////////////////////////////////// + + private void on_cancel_button_clicked() { + this.window.hide(); + } +} + +} diff --git a/src/gui/piePreviewAddSign.vala b/src/gui/piePreviewAddSign.vala index fb5e9fa..4a92067 100644 --- a/src/gui/piePreviewAddSign.vala +++ b/src/gui/piePreviewAddSign.vala @@ -87,7 +87,7 @@ public class PiePreviewAddSign : GLib.Object { ///////////////////////////////////////////////////////////////////// public void load() { - this.icon = new Icon("add", 36); + this.icon = new Icon("list-add", 36); } ///////////////////////////////////////////////////////////////////// diff --git a/src/gui/piePreviewDeleteSign.vala b/src/gui/piePreviewDeleteSign.vala index 6ba4dcb..a830002 100644 --- a/src/gui/piePreviewDeleteSign.vala +++ b/src/gui/piePreviewDeleteSign.vala @@ -85,7 +85,7 @@ public class PiePreviewDeleteSign : GLib.Object { ///////////////////////////////////////////////////////////////////// public void load() { - this.icon = new Icon("stock_delete", PiePreviewDeleteSign.radius*2); + this.icon = new Icon("edit-delete", PiePreviewDeleteSign.radius*2); } ///////////////////////////////////////////////////////////////////// diff --git a/src/gui/preferencesWindow.vala b/src/gui/preferencesWindow.vala index 29b5250..a1dacac 100644 --- a/src/gui/preferencesWindow.vala +++ b/src/gui/preferencesWindow.vala @@ -33,19 +33,21 @@ public class PreferencesWindow : GLib.Object { /// Some Gtk widgets used by this window. ///////////////////////////////////////////////////////////////////// + private Gtk.Stack? stack = null; + private Gtk.Notebook? notebook = null; + private Gtk.Window? window = null; - private Gtk.Label? id_label = null; - private Gtk.Label? name_label = null; - private Gtk.Label? hotkey_label = null; private Gtk.Label? no_pie_label = null; private Gtk.Label? no_slice_label = null; private Gtk.Box? preview_box = null; - private Gtk.Image? icon = null; private Gtk.EventBox? preview_background = null; - private Gtk.Button? icon_button = null; - private Gtk.Button? name_button = null; - private Gtk.Button? hotkey_button = null; - private Gtk.ToolButton? remove_pie_button = null; + private Gtk.Button? remove_pie_button = null; + private Gtk.Button? edit_pie_button = null; + + private ThemeList? theme_list = null; + private Gtk.ToggleButton? indicator = null; + private Gtk.ToggleButton? autostart = null; + private Gtk.ToggleButton? captions = null; ///////////////////////////////////////////////////////////////////// /// Some custom widgets and dialogs used by this window. @@ -53,10 +55,7 @@ public class PreferencesWindow : GLib.Object { private PiePreview? preview = null; private PieList? pie_list = null; - private SettingsWindow? settings_window = null; - private TriggerSelectWindow? trigger_window = null; - private IconSelectWindow? icon_window = null; - private RenameWindow? rename_window = null; + private PieOptionsWindow? pie_options_window = null; ///////////////////////////////////////////////////////////////////// /// C'tor, creates the window. @@ -71,14 +70,49 @@ public class PreferencesWindow : GLib.Object { Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK); - var toolbar = builder.get_object ("toolbar") as Gtk.Widget; - toolbar.get_style_context().add_class("primary-toolbar"); + if (Deamon.header_bar) { + var headerbar = new Gtk.HeaderBar(); + headerbar.show_close_button = true; + headerbar.title = _("Gnome-Pie Settings"); + headerbar.subtitle = _("bake your pies!"); + window.set_titlebar(headerbar); + } + + this.notebook = builder.get_object("notebook") as Gtk.Notebook; + + if (Deamon.stack_switcher) { + var main_box = builder.get_object("main-box") as Gtk.Box; + var pie_settings = builder.get_object("pie-settings") as Gtk.Box; + var general_settings = builder.get_object("general-settings") as Gtk.Box; - var inline_toolbar = builder.get_object ("pies-toolbar") as Gtk.Widget; - inline_toolbar.get_style_context().add_class("inline-toolbar"); + pie_settings.parent.remove(pie_settings); + general_settings.parent.remove(general_settings); + + main_box.remove(this.notebook); + + Gtk.StackSwitcher switcher = new Gtk.StackSwitcher(); + switcher.margin_top = 10; + switcher.set_halign(Gtk.Align.CENTER); + main_box.pack_start(switcher, false, true, 0); + + this.stack = new Gtk.Stack(); + this.stack.transition_duration = 500; + this.stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT; + this.stack.homogeneous = true; + this.stack.halign = Gtk.Align.FILL; + this.stack.expand = true; + main_box.add(stack); + switcher.set_stack(stack); + + this.stack.add_with_properties(general_settings, "name", "1", "title", _("General Settings"), null); + this.stack.add_with_properties(pie_settings, "name", "2", "title", _("Pie Settings"), null); + } this.pie_list = new PieList(); this.pie_list.on_select.connect(this.on_pie_select); + this.pie_list.on_activate.connect(() => { + this.on_edit_pie_button_clicked(); + }); var scroll_area = builder.get_object("pies-scrolledwindow") as Gtk.ScrolledWindow; scroll_area.add(this.pie_list); @@ -94,29 +128,82 @@ public class PreferencesWindow : GLib.Object { preview_box = builder.get_object("preview-box") as Gtk.Box; this.preview_box.pack_start(preview, true, true); - this.id_label = builder.get_object("id-label") as Gtk.Label; - this.name_label = builder.get_object("pie-name-label") as Gtk.Label; - this.hotkey_label = builder.get_object("hotkey-label") as Gtk.Label; this.no_pie_label = builder.get_object("no-pie-label") as Gtk.Label; this.no_slice_label = builder.get_object("no-slice-label") as Gtk.Label; - this.icon = builder.get_object("icon") as Gtk.Image; this.preview_background = builder.get_object("preview-background") as Gtk.EventBox; - (builder.get_object("settings-button") as Gtk.ToolButton).clicked.connect(on_settings_button_clicked); + this.remove_pie_button = builder.get_object("remove-pie-button") as Gtk.Button; + this.remove_pie_button.clicked.connect(on_remove_pie_button_clicked); - this.hotkey_button = builder.get_object("key-button") as Gtk.Button; - this.hotkey_button.clicked.connect(on_key_button_clicked); + this.edit_pie_button = builder.get_object("edit-pie-button") as Gtk.Button; + this.edit_pie_button.clicked.connect(on_edit_pie_button_clicked); - this.icon_button = builder.get_object("icon-button") as Gtk.Button; - this.icon_button.clicked.connect(on_icon_button_clicked); + (builder.get_object("add-pie-button") as Gtk.Button).clicked.connect(on_add_pie_button_clicked); - this.name_button = builder.get_object("rename-button") as Gtk.Button; - this.name_button.clicked.connect(on_rename_button_clicked); + this.theme_list = new ThemeList(); + this.theme_list.on_select_new.connect(() => { + this.captions.active = Config.global.show_captions; + if (Config.global.theme.has_slice_captions) { + this.captions.sensitive = true; + } else { + this.captions.sensitive = false; + } + }); - this.remove_pie_button = builder.get_object("remove-pie-button") as Gtk.ToolButton; - this.remove_pie_button.clicked.connect(on_remove_pie_button_clicked); + scroll_area = builder.get_object("theme-scrolledwindow") as Gtk.ScrolledWindow; + scroll_area.add(this.theme_list); + + this.autostart = (builder.get_object("autostart-checkbox") as Gtk.ToggleButton); + this.autostart.toggled.connect(on_autostart_toggled); + + this.indicator = (builder.get_object("indicator-checkbox") as Gtk.ToggleButton); + this.indicator.toggled.connect(on_indicator_toggled); + + this.captions = (builder.get_object("captions-checkbox") as Gtk.ToggleButton); + this.captions.toggled.connect(on_captions_toggled); + + var scale_slider = (builder.get_object("scale-hscale") as Gtk.Scale); + scale_slider.set_range(0.5, 2.0); + scale_slider.set_increments(0.05, 0.25); + scale_slider.set_value(Config.global.global_scale); + + bool changing = false; + bool changed_again = false; + + scale_slider.value_changed.connect(() => { + if (!changing) { + changing = true; + Timeout.add(300, () => { + if (changed_again) { + changed_again = false; + return true; + } + + Config.global.global_scale = scale_slider.get_value(); + Config.global.load_themes(Config.global.theme.name); + changing = false; + return false; + }); + } else { + changed_again = true; + } + }); - (builder.get_object("add-pie-button") as Gtk.ToolButton).clicked.connect(on_add_pie_button_clicked); + var range_slider = (builder.get_object("range-hscale") as Gtk.Scale); + range_slider.set_range(0, 2000); + range_slider.set_increments(10, 100); + range_slider.set_value(Config.global.activation_range); + range_slider.value_changed.connect(() => { + Config.global.activation_range = (int)range_slider.get_value(); + }); + + var range_slices = (builder.get_object("range-slices") as Gtk.Scale); + range_slices.set_range(12, 96); + range_slices.set_increments(4, 12); + range_slices.set_value(Config.global.max_visible_slices); + range_slices.value_changed.connect(() => { + Config.global.max_visible_slices = (int)range_slices.get_value(); + }); this.window.hide.connect(() => { // save settings on close @@ -143,6 +230,85 @@ public class PreferencesWindow : GLib.Object { var style = this.preview_background.get_style_context(); this.preview_background.override_background_color(Gtk.StateFlags.NORMAL, style.get_background_color(Gtk.StateFlags.NORMAL)); + + this.indicator.active = Config.global.show_indicator; + this.autostart.active = Config.global.auto_start; + this.captions.active = Config.global.show_captions; + + if (Config.global.theme.has_slice_captions) { + this.captions.sensitive = true; + } else { + this.captions.sensitive = false; + } + + if (Deamon.stack_switcher) { + this.stack.set_visible_child_full("2", Gtk.StackTransitionType.NONE); + } else { + this.notebook.set_current_page(1); + } + this.pie_list.has_focus = true; + } + + ///////////////////////////////////////////////////////////////////// + /// Creates or deletes the autostart file. This code is inspired + /// by project synapse as well. + ///////////////////////////////////////////////////////////////////// + + private void on_autostart_toggled(Gtk.ToggleButton check_box) { + + bool active = check_box.active; + if (!active && FileUtils.test(Paths.autostart, FileTest.EXISTS)) { + Config.global.auto_start = false; + // delete the autostart file + FileUtils.remove (Paths.autostart); + } + else if (active && !FileUtils.test(Paths.autostart, FileTest.EXISTS)) { + Config.global.auto_start = true; + + string autostart_entry = + "#!/usr/bin/env xdg-open\n" + + "[Desktop Entry]\n" + + "Name=Gnome-Pie\n" + + "Exec=" + Paths.executable + "\n" + + "Encoding=UTF-8\n" + + "Type=Application\n" + + "X-GNOME-Autostart-enabled=true\n" + + "Icon=gnome-pie\n"; + + // create the autostart file + string autostart_dir = GLib.Path.get_dirname(Paths.autostart); + if (!FileUtils.test(autostart_dir, FileTest.EXISTS | FileTest.IS_DIR)) { + DirUtils.create_with_parents(autostart_dir, 0755); + } + + try { + FileUtils.set_contents(Paths.autostart, autostart_entry); + FileUtils.chmod(Paths.autostart, 0755); + } catch (Error e) { + var d = new Gtk.MessageDialog (this.window, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, + "%s", e.message); + d.run (); + d.destroy (); + } + } + } + + ///////////////////////////////////////////////////////////////////// + /// Shows or hides the indicator. + ///////////////////////////////////////////////////////////////////// + + private void on_indicator_toggled(Gtk.ToggleButton check_box) { + var check = check_box as Gtk.CheckButton; + Config.global.show_indicator = check.active; + } + + ///////////////////////////////////////////////////////////////////// + /// Shows or hides the captions of Slices. + ///////////////////////////////////////////////////////////////////// + + private void on_captions_toggled(Gtk.ToggleButton check_box) { + var check = check_box as Gtk.CheckButton; + Config.global.show_captions = check.active; } ///////////////////////////////////////////////////////////////////// @@ -156,33 +322,13 @@ public class PreferencesWindow : GLib.Object { this.no_pie_label.hide(); this.preview_box.hide(); - this.name_button.sensitive = false; - this.hotkey_button.sensitive = false; - this.icon_button.sensitive = false; this.remove_pie_button.sensitive = false; + this.edit_pie_button.sensitive = false; if (id == "") { - this.id_label.label = ""; - this.name_label.label = _("No Pie selected."); - this.hotkey_label.set_markup(""); - this.icon.icon_name = "stock_unknown"; - this.no_pie_label.show(); } else { var pie = PieManager.all_pies[selected_id]; - this.id_label.label = ("ID: %s").printf(pie.id); - this.name_label.label = PieManager.get_name_of(pie.id); - this.hotkey_label.set_markup(PieManager.get_accelerator_label_of(pie.id)); - - if (pie.icon.contains("/")) - try { - this.icon.pixbuf = new Gdk.Pixbuf.from_file_at_scale(pie.icon, - this.icon.get_pixel_size(), this.icon.get_pixel_size(), true); - } catch (GLib.Error error) { - warning(error.message); - } - else - this.icon.icon_name = pie.icon; this.preview.set_pie(id); this.preview_box.show(); @@ -191,10 +337,8 @@ public class PreferencesWindow : GLib.Object { this.no_slice_label.show(); } - this.name_button.sensitive = true; - this.hotkey_button.sensitive = true; - this.icon_button.sensitive = true; this.remove_pie_button.sensitive = true; + this.edit_pie_button.sensitive = true; } } @@ -202,17 +346,19 @@ public class PreferencesWindow : GLib.Object { /// Called when the add Pie button is clicked. ///////////////////////////////////////////////////////////////////// - private void on_add_pie_button_clicked(Gtk.ToolButton button) { + private void on_add_pie_button_clicked(Gtk.Button button) { var new_pie = PieManager.create_persistent_pie(_("New Pie"), "stock_unknown", null); this.pie_list.reload_all(); this.pie_list.select(new_pie.id); + + this.on_edit_pie_button_clicked(); } ///////////////////////////////////////////////////////////////////// /// Called when the remove Pie button is clicked. ///////////////////////////////////////////////////////////////////// - private void on_remove_pie_button_clicked(Gtk.ToolButton button) { + private void on_remove_pie_button_clicked(Gtk.Button button) { if (this.selected_id != "") { var dialog = new Gtk.MessageDialog((Gtk.Window)this.window.get_toplevel(), Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, @@ -232,74 +378,25 @@ public class PreferencesWindow : GLib.Object { } ///////////////////////////////////////////////////////////////////// - /// Called when rename Pie button is clicked. + /// Called when the edit pie button is clicked. ///////////////////////////////////////////////////////////////////// - private void on_rename_button_clicked(Gtk.Button button) { - if (this.rename_window == null) { - this.rename_window = new RenameWindow(); - this.rename_window.set_parent(window); - this.rename_window.on_ok.connect((name) => { + private void on_edit_pie_button_clicked(Gtk.Button? button = null) { + if (this.pie_options_window == null) { + this.pie_options_window = new PieOptionsWindow(); + this.pie_options_window.set_parent(window); + this.pie_options_window.on_ok.connect((trigger, name, icon) => { var pie = PieManager.all_pies[selected_id]; pie.name = name; - PieManager.create_launcher(pie.id); - this.name_label.label = name; - this.pie_list.reload_all(); - }); - } - - this.rename_window.set_pie(selected_id); - this.rename_window.show(); - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the hotkey button is clicked. - ///////////////////////////////////////////////////////////////////// - - private void on_key_button_clicked(Gtk.Button button) { - if (this.trigger_window == null) { - this.trigger_window = new TriggerSelectWindow(); - this.trigger_window.set_parent(window); - this.trigger_window.on_ok.connect((trigger) => { - PieManager.bind_trigger(trigger, selected_id); - this.hotkey_label.set_markup(trigger.label_with_specials); - }); - } - - this.trigger_window.set_pie(selected_id); - this.trigger_window.show(); - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the general settings button is clicked. - ///////////////////////////////////////////////////////////////////// - - private void on_settings_button_clicked(Gtk.ToolButton button) { - if (this.settings_window == null) { - this.settings_window = new SettingsWindow(); - this.settings_window.set_parent(this.window.get_toplevel() as Gtk.Window); - } - - this.settings_window.show(); - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the icon button is clicked. - ///////////////////////////////////////////////////////////////////// - - private void on_icon_button_clicked(Gtk.Button button) { - if (this.icon_window == null) { - this.icon_window = new IconSelectWindow(this.window); - this.icon_window.on_ok.connect((icon) => { - var pie = PieManager.all_pies[selected_id]; pie.icon = icon; + PieManager.bind_trigger(trigger, selected_id); PieManager.create_launcher(pie.id); this.pie_list.reload_all(); }); } - this.icon_window.show(); - this.icon_window.set_icon(PieManager.all_pies[selected_id].icon); + this.pie_options_window.set_pie(selected_id); + this.pie_options_window.show(); } } diff --git a/src/gui/renameWindow.vala b/src/gui/renameWindow.vala deleted file mode 100644 index de65069..0000000 --- a/src/gui/renameWindow.vala +++ /dev/null @@ -1,109 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// Copyright (c) 2011-2015 by Simon Schneegans -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or (at -// your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -///////////////////////////////////////////////////////////////////////// - -namespace GnomePie { - -///////////////////////////////////////////////////////////////////////// -/// A window which allows selection of a new name for a Pie. -///////////////////////////////////////////////////////////////////////// - -public class RenameWindow : GLib.Object { - - ///////////////////////////////////////////////////////////////////// - /// Gets emitted when the user selects a new name. - ///////////////////////////////////////////////////////////////////// - - public signal void on_ok(string new_name); - - ///////////////////////////////////////////////////////////////////// - /// Some Widgets used by this dialog. - ///////////////////////////////////////////////////////////////////// - - private Gtk.Dialog window = null; - private Gtk.Entry entry = null; - - ///////////////////////////////////////////////////////////////////// - /// C'tor, constructs the Widget. - ///////////////////////////////////////////////////////////////////// - - public RenameWindow() { - try { - - Gtk.Builder builder = new Gtk.Builder(); - - builder.add_from_file (Paths.ui_files + "/rename_pie.ui"); - - window = builder.get_object("window") as Gtk.Dialog; - entry = builder.get_object("name-entry") as Gtk.Entry; - - entry.activate.connect(this.on_ok_button_clicked); - - (builder.get_object("ok-button") as Gtk.Button).clicked.connect(on_ok_button_clicked); - (builder.get_object("cancel-button") as Gtk.Button).clicked.connect(on_cancel_button_clicked); - - this.window.delete_event.connect(this.window.hide_on_delete); - - } catch (GLib.Error e) { - error("Could not load UI: %s\n", e.message); - } - } - - ///////////////////////////////////////////////////////////////////// - /// Sets the parent window, in order to make this window stay in - /// front. - ///////////////////////////////////////////////////////////////////// - - public void set_parent(Gtk.Window parent) { - this.window.set_transient_for(parent); - } - - ///////////////////////////////////////////////////////////////////// - /// Displays the window on the screen. - ///////////////////////////////////////////////////////////////////// - - public void show() { - this.window.show_all(); - this.entry.is_focus = true; - } - - ///////////////////////////////////////////////////////////////////// - /// Make the text entry display the name of the Pie with given ID. - ///////////////////////////////////////////////////////////////////// - - public void set_pie(string id) { - entry.text = PieManager.get_name_of(id); - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the ok button is pressed. - ///////////////////////////////////////////////////////////////////// - - private void on_ok_button_clicked() { - this.on_ok(entry.text); - this.window.hide(); - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the cancel button is pressed. - ///////////////////////////////////////////////////////////////////// - - private void on_cancel_button_clicked() { - this.window.hide(); - } -} - -} diff --git a/src/gui/settingsWindow.vala b/src/gui/settingsWindow.vala deleted file mode 100644 index 6bb10c1..0000000 --- a/src/gui/settingsWindow.vala +++ /dev/null @@ -1,222 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// Copyright (c) 2011-2015 by Simon Schneegans -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or (at -// your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -///////////////////////////////////////////////////////////////////////// - -namespace GnomePie { - -///////////////////////////////////////////////////////////////////////// -/// The settings menu of Gnome-Pie, with options for theme switching and -/// some general options. -///////////////////////////////////////////////////////////////////////// - -public class SettingsWindow : GLib.Object { - - ///////////////////////////////////////////////////////////////////// - /// Some widgets. - ///////////////////////////////////////////////////////////////////// - - private Gtk.Dialog? window = null; - private ThemeList? theme_list = null; - private Gtk.ToggleButton? indicator = null; - private Gtk.ToggleButton? autostart = null; - private Gtk.ToggleButton? captions = null; - - ///////////////////////////////////////////////////////////////////// - /// C'tor creates, the dialog. - ///////////////////////////////////////////////////////////////////// - - public SettingsWindow() { - try { - - Gtk.Builder builder = new Gtk.Builder(); - - builder.add_from_file (Paths.ui_files + "/settings.ui"); - - this.window = builder.get_object("window") as Gtk.Dialog; - - this.theme_list = new ThemeList(); - this.theme_list.on_select_new.connect(() => { - this.captions.active = Config.global.show_captions; - if (Config.global.theme.has_slice_captions) { - this.captions.sensitive = true; - } else { - this.captions.sensitive = false; - } - }); - - var scroll_area = builder.get_object("theme-scrolledwindow") as Gtk.ScrolledWindow; - scroll_area.add(this.theme_list); - - (builder.get_object("close-button") as Gtk.Button).clicked.connect(on_close_button_clicked); - - this.autostart = (builder.get_object("autostart-checkbox") as Gtk.ToggleButton); - this.autostart.toggled.connect(on_autostart_toggled); - - this.indicator = (builder.get_object("indicator-checkbox") as Gtk.ToggleButton); - this.indicator.toggled.connect(on_indicator_toggled); - - this.captions = (builder.get_object("captions-checkbox") as Gtk.ToggleButton); - this.captions.toggled.connect(on_captions_toggled); - - var scale_slider = (builder.get_object("scale-hscale") as Gtk.Scale); - scale_slider.set_range(0.5, 2.0); - scale_slider.set_increments(0.05, 0.25); - scale_slider.set_value(Config.global.global_scale); - - bool changing = false; - bool changed_again = false; - - scale_slider.value_changed.connect(() => { - if (!changing) { - changing = true; - Timeout.add(300, () => { - if (changed_again) { - changed_again = false; - return true; - } - - Config.global.global_scale = scale_slider.get_value(); - Config.global.load_themes(Config.global.theme.name); - changing = false; - return false; - }); - } else { - changed_again = true; - } - }); - - var range_slider = (builder.get_object("range-hscale") as Gtk.Scale); - range_slider.set_range(0, 2000); - range_slider.set_increments(10, 100); - range_slider.set_value(Config.global.activation_range); - range_slider.value_changed.connect(() => { - Config.global.activation_range = (int)range_slider.get_value(); - }); - - var range_slices = (builder.get_object("range-slices") as Gtk.Scale); - range_slices.set_range(12, 96); - range_slices.set_increments(4, 12); - range_slices.set_value(Config.global.max_visible_slices); - range_slices.value_changed.connect(() => { - Config.global.max_visible_slices = (int)range_slices.get_value(); - }); - - this.window.delete_event.connect(this.window.hide_on_delete); - - } catch (GLib.Error e) { - error("Could not load UI: %s\n", e.message); - } - } - - ///////////////////////////////////////////////////////////////////// - /// Sets the parent window, in order to make this window stay in - /// front. - ///////////////////////////////////////////////////////////////////// - - public void set_parent(Gtk.Window parent) { - this.window.set_transient_for(parent); - } - - ///////////////////////////////////////////////////////////////////// - /// Displays the window on the screen. - ///////////////////////////////////////////////////////////////////// - - public void show() { - this.indicator.active = Config.global.show_indicator; - this.autostart.active = Config.global.auto_start; - this.captions.active = Config.global.show_captions; - - if (Config.global.theme.has_slice_captions) { - this.captions.sensitive = true; - } else { - this.captions.sensitive = false; - } - - this.window.show_all(); - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the close button is clicked. - ///////////////////////////////////////////////////////////////////// - - private void on_close_button_clicked() { - this.window.hide(); - } - - ///////////////////////////////////////////////////////////////////// - /// Creates or deletes the autostart file. This code is inspired - /// by project synapse as well. - ///////////////////////////////////////////////////////////////////// - - private void on_autostart_toggled(Gtk.ToggleButton check_box) { - - bool active = check_box.active; - if (!active && FileUtils.test(Paths.autostart, FileTest.EXISTS)) { - Config.global.auto_start = false; - // delete the autostart file - FileUtils.remove (Paths.autostart); - } - else if (active && !FileUtils.test(Paths.autostart, FileTest.EXISTS)) { - Config.global.auto_start = true; - - string autostart_entry = - "#!/usr/bin/env xdg-open\n" + - "[Desktop Entry]\n" + - "Name=Gnome-Pie\n" + - "Exec=" + Paths.executable + "\n" + - "Encoding=UTF-8\n" + - "Type=Application\n" + - "X-GNOME-Autostart-enabled=true\n" + - "Icon=gnome-pie\n"; - - // create the autostart file - string autostart_dir = GLib.Path.get_dirname(Paths.autostart); - if (!FileUtils.test(autostart_dir, FileTest.EXISTS | FileTest.IS_DIR)) { - DirUtils.create_with_parents(autostart_dir, 0755); - } - - try { - FileUtils.set_contents(Paths.autostart, autostart_entry); - FileUtils.chmod(Paths.autostart, 0755); - } catch (Error e) { - var d = new Gtk.MessageDialog (this.window, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, - "%s", e.message); - d.run (); - d.destroy (); - } - } - } - - ///////////////////////////////////////////////////////////////////// - /// Shows or hides the indicator. - ///////////////////////////////////////////////////////////////////// - - private void on_indicator_toggled(Gtk.ToggleButton check_box) { - var check = check_box as Gtk.CheckButton; - Config.global.show_indicator = check.active; - } - - ///////////////////////////////////////////////////////////////////// - /// Shows or hides the captions of Slices. - ///////////////////////////////////////////////////////////////////// - - private void on_captions_toggled(Gtk.ToggleButton check_box) { - var check = check_box as Gtk.CheckButton; - Config.global.show_captions = check.active; - } -} - -} diff --git a/src/gui/sliceTypeList.vala b/src/gui/sliceTypeList.vala index e164dea..1a9ecc4 100644 --- a/src/gui/sliceTypeList.vala +++ b/src/gui/sliceTypeList.vala @@ -62,6 +62,7 @@ class SliceTypeList : Gtk.TreeView { main_column.pack_start(icon_render, false); var name_render = new Gtk.CellRendererText(); + name_render.xpad = 6; main_column.pack_start(name_render, true); base.append_column(main_column); @@ -103,8 +104,8 @@ class SliceTypeList : Gtk.TreeView { var icon = new Icon(description.icon, 36); data.set(current, DataPos.ICON, icon.to_pixbuf()); data.set(current, DataPos.ICON_NAME, description.icon); - data.set(current, DataPos.NAME, "" + GLib.Markup.escape_text(description.name) + "\n" - + "" + GLib.Markup.escape_text(description.description) + ""); + data.set(current, DataPos.NAME, GLib.Markup.escape_text(description.name) + "\n" + + "" + GLib.Markup.escape_text(description.description) + ""); data.set(current, DataPos.ID, description.id); } @@ -116,8 +117,8 @@ class SliceTypeList : Gtk.TreeView { var icon = new Icon(description.icon, 36); data.set(current, DataPos.ICON, icon.to_pixbuf()); data.set(current, DataPos.ICON_NAME, description.icon); - data.set(current, DataPos.NAME, "" + GLib.Markup.escape_text(description.name) + "\n" - + "" + GLib.Markup.escape_text(description.description) + ""); + data.set(current, DataPos.NAME, GLib.Markup.escape_text(description.name) + "\n" + + "" + GLib.Markup.escape_text(description.description) + ""); data.set(current, DataPos.ID, description.id); } diff --git a/src/gui/themeList.vala b/src/gui/themeList.vala index 4173819..517c6d5 100644 --- a/src/gui/themeList.vala +++ b/src/gui/themeList.vala @@ -62,15 +62,18 @@ class ThemeList : Gtk.TreeView { main_column.title = _("Themes"); main_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED); var icon_render = new Gtk.CellRendererPixbuf(); + icon_render.xpad = 4; + icon_render.ypad = 4; main_column.pack_start(icon_render, false); - var theme_render = new Gtk.CellRendererText(); - main_column.pack_start(theme_render, true); + var name_render = new Gtk.CellRendererText(); + name_render.xpad = 6; + main_column.pack_start(name_render, true); this.append_column(main_column); main_column.add_attribute(icon_render, "pixbuf", DataPos.ICON); - main_column.add_attribute(theme_render, "markup", DataPos.NAME); + main_column.add_attribute(name_render, "markup", DataPos.NAME); this.get_selection().changed.connect(() => { Gtk.TreeIter active; @@ -94,10 +97,10 @@ class ThemeList : Gtk.TreeView { Gtk.TreeIter current; data.append(out current); data.set(current, DataPos.ICON, theme.preview_icon.to_pixbuf()); - data.set(current, DataPos.NAME, ""+GLib.Markup.escape_text(theme.name)+" - " - +GLib.Markup.escape_text(theme.description)+"\n" - +""+GLib.Markup.escape_text(_("By")+" "+theme.author) - +""); + data.set(current, DataPos.NAME, GLib.Markup.escape_text(theme.name)+"\n" + + "" + GLib.Markup.escape_text(theme.description) + + " - "+GLib.Markup.escape_text(_("By")+" "+theme.author) + + ""); if(theme == Config.global.theme) get_selection().select_iter(current); } diff --git a/src/gui/triggerSelectButton.vala b/src/gui/triggerSelectButton.vala index 92cd8a3..eb34066 100644 --- a/src/gui/triggerSelectButton.vala +++ b/src/gui/triggerSelectButton.vala @@ -48,9 +48,9 @@ public class TriggerSelectButton : Gtk.ToggleButton { ///////////////////////////////////////////////////////////////////// private Gdk.ModifierType lock_modifiers = Gdk.ModifierType.MOD2_MASK - |Gdk.ModifierType.SUPER_MASK - |Gdk.ModifierType.LOCK_MASK - |Gdk.ModifierType.MOD5_MASK; + |Gdk.ModifierType.MOD4_MASK + |Gdk.ModifierType.MOD5_MASK + |Gdk.ModifierType.LOCK_MASK; ///////////////////////////////////////////////////////////////////// /// C'tor, constructs a new TriggerSelectWindow. diff --git a/src/gui/triggerSelectWindow.vala b/src/gui/triggerSelectWindow.vala deleted file mode 100644 index 56781b4..0000000 --- a/src/gui/triggerSelectWindow.vala +++ /dev/null @@ -1,248 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// Copyright (c) 2011-2015 by Simon Schneegans -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or (at -// your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -///////////////////////////////////////////////////////////////////////// - -namespace GnomePie { - -///////////////////////////////////////////////////////////////////////// -/// This window allows the selection of a hotkey. It is returned in form -/// of a Trigger. Therefore it can be either a keyboard driven hotkey or -/// a mouse based hotkey. -///////////////////////////////////////////////////////////////////////// - -public class TriggerSelectWindow : GLib.Object { - - ///////////////////////////////////////////////////////////////////// - /// This signal is emitted when the user selects a new hot key. - ///////////////////////////////////////////////////////////////////// - - public signal void on_ok(Trigger trigger); - - ///////////////////////////////////////////////////////////////////// - /// Some private members which are needed by other methods. - ///////////////////////////////////////////////////////////////////// - - private Gtk.Dialog window; - private Gtk.CheckButton turbo; - private Gtk.CheckButton delayed; - private Gtk.CheckButton centered; - private Gtk.CheckButton warp; - private Gtk.RadioButton rshape[10]; - private TriggerSelectButton button; - - ///////////////////////////////////////////////////////////////////// - /// The currently configured trigger. - ///////////////////////////////////////////////////////////////////// - - private Trigger trigger = null; - - ///////////////////////////////////////////////////////////////////// - /// The trigger which was active when this window was opened. It is - /// stored in order to check whether anything has changed when the - /// user clicks on OK. - ///////////////////////////////////////////////////////////////////// - - private Trigger original_trigger = null; - - ///////////////////////////////////////////////////////////////////// - /// Radioboxes call toggled() twice per selection change. - /// This flag is used to discard one of the two notifications. - ///////////////////////////////////////////////////////////////////// - - private static int notify_toggle= 0; - - ///////////////////////////////////////////////////////////////////// - /// C'tor, constructs a new TriggerSelectWindow. - ///////////////////////////////////////////////////////////////////// - - public TriggerSelectWindow() { - try { - - Gtk.Builder builder = new Gtk.Builder(); - - builder.add_from_file (Paths.ui_files + "/trigger_select.ui"); - - this.window = builder.get_object("window") as Gtk.Dialog; - this.button = new TriggerSelectButton(true); - this.button.show(); - - this.button.on_select.connect((trigger) => { - this.trigger = new Trigger.from_values(trigger.key_sym, - trigger.modifiers, - trigger.with_mouse, - this.turbo.active, - this.delayed.active, - this.centered.active, - this.warp.active, - this.get_radio_shape()); - }); - - (builder.get_object("trigger-box") as Gtk.Box).pack_start(this.button, true, true); - - (builder.get_object("ok-button") as Gtk.Button).clicked.connect(this.on_ok_button_clicked); - (builder.get_object("cancel-button") as Gtk.Button).clicked.connect(this.on_cancel_button_clicked); - - this.turbo = builder.get_object("turbo-check") as Gtk.CheckButton; - this.turbo.toggled.connect(this.on_check_toggled); - - this.delayed = builder.get_object("delay-check") as Gtk.CheckButton; - this.delayed.toggled.connect(this.on_check_toggled); - - this.centered = builder.get_object("center-check") as Gtk.CheckButton; - this.centered.toggled.connect(this.on_check_toggled); - - this.warp = builder.get_object("warp-check") as Gtk.CheckButton; - this.warp.toggled.connect(this.on_check_toggled); - - for (int i= 0; i < 10; i++) { - this.rshape[i] = builder.get_object("rshape%d".printf(i)) as Gtk.RadioButton; - this.rshape[i].toggled.connect(this.on_radio_toggled); - } - - this.window.delete_event.connect(this.window.hide_on_delete); - - } catch (GLib.Error e) { - error("Could not load UI: %s\n", e.message); - } - } - - ///////////////////////////////////////////////////////////////////// - /// Sets the parent window, in order to make this window stay in - /// front. - ///////////////////////////////////////////////////////////////////// - - public void set_parent(Gtk.Window parent) { - this.window.set_transient_for(parent); - } - - ///////////////////////////////////////////////////////////////////// - /// Displays the window on the screen. - ///////////////////////////////////////////////////////////////////// - - public void show() { - this.window.show_all(); - } - - ///////////////////////////////////////////////////////////////////// - /// Initilizes all members to match the Trigger of the Pie with the - /// given ID. - ///////////////////////////////////////////////////////////////////// - - public void set_pie(string id) { - var trigger = new Trigger.from_string(PieManager.get_accelerator_of(id)); - - this.turbo.active = trigger.turbo; - this.delayed.active = trigger.delayed; - this.centered.active = trigger.centered; - this.warp.active = trigger.warp; - this.set_radio_shape( trigger.shape ); - this.original_trigger = trigger; - this.trigger = trigger; - - this.button.set_trigger(trigger); - } - - ///////////////////////////////////////////////////////////////////// - /// Called when one of the checkboxes is toggled. - ///////////////////////////////////////////////////////////////////// - - private void on_check_toggled() { - if (this.trigger != null) - this.trigger = new Trigger.from_values(this.trigger.key_sym, this.trigger.modifiers, - this.trigger.with_mouse, this.turbo.active, - this.delayed.active, this.centered.active, - this.warp.active, - this.get_radio_shape()); - } - - ///////////////////////////////////////////////////////////////////// - /// Returns the current selected radio-button shape: 0= automatic - /// 5= full pie; 1,3,7,8= quarters; 2,4,6,8=halves - /// 1 | 4 | 7 - /// 2 | 5 | 8 - /// 3 | 6 | 9 - ///////////////////////////////////////////////////////////////////// - - private int get_radio_shape() { - int rs; - for (rs= 0; rs < 10; rs++) - if (this.rshape[rs].active) - break; - return rs; - } - - ///////////////////////////////////////////////////////////////////// - /// Sets the current selected radio-button shape: 0= automatic - /// 5= full pie; 1,3,7,8= quarters; 2,4,6,8=halves - ///////////////////////////////////////////////////////////////////// - - private void set_radio_shape(int rs) { - if (rs < 0 || rs > 9) - rs= 5; //replace invalid value with default= full pie - this.rshape[rs].active= true; - } - - ///////////////////////////////////////////////////////////////////// - /// Called twice when one of the radioboxes is toggled. - ///////////////////////////////////////////////////////////////////// - - private void on_radio_toggled() { - notify_toggle= 1 - notify_toggle; - if (notify_toggle == 1) - on_check_toggled(); //just call once - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the OK-button is pressed. - ///////////////////////////////////////////////////////////////////// - - private void on_ok_button_clicked() { - var assigned_id = PieManager.get_assigned_id(this.trigger); - - if (this.trigger == this.original_trigger) { - // nothing did change - this.window.hide(); - } else if (this.trigger.key_code == this.original_trigger.key_code - && this.trigger.modifiers == this.original_trigger.modifiers - && this.trigger.with_mouse == this.original_trigger.with_mouse) { - // only turbo and/or delayed mode changed, no need to check for double assignment - this.on_ok(this.trigger); - this.window.hide(); - } else if (assigned_id != "") { - // it's already assigned - var error = _("This hotkey is already assigned to the pie \"%s\"! \n\nPlease select " + - "another one or cancel your selection.").printf(PieManager.get_name_of(assigned_id)); - var dialog = new Gtk.MessageDialog((Gtk.Window)this.window.get_toplevel(), Gtk.DialogFlags.MODAL, - Gtk.MessageType.ERROR, Gtk.ButtonsType.CANCEL, error); - dialog.run(); - dialog.destroy(); - } else { - // a unused hot key has been chosen, great! - this.on_ok(this.trigger); - this.window.hide(); - } - } - - ///////////////////////////////////////////////////////////////////// - /// Called when the cancel button is pressed. - ///////////////////////////////////////////////////////////////////// - - private void on_cancel_button_clicked() { - this.window.hide(); - } -} - -} diff --git a/src/pies/defaultConfig.vala b/src/pies/defaultConfig.vala index 6ca45e4..e446c2b 100644 --- a/src/pies/defaultConfig.vala +++ b/src/pies/defaultConfig.vala @@ -26,11 +26,11 @@ namespace Pies { public void create_default_config() { // add a pie with playback controls - var multimedia = PieManager.create_persistent_pie(_("Multimedia"), "stock_media-play", new Trigger.from_string("m")); - multimedia.add_action(new KeyAction(_("Next Track"), "stock_media-next", "XF86AudioNext", true)); - multimedia.add_action(new KeyAction(_("Stop"), "stock_media-stop", "XF86AudioStop")); - multimedia.add_action(new KeyAction(_("Previous Track"), "stock_media-prev", "XF86AudioPrev")); - multimedia.add_action(new KeyAction(_("Play/Pause"), "stock_media-play", "XF86AudioPlay")); + var multimedia = PieManager.create_persistent_pie(_("Multimedia"), "media-playback-start", new Trigger.from_string("m")); + multimedia.add_action(new KeyAction(_("Next Track"), "media-skip-forward", "XF86AudioNext", true)); + multimedia.add_action(new KeyAction(_("Stop"), "media-playback-stop", "XF86AudioStop")); + multimedia.add_action(new KeyAction(_("Previous Track"), "media-skip-backward", "XF86AudioPrev")); + multimedia.add_action(new KeyAction(_("Play/Pause"), "media-playback-start", "XF86AudioPlay")); // add a pie with the users default applications var apps = PieManager.create_persistent_pie(_("Applications"), "applications-accessories", new Trigger.from_string("a")); @@ -47,20 +47,20 @@ namespace Pies { bookmarks.add_group(new DevicesGroup(bookmarks.id)); // add a pie with session controls - var session = PieManager.create_persistent_pie(_("Session"), "gnome-session-halt", new Trigger.from_string("q")); + var session = PieManager.create_persistent_pie(_("Session"), "system-log-out", new Trigger.from_string("q")); session.add_group(new SessionGroup(session.id)); // add a pie with a main menu - var menu = PieManager.create_persistent_pie(_("Main Menu"), "alacarte", new Trigger.from_string("space")); + var menu = PieManager.create_persistent_pie(_("Main Menu"), "start-here", new Trigger.from_string("space")); menu.add_group(new MenuGroup(menu.id)); // add a pie with window controls - var window = PieManager.create_persistent_pie(_("Window"), "gnome-window-manager", new Trigger.from_string("w")); - window.add_action(new KeyAction(_("Scale"), "top", "s")); - window.add_action(new KeyAction(_("Minimize"), "bottom", "F9", true)); + var window = PieManager.create_persistent_pie(_("Window"), "preferences-system-windows", new Trigger.from_string("w")); + window.add_action(new KeyAction(_("Scale"), "go-top", "s")); + window.add_action(new KeyAction(_("Minimize"), "go-bottom", "F9", true)); window.add_action(new KeyAction(_("Close"), "window-close", "F4")); - window.add_action(new KeyAction(_("Maximize"), "window_fullscreen", "F10")); - window.add_action(new KeyAction(_("Restore"), "window_nofullscreen", "F5")); + window.add_action(new KeyAction(_("Maximize"), "view-fullscreen", "F10")); + window.add_action(new KeyAction(_("Restore"), "view-restore", "F5")); // save the configuration to file Pies.save(); diff --git a/src/renderers/pieRenderer.vala b/src/renderers/pieRenderer.vala index 2edee09..cd50644 100644 --- a/src/renderers/pieRenderer.vala +++ b/src/renderers/pieRenderer.vala @@ -422,10 +422,10 @@ public class PieRenderer : GLib.Object { /// Activates the currently active slice. ///////////////////////////////////////////////////////////////////// - public void activate() { + public void activate(uint32 time_stamp) { if (this.active_slice >= this.first_slice_idx && this.active_slice < this.first_slice_idx+this.visible_slice_count) { - slices[active_slice].activate(); + slices[active_slice].activate(time_stamp); } //foreach (var slice in this.slices) diff --git a/src/renderers/pieWindow.vala b/src/renderers/pieWindow.vala index c8ff455..95432c5 100755 --- a/src/renderers/pieWindow.vala +++ b/src/renderers/pieWindow.vala @@ -130,7 +130,7 @@ public class PieWindow : Gtk.Window { // activate on left click this.button_release_event.connect ((e) => { - if (e.button == 1 || PieManager.get_is_turbo(this.renderer.id)) this.activate_slice(); + if (e.button == 1 || PieManager.get_is_turbo(this.renderer.id)) this.activate_slice(e.time); return true; }); @@ -145,7 +145,7 @@ public class PieWindow : Gtk.Window { this.key_press_event.connect((e) => { if (e.keyval != last_key) { last_key = e.keyval; - this.handle_key_press(e.keyval); + this.handle_key_press(e.keyval, e.time); } return true; }); @@ -154,7 +154,7 @@ public class PieWindow : Gtk.Window { this.key_release_event.connect((e) => { last_key = 0; if (PieManager.get_is_turbo(this.renderer.id)) - this.activate_slice(); + this.activate_slice(e.time); else this.handle_key_release(e.keyval); return true; @@ -373,7 +373,7 @@ public class PieWindow : Gtk.Window { /// Activates the currently activate slice. ///////////////////////////////////////////////////////////////////// - private void activate_slice() { + private void activate_slice(uint32 time_stamp) { if (!this.closing) { this.closing = true; this.on_closing(); @@ -381,7 +381,7 @@ public class PieWindow : Gtk.Window { FocusGrabber.ungrab(); GLib.Timeout.add(10, () => { - this.renderer.activate(); + this.renderer.activate(time_stamp); return false; }); @@ -429,9 +429,9 @@ public class PieWindow : Gtk.Window { /// Do some useful stuff when keys are pressed. ///////////////////////////////////////////////////////////////////// - private void handle_key_press(uint key) { + private void handle_key_press(uint key, uint32 time_stamp) { if (Gdk.keyval_name(key) == "Escape") this.cancel(); - else if (Gdk.keyval_name(key) == "Return") this.activate_slice(); + else if (Gdk.keyval_name(key) == "Return") this.activate_slice(time_stamp); else if (!PieManager.get_is_turbo(this.renderer.id)) { if (Gdk.keyval_name(key) == "Up") this.renderer.select_up(); else if (Gdk.keyval_name(key) == "Down") this.renderer.select_down(); @@ -455,7 +455,7 @@ public class PieWindow : Gtk.Window { if (this.renderer.active_slice == index) { GLib.Timeout.add((uint)(Config.global.theme.transition_time*1000.0), ()=> { - this.activate_slice(); + this.activate_slice(time_stamp); return false; }); } diff --git a/src/renderers/sliceRenderer.vala b/src/renderers/sliceRenderer.vala index 862e2a5..dfcf512 100644 --- a/src/renderers/sliceRenderer.vala +++ b/src/renderers/sliceRenderer.vala @@ -157,8 +157,8 @@ public class SliceRenderer : GLib.Object { /// Activates the Action of this slice. ///////////////////////////////////////////////////////////////////// - public void activate() { - action.activate(); + public void activate(uint32 time_stamp) { + action.activate(time_stamp); } ///////////////////////////////////////////////////////////////////// diff --git a/src/utilities/bindingManager.vala b/src/utilities/bindingManager.vala index e90fa74..6ca73cf 100644 --- a/src/utilities/bindingManager.vala +++ b/src/utilities/bindingManager.vala @@ -99,18 +99,22 @@ public class BindingManager : GLib.Object { public void bind(Trigger trigger, string id) { if (trigger.key_code != 0) { - X.Display display = Gdk.X11.get_default_xdisplay(); + unowned X.Display display = Gdk.X11.get_default_xdisplay(); X.ID xid = Gdk.X11.get_default_root_xwindow(); Gdk.error_trap_push(); + // if bound to super key we need to grab MOD4 instead + // (for whatever reason...) + var modifiers = prepare_modifiers(trigger.modifiers); + foreach(uint lock_modifier in lock_modifiers) { if (trigger.with_mouse) { - display.grab_button(trigger.key_code, trigger.modifiers|lock_modifier, xid, false, + display.grab_button(trigger.key_code, modifiers|lock_modifier, xid, false, X.EventMask.ButtonPressMask | X.EventMask.ButtonReleaseMask, X.GrabMode.Async, X.GrabMode.Async, xid, 0); } else { - display.grab_key(trigger.key_code, trigger.modifiers|lock_modifier, + display.grab_key(trigger.key_code, modifiers|lock_modifier, xid, false, X.GrabMode.Async, X.GrabMode.Async); } } @@ -142,17 +146,22 @@ public class BindingManager : GLib.Object { } } - X.Display display = Gdk.X11.get_default_xdisplay(); + unowned X.Display display = Gdk.X11.get_default_xdisplay(); X.ID xid = Gdk.X11.get_default_root_xwindow(); Gee.List remove_bindings = new Gee.ArrayList(); foreach(var binding in bindings) { if(id == binding.id) { + + // if bound to super key we need to ungrab MOD4 instead + // (for whatever reason...) + var modifiers = prepare_modifiers(binding.trigger.modifiers); + foreach(uint lock_modifier in lock_modifiers) { if (binding.trigger.with_mouse) { - display.ungrab_button(binding.trigger.key_code, binding.trigger.modifiers|lock_modifier, xid); + display.ungrab_button(binding.trigger.key_code, modifiers|lock_modifier, xid); } else { - display.ungrab_key(binding.trigger.key_code, binding.trigger.modifiers|lock_modifier, xid); + display.ungrab_key(binding.trigger.key_code, modifiers|lock_modifier, xid); } } remove_bindings.add(binding); @@ -281,6 +290,21 @@ public class BindingManager : GLib.Object { return ""; } + ///////////////////////////////////////////////////////////////////// + /// If SUPER_MASK is set in the input, it will be replaced with + /// MOD4_MASK. For some reason this is required to listen for key + /// presses of the super button.... + ///////////////////////////////////////////////////////////////////// + + private Gdk.ModifierType prepare_modifiers(Gdk.ModifierType mods) { + if ((mods & Gdk.ModifierType.SUPER_MASK) > 0) { + mods |= Gdk.ModifierType.MOD4_MASK; + mods = mods & ~ Gdk.ModifierType.SUPER_MASK; + } + + return mods & ~lock_modifiers[7]; + } + ///////////////////////////////////////////////////////////////////// /// Event filter method needed to fetch X.Events. ///////////////////////////////////////////////////////////////////// @@ -296,9 +320,14 @@ public class BindingManager : GLib.Object { if(xevent->type == X.EventType.KeyPress) { foreach(var binding in bindings) { + // remove NumLock, CapsLock and ScrollLock from key state - uint event_mods = xevent.xkey.state & ~ (lock_modifiers[7]); - if(xevent->xkey.keycode == binding.trigger.key_code && event_mods == binding.trigger.modifiers) { + var event_mods = prepare_modifiers((Gdk.ModifierType)xevent.xkey.state); + var bound_mods = prepare_modifiers(binding.trigger.modifiers); + + if(xevent->xkey.keycode == binding.trigger.key_code && + event_mods == bound_mods) { + if (binding.trigger.delayed) { this.activate_delayed(binding, *xevent); } else { @@ -309,9 +338,14 @@ public class BindingManager : GLib.Object { } else if(xevent->type == X.EventType.ButtonPress) { foreach(var binding in bindings) { + // remove NumLock, CapsLock and ScrollLock from key state - uint event_mods = xevent.xbutton.state & ~ (lock_modifiers[7]); - if(xevent->xbutton.button == binding.trigger.key_code && event_mods == binding.trigger.modifiers) { + var event_mods = prepare_modifiers((Gdk.ModifierType)xevent.xbutton.state); + var bound_mods = prepare_modifiers(binding.trigger.modifiers); + + if(xevent->xbutton.button == binding.trigger.key_code && + event_mods == bound_mods) { + if (binding.trigger.delayed) { this.activate_delayed(binding, *xevent); } else { @@ -343,27 +377,27 @@ public class BindingManager : GLib.Object { // if the trigger is released and an event is currently waiting // simulate that the trigger has been pressed without any inter- // ference of Gnome-Pie - X.Display display = Gdk.X11.get_default_xdisplay(); + unowned X.Display display = Gdk.X11.get_default_xdisplay(); - // unbind the trigger, else we'll capture that event again ;) - unbind(delayed_binding.id); + // unbind the trigger, else we'll capture that event again ;) + unbind(delayed_binding.id); - if (this.delayed_binding.trigger.with_mouse) { - // simulate mouse click - X.Test.fake_button_event(display, this.delayed_event.xbutton.button, true, 0); - display.flush(); + if (this.delayed_binding.trigger.with_mouse) { + // simulate mouse click + XTest.fake_button_event(display, this.delayed_event.xbutton.button, true, 0); + display.flush(); - X.Test.fake_button_event(display, this.delayed_event.xbutton.button, false, 0); + XTest.fake_button_event(display, this.delayed_event.xbutton.button, false, 0); display.flush(); - } else { - // simulate key press - X.Test.fake_key_event(display, this.delayed_event.xkey.keycode, true, 0); - display.flush(); + } else { + // simulate key press + XTest.fake_key_event(display, this.delayed_event.xkey.keycode, true, 0); + display.flush(); - X.Test.fake_key_event(display, this.delayed_event.xkey.keycode, false, 0); - display.flush(); - } + XTest.fake_key_event(display, this.delayed_event.xkey.keycode, false, 0); + display.flush(); + } // bind it again bind(delayed_binding.trigger, delayed_binding.id); diff --git a/src/utilities/color.vala b/src/utilities/color.vala index 6bb9d06..a681e02 100644 --- a/src/utilities/color.vala +++ b/src/utilities/color.vala @@ -76,6 +76,19 @@ public class Color: GLib.Object { ); } + ///////////////////////////////////////////////////////////////////// + /// Creates a color from a given widget style + ///////////////////////////////////////////////////////////////////// + + public Color.from_widget_style(Gtk.Widget widget, string style_name) { + var ctx = widget.get_style_context(); + Gdk.RGBA color; + if (!ctx.lookup_color(style_name, out color)) { + warning("Failed to get style color for widget style \"" + style_name + "\"!"); + } + Color.from_gdk(color); + } + ///////////////////////////////////////////////////////////////////// /// Creates a color, parsed from a string, such as #22EE33 ///////////////////////////////////////////////////////////////////// @@ -128,6 +141,14 @@ public class Color: GLib.Object { v = 1.0f; } + ///////////////////////////////////////////////////////////////////// + /// Returns this color as its hex representation. + ///////////////////////////////////////////////////////////////////// + + public string to_hex_string() { + return "#%02X%02X%02X".printf((int)(_r*255), (int)(_g*255), (int)(_b*255)); + } + ///////////////////////////////////////////////////////////////////// /// The reddish part of the color. ///////////////////////////////////////////////////////////////////// diff --git a/src/utilities/config.vala b/src/utilities/config.vala index abb8b23..dd31885 100644 --- a/src/utilities/config.vala +++ b/src/utilities/config.vala @@ -192,7 +192,7 @@ public class Config : GLib.Object { if (themes.size > 0) { if (current == "") { - current = "Unity"; + current = "Adwaita"; warning("No theme specified! Using default..."); } foreach (var t in themes) { diff --git a/src/utilities/key.vala b/src/utilities/key.vala index 7cf425f..486744d 100644 --- a/src/utilities/key.vala +++ b/src/utilities/key.vala @@ -118,8 +118,8 @@ public class Key : GLib.Object { display.flush(); // press and release the actual key - X.Test.fake_key_event(display, this.key_code, true, 0); - X.Test.fake_key_event(display, this.key_code, false, 0); + XTest.fake_key_event(display, this.key_code, true, 0); + XTest.fake_key_event(display, this.key_code, false, 0); // release the pressed modifiers and re-press the keys hold down by the user press_modifiers(this.modifiers, false); @@ -145,16 +145,16 @@ public class Key : GLib.Object { private void press_modifiers(Gdk.ModifierType modifiers, bool down) { if ((modifiers & Gdk.ModifierType.CONTROL_MASK) > 0) - X.Test.fake_key_event(display, ctrl_code, down, 0); + XTest.fake_key_event(display, ctrl_code, down, 0); if ((modifiers & Gdk.ModifierType.SHIFT_MASK) > 0) - X.Test.fake_key_event(display, shift_code, down, 0); + XTest.fake_key_event(display, shift_code, down, 0); if ((modifiers & Gdk.ModifierType.MOD1_MASK) > 0) - X.Test.fake_key_event(display, alt_code, down, 0); + XTest.fake_key_event(display, alt_code, down, 0); if ((modifiers & Gdk.ModifierType.SUPER_MASK) > 0) - X.Test.fake_key_event(display, super_code, down, 0); + XTest.fake_key_event(display, super_code, down, 0); } } diff --git a/src/utilities/trigger.vala b/src/utilities/trigger.vala index fbd74f8..5373b41 100644 --- a/src/utilities/trigger.vala +++ b/src/utilities/trigger.vala @@ -251,7 +251,7 @@ public class Trigger : GLib.Object { msg += " | " + _("Half pie"); } if (msg != "") - this.label_with_specials += (" [ " + msg + " ]"); + this.label_with_specials += (" [ " + msg + " ]"); } else { this.set_unbound(); -- cgit v1.2.3