SYNERGY-148 Memory leaks on macOS (#6837)

* SYNERGY-148 Memory leaks on macOS

* SYNEGRY-148 Update ChangeLog and fixed one typo
This commit is contained in:
SerhiiGadzhilov 2020-11-11 10:01:09 +03:00 committed by GitHub
parent fd679589e5
commit e9a654e16e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 35 additions and 186 deletions

View file

@ -1,6 +1,7 @@
=========== ===========
Bug fixes: Bug fixes:
- #6831 Incorporating Sonar's major - #6831 Incorporating Sonar's major
- #6837 Memory leaks on macOS system
Enhancements: Enhancements:

View file

@ -112,7 +112,6 @@ MainWindow::MainWindow (AppConfig& appConfig,
m_pSynergy(NULL), m_pSynergy(NULL),
m_SynergyState(synergyDisconnected), m_SynergyState(synergyDisconnected),
m_ServerConfig(5, 3, m_AppConfig->screenName(), this), m_ServerConfig(5, 3, m_AppConfig->screenName(), this),
m_pTempConfigFile(NULL),
m_pTrayIcon(NULL), m_pTrayIcon(NULL),
m_pTrayIconMenu(NULL), m_pTrayIconMenu(NULL),
m_AlreadyHidden(false), m_AlreadyHidden(false),
@ -818,17 +817,19 @@ QString MainWindow::configFilename()
{ {
// TODO: no need to use a temporary file, since we need it to // TODO: no need to use a temporary file, since we need it to
// be permenant (since it'll be used for Windows services, etc). // be permenant (since it'll be used for Windows services, etc).
m_pTempConfigFile = new QTemporaryFile(); QTemporaryFile tempConfigFile;
if (!m_pTempConfigFile->open()) tempConfigFile.setAutoRemove(false);
if (!tempConfigFile.open())
{ {
QMessageBox::critical(this, tr("Cannot write configuration file"), tr("The temporary configuration file required to start synergy can not be written.")); QMessageBox::critical(this, tr("Cannot write configuration file"), tr("The temporary configuration file required to start synergy can not be written."));
return ""; return "";
} }
serverConfig().save(*m_pTempConfigFile); serverConfig().save(tempConfigFile);
filename = m_pTempConfigFile->fileName(); filename = tempConfigFile.fileName();
m_pTempConfigFile->close(); tempConfigFile.close();
} }
else else
{ {
@ -913,13 +914,6 @@ void MainWindow::stopSynergy()
setSynergyState(synergyDisconnected); setSynergyState(synergyDisconnected);
// HACK: deleting the object deletes the physical file, which is
// bad, since it could be in use by the Windows service!
#if !defined(Q_OS_WIN)
delete m_pTempConfigFile;
#endif
m_pTempConfigFile = NULL;
// reset so that new connects cause auto-hide. // reset so that new connects cause auto-hide.
m_AlreadyHidden = false; m_AlreadyHidden = false;
} }

View file

@ -46,7 +46,6 @@ class QComboBox;
class QTabWidget; class QTabWidget;
class QCheckBox; class QCheckBox;
class QRadioButton; class QRadioButton;
class QTemporaryFile;
class QMessageBox; class QMessageBox;
class QAbstractButton; class QAbstractButton;
@ -222,7 +221,6 @@ public slots:
QProcess* m_pSynergy; QProcess* m_pSynergy;
int m_SynergyState; int m_SynergyState;
ServerConfig m_ServerConfig; ServerConfig m_ServerConfig;
QTemporaryFile* m_pTempConfigFile;
QSystemTrayIcon* m_pTrayIcon; QSystemTrayIcon* m_pTrayIcon;
QMenu* m_pTrayIconMenu; QMenu* m_pTrayIconMenu;
bool m_AlreadyHidden; bool m_AlreadyHidden;

View file

@ -253,9 +253,9 @@ OSXKeyState::mapKeyFromEvent(KeyIDs& ids,
} }
// get keyboard info // get keyboard info
TISInputSourceRef currentKeyboardLayout = TISCopyCurrentKeyboardLayoutInputSource(); AutoTISInputSourceRef currentKeyboardLayout(TISCopyCurrentKeyboardLayoutInputSource(), CFRelease);
if (currentKeyboardLayout == NULL) { if (!currentKeyboardLayout) {
return kKeyNone; return kKeyNone;
} }
@ -288,7 +288,7 @@ OSXKeyState::mapKeyFromEvent(KeyIDs& ids,
} }
// translate via uchr resource // translate via uchr resource
CFDataRef ref = (CFDataRef) TISGetInputSourceProperty(currentKeyboardLayout, CFDataRef ref = (CFDataRef) TISGetInputSourceProperty(currentKeyboardLayout.get(),
kTISPropertyUnicodeKeyLayoutData); kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout* layout = (const UCKeyboardLayout*) CFDataGetBytePtr(ref); const UCKeyboardLayout* layout = (const UCKeyboardLayout*) CFDataGetBytePtr(ref);
const bool layoutValid = (layout != NULL); const bool layoutValid = (layout != NULL);
@ -397,9 +397,9 @@ OSXKeyState::pollActiveModifiers() const
SInt32 SInt32
OSXKeyState::pollActiveGroup() const OSXKeyState::pollActiveGroup() const
{ {
TISInputSourceRef keyboardLayout = TISCopyCurrentKeyboardLayoutInputSource(); AutoTISInputSourceRef keyboardLayout(TISCopyCurrentKeyboardLayoutInputSource(), CFRelease);
CFDataRef id = (CFDataRef)TISGetInputSourceProperty( CFDataRef id = (CFDataRef)TISGetInputSourceProperty(
keyboardLayout, kTISPropertyInputSourceID); keyboardLayout.get(), kTISPropertyInputSourceID);
GroupMap::const_iterator i = m_groupMap.find(id); GroupMap::const_iterator i = m_groupMap.find(id);
if (i != m_groupMap.end()) { if (i != m_groupMap.end()) {
@ -430,18 +430,19 @@ void
OSXKeyState::getKeyMap(synergy::KeyMap& keyMap) OSXKeyState::getKeyMap(synergy::KeyMap& keyMap)
{ {
// update keyboard groups // update keyboard groups
SInt32 numGroups {0};
if (getGroups(m_groups)) { if (getGroups(m_groups)) {
m_groupMap.clear(); m_groupMap.clear();
SInt32 numGroups = (SInt32)m_groups.size(); numGroups = CFArrayGetCount(m_groups.get());
for (SInt32 g = 0; g < numGroups; ++g) { for (SInt32 g = 0; g < numGroups; ++g) {
CFDataRef id = (CFDataRef)TISGetInputSourceProperty( TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(m_groups.get(), g);
m_groups[g], kTISPropertyInputSourceID); CFDataRef id = (CFDataRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyInputSourceID);
m_groupMap[id] = g; m_groupMap[id] = g;
} }
} }
UInt32 keyboardType = LMGetKbdType(); UInt32 keyboardType = LMGetKbdType();
for (SInt32 g = 0, n = (SInt32)m_groups.size(); g < n; ++g) { for (SInt32 g = 0; g < numGroups; ++g) {
// add special keys // add special keys
getKeyMapForSpecialKeys(keyMap, g); getKeyMapForSpecialKeys(keyMap, g);
@ -450,8 +451,8 @@ OSXKeyState::getKeyMap(synergy::KeyMap& keyMap)
// add regular keys // add regular keys
// try uchr resource first // try uchr resource first
CFDataRef resourceRef = (CFDataRef)TISGetInputSourceProperty( TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(m_groups.get(), g);
m_groups[g], kTISPropertyUnicodeKeyLayoutData); CFDataRef resourceRef = (CFDataRef)TISGetInputSourceProperty(keyboardLayout, kTISPropertyUnicodeKeyLayoutData);
layoutValid = resourceRef != NULL; layoutValid = resourceRef != NULL;
if (layoutValid) if (layoutValid)
@ -834,51 +835,28 @@ OSXKeyState::handleModifierKey(void* target,
bool bool
OSXKeyState::getGroups(GroupList& groups) const OSXKeyState::getGroups(GroupList& groups) const
{ {
CFIndex n;
bool gotLayouts = false;
// get number of layouts // get number of layouts
CFStringRef keys[] = { kTISPropertyInputSourceCategory }; CFStringRef keys[] = { kTISPropertyInputSourceCategory };
CFStringRef values[] = { kTISCategoryKeyboardInputSource }; CFStringRef values[] = { kTISCategoryKeyboardInputSource };
CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL); AutoCFDictionary dict(CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL), CFRelease);
CFArrayRef kbds = TISCreateInputSourceList(dict, false); GroupList kbds(TISCreateInputSourceList(dict.get(), false), CFRelease);
n = CFArrayGetCount(kbds);
gotLayouts = (n != 0);
if (!gotLayouts) { if (CFArrayGetCount(kbds.get()) > 0) {
groups = std::move(kbds);
}
else{
LOG((CLOG_DEBUG1 "can't get keyboard layouts")); LOG((CLOG_DEBUG1 "can't get keyboard layouts"));
return false; return false;
} }
// get each layout
groups.clear();
for (CFIndex i = 0; i < n; ++i) {
bool addToGroups = true;
TISInputSourceRef keyboardLayout =
(TISInputSourceRef)CFArrayGetValueAtIndex(kbds, i);
if (addToGroups)
groups.push_back(keyboardLayout);
}
return true; return true;
} }
void void
OSXKeyState::setGroup(SInt32 group) OSXKeyState::setGroup(SInt32 group)
{ {
TISSetInputMethodKeyboardLayoutOverride(m_groups[group]); TISInputSourceRef keyboardLayout = (TISInputSourceRef)CFArrayGetValueAtIndex(m_groups.get(), group);
} TISSetInputMethodKeyboardLayoutOverride(keyboardLayout);
void
OSXKeyState::checkKeyboardLayout()
{
// XXX -- should call this when notified that groups have changed.
// if no notification for that then we should poll.
GroupList groups;
if (getGroups(groups) && groups != m_groups) {
updateKeyMap();
updateKeyState();
}
} }
void void

View file

@ -25,9 +25,9 @@
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
typedef TISInputSourceRef KeyLayout;
class IOSXKeyResource; class IOSXKeyResource;
//! OS X key state //! OS X key state
/*! /*!
A key state for OS X. A key state for OS X.
@ -106,7 +106,11 @@ protected:
private: private:
class KeyResource; class KeyResource;
typedef std::vector<KeyLayout> GroupList; typedef void(*CFDeallocator)(CFTypeRef);
typedef std::unique_ptr<const __CFArray, CFDeallocator> GroupList;
typedef std::unique_ptr<const __CFDictionary, CFDeallocator> AutoCFDictionary;
typedef std::unique_ptr<__TISInputSource, CFDeallocator> AutoTISInputSourceRef;
// Add hard coded special keys to a synergy::KeyMap. // Add hard coded special keys to a synergy::KeyMap.
void getKeyMapForSpecialKeys( void getKeyMapForSpecialKeys(
@ -122,10 +126,6 @@ private:
// Change active keyboard group to group // Change active keyboard group to group
void setGroup(SInt32 group); void setGroup(SInt32 group);
// Check if the keyboard layout has changed and update keyboard state
// if so.
void checkKeyboardLayout();
// Send an event for the given modifier key // Send an event for the given modifier key
void handleModifierKey(void* target, void handleModifierKey(void* target,
UInt32 virtualKey, KeyID id, UInt32 virtualKey, KeyID id,
@ -170,7 +170,7 @@ private:
VirtualKeyMap m_virtualKeyMap; VirtualKeyMap m_virtualKeyMap;
mutable UInt32 m_deadKeyState; mutable UInt32 m_deadKeyState;
GroupList m_groups; GroupList m_groups{nullptr, CFRelease};
GroupMap m_groupMap; GroupMap m_groupMap;
bool m_shiftPressed; bool m_shiftPressed;
bool m_controlPressed; bool m_controlPressed;

View file

@ -1,30 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2016 Symless.
*
* 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 COPYING 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/>.
*/
#pragma once
#import <CoreFoundation/CoreFoundation.h>
#include "synergy/key_types.h"
#if defined(__cplusplus)
extern "C" {
#endif
bool fakeNativeMediaKey(KeyID id);
#if defined(__cplusplus)
}
#endif

View file

@ -1,92 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2016 Symless.
*
* 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 COPYING 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.
*/
#import "platform/OSXMediaKeySimulator.h"
#import <Cocoa/Cocoa.h>
int convertKeyIDToNXKeyType(KeyID id)
{
// hidsystem/ev_keymap.h
// NX_KEYTYPE_SOUND_UP 0
// NX_KEYTYPE_SOUND_DOWN 1
// NX_KEYTYPE_BRIGHTNESS_UP 2
// NX_KEYTYPE_BRIGHTNESS_DOWN 3
// NX_KEYTYPE_MUTE 7
// NX_KEYTYPE_EJECT 14
// NX_KEYTYPE_PLAY 16
// NX_KEYTYPE_NEXT 17
// NX_KEYTYPE_PREVIOUS 18
// NX_KEYTYPE_FAST 19
// NX_KEYTYPE_REWIND 20
int type = -1;
switch (id) {
case kKeyAudioUp:
type = 0;
break;
case kKeyAudioDown:
type = 1;
break;
case kKeyBrightnessUp:
type = 2;
break;
case kKeyBrightnessDown:
type = 3;
break;
case kKeyAudioMute:
type = 7;
break;
case kKeyEject:
type = 14;
break;
case kKeyAudioPlay:
type = 16;
break;
case kKeyAudioNext:
type = 17;
break;
case kKeyAudioPrev:
type = 18;
break;
default:
break;
}
return type;
}
bool
fakeNativeMediaKey(KeyID id)
{
NSEvent* downRef = [NSEvent otherEventWithType:NSSystemDefined
location: NSMakePoint(0, 0) modifierFlags:0xa00
timestamp:0 windowNumber:0 context:0 subtype:8
data1:(convertKeyIDToNXKeyType(id) << 16) | ((0xa) << 8)
data2:-1];
CGEventRef downEvent = [downRef CGEvent];
NSEvent* upRef = [NSEvent otherEventWithType:NSSystemDefined
location: NSMakePoint(0, 0) modifierFlags:0xa00
timestamp:0 windowNumber:0 context:0 subtype:8
data1:(convertKeyIDToNXKeyType(id) << 16) | ((0xb) << 8)
data2:-1];
CGEventRef upEvent = [upRef CGEvent];
CGEventPost(0, downEvent);
CGEventPost(0, upEvent);
return true;
}