[client,sdl] add shortcut config file
Allow keyboard shortcuts to be configured via config file.
This commit is contained in:
parent
118f43b377
commit
62f974a5c2
@ -62,6 +62,14 @@ endif()
|
||||
find_package(SDL2 REQUIRED COMPONENTS)
|
||||
include_directories(${SDL2_INCLUDE_DIR})
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
find_package(cJSON)
|
||||
|
||||
set(LIBS "")
|
||||
if (cJSON_FOUND)
|
||||
include_directories(${CJSON_INCLUDE_DIRS})
|
||||
list(APPEND LIBS ${CJSON_LIBRARIES})
|
||||
add_compile_definitions(CJSON_FOUND)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
@ -89,7 +97,7 @@ set(SRCS
|
||||
)
|
||||
|
||||
add_subdirectory(aad)
|
||||
set(LIBS
|
||||
list(APPEND LIBS
|
||||
winpr
|
||||
freerdp
|
||||
freerdp-client
|
||||
|
@ -1,5 +1,6 @@
|
||||
set(DEPS
|
||||
sdl-freerdp-channels.1.xml
|
||||
sdl-freerdp-config.1.xml
|
||||
sdl-freerdp-examples.1.xml
|
||||
sdl-freerdp-envvar.1.xml
|
||||
)
|
||||
@ -8,4 +9,4 @@ set(MANPAGE_NAME ${PROJECT_NAME})
|
||||
if (WITH_BINARY_VERSIONING)
|
||||
set(MANPAGE_NAME ${PROJECT_NAME}${PROJECT_VERSION_MAJOR})
|
||||
endif()
|
||||
generate_and_install_freerdp_man_from_xml(${PROJECT_NAME}.1 ${MANPAGE_NAME}.1 ${DEPS})
|
||||
generate_and_install_freerdp_man_from_xml(${PROJECT_NAME}.1 ${MANPAGE_NAME}.1 "${DEPS}")
|
||||
|
81
client/SDL/man/sdl-freerdp-config.1.xml.in
Normal file
81
client/SDL/man/sdl-freerdp-config.1.xml.in
Normal file
@ -0,0 +1,81 @@
|
||||
<refsect1>
|
||||
<title>Configuration file</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Format and Location:</term>
|
||||
<listitem>
|
||||
<para>The configuration file is stored per user.<sbr/>
|
||||
The <replaceable>XDG_CONFIG_HOME</replaceable> environment variable can be used to override the base directory.<sbr/>
|
||||
This defaults to <replaceable>~/.config</replaceable>
|
||||
The location relative to <replaceable>XDG_CONFIG_HOME</replaceable> is <replaceable>$XDG_CONFIG_HOME/@VENDOR@/@PRODUCT@/@PROJECT_NAME@.json</replaceable><sbr/>
|
||||
The configuration is stored in JSON format</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Supported options:</term>
|
||||
<listitem>
|
||||
<varlistentry>
|
||||
<term><replaceable>SDL_KeyModMask</replaceable></term>
|
||||
<listitem>
|
||||
<varlistentry>
|
||||
<listitem>
|
||||
<para>Defines the key combination required for SDL client shortcuts.<sbr/>
|
||||
Default <replaceable>KMOD_RSHIFT</replaceable><sbr/>
|
||||
An array of <replaceable>SDL_Keymod</replaceable> strings as defined at <replaceable>https://wiki.libsdl.org/SDL2/SDL_Keymod</replaceable></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable>SDL_Fullscreen</replaceable></term>
|
||||
<listitem>
|
||||
<varlistentry>
|
||||
<listitem>
|
||||
<para>Toggles client fullscreen state.<sbr/>
|
||||
Default <replaceable>SDL_SCANCODE_RETURN</replaceable>.<sbr/>
|
||||
A string as defined at <replaceable>https://wiki.libsdl.org/SDL2/SDLScancodeLookup</replaceable></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable>SDL_Resizeable</replaceable></term>
|
||||
<listitem>
|
||||
<varlistentry>
|
||||
<listitem>
|
||||
<para>Toggles local window resizeable state.<sbr/>
|
||||
Default <replaceable>SDL_SCANCODE_R</replaceable>.<sbr/>
|
||||
A string as defined at <replaceable>https://wiki.libsdl.org/SDL2/SDLScancodeLookup</replaceable></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable>SDL_Grab</replaceable></term>
|
||||
<listitem>
|
||||
<varlistentry>
|
||||
<listitem>
|
||||
<para>Toggles keyboard and mouse grab state.<sbr/>
|
||||
Default <replaceable>SDL_SCANCODE_G</replaceable>.<sbr/>
|
||||
A string as defined at <replaceable>https://wiki.libsdl.org/SDL2/SDLScancodeLookup</replaceable></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable>SDL_Disconnect</replaceable></term>
|
||||
<listitem>
|
||||
<varlistentry>
|
||||
<listitem>
|
||||
<para>Disconnects from the RDP session.<sbr/>
|
||||
Default <replaceable>SDL_SCANCODE_D</replaceable>.<sbr/>
|
||||
A string as defined at <replaceable>https://wiki.libsdl.org/SDL2/SDLScancodeLookup</replaceable></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
@ -4,6 +4,7 @@ PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
<!ENTITY syntax SYSTEM "freerdp-argument.1.xml">
|
||||
<!ENTITY channels SYSTEM "sdl-freerdp-channels.1.xml">
|
||||
<!ENTITY config SYSTEM "sdl-freerdp-config.1.xml">
|
||||
<!ENTITY envvar SYSTEM "sdl-freerdp-envvar.1.xml">
|
||||
<!ENTITY examples SYSTEM "sdl-freerdp-examples.1.xml">
|
||||
]
|
||||
@ -51,6 +52,8 @@ PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
|
||||
&channels;
|
||||
|
||||
&config;
|
||||
|
||||
&envvar;
|
||||
|
||||
&examples;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
@ -1600,6 +1601,58 @@ static void SDLCALL winpr_LogOutputFunction(void* userdata, int category, SDL_Lo
|
||||
category2str(category), message);
|
||||
}
|
||||
|
||||
static void print_config_file_help()
|
||||
{
|
||||
#if defined(CJSON_FOUND)
|
||||
std::cout << "CONFIGURATION FILE" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " The SDL client supports some user defined configuration options." << std::endl;
|
||||
std::cout << " Settings are stored in JSON format" << std::endl;
|
||||
std::cout << " The location is a per user file. Location for current user is "
|
||||
<< sdl_get_pref_file() << std::endl;
|
||||
std::cout
|
||||
<< " The XDG_CONFIG_HOME environment variable can be used to override the base directory."
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " The following configuration options are supported:" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_KeyModMask" << std::endl;
|
||||
std::cout << " Defines the key combination required for SDL client shortcuts."
|
||||
<< std::endl;
|
||||
std::cout << " Default KMOD_RSHIFT" << std::endl;
|
||||
std::cout << " An array of SDL_Keymod strings as defined at "
|
||||
"https://wiki.libsdl.org/SDL2/SDL_Keymod"
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Fullscreen" << std::endl;
|
||||
std::cout << " Toggles client fullscreen state." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_RETURN." << std::endl;
|
||||
std::cout << " A string as "
|
||||
"defined at https://wiki.libsdl.org/SDL2/SDLScancodeLookup"
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Resizeable" << std::endl;
|
||||
std::cout << " Toggles local window resizeable state." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_R." << std::endl;
|
||||
std::cout << " A string as "
|
||||
"defined at https://wiki.libsdl.org/SDL2/SDLScancodeLookup"
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Grab" << std::endl;
|
||||
std::cout << " Toggles keyboard and mouse grab state." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_G." << std::endl;
|
||||
std::cout << " A string as "
|
||||
"defined at https://wiki.libsdl.org/SDL2/SDLScancodeLookup"
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " SDL_Disconnect" << std::endl;
|
||||
std::cout << " Disconnects from the RDP session." << std::endl;
|
||||
std::cout << " Default SDL_SCANCODE_D." << std::endl;
|
||||
std::cout << " A string as defined at https://wiki.libsdl.org/SDL2/SDLScancodeLookup"
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
@ -1624,6 +1677,7 @@ int main(int argc, char* argv[])
|
||||
if (status)
|
||||
{
|
||||
rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
|
||||
print_config_file_help();
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_ListMonitors))
|
||||
sdl_list_monitors(sdl);
|
||||
return rc;
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "sdl_freerdp.hpp"
|
||||
#include "sdl_utils.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <freerdp/scancode.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
@ -376,40 +378,93 @@ BOOL sdlInput::keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uint32_t sdlInput::prefToMask()
|
||||
{
|
||||
const std::map<std::string, SDL_Keymod> mapping = {
|
||||
{ "KMOD_LSHIFT", KMOD_LSHIFT },
|
||||
{ "KMOD_RSHIFT", KMOD_RSHIFT },
|
||||
{ "KMOD_LCTRL", KMOD_LCTRL },
|
||||
{ "KMOD_RCTRL", KMOD_RCTRL },
|
||||
{ "KMOD_LALT", KMOD_LALT },
|
||||
{ "KMOD_RALT", KMOD_RALT },
|
||||
{ "KMOD_LGUI", KMOD_LGUI },
|
||||
{ "KMOD_RGUI", KMOD_RGUI },
|
||||
{ "KMOD_NUM", KMOD_NUM },
|
||||
{ "KMOD_CAPS", KMOD_CAPS },
|
||||
{ "KMOD_MODE", KMOD_MODE },
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
{ "KMOD_SCROLL", KMOD_SCROLL },
|
||||
#endif
|
||||
{ "KMOD_CTRL", KMOD_CTRL },
|
||||
{ "KMOD_SHIFT", KMOD_SHIFT },
|
||||
{ "KMOD_ALT", KMOD_ALT },
|
||||
{ "KMOD_GUI", KMOD_GUI }
|
||||
};
|
||||
uint32_t mod = KMOD_NONE;
|
||||
for (const auto& val : sdl_get_pref_array("SDL_KeyModMask", { "KMOD_RSHIFT" }))
|
||||
{
|
||||
auto it = mapping.find(val);
|
||||
if (it != mapping.end())
|
||||
{
|
||||
mod |= it->second;
|
||||
}
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
||||
static const char* sdl_scancode_name(Uint32 scancode)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(map); x++)
|
||||
for (const auto& cur : map)
|
||||
{
|
||||
const scancode_entry_t* cur = &map[x];
|
||||
if (cur->sdl == scancode)
|
||||
return cur->sdl_name;
|
||||
if (cur.sdl == scancode)
|
||||
return cur.sdl_name;
|
||||
}
|
||||
|
||||
return "SDL_SCANCODE_UNKNOWN";
|
||||
}
|
||||
|
||||
static Uint32 sdl_scancode_val(const char* scancodeName)
|
||||
{
|
||||
for (const auto& cur : map)
|
||||
{
|
||||
if (strcmp(cur.sdl_name, scancodeName) == 0)
|
||||
return cur.sdl;
|
||||
}
|
||||
|
||||
return SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
static const char* sdl_rdp_scancode_name(UINT32 scancode)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(map); x++)
|
||||
for (const auto& cur : map)
|
||||
{
|
||||
const scancode_entry_t* cur = &map[x];
|
||||
if (cur->rdp == scancode)
|
||||
return cur->rdp_name;
|
||||
if (cur.rdp == scancode)
|
||||
return cur.rdp_name;
|
||||
}
|
||||
|
||||
return "RDP_SCANCODE_UNKNOWN";
|
||||
}
|
||||
|
||||
static UINT32 sdl_rdp_scancode_val(const char* scancodeName)
|
||||
{
|
||||
for (const auto& cur : map)
|
||||
{
|
||||
if (strcmp(cur.rdp_name, scancodeName) == 0)
|
||||
return cur.rdp;
|
||||
}
|
||||
|
||||
return RDP_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
static UINT32 sdl_scancode_to_rdp(Uint32 scancode)
|
||||
{
|
||||
UINT32 rdp = RDP_SCANCODE_UNKNOWN;
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(map); x++)
|
||||
for (const auto& cur : map)
|
||||
{
|
||||
const scancode_entry_t* cur = &map[x];
|
||||
if (cur->sdl == scancode)
|
||||
if (cur.sdl == scancode)
|
||||
{
|
||||
rdp = cur->rdp;
|
||||
rdp = cur.rdp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -422,32 +477,52 @@ static UINT32 sdl_scancode_to_rdp(Uint32 scancode)
|
||||
return rdp;
|
||||
}
|
||||
|
||||
uint32_t sdlInput::prefKeyValue(const std::string& key, uint32_t fallback)
|
||||
{
|
||||
auto item = sdl_get_pref_string(key);
|
||||
if (item.empty())
|
||||
return fallback;
|
||||
auto val = sdl_scancode_val(item.c_str());
|
||||
if (val == SDL_SCANCODE_UNKNOWN)
|
||||
return fallback;
|
||||
return val;
|
||||
}
|
||||
|
||||
BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev)
|
||||
{
|
||||
WINPR_ASSERT(ev);
|
||||
const UINT32 rdp_scancode = sdl_scancode_to_rdp(ev->keysym.scancode);
|
||||
const SDL_Keymod mods = SDL_GetModState();
|
||||
const SDL_Keymod mask = KMOD_RSHIFT;
|
||||
const auto mask = prefToMask();
|
||||
const auto valFullscreen = prefKeyValue("SDL_Fullscreen", SDL_SCANCODE_RETURN);
|
||||
const auto valResizeable = prefKeyValue("SDL_Resizeable", SDL_SCANCODE_R);
|
||||
const auto valGrab = prefKeyValue("SDL_Grab", SDL_SCANCODE_G);
|
||||
const auto valDisconnect = prefKeyValue("SDL_Disconnect", SDL_SCANCODE_D);
|
||||
|
||||
if ((mods & mask) == mask)
|
||||
{
|
||||
if (ev->type == SDL_KEYDOWN)
|
||||
{
|
||||
switch (ev->keysym.scancode)
|
||||
if (ev->keysym.scancode == valFullscreen)
|
||||
{
|
||||
case SDL_SCANCODE_RETURN:
|
||||
_sdl->update_fullscreen(!_sdl->fullscreen);
|
||||
return TRUE;
|
||||
case SDL_SCANCODE_R:
|
||||
_sdl->update_resizeable(!_sdl->resizeable);
|
||||
return TRUE;
|
||||
case SDL_SCANCODE_G:
|
||||
keyboard_grab(ev->windowID, _sdl->grab_kbd ? SDL_FALSE : SDL_TRUE);
|
||||
return TRUE;
|
||||
case SDL_SCANCODE_D:
|
||||
freerdp_abort_connect_context(_sdl->context());
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
_sdl->update_fullscreen(!_sdl->fullscreen);
|
||||
return TRUE;
|
||||
}
|
||||
if (ev->keysym.scancode == valResizeable)
|
||||
{
|
||||
_sdl->update_resizeable(!_sdl->resizeable);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (ev->keysym.scancode == valGrab)
|
||||
{
|
||||
keyboard_grab(ev->windowID, _sdl->grab_kbd ? SDL_FALSE : SDL_TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
if (ev->keysym.scancode == valDisconnect)
|
||||
{
|
||||
freerdp_abort_connect_context(_sdl->context());
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <SDL.h>
|
||||
@ -45,6 +47,9 @@ class sdlInput
|
||||
static BOOL keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
|
||||
UINT32 imeConvMode);
|
||||
|
||||
static uint32_t prefToMask();
|
||||
static uint32_t prefKeyValue(const std::string& key, uint32_t fallback = SDL_SCANCODE_UNKNOWN);
|
||||
|
||||
private:
|
||||
SdlContext* _sdl;
|
||||
Uint32 _lastWindowID;
|
||||
|
@ -17,6 +17,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#elif __has_include(<experimental/filesystem>)
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
#error Could not find system header "<filesystem>" or "<experimental/filesystem>"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include "sdl_utils.hpp"
|
||||
|
||||
@ -24,6 +35,12 @@
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <winpr/path.h>
|
||||
#include <freerdp/version.h>
|
||||
#if defined(CJSON_FOUND)
|
||||
#include <cjson/cJSON.h>
|
||||
#endif
|
||||
|
||||
const char* sdl_event_type_str(Uint32 type)
|
||||
{
|
||||
#define STR(x) #x
|
||||
@ -286,3 +303,112 @@ bool sdl_push_quit()
|
||||
SDL_PushEvent(&ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CJSON_FOUND)
|
||||
using cJSONPtr = std::unique_ptr<cJSON, decltype(&cJSON_Delete)>;
|
||||
|
||||
static cJSONPtr get()
|
||||
{
|
||||
auto config = sdl_get_pref_file();
|
||||
|
||||
std::ifstream ifs(config);
|
||||
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
return { cJSON_ParseWithLength(content.c_str(), content.size()), cJSON_Delete };
|
||||
}
|
||||
|
||||
static cJSON* get_item(const std::string& key)
|
||||
{
|
||||
static cJSONPtr config{ nullptr, cJSON_Delete };
|
||||
if (!config)
|
||||
config = get();
|
||||
if (!config)
|
||||
return nullptr;
|
||||
return cJSON_GetObjectItem(config.get(), key.c_str());
|
||||
}
|
||||
|
||||
static std::string item_to_str(cJSON* item, const std::string& fallback = "")
|
||||
{
|
||||
if (!item || !cJSON_IsString(item))
|
||||
return fallback;
|
||||
auto str = cJSON_GetStringValue(item);
|
||||
if (!str)
|
||||
return {};
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string sdl_get_pref_string(const std::string& key, const std::string& fallback)
|
||||
{
|
||||
#if defined(CJSON_FOUND)
|
||||
auto item = get_item(key);
|
||||
return item_to_str(item, fallback);
|
||||
#else
|
||||
return fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool sdl_get_pref_bool(const std::string& key, bool fallback)
|
||||
{
|
||||
#if defined(CJSON_FOUND)
|
||||
auto item = get_item(key);
|
||||
if (!item || !cJSON_IsBool(item))
|
||||
return fallback;
|
||||
return cJSON_IsTrue(item);
|
||||
#else
|
||||
return fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t sdl_get_pref_int(const std::string& key, int64_t fallback)
|
||||
{
|
||||
#if defined(CJSON_FOUND)
|
||||
auto item = get_item(key);
|
||||
if (!item || !cJSON_IsNumber(item))
|
||||
return fallback;
|
||||
auto val = cJSON_GetNumberValue(item);
|
||||
return static_cast<int64_t>(val);
|
||||
#else
|
||||
return fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> sdl_get_pref_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback)
|
||||
{
|
||||
#if defined(CJSON_FOUND)
|
||||
auto item = get_item(key);
|
||||
if (!item || !cJSON_IsArray(item))
|
||||
return fallback;
|
||||
|
||||
std::vector<std::string> values;
|
||||
for (int x = 0; x < cJSON_GetArraySize(item); x++)
|
||||
{
|
||||
auto cur = cJSON_GetArrayItem(item, x);
|
||||
values.push_back(item_to_str(cur));
|
||||
}
|
||||
|
||||
return values;
|
||||
#else
|
||||
return fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string sdl_get_pref_dir()
|
||||
{
|
||||
using CStringPtr = std::unique_ptr<char, decltype(&free)>;
|
||||
CStringPtr path(GetKnownPath(KNOWN_PATH_XDG_CONFIG_HOME), free);
|
||||
if (!path)
|
||||
return {};
|
||||
|
||||
fs::path config{ path.get() };
|
||||
config /= FREERDP_VENDOR;
|
||||
config /= FREERDP_PRODUCT;
|
||||
return config.string();
|
||||
}
|
||||
|
||||
std::string sdl_get_pref_file()
|
||||
{
|
||||
fs::path config{ sdl_get_pref_dir() };
|
||||
config /= "sdl-freerdp.json";
|
||||
return config.string();
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CriticalSection
|
||||
{
|
||||
@ -98,3 +100,12 @@ const char* sdl_error_string(Uint32 res);
|
||||
#define sdl_log_error(res, log, what) sdl_log_error_ex(res, log, what, __FILE__, __LINE__, __func__)
|
||||
BOOL sdl_log_error_ex(Uint32 res, wLog* log, const char* what, const char* file, size_t line,
|
||||
const char* fkt);
|
||||
|
||||
std::string sdl_get_pref_dir();
|
||||
std::string sdl_get_pref_file();
|
||||
|
||||
std::string sdl_get_pref_string(const std::string& key, const std::string& fallback = "");
|
||||
int64_t sdl_get_pref_int(const std::string& key, int64_t fallback = 0);
|
||||
bool sdl_get_pref_bool(const std::string& key, bool fallback = false);
|
||||
std::vector<std::string> sdl_get_pref_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback = {});
|
||||
|
@ -2,48 +2,54 @@ include(GNUInstallDirs)
|
||||
include(FindDocBookXSL)
|
||||
|
||||
function(install_freerdp_man manpage section)
|
||||
if(WITH_MANPAGES)
|
||||
install(FILES ${manpage} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${section})
|
||||
endif()
|
||||
if(WITH_MANPAGES)
|
||||
install(FILES ${manpage} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${section})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(generate_and_install_freerdp_man_from_xml template manpage dependencies)
|
||||
if(WITH_MANPAGES)
|
||||
find_program(XSLTPROC_EXECUTABLE NAMES xsltproc REQUIRED)
|
||||
if (NOT DOCBOOKXSL_FOUND)
|
||||
message(FATAL_ERROR "docbook xsl not found but required for manpage generation")
|
||||
if(WITH_MANPAGES)
|
||||
find_program(XSLTPROC_EXECUTABLE NAMES xsltproc REQUIRED)
|
||||
if (NOT DOCBOOKXSL_FOUND)
|
||||
message(FATAL_ERROR "docbook xsl not found but required for manpage generation")
|
||||
endif()
|
||||
|
||||
# We need the variable ${MAN_TODAY} to contain the current date in ISO
|
||||
# format to replace it in the configure_file step.
|
||||
include(today)
|
||||
|
||||
TODAY(MAN_TODAY)
|
||||
|
||||
configure_file(${template}.xml.in ${manpage}.xml @ONLY IMMEDIATE)
|
||||
|
||||
foreach(DEP IN LISTS dependencies)
|
||||
set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/${DEP}.in)
|
||||
set(DST ${CMAKE_CURRENT_BINARY_DIR}/${DEP})
|
||||
|
||||
if (EXISTS ${SRC})
|
||||
message("generating ${DST} from ${SRC}")
|
||||
configure_file(${SRC} ${DST} @ONLY IMMEDIATE)
|
||||
else()
|
||||
message("using ${DST} from ${SRC}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${manpage}
|
||||
COMMAND ${CMAKE_BINARY_DIR}/client/common/man/generate_argument_docbook
|
||||
COMMAND ${XSLTPROC_EXECUTABLE} --path "${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}" ${DOCBOOKXSL_DIR}/manpages/docbook.xsl ${manpage}.xml
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${manpage}.xml
|
||||
generate_argument_docbook
|
||||
${template}.xml.in
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
${manpage}.manpage ALL
|
||||
DEPENDS
|
||||
${manpage}
|
||||
)
|
||||
install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${manpage} 1)
|
||||
endif()
|
||||
|
||||
# We need the variable ${MAN_TODAY} to contain the current date in ISO
|
||||
# format to replace it in the configure_file step.
|
||||
include(today)
|
||||
|
||||
TODAY(MAN_TODAY)
|
||||
|
||||
configure_file(${template}.xml.in ${manpage}.xml @ONLY IMMEDIATE)
|
||||
|
||||
set(dep_SRC)
|
||||
foreach(dep ${dependencies})
|
||||
set(cur_SRC ${CMAKE_CURRENT_SOURCE_DIR}/${dep})
|
||||
list(APPEND dep_SRC ${cur_SRC})
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${manpage}
|
||||
COMMAND ${CMAKE_BINARY_DIR}/client/common/man/generate_argument_docbook
|
||||
COMMAND ${XSLTPROC_EXECUTABLE} --path ${CMAKE_CURRENT_SOURCE_DIR} ${DOCBOOKXSL_DIR}/manpages/docbook.xsl ${manpage}.xml
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${manpage}.xml
|
||||
generate_argument_docbook
|
||||
${template}.xml.in
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
${manpage}.manpage ALL
|
||||
DEPENDS
|
||||
${manpage}
|
||||
)
|
||||
install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${manpage} 1)
|
||||
endif()
|
||||
endfunction()
|
||||
|
@ -29,5 +29,7 @@
|
||||
#define FREERDP_VERSION_FULL "${FREERDP_VERSION_FULL}"
|
||||
#define FREERDP_GIT_REVISION "${GIT_REVISION}"
|
||||
#define FREERDP_USER_AGENT "FreeRDP/${FREERDP_VERSION_FULL}"
|
||||
#define FREERDP_VENDOR "${VENDOR}"
|
||||
#define FREERDP_PRODUCT "${PRODUCT}"
|
||||
|
||||
#endif /* FREERDP_VERSION_H */
|
||||
|
Loading…
Reference in New Issue
Block a user