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:
parent
fd679589e5
commit
e9a654e16e
7 changed files with 35 additions and 186 deletions
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue