From b683ce2789d95b2e9f221e75adc30efd91cfb901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 24 Jan 2015 11:03:06 +0100 Subject: Imported Upstream version 0.5.7 --- src/CMakeLists.txt | 4 - src/deamon.vala | 143 +++++++++++------------- src/gui/aboutWindow.vala | 26 ++--- src/gui/iconSelectWindow.vala | 216 +++++++++++++++++------------------- src/gui/indicator.vala | 13 +-- src/gui/newSliceWindow.vala | 178 +++++++++++++++--------------- src/gui/newsWindow.vala | 40 +++---- src/gui/piePreview.vala | 198 ++++++++++++++++----------------- src/gui/piePreviewCenter.vala | 65 +++++------ src/gui/piePreviewRenderer.vala | 201 ++++++++++++++++++---------------- src/gui/preferencesWindow.vala | 231 +++++++++++++++++++-------------------- src/gui/settingsWindow.vala | 88 ++++++++------- src/gui/triggerSelectWindow.vala | 78 ++++++------- src/images/image.vala | 95 ++++++++-------- src/renderers/pieRenderer.vala | 150 ++++++++++++------------- src/renderers/pieWindow.vala | 38 +++---- src/utilities/color.vala | 87 +++++++-------- src/utilities/config.vala | 62 ++++++----- src/utilities/focusGrabber.vala | 120 ++++++++------------ 19 files changed, 986 insertions(+), 1047 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7138fdd..ee08045 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,10 +12,6 @@ if (${INDICATOR3_FOUND}) LIST(APPEND DEFINES --define HAVE_APPINDICATOR) endif(${INDICATOR3_FOUND}) -if (${GTK3_FOUND}) - LIST(APPEND DEFINES --define HAVE_GTK_3) -endif(${GTK3_FOUND}) - if (${GMENU3_FOUND}) LIST(APPEND DEFINES --define HAVE_GMENU_3) endif (${GMENU3_FOUND}) diff --git a/src/deamon.vala b/src/deamon.vala index fb9618b..2e79d10 100644 --- a/src/deamon.vala +++ b/src/deamon.vala @@ -36,15 +36,12 @@ public class Deamon : GLib.Object { ///////////////////////////////////////////////////////////////////// public static int main(string[] args) { - version = "0.5.6"; + version = "0.5.7"; Logger.init(); - Gdk.threads_init(); Gtk.init(ref args); Paths.init(); - message("Welcome to Gnome-Pie " + version + "!"); - // create the Deamon and run it var deamon = new GnomePie.Deamon(); deamon.run(args); @@ -83,95 +80,51 @@ public class Deamon : GLib.Object { ///////////////////////////////////////////////////////////////////// public void run(string[] args) { - // create command line options - var context = new GLib.OptionContext(""); - context.set_help_enabled(true); - context.add_main_entries(options, null); - context.add_group(Gtk.get_option_group (false)); - - try { - context.parse(ref args); - } catch(GLib.OptionError error) { - warning(error.message); - } - - if (Deamon.reset) { - if (GLib.FileUtils.remove(Paths.pie_config) == 0) - message("Removed file \"%s\"", Paths.pie_config); - if (GLib.FileUtils.remove(Paths.settings) == 0) - message("Removed file \"%s\"", Paths.settings); - - return; - } // create unique application - var app = new Unique.App("org.gnome.gnomepie", null); - - #if HAVE_GTK_3 - if (app.is_running()) { - #else - if (app.is_running) { - #endif - // inform the running instance of the pie to be opened - if (open_pie != null) { - message("Gnome-Pie is already running. Sending request to open pie " + open_pie + "."); - var data = new Unique.MessageData(); - data.set_text(open_pie, open_pie.length); - app.send_message(Unique.Command.ACTIVATE, data); - - return; - } - - message("Gnome-Pie is already running. Sending request to open config menu."); - app.send_message(Unique.Command.ACTIVATE, null); + var app = new GLib.Application("org.gnome.gnomepie", GLib.ApplicationFlags.HANDLES_COMMAND_LINE); - return; - } - - // wait for incoming messages - app.message_received.connect((cmd, data, event_time) => { - if (cmd == Unique.Command.ACTIVATE) { - var pie = data.get_text(); - - if (pie != null && pie != "") PieManager.open_pie(pie); - else this.indicator.show_preferences(); - - return Unique.Response.OK; + app.command_line.connect((cmd) => { + string[] tmp = cmd.get_arguments(); + unowned string[] remote_args = tmp; + if (!handle_command_line(remote_args, true)) { + Gtk.main_quit(); } - return Unique.Response.PASSTHROUGH; + return 0; }); - Gdk.threads_enter(); + app.startup.connect(() => { - // init locale support - Intl.bindtextdomain ("gnomepie", Paths.locales); - Intl.textdomain ("gnomepie"); + message("Welcome to Gnome-Pie " + version + "!"); - // init toolkits and static stuff - ActionRegistry.init(); - GroupRegistry.init(); + // init locale support + Intl.bindtextdomain ("gnomepie", Paths.locales); + Intl.textdomain ("gnomepie"); - PieManager.init(); - Icon.init(); + // init toolkits and static stuff + ActionRegistry.init(); + GroupRegistry.init(); - // launch the indicator - this.indicator = new Indicator(); + PieManager.init(); + Icon.init(); - // connect SigHandlers - Posix.signal(Posix.SIGINT, sig_handler); - Posix.signal(Posix.SIGTERM, sig_handler); + // launch the indicator + this.indicator = new Indicator(); - // finished loading... so run the prog! - message("Started happily..."); + // connect SigHandlers + Posix.signal(Posix.SIGINT, sig_handler); + Posix.signal(Posix.SIGTERM, sig_handler); - // open pie if neccessary - if (open_pie != null) - PieManager.open_pie(open_pie); + // finished loading... so run the prog! + message("Started happily..."); - Gtk.main(); + if (handle_command_line(args, false)) { + Gtk.main(); + } + }); - Gdk.threads_leave(); + app.run(args); } ///////////////////////////////////////////////////////////////////// @@ -183,6 +136,42 @@ public class Deamon : GLib.Object { message("Caught signal (%d), bye!".printf(sig)); Gtk.main_quit(); } + + ///////////////////////////////////////////////////////////////////// + /// Handles command line parameters. + ///////////////////////////////////////////////////////////////////// + + private bool handle_command_line(string[] args, bool show_preferences) { + // create command line options + var context = new GLib.OptionContext(""); + context.set_help_enabled(true); + context.add_main_entries(options, null); + context.add_group(Gtk.get_option_group (false)); + + try { + context.parse(ref args); + } catch(GLib.OptionError error) { + warning(error.message); + } + + if (reset) { + if (GLib.FileUtils.remove(Paths.pie_config) == 0) + message("Removed file \"%s\"", Paths.pie_config); + if (GLib.FileUtils.remove(Paths.settings) == 0) + message("Removed file \"%s\"", Paths.settings); + + return false; + } + + if (open_pie != null && open_pie != "") { + PieManager.open_pie(open_pie); + open_pie = ""; + } else if (show_preferences) { + this.indicator.show_preferences(); + } + + return true; + } } } diff --git a/src/gui/aboutWindow.vala b/src/gui/aboutWindow.vala index c6b7453..39258cb 100644 --- a/src/gui/aboutWindow.vala +++ b/src/gui/aboutWindow.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,25 +12,25 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// A simple about dialog. ///////////////////////////////////////////////////////////////////////// public class AboutWindow: Gtk.AboutDialog { - + ///////////////////////////////////////////////////////////////////// /// C'tor, creates a new about dialog. The entries are sorted alpha- /// betically. ///////////////////////////////////////////////////////////////////// - + public AboutWindow () { string[] devs = { - "Simon Schneegans ", + "Simon Schneegans ", "Francesco Piccinno " }; string[] artists = { @@ -48,29 +48,29 @@ public class AboutWindow: Gtk.AboutDialog { "Ting Zhou (ZH-CN)", "Martin Dinov (BG)" }; - + // sort translators GLib.List translator_list = new GLib.List(); foreach (var translator in translators) translator_list.append(translator); - + translator_list.sort((a, b) => { return a.ascii_casecmp(b); }); - + string translator_string = ""; foreach (var translator in translator_list) translator_string += translator + "\n"; - + GLib.Object ( artists : artists, authors : devs, translator_credits : translator_string, - copyright : "Copyright (C) 2011-2012 Simon Schneegans ", + copyright : "Copyright (C) 2011-2015 Simon Schneegans ", program_name: "Gnome-Pie", logo_icon_name: "gnome-pie", - website: "http://www.simonschneegans.de/?page_id=12", - website_label: "www.gnome-pie.simonschneegans.de", + website: "http://simmesimme.github.io/gnome-pie.html", + website_label: "Homepage", version: Deamon.version ); } diff --git a/src/gui/iconSelectWindow.vala b/src/gui/iconSelectWindow.vala index 9159f15..2560811 100644 --- a/src/gui/iconSelectWindow.vala +++ b/src/gui/iconSelectWindow.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,29 +12,29 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// -/// A window which allows selection of an Icon of the user's current icon +///////////////////////////////////////////////////////////////////////// +/// A window which allows selection of an Icon of the user's current icon /// theme. Custom icons/images can be selested as well. Loading of icons /// happens in an extra thread and a spinner is displayed while loading. ///////////////////////////////////////////////////////////////////////// public class IconSelectWindow : GLib.Object { - + ///////////////////////////////////////////////////////////////////// /// This signal gets emitted when the user selects a new icon. ///////////////////////////////////////////////////////////////////// - + public signal void on_ok(string icon_name); - + ///////////////////////////////////////////////////////////////////// /// Stores the currently selected icon. ///////////////////////////////////////////////////////////////////// - + private string active_icon = ""; ///////////////////////////////////////////////////////////////////// @@ -42,64 +42,64 @@ public class IconSelectWindow : GLib.Object { ///////////////////////////////////////////////////////////////////// private static Gtk.ListStore icon_list = null; - + ///////////////////////////////////////////////////////////////////// /// True, if the icon theme is currently reloaded. ///////////////////////////////////////////////////////////////////// - + private static bool loading = false; - + ///////////////////////////////////////////////////////////////////// /// If set to true, the icon list will be reloaded next time the /// window opens. ///////////////////////////////////////////////////////////////////// - + private static bool need_reload = true; - + ///////////////////////////////////////////////////////////////////// /// Icons of these contexts won't appear in the list. ///////////////////////////////////////////////////////////////////// - + private const string disabled_contexts = "Animations, FileSystems"; - + ///////////////////////////////////////////////////////////////////// /// The list of icons, filtered according to the chosen type and /// filter string. ///////////////////////////////////////////////////////////////////// - + private Gtk.TreeModelFilter icon_list_filtered = null; - + ///////////////////////////////////////////////////////////////////// /// The Gtk widget displaying the icons. ///////////////////////////////////////////////////////////////////// - + private Gtk.IconView icon_view = null; - + ///////////////////////////////////////////////////////////////////// /// This spinner is displayed when the icons are loaded. ///////////////////////////////////////////////////////////////////// - + private Gtk.Spinner spinner = null; - + ///////////////////////////////////////////////////////////////////// /// A Gtk widget used for custom icon/image selection. ///////////////////////////////////////////////////////////////////// - + private Gtk.FileChooserWidget file_chooser = null; - + ///////////////////////////////////////////////////////////////////// /// The notebook containing the different icon choice possibilities: /// from the theme or custom. ///////////////////////////////////////////////////////////////////// - + private Gtk.Notebook tabs = null; - + ///////////////////////////////////////////////////////////////////// /// The main window. ///////////////////////////////////////////////////////////////////// - + private Gtk.Window window = null; - + ///////////////////////////////////////////////////////////////////// /// A little structure containing data for one icon in the icon_view. ///////////////////////////////////////////////////////////////////// @@ -109,19 +109,19 @@ public class IconSelectWindow : GLib.Object { public IconContext context; public Gdk.Pixbuf pixbuf; } - + ///////////////////////////////////////////////////////////////////// /// This queue is used for icon loading. A loading thread pushes /// icons into it --- the main thread updates the icon_view /// accordingly. ///////////////////////////////////////////////////////////////////// - + private GLib.AsyncQueue load_queue; - + ///////////////////////////////////////////////////////////////////// /// Possible icon types. ///////////////////////////////////////////////////////////////////// - + private enum IconContext { ALL, APPS, @@ -131,20 +131,20 @@ public class IconSelectWindow : GLib.Object { EMOTES, OTHER } - + ///////////////////////////////////////////////////////////////////// /// C'tor, creates a new IconSelectWindow. ///////////////////////////////////////////////////////////////////// - + public IconSelectWindow(Gtk.Window parent) { try { this.load_queue = new GLib.AsyncQueue(); - + if (IconSelectWindow.icon_list == null) { IconSelectWindow.icon_list = new Gtk.ListStore(3, typeof(string), // icon name typeof(IconContext), // icon type typeof(Gdk.Pixbuf)); // the icon itself - + // disable sorting until all icons are loaded // else loading becomes horribly slow IconSelectWindow.icon_list.set_default_sort_func(() => {return 0;}); @@ -155,10 +155,10 @@ public class IconSelectWindow : GLib.Object { else IconSelectWindow.need_reload = true; }); } - + // make the icon_view filterable this.icon_list_filtered = new Gtk.TreeModelFilter(IconSelectWindow.icon_list, null); - + Gtk.Builder builder = new Gtk.Builder(); builder.add_from_file (Paths.ui_files + "/icon_select.ui"); @@ -166,42 +166,38 @@ public class IconSelectWindow : GLib.Object { this.window = builder.get_object("window") as Gtk.Window; this.window.set_transient_for(parent); this.window.set_modal(true); - + this.tabs = builder.get_object("tabs") as Gtk.Notebook; - + this.spinner = builder.get_object("spinner") as Gtk.Spinner; this.spinner.start(); - + (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); - - var combo_box = builder.get_object("combo-box") as Gtk.VBox; - + + var combo_box = builder.get_object("combo-box") as Gtk.Box; + // context combo - #if HAVE_GTK_3 - var context_combo = new Gtk.ComboBoxText(); - #else - var context_combo = new Gtk.ComboBox.text(); - #endif - context_combo.append_text(_("All icons")); - context_combo.append_text(_("Applications")); - context_combo.append_text(_("Actions")); - context_combo.append_text(_("Places")); - context_combo.append_text(_("File types")); - context_combo.append_text(_("Emotes")); - context_combo.append_text(_("Miscellaneous")); - - context_combo.set_active(0); - - context_combo.changed.connect(() => { - this.icon_list_filtered.refilter(); - }); - + var context_combo = new Gtk.ComboBoxText(); + context_combo.append_text(_("All icons")); + context_combo.append_text(_("Applications")); + context_combo.append_text(_("Actions")); + context_combo.append_text(_("Places")); + context_combo.append_text(_("File types")); + context_combo.append_text(_("Emotes")); + context_combo.append_text(_("Miscellaneous")); + + context_combo.set_active(0); + + context_combo.changed.connect(() => { + this.icon_list_filtered.refilter(); + }); + combo_box.pack_start(context_combo, false, false); - + // string filter entry var filter = builder.get_object("filter-entry") as Gtk.Entry; - + // only display items which have the selected type // and whose name contains the text entered in the entry this.icon_list_filtered.set_visible_func((model, iter) => { @@ -209,25 +205,25 @@ public class IconSelectWindow : GLib.Object { IconContext context = IconContext.ALL; model.get(iter, 0, out name); model.get(iter, 1, out context); - + if (name == null) return false; - + return (context_combo.get_active() == context || context_combo.get_active() == IconContext.ALL) && name.down().contains(filter.text.down()); }); - + // clear when the users clicks on the "clear" icon filter.icon_release.connect((pos, event) => { if (pos == Gtk.EntryIconPosition.SECONDARY) filter.text = ""; }); - + // refilter on input filter.notify["text"].connect(() => { this.icon_list_filtered.refilter(); }); - + // container for the icon_view var scroll = builder.get_object("icon-scrolledwindow") as Gtk.ScrolledWindow; @@ -237,7 +233,7 @@ public class IconSelectWindow : GLib.Object { this.icon_view.item_padding = 2; this.icon_view.pixbuf_column = 2; this.icon_view.tooltip_column = 0; - + // set active_icon if selection changes this.icon_view.selection_changed.connect(() => { foreach (var path in this.icon_view.get_selected_items()) { @@ -246,7 +242,7 @@ public class IconSelectWindow : GLib.Object { this.icon_list_filtered.get(iter, 0, out this.active_icon); } }); - + // hide this window when the user activates an icon this.icon_view.item_activated.connect((path) => { Gtk.TreeIter iter; @@ -255,46 +251,40 @@ public class IconSelectWindow : GLib.Object { this.on_ok(this.active_icon); this.window.hide(); }); - + scroll.add(this.icon_view); - + // file chooser widget this.file_chooser = builder.get_object("filechooser") as Gtk.FileChooserWidget; var file_filter = new Gtk.FileFilter(); file_filter.add_pixbuf_formats(); - - #if HAVE_GTK_3 - file_filter.set_filter_name(_("All supported image formats")); - #else - file_filter.set_name(_("All supported image formats")); - #endif - + file_filter.set_filter_name(_("All supported image formats")); file_chooser.add_filter(file_filter); - + // set active_icon if the user selected a file file_chooser.selection_changed.connect(() => { if (file_chooser.get_filename() != null && GLib.FileUtils.test(file_chooser.get_filename(), GLib.FileTest.IS_REGULAR)) - + this.active_icon = file_chooser.get_filename(); }); - + // hide this window when the user activates a file file_chooser.file_activated.connect(() => { this.active_icon = file_chooser.get_filename(); this.on_ok(this.active_icon); this.window.hide(); }); - + this.window.set_focus(this.icon_view); this.window.delete_event.connect(this.window.hide_on_delete); - + } catch (GLib.Error e) { error("Could not load UI: %s\n", e.message); } } - + ///////////////////////////////////////////////////////////////////// /// Displays the window. The icons are reloaded if neccessary. ///////////////////////////////////////////////////////////////////// @@ -302,27 +292,27 @@ public class IconSelectWindow : GLib.Object { public void show() { this.window.show_all(); this.spinner.hide(); - + if (IconSelectWindow.need_reload) { IconSelectWindow.need_reload = false; this.load_icons(); } - } - + } + public static void clear_icons() { if (IconSelectWindow.icon_list != null) { IconSelectWindow.need_reload = true; IconSelectWindow.icon_list.clear(); } } - + ///////////////////////////////////////////////////////////////////// /// Makes the window select the icon of the given Pie. ///////////////////////////////////////////////////////////////////// - + public void set_icon(string icon) { this.active_icon = icon; - + if (icon.contains("/")) { this.file_chooser.set_filename(icon); this.tabs.set_current_page(1); @@ -330,7 +320,7 @@ public class IconSelectWindow : GLib.Object { this.icon_list_filtered.foreach((model, path, iter) => { string name = ""; model.get(iter, 0, out name); - + if (name == icon) { this.icon_view.select_path(path); this.icon_view.scroll_to_path(path, true, 0.5f, 0.0f); @@ -338,38 +328,38 @@ public class IconSelectWindow : GLib.Object { } return (name == icon); }); - + this.tabs.set_current_page(0); } - } - + } + ///////////////////////////////////////////////////////////////////// /// Called when the user clicks the ok button. ///////////////////////////////////////////////////////////////////// - + private void on_ok_button_clicked() { this.on_ok(this.active_icon); this.window.hide(); } - + ///////////////////////////////////////////////////////////////////// /// Called when the user clicks the cancel button. ///////////////////////////////////////////////////////////////////// - + private void on_cancel_button_clicked() { this.window.hide(); } - + ///////////////////////////////////////////////////////////////////// /// (Re)load all icons. ///////////////////////////////////////////////////////////////////// - + private void load_icons() { // only if it's not loading currently if (!IconSelectWindow.loading) { IconSelectWindow.loading = true; IconSelectWindow.icon_list.clear(); - + // display the spinner if (spinner != null) this.spinner.visible = true; @@ -389,7 +379,7 @@ public class IconSelectWindow : GLib.Object { 1, new_entry.context, 2, new_entry.pixbuf); } - + // enable sorting of the icon_view if loading finished if (!IconSelectWindow.loading) { IconSelectWindow.icon_list.set_sort_column_id(0, Gtk.SortType.ASCENDING); @@ -399,19 +389,19 @@ public class IconSelectWindow : GLib.Object { }); } } - + ///////////////////////////////////////////////////////////////////// /// Loads all icons of an icon theme and pushes them into the /// load_queue. ///////////////////////////////////////////////////////////////////// - + private async void load_all() { var icon_theme = Gtk.IconTheme.get_default(); - + foreach (var context in icon_theme.list_contexts()) { if (!disabled_contexts.contains(context)) { foreach (var icon in icon_theme.list_icons(context)) { - + IconContext icon_context = IconContext.OTHER; switch(context) { case "Apps": case "Applications": @@ -426,31 +416,31 @@ public class IconSelectWindow : GLib.Object { icon_context = IconContext.ACTIONS; break; default: break; } - + Idle.add(load_all.callback); yield; - + try { // create a new entry for the queue var new_entry = new ListEntry(); new_entry.name = icon; new_entry.context = icon_context; new_entry.pixbuf = icon_theme.load_icon(icon, 32, 0); - + // some icons have only weird sizes... do not include them if (new_entry.pixbuf.width == 32) this.load_queue.push(new_entry); - + } catch (GLib.Error e) { warning("Failed to load image " + icon); } } } } - + // finished loading IconSelectWindow.loading = false; - + // hide the spinner if (spinner != null) spinner.visible = false; diff --git a/src/gui/indicator.vala b/src/gui/indicator.vala index 18d4e68..1277fb8 100644 --- a/src/gui/indicator.vala +++ b/src/gui/indicator.vala @@ -68,12 +68,9 @@ public class Indicator : GLib.Object { public Indicator() { string icon = ""; + var screen = (Gdk.X11.Screen)Gdk.Screen.get_default(); - #if HAVE_GTK_3 - if (Gdk.X11Screen.get_window_manager_name(Gdk.Screen.get_default()) == "Mutter") - #else - if (Gdk.x11_screen_get_window_manager_name(Gdk.Screen.get_default()) == "Mutter") - #endif + if (screen.get_window_manager_name() == "Mutter") icon = "gnome-pie"; else icon = "gnome-pie-symbolic"; @@ -114,7 +111,7 @@ public class Indicator : GLib.Object { this.prefs = new PreferencesWindow(); // preferences item - var item = new Gtk.ImageMenuItem.from_stock (Gtk.Stock.PREFERENCES, null); + var item = new Gtk.ImageMenuItem.with_mnemonic(_("_Preferences")); item.activate.connect(() => { this.prefs.show(); }); @@ -123,7 +120,7 @@ public class Indicator : GLib.Object { menu.append(item); // about item - item = new Gtk.ImageMenuItem.from_stock (Gtk.Stock.ABOUT, null); + item = new Gtk.ImageMenuItem.with_mnemonic(_("_About")); item.show(); item.activate.connect(() => { var about = new AboutWindow(); @@ -138,7 +135,7 @@ public class Indicator : GLib.Object { menu.append(sepa); // quit item - item = new Gtk.ImageMenuItem.from_stock(Gtk.Stock.QUIT, null); + item = new Gtk.ImageMenuItem.with_mnemonic(_("_Quit")); item.activate.connect(Gtk.main_quit); item.show(); menu.append(item); diff --git a/src/gui/newSliceWindow.vala b/src/gui/newSliceWindow.vala index ade6432..92c7701 100644 --- a/src/gui/newSliceWindow.vala +++ b/src/gui/newSliceWindow.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,12 +12,12 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// A window which allows selection of a new Slice which is about to be /// added to a Pie. It can be also used to edit an existing Slice ///////////////////////////////////////////////////////////////////////// @@ -28,7 +28,7 @@ public class NewSliceWindow : GLib.Object { /// This signal gets emitted when the user confirms his selection. ///////////////////////////////////////////////////////////////////// - public signal void on_select(ActionGroup action, bool as_new_slice, int at_position); + public signal void on_select(ActionGroup action, bool as_new_slice, int at_position); ///////////////////////////////////////////////////////////////////// /// The contained list of slice types. It contains both: Groups and @@ -36,78 +36,78 @@ public class NewSliceWindow : GLib.Object { ///////////////////////////////////////////////////////////////////// private SliceTypeList slice_type_list = null; - + ///////////////////////////////////////////////////////////////////// /// The IconSelectWindow used for icon selection for a Slice. ///////////////////////////////////////////////////////////////////// - + private IconSelectWindow? icon_window = null; - + ///////////////////////////////////////////////////////////////////// /// Some widgets of this window. Loaded by a ui-builder and stored /// for later access. ///////////////////////////////////////////////////////////////////// - + private Gtk.Dialog window = null; - private Gtk.HBox name_box = null; - private Gtk.HBox command_box = null; + private Gtk.Box name_box = null; + private Gtk.Box command_box = null; private Gtk.Button icon_button = null; - private Gtk.VBox no_options_box = null; - private Gtk.HBox pie_box = null; - private Gtk.HBox hotkey_box = null; - private Gtk.HBox uri_box = null; - private Gtk.HBox quickaction_box = null; + private Gtk.Box no_options_box = null; + private Gtk.Box pie_box = null; + private Gtk.Box hotkey_box = null; + private Gtk.Box uri_box = null; + private Gtk.Box quickaction_box = null; private Gtk.Image icon = null; private Gtk.Entry name_entry = null; private Gtk.Entry command_entry = null; private Gtk.Entry uri_entry = null; private Gtk.CheckButton quickaction_checkbutton = null; - + ///////////////////////////////////////////////////////////////////// /// Two custom widgets. For Pie and hotkey selection respectively. ///////////////////////////////////////////////////////////////////// - + private PieComboList pie_select = null; private TriggerSelectButton key_select = null; - + ///////////////////////////////////////////////////////////////////// /// These members store information on the currently selected Slice. ///////////////////////////////////////////////////////////////////// - + private string current_type = ""; private string current_icon = ""; private string current_id = ""; private string current_custom_icon = ""; private string current_hotkey = ""; private string current_pie_to_open = ""; - + ///////////////////////////////////////////////////////////////////// /// The position of the edited Slice in its parent Pie. ///////////////////////////////////////////////////////////////////// - + private int slice_position = 0; - + ///////////////////////////////////////////////////////////////////// /// True, if the Slice i going to be added as a new Slice. Else it /// will edit the Slice at slice_position in its parent Pie. ///////////////////////////////////////////////////////////////////// - + private bool add_as_new_slice = true; - + ///////////////////////////////////////////////////////////////////// /// C'tor creates a new window. ///////////////////////////////////////////////////////////////////// - + public NewSliceWindow() { try { - + Gtk.Builder builder = new Gtk.Builder(); builder.add_from_file (Paths.ui_files + "/slice_select.ui"); - + this.slice_type_list = new SliceTypeList(); this.slice_type_list.on_select.connect((type, icon) => { - + this.name_box.hide(); this.command_box.hide(); this.icon_button.sensitive = false; @@ -116,9 +116,9 @@ public class NewSliceWindow : GLib.Object { this.hotkey_box.hide(); this.uri_box.hide(); this.quickaction_box.hide(); - + this.current_type = type; - + switch (type) { case "bookmarks": case "clipboard": case "devices": case "menu": case "session": case "window_list": @@ -156,101 +156,101 @@ public class NewSliceWindow : GLib.Object { break; } }); - - this.name_box = builder.get_object("name-box") as Gtk.HBox; - this.command_box = builder.get_object("command-box") as Gtk.HBox; + + this.name_box = builder.get_object("name-box") as Gtk.Box; + this.command_box = builder.get_object("command-box") as Gtk.Box; this.icon_button = builder.get_object("icon-button") as Gtk.Button; - this.no_options_box = builder.get_object("no-options-box") as Gtk.VBox; - this.pie_box = builder.get_object("pie-box") as Gtk.HBox; + this.no_options_box = builder.get_object("no-options-box") as Gtk.Box; + this.pie_box = builder.get_object("pie-box") as Gtk.Box; this.pie_select = new PieComboList(); this.pie_select.on_select.connect((id) => { this.current_pie_to_open = id; this.set_icon(PieManager.all_pies[id].icon); }); - + this.pie_box.pack_start(this.pie_select, true, true); - - this.hotkey_box = builder.get_object("hotkey-box") as Gtk.HBox; + + this.hotkey_box = builder.get_object("hotkey-box") as Gtk.Box; this.key_select = new TriggerSelectButton(false); this.hotkey_box.pack_start(this.key_select, false, true); this.key_select.on_select.connect((trigger) => { this.current_hotkey = trigger.name; }); - - this.uri_box = builder.get_object("uri-box") as Gtk.HBox; - + + this.uri_box = builder.get_object("uri-box") as Gtk.Box; + this.name_entry = builder.get_object("name-entry") as Gtk.Entry; this.uri_entry = builder.get_object("uri-entry") as Gtk.Entry; this.command_entry = builder.get_object("command-entry") as Gtk.Entry; this.quickaction_checkbutton = builder.get_object("quick-action-checkbutton") as Gtk.CheckButton; - - this.quickaction_box = builder.get_object("quickaction-box") as Gtk.HBox; - this.icon = builder.get_object("icon") as Gtk.Image; - + + this.quickaction_box = builder.get_object("quickaction-box") as Gtk.Box; + this.icon = builder.get_object("icon") as Gtk.Image; + this.icon_button.clicked.connect(on_icon_button_clicked); - + var scroll_area = builder.get_object("slice-scrolledwindow") as Gtk.ScrolledWindow; scroll_area.add(this.slice_type_list); this.window = builder.get_object("window") as Gtk.Dialog; - + (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); } - + ///////////////////////////////////////////////////////////////////// /// Sows the window on the screen. ///////////////////////////////////////////////////////////////////// - + public void show() { this.slice_type_list.select_first(); this.pie_select.select_first(); this.key_select.set_trigger(new Trigger()); this.window.show_all(); } - + ///////////////////////////////////////////////////////////////////// /// Reloads the window. ///////////////////////////////////////////////////////////////////// - + public void reload() { this.pie_select.reload(); } - + ///////////////////////////////////////////////////////////////////// /// Makes all widgets display stuff according to the given action. ///////////////////////////////////////////////////////////////////// - + public void set_action(ActionGroup group, int position) { this.set_default(group.parent_id, position); - + this.add_as_new_slice = false; string type = ""; - + if (group.get_type().depth() == 2) { var action = group.actions[0]; type = ActionRegistry.descriptions[action.get_type().name()].id; this.select_type(type); - + this.set_icon(action.icon); this.quickaction_checkbutton.active = action.is_quickaction; this.name_entry.text = action.name; - + switch (type) { case "app": this.current_custom_icon = action.icon; @@ -269,17 +269,17 @@ public class NewSliceWindow : GLib.Object { this.uri_entry.text = action.real_command; break; } - + } else { type = GroupRegistry.descriptions[group.get_type().name()].id; this.select_type(type); } } - + ///////////////////////////////////////////////////////////////////// /// Selects a default action. ///////////////////////////////////////////////////////////////////// - + public void set_default(string pie_id, int position) { this.slice_position = position; this.add_as_new_slice = true; @@ -292,25 +292,25 @@ public class NewSliceWindow : GLib.Object { this.command_entry.text = ""; this.uri_entry.text = ""; } - + ///////////////////////////////////////////////////////////////////// /// Selects a specific action type. ///////////////////////////////////////////////////////////////////// - + private void select_type(string type) { this.current_type = type; this.slice_type_list.select(type); } - + ///////////////////////////////////////////////////////////////////// /// Called, when the user presses the ok button. ///////////////////////////////////////////////////////////////////// - + private void on_ok_button_clicked() { this.window.hide(); - + ActionGroup group = null; - + switch (this.current_type) { case "bookmarks": group = new BookmarkGroup(this.current_id); break; case "clipboard": group = new ClipboardGroup(this.current_id); break; @@ -321,44 +321,44 @@ public class NewSliceWindow : GLib.Object { case "app": group = new ActionGroup(this.current_id); - group.add_action(new AppAction(this.name_entry.text, this.current_icon, - this.command_entry.text, + group.add_action(new AppAction(this.name_entry.text, this.current_icon, + this.command_entry.text, this.quickaction_checkbutton.active)); break; case "key": group = new ActionGroup(this.current_id); - group.add_action(new KeyAction(this.name_entry.text, this.current_icon, - this.current_hotkey, + group.add_action(new KeyAction(this.name_entry.text, this.current_icon, + this.current_hotkey, this.quickaction_checkbutton.active)); break; case "pie": group = new ActionGroup(this.current_id); - group.add_action(new PieAction(this.current_pie_to_open, + group.add_action(new PieAction(this.current_pie_to_open, this.quickaction_checkbutton.active)); break; case "uri": group = new ActionGroup(this.current_id); - group.add_action(new UriAction(this.name_entry.text, this.current_icon, - this.uri_entry.text, + group.add_action(new UriAction(this.name_entry.text, this.current_icon, + this.uri_entry.text, this.quickaction_checkbutton.active)); break; } - + this.on_select(group, this.add_as_new_slice, this.slice_position); } - + ///////////////////////////////////////////////////////////////////// /// Called when the user presses the cancel button. ///////////////////////////////////////////////////////////////////// - + private void on_cancel_button_clicked() { this.window.hide(); - } - + } + ///////////////////////////////////////////////////////////////////// /// Called when the user presses the icon select button. ///////////////////////////////////////////////////////////////////// - + private void on_icon_button_clicked(Gtk.Button button) { if (this.icon_window == null) { this.icon_window = new IconSelectWindow(this.window); @@ -367,30 +367,30 @@ public class NewSliceWindow : GLib.Object { this.set_icon(icon); }); } - + this.icon_window.show(); this.icon_window.set_icon(this.current_icon); } - + ///////////////////////////////////////////////////////////////////// /// Helper method which sets the icon of the icon select button. /// It assures that both can be displayed: A customly chosen image /// from or an icon from the current theme. ///////////////////////////////////////////////////////////////////// - + private void set_icon(string icon) { if (icon.contains("/")) try { - this.icon.pixbuf = new Gdk.Pixbuf.from_file_at_scale(icon, this.icon.get_pixel_size(), + this.icon.pixbuf = new Gdk.Pixbuf.from_file_at_scale(icon, this.icon.get_pixel_size(), this.icon.get_pixel_size(), true); } catch (GLib.Error error) { warning(error.message); } else this.icon.icon_name = icon; - + this.current_icon = icon; - } + } } } diff --git a/src/gui/newsWindow.vala b/src/gui/newsWindow.vala index 75de60e..373135f 100644 --- a/src/gui/newsWindow.vala +++ b/src/gui/newsWindow.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,57 +12,57 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// -/// +///////////////////////////////////////////////////////////////////////// +/// ///////////////////////////////////////////////////////////////////////// public class NewsWindow: Gtk.Dialog { public static const int news_count = 2; - + ///////////////////////////////////////////////////////////////////// - /// + /// ///////////////////////////////////////////////////////////////////// public NewsWindow () { this.title = "Gnome-Pie"; - + this.set_border_width(5); - - var box = new Gtk.VBox(false, 12); - + + var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 12); + var image = new Gtk.Image.from_icon_name("gnome-pie", Gtk.IconSize.DIALOG); box.pack_start(image); - + var news = new Gtk.Label(""); news.wrap = true; news.set_width_chars(75); news.set_markup("Thank you!\n\n"); - + box.pack_start(news, false, false); - + var check = new Gtk.CheckButton.with_label("Don't show this window again."); check.toggled.connect((check_box) => { var checky = check_box as Gtk.CheckButton; - + if (checky.active) Config.global.showed_news = news_count; else Config.global.showed_news = news_count-1; - + Config.global.save(); }); - + box.pack_end(check); - + (this.get_content_area() as Gtk.VBox).pack_start(box); this.get_content_area().show_all(); - - this.add_button(Gtk.Stock.CLOSE, 0); - + + this.add_button(_("_Close"), 0); + this.response.connect((id) => { if (id == 0) this.hide(); diff --git a/src/gui/piePreview.vala b/src/gui/piePreview.vala index 3ddf6c8..0420d5e 100644 --- a/src/gui/piePreview.vala +++ b/src/gui/piePreview.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,12 +12,12 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// A custom widget displaying the preview of a Pie. It can be used to /// configure the displayed Pie in various aspects. ///////////////////////////////////////////////////////////////////////// @@ -31,42 +31,42 @@ class PiePreview : Gtk.DrawingArea { public signal void on_last_slice_removed(); public signal void on_first_slice_added(); - + ///////////////////////////////////////////////////////////////////// /// The internally used renderer to draw the Pie. ///////////////////////////////////////////////////////////////////// private PiePreviewRenderer renderer = null; - + ///////////////////////////////////////////////////////////////////// /// The window which pops up, when a Slice is added or edited. ///////////////////////////////////////////////////////////////////// - + private NewSliceWindow? new_slice_window = null; - + ///////////////////////////////////////////////////////////////////// /// A timer used for calculating the frame time. ///////////////////////////////////////////////////////////////////// - + private GLib.Timer timer; - + ///////////////////////////////////////////////////////////////////// /// True, when it is possible to drag a slice from this widget. /// False, when the user currently hovers over the add sign. ///////////////////////////////////////////////////////////////////// - + private bool drag_enabled = false; - + ///////////////////////////////////////////////////////////////////// /// The ID of the currently displayed Pie. ///////////////////////////////////////////////////////////////////// - + private string current_id = ""; - + ///////////////////////////////////////////////////////////////////// /// The position from where a Slice-drag started. ///////////////////////////////////////////////////////////////////// - + private int drag_start_index = -1; private string drag_start_id = ""; @@ -75,50 +75,45 @@ class PiePreview : Gtk.DrawingArea { ///////////////////////////////////////////////////////////////////// public PiePreview() { - this.renderer = new PiePreviewRenderer(); - - #if HAVE_GTK_3 - this.draw.connect(this.on_draw); - #else - this.expose_event.connect(this.on_draw); - #endif - + this.renderer = new PiePreviewRenderer(this); + + this.draw.connect(this.on_draw); this.timer = new GLib.Timer(); - this.set_events(Gdk.EventMask.POINTER_MOTION_MASK + this.set_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK); - + // setup drag and drop this.enable_drag_source(); - + Gtk.TargetEntry uri_dest = {"text/uri-list", 0, 0}; Gtk.TargetEntry slice_dest = {"text/plain", Gtk.TargetFlags.SAME_WIDGET, 0}; Gtk.TargetEntry[] destinations = { uri_dest, slice_dest }; Gtk.drag_dest_set(this, Gtk.DestDefaults.ALL, destinations, Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK); - + this.drag_begin.connect(this.on_start_drag); this.drag_end.connect(this.on_end_drag); this.drag_data_received.connect(this.on_dnd_received); - + // connect mouse events this.drag_motion.connect(this.on_drag_move); this.leave_notify_event.connect(this.on_mouse_leave); - this.enter_notify_event.connect(this.on_mouse_enter); + this.enter_notify_event.connect(this.on_mouse_enter); this.motion_notify_event.connect_after(this.on_mouse_move); this.button_release_event.connect_after(this.on_button_release); this.button_press_event.connect_after(this.on_button_press); - + this.new_slice_window = new NewSliceWindow(); this.new_slice_window.on_select.connect((new_action, as_new_slice, at_position) => { var pie = PieManager.all_pies[this.current_id]; - + if (new_action.has_quickaction()) renderer.disable_quickactions(); - + if (as_new_slice) { pie.add_group(new_action, at_position+1); this.renderer.add_group(new_action, at_position+1); - + if (this.renderer.slice_count() == 1) this.on_first_slice_added(); } else { @@ -126,72 +121,74 @@ class PiePreview : Gtk.DrawingArea { this.renderer.update_group(new_action, at_position); } }); - + this.renderer.on_edit_slice.connect((pos) => { this.new_slice_window.reload(); - + this.new_slice_window.set_parent(this.get_toplevel() as Gtk.Window); this.new_slice_window.show(); - + var pie = PieManager.all_pies[this.current_id]; this.new_slice_window.set_action(pie.action_groups[pos], pos); }); - + this.renderer.on_add_slice.connect((pos) => { this.new_slice_window.reload(); - + this.new_slice_window.set_parent(this.get_toplevel() as Gtk.Window); this.new_slice_window.show(); - + this.new_slice_window.set_default(this.current_id, pos); }); - + this.renderer.on_remove_slice.connect((pos) => { - + var dialog = new Gtk.MessageDialog(this.get_toplevel() as Gtk.Window, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _("Do you really want to delete this Slice?")); - + dialog.response.connect((response) => { if (response == Gtk.ResponseType.YES) { var pie = PieManager.all_pies[this.current_id]; - + pie.remove_group(pos); this.renderer.remove_group(pos); - + if (this.renderer.slice_count() == 0) this.on_last_slice_removed(); } }); - + dialog.run(); dialog.destroy(); }); } - + ///////////////////////////////////////////////////////////////////// /// Sets the currently displayed Pie to the Pie with the given ID. ///////////////////////////////////////////////////////////////////// - + public void set_pie(string id) { + var style = this.get_style_context(); + this.current_id = id; - this.modify_bg(Gtk.StateType.NORMAL, Gtk.rc_get_style(this).light[Gtk.StateType.NORMAL]); + this.override_background_color(Gtk.StateFlags.NORMAL, style.get_background_color(Gtk.StateFlags.NORMAL)); this.renderer.load_pie(PieManager.all_pies[id]); - + if (id == this.drag_start_id) { this.renderer.hide_group(this.drag_start_index); } } - + ///////////////////////////////////////////////////////////////////// /// Begins the draw loop. It automatically ends, when the containing /// window becomes invisible. ///////////////////////////////////////////////////////////////////// - + public void draw_loop() { this.timer.start(); this.queue_draw(); - + GLib.Timeout.add((uint)(1000.0/Config.global.refresh_rate), () => { this.queue_draw(); return this.get_toplevel().visible; @@ -201,97 +198,92 @@ class PiePreview : Gtk.DrawingArea { ///////////////////////////////////////////////////////////////////// /// Called every frame. ///////////////////////////////////////////////////////////////////// - - #if HAVE_GTK_3 - private bool on_draw(Cairo.Context ctx) { - #else - private bool on_draw(Gtk.Widget da, Gdk.EventExpose event) { - var ctx = Gdk.cairo_create(this.get_window()); - #endif + + private bool on_draw(Cairo.Context ctx) { // store the frame time double frame_time = this.timer.elapsed(); this.timer.reset(); - + Gtk.Allocation allocation; this.get_allocation(out allocation); - + ctx.translate((int)(allocation.width*0.5), (int)(allocation.height*0.5)); - + this.renderer.draw(frame_time, ctx); - + return true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the mouse leaves the area of this widget. ///////////////////////////////////////////////////////////////////// - + public bool on_mouse_leave(Gdk.EventCrossing event) { this.renderer.on_mouse_leave(); return true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the mouse enters the area of this widget. ///////////////////////////////////////////////////////////////////// - + public bool on_mouse_enter(Gdk.EventCrossing event) { this.renderer.on_mouse_enter(); return true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the mouse moves in the area of this widget. ///////////////////////////////////////////////////////////////////// - + private bool on_mouse_move(Gdk.EventMotion event) { this.renderer.set_dnd_mode(false); Gtk.Allocation allocation; this.get_allocation(out allocation); this.renderer.on_mouse_move(event.x-allocation.width*0.5, event.y-allocation.height*0.5); - + if (this.renderer.get_active_slice() < 0) this.disable_drag_source(); else this.enable_drag_source(); - + return true; } - + ///////////////////////////////////////////////////////////////////// /// Called when a mouse button is pressed. ///////////////////////////////////////////////////////////////////// - + private bool on_button_press() { this.renderer.on_button_press(); return true; } - + ///////////////////////////////////////////////////////////////////// /// Called when a mouse button is released. ///////////////////////////////////////////////////////////////////// - + private bool on_button_release() { - if (!this.renderer.drag_n_drop_mode) + if (!this.renderer.drag_n_drop_mode) this.renderer.on_button_release(); return true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the mouse is moved over this widget. ///////////////////////////////////////////////////////////////////// - + private bool on_drag_move(Gdk.DragContext ctx, int x, int y, uint time) { this.renderer.set_dnd_mode(true); Gtk.Allocation allocation; this.get_allocation(out allocation); this.renderer.on_mouse_move(x-allocation.width*0.5, y-allocation.height*0.5); - + return true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the user tries to drag something from this widget. ///////////////////////////////////////////////////////////////////// - + private void on_start_drag(Gdk.DragContext ctx) { this.drag_start_index = this.renderer.get_active_slice(); this.drag_start_id = this.current_id; @@ -300,19 +292,19 @@ class PiePreview : Gtk.DrawingArea { this.renderer.hide_group(this.drag_start_index); Gtk.drag_set_icon_pixbuf(ctx, pixbuf, icon.size()/2, icon.size()/2); - + this.renderer.set_dnd_mode(true); } - + ///////////////////////////////////////////////////////////////////// /// Called when the user finishes a drag operation on this widget. /// Only used for Slice-movement. ///////////////////////////////////////////////////////////////////// - + private void on_end_drag(Gdk.DragContext context) { - + if (context.list_targets() != null) { - + int target_index = this.renderer.get_active_slice(); this.renderer.set_dnd_mode(false); @@ -328,48 +320,48 @@ class PiePreview : Gtk.DrawingArea { var dst_pie = PieManager.all_pies[this.current_id]; dst_pie.add_group(src_pie.action_groups[this.drag_start_index], target_index); this.renderer.add_group(dst_pie.action_groups[target_index], target_index); - + if (this.renderer.slices.size == 1) this.on_first_slice_added(); - + if ((context.get_actions() & Gdk.DragAction.COPY) == 0) src_pie.remove_group(this.drag_start_index); } - - + + } }); - + this.drag_start_index = -1; this.drag_start_id = ""; - } + } } - + ///////////////////////////////////////////////////////////////////// /// Called when the user finishes a drag operation on this widget. /// Only used for external drags. ///////////////////////////////////////////////////////////////////// - - private void on_dnd_received(Gdk.DragContext context, int x, int y, + + private void on_dnd_received(Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint info, uint time_) { - + var pie = PieManager.all_pies[this.current_id]; int position = this.renderer.get_active_slice(); this.renderer.set_dnd_mode(false); - + foreach (var uri in selection_data.get_uris()) { pie.add_action(ActionRegistry.new_for_uri(uri), position); this.renderer.add_group(pie.action_groups[position], position); - + if (this.renderer.slices.size == 1) this.on_first_slice_added(); } } - + ///////////////////////////////////////////////////////////////////// /// Enables this widget to be a source for drag operations. ///////////////////////////////////////////////////////////////////// - + private void enable_drag_source() { if (!this.drag_enabled) { this.drag_enabled = true; @@ -378,18 +370,18 @@ class PiePreview : Gtk.DrawingArea { Gtk.drag_source_set(this, Gdk.ModifierType.BUTTON1_MASK, sources, Gdk.DragAction.MOVE | Gdk.DragAction.COPY); } } - + ///////////////////////////////////////////////////////////////////// /// Disables this widget to be a source for drag operations. - ///////////////////////////////////////////////////////////////////// - + ///////////////////////////////////////////////////////////////////// + private void disable_drag_source() { if (this.drag_enabled) { this.drag_enabled = false; Gtk.drag_source_unset(this); } } - + } } diff --git a/src/gui/piePreviewCenter.vala b/src/gui/piePreviewCenter.vala index 21bbd78..20527bc 100644 --- a/src/gui/piePreviewCenter.vala +++ b/src/gui/piePreviewCenter.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,79 +12,80 @@ 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 . +this program. If not, see . */ using GLib.Math; namespace GnomePie { -///////////////////////////////////////////////////////////////////////// -/// +///////////////////////////////////////////////////////////////////////// +/// ///////////////////////////////////////////////////////////////////////// public class PiePreviewCenter : GLib.Object { - + ///////////////////////////////////////////////////////////////////// /// THe Images displayed. When the displayed text changes the /// currently displayed text becomes the old_text. So it's possible /// to create a smooth transitions. ///////////////////////////////////////////////////////////////////// - + private RenderedText text = null; private RenderedText old_text = null; - + ///////////////////////////////////////////////////////////////////// /// Stores the currently displayed text in order to avoid frequent /// and useless updates. ///////////////////////////////////////////////////////////////////// - + private string current_text = null; - + ///////////////////////////////////////////////////////////////////// /// An AnimatedValue for smooth transitions. ///////////////////////////////////////////////////////////////////// - - private AnimatedValue blend; - + + private AnimatedValue blend; + ///////////////////////////////////////////////////////////////////// /// The parent renderer. ///////////////////////////////////////////////////////////////////// - - private unowned PiePreviewRenderer parent; - + + private unowned PiePreviewRenderer parent; + ///////////////////////////////////////////////////////////////////// /// C'tor, sets everything up. ///////////////////////////////////////////////////////////////////// - + public PiePreviewCenter(PiePreviewRenderer parent) { this.parent = parent; this.blend = new AnimatedValue.linear(0, 0, 0); - + this.text = new RenderedText("", 1, 1, "", new Color(), 1.0); this.old_text = text; } - + ///////////////////////////////////////////////////////////////////// /// Updates the currently displayed text. It will be smoothly - /// blended and may contain pango markup. + /// blended and may contain pango markup. ///////////////////////////////////////////////////////////////////// - + public void set_text(string text) { if (text != this.current_text) { - - var style = new Gtk.Style(); - + + var style = parent.parent.get_style_context(); + this.old_text = this.text; - this.text = new RenderedText.with_markup(text, 180, 180, style.font_desc.get_family()+" 10", - new Color.from_gdk(style.fg[0]), 1.0); + this.text = new RenderedText.with_markup( + text, 180, 180, style.get_font(Gtk.StateFlags.NORMAL).get_family()+" 10", + new Color.from_gdk(style.get_color(Gtk.StateFlags.NORMAL)), 1.0); this.current_text = text; - + this.blend.reset_target(0.0, 0.0); this.blend.reset_target(1.0, 0.1); } } - + ///////////////////////////////////////////////////////////////////// /// Draws the center to the given context. ///////////////////////////////////////////////////////////////////// @@ -92,15 +93,15 @@ public class PiePreviewCenter : GLib.Object { public void draw(double frame_time, Cairo.Context ctx) { this.blend.update(frame_time); - + ctx.save(); - - if (this.parent.slice_count() == 0) + + if (this.parent.slice_count() == 0) ctx.translate(0, 40); - + this.old_text.paint_on(ctx, 1-this.blend.val); this.text.paint_on(ctx, this.blend.val); - + ctx.restore(); } } diff --git a/src/gui/piePreviewRenderer.vala b/src/gui/piePreviewRenderer.vala index 6fff397..626ab73 100644 --- a/src/gui/piePreviewRenderer.vala +++ b/src/gui/piePreviewRenderer.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,110 +12,117 @@ 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 . +this program. If not, see . */ using GLib.Math; namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// A complex class which is able to draw the preview of a Pie. It can /// manipulate the displayed Pie as well. ///////////////////////////////////////////////////////////////////////// public class PiePreviewRenderer : GLib.Object { - + ///////////////////////////////////////////////////////////////////// /// These signals get emitted when a slice is added, removed or /// manipulated. ///////////////////////////////////////////////////////////////////// - + public signal void on_add_slice(int position); public signal void on_remove_slice(int position); public signal void on_edit_slice(int position); - + ///////////////////////////////////////////////////////////////////// /// True, when there is currently a drag going on. ///////////////////////////////////////////////////////////////////// - + public bool drag_n_drop_mode { get; private set; default=false; } - + ///////////////////////////////////////////////////////////////////// /// A list containing all SliceRenderers of this Pie. ///////////////////////////////////////////////////////////////////// - + public Gee.ArrayList slices; - + ///////////////////////////////////////////////////////////////////// /// When a Slice is moved within a Pie it is temporarily removed. /// If so, it is stored in this member. ///////////////////////////////////////////////////////////////////// - + public PiePreviewSliceRenderer hidden_group { get; private set; default=null; } - + ///////////////////////////////////////////////////////////////////// /// The add sign which indicates that a new Slice could be added. ///////////////////////////////////////////////////////////////////// - + private PiePreviewAddSign add_sign = null; - + ///////////////////////////////////////////////////////////////////// /// The object which renders the name of the currently selected Slice /// in the middle. ///////////////////////////////////////////////////////////////////// - + private PiePreviewCenter center_renderer = null; private enum CenterDisplay { NONE, ACTIVE_SLICE, DROP, ADD, DELETE } - + ///////////////////////////////////////////////////////////////////// /// Some members storing some inter-frame-information. ///////////////////////////////////////////////////////////////////// private int active_slice = -1; - private double angle = 0.0; + private double angle = 0.0; private double mouse_x = 0.0; private double mouse_y = 0.0; - + + ///////////////////////////////////////////////////////////////////// + /// The parent DrawingArea. + ///////////////////////////////////////////////////////////////////// + + public unowned Gtk.DrawingArea parent; + ///////////////////////////////////////////////////////////////////// /// C'tor, initializes members. ///////////////////////////////////////////////////////////////////// - - public PiePreviewRenderer() { - this.slices = new Gee.ArrayList(); + + public PiePreviewRenderer(Gtk.DrawingArea parent) { + this.parent = parent; + this.slices = new Gee.ArrayList(); this.center_renderer = new PiePreviewCenter(this); this.add_sign = new PiePreviewAddSign(this); this.add_sign.load(); - + this.add_sign.on_clicked.connect((pos) => { this.on_add_slice(pos); }); } - + ///////////////////////////////////////////////////////////////////// /// Loads an Pie. All members are initialized accordingly. ///////////////////////////////////////////////////////////////////// - + public void load_pie(Pie pie) { this.slices.clear(); - + foreach (var group in pie.action_groups) { var renderer = new PiePreviewSliceRenderer(this); renderer.load(group); - + this.add_slice_renderer(renderer); this.connect_siganls(renderer); } - + this.active_slice = -1; this.update_sizes(); this.update_positions(false); } - + ///////////////////////////////////////////////////////////////////// /// Enables or disables the drag n dropn mode. ///////////////////////////////////////////////////////////////////// - + public void set_dnd_mode(bool dnd) { if (this.drag_n_drop_mode != dnd) { this.drag_n_drop_mode = dnd; @@ -123,144 +130,144 @@ public class PiePreviewRenderer : GLib.Object { this.update_sizes(); } } - + ///////////////////////////////////////////////////////////////////// /// Returns the number of Slices. ///////////////////////////////////////////////////////////////////// - + public int slice_count() { - if (this.drag_n_drop_mode && !(this.slices.size == 0)) + if (this.drag_n_drop_mode && !(this.slices.size == 0)) return slices.size+1; - + return slices.size; } - + ///////////////////////////////////////////////////////////////////// /// Returns the index of the currently hovered Slice. ///////////////////////////////////////////////////////////////////// - + public int get_active_slice() { if (this.slices.size == 0) return 0; - + if (this.drag_n_drop_mode) return (int)(this.angle/(2*PI)*this.slice_count() + 0.5) % this.slice_count(); - + return this.active_slice; } - + ///////////////////////////////////////////////////////////////////// /// Returns the Icon of the currently hovered Slice. ///////////////////////////////////////////////////////////////////// - + public Icon get_active_icon() { if (this.active_slice >= 0 && this.active_slice < this.slices.size) return this.slices[this.active_slice].icon; else return new Icon("", 24); } - + ///////////////////////////////////////////////////////////////////// /// Draws the entire Pie to the given context. ///////////////////////////////////////////////////////////////////// - + public void draw(double frame_time, Cairo.Context ctx) { this.add_sign.draw(frame_time, ctx); this.center_renderer.draw(frame_time, ctx); - + foreach (var slice in this.slices) slice.draw(frame_time, ctx); } - + ///////////////////////////////////////////////////////////////////// /// Called when the mouse leaves the drawing area of this renderer. ///////////////////////////////////////////////////////////////////// - + public void on_mouse_leave() { this.add_sign.hide(); this.update_positions(); this.update_center(CenterDisplay.NONE); - + foreach (var slice in this.slices) slice.on_mouse_leave(); } - + ///////////////////////////////////////////////////////////////////// /// Called when the mouse enters the drawing area of this renderer. ///////////////////////////////////////////////////////////////////// - + public void on_mouse_enter() { this.add_sign.show(); this.update_positions(); } - + ///////////////////////////////////////////////////////////////////// /// Called when the mouse moves in the drawing area of this renderer. ///////////////////////////////////////////////////////////////////// - + public void on_mouse_move(double x, double y) { this.mouse_x = x; this.mouse_y = y; - + this.angle = acos(x/sqrt(x*x + y*y)); if (y < 0) this.angle = 2*PI - this.angle; - + if (!this.drag_n_drop_mode) this.active_slice = -1; - + bool delete_hovered = false; - + for (int i=0; i index) { this.slices.remove_at(index); @@ -268,22 +275,22 @@ public class PiePreviewRenderer : GLib.Object { this.update_sizes(); } } - + ///////////////////////////////////////////////////////////////////// /// Hides the Slice at the given position temporarily. ///////////////////////////////////////////////////////////////////// - + public void hide_group(int index) { if (this.slices.size > index) { this.hidden_group = this.slices[index]; this.remove_group(index); } } - + ///////////////////////////////////////////////////////////////////// /// Re-shows a Slice which has been hidden before. ///////////////////////////////////////////////////////////////////// - + public void show_hidden_group_at(int index) { if (this.slices.size >= index && this.hidden_group != null) { this.hidden_group.set_position(index, false); @@ -291,78 +298,78 @@ public class PiePreviewRenderer : GLib.Object { this.hidden_group = null; } } - + ///////////////////////////////////////////////////////////////////// /// Updates a Slice at the given position. ///////////////////////////////////////////////////////////////////// - + public void update_group(ActionGroup group, int index) { if (this.slices.size > index) { var renderer = new PiePreviewSliceRenderer(this); this.slices.set(index, renderer); renderer.load(group); - + this.connect_siganls(renderer); - + this.update_positions(false); this.update_sizes(); } } - + ///////////////////////////////////////////////////////////////////// /// Disables all quickactions of this pie preview. ///////////////////////////////////////////////////////////////////// - + public void disable_quickactions() { foreach (var slice in this.slices) slice.disable_quickactions(); } - + ///////////////////////////////////////////////////////////////////// /// Helper method which adds a new Slice to the given position. ///////////////////////////////////////////////////////////////////// - + private void add_slice_renderer(PiePreviewSliceRenderer renderer, int at_position = -1) { if (at_position < 0 || at_position >= this.slices.size) this.slices.add(renderer); else this.slices.insert(at_position, renderer); - + this.update_positions(false); this.update_sizes(); } - + ///////////////////////////////////////////////////////////////////// /// Helper method which connects all neccessary signals of a newly /// added Slice. ///////////////////////////////////////////////////////////////////// - + private void connect_siganls(PiePreviewSliceRenderer renderer) { renderer.on_clicked.connect((pos) => { this.on_edit_slice(pos); }); - + renderer.on_remove.connect((pos) => { this.on_remove_slice(pos); }); } - + ///////////////////////////////////////////////////////////////////// /// Moves all slices to their positions. This may happen smoothly if /// desired. ///////////////////////////////////////////////////////////////////// - + private void update_positions(bool smoothly = true) { if (this.slices.size > 0) { if (this.add_sign.visible) { int add_position = 0; add_position = (int)(this.angle/(2*PI)*this.slice_count()) % this.slice_count(); this.add_sign.set_position(add_position); - + for (int i=0; i= add_position ? i+1 : i, smoothly); } - + this.update_center(CenterDisplay.DROP); - + } else { for (int i=0; i 20) size = 0.5; else if (this.slice_count() > 8) size = 1.0 - (double)(this.slice_count() - 8)/24.0; - + this.add_sign.set_size(size); - - for (int i=0; i= 0 && this.active_slice < this.slices.size) - this.center_renderer.set_text("" + GLib.Markup.escape_text(slices[this.active_slice].name) + "\n" + this.center_renderer.set_text("" + GLib.Markup.escape_text(slices[this.active_slice].name) + "\n" + _("Click to edit") + "\n" + _("Drag to move") + ""); break; case CenterDisplay.ADD: @@ -423,7 +430,7 @@ public class PiePreviewRenderer : GLib.Object { break; case CenterDisplay.DELETE: if (this.active_slice >= 0 && this.active_slice < this.slices.size) - this.center_renderer.set_text("" + GLib.Markup.escape_text(slices[this.active_slice].name) + "\n" + this.center_renderer.set_text("" + GLib.Markup.escape_text(slices[this.active_slice].name) + "\n" + _("Click to delete") + "\n" + _("Drag to move") + ""); break; default: diff --git a/src/gui/preferencesWindow.vala b/src/gui/preferencesWindow.vala index 3055bc5..8cdc853 100644 --- a/src/gui/preferencesWindow.vala +++ b/src/gui/preferencesWindow.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,164 +12,155 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// The settings menu of Gnome-Pie. ///////////////////////////////////////////////////////////////////////// public class PreferencesWindow : GLib.Object { - + ///////////////////////////////////////////////////////////////////// /// The ID of the currently selected Pie. ///////////////////////////////////////////////////////////////////// - + private string selected_id = ""; - + ///////////////////////////////////////////////////////////////////// /// Some Gtk widgets used by this window. ///////////////////////////////////////////////////////////////////// - + 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.VBox? preview_box = 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; - + ///////////////////////////////////////////////////////////////////// /// Some custom widgets and dialogs used by this window. ///////////////////////////////////////////////////////////////////// - + 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; - + ///////////////////////////////////////////////////////////////////// /// C'tor, creates the window. ///////////////////////////////////////////////////////////////////// - + public PreferencesWindow() { - try { - var builder = new Gtk.Builder(); - - builder.add_from_file (Paths.ui_files + "/preferences.ui"); - - this.window = builder.get_object("window") as Gtk.Window; - - this.window.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | - Gdk.EventMask.KEY_RELEASE_MASK | - Gdk.EventMask.KEY_PRESS_MASK | - Gdk.EventMask.POINTER_MOTION_MASK); - - #if HAVE_GTK_3 - var toolbar = builder.get_object ("toolbar") as Gtk.Widget; - toolbar.get_style_context().add_class("primary-toolbar"); - - var inline_toolbar = builder.get_object ("pies-toolbar") as Gtk.Widget; - inline_toolbar.get_style_context().add_class("inline-toolbar"); - #endif - - this.pie_list = new PieList(); - this.pie_list.on_select.connect(this.on_pie_select); - - var scroll_area = builder.get_object("pies-scrolledwindow") as Gtk.ScrolledWindow; - scroll_area.add(this.pie_list); - - this.preview = new PiePreview(); - this.preview.on_first_slice_added.connect(() => { - this.no_slice_label.hide(); - }); - - this.preview.on_last_slice_removed.connect(() => { - this.no_slice_label.show(); - }); - - preview_box = builder.get_object("preview-box") as Gtk.VBox; - 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.hotkey_button = builder.get_object("key-button") as Gtk.Button; - this.hotkey_button.clicked.connect(on_key_button_clicked); - - this.icon_button = builder.get_object("icon-button") as Gtk.Button; - this.icon_button.clicked.connect(on_icon_button_clicked); - - this.name_button = builder.get_object("rename-button") as Gtk.Button; - this.name_button.clicked.connect(on_rename_button_clicked); - - this.remove_pie_button = builder.get_object("remove-pie-button") as Gtk.ToolButton; - this.remove_pie_button.clicked.connect(on_remove_pie_button_clicked); - - (builder.get_object("add-pie-button") as Gtk.ToolButton).clicked.connect(on_add_pie_button_clicked); - - this.window.hide.connect(() => { - // save settings on close - Config.global.save(); - Pies.save(); - - Timeout.add(100, () => { - IconSelectWindow.clear_icons(); - return false; - }); + var builder = new Gtk.Builder.from_file(Paths.ui_files + "/preferences.ui"); + + this.window = builder.get_object("window") as Gtk.Window; + this.window.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | + Gdk.EventMask.KEY_RELEASE_MASK | + 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"); + + var inline_toolbar = builder.get_object ("pies-toolbar") as Gtk.Widget; + inline_toolbar.get_style_context().add_class("inline-toolbar"); + + this.pie_list = new PieList(); + this.pie_list.on_select.connect(this.on_pie_select); + + var scroll_area = builder.get_object("pies-scrolledwindow") as Gtk.ScrolledWindow; + scroll_area.add(this.pie_list); + + this.preview = new PiePreview(); + this.preview.on_first_slice_added.connect(() => { + this.no_slice_label.hide(); + }); + + this.preview.on_last_slice_removed.connect(() => { + this.no_slice_label.show(); + }); + + 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.hotkey_button = builder.get_object("key-button") as Gtk.Button; + this.hotkey_button.clicked.connect(on_key_button_clicked); + + this.icon_button = builder.get_object("icon-button") as Gtk.Button; + this.icon_button.clicked.connect(on_icon_button_clicked); + + this.name_button = builder.get_object("rename-button") as Gtk.Button; + this.name_button.clicked.connect(on_rename_button_clicked); + + this.remove_pie_button = builder.get_object("remove-pie-button") as Gtk.ToolButton; + this.remove_pie_button.clicked.connect(on_remove_pie_button_clicked); + + (builder.get_object("add-pie-button") as Gtk.ToolButton).clicked.connect(on_add_pie_button_clicked); + + this.window.hide.connect(() => { + // save settings on close + Config.global.save(); + Pies.save(); + + Timeout.add(100, () => { + IconSelectWindow.clear_icons(); + return false; }); - - this.window.delete_event.connect(this.window.hide_on_delete); - - } catch (GLib.Error e) { - error("Could not load UI: %s\n", e.message); - } + }); + + this.window.delete_event.connect(this.window.hide_on_delete); } - + ///////////////////////////////////////////////////////////////////// /// Shows the window. ///////////////////////////////////////////////////////////////////// - + public void show() { this.preview.draw_loop(); this.window.show_all(); this.pie_list.select_first(); - this.preview_background.modify_bg(Gtk.StateType.NORMAL, Gtk.rc_get_style(this.window).light[0]); + + var style = this.preview_background.get_style_context(); + this.preview_background.override_background_color(Gtk.StateFlags.NORMAL, style.get_background_color(Gtk.StateFlags.NORMAL)); } - + ///////////////////////////////////////////////////////////////////// /// Called when a new Pie is selected in the PieList. ///////////////////////////////////////////////////////////////////// - + private void on_pie_select(string id) { selected_id = id; - + this.no_slice_label.hide(); 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; - + if (id == "") { this.id_label.label = ""; this.name_label.label = _("No Pie selected."); @@ -182,51 +173,51 @@ public class PreferencesWindow : GLib.Object { 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.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(); - + if (pie.action_groups.size == 0) { 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; } } - + ///////////////////////////////////////////////////////////////////// /// Called when the add Pie button is clicked. ///////////////////////////////////////////////////////////////////// - + private void on_add_pie_button_clicked(Gtk.ToolButton 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); } - + ///////////////////////////////////////////////////////////////////// /// Called when the remove Pie button is clicked. ///////////////////////////////////////////////////////////////////// - + private void on_remove_pie_button_clicked(Gtk.ToolButton 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, _("Do you really want to delete the selected Pie with all contained Slices?")); - + dialog.response.connect((response) => { if (response == Gtk.ResponseType.YES) { PieManager.remove_pie(selected_id); @@ -234,16 +225,16 @@ public class PreferencesWindow : GLib.Object { this.pie_list.select_first(); } }); - + dialog.run(); dialog.destroy(); } } - + ///////////////////////////////////////////////////////////////////// /// Called when rename Pie button is clicked. ///////////////////////////////////////////////////////////////////// - + private void on_rename_button_clicked(Gtk.Button button) { if (this.rename_window == null) { this.rename_window = new RenameWindow(); @@ -256,15 +247,15 @@ public class PreferencesWindow : GLib.Object { 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(); @@ -274,28 +265,28 @@ public class PreferencesWindow : GLib.Object { 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); @@ -306,7 +297,7 @@ public class PreferencesWindow : GLib.Object { this.pie_list.reload_all(); }); } - + this.icon_window.show(); this.icon_window.set_icon(PieManager.all_pies[selected_id].icon); } diff --git a/src/gui/settingsWindow.vala b/src/gui/settingsWindow.vala index 81f8f7e..b03ae2f 100644 --- a/src/gui/settingsWindow.vala +++ b/src/gui/settingsWindow.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,41 +12,41 @@ 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 . +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; @@ -56,26 +56,26 @@ public class SettingsWindow : GLib.Object { 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.HScale); + + 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; @@ -97,56 +97,64 @@ public class SettingsWindow : GLib.Object { changed_again = true; } }); - + + var range_slider = (builder.get_object("range-hscale") as Gtk.Scale); + range_slider.set_range(100, 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(); + }); + 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.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(); + + 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; @@ -155,9 +163,9 @@ public class SettingsWindow : GLib.Object { } else if (active && !FileUtils.test(Paths.autostart, FileTest.EXISTS)) { Config.global.auto_start = true; - - string autostart_entry = - "#!/usr/bin/env xdg-open\n" + + + string autostart_entry = + "#!/usr/bin/env xdg-open\n" + "[Desktop Entry]\n" + "Name=Gnome-Pie\n" + "Exec=" + Paths.executable + "\n" + @@ -171,7 +179,7 @@ public class SettingsWindow : GLib.Object { 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); @@ -183,20 +191,20 @@ public class SettingsWindow : GLib.Object { } } } - + ///////////////////////////////////////////////////////////////////// /// 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/triggerSelectWindow.vala b/src/gui/triggerSelectWindow.vala index 23eea3c..611c179 100644 --- a/src/gui/triggerSelectWindow.vala +++ b/src/gui/triggerSelectWindow.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,56 +12,56 @@ 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 . +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 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; - + ///////////////////////////////////////////////////////////////////// /// 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"); @@ -69,7 +69,7 @@ public class TriggerSelectWindow : GLib.Object { 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, @@ -78,80 +78,80 @@ public class TriggerSelectWindow : GLib.Object { this.delayed.active, this.centered.active); }); - - (builder.get_object("trigger-box") as Gtk.VBox).pack_start(this.button, true, true); - + + (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.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.original_trigger = trigger; this.trigger = trigger; - + this.button.set_trigger(trigger); } - + ///////////////////////////////////////////////////////////////////// /// Called when one of the three checkoxes 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); } - + ///////////////////////////////////////////////////////////////////// /// 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(); @@ -175,14 +175,14 @@ public class TriggerSelectWindow : GLib.Object { this.window.hide(); } } - + ///////////////////////////////////////////////////////////////////// /// Called when the cancel button is pressed. ///////////////////////////////////////////////////////////////////// - + private void on_cancel_button_clicked() { this.window.hide(); - } + } } } diff --git a/src/images/image.vala b/src/images/image.vala index 197523b..e65e34a 100644 --- a/src/images/image.vala +++ b/src/images/image.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,78 +12,73 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// A class which loads image files. It can load image files in various -/// formats, including jpeg, png and svg. +/// formats, including jpeg, png and svg. ///////////////////////////////////////////////////////////////////////// public class Image : GLib.Object { - + ///////////////////////////////////////////////////////////////////// /// The internally used surface. ///////////////////////////////////////////////////////////////////// - + public Cairo.ImageSurface surface { public get; protected set; default=null; } - + ///////////////////////////////////////////////////////////////////// /// Creates an empty Image. ///////////////////////////////////////////////////////////////////// - + public Image.empty(int width, int height, Color? color = null) { this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height); - + if (color != null) { var ctx = this.context(); ctx.set_source_rgb(color.r, color.g, color.b); ctx.paint(); } } - + ///////////////////////////////////////////////////////////////////// /// Creates an image from the the given filename. ///////////////////////////////////////////////////////////////////// - + public Image.from_file(string filename) { this.load_file(filename); } - + ///////////////////////////////////////////////////////////////////// /// Creates an image from the the given filename at a given size. ///////////////////////////////////////////////////////////////////// - + public Image.from_file_at_size(string filename, int width, int height) { this.load_file_at_size(filename, width, height); } - + ///////////////////////////////////////////////////////////////////// /// Creates an image from the the given Gdk.Pixbuf. ///////////////////////////////////////////////////////////////////// - + public Image.from_pixbuf(Gdk.Pixbuf pixbuf) { if (pixbuf != null) this.load_pixbuf(pixbuf); else this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, 1, 1); } - + ///////////////////////////////////////////////////////////////////// /// Captures a part of the screen. ///////////////////////////////////////////////////////////////////// - + public Image.capture_screen(int posx, int posy, int width, int height, bool hide_pies = true) { Gdk.Window root = Gdk.get_default_root_window(); - #if HAVE_GTK_3 - Gdk.Pixbuf pixbuf = Gdk.pixbuf_get_from_window(root, posx, posy, width, height); - #else - Gdk.Pixbuf pixbuf = Gdk.pixbuf_get_from_drawable(null, root, null, posx, posy, 0, 0, width, height); - #endif - + Gdk.Pixbuf pixbuf = Gdk.pixbuf_get_from_window(root, posx, posy, width, height); this.load_pixbuf(pixbuf); - + if (hide_pies) { // check for opened pies foreach (var window in PieManager.opened_windows) { @@ -93,21 +88,21 @@ public class Image : GLib.Object { window.get_size(out dx, out dy); var ctx = this.context(); - ctx.translate((int)(x-posx + (dx+3)/2), (int)(y-posy + (dy+3)/2)); + ctx.translate((int)(x-posx + (dx+3)/2), (int)(y-posy + (dy+3)/2)); window.background.paint_on(ctx); } } } } - + ///////////////////////////////////////////////////////////////////// /// Loads an image from the the given filename. ///////////////////////////////////////////////////////////////////// - + public void load_file(string filename) { try { var pixbuf = new Gdk.Pixbuf.from_file(filename); - + if (pixbuf != null) { this.load_pixbuf(pixbuf); } else { @@ -119,64 +114,64 @@ public class Image : GLib.Object { this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, 1, 1); } } - + ///////////////////////////////////////////////////////////////////// /// Loads an image from the the given filename at a given size. ///////////////////////////////////////////////////////////////////// - + public void load_file_at_size(string filename, int width, int height) { try { var pixbuf = new Gdk.Pixbuf.from_file_at_size(filename, width, height); - + if (pixbuf != null) { this.load_pixbuf(pixbuf); } else { warning("Failed to load " + filename + "!"); this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height); } - + } catch (GLib.Error e) { message("Error loading image file: %s", e.message); this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height); } } - + ///////////////////////////////////////////////////////////////////// /// Loads an image from the the given Gdk.Pixbuf. ///////////////////////////////////////////////////////////////////// - + public void load_pixbuf(Gdk.Pixbuf pixbuf) { this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, pixbuf.width, pixbuf.height); - + var ctx = this.context(); Gdk.cairo_set_source_pixbuf(ctx, pixbuf, 1.0, 1.0); ctx.paint(); } - + ///////////////////////////////////////////////////////////////////// /// Paints the image onto the given Cairo.Context ///////////////////////////////////////////////////////////////////// - + public void paint_on(Cairo.Context ctx, double alpha = 1.0) { ctx.set_source_surface(this.surface, (int)(-0.5*this.width()-1), (int)(-0.5*this.height()-1)); if (alpha >= 1.0) ctx.paint(); else ctx.paint_with_alpha(alpha); } - + ///////////////////////////////////////////////////////////////////// /// Converts the image to a Gdk.Pixbuf. ///////////////////////////////////////////////////////////////////// - + public Gdk.Pixbuf to_pixbuf() { if (this.surface == null || this.surface.get_data().length <= 0) return new Gdk.Pixbuf(Gdk.Colorspace.RGB, true, 8, 1, 1); - - var pixbuf = new Gdk.Pixbuf.from_data(this.surface.get_data(), Gdk.Colorspace.RGB, true, 8, + + var pixbuf = new Gdk.Pixbuf.from_data(this.surface.get_data(), Gdk.Colorspace.RGB, true, 8, width(), height(), this.surface.get_stride(), null); - + pixbuf = pixbuf.copy(); - - // funny stuff here --- need to swap Red end Blue because Cairo + + // funny stuff here --- need to swap Red end Blue because Cairo // and Gdk are different... uint8* p = pixbuf.pixels; for (int i=0; i. +this program. If not, see . */ using GLib.Math; namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// This class renders a Pie. In order to accomplish that, it owns a /// CenterRenderer and some SliceRenderers. ///////////////////////////////////////////////////////////////////////// @@ -35,14 +35,14 @@ public class PieRenderer : GLib.Object { ///////////////////////////////////////////////////////////////////// /// The index of the currently active slice. - ///////////////////////////////////////////////////////////////////// - + ///////////////////////////////////////////////////////////////////// + public int active_slice { get; private set; } ///////////////////////////////////////////////////////////////////// /// True, if the hot keys are currently displayed. ///////////////////////////////////////////////////////////////////// - + public bool show_hotkeys { get; set; } ///////////////////////////////////////////////////////////////////// @@ -50,195 +50,195 @@ public class PieRenderer : GLib.Object { ///////////////////////////////////////////////////////////////////// public int size { get; private set; } - + ///////////////////////////////////////////////////////////////////// /// True if the pie should close when it's trigger is released. ///////////////////////////////////////////////////////////////////// - + public bool turbo_mode { get; private set; default=false; } - + ///////////////////////////////////////////////////////////////////// /// True if the pie is currently navigated with the keyboard. This is /// set to false as soon as the mouse moves. ///////////////////////////////////////////////////////////////////// - + public bool key_board_control { get; set; default=false; } - + ///////////////////////////////////////////////////////////////////// /// All SliceRenderers used to draw this Pie. ///////////////////////////////////////////////////////////////////// - + private Gee.ArrayList slices; - + ///////////////////////////////////////////////////////////////////// /// The renderer for the center of this pie. ///////////////////////////////////////////////////////////////////// - + private CenterRenderer center; - + ///////////////////////////////////////////////////////////////////// /// C'tor, initializes members. ///////////////////////////////////////////////////////////////////// - + public PieRenderer() { - this.slices = new Gee.ArrayList(); + this.slices = new Gee.ArrayList(); this.center = new CenterRenderer(this); this.quickaction = -1; this.active_slice = -2; this.size = 0; } - + ///////////////////////////////////////////////////////////////////// /// Loads a Pie. All members are initialized accordingly. ///////////////////////////////////////////////////////////////////// - + public void load_pie(Pie pie) { this.slices.clear(); - + int count = 0; foreach (var group in pie.action_groups) { foreach (var action in group.actions) { var renderer = new SliceRenderer(this); this.slices.add(renderer); renderer.load(action, slices.size-1); - + if (action.is_quickaction) { this.quickaction = count; } - + ++count; } } - + this.turbo_mode = PieManager.get_is_turbo(pie.id); - + this.set_highlighted_slice(this.quickaction); - + this.size = (int)fmax(2*Config.global.theme.radius + 2*Config.global.theme.slice_radius*Config.global.theme.max_zoom, 2*Config.global.theme.center_radius); - + // increase size if there are many slices if (slices.size > 0) { this.size = (int)fmax(this.size, - (((Config.global.theme.slice_radius + Config.global.theme.slice_gap)/tan(PI/slices.size)) + (((Config.global.theme.slice_radius + Config.global.theme.slice_gap)/tan(PI/slices.size)) + Config.global.theme.slice_radius)*2*Config.global.theme.max_zoom); } } - + ///////////////////////////////////////////////////////////////////// /// Activates the currently active slice. ///////////////////////////////////////////////////////////////////// - + public void activate() { if (this.active_slice >= 0 && this.active_slice < this.slices.size) { slices[active_slice].activate(); } - + foreach (var slice in this.slices) slice.fade_out(); - + center.fade_out(); } - + ///////////////////////////////////////////////////////////////////// /// Asks all renders to fade out. ///////////////////////////////////////////////////////////////////// - + public void cancel() { foreach (var slice in this.slices) slice.fade_out(); - + center.fade_out(); } - + ///////////////////////////////////////////////////////////////////// /// Called when the up-key is pressed. Selects the next slice towards - /// the top. + /// the top. ///////////////////////////////////////////////////////////////////// - + public void select_up() { int bottom = this.slice_count()/4; int top = this.slice_count()*3/4; - + if (this.active_slice == -1 || this.active_slice == bottom) this.set_highlighted_slice(top); else if (this.active_slice > bottom && this.active_slice < top) this.set_highlighted_slice(this.active_slice+1); else if (this.active_slice != top) this.set_highlighted_slice((this.active_slice-1+this.slice_count())%this.slice_count()); - + this.key_board_control = true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the down-key is pressed. Selects the next slice - /// towards the bottom. + /// towards the bottom. ///////////////////////////////////////////////////////////////////// - + public void select_down() { int bottom = this.slice_count()/4; int top = this.slice_count()*3/4; - + if (this.active_slice == -1 || this.active_slice == top) this.set_highlighted_slice(bottom); else if (this.active_slice > bottom && this.active_slice < top) this.set_highlighted_slice(this.active_slice-1); else if (this.active_slice != bottom) this.set_highlighted_slice((this.active_slice+1)%this.slice_count()); - + this.key_board_control = true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the left-key is pressed. Selects the next slice - /// towards the left. + /// towards the left. ///////////////////////////////////////////////////////////////////// - + public void select_left() { int left = this.slice_count()/2; int right = 0; - + if (this.active_slice == -1 || this.active_slice == right) this.set_highlighted_slice(left); else if (this.active_slice > left) this.set_highlighted_slice(this.active_slice-1); else if (this.active_slice < left) this.set_highlighted_slice(this.active_slice+1); - + this.key_board_control = true; } - + ///////////////////////////////////////////////////////////////////// /// Called when the right-key is pressed. Selects the next slice - /// towards the right. + /// towards the right. ///////////////////////////////////////////////////////////////////// - + public void select_right() { int left = this.slice_count()/2; int right = 0; - + if (this.active_slice == -1 || this.active_slice == left) this.set_highlighted_slice(right); else if (this.active_slice > left) this.set_highlighted_slice((this.active_slice+1)%this.slice_count()); else if (this.active_slice < left && this.active_slice != right) this.set_highlighted_slice((this.active_slice-1+this.slice_count())%this.slice_count()); - + this.key_board_control = true; } - + ///////////////////////////////////////////////////////////////////// /// Returns the amount of slices in this pie. ///////////////////////////////////////////////////////////////////// - + public int slice_count() { return slices.size; } - + ///////////////////////////////////////////////////////////////////// /// Draws the entire pie. ///////////////////////////////////////////////////////////////////// - + public void draw(double frame_time, Cairo.Context ctx, int mouse_x, int mouse_y) { if (this.size > 0) { double distance = sqrt(mouse_x*mouse_x + mouse_y*mouse_y); @@ -247,62 +247,62 @@ public class PieRenderer : GLib.Object { if (this.key_board_control) { angle = 2.0*PI*this.active_slice/(double)slice_count(); } else { - + if (distance > 0) { angle = acos(mouse_x/distance); - if (mouse_y < 0) + if (mouse_y < 0) angle = 2*PI - angle; } - + int next_active_slice = this.active_slice; - + if (distance < Config.global.theme.active_radius && this.quickaction >= 0 && this.quickaction < this.slices.size) { - - next_active_slice = this.quickaction; + + next_active_slice = this.quickaction; angle = 2.0*PI*quickaction/(double)slice_count(); - } else if (distance > Config.global.theme.active_radius && this.slice_count() > 0) { + } else if (distance > Config.global.theme.active_radius && this.slice_count() > 0 && distance < Config.global.activation_range) { next_active_slice = (int)(angle*slices.size/(2*PI) + 0.5) % this.slice_count(); } else { next_active_slice = -1; } - + this.set_highlighted_slice(next_active_slice); } center.draw(frame_time, ctx, angle, distance); - + foreach (var slice in this.slices) slice.draw(frame_time, ctx, angle, distance); } } - + ///////////////////////////////////////////////////////////////////// /// Called when the user moves the mouse. ///////////////////////////////////////////////////////////////////// - + public void on_mouse_move() { this.key_board_control = false; } - + ///////////////////////////////////////////////////////////////////// /// Called when the currently active slice changes. ///////////////////////////////////////////////////////////////////// - + public void set_highlighted_slice(int index) { if (index != this.active_slice) { - if (index >= 0 && index < this.slice_count()) + if (index >= 0 && index < this.slice_count()) this.active_slice = index; else if (this.quickaction >= 0) this.active_slice = this.quickaction; else this.active_slice = -1; - + SliceRenderer? active = (this.active_slice >= 0 && this.active_slice < this.slice_count()) ? this.slices[this.active_slice] : null; - + center.set_active_slice(active); - + foreach (var slice in this.slices) slice.set_active_slice(active); } diff --git a/src/renderers/pieWindow.vala b/src/renderers/pieWindow.vala index a95b3e3..da346dd 100644 --- a/src/renderers/pieWindow.vala +++ b/src/renderers/pieWindow.vala @@ -89,11 +89,7 @@ public class PieWindow : Gtk.Window { // check for compositing if (this.screen.is_composited()) { - #if HAVE_GTK_3 - this.set_visual(this.screen.get_rgba_visual()); - #else - this.set_colormap(this.screen.get_rgba_colormap()); - #endif + this.set_visual(this.screen.get_rgba_visual()); this.has_compositing = true; } @@ -147,11 +143,7 @@ public class PieWindow : Gtk.Window { }); // draw the pie on expose - #if HAVE_GTK_3 - this.draw.connect(this.draw_window); - #else - this.expose_event.connect(this.draw_window); - #endif + this.draw.connect(this.draw_window); } ///////////////////////////////////////////////////////////////////// @@ -214,13 +206,7 @@ public class PieWindow : Gtk.Window { /// Draw the Pie. ///////////////////////////////////////////////////////////////////// - #if HAVE_GTK_3 - private bool draw_window(Cairo.Context ctx) { - #else - private bool draw_window(Gtk.Widget da, Gdk.EventExpose event) { - // clear the window - var ctx = Gdk.cairo_create(this.get_window()); - #endif + private bool draw_window(Cairo.Context ctx) { // paint the background image if there is no compositing if (this.has_compositing) { ctx.set_operator (Cairo.Operator.CLEAR); @@ -237,7 +223,17 @@ public class PieWindow : Gtk.Window { // get the mouse position double mouse_x = 0.0, mouse_y = 0.0; - this.get_pointer(out mouse_x, out mouse_y); + Gdk.ModifierType mask; + + var display = Gdk.Display.get_default(); + var manager = display.get_device_manager(); + GLib.List list = manager.list_devices(Gdk.DeviceType.MASTER); + + foreach(var device in list) { + if (device.input_source != Gdk.InputSource.KEYBOARD) { + this.get_window().get_device_position_double(device, out mouse_x, out mouse_y, out mask); + } + } // store the frame time double frame_time = this.timer.elapsed(); @@ -260,7 +256,11 @@ public class PieWindow : Gtk.Window { this.on_closing(); Gtk.grab_remove(this); FocusGrabber.ungrab(); - this.renderer.activate(); + + GLib.Timeout.add(10, () => { + this.renderer.activate(); + return false; + }); GLib.Timeout.add((uint)(Config.global.theme.fade_out_time*1000), () => { this.closed = true; diff --git a/src/utilities/color.vala b/src/utilities/color.vala index 836411e..bf60e3f 100644 --- a/src/utilities/color.vala +++ b/src/utilities/color.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,14 +12,14 @@ 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 . +this program. If not, see . */ using GLib.Math; namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// A Color class with full rgb/hsv support /// and some useful utility methods. ///////////////////////////////////////////////////////////////////////// @@ -35,15 +35,15 @@ public class Color: GLib.Object { private float _g; private float _b; private float _a; - + ///////////////////////////////////////////////////////////////////// /// Creates a white Color. ///////////////////////////////////////////////////////////////////// - + public Color() { Color.from_rgb(1.0f, 1.0f, 1.0f); } - + ///////////////////////////////////////////////////////////////////// /// Creates a solid color with the given RGB values. ///////////////////////////////////////////////////////////////////// @@ -51,47 +51,48 @@ public class Color: GLib.Object { public Color.from_rgb(float red, float green, float blue) { Color.from_rgba(red, green, blue, 1.0f); } - + ///////////////////////////////////////////////////////////////////// /// Creates a translucient color with the given RGBA values. ///////////////////////////////////////////////////////////////////// - + public Color.from_rgba(float red, float green, float blue, float alpha) { r = red; g = green; b = blue; a = alpha; } - + ///////////////////////////////////////////////////////////////////// /// Creates a color from the given Gdk.Color ///////////////////////////////////////////////////////////////////// - - public Color.from_gdk(Gdk.Color color) { - Color.from_rgb( - (float)color.red/65535.0f, - (float)color.green/65535.0f, - (float)color.blue/65535.0f + + public Color.from_gdk(Gdk.RGBA color) { + Color.from_rgba( + (float)color.red, + (float)color.green, + (float)color.blue, + (float)color.alpha ); } - + ///////////////////////////////////////////////////////////////////// /// Creates a color, parsed from a string, such as #22EE33 ///////////////////////////////////////////////////////////////////// - + public Color.from_string(string hex_string) { - Gdk.Color color; - Gdk.Color.parse(hex_string, out color); + var color = Gdk.RGBA(); + color.parse(hex_string); Color.from_gdk(color); } - + ///////////////////////////////////////////////////////////////////// /// Gets the main color from an Image. Code from Unity. ///////////////////////////////////////////////////////////////////// - + public Color.from_icon(Image icon) { unowned uchar[] data = icon.surface.get_data(); - + uint width = icon.surface.get_width(); uint height = icon.surface.get_height(); uint row_bytes = icon.surface.get_stride(); @@ -99,7 +100,7 @@ public class Color: GLib.Object { double total = 0.0; double rtotal = 0.0; double gtotal = 0.0; - double btotal = 0.0; + double btotal = 0.0; for (uint i = 0; i < width; ++i) { for (uint j = 0; j < height; ++j) { @@ -126,7 +127,7 @@ public class Color: GLib.Object { v = 1.0f; } - + ///////////////////////////////////////////////////////////////////// /// The reddish part of the color. ///////////////////////////////////////////////////////////////////// @@ -138,14 +139,14 @@ public class Color: GLib.Object { set { if (value > 1.0f) _r = 1.0f; else if (value < 0.0f) _r = 0.0f; - else _r = value; + else _r = value; } } - + ///////////////////////////////////////////////////////////////////// /// The greenish part of the color. ///////////////////////////////////////////////////////////////////// - + public float g { get { return _g; @@ -153,14 +154,14 @@ public class Color: GLib.Object { set { if (value > 1.0f) _g = 1.0f; else if (value < 0.0f) _g = 0.0f; - else _g = value; + else _g = value; } } - + ///////////////////////////////////////////////////////////////////// /// The blueish part of the color. ///////////////////////////////////////////////////////////////////// - + public float b { get { return _b; @@ -168,14 +169,14 @@ public class Color: GLib.Object { set { if (value > 1.0f) _b = 1.0f; else if (value < 0.0f) _b = 0.0f; - else _b = value; + else _b = value; } } - + ///////////////////////////////////////////////////////////////////// /// The transparency of the color. ///////////////////////////////////////////////////////////////////// - + public float a { get { return _a; @@ -183,14 +184,14 @@ public class Color: GLib.Object { set { if (value > 1.0f) _a = 1.0f; else if (value < 0.0f) _a = 0.0f; - else _a = value; + else _a = value; } } - + ///////////////////////////////////////////////////////////////////// /// The hue of the color. ///////////////////////////////////////////////////////////////////// - + public float h { get { if (s > 0.0f) { @@ -210,11 +211,11 @@ public class Color: GLib.Object { setHSV(value, s, v); } } - + ///////////////////////////////////////////////////////////////////// /// The saturation of the color. ///////////////////////////////////////////////////////////////////// - + public float s { get { if (v == 0.0f) return 0.0f; @@ -226,11 +227,11 @@ public class Color: GLib.Object { else setHSV(h, value, v); } } - + ///////////////////////////////////////////////////////////////////// /// The value of the color. ///////////////////////////////////////////////////////////////////// - + public float v { get { return fmaxf(fmaxf(r, g), b); @@ -241,16 +242,16 @@ public class Color: GLib.Object { else setHSV(h, s, value); } } - + ///////////////////////////////////////////////////////////////////// /// Inverts the color. ///////////////////////////////////////////////////////////////////// - + public void invert() { h += 180.0f; v = 1.0f - v; } - + ///////////////////////////////////////////////////////////////////// /// Private member, used to apply color changes. ///////////////////////////////////////////////////////////////////// diff --git a/src/utilities/config.vala b/src/utilities/config.vala index 1d8b714..2ec2788 100644 --- a/src/utilities/config.vala +++ b/src/utilities/config.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,12 +12,12 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// A singleton class for storing global settings. These settings can /// be loaded from and saved to an XML file. ///////////////////////////////////////////////////////////////////////// @@ -29,11 +29,11 @@ public class Config : GLib.Object { ///////////////////////////////////////////////////////////////////// private static Config _instance = null; - + ///////////////////////////////////////////////////////////////////// /// Returns the singleton instance. ///////////////////////////////////////////////////////////////////// - + public static Config global { get { if (_instance == null) { @@ -46,7 +46,7 @@ public class Config : GLib.Object { _instance = value; } } - + ///////////////////////////////////////////////////////////////////// /// All settings variables. ///////////////////////////////////////////////////////////////////// @@ -54,16 +54,17 @@ public class Config : GLib.Object { public Theme theme { get; set; } public double refresh_rate { get; set; default = 60.0; } public double global_scale { get; set; default = 1.0; } + public int activation_range { get; set; default = 300; } public bool show_indicator { get; set; default = true; } public bool show_captions { get; set; default = true; } public bool auto_start { get; set; default = false; } public int showed_news { get; set; default = 0; } public Gee.ArrayList themes { get; private set; } - + ///////////////////////////////////////////////////////////////////// /// Saves all above variables to a file. ///////////////////////////////////////////////////////////////////// - + public void save() { var writer = new Xml.TextWriter.filename(Paths.settings); writer.start_document("1.0"); @@ -71,28 +72,29 @@ public class Config : GLib.Object { writer.write_attribute("theme", theme.name); writer.write_attribute("refresh_rate", refresh_rate.to_string()); writer.write_attribute("global_scale", global_scale.to_string()); + writer.write_attribute("activation_range", activation_range.to_string()); writer.write_attribute("show_indicator", show_indicator ? "true" : "false"); writer.write_attribute("show_captions", show_captions ? "true" : "false"); writer.write_attribute("showed_news", showed_news.to_string()); writer.end_element(); writer.end_document(); } - + ///////////////////////////////////////////////////////////////////// /// Loads all settings variables from a file. ///////////////////////////////////////////////////////////////////// - + private void load() { - + // check for auto_start filename this.auto_start = FileUtils.test(Paths.autostart, FileTest.EXISTS); - + // parse the settings file Xml.Parser.init(); Xml.Doc* settingsXML = Xml.Parser.parse_file(Paths.settings); bool error_occrured = false; string theme_name = ""; - + if (settingsXML != null) { Xml.Node* root = settingsXML->get_root_element(); @@ -101,7 +103,7 @@ public class Config : GLib.Object { for (Xml.Attr* attribute = root->properties; attribute != null; attribute = attribute->next) { string attr_name = attribute->name.down(); string attr_content = attribute->children->content; - + switch (attr_name) { case "theme": theme_name = attr_content; @@ -113,6 +115,10 @@ public class Config : GLib.Object { global_scale = double.parse(attr_content); global_scale.clamp(0.5, 2.0); break; + case "activation_range": + activation_range = int.parse(attr_content); + activation_range.clamp(100, 2000); + break; case "show_indicator": show_indicator = bool.parse(attr_content); break; @@ -127,45 +133,45 @@ public class Config : GLib.Object { break; } } - + Xml.Parser.cleanup(); - + } else { warning("Error loading settings: gnome-pie.conf is empty! Using defaults..."); error_occrured = true; } - + delete settingsXML; - + } else { warning("Error loading settings: gnome-pie.conf not found! Using defaults..."); error_occrured = true; } - + load_themes(theme_name); if (error_occrured) save(); } - + ///////////////////////////////////////////////////////////////////// /// Registers all themes in the user's and in the global /// theme directory. ///////////////////////////////////////////////////////////////////// - + public void load_themes(string current) { themes = new Gee.ArrayList(); try { string name; - + // load global themes var d = Dir.open(Paths.global_themes); while ((name = d.read_name()) != null) { var theme = new Theme(Paths.global_themes + "/" + name); - + if (theme.load()) themes.add(theme); } - + // load local themes d = Dir.open(Paths.local_themes); while ((name = d.read_name()) != null) { @@ -173,11 +179,11 @@ public class Config : GLib.Object { if (theme.load()) themes.add(theme); } - + } catch (Error e) { warning (e.message); - } - + } + if (themes.size > 0) { if (current == "") { current = "Unity"; @@ -197,7 +203,7 @@ public class Config : GLib.Object { } else error("No theme found!"); } - + } } diff --git a/src/utilities/focusGrabber.vala b/src/utilities/focusGrabber.vala index e5900d6..b551def 100644 --- a/src/utilities/focusGrabber.vala +++ b/src/utilities/focusGrabber.vala @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2011 by Simon Schneegans This program is free software: you can redistribute it and/or modify it @@ -12,12 +12,12 @@ 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 . +this program. If not, see . */ namespace GnomePie { -///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// /// Some helper methods which focus the input on a given Gtk.Window. ///////////////////////////////////////////////////////////////////////// @@ -27,7 +27,7 @@ public class FocusGrabber : GLib.Object { /// Utilities for grabbing focus. /// Code roughly from Gnome-Do/Synapse. ///////////////////////////////////////////////////////////////////// - + public static void grab(Gdk.Window window, bool keyboard = true, bool pointer = true, bool owner_events = true) { if (keyboard || pointer) { window.raise(); @@ -42,90 +42,56 @@ public class FocusGrabber : GLib.Object { } } } - + ///////////////////////////////////////////////////////////////////// /// Code roughly from Gnome-Do/Synapse. ///////////////////////////////////////////////////////////////////// - + public static void ungrab(bool keyboard = true, bool pointer = true) { - #if HAVE_GTK_3 - - var display = Gdk.Display.get_default(); - var manager = display.get_device_manager(); - - #if VALA_0_16 || VALA_0_17 - GLib.List list = manager.list_devices(Gdk.DeviceType.MASTER); - #else - unowned GLib.List list = manager.list_devices(Gdk.DeviceType.MASTER); - #endif - - foreach(var device in list) { - if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard) - || (device.input_source != Gdk.InputSource.KEYBOARD && pointer)) - - device.ungrab(Gdk.CURRENT_TIME); - } - - #else - - if (pointer) Gdk.pointer_ungrab(Gdk.CURRENT_TIME); - if (keyboard) Gdk.keyboard_ungrab(Gdk.CURRENT_TIME); - - #endif + var display = Gdk.Display.get_default(); + var manager = display.get_device_manager(); + + GLib.List list = manager.list_devices(Gdk.DeviceType.MASTER); + + foreach(var device in list) { + if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard) + || (device.input_source != Gdk.InputSource.KEYBOARD && pointer)) + + device.ungrab(Gdk.CURRENT_TIME); + } } - + ///////////////////////////////////////////////////////////////////// /// Code roughly from Gnome-Do/Synapse. ///////////////////////////////////////////////////////////////////// - + private static bool try_grab_window(Gdk.Window window, bool keyboard, bool pointer, bool owner_events) { - #if HAVE_GTK_3 - - var display = Gdk.Display.get_default(); - var manager = display.get_device_manager(); - - bool grabbed_all = true; - - #if VALA_0_16 - GLib.List list = manager.list_devices(Gdk.DeviceType.MASTER); - #else - unowned GLib.List list = manager.list_devices(Gdk.DeviceType.MASTER); - #endif - - foreach(var device in list) { - if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard) - || (device.input_source != Gdk.InputSource.KEYBOARD && pointer)) { - - var status = device.grab(window, Gdk.GrabOwnership.APPLICATION, owner_events, - Gdk.EventMask.ALL_EVENTS_MASK, null, Gdk.CURRENT_TIME); - - if (status != Gdk.GrabStatus.SUCCESS) - grabbed_all = false; - } - } - - if (grabbed_all) - return true; - - ungrab(keyboard, pointer); - - #else - - if (!pointer || Gdk.pointer_grab(window, owner_events, Gdk.EventMask.BUTTON_PRESS_MASK | - Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK, - null, null, Gdk.CURRENT_TIME) == Gdk.GrabStatus.SUCCESS) { - - if (!keyboard || Gdk.keyboard_grab(window, owner_events, Gdk.CURRENT_TIME) == Gdk.GrabStatus.SUCCESS) { - return true; - } else if (pointer) { - ungrab(false, true); - return false; - } + var display = Gdk.Display.get_default(); + var manager = display.get_device_manager(); + + bool grabbed_all = true; + + GLib.List list = manager.list_devices(Gdk.DeviceType.MASTER); + + foreach(var device in list) { + if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard) + || (device.input_source != Gdk.InputSource.KEYBOARD && pointer)) { + + var status = device.grab(window, Gdk.GrabOwnership.APPLICATION, owner_events, + Gdk.EventMask.ALL_EVENTS_MASK, null, Gdk.CURRENT_TIME); + + if (status != Gdk.GrabStatus.SUCCESS) + grabbed_all = false; } - #endif - + } + + if (grabbed_all) + return true; + + ungrab(keyboard, pointer); + return false; - } + } } } -- cgit v1.2.3