GHOST: Support Unity taskbar progress API
authorLukas Stockner <lukas.stockner@freenet.de>
Thu, 15 Mar 2018 19:43:08 +0000 (20:43 +0100)
committerLukas Stockner <lukas.stockner@freenet.de>
Thu, 15 Mar 2018 21:49:56 +0000 (22:49 +0100)
Unity itself is deprecated, but the API is also supported by KDE and the GNOME Dock extension,
which means that it will be useful for a wide variety of distributions.

To get a progress bar, the system must have a blender.desktop file and libunity installed.

The need for libunity is annoying, but the only alternative would be to integrate a DBus library...

Reviewers: campbellbarton, brecht

Differential Revision: https://developer.blender.org/D3106

intern/ghost/CMakeLists.txt
intern/ghost/intern/GHOST_TaskbarX11.cpp [new file with mode: 0644]
intern/ghost/intern/GHOST_TaskbarX11.h [new file with mode: 0644]
intern/ghost/intern/GHOST_WindowX11.cpp
intern/ghost/intern/GHOST_WindowX11.h

index 5a97da2..ba569ff 100644 (file)
@@ -177,10 +177,12 @@ elseif(WITH_X11)
                intern/GHOST_DisplayManagerX11.cpp
                intern/GHOST_SystemX11.cpp
                intern/GHOST_WindowX11.cpp
+               intern/GHOST_TaskbarX11.cpp
 
                intern/GHOST_DisplayManagerX11.h
                intern/GHOST_SystemX11.h
                intern/GHOST_WindowX11.h
+               intern/GHOST_TaskbarX11.h
        )
 
        if(NOT WITH_GL_EGL)
diff --git a/intern/ghost/intern/GHOST_TaskbarX11.cpp b/intern/ghost/intern/GHOST_TaskbarX11.cpp
new file mode 100644 (file)
index 0000000..b47068d
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ *   Lukas Stockner
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_TaskbarX11.cpp
+ *  \ingroup GHOST
+ */
+
+#include "GHOST_TaskbarX11.h"
+
+#include <dlfcn.h>
+#include <cstdio>
+#include <cassert>
+#include <cstdlib>
+
+typedef void*(*unity_get_entry_t)(const char*);
+typedef void(*unity_set_progress_t)(void*, double);
+typedef void(*unity_set_progress_visible_t)(void*, int);
+typedef int(*unity_event_loop_t)(void*, int);
+
+static unity_get_entry_t unity_get_entry;
+static unity_set_progress_t unity_set_progress;
+static unity_set_progress_visible_t unity_set_progress_visible;
+static unity_event_loop_t unity_event_loop;
+
+static bool libunity_initialized = false;
+static bool libunity_available = false;
+void* libunity_handle = NULL;
+
+void GHOST_TaskBarX11::free()
+{
+       if(libunity_handle) {
+               dlclose(libunity_handle);
+               libunity_handle = NULL;
+       }
+}
+
+bool GHOST_TaskBarX11::init()
+{
+       if(libunity_initialized) {
+               return libunity_available;
+       }
+
+       libunity_initialized = true;
+
+       const char *libunity_names[] = {"libunity.so.4", "libunity.so.6", "libunity.so.9", "libunity.so", NULL};
+       for(int i = 0; libunity_names[i]; i++) {
+               libunity_handle = dlopen(libunity_names[i], RTLD_LAZY);
+               if(libunity_handle) {
+                       break;
+               }
+       }
+
+       if(!libunity_handle) {
+               return false;
+       }
+
+       unity_get_entry = (unity_get_entry_t) dlsym(libunity_handle, "unity_launcher_entry_get_for_desktop_id");
+       if(!unity_get_entry) {
+               fprintf(stderr, "failed to load libunity: %s\n", dlerror());
+               return false;
+       }
+       unity_set_progress = (unity_set_progress_t) dlsym(libunity_handle, "unity_launcher_entry_set_progress");
+       if(!unity_set_progress) {
+               fprintf(stderr, "failed to load libunity: %s\n", dlerror());
+               return false;
+       }
+       unity_set_progress_visible = (unity_set_progress_visible_t) dlsym(libunity_handle, "unity_launcher_entry_set_progress_visible");
+       if(!unity_set_progress_visible) {
+               fprintf(stderr, "failed to load libunity: %s\n", dlerror());
+               return false;
+       }
+       unity_event_loop = (unity_event_loop_t) dlsym(libunity_handle, "g_main_context_iteration");
+       if(!unity_event_loop) {
+               fprintf(stderr, "failed to load libunity: %s\n", dlerror());
+               return false;
+       }
+
+       atexit(GHOST_TaskBarX11::free);
+
+       libunity_available = true;
+       return true;
+}
+
+GHOST_TaskBarX11::GHOST_TaskBarX11(const char *name)
+{
+       if(GHOST_TaskBarX11::init()) {
+               handle = unity_get_entry(name);
+       }
+       else {
+               handle = NULL;
+       }
+}
+
+bool GHOST_TaskBarX11::is_valid()
+{
+       return (handle != NULL);
+}
+
+void GHOST_TaskBarX11::set_progress(double progress)
+{
+       assert(is_valid());
+       unity_set_progress(handle, progress);
+}
+
+void GHOST_TaskBarX11::set_progress_enabled(bool enabled)
+{
+       assert(is_valid());
+       unity_set_progress_visible(handle, enabled ? 1 : 0);
+       unity_event_loop(NULL, 0);
+}
\ No newline at end of file
diff --git a/intern/ghost/intern/GHOST_TaskbarX11.h b/intern/ghost/intern/GHOST_TaskbarX11.h
new file mode 100644 (file)
index 0000000..ed0e5f9
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s):
+ *   Lukas Stockner
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/intern/GHOST_TaskbarX11.h
+ *  \ingroup GHOST
+ */
+#ifndef __GHOST_TASKBARX11_H__
+#define __GHOST_TASKBARX11_H__
+
+class GHOST_TaskBarX11
+{
+public:
+       static bool init();
+       static void free();
+
+       GHOST_TaskBarX11(const char *name);
+
+       bool is_valid();
+       void set_progress(double progress);
+       void set_progress_enabled(bool enabled);
+private:
+       void *handle;
+};
+
+#endif /*__GHOST_TASKBARX11_H__*/
index 1abdec3..13fef7d 100644 (file)
@@ -334,6 +334,7 @@ GHOST_WindowX11(GHOST_SystemX11 *system,
       m_empty_cursor(None),
       m_custom_cursor(None),
       m_visible_cursor(None),
+      m_taskbar("blender.desktop"),
 #ifdef WITH_XDND
       m_dropTarget(NULL),
 #endif
@@ -1717,3 +1718,24 @@ getDPIHint()
        int dpi = pixelDiagonal / inchDiagonal;
        return dpi;
 }
+
+GHOST_TSuccess GHOST_WindowX11::setProgressBar(float progress)
+{
+       if (m_taskbar.is_valid()) {
+               m_taskbar.set_progress(progress);
+               m_taskbar.set_progress_enabled(true);
+               return GHOST_kSuccess;
+       }
+
+       return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_WindowX11::endProgressBar()
+{
+       if (m_taskbar.is_valid()) {
+               m_taskbar.set_progress_enabled(false);
+               return GHOST_kSuccess;
+       }
+
+       return GHOST_kFailure;
+}
index 5c54c1e..236fe0b 100644 (file)
@@ -41,6 +41,8 @@
 #  include <X11/extensions/XInput.h>
 #endif
 
+#include "GHOST_TaskbarX11.h"
+
 #include <map>
 
 class STR_String;
@@ -166,6 +168,9 @@ public:
        invalidate(
            );
 
+       GHOST_TSuccess setProgressBar(float progress);
+       GHOST_TSuccess endProgressBar();
+
        /**
         * Destructor.
         * Closes the window and disposes resources allocated.
@@ -347,6 +352,8 @@ private:
        /** Cache of XC_* ID's to XCursor structures */
        std::map<unsigned int, Cursor> m_standard_cursors;
 
+       GHOST_TaskBarX11 m_taskbar;
+
 #ifdef WITH_XDND
        GHOST_DropTargetX11 *m_dropTarget;
 #endif