diff --git a/data/gschema.xml b/data/gschema.xml
index 26bc8d0..f0586d3 100644
--- a/data/gschema.xml
+++ b/data/gschema.xml
@@ -1,10 +1,15 @@
-
+
+ false
+ Whether indicator is hidden and inactive
+ Always hide indicator if set to true. While hidden the indicator does not monitor the clipboard.
+
+
true
- Whether indicator is visible
- Hide indicator if set to false. It is still running, just hidden
+ Whether indicator is active
+ Whether the indicator is monitoring and recording the clipboard contents
diff --git a/src/HistoryWidget.vala b/src/HistoryWidget.vala
index d2210f6..3226a34 100644
--- a/src/HistoryWidget.vala
+++ b/src/HistoryWidget.vala
@@ -4,27 +4,63 @@
*/
public class Clipboard.HistoryWidget : Gtk.Box {
+ private const string ACTIVE_DESCRIPTION = N_("Monitoring the clipboard contents");
+ private const string PRIVACY_DESCRIPTION = N_("Privacy Mode is On");
+
private Gee.HashSet clipboard_text_set;
private Gtk.ListBox clipboard_item_list;
private string last_text = "";
private uint wait_timeout = 0;
+ private Granite.SwitchModelButton active_switch;
+ private Gtk.Box privacy_widget;
+ private Gtk.ScrolledWindow scroll_box;
+ private Gtk.Stack stack;
+ private unowned Gtk.Clipboard clipboard;
public signal void close_request ();
construct {
+ orientation = VERTICAL;
+ spacing = 6;
+
+ active_switch = new Granite.SwitchModelButton (_("Clipboard Manager")) {
+ description = _(ACTIVE_DESCRIPTION)
+ };
+
+ var inactive_header_label = new Granite.HeaderLabel (_("The ClipboardManager is disabled"));
+ var inactive_subheader_label = new Gtk.Label ("") {
+ label = Granite.TOOLTIP_SECONDARY_TEXT_MARKUP.printf (_("History is off in the Privacy and Security settings")),
+ use_markup = true
+ };
+ privacy_widget = new Gtk.Box (VERTICAL, 0) {
+ margin_start = 6,
+ margin_end = 6
+ };
+ privacy_widget.add (inactive_header_label);
+ privacy_widget.add (inactive_subheader_label);
+
+ Clipboard.Indicator.settings.bind ("active", active_switch, "active", DEFAULT);
+
clipboard_text_set = new Gee.HashSet ();
clipboard_item_list = new Gtk.ListBox () {
selection_mode = SINGLE
};
clipboard_item_list.set_placeholder (new Gtk.Label (_("Clipboard Empty")));
- var scroll_box = new Gtk.ScrolledWindow (null, null);
+
+ scroll_box = new Gtk.ScrolledWindow (null, null);
scroll_box.max_content_height = 512;
scroll_box.propagate_natural_height = true;
scroll_box.hscrollbar_policy = Gtk.PolicyType.NEVER;
scroll_box.add (clipboard_item_list);
- add (scroll_box);
+ stack = new Gtk.Stack ();
+ stack.add_named (scroll_box, "clipboard");
+ stack.add_named (privacy_widget, "privacy");
+
+ add (active_switch);
+ add (stack);
+
show_all ();
clipboard_item_list.row_activated.connect ((row) => {
@@ -33,6 +69,8 @@ public class Clipboard.HistoryWidget : Gtk.Box {
clipboard.set_text (text, -1);
close_request ();
});
+
+ clipboard = Gtk.Clipboard.get_default (Gdk.Display.get_default ());
}
~HistoryWidget () {
@@ -41,28 +79,43 @@ public class Clipboard.HistoryWidget : Gtk.Box {
// No notifications from clipboard? So poll it periodically for new text
public void wait_for_text () {
- var clipboard = Gtk.Clipboard.get_default (Gdk.Display.get_default ());
- wait_timeout = Timeout.add_full (Priority.LOW, 1000, () => {
- if (clipboard.wait_is_text_available ()) {
- clipboard.request_text ((cb, text) => {
- if (text != last_text && !clipboard_text_set.contains (text)) {
- last_text = text;
- clipboard_text_set.add (text);
- var new_item = new ItemRow (text);
- clipboard_item_list.prepend (new_item);
- clipboard_item_list.select_row (new_item);
- clipboard_item_list.show_all ();
- }
- });
- }
-
- return Source.CONTINUE;
+ clipboard.owner_change.connect (on_clipboard_owner_change);
+ }
+
+ private void on_clipboard_owner_change () requires (clipboard != null) {
+ if (clipboard.wait_is_text_available ()) {
+ clipboard.request_text ((cb, text) => {
+ if (!clipboard_text_set.contains (text)) {
+ clipboard_text_set.add (text);
+ var new_item = new ItemRow (text);
+ clipboard_item_list.prepend (new_item);
+ clipboard_item_list.select_row (new_item);
+ }
+ });
+ }
+ }
+
+ public void stop_waiting_for_text () requires (clipboard != null) {
+ clipboard.owner_change.disconnect (on_clipboard_owner_change);
+ }
+
+ public void clear_history () {
+ clipboard_text_set.clear ();
+ clipboard_item_list.@foreach ((child) => {
+ child.destroy ();
});
}
- public void stop_waiting_for_text () {
- if (wait_timeout > 0) {
- Source.remove (wait_timeout);
+ public void set_privacy_mode (bool privacy_on) {
+ active_switch.sensitive = !privacy_on;
+ stack.visible_child_name = privacy_on ? "privacy" : "clipboard";
+ if (privacy_on) {
+ stop_waiting_for_text ();
+ clear_history ();
+ active_switch.description = _(PRIVACY_DESCRIPTION);
+ } else {
+ wait_for_text ();
+ active_switch.description = _(ACTIVE_DESCRIPTION);
}
}
diff --git a/src/Indicator.vala b/src/Indicator.vala
index 3824488..4d3e75d 100644
--- a/src/Indicator.vala
+++ b/src/Indicator.vala
@@ -4,10 +4,17 @@
*/
public class Clipboard.Indicator : Wingpanel.Indicator {
- private static GLib.Settings settings;
+ public static GLib.Settings settings;
+ private static GLib.Settings gnome_privacy_settings;
+ private const string NORMAL_ICON_NAME = "edit-copy-symbolic";
+ private const string STOPPED_ICON_NAME = "task-past-due-symbolic";
private Gtk.Image panel_icon;
private HistoryWidget history_widget;
+ public bool always_hide { get; set; }
+ public bool active { get; set; }
+ public bool privacy_on { get; set; }
+
public Wingpanel.IndicatorManager.ServerType server_type { get; construct set; }
public Indicator (Wingpanel.IndicatorManager.ServerType indicator_server_type) {
@@ -21,45 +28,70 @@ public class Clipboard.Indicator : Wingpanel.Indicator {
Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
Intl.textdomain (GETTEXT_PACKAGE);
+ visible = true;
+
settings = new GLib.Settings ("io.github.ellie_commons.indicator-clipboard");
- settings.bind ("visible", this, "visible", GLib.SettingsBindFlags.DEFAULT);
+ settings.bind ("always-hide", this, "always-hide", DEFAULT);
+ settings.bind ("active", this, "active", DEFAULT);
+
+
+ // Ensure correct appearance before showing
+ get_display_widget ();
+ get_widget ();
+ update_appearance ();
}
+
public override Gtk.Widget get_display_widget () {
if (panel_icon == null) {
- panel_icon = new Gtk.Image.from_icon_name ("edit-copy-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
+ panel_icon = new Gtk.Image.from_icon_name (NORMAL_ICON_NAME, Gtk.IconSize.SMALL_TOOLBAR);
if (server_type == Wingpanel.IndicatorManager.ServerType.GREETER) {
this.visible = false;
} else {
- // var visible_settings = new Settings ("io.elementary.desktop.wingpanel.clipboard");
- // visible_settings.bind ("show-indicator", this, "visible", SettingsBindFlags.DEFAULT);
- this.visible = true;
+ gnome_privacy_settings = new Settings ("org.gnome.desktop.privacy");
+ gnome_privacy_settings.bind ("remember-recent-files", this, "privacy-on", DEFAULT | INVERT_BOOLEAN);
}
}
- get_widget ();
return panel_icon;
}
public override Gtk.Widget? get_widget () {
if (history_widget == null &&
server_type == Wingpanel.IndicatorManager.ServerType.SESSION) {
- history_widget = new HistoryWidget ();
- history_widget.close_request.connect (() => {
- close ();
- });
- history_widget.wait_for_text ();
+
+ history_widget = new HistoryWidget ();
+ history_widget.close_request.connect (() => {
+ close ();
+ });
+
+ this.notify["privacy-on"].connect (update_appearance);
+ this.notify["always-hide"].connect (update_appearance);
+ this.notify["active"].connect (update_appearance);
+ update_appearance ();
}
return history_widget;
}
public override void opened () {
+
}
public override void closed () {
}
+
+ private void update_appearance () {
+ if (!active || privacy_on || always_hide) {
+ panel_icon.icon_name = STOPPED_ICON_NAME;
+ } else if (active && !privacy_on && !always_hide) {
+ panel_icon.icon_name = NORMAL_ICON_NAME;
+ }
+
+ visible = !always_hide;
+ history_widget.set_privacy_mode (privacy_on);
+ }
}
public Wingpanel.Indicator? get_indicator (Module module, Wingpanel.IndicatorManager.ServerType server_type) {