From 93bd5880d984fdca6d85672abf497a14b1f50131 Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Thu, 27 Oct 2016 10:35:02 +0200 Subject: Updated the way icons are loaded on Linux with Gtk and AppIndicator trayicons. The icons are now loaded from SVG to give the best possible resolution. This fixes #1710 This fixes #2034 --- .../Duplicati.GUI.TrayIcon/AppIndicatorRunner.cs | 45 ++++--- .../Duplicati.GUI.TrayIcon.csproj | 24 ++++ Duplicati/GUI/Duplicati.GUI.TrayIcon/GtkRunner.cs | 133 ++++++++++++++------- .../SVGIcons/dark/context_menu_open.svg | 13 ++ .../SVGIcons/dark/context_menu_pause.svg | 14 +++ .../SVGIcons/dark/context_menu_quit.svg | 13 ++ .../SVGIcons/dark/context_menu_resume.svg | 13 ++ .../SVGIcons/light/context_menu_open.svg | 13 ++ .../SVGIcons/light/context_menu_pause.svg | 14 +++ .../SVGIcons/light/context_menu_quit.svg | 13 ++ .../SVGIcons/light/context_menu_resume.svg | 13 ++ 11 files changed, 238 insertions(+), 70 deletions(-) create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_open.svg create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_pause.svg create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_quit.svg create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_resume.svg create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_open.svg create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_pause.svg create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_quit.svg create mode 100644 Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_resume.svg (limited to 'Duplicati/GUI/Duplicati.GUI.TrayIcon') diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/AppIndicatorRunner.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/AppIndicatorRunner.cs index ecacbbd8d..407db2157 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/AppIndicatorRunner.cs +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/AppIndicatorRunner.cs @@ -54,32 +54,29 @@ namespace Duplicati.GUI.TrayIcon { set { + m_appIndicator.IconName = GetTrayIconFilename(value); + switch(value) { - case TrayIcons.Paused: - m_appIndicator.IconName = "normal-pause"; - m_appIndicator.IconDesc = "Paused"; - break; - case TrayIcons.Running: - m_appIndicator.IconName = "normal-running"; - m_appIndicator.IconDesc = "Running"; - break; - case TrayIcons.IdleError: - m_appIndicator.IconName = "normal-error"; - m_appIndicator.IconDesc = "Error"; - break; - case TrayIcons.RunningError: - m_appIndicator.IconName = "normal-running"; - break; - case TrayIcons.PausedError: - m_appIndicator.IconName = "normal-pause"; - m_appIndicator.IconDesc = "Paused"; - break; - case TrayIcons.Idle: - default: - m_appIndicator.IconName = "normal"; - m_appIndicator.IconDesc = "Ready"; - break; + case TrayIcons.Paused: + m_appIndicator.IconDesc = "Paused"; + break; + case TrayIcons.Running: + m_appIndicator.IconDesc = "Running"; + break; + case TrayIcons.IdleError: + m_appIndicator.IconDesc = "Error"; + break; + case TrayIcons.RunningError: + m_appIndicator.IconDesc = "Running"; + break; + case TrayIcons.PausedError: + m_appIndicator.IconDesc = "Paused"; + break; + case TrayIcons.Idle: + default: + m_appIndicator.IconDesc = "Ready"; + break; } } } diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj index 9429b8ac5..4556e4aa9 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj @@ -372,5 +372,29 @@ OSXTrayHost\rumps.py PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + \ No newline at end of file diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/GtkRunner.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/GtkRunner.cs index caaa16377..5237edb81 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/GtkRunner.cs +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/GtkRunner.cs @@ -24,11 +24,16 @@ namespace Duplicati.GUI.TrayIcon { public class GtkRunner : TrayIconBase { + private static string m_svgfolder; + /// /// Static constructor that ensures the Gtk environment is initialized /// static GtkRunner() { + m_svgfolder = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "SVGIcons"); + m_svgfolder = System.IO.Path.Combine(m_svgfolder, "dark"); + Gtk.Application.Init(); } @@ -45,34 +50,36 @@ namespace Duplicati.GUI.TrayIcon private static Dictionary _icons = new Dictionary(); public MenuItem MenuItem { get { return m_item; } } - - private Gtk.Image GetIcon(MenuIcons icon) - { - if (Duplicati.Library.Utility.Utility.IsClientOSX) - return null; - if (!_icons.ContainsKey(icon)) + private string GetFilenameForIcon(MenuIcons icon) + { + switch (icon) { - switch(icon) - { - case MenuIcons.None: - _icons[icon] = null; - break; case MenuIcons.Pause: - _icons[icon] = ImageToGtk(ImageLoader.Pause); - break; + return "context_menu_pause"; case MenuIcons.Quit: - _icons[icon] = ImageToGtk(ImageLoader.CloseMenuIcon); - break; + return "context_menu_quit"; case MenuIcons.Resume: - _icons[icon] = ImageToGtk(ImageLoader.Play); - break; + return "context_menu_resume"; case MenuIcons.Status: - _icons[icon] = ImageToGtk(ImageLoader.StatusMenuIcon); - break; + return "context_menu_open"; default: - _icons[icon] = null; - break; + return null; + } + } + + private Gtk.Image GetIcon(MenuIcons icon) + { + if (!_icons.ContainsKey(icon)) + { + _icons[icon] = null; + + var filename = GetFilenameForIcon(icon); + if (filename != null) + { + filename = System.IO.Path.Combine(m_svgfolder, System.IO.Path.ChangeExtension(filename, ".svg")); + if (System.IO.File.Exists(filename)) + _icons[icon] = new Gtk.Image(filename); } } @@ -89,9 +96,9 @@ namespace Duplicati.GUI.TrayIcon if (!Duplicati.Library.Utility.Utility.IsClientOSX) if (icon != MenuIcons.None) { ((ImageMenuItem)m_item).Image = GetIcon(icon); - - //TODO: Not sure we should do this, it overrides policy? - m_item.ExposeEvent += DrawImageMenuItemImage; + + // On some (older versions) of GDK, this hack is required + //m_item.ExposeEvent += DrawImageMenuItemImage; } if (subitems != null && subitems.Count > 0) @@ -116,6 +123,7 @@ namespace Duplicati.GUI.TrayIcon m_callback(); } + /* /// Draw the image to the image menu item. Taken from: http://mono.1490590.n4.nabble.com/ImageMenuItem-does-not-display-the-image-Linux-platform-tp3510861p3511376.html /// The event source. /// The event args. @@ -133,7 +141,8 @@ namespace Duplicati.GUI.TrayIcon args.Event.Window.DrawPixbuf(mainGC, image.Pixbuf, 0, 0, r.Left + 2, r.Top + (r.Height - image.Pixbuf.Height) / 2, -1, -1, Gdk.RgbDither.None, 0, 0); - } + } + */ public string Text { @@ -176,7 +185,9 @@ namespace Duplicati.GUI.TrayIcon protected virtual void CreateTrayInstance() { - m_trayIcon = new StatusIcon(); + // Sometimes the tray icon will not display + // if it is not created with an icon + m_trayIcon = StatusIcon.NewFromStock(Stock.About); } protected override void Run (string[] args) @@ -231,33 +242,63 @@ namespace Duplicati.GUI.TrayIcon Gtk.Image img = new Gtk.Image(stream); return img; } - } + } + + protected static string GetTrayIconFilename(TrayIcons icon) + { + switch (icon) + { + case TrayIcons.Paused: + return "normal-pause"; + case TrayIcons.Running: + return "normal-running"; + case TrayIcons.IdleError: + return "normal-error"; + case TrayIcons.RunningError: + return "normal-running"; + case TrayIcons.PausedError: + return "normal-pause"; + case TrayIcons.Idle: + default: + return "normal"; + } + } protected static Pixbuf GetIcon(TrayIcons icon) { if (!_images.ContainsKey(icon)) { - switch(icon) + if (Duplicati.Library.Utility.Utility.IsClientOSX) { - case TrayIcons.Paused: - _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.PauseIcon).ToBitmap()); - break; - case TrayIcons.Running: - _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap()); - break; - case TrayIcons.IdleError: - _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.ErrorIcon).ToBitmap()); - break; - case TrayIcons.RunningError: - _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap()); - break; - case TrayIcons.PausedError: + switch (icon) + { + case TrayIcons.Paused: _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.PauseIcon).ToBitmap()); - break; - case TrayIcons.Idle: - default: - _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.NormalIcon).ToBitmap()); - break; + break; + case TrayIcons.Running: + _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap()); + break; + case TrayIcons.IdleError: + _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.ErrorIcon).ToBitmap()); + break; + case TrayIcons.RunningError: + _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.WorkingIcon).ToBitmap()); + break; + case TrayIcons.PausedError: + _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.PauseIcon).ToBitmap()); + break; + case TrayIcons.Idle: + default: + _images[icon] = ImageToPixbuf(ImageLoader.LoadIcon(ImageLoader.NormalIcon).ToBitmap()); + break; + } + } + else + { + _images[icon] = null; + var filename = System.IO.Path.Combine(m_svgfolder, System.IO.Path.ChangeExtension(GetTrayIconFilename(icon), ".svg")); + if (System.IO.File.Exists(filename)) + _images[icon] = new Pixbuf(filename); } } diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_open.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_open.svg new file mode 100644 index 000000000..8dfe03665 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_open.svg @@ -0,0 +1,13 @@ + + + + + tray context menu icons + + + + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_pause.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_pause.svg new file mode 100644 index 000000000..8f646c100 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_pause.svg @@ -0,0 +1,14 @@ + + + + + tray context menu icons + + + + + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_quit.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_quit.svg new file mode 100644 index 000000000..bc3cfae06 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_quit.svg @@ -0,0 +1,13 @@ + + + + + tray context menu icons + + + + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_resume.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_resume.svg new file mode 100644 index 000000000..b1c4ed79d --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/dark/context_menu_resume.svg @@ -0,0 +1,13 @@ + + + + + tray context menu icons + + + + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_open.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_open.svg new file mode 100644 index 000000000..8dfe03665 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_open.svg @@ -0,0 +1,13 @@ + + + + + tray context menu icons + + + + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_pause.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_pause.svg new file mode 100644 index 000000000..8f646c100 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_pause.svg @@ -0,0 +1,14 @@ + + + + + tray context menu icons + + + + + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_quit.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_quit.svg new file mode 100644 index 000000000..bc3cfae06 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_quit.svg @@ -0,0 +1,13 @@ + + + + + tray context menu icons + + + + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_resume.svg b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_resume.svg new file mode 100644 index 000000000..b1c4ed79d --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SVGIcons/light/context_menu_resume.svg @@ -0,0 +1,13 @@ + + + + + tray context menu icons + + + + -- cgit v1.2.3