From b7d452d2a0df442b2c4241bf91734a6fdc66365e Mon Sep 17 00:00:00 2001 From: Arda Demir Date: Tue, 14 Apr 2020 18:53:53 +0300 Subject: [PATCH] Libnotify support for linux client (#2099) Add libnotify support for linux client Also unify notification management Make libnotify mandatory for the client. It is installed on 100% of Arch Linux systems and on 70% of Debian systems. I'd guess the remaining Debian systems are servers. Detect dependent libraries of `libnotify` using `pkg-config`. Remove library-specific code from the game module. Decrement refcount for libnotify notification object before leaving the function. --- .github/workflows/build.yaml | 2 +- CMakeLists.txt | 14 +++++--- README.md | 4 +-- cmake/FindNotify.cmake | 4 +++ src/engine/client.h | 1 + src/engine/client/backend_sdl.cpp | 3 -- src/engine/client/client.cpp | 14 ++++++++ src/engine/client/client.h | 1 + src/engine/client/notifications.cpp | 35 ++++++++++++++++++++ src/engine/client/notifications.h | 6 ++++ src/game/client/components/chat.cpp | 10 +----- src/osx/notification.h | 10 ------ src/osx/{notification.mm => notifications.m} | 13 ++++++-- 13 files changed, 84 insertions(+), 33 deletions(-) create mode 100644 cmake/FindNotify.cmake create mode 100644 src/engine/client/notifications.cpp create mode 100644 src/engine/client/notifications.h delete mode 100644 src/osx/notification.h rename src/osx/{notification.mm => notifications.m} (71%) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 987273739..c0292de51 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -52,7 +52,7 @@ jobs: if: contains(matrix.os, 'ubuntu') run: | sudo apt-get update -y - sudo apt-get install pkg-config cmake libfreetype6-dev libsdl2-dev -y + sudo apt-get install pkg-config cmake libfreetype6-dev libnotify-dev libsdl2-dev -y - name: Prepare MacOS if: contains(matrix.os, 'macOS') diff --git a/CMakeLists.txt b/CMakeLists.txt index 311e604b1..5d8537386 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -463,18 +463,18 @@ elseif(TARGET_OS STREQUAL "mac") find_library(OPENGL OpenGL) find_library(SECURITY Security) set(PLATFORM_CLIENT - src/osx/notification.h - src/osx/notification.mm + src/osx/notifications.m src/osxlaunch/client.m ) set(PLATFORM_CLIENT_LIBS ${COCOA} ${OPENGL}) set(PLATFORM_LIBS ${CARBON} ${SECURITY}) else() - set(PLATFORM_CLIENT) + find_package(Notify) find_package(OpenGL) find_package(X11) - set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${X11_X11_LIB}) - set(PLATFORM_CLIENT_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH}) + set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${X11_X11_LIB} ${NOTIFY_LIBRARIES}) + set(PLATFORM_CLIENT_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH} ${NOTIFY_INCLUDE_DIRS}) + set(PLATFORM_CLIENT) if(TARGET_OS STREQUAL "linux") set(PLATFORM_LIBS rt) # clock_gettime for glibc < 2.17 else() @@ -822,6 +822,8 @@ if(CLIENT) input.cpp input.h keynames.h + notifications.cpp + notifications.h opengl_sl.cpp opengl_sl.h opengl_sl_program.cpp @@ -1011,6 +1013,8 @@ if(CLIENT) ${SDL2_INCLUDE_DIRS} ${WAVPACK_INCLUDE_DIRS} ${FFMPEG_INCLUDE_DIRS} + + ${PLATFORM_CLIENT_INCLUDE_DIRS} ) set(PARAMS "${WAVPACK_INCLUDE_DIRS};${WAVPACK_INCLUDE_DIRS}") diff --git a/README.md b/README.md index dc2424e7b..552d696aa 100644 --- a/README.md +++ b/README.md @@ -39,11 +39,11 @@ Pass the number of threads for compilation to `make -j`. `$(nproc)` in this case You can install the required libraries on your system, `touch CMakeLists.txt` and CMake will use the system-wide libraries by default. You can install all required dependencies and CMake on Debian or Ubuntu like this: - sudo apt install cmake git libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libwavpack-dev python + sudo apt install cmake git libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libwavpack-dev python Or on Arch Linux like this: - sudo pacman -S --needed base-devel cmake curl freetype2 git glew opusfile python sdl2 wavpack + sudo pacman -S --needed base-devel cmake curl freetype2 git glew libnotify opusfile python sdl2 wavpack There is an [AUR package for pnglite](https://aur.archlinux.org/packages/pnglite/). For instructions on installing it, see [AUR packages installation instructions on ArchWiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages). diff --git a/cmake/FindNotify.cmake b/cmake/FindNotify.cmake new file mode 100644 index 000000000..2f8639780 --- /dev/null +++ b/cmake/FindNotify.cmake @@ -0,0 +1,4 @@ +find_package(PkgConfig REQUIRED QUIET) +pkg_check_modules(NOTIFY REQUIRED QUIET libnotify) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LibNotify DEFAULT_MSG NOTIFY_LIBRARIES NOTIFY_INCLUDE_DIRS) diff --git a/src/engine/client.h b/src/engine/client.h index 1a4edd897..33a08fc74 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -121,6 +121,7 @@ public: virtual void ToggleWindowBordered() = 0; virtual void ToggleWindowVSync() = 0; virtual void LoadFont() = 0; + virtual void Notify(const char *pTitle, const char *pMessage) = 0; // networking virtual void EnterGame() = 0; diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 84adfd53b..45d3a1725 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -2573,9 +2573,6 @@ void CGraphicsBackend_SDL_OpenGL::SetWindowGrab(bool Grab) void CGraphicsBackend_SDL_OpenGL::NotifyWindow() { - if(!g_Config.m_ClShowNotifications) - return; - // get window handle SDL_SysWMinfo info; SDL_VERSION(&info.version); diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 000bd742a..33aa833cb 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -3783,6 +3784,15 @@ void CClient::LoadFont() m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load font. filename='%s'", pFontFile); } +void CClient::Notify(const char *pTitle, const char *pMessage) +{ + if(!g_Config.m_ClShowNotifications) + return; + + NotificationsNotify(pTitle, pMessage); + Graphics()->NotifyWindow(); +} + void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { CClient *pSelf = (CClient *)pUserData; @@ -3954,6 +3964,8 @@ int main(int argc, const char **argv) // ignore_convention RandInitFailed = true; } + NotificationsInit(); + CClient *pClient = CreateClient(); IKernel *pKernel = IKernel::Create(); pKernel->RegisterInterface(pClient, false); @@ -4086,6 +4098,8 @@ int main(int argc, const char **argv) // ignore_convention pClient->~CClient(); free(pClient); + NotificationsUninit(); + if(Restarting) { char aBuf[512]; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index f7258b419..893839c37 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -428,6 +428,7 @@ public: void ToggleWindowBordered(); void ToggleWindowVSync(); void LoadFont(); + void Notify(const char *pTitle, const char *pMessage); // DDRace diff --git a/src/engine/client/notifications.cpp b/src/engine/client/notifications.cpp new file mode 100644 index 000000000..ec0934b5a --- /dev/null +++ b/src/engine/client/notifications.cpp @@ -0,0 +1,35 @@ +#include "notifications.h" + +#include + +#if defined(CONF_PLATFORM_MACOSX) +// Code is in src/osx/notification.mm. +#elif defined(CONF_FAMILY_UNIX) +#include +void NotificationsInit() +{ + notify_init("DDNet Client"); +} +void NotificationsUninit() +{ + notify_uninit(); +} +void NotificationsNotify(const char *pTitle, const char *pMessage) +{ + NotifyNotification *pNotif = notify_notification_new(pTitle, pMessage, NULL); + notify_notification_show(pNotif, NULL); + g_object_unref(G_OBJECT(pNotif)); +} +#else +void NotificationsInit() +{ +} +void NotificationsUninit() +{ +} +void NotificationsNotify(const char *pTitle, const char *pMessage) +{ + (void)pTitle; + (void)pMessage; +} +#endif diff --git a/src/engine/client/notifications.h b/src/engine/client/notifications.h new file mode 100644 index 000000000..35d7b588a --- /dev/null +++ b/src/engine/client/notifications.h @@ -0,0 +1,6 @@ +#ifndef ENGINE_CLIENT_NOTIFICATIONS_H +#define ENGINE_CLIENT_NOTIFICATIONS_H +void NotificationsInit(); +void NotificationsUninit(); +void NotificationsNotify(const char *pTitle, const char *pMessage); +#endif // ENGINE_CLIENT_NOTIFICATIONS_H diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 2c2e20c9b..a99973d10 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -19,10 +19,6 @@ #include #include -#ifdef CONF_PLATFORM_MACOSX -#include -#endif - #include "chat.h" @@ -704,13 +700,9 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) { if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10) { -#ifdef CONF_PLATFORM_MACOSX char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText); - CNotification::Notify("DDNet-Chat", aBuf); -#else - Graphics()->NotifyWindow(); -#endif + Client()->Notify("DDNet Chat", aBuf); if(g_Config.m_SndHighlight) { m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); diff --git a/src/osx/notification.h b/src/osx/notification.h deleted file mode 100644 index 5834f3eb5..000000000 --- a/src/osx/notification.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef OSX_NOTIFICATION_H -#define OSX_NOTIFICATION_H - -class CNotification -{ -public: - static void Notify(const char *pTitle, const char *pMsg); -}; - -#endif // OSX_NOTIFICATION_H diff --git a/src/osx/notification.mm b/src/osx/notifications.m similarity index 71% rename from src/osx/notification.mm rename to src/osx/notifications.m index 761a0564f..39ed0aee1 100644 --- a/src/osx/notification.mm +++ b/src/osx/notifications.m @@ -1,12 +1,19 @@ +#import + #import #import #import -#import "notification.h" -void CNotification::Notify(const char *pTitle, const char *pMsg) +void NotificationsInit() +{ +} +void NotificationsUninit() +{ +} +void NotificationsNotify(const char *pTitle, const char *pMessage) { NSString* pNsTitle = [NSString stringWithCString:pTitle encoding:NSUTF8StringEncoding]; - NSString* pNsMsg = [NSString stringWithCString:pMsg encoding:NSUTF8StringEncoding]; + NSString* pNsMsg = [NSString stringWithCString:pMessage encoding:NSUTF8StringEncoding]; NSUserNotification *pNotification = [[NSUserNotification alloc] autorelease]; pNotification.title = pNsTitle;