mirror of
https://github.com/glfw/glfw.git
synced 2024-12-01 22:37:12 +00:00
Linux Added support for taskbar progress (KDE & Unity)
This commit is contained in:
parent
fb4c22ed9c
commit
827cf79f63
@ -1272,11 +1272,11 @@ extern "C" {
|
|||||||
#define GLFW_HAND_CURSOR GLFW_POINTING_HAND_CURSOR
|
#define GLFW_HAND_CURSOR GLFW_POINTING_HAND_CURSOR
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
#define GLFW_TASKBAR_PROGRESS_NOPROGRESS 0x00
|
#define GLFW_TASKBAR_PROGRESS_NOPROGRESS 0
|
||||||
#define GLFW_TASKBAR_PROGRESS_INDETERMINATE 0x01
|
#define GLFW_TASKBAR_PROGRESS_INDETERMINATE 1
|
||||||
#define GLFW_TASKBAR_PROGRESS_NORMAL 0x02
|
#define GLFW_TASKBAR_PROGRESS_NORMAL 2
|
||||||
#define GLFW_TASKBAR_PROGRESS_ERROR 0x04
|
#define GLFW_TASKBAR_PROGRESS_ERROR 3
|
||||||
#define GLFW_TASKBAR_PROGRESS_PAUSED 0x08
|
#define GLFW_TASKBAR_PROGRESS_PAUSED 4
|
||||||
|
|
||||||
#define GLFW_CONNECTED 0x00040001
|
#define GLFW_CONNECTED 0x00040001
|
||||||
#define GLFW_DISCONNECTED 0x00040002
|
#define GLFW_DISCONNECTED 0x00040002
|
||||||
|
@ -17,7 +17,8 @@ elseif (WIN32)
|
|||||||
win32_time.c win32_thread.c)
|
win32_time.c win32_thread.c)
|
||||||
else()
|
else()
|
||||||
target_sources(glfw PRIVATE posix_time.h posix_thread.h posix_module.c
|
target_sources(glfw PRIVATE posix_time.h posix_thread.h posix_module.c
|
||||||
posix_time.c posix_thread.c)
|
posix_time.c posix_thread.c posix_dbus.h
|
||||||
|
posix_dbus.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target(update_mappings
|
add_custom_target(update_mappings
|
||||||
|
@ -877,6 +877,7 @@ struct _GLFWlibrary
|
|||||||
GLFW_PLATFORM_LIBRARY_WINDOW_STATE
|
GLFW_PLATFORM_LIBRARY_WINDOW_STATE
|
||||||
GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||||
GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||||
|
GLFW_PLATFORM_LIBRARY_DBUS_STATE
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global state shared between compilation units of GLFW
|
// Global state shared between compilation units of GLFW
|
||||||
|
@ -153,11 +153,15 @@
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include "win32_time.h"
|
#include "win32_time.h"
|
||||||
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
|
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
|
||||||
|
#define GLFW_PLATFORM_LIBRARY_DBUS_STATE
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include "cocoa_time.h"
|
#include "cocoa_time.h"
|
||||||
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE
|
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE
|
||||||
|
#define GLFW_PLATFORM_LIBRARY_DBUS_STATE
|
||||||
#else
|
#else
|
||||||
#include "posix_time.h"
|
#include "posix_time.h"
|
||||||
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
|
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
|
||||||
|
#include "posix_dbus.h"
|
||||||
|
#define GLFW_PLATFORM_LIBRARY_DBUS_STATE GLFW_POSIX_LIBRARY_DBUS_STATE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
126
src/posix_dbus.c
Normal file
126
src/posix_dbus.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.4 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
void _glfwInitDBusPOSIX(void)
|
||||||
|
{
|
||||||
|
//Initialize DBus library functions
|
||||||
|
_glfw.dbus.handle = NULL;
|
||||||
|
_glfw.dbus.connection = NULL;
|
||||||
|
|
||||||
|
_glfw.dbus.handle = _glfwPlatformLoadModule("libdbus-1.so.3");
|
||||||
|
if (_glfw.dbus.handle)
|
||||||
|
{
|
||||||
|
_glfw.dbus.error_init = (PFN_dbus_error_init)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_error_init");
|
||||||
|
_glfw.dbus.error_is_set = (PFN_dbus_error_is_set)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_error_is_set");
|
||||||
|
_glfw.dbus.error_free = (PFN_dbus_error_free)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_error_free");
|
||||||
|
_glfw.dbus.connection_unref = (PFN_dbus_connection_unref)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_connection_unref");
|
||||||
|
_glfw.dbus.connection_send = (PFN_dbus_connection_send)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_connection_send");
|
||||||
|
_glfw.dbus.connection_flush = (PFN_dbus_connection_flush)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_connection_flush");
|
||||||
|
_glfw.dbus.bus_request_name = (PFN_dbus_bus_request_name)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_bus_request_name");
|
||||||
|
_glfw.dbus.bus_get = (PFN_dbus_bus_get)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_bus_get");
|
||||||
|
_glfw.dbus.message_unref = (PFN_dbus_message_unref)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_message_unref");
|
||||||
|
_glfw.dbus.message_new_signal = (PFN_dbus_message_new_signal)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_message_new_signal");
|
||||||
|
_glfw.dbus.message_iter_init_append = (PFN_dbus_message_iter_init_append)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_message_iter_init_append");
|
||||||
|
_glfw.dbus.message_iter_append_basic = (PFN_dbus_message_iter_append_basic)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_message_iter_append_basic");
|
||||||
|
_glfw.dbus.message_iter_open_container = (PFN_dbus_message_iter_open_container)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_message_iter_open_container");
|
||||||
|
_glfw.dbus.message_iter_close_container = (PFN_dbus_message_iter_close_container)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.dbus.handle, "dbus_message_iter_close_container");
|
||||||
|
|
||||||
|
//Initialize DBus connection
|
||||||
|
dbus_error_init(&_glfw.dbus.error);
|
||||||
|
_glfw.dbus.connection = dbus_bus_get(DBUS_BUS_SESSION, &_glfw.dbus.error);
|
||||||
|
|
||||||
|
//Check for errors
|
||||||
|
if(dbus_error_is_set(&_glfw.dbus.error) || !_glfw.dbus.connection)
|
||||||
|
{
|
||||||
|
if(dbus_error_is_set(&_glfw.dbus.error))
|
||||||
|
dbus_error_free(&_glfw.dbus.error);
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to connect to DBus");
|
||||||
|
|
||||||
|
dbus_connection_unref(_glfw.dbus.connection);
|
||||||
|
_glfw.dbus.connection = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Request name
|
||||||
|
const int res = dbus_bus_request_name(_glfw.dbus.connection, "org.glfw", DBUS_NAME_FLAG_REPLACE_EXISTING, &_glfw.dbus.error);
|
||||||
|
|
||||||
|
//Check for errors
|
||||||
|
if(dbus_error_is_set(&_glfw.dbus.error) || res != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
||||||
|
{
|
||||||
|
if(dbus_error_is_set(&_glfw.dbus.error))
|
||||||
|
dbus_error_free(&_glfw.dbus.error);
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to request DBus name");
|
||||||
|
|
||||||
|
dbus_connection_unref(_glfw.dbus.connection);
|
||||||
|
_glfw.dbus.connection = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_glfw.dbus.connection)
|
||||||
|
{
|
||||||
|
//Window NULL is safe here because it won't get
|
||||||
|
//used inside th eSetWindowTaskbarProgress function
|
||||||
|
_glfw.platform.setWindowTaskbarProgress(NULL, GLFW_TASKBAR_PROGRESS_NOPROGRESS, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwTerminateDBusPOSIX(void)
|
||||||
|
{
|
||||||
|
if (_glfw.dbus.connection)
|
||||||
|
{
|
||||||
|
dbus_connection_unref(_glfw.dbus.connection);
|
||||||
|
_glfw.dbus.connection = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.dbus.handle)
|
||||||
|
{
|
||||||
|
_glfwPlatformFreeModule(_glfw.dbus.handle);
|
||||||
|
_glfw.dbus.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
131
src/posix_dbus.h
Normal file
131
src/posix_dbus.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.4 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
//Taken from DBus docs (https://dbus.freedesktop.org/doc/api/html/index.html)
|
||||||
|
typedef struct DBusConnection DBusConnection;
|
||||||
|
typedef struct DBusMessage DBusMessage;
|
||||||
|
typedef unsigned int dbus_bool_t;
|
||||||
|
typedef unsigned int dbus_uint32_t;
|
||||||
|
|
||||||
|
enum DBusBusType
|
||||||
|
{
|
||||||
|
DBUS_BUS_SESSION,
|
||||||
|
DBUS_BUS_SYSTEM,
|
||||||
|
DBUS_BUS_STARTER
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DBusError
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
const char* message;
|
||||||
|
unsigned int dummy1 : 1;
|
||||||
|
unsigned int dummy2 : 1;
|
||||||
|
unsigned int dummy3 : 1;
|
||||||
|
unsigned int dummy4 : 1;
|
||||||
|
unsigned int dummy5 : 1;
|
||||||
|
void* padding1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DBusMessageIter
|
||||||
|
{
|
||||||
|
void* dummy1;
|
||||||
|
void* dummy2;
|
||||||
|
dbus_uint32_t dummy3;
|
||||||
|
int dummy4, dummy5, dummy6, dummy7, dummy8, dummy9, dummy10, dummy11;
|
||||||
|
int pad1;
|
||||||
|
void* pad2;
|
||||||
|
void* pad3;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DBUS_NAME_FLAG_REPLACE_EXISTING 0x2
|
||||||
|
#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
|
||||||
|
#define DBUS_TYPE_STRING (unsigned int)'s'
|
||||||
|
#define DBUS_TYPE_ARRAY (unsigned int)'a'
|
||||||
|
#define DBUS_TYPE_DICT_ENTRY (unsigned int)'e'
|
||||||
|
#define DBUS_TYPE_VARIANT (unsigned int)'v'
|
||||||
|
#define DBUS_TYPE_BOOLEAN (unsigned int)'b'
|
||||||
|
#define DBUS_TYPE_DOUBLE (unsigned int)'d'
|
||||||
|
|
||||||
|
typedef void (* PFN_dbus_error_init)(struct DBusError*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_error_is_set)(const struct DBusError*);
|
||||||
|
typedef void (* PFN_dbus_error_free)(struct DBusError*);
|
||||||
|
typedef void (* PFN_dbus_connection_unref)(DBusConnection*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_connection_send)(DBusConnection*, DBusMessage*, dbus_uint32_t*);
|
||||||
|
typedef void (* PFN_dbus_connection_flush)(DBusConnection*);
|
||||||
|
typedef int (* PFN_dbus_bus_request_name)(DBusConnection*, const char*, unsigned int, struct DBusError*);
|
||||||
|
typedef DBusConnection* (* PFN_dbus_bus_get)(enum DBusBusType, struct DBusError*);
|
||||||
|
typedef void (* PFN_dbus_message_unref)(DBusMessage*);
|
||||||
|
typedef DBusMessage* (* PFN_dbus_message_new_signal)(const char*, const char*, const char*);
|
||||||
|
typedef void (* PFN_dbus_message_iter_init_append)(DBusMessage*, struct DBusMessageIter*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_append_basic)(struct DBusMessageIter*, int, const void*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_open_container)(struct DBusMessageIter*, int, const char*, struct DBusMessageIter*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_close_container)(struct DBusMessageIter*, struct DBusMessageIter*);
|
||||||
|
|
||||||
|
#define dbus_error_init _glfw.dbus.error_init
|
||||||
|
#define dbus_error_is_set _glfw.dbus.error_is_set
|
||||||
|
#define dbus_error_free _glfw.dbus.error_free
|
||||||
|
#define dbus_connection_unref _glfw.dbus.connection_unref
|
||||||
|
#define dbus_connection_send _glfw.dbus.connection_send
|
||||||
|
#define dbus_connection_flush _glfw.dbus.connection_flush
|
||||||
|
#define dbus_bus_request_name _glfw.dbus.bus_request_name
|
||||||
|
#define dbus_bus_get _glfw.dbus.bus_get
|
||||||
|
#define dbus_message_unref _glfw.dbus.message_unref
|
||||||
|
#define dbus_message_new_signal _glfw.dbus.message_new_signal
|
||||||
|
#define dbus_message_iter_init_append _glfw.dbus.message_iter_init_append
|
||||||
|
#define dbus_message_iter_append_basic _glfw.dbus.message_iter_append_basic
|
||||||
|
#define dbus_message_iter_open_container _glfw.dbus.message_iter_open_container
|
||||||
|
#define dbus_message_iter_close_container _glfw.dbus.message_iter_close_container
|
||||||
|
|
||||||
|
#define GLFW_POSIX_LIBRARY_DBUS_STATE _GLFWDBusPOSIX dbus;
|
||||||
|
|
||||||
|
// POSIX-specific dbus data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWDBusPOSIX
|
||||||
|
{
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFN_dbus_error_init error_init;
|
||||||
|
PFN_dbus_error_is_set error_is_set;
|
||||||
|
PFN_dbus_error_free error_free;
|
||||||
|
PFN_dbus_connection_unref connection_unref;
|
||||||
|
PFN_dbus_connection_send connection_send;
|
||||||
|
PFN_dbus_connection_flush connection_flush;
|
||||||
|
PFN_dbus_bus_request_name bus_request_name;
|
||||||
|
PFN_dbus_bus_get bus_get;
|
||||||
|
PFN_dbus_message_unref message_unref;
|
||||||
|
PFN_dbus_message_new_signal message_new_signal;
|
||||||
|
PFN_dbus_message_iter_init_append message_iter_init_append;
|
||||||
|
PFN_dbus_message_iter_append_basic message_iter_append_basic;
|
||||||
|
PFN_dbus_message_iter_open_container message_iter_open_container;
|
||||||
|
PFN_dbus_message_iter_close_container message_iter_close_container;
|
||||||
|
|
||||||
|
DBusConnection* connection;
|
||||||
|
struct DBusError error;
|
||||||
|
} _GLFWDBusPOSIX;
|
||||||
|
|
||||||
|
void _glfwInitDBusPOSIX(void);
|
||||||
|
void _glfwTerminateDBusPOSIX(void);
|
@ -1618,7 +1618,28 @@ void _glfwSetWindowTaskbarProgressWin32(_GLFWwindow* window, const int progressS
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = window->win32.TaskbarList->lpVtbl->SetProgressState(window->win32.TaskbarList, window->win32.handle, progressState);
|
int32_t winProgressState = 0;
|
||||||
|
switch(progressState)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
winProgressState = 0x1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
winProgressState = 0x2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
winProgressState = 0x4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
winProgressState = 0x8;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
winProgressState = 0x0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = window->win32.TaskbarList->lpVtbl->SetProgressState(window->win32.TaskbarList, window->win32.handle, winProgressState);
|
||||||
if (res != S_OK)
|
if (res != S_OK)
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar progress state");
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar progress state");
|
||||||
}
|
}
|
||||||
|
@ -504,6 +504,8 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
|
|||||||
|
|
||||||
int _glfwInitWayland(void)
|
int _glfwInitWayland(void)
|
||||||
{
|
{
|
||||||
|
_glfwInitDBusPOSIX();
|
||||||
|
|
||||||
// These must be set before any failure checks
|
// These must be set before any failure checks
|
||||||
_glfw.wl.keyRepeatTimerfd = -1;
|
_glfw.wl.keyRepeatTimerfd = -1;
|
||||||
_glfw.wl.cursorTimerfd = -1;
|
_glfw.wl.cursorTimerfd = -1;
|
||||||
@ -790,5 +792,7 @@ void _glfwTerminateWayland(void)
|
|||||||
close(_glfw.wl.cursorTimerfd);
|
close(_glfw.wl.cursorTimerfd);
|
||||||
|
|
||||||
_glfw_free(_glfw.wl.clipboardString);
|
_glfw_free(_glfw.wl.clipboardString);
|
||||||
|
|
||||||
|
_glfwTerminateDBusPOSIX();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1901,8 +1901,94 @@ void _glfwSetWindowIconWayland(_GLFWwindow* window,
|
|||||||
|
|
||||||
void _glfwSetWindowTaskbarProgress(_GLFWwindow* window, const int progressState, int completed)
|
void _glfwSetWindowTaskbarProgress(_GLFWwindow* window, const int progressState, int completed)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
if(!_glfw.dbus.handle || !_glfw.dbus.connection)
|
||||||
"Wayland: The platform does not support setting the window taskbar progress");
|
return;
|
||||||
|
|
||||||
|
//Signal signature:
|
||||||
|
//signal com.canonical.Unity.LauncherEntry.Update (in s app_uri, in a{sv} properties)
|
||||||
|
|
||||||
|
const dbus_bool_t progressVisible = (taskbarState != GLFW_TASKBAR_PROGRESS_NOPROGRESS);
|
||||||
|
const double progressValue = (double)completed / 100.0;
|
||||||
|
|
||||||
|
struct DBusMessageIter args;
|
||||||
|
memset(&args, 0, sizeof(args));
|
||||||
|
|
||||||
|
//Get name of the running executable
|
||||||
|
char exeName[PATH_MAX];
|
||||||
|
memset(exeName, 0, sizeof(char) * PATH_MAX);
|
||||||
|
if(readlink("/proc/self/exe", exeName, PATH_MAX) == -1)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to get name of the running executable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char* exeNameEnd = strchr(exeName, '\0');
|
||||||
|
char* lastFound = strrchr(exeName, '/');
|
||||||
|
if(!lastFound || !exeNameEnd)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to get name of the running executable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned int exeNameLength = (exeNameEnd - lastFound) - 1;
|
||||||
|
|
||||||
|
//Create our final desktop file uri
|
||||||
|
unsigned int desktopFileLength = strlen("application://") + exeNameLength + strlen(".desktop") + 1;
|
||||||
|
char desktopFile[desktopFileLength];
|
||||||
|
memset(desktopFile, 0, sizeof(char) * desktopFileLength);
|
||||||
|
strcpy(desktopFile, "application://");
|
||||||
|
memcpy(desktopFile + strlen("application://"), lastFound + 1, exeNameLength);
|
||||||
|
strcpy(desktopFile + strlen("application://") + (exeNameLength), ".desktop");
|
||||||
|
desktopFile[desktopFileLength - 1] = '\0';
|
||||||
|
|
||||||
|
DBusMessage* msg = dbus_message_new_signal("/org/glfw", "com.canonical.Unity.LauncherEntry", "Update");
|
||||||
|
if(!msg)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create new DBus message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(msg, &args);
|
||||||
|
|
||||||
|
//Setup app_uri parameter
|
||||||
|
const char* desktopFileStr = desktopFile;
|
||||||
|
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &desktopFileStr);
|
||||||
|
|
||||||
|
//Set properties parameter
|
||||||
|
struct DBusMessageIter sub1, sub2, sub3;
|
||||||
|
memset(&sub1, 0, sizeof(sub1));
|
||||||
|
memset(&sub2, 0, sizeof(sub2));
|
||||||
|
memset(&sub3, 0, sizeof(sub3));
|
||||||
|
|
||||||
|
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{sv}", &sub1);
|
||||||
|
|
||||||
|
//Set progress visible property
|
||||||
|
dbus_message_iter_open_container(&sub1, DBUS_TYPE_DICT_ENTRY, NULL, &sub2);
|
||||||
|
const char* progressVisibleStr = "progress-visible";
|
||||||
|
dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &progressVisibleStr);
|
||||||
|
dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "b", &sub3);
|
||||||
|
dbus_message_iter_append_basic(&sub3, DBUS_TYPE_BOOLEAN, &progressVisible);
|
||||||
|
dbus_message_iter_close_container(&sub2, &sub3);
|
||||||
|
dbus_message_iter_close_container(&sub1, &sub2);
|
||||||
|
|
||||||
|
//Set progress value property
|
||||||
|
dbus_message_iter_open_container(&sub1, DBUS_TYPE_DICT_ENTRY, NULL, &sub2);
|
||||||
|
const char* progressValueStr = "progress";
|
||||||
|
dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &progressValueStr);
|
||||||
|
dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "d", &sub3);
|
||||||
|
dbus_message_iter_append_basic(&sub3, DBUS_TYPE_DOUBLE, &progressValue);
|
||||||
|
dbus_message_iter_close_container(&sub2, &sub3);
|
||||||
|
dbus_message_iter_close_container(&sub1, &sub2);
|
||||||
|
|
||||||
|
dbus_message_iter_close_container(&args, &sub1);
|
||||||
|
|
||||||
|
//Finally send the signal
|
||||||
|
unsigned int serial = 0;
|
||||||
|
if(!dbus_connection_send(_glfw.dbus.connection, msg, &serial))
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to send DBus message");
|
||||||
|
else
|
||||||
|
dbus_connection_flush(_glfw.dbus.connection);
|
||||||
|
|
||||||
|
//Free the message
|
||||||
|
dbus_message_unref(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
|
void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
|
@ -1320,6 +1320,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
|
|||||||
|
|
||||||
int _glfwInitX11(void)
|
int _glfwInitX11(void)
|
||||||
{
|
{
|
||||||
|
_glfwInitDBusPOSIX();
|
||||||
|
|
||||||
_glfw.x11.xlib.AllocClassHint = (PFN_XAllocClassHint)
|
_glfw.x11.xlib.AllocClassHint = (PFN_XAllocClassHint)
|
||||||
_glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocClassHint");
|
_glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocClassHint");
|
||||||
_glfw.x11.xlib.AllocSizeHints = (PFN_XAllocSizeHints)
|
_glfw.x11.xlib.AllocSizeHints = (PFN_XAllocSizeHints)
|
||||||
@ -1651,5 +1653,7 @@ void _glfwTerminateX11(void)
|
|||||||
close(_glfw.x11.emptyEventPipe[0]);
|
close(_glfw.x11.emptyEventPipe[0]);
|
||||||
close(_glfw.x11.emptyEventPipe[1]);
|
close(_glfw.x11.emptyEventPipe[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfwTerminateDBusPOSIX();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2150,9 +2150,96 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag
|
|||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwSetWindowTaskbarProgressX11(_GLFWwindow* window, const int taskbarState, int completed)
|
void _glfwSetWindowTaskbarProgressX11(_GLFWwindow* /*window*/, const int taskbarState, int completed)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, "X11: The platform does not support setting the window taskbar progress");
|
if(!_glfw.dbus.handle || !_glfw.dbus.connection)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Signal signature:
|
||||||
|
//signal com.canonical.Unity.LauncherEntry.Update (in s app_uri, in a{sv} properties)
|
||||||
|
|
||||||
|
const dbus_bool_t progressVisible = (taskbarState != GLFW_TASKBAR_PROGRESS_NOPROGRESS);
|
||||||
|
const double progressValue = (double)completed / 100.0;
|
||||||
|
|
||||||
|
struct DBusMessageIter args;
|
||||||
|
memset(&args, 0, sizeof(args));
|
||||||
|
|
||||||
|
//Get name of the running executable
|
||||||
|
char exeName[PATH_MAX];
|
||||||
|
memset(exeName, 0, sizeof(char) * PATH_MAX);
|
||||||
|
if(readlink("/proc/self/exe", exeName, PATH_MAX) == -1)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to get name of the running executable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char* exeNameEnd = strchr(exeName, '\0');
|
||||||
|
char* lastFound = strrchr(exeName, '/');
|
||||||
|
if(!lastFound || !exeNameEnd)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to get name of the running executable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned int exeNameLength = (exeNameEnd - lastFound) - 1;
|
||||||
|
|
||||||
|
//Create our final desktop file uri
|
||||||
|
unsigned int desktopFileLength = strlen("application://") + exeNameLength + strlen(".desktop") + 1;
|
||||||
|
char desktopFile[desktopFileLength];
|
||||||
|
memset(desktopFile, 0, sizeof(char) * desktopFileLength);
|
||||||
|
strcpy(desktopFile, "application://");
|
||||||
|
memcpy(desktopFile + strlen("application://"), lastFound + 1, exeNameLength);
|
||||||
|
strcpy(desktopFile + strlen("application://") + (exeNameLength), ".desktop");
|
||||||
|
desktopFile[desktopFileLength - 1] = '\0';
|
||||||
|
|
||||||
|
DBusMessage* msg = dbus_message_new_signal("/org/glfw", "com.canonical.Unity.LauncherEntry", "Update");
|
||||||
|
if(!msg)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create new DBus message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(msg, &args);
|
||||||
|
|
||||||
|
//Setup app_uri parameter
|
||||||
|
const char* desktopFileStr = desktopFile;
|
||||||
|
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &desktopFileStr);
|
||||||
|
|
||||||
|
//Set properties parameter
|
||||||
|
struct DBusMessageIter sub1, sub2, sub3;
|
||||||
|
memset(&sub1, 0, sizeof(sub1));
|
||||||
|
memset(&sub2, 0, sizeof(sub2));
|
||||||
|
memset(&sub3, 0, sizeof(sub3));
|
||||||
|
|
||||||
|
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{sv}", &sub1);
|
||||||
|
|
||||||
|
//Set progress visible property
|
||||||
|
dbus_message_iter_open_container(&sub1, DBUS_TYPE_DICT_ENTRY, NULL, &sub2);
|
||||||
|
const char* progressVisibleStr = "progress-visible";
|
||||||
|
dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &progressVisibleStr);
|
||||||
|
dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "b", &sub3);
|
||||||
|
dbus_message_iter_append_basic(&sub3, DBUS_TYPE_BOOLEAN, &progressVisible);
|
||||||
|
dbus_message_iter_close_container(&sub2, &sub3);
|
||||||
|
dbus_message_iter_close_container(&sub1, &sub2);
|
||||||
|
|
||||||
|
//Set progress value property
|
||||||
|
dbus_message_iter_open_container(&sub1, DBUS_TYPE_DICT_ENTRY, NULL, &sub2);
|
||||||
|
const char* progressValueStr = "progress";
|
||||||
|
dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &progressValueStr);
|
||||||
|
dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "d", &sub3);
|
||||||
|
dbus_message_iter_append_basic(&sub3, DBUS_TYPE_DOUBLE, &progressValue);
|
||||||
|
dbus_message_iter_close_container(&sub2, &sub3);
|
||||||
|
dbus_message_iter_close_container(&sub1, &sub2);
|
||||||
|
|
||||||
|
dbus_message_iter_close_container(&args, &sub1);
|
||||||
|
|
||||||
|
//Finally send the signal
|
||||||
|
unsigned int serial = 0;
|
||||||
|
if(!dbus_connection_send(_glfw.dbus.connection, msg, &serial))
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to send DBus message");
|
||||||
|
else
|
||||||
|
dbus_connection_flush(_glfw.dbus.connection);
|
||||||
|
|
||||||
|
//Free the message
|
||||||
|
dbus_message_unref(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwGetWindowPosX11(_GLFWwindow* window, int* xpos, int* ypos)
|
void _glfwGetWindowPosX11(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
|
Loading…
Reference in New Issue
Block a user