deskflow/src/lib/synergy/Screen.cpp

413 lines
9.6 KiB
C++
Raw Normal View History

2012-06-10 16:50:54 +00:00
/*
* synergy -- mouse and keyboard sharing utility
2016-09-07 14:24:00 +00:00
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2003 Chris Schoeneman
*
2012-06-10 16:50:54 +00:00
* 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 LICENSE that should have accompanied this file.
*
2012-06-10 16:50:54 +00:00
* 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/>.
*/
#include "synergy/Screen.h"
#include "base/IEventQueue.h"
#include "base/Log.h"
#include "base/TMethodEventJob.h"
#include "server/ClientProxy.h"
#include "synergy/IPlatformScreen.h"
#include "synergy/protocol_types.h"
2012-06-10 16:50:54 +00:00
namespace synergy {
2012-06-10 16:50:54 +00:00
//
2014-11-11 13:51:47 +00:00
// Screen
2012-06-10 16:50:54 +00:00
//
Screen::Screen(IPlatformScreen *platformScreen, IEventQueue *events)
: m_screen(platformScreen),
m_isPrimary(platformScreen->isPrimary()),
m_enabled(false),
m_entered(m_isPrimary),
m_fakeInput(false),
m_events(events),
m_mock(false),
m_enableDragDrop(false) {
assert(m_screen != NULL);
2012-06-10 16:50:54 +00:00
// reset options
resetOptions();
2012-06-10 16:50:54 +00:00
LOG((CLOG_DEBUG "opened display"));
2012-06-10 16:50:54 +00:00
}
Screen::~Screen() {
if (m_mock) {
return;
}
if (m_enabled) {
disable();
}
assert(!m_enabled);
Refactored core process management and IPC client (#7425) * Also ignore `command_pre` for Fedora itself * Improve warning message * Fixed layout issues on main window * Restore fusion theme for Windows dark mode * Further correct main window layout * Set CWD for launch on Windows to same dir as .env * Use signals for tray icon instead of callback * Reduce complexity for setting tray icon * Further reduce tray icon complexity * Reduce tray retry time * Fixed tray not showing on macOS * Refactor function names * Move tray icon to lib * Decouple server connection class * Move server connection to lib * Move client config to lib * Remove redundant forward declarations * Fixed some namespaces in the new lib * Move core process code to new class * Improve member names on new process class * Remove copy/pasta code * Move OSX helpers to lib * Add .mm to lib config * Fixed copyright * Improve reliability of log line handling * Fixed TLS certificate generate bugs * Remove client list * Refactor core process handling to fix various problems * Fixed process/connection status bugs * Fixed function signature issue on macOS * Fixed override warnings * Fixed string format warning * Save `wasStarted` state and use that instead * Use only filename in dialog * Use lambda for simple slot * Scroll to bottom if at bottome * Set value based on position before text added and set horizontal scroll too * Add 1px tollerance for Linux * Simplify start/stop mutex * Always stop service on restart * Increase scroll bottom threshold to 2 * Log warning instead of critical * Fixed long-standing dir CD-up hack * Remove include * Remove include * Fixed rogue dumbisense includes * Account for optional distro_like * Add QAction include to solve incomplete type * Remove rogue #pragma * Static cast log value * Solve event queue delete warning * Fixed integ test on Windows 10 * Reduce enum verbosity * Use static instance instead of global * Make function const * Use unique_ptr instead of new and delete, and made some functions const * Fixed smart pointer use * Fixed variable shadowing * Fixed wrong use of using * Fixed missing namespace using * Simplify TLS error handling * Improve UX around certificate errors and success * Decouple app config from core process through interface * First iteration of core process test * Mark dtor as override * Rename attach launch entry * Add TODO * Create proxy for process * Move IPC client to deps * Fixed warnings * Reorganize new GUI lib dir structure * Update includes to reflect new paths * Reorg GUI tests * Abstract IPC client * Refactor about screen * Fixed .ui warnings * Remove redundant include * Fixed typo * Fixed typos and add spelling * Fixed misleading function name * Improve comment * Improve code coverage for core process * Remove noisy log line * Make global const * Use default dtor * Use vector instead of new * Make ctor explicit * Make ctor explicit (2) * Use enum class * Fixed bad enum * Stub out core tool * Stub out dir operation * Extract byte functions * Add missing return path * Simplify byte/int functions * Fix truncation * Use ctor member assignment * Fixed segfault in process proxy * Fixed print warning * Make function const * Cleanup header * Fixed missing name * Update ChangeLog * Make more functions const
2024-08-07 14:05:18 +00:00
// TODO: why assert this? it appears to be false when an elevated dialog
// appears on windows and the process is killed.
assert(m_entered == m_isPrimary);
Refactored core process management and IPC client (#7425) * Also ignore `command_pre` for Fedora itself * Improve warning message * Fixed layout issues on main window * Restore fusion theme for Windows dark mode * Further correct main window layout * Set CWD for launch on Windows to same dir as .env * Use signals for tray icon instead of callback * Reduce complexity for setting tray icon * Further reduce tray icon complexity * Reduce tray retry time * Fixed tray not showing on macOS * Refactor function names * Move tray icon to lib * Decouple server connection class * Move server connection to lib * Move client config to lib * Remove redundant forward declarations * Fixed some namespaces in the new lib * Move core process code to new class * Improve member names on new process class * Remove copy/pasta code * Move OSX helpers to lib * Add .mm to lib config * Fixed copyright * Improve reliability of log line handling * Fixed TLS certificate generate bugs * Remove client list * Refactor core process handling to fix various problems * Fixed process/connection status bugs * Fixed function signature issue on macOS * Fixed override warnings * Fixed string format warning * Save `wasStarted` state and use that instead * Use only filename in dialog * Use lambda for simple slot * Scroll to bottom if at bottome * Set value based on position before text added and set horizontal scroll too * Add 1px tollerance for Linux * Simplify start/stop mutex * Always stop service on restart * Increase scroll bottom threshold to 2 * Log warning instead of critical * Fixed long-standing dir CD-up hack * Remove include * Remove include * Fixed rogue dumbisense includes * Account for optional distro_like * Add QAction include to solve incomplete type * Remove rogue #pragma * Static cast log value * Solve event queue delete warning * Fixed integ test on Windows 10 * Reduce enum verbosity * Use static instance instead of global * Make function const * Use unique_ptr instead of new and delete, and made some functions const * Fixed smart pointer use * Fixed variable shadowing * Fixed wrong use of using * Fixed missing namespace using * Simplify TLS error handling * Improve UX around certificate errors and success * Decouple app config from core process through interface * First iteration of core process test * Mark dtor as override * Rename attach launch entry * Add TODO * Create proxy for process * Move IPC client to deps * Fixed warnings * Reorganize new GUI lib dir structure * Update includes to reflect new paths * Reorg GUI tests * Abstract IPC client * Refactor about screen * Fixed .ui warnings * Remove redundant include * Fixed typo * Fixed typos and add spelling * Fixed misleading function name * Improve comment * Improve code coverage for core process * Remove noisy log line * Make global const * Use default dtor * Use vector instead of new * Make ctor explicit * Make ctor explicit (2) * Use enum class * Fixed bad enum * Stub out core tool * Stub out dir operation * Extract byte functions * Add missing return path * Simplify byte/int functions * Fix truncation * Use ctor member assignment * Fixed segfault in process proxy * Fixed print warning * Make function const * Cleanup header * Fixed missing name * Update ChangeLog * Make more functions const
2024-08-07 14:05:18 +00:00
delete m_screen;
LOG((CLOG_DEBUG "closed display"));
}
void Screen::enable() {
assert(!m_enabled);
2012-06-10 16:50:54 +00:00
m_screen->updateKeyMap();
m_screen->updateKeyState();
m_screen->enable();
if (m_isPrimary) {
enablePrimary();
} else {
enableSecondary();
}
// note activation
m_enabled = true;
2012-06-10 16:50:54 +00:00
}
void Screen::disable() {
assert(m_enabled);
2012-06-10 16:50:54 +00:00
if (!m_isPrimary && m_entered) {
leave();
} else if (m_isPrimary && !m_entered) {
enter(0);
}
m_screen->disable();
if (m_isPrimary) {
disablePrimary();
} else {
disableSecondary();
}
2012-06-10 16:50:54 +00:00
// note deactivation
m_enabled = false;
2012-06-10 16:50:54 +00:00
}
void Screen::enter(KeyModifierMask toggleMask) {
assert(m_entered == false);
LOG((CLOG_INFO "entering screen"));
2012-06-10 16:50:54 +00:00
// now on screen
m_entered = true;
2012-06-10 16:50:54 +00:00
m_screen->enter();
if (m_isPrimary) {
enterPrimary();
} else {
enterSecondary(toggleMask);
}
2012-06-10 16:50:54 +00:00
}
bool Screen::leave() {
assert(m_entered == true);
LOG((CLOG_INFO "leaving screen"));
2012-06-10 16:50:54 +00:00
if (!m_screen->leave()) {
return false;
}
if (m_isPrimary) {
leavePrimary();
} else {
leaveSecondary();
}
2012-06-10 16:50:54 +00:00
// make sure our idea of clipboard ownership is correct
m_screen->checkClipboards();
2012-06-10 16:50:54 +00:00
// now not on screen
m_entered = false;
2012-06-10 16:50:54 +00:00
return true;
2012-06-10 16:50:54 +00:00
}
void Screen::reconfigure(UInt32 activeSides) {
assert(m_isPrimary);
m_screen->reconfigure(activeSides);
2012-06-10 16:50:54 +00:00
}
void Screen::warpCursor(SInt32 x, SInt32 y) {
assert(m_isPrimary);
m_screen->warpCursor(x, y);
2012-06-10 16:50:54 +00:00
}
void Screen::setClipboard(ClipboardID id, const IClipboard *clipboard) {
m_screen->setClipboard(id, clipboard);
2012-06-10 16:50:54 +00:00
}
void Screen::grabClipboard(ClipboardID id) { m_screen->setClipboard(id, NULL); }
2012-06-10 16:50:54 +00:00
void Screen::screensaver(bool) const {
// do nothing
2012-06-10 16:50:54 +00:00
}
void Screen::keyDown(
KeyID id, KeyModifierMask mask, KeyButton button, const String &lang) {
// check for ctrl+alt+del emulation
if (id == kKeyDelete && (mask & (KeyModifierControl | KeyModifierAlt)) ==
(KeyModifierControl | KeyModifierAlt)) {
LOG((CLOG_DEBUG "emulating ctrl+alt+del press"));
if (m_screen->fakeCtrlAltDel()) {
return;
}
}
m_screen->fakeKeyDown(id, mask, button, lang);
2012-06-10 16:50:54 +00:00
}
void Screen::keyRepeat(
KeyID id, KeyModifierMask mask, SInt32 count, KeyButton button,
const String &lang) {
assert(!m_isPrimary);
m_screen->fakeKeyRepeat(id, mask, count, button, lang);
2012-06-10 16:50:54 +00:00
}
void Screen::keyUp(KeyID, KeyModifierMask, KeyButton button) {
m_screen->fakeKeyUp(button);
2012-06-10 16:50:54 +00:00
}
void Screen::mouseDown(ButtonID button) {
m_screen->fakeMouseButton(button, true);
2012-06-10 16:50:54 +00:00
}
void Screen::mouseUp(ButtonID button) {
m_screen->fakeMouseButton(button, false);
2012-06-10 16:50:54 +00:00
}
void Screen::mouseMove(SInt32 x, SInt32 y) {
assert(!m_isPrimary);
m_screen->fakeMouseMove(x, y);
2012-06-10 16:50:54 +00:00
}
void Screen::mouseRelativeMove(SInt32 dx, SInt32 dy) {
assert(!m_isPrimary);
m_screen->fakeMouseRelativeMove(dx, dy);
2012-06-10 16:50:54 +00:00
}
void Screen::mouseWheel(SInt32 xDelta, SInt32 yDelta) const {
assert(!m_isPrimary);
m_screen->fakeMouseWheel(xDelta, yDelta);
}
void Screen::resetOptions() {
// reset options
m_halfDuplex = 0;
2012-06-10 16:50:54 +00:00
// let screen handle its own options
m_screen->resetOptions();
2012-06-10 16:50:54 +00:00
}
void Screen::setOptions(const OptionsList &options) {
// update options
for (UInt32 i = 0, n = (UInt32)options.size(); i < n; i += 2) {
if (options[i] == kOptionHalfDuplexCapsLock) {
if (options[i + 1] != 0) {
m_halfDuplex |= KeyModifierCapsLock;
} else {
m_halfDuplex &= ~KeyModifierCapsLock;
}
LOG(
(CLOG_DEBUG1 "half-duplex caps-lock %s",
((m_halfDuplex & KeyModifierCapsLock) != 0) ? "on" : "off"));
} else if (options[i] == kOptionHalfDuplexNumLock) {
if (options[i + 1] != 0) {
m_halfDuplex |= KeyModifierNumLock;
} else {
m_halfDuplex &= ~KeyModifierNumLock;
}
LOG(
(CLOG_DEBUG1 "half-duplex num-lock %s",
((m_halfDuplex & KeyModifierNumLock) != 0) ? "on" : "off"));
} else if (options[i] == kOptionHalfDuplexScrollLock) {
if (options[i + 1] != 0) {
m_halfDuplex |= KeyModifierScrollLock;
} else {
m_halfDuplex &= ~KeyModifierScrollLock;
}
LOG(
(CLOG_DEBUG1 "half-duplex scroll-lock %s",
((m_halfDuplex & KeyModifierScrollLock) != 0) ? "on" : "off"));
}
}
// update half-duplex options
m_screen->setHalfDuplexMask(m_halfDuplex);
// let screen handle its own options
m_screen->setOptions(options);
2012-06-10 16:50:54 +00:00
}
void Screen::setSequenceNumber(UInt32 seqNum) {
m_screen->setSequenceNumber(seqNum);
2012-06-10 16:50:54 +00:00
}
UInt32 Screen::registerHotKey(KeyID key, KeyModifierMask mask) {
return m_screen->registerHotKey(key, mask);
2012-06-10 16:50:54 +00:00
}
void Screen::unregisterHotKey(UInt32 id) { m_screen->unregisterHotKey(id); }
void Screen::fakeInputBegin() {
assert(!m_fakeInput);
m_fakeInput = true;
m_screen->fakeInputBegin();
2012-06-10 16:50:54 +00:00
}
void Screen::fakeInputEnd() {
assert(m_fakeInput);
m_fakeInput = false;
m_screen->fakeInputEnd();
}
bool Screen::isOnScreen() const { return m_entered; }
bool Screen::isLockedToScreen() const {
// check for pressed mouse buttons
// HACK: commented out as it breaks new drag drop feature
UInt32 buttonID = 0;
if (m_screen->isAnyMouseButtonDown(buttonID)) {
if (buttonID != kButtonLeft) {
LOG((CLOG_DEBUG "locked by mouse buttonID: %d", buttonID));
}
if (m_enableDragDrop) {
return (buttonID == kButtonLeft) ? false : true;
} else {
return true;
}
}
// not locked
return false;
}
SInt32 Screen::getJumpZoneSize() const {
if (!m_isPrimary) {
return 0;
} else {
return m_screen->getJumpZoneSize();
}
}
void Screen::getCursorCenter(SInt32 &x, SInt32 &y) const {
m_screen->getCursorCenter(x, y);
}
KeyModifierMask Screen::getActiveModifiers() const {
return m_screen->getActiveModifiers();
}
KeyModifierMask Screen::pollActiveModifiers() const {
return m_screen->pollActiveModifiers();
}
bool Screen::isDraggingStarted() const { return m_screen->isDraggingStarted(); }
bool Screen::isFakeDraggingStarted() const {
return m_screen->isFakeDraggingStarted();
}
void Screen::setDraggingStarted(bool started) {
m_screen->setDraggingStarted(started);
}
void Screen::startDraggingFiles(DragFileList &fileList) {
m_screen->fakeDraggingFiles(fileList);
2012-06-10 16:50:54 +00:00
}
void Screen::setEnableDragDrop(bool enabled) { m_enableDragDrop = enabled; }
String &Screen::getDraggingFilename() const {
return m_screen->getDraggingFilename();
2012-06-10 16:50:54 +00:00
}
void Screen::clearDraggingFilename() { m_screen->clearDraggingFilename(); }
const String &Screen::getDropTarget() const {
return m_screen->getDropTarget();
2012-06-10 16:50:54 +00:00
}
void *Screen::getEventTarget() const { return m_screen; }
bool Screen::getClipboard(ClipboardID id, IClipboard *clipboard) const {
return m_screen->getClipboard(id, clipboard);
2012-06-10 16:50:54 +00:00
}
void Screen::getShape(SInt32 &x, SInt32 &y, SInt32 &w, SInt32 &h) const {
m_screen->getShape(x, y, w, h);
}
2012-06-10 16:50:54 +00:00
void Screen::getCursorPos(SInt32 &x, SInt32 &y) const {
m_screen->getCursorPos(x, y);
2012-06-10 16:50:54 +00:00
}
void Screen::enablePrimary() {
// get notified of screen saver activation/deactivation
m_screen->openScreensaver(true);
2012-06-10 16:50:54 +00:00
// claim screen changed size
m_events->addEvent(
Event(m_events->forIScreen().shapeChanged(), getEventTarget()));
2012-06-10 16:50:54 +00:00
}
void Screen::enableSecondary() {
// assume primary has all clipboards
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
grabClipboard(id);
}
2012-06-10 16:50:54 +00:00
}
void Screen::disablePrimary() {
// done with screen saver
m_screen->closeScreensaver();
2012-06-10 16:50:54 +00:00
}
void Screen::disableSecondary() {
// done with screen saver
m_screen->closeScreensaver();
2012-06-10 16:50:54 +00:00
}
void Screen::enterPrimary() {
// do nothing
2012-06-10 16:50:54 +00:00
}
void Screen::enterSecondary(KeyModifierMask) {
// do nothing
2012-06-10 16:50:54 +00:00
}
void Screen::leavePrimary() {
// we don't track keys while on the primary screen so update our
// idea of them now. this is particularly to update the state of
// the toggle modifiers.
m_screen->updateKeyState();
2012-06-10 16:50:54 +00:00
}
void Screen::leaveSecondary() {
// release any keys we think are still down
m_screen->fakeAllKeysUp();
SYNERGY-1032 - Use native notifications for secure input on MacOS (#7041) * SYNERGY-1017 - Try usnig NSUserNotification * SYNERGY-1032 - Use UNUserNotificationCenter instead of deprecated notifications * SYNERGY-1032 - Update app delegate and add log after notification access * SYNERGY-1032 - Try using deprecated notification * SYNERGY-1032 - Add notifications to the platform dependant code * SYNERGY-1032 - Check for development builds before asking permission for notifications * SYNERGY-1032 - Remove old notification and secure input detection * SYNERGY-1032 - Add permission request to the main app * SYNERGY-1032 - Only show notifications on server * SYNERGY-1032 - Request and show notification from main app * SYNERGY-1032 - Remove logging from OSX helpers * SYNERGY-1032 - Add UN notification for testing * SYNERGY-1032 - Show notification once * SYNERGY-1032 - Try replicating old flow * SYNERGY-1032 - Reuse notification center * SYNERGY-1032 - Send notification after granting permission * SYNERGY-1032 - Update app delegate * SYNERGY-1032 - Remove deprecated property * SYNERGY-1032 - Add output for debugging * SYNERGY-1032 - Try updating delegate * SYNERGY-1032 - Print current bundle name * SYNERGY-1032 - Add AppDelegate to the server * SYNERGY-1032 - Move notification creation to synergy app * SYNERGY-1032 - Update notification text * SYNERGY-1032 - Fix QString conversion for notification * SYNERGY-1032 - Move notification creation outside the handler * SYNERGY-1032 - Remove debug notification, show notification with no delay * SYNERGY-1032 - Show notification inside the completion handler * SYNERGY-1032 - Remove timed notification trigger * SYNERGY-1032 - Request permissions on synergy start * SYNERGY-1032 - Remove unused includes * SYNERGY-1032 - Update changelog * SYNERGY-1032 - Add empty notification implementations for Windows and Linux * SYNERGY-1032 - Removed temporary debug messages * SYNERGY-1032 - Resolve code smell
2021-06-29 10:20:56 +00:00
}
String Screen::getSecureInputApp() const {
return m_screen->getSecureInputApp();
}
} // namespace synergy