Skip to content

Commit

Permalink
Merge pull request #28 from pkerling/issue/7-screensaver
Browse files Browse the repository at this point in the history
Screensaver inhibition
  • Loading branch information
pkerling authored Jun 30, 2017
2 parents 25a95e0 + 4478f19 commit 21352a0
Show file tree
Hide file tree
Showing 24 changed files with 450 additions and 26 deletions.
3 changes: 2 additions & 1 deletion cmake/scripts/linux/ExtraTargets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ endif()
if(CORE_PLATFORM_NAME STREQUAL "wayland")
# This cannot go into wayland.cmake since it requires the Wayland dependencies
# to already be resolved
set(PROTOCOL_XMLS "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml")
set(PROTOCOL_XMLS "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml"
"${WAYLAND_PROTOCOLS_DIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml")
add_custom_command(OUTPUT "${WAYLAND_EXTRA_PROTOCOL_GENERATED_DIR}/wayland-extra-protocols.hpp" "${WAYLAND_EXTRA_PROTOCOL_GENERATED_DIR}/wayland-extra-protocols.cpp"
COMMAND "${WAYLANDPP_SCANNER}" ${PROTOCOL_XMLS} "${WAYLAND_EXTRA_PROTOCOL_GENERATED_DIR}/wayland-extra-protocols.hpp" "${WAYLAND_EXTRA_PROTOCOL_GENERATED_DIR}/wayland-extra-protocols.cpp"
DEPENDS "${WAYLANDPP_SCANNER}" ${PROTOCOL_XMLS}
Expand Down
1 change: 1 addition & 0 deletions cmake/treedata/linux/subdirs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ xbmc/storage/linux storage/linux
xbmc/filesystem/posix filesystem/posix
xbmc/utils/posix utils_posix
xbmc/platform/posix posix
xbmc/windowing/linux windowing/linux
29 changes: 15 additions & 14 deletions xbmc/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,20 +680,6 @@ bool CApplication::CreateGUI()
return false;
}

// Set default screen saver mode
auto screensaverModeSetting = std::static_pointer_cast<CSettingString>(m_ServiceManager->GetSettings().GetSetting(CSettings::SETTING_SCREENSAVER_MODE));
// Can only set this after windowing has been initialized since it depends on it
if (g_Windowing.GetOSScreenSaver())
{
// If OS has a screen saver, use it by default
screensaverModeSetting->SetDefault("");
}
else
{
// If OS has no screen saver, use Kodi one by default
screensaverModeSetting->SetDefault("screensaver.xbmc.builtin.dim");
}
CheckOSScreenSaverInhibitionSetting();

// Retrieve the matching resolution based on GUI settings
bool sav_res = false;
Expand Down Expand Up @@ -729,6 +715,21 @@ bool CApplication::CreateGUI()
return false;
}

// Set default screen saver mode
auto screensaverModeSetting = std::static_pointer_cast<CSettingString>(m_ServiceManager->GetSettings().GetSetting(CSettings::SETTING_SCREENSAVER_MODE));
// Can only set this after windowing has been initialized since it depends on it
if (g_Windowing.GetOSScreenSaver())
{
// If OS has a screen saver, use it by default
screensaverModeSetting->SetDefault("");
}
else
{
// If OS has no screen saver, use Kodi one by default
screensaverModeSetting->SetDefault("screensaver.xbmc.builtin.dim");
}
CheckOSScreenSaverInhibitionSetting();

if (sav_res)
CDisplaySettings::GetInstance().SetCurrentResolution(RES_DESKTOP, true);

Expand Down
1 change: 1 addition & 0 deletions xbmc/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ set(HEADERS ConvUtils.h
DllBCM.h
LinuxResourceCounter.h
LinuxTimezone.h
PlatformConstants.h
PlatformDefs.h
PlatformInclude.h
PosixMountProvider.h
Expand Down
33 changes: 33 additions & 0 deletions xbmc/linux/DBusMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ void CDBusMessage::AppendArgument<bool>(const bool arg)
AppendWithType(DBUS_TYPE_BOOLEAN, &convArg);
}

template<>
void CDBusMessage::AppendArgument<std::string>(const std::string arg)
{
AppendArgument(arg.c_str());
}

void CDBusMessage::AppendArgument(const char **arrayString, unsigned int length)
{
PrepareArgument();
Expand Down Expand Up @@ -170,3 +176,30 @@ void CDBusMessage::PrepareArgument()

m_haveArgs = true;
}

bool CDBusMessage::InitializeReplyIter(DBusMessageIter* iter)
{
if (!m_reply)
{
throw std::logic_error("Cannot get reply arguments of message that does not have reply");
}
if (!dbus_message_iter_init(m_reply.get(), iter))
{
CLog::Log(LOGWARNING, "Tried to obtain reply arguments from message that has zero arguments");
return false;
}
return true;
}

bool CDBusMessage::CheckTypeAndGetValue(DBusMessageIter* iter, int expectType, void* dest)
{
const int haveType = dbus_message_iter_get_arg_type(iter);
if (haveType != expectType)
{
CLog::Log(LOGDEBUG, "DBus argument type mismatch: expected %d, got %d", expectType, haveType);
return false;
}

dbus_message_iter_get_basic(iter, dest);
return true;
}
69 changes: 69 additions & 0 deletions xbmc/linux/DBusMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <cstdint>
#include <memory>
#include <string>
#include <type_traits>

#include <dbus/dbus.h>

Expand All @@ -42,6 +43,9 @@ template<> struct ToDBusType<std::int64_t> { static constexpr int TYPE = DBUS_TY
template<> struct ToDBusType<std::uint64_t> { static constexpr int TYPE = DBUS_TYPE_UINT64; };
template<> struct ToDBusType<double> { static constexpr int TYPE = DBUS_TYPE_DOUBLE; };

template<typename T>
using ToDBusTypeFromPointer = ToDBusType<typename std::remove_pointer<T>::type>;

struct DBusMessageDeleter
{
void operator()(DBusMessage* message) const;
Expand All @@ -63,6 +67,48 @@ class CDBusMessage
}
void AppendArgument(const char **arrayString, unsigned int length);

template<typename TFirst>
void AppendArguments(const TFirst first)
{
AppendArgument(first);
// Recursion end
}
template<typename TFirst, typename... TArgs>
void AppendArguments(const TFirst first, const TArgs... args)
{
AppendArgument(first);
AppendArguments(args...);
}

/**
* Retrieve simple arguments from DBus reply message
*
* You MUST use the correct fixed-width integer typedefs (e.g. std::uint16_t)
* corresponding to the DBus types for the variables or you will get potentially
* differing behavior between architectures since the DBus argument type detection
* is based on the width of the type.
*
* Complex arguments (arrays, structs) are not supported.
*
* Returned pointers for strings are only valid until the instance of this class
* is deleted.
*
* \throw std::logic_error if the message has no reply
* \return whether all arguments could be retrieved (false on argument type
* mismatch or when more arguments were to be retrieved than there are
* in the message)
*/
template<typename... TArgs>
bool GetReplyArguments(TArgs*... args)
{
DBusMessageIter iter;
if (!InitializeReplyIter(&iter))
{
return false;
}
return GetReplyArgumentsWithIter(&iter, args...);
}

DBusMessage *SendSystem();
DBusMessage *SendSession();
DBusMessage *SendSystem(CDBusError& error);
Expand All @@ -80,6 +126,27 @@ class CDBusMessage

void PrepareArgument();

bool InitializeReplyIter(DBusMessageIter* iter);
bool CheckTypeAndGetValue(DBusMessageIter* iter, int expectType, void* dest);
template<typename TFirst>
bool GetReplyArgumentsWithIter(DBusMessageIter* iter, TFirst* first)
{
// Recursion end
return CheckTypeAndGetValue(iter, ToDBusTypeFromPointer<TFirst>::TYPE, first);
}
template<typename TFirst, typename... TArgs>
bool GetReplyArgumentsWithIter(DBusMessageIter* iter, TFirst* first, TArgs*... args)
{
if (!CheckTypeAndGetValue(iter, ToDBusTypeFromPointer<TFirst>::TYPE, first))
{
return false;
}
// Ignore return value, if we try to read past the end of the message this
// will be catched by the type check (past-end type is DBUS_TYPE_INVALID)
dbus_message_iter_next(iter);
return GetReplyArgumentsWithIter(iter, args...);
}

DBusMessagePtr m_message;
DBusMessagePtr m_reply;
DBusMessageIter m_args;
Expand All @@ -88,4 +155,6 @@ class CDBusMessage

template<>
void CDBusMessage::AppendArgument<bool>(const bool arg);
template<>
void CDBusMessage::AppendArgument<std::string>(const std::string arg);
#endif
35 changes: 35 additions & 0 deletions xbmc/linux/PlatformConstants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2017 Team XBMC
* http://xbmc.org
*
* 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, 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 XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#pragma once

#include <string>

namespace KODI
{
namespace LINUX
{

/**
* Name of the kodi .desktop file without the extension
*/
const std::string DESKTOP_FILE_NAME = "kodi";

}
}
6 changes: 6 additions & 0 deletions xbmc/windowing/OSScreenSaver.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class COSScreenSaverInhibitor
class IOSScreenSaver
{
public:
IOSScreenSaver() {}
virtual ~IOSScreenSaver() {}
/**
* Do not allow the OS screen saver to become active
Expand All @@ -81,6 +82,11 @@ class IOSScreenSaver
* MUST NOT produce any side-effects.
*/
virtual void Uninhibit() = 0;

private:
// Not designed to be copyable
IOSScreenSaver(IOSScreenSaver const& other) = delete;
IOSScreenSaver& operator=(IOSScreenSaver const& other) = delete;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion xbmc/windowing/XkbcommonKeymap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ CXkbcommonContext::~CXkbcommonContext()
CXkbcommonKeymap*
CXkbcommonContext::KeymapFromSharedMemory(int fd, std::size_t size)
{
CMmap mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
CMmap mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
auto keymapString = static_cast<const char *> (mmap.data());

xkb_keymap* keymap = xkb_keymap_new_from_string(m_context, keymapString, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
Expand Down
11 changes: 11 additions & 0 deletions xbmc/windowing/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(SOURCES "")
set(HEADERS "")

if(DBUS_FOUND)
list(APPEND SOURCES OSScreenSaverFreedesktop.cpp)
list(APPEND HEADERS OSScreenSaverFreedesktop.h)
endif()

if(SOURCES)
core_add_library(windowing_linux)
endif()
88 changes: 88 additions & 0 deletions xbmc/windowing/linux/OSScreenSaverFreedesktop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2017 Team XBMC
* http://xbmc.org
*
* 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, 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 XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include "OSScreenSaverFreedesktop.h"

#include "guilib/LocalizeStrings.h"
#include "linux/DBusMessage.h"
#include "linux/DBusUtil.h"
#include "linux/PlatformConstants.h"
#include "utils/log.h"

using namespace KODI::WINDOWING::LINUX;

namespace
{
const std::string SCREENSAVER_OBJECT = "/org/freedesktop/ScreenSaver";
const std::string SCREENSAVER_INTERFACE = "org.freedesktop.ScreenSaver";
}

bool COSScreenSaverFreedesktop::IsAvailable()
{
// Test by making a call to a function without side-effects
CDBusMessage dummyMessage(SCREENSAVER_INTERFACE, SCREENSAVER_OBJECT, SCREENSAVER_INTERFACE, "GetActive");
CDBusError error;
dummyMessage.SendSession(error);
// We do not care whether GetActive() is actually supported, we're just checking for the name to be there
// (GNOME for example does not support GetActive)
return !error || error.Name() == DBUS_ERROR_NOT_SUPPORTED;
}

void COSScreenSaverFreedesktop::Inhibit()
{
if (m_inhibited)
{
return;
}

CDBusMessage inhibitMessage(SCREENSAVER_INTERFACE, SCREENSAVER_OBJECT, SCREENSAVER_INTERFACE, "Inhibit");
inhibitMessage.AppendArguments(KODI::LINUX::DESKTOP_FILE_NAME, g_localizeStrings.Get(14086));
if (!inhibitMessage.SendSession())
{
// DBus call failed
CLog::Log(LOGERROR, "Inhibiting freedesktop screen saver failed");
return;
}

if (!inhibitMessage.GetReplyArguments(&m_cookie))
{
CLog::Log(LOGERROR, "Could not retrieve cookie from org.freedesktop.ScreenSaver Inhibit response");
return;
}

m_inhibited = true;
}

void COSScreenSaverFreedesktop::Uninhibit()
{
if (!m_inhibited)
{
return;
}

CDBusMessage uninhibitMessage(SCREENSAVER_INTERFACE, SCREENSAVER_OBJECT, SCREENSAVER_INTERFACE, "UnInhibit");
uninhibitMessage.AppendArgument(m_cookie);
if (!uninhibitMessage.SendSession())
{
CLog::Log(LOGERROR, "Uninhibiting freedesktop screen saver failed");
}

m_inhibited = false;
}
Loading

0 comments on commit 21352a0

Please sign in to comment.