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; +} +