1 /*
2  * synergy -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2016 Symless Ltd.
4  * Copyright (C) 2008 Volker Lanz (vl@fidra.de)
5  *
6  * This package is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * found in the file LICENSE that should have accompanied this file.
9  *
10  * This package is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "QSynergyApplication.h"
20 #include "LicenseManager.h"
21 #include "MainWindow.h"
22 #include "AppConfig.h"
23 #include "SetupWizard.h"
24 #include "SetupWizardBlocker.h"
25 
26 #include <QtCore>
27 #include <QtGui>
28 #include <QMessageBox>
29 
30 #if defined(Q_OS_MAC)
31 #include <Carbon/Carbon.h>
32 #endif
33 
34 #ifdef Q_OS_DARWIN
35 #include <cstdlib>
36 #endif
37 
38 class QThreadImpl : public QThread
39 {
40 public:
msleep(unsigned long msecs)41     static void msleep(unsigned long msecs)
42     {
43         QThread::msleep(msecs);
44     }
45 };
46 
47 QString getSystemSettingPath();
48 
49 #if defined(Q_OS_MAC)
50 bool checkMacAssistiveDevices();
51 #endif
52 
main(int argc,char * argv[])53 int main(int argc, char* argv[])
54 {
55 #ifdef Q_OS_DARWIN
56     /* Workaround for QTBUG-40332 - "High ping when QNetworkAccessManager is instantiated" */
57     ::setenv ("QT_BEARER_POLL_TIMEOUT", "-1", 1);
58 #endif
59 
60 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
61     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
62 #endif
63 
64     QCoreApplication::setOrganizationName("Synergy");
65     QCoreApplication::setOrganizationDomain("http://symless.com/");
66     QCoreApplication::setApplicationName("Synergy");
67 
68     QSynergyApplication app(argc, argv);
69 
70 #if defined(Q_OS_MAC)
71 
72     if (app.applicationDirPath().startsWith("/Volumes/")) {
73         QMessageBox::information(
74             NULL, "Synergy",
75             "Please drag Synergy to the Applications folder, and open it from there.");
76         return 1;
77     }
78 
79     if (!checkMacAssistiveDevices())
80     {
81         return 1;
82     }
83 #endif
84 
85 #ifndef Q_OS_WIN
86     QApplication::setQuitOnLastWindowClosed(false);
87 #endif
88 
89     AppConfig appConfig;
90     qRegisterMetaType<Edition>("Edition");
91 #ifndef SYNERGY_ENTERPRISE
92     LicenseManager licenseManager (&appConfig);
93 #endif
94 
95     app.switchTranslator(appConfig.language());
96 
97 #ifdef SYNERGY_ENTERPRISE
98     MainWindow mainWindow(appConfig);
99 #else
100     MainWindow mainWindow(appConfig, licenseManager);
101 #endif
102 
103     QObject::connect(dynamic_cast<QObject*>(&app), SIGNAL(aboutToQuit()),
104                 &mainWindow, SLOT(saveSettings()));
105 
106     std::unique_ptr<SetupWizardBlocker> setupBlocker;
107     if (qgetenv("XDG_SESSION_TYPE") == "wayland")
108     {
109         setupBlocker.reset(new SetupWizardBlocker(mainWindow, SetupWizardBlocker::qBlockerType::waylandDetected));
110         setupBlocker->show();
111         return QApplication::exec();
112     }
113 
114     std::unique_ptr<SetupWizard> setupWizard;
115     if (appConfig.wizardShouldRun())
116     {
117         setupWizard.reset(new SetupWizard(mainWindow));
118         setupWizard->show();
119     }
120     else
121     {
122         mainWindow.open();
123     }
124 
125     return app.exec();
126 }
127 
128 
129 #if defined(Q_OS_MAC)
checkMacAssistiveDevices()130 bool checkMacAssistiveDevices()
131 {
132 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 // mavericks
133 
134     // new in mavericks, applications are trusted individually
135     // with use of the accessibility api. this call will show a
136     // prompt which can show the security/privacy/accessibility
137     // tab, with a list of allowed applications. synergy should
138     // show up there automatically, but will be unchecked.
139 
140     if (AXIsProcessTrusted()) {
141         return true;
142     }
143 
144     const void* keys[] = { kAXTrustedCheckOptionPrompt };
145     const void* trueValue[] = { kCFBooleanTrue };
146     CFDictionaryRef options = CFDictionaryCreate(NULL, keys, trueValue, 1, NULL, NULL);
147 
148     bool result = AXIsProcessTrustedWithOptions(options);
149     CFRelease(options);
150     return result;
151 
152 #else
153 
154     // now deprecated in mavericks.
155     bool result = AXAPIEnabled();
156     if (!result) {
157         QMessageBox::information(
158             NULL, "Synergy",
159             "Please enable access to assistive devices "
160             "System Preferences -> Security & Privacy -> "
161             "Privacy -> Accessibility, then re-open Synergy.");
162     }
163     return result;
164 
165 #endif
166 }
167 #endif
168