diff --git a/CMakeLists.txt b/CMakeLists.txt
index d259a6a2..09f346da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,11 +74,6 @@ endif()
# Depending on the platform, pass in the required defines.
if (UNIX)
-
- # warnings as errors:
- # we have a problem with people checking in code with warnings.
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-unused-local-typedef")
-
if (NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif()
diff --git a/ChangeLog b/ChangeLog
index ebb695d4..3a8df367 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+v1.8.8-rc1
+==========
+Bug #5196 - Some keys on Korean and Japanese keyboards have the same keycode
+Bug #5578 - Pressing Hangul key results in alt+'a'
+Bug #5785 - Can't switch screens when cursor is in a corner
+Bug #3992 - macOS: Dragging is broken in Unity 3D
+Bug #5075 - macOS: Build fails on macOS 10.9 due to unknown compiler flag
+Bug #5809 - macOS: No version number is shown in the App Info dialog
+Bug #3197 - Linux: switchDoubleTap option is not working
+Bug #4477 - Linux: Mouse buttons higher than id 10 result in crash
+Bug #5832 - Linux: Screen size misdetected on multi-monitor display
+Enhancement #4504 - Improved Korean language description
+Enhancement #5525 - Added support for precise screen positioning in config file
+Enhancement #4290 - Windows: Removed annoying alt+print screen functionality
+
v1.8.7-stable
=============
Bug #5784 - Edition changes when reopening GUI
diff --git a/src/gui/res/lang/Languages.xml b/src/gui/res/lang/Languages.xml
index 0a7f3d98..5948f9c6 100644
--- a/src/gui/res/lang/Languages.xml
+++ b/src/gui/res/lang/Languages.xml
@@ -36,11 +36,11 @@
-
+
-
+
diff --git a/src/gui/res/mac/Info.plist b/src/gui/res/mac/Info.plist
index 5cd23eaf..b2d87e09 100644
--- a/src/gui/res/mac/Info.plist
+++ b/src/gui/res/mac/Info.plist
@@ -1,20 +1,28 @@
-
-
+
-
- CFBundleInfoDictionaryVersion
- 6.0
- NSPrincipalClass
- NSApplication
- CFBundleIconFile
- Synergy.icns
- CFBundlePackageType
- APPL
- CFBundleSignature
- ????
- CFBundleExecutable
- Synergy
- CFBundleIdentifier
- synergy
-
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleDisplayName
+ Synergy
+ CFBundleExecutable
+ Synergy
+ CFBundleIconFile
+ Synergy.icns
+ CFBundleIdentifier
+ synergy
+
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ Synergy
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.8.8
+ CFBundleVersion
+ 1.8.8
+ NSHumanReadableCopyright
+ © 2012-2016, Symless Ltd
+
diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp
index f7be9fbf..cf4d0c1e 100644
--- a/src/gui/src/main.cpp
+++ b/src/gui/src/main.cpp
@@ -119,8 +119,8 @@ int waitForTray()
if (++trayAttempts > TRAY_RETRY_COUNT)
{
QMessageBox::critical(NULL, "Synergy",
- QObject::tr("System tray is unavailable, quitting."));
- return false;
+ QObject::tr("System tray is unavailable, don't close your window."));
+ return true;
}
QThreadImpl::msleep(TRAY_RETRY_WAIT);
diff --git a/src/lib/platform/MSWindowsKeyState.cpp b/src/lib/platform/MSWindowsKeyState.cpp
index 9c4e729a..4e093bd3 100644
--- a/src/lib/platform/MSWindowsKeyState.cpp
+++ b/src/lib/platform/MSWindowsKeyState.cpp
@@ -61,11 +61,11 @@ const KeyID MSWindowsKeyState::s_virtualKey[] =
/* 0x012 */ { kKeyAlt_L }, // VK_MENU
/* 0x013 */ { kKeyPause }, // VK_PAUSE
/* 0x014 */ { kKeyCapsLock }, // VK_CAPITAL
- /* 0x015 */ { kKeyHangulKana }, // VK_HANGUL, VK_KANA
+ /* 0x015 */ { kKeyKana }, // VK_HANGUL, VK_KANA
/* 0x016 */ { kKeyNone }, // undefined
/* 0x017 */ { kKeyNone }, // VK_JUNJA
/* 0x018 */ { kKeyNone }, // VK_FINAL
- /* 0x019 */ { kKeyHanjaKanzi }, // VK_KANJI
+ /* 0x019 */ { kKeyKanzi }, // VK_HANJA, VK_KANJI
/* 0x01a */ { kKeyNone }, // undefined
/* 0x01b */ { kKeyEscape }, // VK_ESCAPE
/* 0x01c */ { kKeyHenkan }, // VK_CONVERT
@@ -318,11 +318,11 @@ const KeyID MSWindowsKeyState::s_virtualKey[] =
/* 0x112 */ { kKeyAlt_R }, // VK_MENU
/* 0x113 */ { kKeyNone }, // VK_PAUSE
/* 0x114 */ { kKeyNone }, // VK_CAPITAL
- /* 0x115 */ { kKeyNone }, // VK_KANA
- /* 0x116 */ { kKeyNone }, // VK_HANGUL
+ /* 0x115 */ { kKeyHangul }, // VK_HANGUL
+ /* 0x116 */ { kKeyNone }, // undefined
/* 0x117 */ { kKeyNone }, // VK_JUNJA
/* 0x118 */ { kKeyNone }, // VK_FINAL
- /* 0x119 */ { kKeyNone }, // VK_KANJI
+ /* 0x119 */ { kKeyHanja }, // VK_HANJA
/* 0x11a */ { kKeyNone }, // undefined
/* 0x11b */ { kKeyNone }, // VK_ESCAPE
/* 0x11c */ { kKeyNone }, // VK_CONVERT
@@ -728,6 +728,10 @@ MSWindowsKeyState::mapKeyFromEvent(WPARAM charAndVirtKey,
// that so we clear it.
active &= ~s_controlAlt;
}
+ if (id == kKeyHangul) {
+ // If shift-space is used to change input mode, clear shift modifier.
+ active &= ~KeyModifierShift;
+ }
*maskOut = active;
}
@@ -1071,13 +1075,8 @@ MSWindowsKeyState::getKeyMap(synergy::KeyMap& keyMap)
}
}
- // add alt+printscreen
- if (m_buttonToVK[0x54u] == 0) {
- m_buttonToVK[0x54u] = VK_SNAPSHOT;
- }
-
// set virtual key to button table
- if (GetKeyboardLayout(0) == m_groups[g]) {
+ if (activeLayout == m_groups[g]) {
for (KeyButton i = 0; i < 512; ++i) {
if (m_buttonToVK[i] != 0) {
if (m_virtualKeyToButton[m_buttonToVK[i]] == 0) {
@@ -1339,8 +1338,20 @@ MSWindowsKeyState::setWindowGroup(SInt32 group)
}
KeyID
-MSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button)
+MSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button) const
{
+ // Some virtual keycodes have same values.
+ // VK_HANGUL == VK_KANA, VK_HANJA == NK_KANJI
+ // which are used to change the input mode of IME.
+ // But they have different X11 keysym. So we should distinguish them.
+ if ((LOWORD(m_keyLayout) & 0xffffu) == 0x0412u) { // 0x0412 : Korean Locale ID
+ if (virtualKey == VK_HANGUL || virtualKey == VK_HANJA) {
+ // If shift-space is used to change the input mode,
+ // the extented bit is not set. So add it to get right key id.
+ button |= 0x100u;
+ }
+ }
+
if ((button & 0x100u) != 0) {
virtualKey += 0x100u;
}
@@ -1392,3 +1403,4 @@ MSWindowsKeyState::addKeyEntry(synergy::KeyMap& keyMap, synergy::KeyMap::KeyItem
m_keyToVKMap[item.m_id] = static_cast(item.m_client);
}
}
+
diff --git a/src/lib/platform/MSWindowsKeyState.h b/src/lib/platform/MSWindowsKeyState.h
index 4313f741..fcbd5d98 100644
--- a/src/lib/platform/MSWindowsKeyState.h
+++ b/src/lib/platform/MSWindowsKeyState.h
@@ -122,7 +122,7 @@ public:
(button should include the extended key bit), or kKeyNone if there is
no such key.
*/
- static KeyID getKeyID(UINT virtualKey, KeyButton button);
+ KeyID getKeyID(UINT virtualKey, KeyButton button) const;
//! Map button to virtual key
/*!
diff --git a/src/lib/platform/OSXScreen.mm b/src/lib/platform/OSXScreen.mm
index cee57b4e..2a6f7b8c 100644
--- a/src/lib/platform/OSXScreen.mm
+++ b/src/lib/platform/OSXScreen.mm
@@ -483,7 +483,23 @@ OSXScreen::postMouseEvent(CGPoint& pos) const
// Fix for sticky keys
CGEventFlags modifiers = m_keyState->getModifierStateAsOSXFlags();
CGEventSetFlags(event, modifiers);
-
+
+ // Set movement deltas to fix issues with certain 3D programs
+ SInt64 deltaX = pos.x;
+ deltaX -= m_xCursor;
+
+ SInt64 deltaY = pos.y;
+ deltaY -= m_yCursor;
+
+ CGEventSetIntegerValueField(event, kCGMouseEventDeltaX, deltaX);
+ CGEventSetIntegerValueField(event, kCGMouseEventDeltaY, deltaY);
+
+ double deltaFX = deltaX;
+ double deltaFY = deltaY;
+
+ CGEventSetDoubleValueField(event, kCGMouseEventDeltaX, deltaFX);
+ CGEventSetDoubleValueField(event, kCGMouseEventDeltaY, deltaFY);
+
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp
index c7032470..6a0d72bf 100644
--- a/src/lib/platform/XWindowsScreen.cpp
+++ b/src/lib/platform/XWindowsScreen.cpp
@@ -160,15 +160,12 @@ XWindowsScreen::XWindowsScreen(
// primary/secondary screen only initialization
if (m_isPrimary) {
- // start watching for events on other windows
- selectEvents(m_root);
- m_xi2detected = detectXI2();
-
- if (m_xi2detected) {
#ifdef HAVE_XI2
+ m_xi2detected = detectXI2();
+ if (m_xi2detected) {
selectXIRawMotion();
-#endif
} else
+#endif
{
// start watching for events on other windows
selectEvents(m_root);
@@ -745,7 +742,7 @@ XWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", synergy::KeyMap::formatKey(key, mask).c_str(), key, mask));
return 0;
}
-
+
LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", synergy::KeyMap::formatKey(key, mask).c_str(), key, mask, id));
return id;
}
@@ -827,7 +824,7 @@ void
XWindowsScreen::fakeMouseButton(ButtonID button, bool press)
{
const unsigned int xButton = mapButtonToX(button);
- if (xButton != 0) {
+ if (xButton > 0 && xButton < 11) {
XTestFakeButtonEvent(m_display, xButton,
press ? True : False, CurrentTime);
XFlush(m_display);
@@ -977,22 +974,6 @@ XWindowsScreen::saveShape()
m_w = WidthOfScreen(DefaultScreenOfDisplay(m_display));
m_h = HeightOfScreen(DefaultScreenOfDisplay(m_display));
-#if HAVE_X11_EXTENSIONS_XRANDR_H
- if (m_xrandr){
- int numSizes;
- XRRScreenSize* xrrs;
- Rotation rotation;
- xrrs = XRRSizes(m_display, DefaultScreen(m_display), &numSizes);
- XRRRotations(m_display, DefaultScreen(m_display), &rotation);
- if (xrrs != NULL) {
- if (rotation & (RR_Rotate_90|RR_Rotate_270) ){
- m_w = xrrs->height;
- m_h = xrrs->width;
- }
- }
- }
-#endif
-
// get center of default screen
m_xCenter = m_x + (m_w >> 1);
m_yCenter = m_y + (m_h >> 1);
@@ -1300,7 +1281,7 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*)
// handle the event ourself
switch (xevent->type) {
case CreateNotify:
- if (m_isPrimary) {
+ if (m_isPrimary && !m_xi2detected) {
// select events on new window
selectEvents(xevent->xcreatewindow.window);
}
diff --git a/src/lib/server/Config.cpp b/src/lib/server/Config.cpp
index dac8f58e..e50cf1d2 100644
--- a/src/lib/server/Config.cpp
+++ b/src/lib/server/Config.cpp
@@ -2096,11 +2096,11 @@ ConfigReadContext::parseInterval(const ArgList& args) const
}
char* end;
- long startValue = strtol(args[0].c_str(), &end, 10);
+ double startValue = strtod(args[0].c_str(), &end);
if (end[0] != '\0') {
throw XConfigRead(*this, "invalid interval \"%{1}\"", concatArgs(args));
}
- long endValue = strtol(args[1].c_str(), &end, 10);
+ double endValue = strtod(args[1].c_str(), &end);
if (end[0] != '\0') {
throw XConfigRead(*this, "invalid interval \"%{1}\"", concatArgs(args));
}
diff --git a/src/lib/server/Server.cpp b/src/lib/server/Server.cpp
index c980d03b..fd90f5f3 100644
--- a/src/lib/server/Server.cpp
+++ b/src/lib/server/Server.cpp
@@ -1766,52 +1766,66 @@ Server::onMouseMovePrimary(SInt32 x, SInt32 y)
}
// see if we should change screens
- EDirection dir;
+ // when the cursor is in a corner, there may be a screen either
+ // horizontally or vertically. check both directions.
+ EDirection dirh = kNoDirection, dirv = kNoDirection;
+ SInt32 xh = x, yv = y;
if (x < ax + zoneSize) {
- x -= zoneSize;
- dir = kLeft;
+ xh -= zoneSize;
+ dirh = kLeft;
}
else if (x >= ax + aw - zoneSize) {
- x += zoneSize;
- dir = kRight;
+ xh += zoneSize;
+ dirh = kRight;
}
- else if (y < ay + zoneSize) {
- y -= zoneSize;
- dir = kTop;
+ if (y < ay + zoneSize) {
+ yv -= zoneSize;
+ dirv = kTop;
}
else if (y >= ay + ah - zoneSize) {
- y += zoneSize;
- dir = kBottom;
+ yv += zoneSize;
+ dirv = kBottom;
}
- else {
+ if (dirh == kNoDirection && dirv == kNoDirection) {
// still on local screen
noSwitch(x, y);
return false;
}
- // get jump destination
- BaseClientProxy* newScreen = mapToNeighbor(m_active, dir, x, y);
+ // check both horizontally and vertically
+ EDirection dirs[] = {dirh, dirv};
+ SInt32 xs[] = {xh, x}, ys[] = {y, yv};
+ for (int i = 0; i < 2; ++i) {
+ EDirection dir = dirs[i];
+ if (dir == kNoDirection) {
+ continue;
+ }
+ x = xs[i], y = ys[i];
- // should we switch or not?
- if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) {
- if (m_args.m_enableDragDrop
- && m_screen->isDraggingStarted()
- && m_active != newScreen
- && m_waitDragInfoThread) {
- if (m_sendDragInfoThread == NULL) {
- m_sendDragInfoThread = new Thread(
- new TMethodJob(
- this,
- &Server::sendDragInfoThread, newScreen));
+ // get jump destination
+ BaseClientProxy* newScreen = mapToNeighbor(m_active, dir, x, y);
+
+ // should we switch or not?
+ if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) {
+ if (m_args.m_enableDragDrop
+ && m_screen->isDraggingStarted()
+ && m_active != newScreen
+ && m_waitDragInfoThread) {
+ if (m_sendDragInfoThread == NULL) {
+ m_sendDragInfoThread = new Thread(
+ new TMethodJob(
+ this,
+ &Server::sendDragInfoThread, newScreen));
+ }
+
+ return false;
}
- return false;
+ // switch screen
+ switchScreen(newScreen, x, y, false);
+ m_waitDragInfoThread = true;
+ return true;
}
-
- // switch screen
- switchScreen(newScreen, x, y, false);
- m_waitDragInfoThread = true;
- return true;
}
return false;
diff --git a/src/lib/synergy/key_types.h b/src/lib/synergy/key_types.h
index ea9387b1..f45cea24 100644
--- a/src/lib/synergy/key_types.h
+++ b/src/lib/synergy/key_types.h
@@ -110,10 +110,12 @@ static const KeyID kKeyScrollLock = 0xEF14;
static const KeyID kKeySysReq = 0xEF15;
static const KeyID kKeyEscape = 0xEF1B;
static const KeyID kKeyHenkan = 0xEF23; /* Start/Stop Conversion */
-static const KeyID kKeyHangulKana = 0xEF26; /* Hangul, Kana */
+static const KeyID kKeyKana = 0xEF26; /* Kana */
static const KeyID kKeyHiraganaKatakana = 0xEF27; /* Hiragana/Katakana toggle */
static const KeyID kKeyZenkaku = 0xEF2A; /* Zenkaku/Hankaku */
-static const KeyID kKeyHanjaKanzi = 0xEF2A; /* Hanja, Kanzi */
+static const KeyID kKeyKanzi = 0xEF2A; /* Kanzi */
+static const KeyID kKeyHangul = 0xEF31; /* Hangul */
+static const KeyID kKeyHanja = 0xEF34; /* Hanja */
static const KeyID kKeyDelete = 0xEFFF; /* Delete, rubout */
// cursor control
diff --git a/src/micro/uSynergy.h b/src/micro/uSynergy.h
index 44534d24..3d064d51 100644
--- a/src/micro/uSynergy.h
+++ b/src/micro/uSynergy.h
@@ -46,7 +46,7 @@ extern "C" {
#error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN"
#elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN)
/* Attempt to auto detect */
- #if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN)
+ #if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN)
#define USYNERGY_LITTLE_ENDIAN
#elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN)
#define USYNERGY_BIG_ENDIAN
diff --git a/src/test/integtests/platform/MSWindowsKeyStateTests.cpp b/src/test/integtests/platform/MSWindowsKeyStateTests.cpp
index c7a4b666..0affab6e 100644
--- a/src/test/integtests/platform/MSWindowsKeyStateTests.cpp
+++ b/src/test/integtests/platform/MSWindowsKeyStateTests.cpp
@@ -121,3 +121,24 @@ TEST_F(MSWindowsKeyStateTests, saveModifiers_noModifiers_savedModifiers0)
ASSERT_EQ(0, keyState.getSavedModifiers());
delete desks;
}
+
+TEST_F(MSWindowsKeyStateTests, testKoreanLocale_inputModeKey_resultCorrectKeyID)
+{
+ NiceMock eventQueue;
+ MSWindowsDesks* desks = newDesks(&eventQueue);
+ MockKeyMap keyMap;
+ MSWindowsKeyState keyState(desks, getEventTarget(), &eventQueue, keyMap);
+
+ keyState.setKeyLayout((HKL)0x00000412u); // for ko-KR local ID
+ ASSERT_EQ(0xEF31, keyState.getKeyID(0x15u, 0x1f2u)); // VK_HANGUL from Hangul key
+ ASSERT_EQ(0xEF34, keyState.getKeyID(0x19u, 0x1f1u)); // VK_HANJA from Hanja key
+ ASSERT_EQ(0xEF31, keyState.getKeyID(0x15u, 0x11du)); // VK_HANGUL from R-Alt key
+ ASSERT_EQ(0xEF34, keyState.getKeyID(0x19u, 0x138u)); // VK_HANJA from R-Ctrl key
+
+ keyState.setKeyLayout((HKL)0x00000411); // for ja-jp locale ID
+ ASSERT_EQ(0xEF26, keyState.getKeyID(0x15u, 0x1du)); // VK_KANA
+ ASSERT_EQ(0xEF2A, keyState.getKeyID(0x19u, 0x38u)); // VK_KANJI
+
+ delete desks;
+}
+