From 41149ca134ff1ffe1029e3eebf1c6b3e95ef4422 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Thu, 15 Mar 2018 20:43:08 +0100 Subject: GHOST: Support Unity taskbar progress API 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 | 2 + intern/ghost/intern/GHOST_TaskbarX11.cpp | 130 +++++++++++++++++++++++++++++++ intern/ghost/intern/GHOST_TaskbarX11.h | 45 +++++++++++ intern/ghost/intern/GHOST_WindowX11.cpp | 22 ++++++ intern/ghost/intern/GHOST_WindowX11.h | 7 ++ 5 files changed, 206 insertions(+) create mode 100644 intern/ghost/intern/GHOST_TaskbarX11.cpp create mode 100644 intern/ghost/intern/GHOST_TaskbarX11.h (limited to 'intern/ghost') diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 5a97da28d17..ba569ff4166 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -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 index 00000000000..b47068df39f --- /dev/null +++ b/intern/ghost/intern/GHOST_TaskbarX11.cpp @@ -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 +#include +#include +#include + +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 index 00000000000..ed0e5f9b329 --- /dev/null +++ b/intern/ghost/intern/GHOST_TaskbarX11.h @@ -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__*/ diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 1abdec37403..13fef7d1db1 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -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; +} diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 5c54c1e8162..236fe0b76b0 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -41,6 +41,8 @@ # include #endif +#include "GHOST_TaskbarX11.h" + #include 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 m_standard_cursors; + GHOST_TaskBarX11 m_taskbar; + #ifdef WITH_XDND GHOST_DropTargetX11 *m_dropTarget; #endif -- cgit v1.2.3