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.
This commit is contained in:
Arda Demir 2020-04-14 18:53:53 +03:00 committed by GitHub
parent 6e44394342
commit b7d452d2a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 84 additions and 33 deletions

View file

@ -52,7 +52,7 @@ jobs:
if: contains(matrix.os, 'ubuntu') if: contains(matrix.os, 'ubuntu')
run: | run: |
sudo apt-get update -y 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 - name: Prepare MacOS
if: contains(matrix.os, 'macOS') if: contains(matrix.os, 'macOS')

View file

@ -463,18 +463,18 @@ elseif(TARGET_OS STREQUAL "mac")
find_library(OPENGL OpenGL) find_library(OPENGL OpenGL)
find_library(SECURITY Security) find_library(SECURITY Security)
set(PLATFORM_CLIENT set(PLATFORM_CLIENT
src/osx/notification.h src/osx/notifications.m
src/osx/notification.mm
src/osxlaunch/client.m src/osxlaunch/client.m
) )
set(PLATFORM_CLIENT_LIBS ${COCOA} ${OPENGL}) set(PLATFORM_CLIENT_LIBS ${COCOA} ${OPENGL})
set(PLATFORM_LIBS ${CARBON} ${SECURITY}) set(PLATFORM_LIBS ${CARBON} ${SECURITY})
else() else()
set(PLATFORM_CLIENT) find_package(Notify)
find_package(OpenGL) find_package(OpenGL)
find_package(X11) find_package(X11)
set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${X11_X11_LIB}) set(PLATFORM_CLIENT_LIBS ${OPENGL_gl_LIBRARY} ${X11_X11_LIB} ${NOTIFY_LIBRARIES})
set(PLATFORM_CLIENT_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH}) set(PLATFORM_CLIENT_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH} ${NOTIFY_INCLUDE_DIRS})
set(PLATFORM_CLIENT)
if(TARGET_OS STREQUAL "linux") if(TARGET_OS STREQUAL "linux")
set(PLATFORM_LIBS rt) # clock_gettime for glibc < 2.17 set(PLATFORM_LIBS rt) # clock_gettime for glibc < 2.17
else() else()
@ -822,6 +822,8 @@ if(CLIENT)
input.cpp input.cpp
input.h input.h
keynames.h keynames.h
notifications.cpp
notifications.h
opengl_sl.cpp opengl_sl.cpp
opengl_sl.h opengl_sl.h
opengl_sl_program.cpp opengl_sl_program.cpp
@ -1011,6 +1013,8 @@ if(CLIENT)
${SDL2_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS}
${WAVPACK_INCLUDE_DIRS} ${WAVPACK_INCLUDE_DIRS}
${FFMPEG_INCLUDE_DIRS} ${FFMPEG_INCLUDE_DIRS}
${PLATFORM_CLIENT_INCLUDE_DIRS}
) )
set(PARAMS "${WAVPACK_INCLUDE_DIRS};${WAVPACK_INCLUDE_DIRS}") set(PARAMS "${WAVPACK_INCLUDE_DIRS};${WAVPACK_INCLUDE_DIRS}")

View file

@ -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: 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: 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). 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).

4
cmake/FindNotify.cmake Normal file
View file

@ -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)

View file

@ -121,6 +121,7 @@ public:
virtual void ToggleWindowBordered() = 0; virtual void ToggleWindowBordered() = 0;
virtual void ToggleWindowVSync() = 0; virtual void ToggleWindowVSync() = 0;
virtual void LoadFont() = 0; virtual void LoadFont() = 0;
virtual void Notify(const char *pTitle, const char *pMessage) = 0;
// networking // networking
virtual void EnterGame() = 0; virtual void EnterGame() = 0;

View file

@ -2573,9 +2573,6 @@ void CGraphicsBackend_SDL_OpenGL::SetWindowGrab(bool Grab)
void CGraphicsBackend_SDL_OpenGL::NotifyWindow() void CGraphicsBackend_SDL_OpenGL::NotifyWindow()
{ {
if(!g_Config.m_ClShowNotifications)
return;
// get window handle // get window handle
SDL_SysWMinfo info; SDL_SysWMinfo info;
SDL_VERSION(&info.version); SDL_VERSION(&info.version);

View file

@ -34,6 +34,7 @@
#include <engine/textrender.h> #include <engine/textrender.h>
#include <engine/client/http.h> #include <engine/client/http.h>
#include <engine/client/notifications.h>
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <engine/shared/compression.h> #include <engine/shared/compression.h>
#include <engine/shared/datafile.h> #include <engine/shared/datafile.h>
@ -3783,6 +3784,15 @@ void CClient::LoadFont()
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load font. filename='%s'", pFontFile); 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) void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{ {
CClient *pSelf = (CClient *)pUserData; CClient *pSelf = (CClient *)pUserData;
@ -3954,6 +3964,8 @@ int main(int argc, const char **argv) // ignore_convention
RandInitFailed = true; RandInitFailed = true;
} }
NotificationsInit();
CClient *pClient = CreateClient(); CClient *pClient = CreateClient();
IKernel *pKernel = IKernel::Create(); IKernel *pKernel = IKernel::Create();
pKernel->RegisterInterface(pClient, false); pKernel->RegisterInterface(pClient, false);
@ -4086,6 +4098,8 @@ int main(int argc, const char **argv) // ignore_convention
pClient->~CClient(); pClient->~CClient();
free(pClient); free(pClient);
NotificationsUninit();
if(Restarting) if(Restarting)
{ {
char aBuf[512]; char aBuf[512];

View file

@ -428,6 +428,7 @@ public:
void ToggleWindowBordered(); void ToggleWindowBordered();
void ToggleWindowVSync(); void ToggleWindowVSync();
void LoadFont(); void LoadFont();
void Notify(const char *pTitle, const char *pMessage);
// DDRace // DDRace

View file

@ -0,0 +1,35 @@
#include "notifications.h"
#include <base/detect.h>
#if defined(CONF_PLATFORM_MACOSX)
// Code is in src/osx/notification.mm.
#elif defined(CONF_FAMILY_UNIX)
#include <libnotify/notify.h>
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

View file

@ -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

View file

@ -19,10 +19,6 @@
#include <game/client/components/sounds.h> #include <game/client/components/sounds.h>
#include <game/localization.h> #include <game/localization.h>
#ifdef CONF_PLATFORM_MACOSX
#include <osx/notification.h>
#endif
#include "chat.h" #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) if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10)
{ {
#ifdef CONF_PLATFORM_MACOSX
char aBuf[1024]; char aBuf[1024];
str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText); str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText);
CNotification::Notify("DDNet-Chat", aBuf); Client()->Notify("DDNet Chat", aBuf);
#else
Graphics()->NotifyWindow();
#endif
if(g_Config.m_SndHighlight) if(g_Config.m_SndHighlight)
{ {
m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0);

View file

@ -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

View file

@ -1,12 +1,19 @@
#import <engine/client/notifications.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <Foundation/NSUserNotification.h> #import <Foundation/NSUserNotification.h>
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#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* 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]; NSUserNotification *pNotification = [[NSUserNotification alloc] autorelease];
pNotification.title = pNsTitle; pNotification.title = pNsTitle;