Bug 1418749 - widget/gtk: Add a TaskbarProgress implementation for gtk3/x11. r=karlt
☠☠ backed out by bd9a72daf251 ☠ ☠
authorMichael Webster <miketwebster@gmail.com>
Mon, 26 Feb 2018 16:40:00 +0200
changeset 461159 45ae173a1348b3f3d318070f84b1d7d8da89e5b4
parent 461158 533de41e4cb3c8356e254f662371c0e852ce18ca
child 461160 df08d5fbb370b56dd7451496d655bb260ac1c396
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1418749
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1418749 - widget/gtk: Add a TaskbarProgress implementation for gtk3/x11. r=karlt https://bugzilla.mozilla.org/show_bug.cgi?id=1418749 This adds support for download progress reporting via the XApp method currently used in the Cinnamon desktop, by establishing a new X11 window property to be supported/read by the window manager. See https://github.com/linuxmint/xapps/blob/master/libxapp/xapp-gtk-window.c, as well as https://github.com/linuxmint/muffin/commit/39045da0ea06f for more details. The property-setting code lives in nsWindow - it's a small and stable enough chunk that it made more sense to do this than actually depend on another external library. As nsWindow is already using x11 calls, this seemed the safest place for it, without affecting the build. The TaskbarProgress instance is initialized via the DownloadsTaskbar js module, and is handed a pointer to the current main window to call SetProgress on. Most of the javascript side of this is in line with how the other platforms are handled. Without a supporting window manager/desktop environment (currently just Cinnamon/Muffin 3.6,) the simplest way to observe working behavior is by calling 'xprop -spy' on the browser window being testing and watching for updates during a download.
browser/components/downloads/DownloadsTaskbar.jsm
widget/gtk/TaskbarProgress.cpp
widget/gtk/TaskbarProgress.h
widget/gtk/moz.build
widget/gtk/nsWidgetFactory.cpp
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
widget/moz.build
widget/nsIGtkTaskbarProgress.idl
widget/nsWidgetsCID.h
--- a/browser/components/downloads/DownloadsTaskbar.jsm
+++ b/browser/components/downloads/DownloadsTaskbar.jsm
@@ -35,16 +35,22 @@ XPCOMUtils.defineLazyGetter(this, "gWinT
 });
 
 XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function() {
   return ("@mozilla.org/widget/macdocksupport;1" in Cc) &&
          Cc["@mozilla.org/widget/macdocksupport;1"]
            .getService(Ci.nsITaskbarProgress);
 });
 
+XPCOMUtils.defineLazyGetter(this, "gGtkTaskbarProgress", function() {
+  return ("@mozilla.org/widget/taskbarprogress/gtk;1" in Cc) &&
+         Cc["@mozilla.org/widget/taskbarprogress/gtk;1"]
+           .getService(Ci.nsIGtkTaskbarProgress);
+});
+
 // DownloadsTaskbar
 
 /**
  * Handles the download progress indicator in the taskbar.
  */
 var DownloadsTaskbar = {
   /**
    * Underlying DownloadSummary providing the aggregate download information, or
@@ -84,16 +90,20 @@ var DownloadsTaskbar = {
         Services.obs.addObserver(() => {
           this._taskbarProgress = null;
           gMacTaskbarProgress = null;
         }, "quit-application-granted");
       } else if (gWinTaskbar) {
         // On Windows, the indicator is currently hidden because we have no
         // previous browser window, thus we should attach the indicator now.
         this._attachIndicator(aBrowserWindow);
+      } else if (gGtkTaskbarProgress) {
+        this._taskbarProgress = gGtkTaskbarProgress;
+
+        this._attachGtkTaskbarProgress(aBrowserWindow);
       } else {
         // The taskbar indicator is not available on this platform.
         return;
       }
     }
 
     // Ensure that the DownloadSummary object will be created asynchronously.
     if (!this._summary) {
@@ -138,16 +148,45 @@ var DownloadsTaskbar = {
         // The last browser window has been closed.  We remove the reference to
         // the taskbar progress object so that the indicator will be registered
         // again on the next browser window that is opened.
         this._taskbarProgress = null;
       }
     });
   },
 
+  /**
+   * In gtk3, the window itself implements the progress interface.
+   */
+  _attachGtkTaskbarProgress(aWindow) {
+    // Set the current window.
+    this._taskbarProgress.setPrimaryWindow(aWindow);
+
+    // If the DownloadSummary object has already been created, we should update
+    // the state of the new indicator, otherwise it will be updated as soon as
+    // the DownloadSummary view is registered.
+    if (this._summary) {
+      this.onSummaryChanged();
+    }
+
+    aWindow.addEventListener("unload", () => {
+      // Locate another browser window, excluding the one being closed.
+      let browserWindow = RecentWindow.getMostRecentBrowserWindow();
+      if (browserWindow) {
+        // Move the progress indicator to the other browser window.
+        this._attachGtkTaskbarProgress(browserWindow);
+      } else {
+        // The last browser window has been closed.  We remove the reference to
+        // the taskbar progress object so that the indicator will be registered
+        // again on the next browser window that is opened.
+        this._taskbarProgress = null;
+      }
+    });
+  },
+
   // DownloadSummary view
 
   onSummaryChanged() {
     // If the last browser window has been closed, we have no indicator any more.
     if (!this._taskbarProgress) {
       return;
     }
 
new file mode 100644
--- /dev/null
+++ b/widget/gtk/TaskbarProgress.cpp
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Logging.h"
+
+#include "TaskbarProgress.h"
+#include "nsWindow.h"
+#include "WidgetUtils.h"
+#include "nsPIDOMWindow.h"
+
+using mozilla::LogLevel;
+static mozilla::LazyLogModule gGtkTaskbarProgressLog("nsIGtkTaskbarProgress");
+
+/******************************************************************************
+ * TaskbarProgress
+ ******************************************************************************/
+
+NS_IMPL_ISUPPORTS(TaskbarProgress, nsIGtkTaskbarProgress, nsITaskbarProgress)
+
+TaskbarProgress::TaskbarProgress()
+    : mPrimaryWindow(nullptr)
+{
+  MOZ_LOG(gGtkTaskbarProgressLog, LogLevel::Info,
+          ("%p TaskbarProgress()", this));
+}
+
+TaskbarProgress::~TaskbarProgress()
+{
+  MOZ_LOG(gGtkTaskbarProgressLog, LogLevel::Info,
+          ("%p ~TaskbarProgress()", this));
+}
+
+NS_IMETHODIMP
+TaskbarProgress::SetProgressState(nsTaskbarProgressState aState,
+                                  uint64_t               aCurrentValue,
+                                  uint64_t               aMaxValue)
+{
+#ifdef MOZ_X11
+  NS_ENSURE_TRUE(mPrimaryWindow != nullptr, NS_ERROR_FAILURE);
+  NS_ENSURE_ARG_RANGE(aState, 0, STATE_PAUSED);
+
+  if (aState == STATE_NO_PROGRESS || aState == STATE_INDETERMINATE) {
+    NS_ENSURE_TRUE(aCurrentValue == 0, NS_ERROR_INVALID_ARG);
+    NS_ENSURE_TRUE(aMaxValue == 0, NS_ERROR_INVALID_ARG);
+  }
+
+  NS_ENSURE_TRUE((aCurrentValue <= aMaxValue), NS_ERROR_ILLEGAL_VALUE);
+
+  gulong progress;
+
+  if (aMaxValue == 0) {
+    progress = 0;
+  } else {
+    // Rounding down to ensure we don't set to 'full' until the operation
+    // is completely finished.
+    progress = (gulong) (((double)aCurrentValue / aMaxValue) * 100.0);
+  }
+
+  // Check if the resultant value is the same as the previous call, and
+  // ignore this update if it is.
+
+  if (progress == mCurrentProgress) {
+    return NS_OK;
+  }
+
+  mCurrentProgress = progress;
+
+  MOZ_LOG(gGtkTaskbarProgressLog, LogLevel::Debug,
+          ("GtkTaskbarProgress::SetProgressState progress: %lu", progress));
+
+  mPrimaryWindow->SetProgress(progress);
+#endif
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+TaskbarProgress::SetPrimaryWindow(mozIDOMWindowProxy* aWindow)
+{
+  NS_ENSURE_TRUE(aWindow != nullptr, NS_ERROR_ILLEGAL_VALUE);
+
+  auto* parent = nsPIDOMWindowOuter::From(aWindow);
+  RefPtr<nsIWidget> widget = mozilla::widget::WidgetUtils::DOMWindowToWidget(parent);
+
+  mPrimaryWindow = static_cast<nsWindow*>(widget.get());
+
+  // Clear our current progress.  We get a forced update from the DownloadsTaskbar
+  // after returning from this function - zeroing out our progress will make sure the
+  // new window gets the property set on it immediately, rather than waiting for the
+  // progress value to change (which could be a while depending on size.)
+  mCurrentProgress = 0;
+
+  MOZ_LOG(gGtkTaskbarProgressLog, LogLevel::Debug,
+          ("GtkTaskbarProgress::SetPrimaryWindow window: %p", mPrimaryWindow.get()));
+
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/widget/gtk/TaskbarProgress.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TaskbarProgress_h_
+#define TaskbarProgress_h_
+
+#include "nsIGtkTaskbarProgress.h"
+
+class nsWindow;
+
+class TaskbarProgress final : public nsIGtkTaskbarProgress
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIGTKTASKBARPROGRESS
+  NS_DECL_NSITASKBARPROGRESS
+
+  TaskbarProgress();
+
+protected:
+  ~TaskbarProgress();
+
+  // We track the progress value so we can avoid updating the X window property
+  // unnecessarily.
+  unsigned long mCurrentProgress;
+
+  RefPtr<nsWindow> mPrimaryWindow;
+};
+
+#endif // #ifndef TaskbarProgress_h_
--- a/widget/gtk/moz.build
+++ b/widget/gtk/moz.build
@@ -43,16 +43,17 @@ UNIFIED_SOURCES += [
     'nsGtkKeyUtils.cpp',
     'nsImageToPixbuf.cpp',
     'nsLookAndFeel.cpp',
     'nsNativeThemeGTK.cpp',
     'nsSound.cpp',
     'nsToolkit.cpp',
     'nsWidgetFactory.cpp',
     'ScreenHelperGTK.cpp',
+    'TaskbarProgress.cpp',
     'WakeLockListener.cpp',
     'WidgetTraceEvent.cpp',
     'WidgetUtilsGtk.cpp',
 ]
 
 SOURCES += [
     'nsWindow.cpp', # conflicts with X11 headers
 ]
--- a/widget/gtk/nsWidgetFactory.cpp
+++ b/widget/gtk/nsWidgetFactory.cpp
@@ -21,16 +21,17 @@
 #ifdef MOZ_X11
 #include "nsClipboardHelper.h"
 #include "nsClipboard.h"
 #include "nsDragService.h"
 #endif
 #ifdef MOZ_WIDGET_GTK
 #include "nsApplicationChooser.h"
 #endif
+#include "TaskbarProgress.h"
 #include "nsColorPicker.h"
 #include "nsFilePicker.h"
 #include "nsSound.h"
 #include "nsBidiKeyboard.h"
 #include "nsGTKToolkit.h"
 #include "WakeLockListener.h"
 
 #ifdef NS_PRINTING
@@ -66,16 +67,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFor
 #ifdef MOZ_X11
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceGTK, nsIdleServiceGTK::GetInstance)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDragService, nsDragService::GetInstance)
 #endif
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISound, nsSound::GetInstance)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf)
+NS_GENERIC_FACTORY_CONSTRUCTOR(TaskbarProgress)
 
 
 // from nsWindow.cpp
 extern bool gDisableNativeTheme;
 
 static nsresult
 nsNativeThemeGTKConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult)
@@ -198,16 +200,17 @@ nsClipboardConstructor(nsISupports *aOut
 NS_DEFINE_NAMED_CID(NS_WINDOW_CID);
 NS_DEFINE_NAMED_CID(NS_CHILD_CID);
 NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
 NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
 NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
 #ifdef MOZ_WIDGET_GTK
 NS_DEFINE_NAMED_CID(NS_APPLICATIONCHOOSER_CID);
 #endif
+NS_DEFINE_NAMED_CID(NS_GTK_TASKBARPROGRESS_CID);
 NS_DEFINE_NAMED_CID(NS_SOUND_CID);
 NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID);
 #ifdef MOZ_X11
 NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
 NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
@@ -232,16 +235,17 @@ static const mozilla::Module::CIDEntry k
     { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor },
     { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor },
     { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor, Module::ALLOW_IN_GPU_PROCESS },
     { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerConstructor, Module::MAIN_PROCESS_ONLY },
     { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerConstructor, Module::MAIN_PROCESS_ONLY },
 #ifdef MOZ_WIDGET_GTK
     { &kNS_APPLICATIONCHOOSER_CID, false, nullptr, nsApplicationChooserConstructor, Module::MAIN_PROCESS_ONLY },
 #endif
+    { &kNS_GTK_TASKBARPROGRESS_CID, false, nullptr, TaskbarProgressConstructor},
     { &kNS_SOUND_CID, false, nullptr, nsISoundConstructor, Module::MAIN_PROCESS_ONLY },
     { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor },
 #ifdef MOZ_X11
     { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor, Module::MAIN_PROCESS_ONLY },
     { &kNS_CLIPBOARDHELPER_CID, false, nullptr, nsClipboardHelperConstructor },
     { &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY },
 #endif
     { &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor },
@@ -268,16 +272,17 @@ static const mozilla::Module::ContractID
     { "@mozilla.org/widget/window/gtk;1", &kNS_WINDOW_CID },
     { "@mozilla.org/widgets/child_window/gtk;1", &kNS_CHILD_CID },
     { "@mozilla.org/widget/appshell/gtk;1", &kNS_APPSHELL_CID, Module::ALLOW_IN_GPU_PROCESS },
     { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::MAIN_PROCESS_ONLY },
     { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::MAIN_PROCESS_ONLY },
 #ifdef MOZ_WIDGET_GTK
     { "@mozilla.org/applicationchooser;1", &kNS_APPLICATIONCHOOSER_CID, Module::MAIN_PROCESS_ONLY },
 #endif
+    { "@mozilla.org/widget/taskbarprogress/gtk;1", &kNS_GTK_TASKBARPROGRESS_CID },
     { "@mozilla.org/sound;1", &kNS_SOUND_CID, Module::MAIN_PROCESS_ONLY },
     { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
 #ifdef MOZ_X11
     { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, Module::MAIN_PROCESS_ONLY },
     { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
     { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::MAIN_PROCESS_ONLY },
 #endif
     { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -7036,8 +7036,70 @@ nsWindow::GetWaylandSurface()
 {
   if (mContainer)
     return moz_container_get_wl_surface(MOZ_CONTAINER(mContainer));
 
   NS_WARNING("nsWindow::GetWaylandSurfaces(): We don't have any mContainer for drawing!");
   return nullptr;
 }
 #endif
+
+#ifdef MOZ_X11
+/* XApp progress support currently works by setting a property
+ * on a window with this Atom name.  A supporting window manager
+ * will notice this and pass it along to whatever handling has
+ * been implemented on that end (e.g. passing it on to a taskbar
+ * widget.)  There is no issue if WM support is lacking, this is
+ * simply ignored in that case.
+ *
+ * See https://github.com/linuxmint/xapps/blob/master/libxapp/xapp-gtk-window.c
+ * for further details.
+ */
+
+#define PROGRESS_HINT  "_NET_WM_XAPP_PROGRESS"
+
+static void
+set_window_hint_cardinal (Window       xid,
+                          const gchar *atom_name,
+                          gulong       cardinal)
+{
+  GdkDisplay *display;
+
+  display = gdk_display_get_default ();
+
+  if (cardinal > 0)
+  {
+    XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                     xid,
+                     gdk_x11_get_xatom_by_name_for_display (display, atom_name),
+                     XA_CARDINAL, 32,
+                     PropModeReplace,
+                     (guchar *) &cardinal, 1);
+  }
+  else
+  {
+    XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                     xid,
+                     gdk_x11_get_xatom_by_name_for_display (display, atom_name));
+  }
+}
+#endif // MOZ_X11
+
+void
+nsWindow::SetProgress(unsigned long progressPercent)
+{
+#ifdef MOZ_X11
+
+  if (!mIsX11Display) {
+    return;
+  }
+
+  if (!mShell) {
+    return;
+  }
+
+  progressPercent = CLAMP(progressPercent, 0, 100);
+
+  set_window_hint_cardinal(GDK_WINDOW_XID(gtk_widget_get_window(mShell)),
+                           PROGRESS_HINT,
+                           progressPercent);
+#endif // MOZ_X11
+}
\ No newline at end of file
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -223,16 +223,18 @@ public:
 #endif
 
     virtual already_AddRefed<mozilla::gfx::DrawTarget>
                        StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
                                                   mozilla::layers::BufferMode* aBufferMode) override;
     virtual void       EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget,
                                                 LayoutDeviceIntRegion& aInvalidRegion) override;
 
+    void               SetProgress(unsigned long progressPercent);
+
 private:
     void               UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, nsIntRect aBoundsRect);
 
     void               NativeMove();
     void               NativeResize();
     void               NativeMoveResize();
 
     void               NativeShow  (bool    aAction);
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -79,16 +79,21 @@ DIRS += ['headless']
 # source tree.
 #
 if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     DIRS += ['gtk']
 
     if CONFIG['MOZ_X11']:
         DIRS += ['gtkxtbin']
 
+    XPIDL_SOURCES += [
+        'nsIGtkTaskbarProgress.idl',
+        'nsITaskbarProgress.idl',
+    ]
+
 XPIDL_SOURCES += [
     'nsIAppShell.idl',
     'nsIBaseWindow.idl',
     'nsIBidiKeyboard.idl',
     'nsIClipboard.idl',
     'nsIClipboardDragDropHookList.idl',
     'nsIClipboardDragDropHooks.idl',
     'nsIClipboardHelper.idl',
new file mode 100644
--- /dev/null
+++ b/widget/nsIGtkTaskbarProgress.idl
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsITaskbarProgress.idl"
+
+interface mozIDOMWindowProxy;
+
+/**
+ * Allow the TaskbarProgress instance to set a new target window.
+ */
+
+[scriptable, uuid(39f6fc5a-2386-4bc6-941c-d7479253bc3f)]
+interface nsIGtkTaskbarProgress : nsITaskbarProgress
+{
+  /**
+   * Sets the window that is considered primary for purposes of
+   * setting the XApp progress property.
+   */
+
+  void setPrimaryWindow(in mozIDOMWindowProxy aWindow);
+};
--- a/widget/nsWidgetsCID.h
+++ b/widget/nsWidgetsCID.h
@@ -150,16 +150,20 @@
 // {B16656B2-5187-498f-ABF4-56346126BFDB}
 #define NS_WIN_JUMPLISTSHORTCUT_CID \
 { 0xb16656b2, 0x5187, 0x498f, { 0xab, 0xf4, 0x56, 0x34, 0x61, 0x26, 0xbf, 0xdb } }
 
 // {e9096367-ddd9-45e4-b762-49c0c18b7119}
 #define NS_MACWEBAPPUTILS_CID \
 { 0xe9096367, 0xddd9, 0x45e4, { 0xb7, 0x62, 0x49, 0xc0, 0xc1, 0x8b, 0x71, 0x19 } }
 
+// {a9339876-0027-430f-b953-84c9c11c2da3}
+#define NS_GTK_TASKBARPROGRESS_CID \
+{ 0xa9339876, 0x0027, 0x430f, { 0xb9, 0x53, 0x84, 0xc9, 0xc1, 0x1c, 0x2d, 0xa3 } }
+
 //-----------------------------------------------------------
 //Printing
 //-----------------------------------------------------------
 #define NS_DEVICE_CONTEXT_SPEC_CID \
 { 0xd3f69889, 0xe13a, 0x4321, \
 { 0x98, 0x0c, 0xa3, 0x93, 0x32, 0xe2, 0x1f, 0x34 } }
 
 #define NS_PRINTSETTINGSSERVICE_CID \