Synergy 1267 endless notifications during connection (#7104)
* SYNERGY-1267 Endless notification during connection * SYNERGY-1267 Endless notification. Server part * SYNERGY-1267 Change notification trace level * Update ChangeLog * SYNERGY-1267 Fix Linux compilation * SYNERGY-1267 Fix code smell * SYNERGY-1267 Add requested changes
This commit is contained in:
parent
4ddb6173e7
commit
65ec504696
18 changed files with 285 additions and 138 deletions
|
|
@ -2,7 +2,7 @@ v1.14.2-snapshot
|
||||||
===========
|
===========
|
||||||
Bug fixes:
|
Bug fixes:
|
||||||
- #7070 Fix radio button shifted focus on macOS
|
- #7070 Fix radio button shifted focus on macOS
|
||||||
- #7038 Fix client and server different keyboard layout errors
|
- #7038 | #7104 Fix client and server different keyboard layout errors
|
||||||
- #7078 Fix clipboard re-enables automatically
|
- #7078 Fix clipboard re-enables automatically
|
||||||
- #7077 Fix Ubuntu, CentOS and Debian build after SYNERGY-1161
|
- #7077 Fix Ubuntu, CentOS and Debian build after SYNERGY-1161
|
||||||
- #7080 Add trace if the system can't open file with trusted fingerprints
|
- #7080 Add trace if the system can't open file with trusted fingerprints
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,7 @@ Client::handshakeComplete()
|
||||||
{
|
{
|
||||||
m_ready = true;
|
m_ready = true;
|
||||||
m_screen->enable();
|
m_screen->enable();
|
||||||
|
checkMissedLanguages();
|
||||||
sendEvent(m_events->forClient().connected(), NULL);
|
sendEvent(m_events->forClient().connected(), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -723,13 +724,14 @@ void
|
||||||
Client::handleHello(const Event&, void*)
|
Client::handleHello(const Event&, void*)
|
||||||
{
|
{
|
||||||
SInt16 major, minor;
|
SInt16 major, minor;
|
||||||
String keyboardLayoutList("<unknown>");
|
String remoteLanguages;
|
||||||
if (!ProtocolUtil::readf(m_stream, kMsgHello, &major, &minor, &keyboardLayoutList)) {
|
if (!ProtocolUtil::readf(m_stream, kMsgHello, &major, &minor, &remoteLanguages)) {
|
||||||
sendConnectionFailedEvent("Protocol error from server, check encryption settings");
|
sendConnectionFailedEvent("Protocol error from server, check encryption settings");
|
||||||
cleanupTimer();
|
cleanupTimer();
|
||||||
cleanupConnection();
|
cleanupConnection();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_languageManager.setRemoteLanguages(remoteLanguages);
|
||||||
|
|
||||||
// check versions
|
// check versions
|
||||||
LOG((CLOG_DEBUG1 "got hello version %d.%d", major, minor));
|
LOG((CLOG_DEBUG1 "got hello version %d.%d", major, minor));
|
||||||
|
|
@ -749,37 +751,11 @@ Client::handleHello(const Event&, void*)
|
||||||
}
|
}
|
||||||
|
|
||||||
// say hello back
|
// say hello back
|
||||||
LOG((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion));
|
|
||||||
String allKeyboardLayoutsStr;
|
|
||||||
for (const auto& layout : AppUtil::instance().getKeyboardLayoutList()) {
|
|
||||||
allKeyboardLayoutsStr += layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "say hello version %d.%d", helloBackMajor, helloBackMinor));
|
LOG((CLOG_DEBUG1 "say hello version %d.%d", helloBackMajor, helloBackMinor));
|
||||||
|
auto localLanguages = m_languageManager.getSerializedLocalLanguages();
|
||||||
ProtocolUtil::writef(m_stream, kMsgHelloBack,
|
ProtocolUtil::writef(m_stream, kMsgHelloBack,
|
||||||
helloBackMajor,
|
helloBackMajor,
|
||||||
helloBackMinor, & m_name, &allKeyboardLayoutsStr);
|
helloBackMinor, & m_name, &localLanguages);
|
||||||
|
|
||||||
if(m_args.m_enableLangSync) {
|
|
||||||
std::vector<String> missed;
|
|
||||||
std::vector<String> supported;
|
|
||||||
AppUtil::getKeyboardLayoutsDiff(keyboardLayoutList,
|
|
||||||
AppUtil::instance().getKeyboardLayoutList(),
|
|
||||||
missed, supported);
|
|
||||||
|
|
||||||
if(!supported.empty()) {
|
|
||||||
LOG((CLOG_DEBUG "Supported server languages: %s", AppUtil::joinStrVector(supported, ", ").c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!missed.empty()) {
|
|
||||||
auto result = AppUtil::joinStrVector(missed, ", ");
|
|
||||||
AppUtil::instance().showNotification("Language synchronization error",
|
|
||||||
"These languages are required for client proper work: " + result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOG((CLOG_DEBUG "Language sync logic is disabled."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// now connected but waiting to complete handshake
|
// now connected but waiting to complete handshake
|
||||||
setupScreen();
|
setupScreen();
|
||||||
|
|
@ -841,6 +817,21 @@ Client::onFileRecieveCompleted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Client::checkMissedLanguages() const
|
||||||
|
{
|
||||||
|
if (m_args.m_enableLangSync) {
|
||||||
|
auto missedLanguages = m_languageManager.getMissedLanguages();
|
||||||
|
if (!missedLanguages.empty()) {
|
||||||
|
AppUtil::instance().showNotification("Language synchronization error",
|
||||||
|
"These languages are required for the client to work: " + missedLanguages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG((CLOG_DEBUG "Language sync logic is disabled."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Client::handleStopRetry(const Event&, void*)
|
Client::handleStopRetry(const Event&, void*)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "synergy/DragInformation.h"
|
#include "synergy/DragInformation.h"
|
||||||
#include "synergy/INode.h"
|
#include "synergy/INode.h"
|
||||||
#include "synergy/ClientArgs.h"
|
#include "synergy/ClientArgs.h"
|
||||||
|
#include "synergy/languages/LanguageManager.h"
|
||||||
#include "net/NetworkAddress.h"
|
#include "net/NetworkAddress.h"
|
||||||
#include "base/EventTypes.h"
|
#include "base/EventTypes.h"
|
||||||
#include "mt/CondVar.h"
|
#include "mt/CondVar.h"
|
||||||
|
|
@ -208,6 +209,7 @@ private:
|
||||||
void handleStopRetry(const Event&, void*);
|
void handleStopRetry(const Event&, void*);
|
||||||
void onFileRecieveCompleted();
|
void onFileRecieveCompleted();
|
||||||
void sendClipboardThread(void*);
|
void sendClipboardThread(void*);
|
||||||
|
void checkMissedLanguages() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
|
@ -241,4 +243,5 @@ private:
|
||||||
size_t m_maximumClipboardSize;
|
size_t m_maximumClipboardSize;
|
||||||
lib::synergy::ClientArgs m_args;
|
lib::synergy::ClientArgs m_args;
|
||||||
size_t m_resolvedAddressesCount = 0;
|
size_t m_resolvedAddressesCount = 0;
|
||||||
|
synergy::languages::LanguageManager m_languageManager;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -60,14 +60,11 @@ ClientProxyUnknown::ClientProxyUnknown(synergy::IStream* stream, double timeout,
|
||||||
addStreamHandlers();
|
addStreamHandlers();
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "saying hello"));
|
LOG((CLOG_DEBUG1 "saying hello"));
|
||||||
String allKeyboardLayoutsStr;
|
auto localLanguages = m_languageManager.getSerializedLocalLanguages();
|
||||||
for (const auto& layout : AppUtil::instance().getKeyboardLayoutList()) {
|
|
||||||
allKeyboardLayoutsStr += layout;
|
|
||||||
}
|
|
||||||
ProtocolUtil::writef(m_stream, kMsgHello,
|
ProtocolUtil::writef(m_stream, kMsgHello,
|
||||||
kProtocolMajorVersion,
|
kProtocolMajorVersion,
|
||||||
kProtocolMinorVersion,
|
kProtocolMinorVersion,
|
||||||
&allKeyboardLayoutsStr);
|
&localLanguages);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientProxyUnknown::~ClientProxyUnknown()
|
ClientProxyUnknown::~ClientProxyUnknown()
|
||||||
|
|
@ -186,7 +183,7 @@ ClientProxyUnknown::handleData(const Event&, void*)
|
||||||
LOG((CLOG_DEBUG1 "parsing hello reply"));
|
LOG((CLOG_DEBUG1 "parsing hello reply"));
|
||||||
|
|
||||||
String name("<unknown>");
|
String name("<unknown>");
|
||||||
String keyboardLayoutList("<unknown>");
|
|
||||||
try {
|
try {
|
||||||
// limit the maximum length of the hello
|
// limit the maximum length of the hello
|
||||||
UInt32 n = m_stream->getSize();
|
UInt32 n = m_stream->getSize();
|
||||||
|
|
@ -197,10 +194,13 @@ ClientProxyUnknown::handleData(const Event&, void*)
|
||||||
|
|
||||||
// parse the reply to hello
|
// parse the reply to hello
|
||||||
SInt16 major, minor;
|
SInt16 major, minor;
|
||||||
|
String remoteLanguages;
|
||||||
if (!ProtocolUtil::readf(m_stream, kMsgHelloBack,
|
if (!ProtocolUtil::readf(m_stream, kMsgHelloBack,
|
||||||
&major, &minor, &name, &keyboardLayoutList)) {
|
&major, &minor, &name, &remoteLanguages)) {
|
||||||
throw XBadClient();
|
throw XBadClient();
|
||||||
}
|
}
|
||||||
|
m_languageManager.setRemoteLanguages(remoteLanguages);
|
||||||
|
m_server->setLanguageManager(m_languageManager);
|
||||||
|
|
||||||
// disallow invalid version numbers
|
// disallow invalid version numbers
|
||||||
if (major <= 0 || minor < 0) {
|
if (major <= 0 || minor < 0) {
|
||||||
|
|
@ -254,22 +254,6 @@ ClientProxyUnknown::handleData(const Event&, void*)
|
||||||
throw XIncompatibleClient(major, minor);
|
throw XIncompatibleClient(major, minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<String> missed;
|
|
||||||
std::vector<String> supported;
|
|
||||||
AppUtil::getKeyboardLayoutsDiff(keyboardLayoutList,
|
|
||||||
AppUtil::instance().getKeyboardLayoutList(),
|
|
||||||
missed, supported);
|
|
||||||
|
|
||||||
if(!supported.empty()) {
|
|
||||||
LOG((CLOG_DEBUG "Supported client languages: %s", AppUtil::joinStrVector(supported, ", ").c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!missed.empty()) {
|
|
||||||
auto result = AppUtil::joinStrVector(missed, ", ");
|
|
||||||
AppUtil::instance().showNotification("Language synchronization error",
|
|
||||||
"These languages are required for server proper work: " + result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the proxy is created and now proxy now owns the stream
|
// the proxy is created and now proxy now owns the stream
|
||||||
LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor));
|
LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor));
|
||||||
m_stream = NULL;
|
m_stream = NULL;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "base/Event.h"
|
#include "base/Event.h"
|
||||||
#include "base/EventTypes.h"
|
#include "base/EventTypes.h"
|
||||||
|
#include "synergy/languages/LanguageManager.h"
|
||||||
|
|
||||||
class ClientProxy;
|
class ClientProxy;
|
||||||
class EventQueueTimer;
|
class EventQueueTimer;
|
||||||
|
|
@ -73,4 +74,5 @@ private:
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
Server* m_server;
|
Server* m_server;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
synergy::languages::LanguageManager m_languageManager;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,8 @@ Server::adoptClient(BaseClientProxy* client)
|
||||||
client->screensaver(true);
|
client->screensaver(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkMissedLanguages();
|
||||||
|
|
||||||
// send notification
|
// send notification
|
||||||
Server::ScreenConnectedInfo* info =
|
Server::ScreenConnectedInfo* info =
|
||||||
new Server::ScreenConnectedInfo(getName(client));
|
new Server::ScreenConnectedInfo(getName(client));
|
||||||
|
|
@ -1931,6 +1933,16 @@ Server::sendDragInfo(BaseClientProxy* newScreen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Server::checkMissedLanguages() const
|
||||||
|
{
|
||||||
|
auto missedLanguages = m_languageManager.getMissedLanguages();
|
||||||
|
if (!missedLanguages.empty()) {
|
||||||
|
AppUtil::instance().showNotification("Language synchronization error",
|
||||||
|
"These languages are required for the server to work: " + missedLanguages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Server::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
Server::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include "synergy/INode.h"
|
#include "synergy/INode.h"
|
||||||
#include "synergy/DragInformation.h"
|
#include "synergy/DragInformation.h"
|
||||||
#include "synergy/ServerArgs.h"
|
#include "synergy/ServerArgs.h"
|
||||||
|
#include "synergy/languages/LanguageManager.h"
|
||||||
#include "base/Event.h"
|
#include "base/Event.h"
|
||||||
#include "base/Stopwatch.h"
|
#include "base/Stopwatch.h"
|
||||||
#include "base/EventTypes.h"
|
#include "base/EventTypes.h"
|
||||||
|
|
@ -155,7 +156,10 @@ public:
|
||||||
|
|
||||||
//! Store ClientListener pointer
|
//! Store ClientListener pointer
|
||||||
void setListener(ClientListener* p) { m_clientListener = p; }
|
void setListener(ClientListener* p) { m_clientListener = p; }
|
||||||
|
|
||||||
|
//! Set language manager
|
||||||
|
void setLanguageManager(const synergy::languages::LanguageManager& manager) { m_languageManager = manager; }
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
@ -373,6 +377,9 @@ private:
|
||||||
// send drag info to new client screen
|
// send drag info to new client screen
|
||||||
void sendDragInfo(BaseClientProxy* newScreen);
|
void sendDragInfo(BaseClientProxy* newScreen);
|
||||||
|
|
||||||
|
//Shows notification if there are missed languages
|
||||||
|
void checkMissedLanguages() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
|
||||||
|
|
@ -487,4 +494,5 @@ private:
|
||||||
|
|
||||||
ClientListener* m_clientListener;
|
ClientListener* m_clientListener;
|
||||||
lib::synergy::ServerArgs m_args;
|
lib::synergy::ServerArgs m_args;
|
||||||
|
synergy::languages::LanguageManager m_languageManager;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -52,22 +52,3 @@ AppUtil::instance()
|
||||||
assert(s_instance != nullptr);
|
assert(s_instance != nullptr);
|
||||||
return *s_instance;
|
return *s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AppUtil::getKeyboardLayoutsDiff(const String& remoteCompressedLanguages,
|
|
||||||
const std::vector<String>& localLanguages,
|
|
||||||
std::vector<String>& missedLang,
|
|
||||||
std::vector<String>& supportedLang)
|
|
||||||
{
|
|
||||||
missedLang.clear();
|
|
||||||
supportedLang.clear();
|
|
||||||
for(int i = 0; i <= (int)remoteCompressedLanguages.size() - 2; i +=2) {
|
|
||||||
auto layout = remoteCompressedLanguages.substr(i, 2);
|
|
||||||
if (std::find(localLanguages.begin(), localLanguages.end(), layout) == localLanguages.end()) {
|
|
||||||
missedLang.push_back(layout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
supportedLang.push_back(layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,7 @@ public:
|
||||||
static AppUtil& instance();
|
static AppUtil& instance();
|
||||||
static void exitAppStatic(int code) { instance().exitApp(code); }
|
static void exitAppStatic(int code) { instance().exitApp(code); }
|
||||||
virtual void beforeAppExit() {}
|
virtual void beforeAppExit() {}
|
||||||
static void getKeyboardLayoutsDiff(const String& remoteCompressedLanguages,
|
|
||||||
const std::vector<String>& localLanguages,
|
|
||||||
std::vector<String>& missedLang,
|
|
||||||
std::vector<String>& supportedLang);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IApp* m_app;
|
IApp* m_app;
|
||||||
static AppUtil* s_instance;
|
static AppUtil* s_instance;
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
file(GLOB headers "*.h")
|
file(GLOB headers "*.h" "languages/*.h")
|
||||||
file(GLOB sources "*.cpp")
|
file(GLOB sources "*.cpp" "languages/*.cpp")
|
||||||
|
|
||||||
# arch
|
# arch
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
||||||
|
|
@ -32,18 +32,4 @@ public:
|
||||||
virtual std::vector<String> getKeyboardLayoutList() = 0;
|
virtual std::vector<String> getKeyboardLayoutList() = 0;
|
||||||
virtual String getCurrentLanguageCode() = 0;
|
virtual String getCurrentLanguageCode() = 0;
|
||||||
virtual void showNotification(const String& title, const String& text) const = 0;
|
virtual void showNotification(const String& title, const String& text) const = 0;
|
||||||
|
|
||||||
static String joinStrVector(const std::vector<String>& source, const String& delim)
|
|
||||||
{
|
|
||||||
String result;
|
|
||||||
for(size_t i = 0; i < source.size(); i++)
|
|
||||||
{
|
|
||||||
result += source[i];
|
|
||||||
|
|
||||||
if(i < source.size() - 1) {
|
|
||||||
result += delim;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::move(result);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
94
src/lib/synergy/languages/LanguageManager.cpp
Normal file
94
src/lib/synergy/languages/LanguageManager.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2014-2021 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include "LanguageManager.h"
|
||||||
|
#include "base/Log.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
String vectorToString(const std::vector<String>& vector, const String& delimiter = "")
|
||||||
|
{
|
||||||
|
String string;
|
||||||
|
for (const auto& item : vector) {
|
||||||
|
if (&item != &vector[0]) {
|
||||||
|
string += delimiter;
|
||||||
|
}
|
||||||
|
string += item;
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //anonymous namespace
|
||||||
|
|
||||||
|
namespace synergy {
|
||||||
|
|
||||||
|
namespace languages {
|
||||||
|
|
||||||
|
LanguageManager::LanguageManager(const std::vector<String>& localLanguages) :
|
||||||
|
m_localLanguages(localLanguages)
|
||||||
|
{
|
||||||
|
LOG((CLOG_INFO "Local languages: %s", vectorToString(m_localLanguages, ", ").c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageManager::setRemoteLanguages(const String& remoteLanguages)
|
||||||
|
{
|
||||||
|
m_remoteLanguages.clear();
|
||||||
|
if (!remoteLanguages.empty()) {
|
||||||
|
for (size_t i = 0; i <= remoteLanguages.size() - 2; i +=2) {
|
||||||
|
m_remoteLanguages.push_back(remoteLanguages.substr(i, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG((CLOG_INFO "Remote languages: %s", vectorToString(m_remoteLanguages, ", ").c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<String>& LanguageManager::getRemoteLanguages() const
|
||||||
|
{
|
||||||
|
return m_remoteLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<String>& LanguageManager::getLocalLanguages() const
|
||||||
|
{
|
||||||
|
return m_localLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
|
String LanguageManager::getMissedLanguages() const
|
||||||
|
{
|
||||||
|
String missedLanguages;
|
||||||
|
|
||||||
|
for (const auto& language : m_remoteLanguages) {
|
||||||
|
if (std::find(m_localLanguages.begin(), m_localLanguages.end(), language) == m_localLanguages.end()) {
|
||||||
|
if (!missedLanguages.empty()) {
|
||||||
|
missedLanguages += ", ";
|
||||||
|
}
|
||||||
|
missedLanguages += language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return missedLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
|
String LanguageManager::getSerializedLocalLanguages() const
|
||||||
|
{
|
||||||
|
return vectorToString(m_localLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace languages
|
||||||
|
|
||||||
|
} //namespace synergy
|
||||||
|
|
||||||
|
|
||||||
71
src/lib/synergy/languages/LanguageManager.h
Normal file
71
src/lib/synergy/languages/LanguageManager.h
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2014-2021 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef SYNERGY_LANGUAGESLANGUAGEMANAGER_H
|
||||||
|
#define SYNERGY_LANGUAGESLANGUAGEMANAGER_H
|
||||||
|
|
||||||
|
#include "synergy/AppUtil.h"
|
||||||
|
#include "base/String.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace synergy {
|
||||||
|
|
||||||
|
namespace languages {
|
||||||
|
|
||||||
|
class LanguageManager
|
||||||
|
{
|
||||||
|
std::vector<String> m_remoteLanguages;
|
||||||
|
std::vector<String> m_localLanguages;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LanguageManager(const std::vector<String>& localLanguages = AppUtil::instance().getKeyboardLayoutList());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setRemoteLanguages sets remote languages
|
||||||
|
* @param remoteLanguages is a string with sericalized languages
|
||||||
|
*/
|
||||||
|
void setRemoteLanguages(const String& remoteLanguages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getRemoteLanguages getter for remote languages
|
||||||
|
* @return vector of remote languages
|
||||||
|
*/
|
||||||
|
const std::vector<String>& getRemoteLanguages() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getLocalLanguages getter for local languages
|
||||||
|
* @return vector of local languages
|
||||||
|
*/
|
||||||
|
const std::vector<String>& getLocalLanguages() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getMissedLanguages getter for missed languages on local machine
|
||||||
|
* @return difference between remote and local languages as a coma separated string
|
||||||
|
*/
|
||||||
|
String getMissedLanguages() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getSerializedLocalLanguages getter for local serialized languages
|
||||||
|
* @return serialized local languages as a string
|
||||||
|
*/
|
||||||
|
String getSerializedLocalLanguages() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace languages
|
||||||
|
|
||||||
|
} //namespace synergy
|
||||||
|
|
||||||
|
#endif // SYNERGY_LANGUAGESLANGUAGEMANAGER_H
|
||||||
|
|
@ -172,8 +172,8 @@ AppUtilUnix::getCurrentLanguageCode()
|
||||||
void
|
void
|
||||||
AppUtilUnix::showNotification(const String & title, const String & text) const
|
AppUtilUnix::showNotification(const String & title, const String & text) const
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str()));
|
|
||||||
#if WINAPI_XWINDOWS
|
#if WINAPI_XWINDOWS
|
||||||
|
LOG((CLOG_INFO "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str()));
|
||||||
if (!notify_init("Synergy"))
|
if (!notify_init("Synergy"))
|
||||||
{
|
{
|
||||||
LOG((CLOG_INFO "Failed to initialize libnotify"));
|
LOG((CLOG_INFO "Failed to initialize libnotify"));
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ public:
|
||||||
void
|
void
|
||||||
AppUtilWindows::showNotification(const String & title, const String & text) const
|
AppUtilWindows::showNotification(const String & title, const String & text) const
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str()));
|
LOG((CLOG_INFO "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str()));
|
||||||
if (!WinToastLib::WinToast::isCompatible()) {
|
if (!WinToastLib::WinToast::isCompatible()) {
|
||||||
LOG((CLOG_INFO "This system does not support toast notifications"));
|
LOG((CLOG_INFO "This system does not support toast notifications"));
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
file(GLOB_RECURSE headers "*.h")
|
file(GLOB_RECURSE headers "*.h" "languages/*.h")
|
||||||
file(GLOB_RECURSE sources "*.cpp")
|
file(GLOB_RECURSE sources "*.cpp" "languages/*.cpp")
|
||||||
|
|
||||||
file(GLOB_RECURSE remove_platform "platform/*")
|
file(GLOB_RECURSE remove_platform "platform/*")
|
||||||
list(REMOVE_ITEM headers ${remove_platform})
|
list(REMOVE_ITEM headers ${remove_platform})
|
||||||
|
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2014-2016 Symless Ltd.
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file LICENSE that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "test/global/gtest.h"
|
|
||||||
#include "synergy/AppUtil.h"
|
|
||||||
|
|
||||||
TEST(AppUtilTests, keyboardLayoutTest)
|
|
||||||
{
|
|
||||||
String layoutList1 = "ruenby";
|
|
||||||
std::vector<String> layoutList2 = { "ru", "en" };
|
|
||||||
std::vector<String> missed;
|
|
||||||
std::vector<String> supported;
|
|
||||||
AppUtil::getKeyboardLayoutsDiff(layoutList1, layoutList2, missed, supported);
|
|
||||||
|
|
||||||
EXPECT_EQ(missed, std::vector<String>{ "by" });
|
|
||||||
EXPECT_EQ(supported, layoutList2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AppUtilTests, joinVectorTest)
|
|
||||||
{
|
|
||||||
std::vector<String> layouts = { "ru", "en" };
|
|
||||||
auto result = AppUtil::joinStrVector(layouts, ", ");
|
|
||||||
|
|
||||||
EXPECT_EQ(result, "ru, en");
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2014-2021 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "synergy/languages/LanguageManager.h"
|
||||||
|
#include "test/global/gtest.h"
|
||||||
|
|
||||||
|
|
||||||
|
TEST(LanguageManager, RemoteLanguagesTest)
|
||||||
|
{
|
||||||
|
std::string remoteLanguages = "ruenuk";
|
||||||
|
synergy::languages::LanguageManager manager({"ru", "en", "uk"});
|
||||||
|
|
||||||
|
manager.setRemoteLanguages(remoteLanguages);
|
||||||
|
EXPECT_EQ((std::vector<std::string> {"ru", "en", "uk"}), manager.getRemoteLanguages());
|
||||||
|
|
||||||
|
manager.setRemoteLanguages(String());
|
||||||
|
EXPECT_TRUE(manager.getRemoteLanguages().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LanguageManager, LocalLanguagesTest)
|
||||||
|
{
|
||||||
|
std::vector<String> localLanguages = {"ru", "en", "uk"};
|
||||||
|
synergy::languages::LanguageManager manager(localLanguages);
|
||||||
|
|
||||||
|
EXPECT_EQ((std::vector<std::string> {"ru", "en", "uk"}), manager.getLocalLanguages());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LanguageManager, MissedLanguagesTest)
|
||||||
|
{
|
||||||
|
String remoteLanguages = "ruenuk";
|
||||||
|
std::vector<String> localLanguages = {"en"};
|
||||||
|
synergy::languages::LanguageManager manager(localLanguages);
|
||||||
|
|
||||||
|
manager.setRemoteLanguages(remoteLanguages);
|
||||||
|
EXPECT_EQ("ru, uk", manager.getMissedLanguages());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LanguageManager, SerializeLocalLanguagesTest)
|
||||||
|
{
|
||||||
|
std::vector<String> localLanguages = {"ru", "en", "uk"};
|
||||||
|
synergy::languages::LanguageManager manager(localLanguages);
|
||||||
|
|
||||||
|
EXPECT_EQ("ruenuk", manager.getSerializedLocalLanguages());
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue