aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/barrier/Screen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/barrier/Screen.cpp')
-rw-r--r--src/lib/barrier/Screen.cpp559
1 files changed, 559 insertions, 0 deletions
diff --git a/src/lib/barrier/Screen.cpp b/src/lib/barrier/Screen.cpp
new file mode 100644
index 0000000..32442f6
--- /dev/null
+++ b/src/lib/barrier/Screen.cpp
@@ -0,0 +1,559 @@
+/*
+ * barrier -- mouse and keyboard sharing utility
+ * Copyright (C) 2012-2016 Symless Ltd.
+ * Copyright (C) 2003 Chris Schoeneman
+ *
+ * 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.
+ *
+ * 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 "barrier/Screen.h"
+#include "barrier/IPlatformScreen.h"
+#include "barrier/protocol_types.h"
+#include "base/Log.h"
+#include "base/IEventQueue.h"
+#include "server/ClientProxy.h"
+#include "base/TMethodEventJob.h"
+
+namespace barrier {
+
+//
+// Screen
+//
+
+Screen::Screen(IPlatformScreen* platformScreen, IEventQueue* events) :
+ m_screen(platformScreen),
+ m_isPrimary(platformScreen->isPrimary()),
+ m_enabled(false),
+ m_entered(m_isPrimary),
+ m_screenSaverSync(true),
+ m_fakeInput(false),
+ m_events(events),
+ m_mock(false),
+ m_enableDragDrop(false)
+{
+ assert(m_screen != NULL);
+
+ // reset options
+ resetOptions();
+
+ LOG((CLOG_DEBUG "opened display"));
+}
+
+Screen::~Screen()
+{
+ if (m_mock) {
+ return;
+ }
+
+ if (m_enabled) {
+ disable();
+ }
+ assert(!m_enabled);
+ assert(m_entered == m_isPrimary);
+ delete m_screen;
+ LOG((CLOG_DEBUG "closed display"));
+}
+
+void
+Screen::enable()
+{
+ assert(!m_enabled);
+
+ m_screen->updateKeyMap();
+ m_screen->updateKeyState();
+ m_screen->enable();
+ if (m_isPrimary) {
+ enablePrimary();
+ }
+ else {
+ enableSecondary();
+ }
+
+ // note activation
+ m_enabled = true;
+}
+
+void
+Screen::disable()
+{
+ assert(m_enabled);
+
+ if (!m_isPrimary && m_entered) {
+ leave();
+ }
+ else if (m_isPrimary && !m_entered) {
+ enter(0);
+ }
+ m_screen->disable();
+ if (m_isPrimary) {
+ disablePrimary();
+ }
+ else {
+ disableSecondary();
+ }
+
+ // note deactivation
+ m_enabled = false;
+}
+
+void
+Screen::enter(KeyModifierMask toggleMask)
+{
+ assert(m_entered == false);
+ LOG((CLOG_INFO "entering screen"));
+
+ // now on screen
+ m_entered = true;
+
+ m_screen->enter();
+ if (m_isPrimary) {
+ enterPrimary();
+ }
+ else {
+ enterSecondary(toggleMask);
+ }
+}
+
+bool
+Screen::leave()
+{
+ assert(m_entered == true);
+ LOG((CLOG_INFO "leaving screen"));
+
+ if (!m_screen->leave()) {
+ return false;
+ }
+ if (m_isPrimary) {
+ leavePrimary();
+ }
+ else {
+ leaveSecondary();
+ }
+
+ // make sure our idea of clipboard ownership is correct
+ m_screen->checkClipboards();
+
+ // now not on screen
+ m_entered = false;
+
+ return true;
+}
+
+void
+Screen::reconfigure(UInt32 activeSides)
+{
+ assert(m_isPrimary);
+ m_screen->reconfigure(activeSides);
+}
+
+void
+Screen::warpCursor(SInt32 x, SInt32 y)
+{
+ assert(m_isPrimary);
+ m_screen->warpCursor(x, y);
+}
+
+void
+Screen::setClipboard(ClipboardID id, const IClipboard* clipboard)
+{
+ m_screen->setClipboard(id, clipboard);
+}
+
+void
+Screen::grabClipboard(ClipboardID id)
+{
+ m_screen->setClipboard(id, NULL);
+}
+
+void
+Screen::screensaver(bool activate)
+{
+ if (!m_isPrimary) {
+ // activate/deactivation screen saver iff synchronization enabled
+ if (m_screenSaverSync) {
+ m_screen->screensaver(activate);
+ }
+ }
+}
+
+void
+Screen::keyDown(KeyID id, KeyModifierMask mask, KeyButton button)
+{
+ // 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);
+}
+
+void
+Screen::keyRepeat(KeyID id,
+ KeyModifierMask mask, SInt32 count, KeyButton button)
+{
+ assert(!m_isPrimary);
+ m_screen->fakeKeyRepeat(id, mask, count, button);
+}
+
+void
+Screen::keyUp(KeyID, KeyModifierMask, KeyButton button)
+{
+ m_screen->fakeKeyUp(button);
+}
+
+void
+Screen::mouseDown(ButtonID button)
+{
+ m_screen->fakeMouseButton(button, true);
+}
+
+void
+Screen::mouseUp(ButtonID button)
+{
+ m_screen->fakeMouseButton(button, false);
+}
+
+void
+Screen::mouseMove(SInt32 x, SInt32 y)
+{
+ assert(!m_isPrimary);
+ m_screen->fakeMouseMove(x, y);
+}
+
+void
+Screen::mouseRelativeMove(SInt32 dx, SInt32 dy)
+{
+ assert(!m_isPrimary);
+ m_screen->fakeMouseRelativeMove(dx, dy);
+}
+
+void
+Screen::mouseWheel(SInt32 xDelta, SInt32 yDelta)
+{
+ assert(!m_isPrimary);
+ m_screen->fakeMouseWheel(xDelta, yDelta);
+}
+
+void
+Screen::resetOptions()
+{
+ // reset options
+ m_halfDuplex = 0;
+
+ // if screen saver synchronization was off then turn it on since
+ // that's the default option state.
+ if (!m_screenSaverSync) {
+ m_screenSaverSync = true;
+ if (!m_isPrimary) {
+ m_screen->openScreensaver(false);
+ }
+ }
+
+ // let screen handle its own options
+ m_screen->resetOptions();
+}
+
+void
+Screen::setOptions(const OptionsList& options)
+{
+ // update options
+ bool oldScreenSaverSync = m_screenSaverSync;
+ for (UInt32 i = 0, n = (UInt32)options.size(); i < n; i += 2) {
+ if (options[i] == kOptionScreenSaverSync) {
+ m_screenSaverSync = (options[i + 1] != 0);
+ LOG((CLOG_DEBUG1 "screen saver synchronization %s", m_screenSaverSync ? "on" : "off"));
+ }
+ else 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);
+
+ // update screen saver synchronization
+ if (!m_isPrimary && oldScreenSaverSync != m_screenSaverSync) {
+ if (m_screenSaverSync) {
+ m_screen->openScreensaver(false);
+ }
+ else {
+ m_screen->closeScreensaver();
+ }
+ }
+
+ // let screen handle its own options
+ m_screen->setOptions(options);
+}
+
+void
+Screen::setSequenceNumber(UInt32 seqNum)
+{
+ m_screen->setSequenceNumber(seqNum);
+}
+
+UInt32
+Screen::registerHotKey(KeyID key, KeyModifierMask mask)
+{
+ return m_screen->registerHotKey(key, mask);
+}
+
+void
+Screen::unregisterHotKey(UInt32 id)
+{
+ m_screen->unregisterHotKey(id);
+}
+
+void
+Screen::fakeInputBegin()
+{
+ assert(!m_fakeInput);
+
+ m_fakeInput = true;
+ m_screen->fakeInputBegin();
+}
+
+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);
+}
+
+void
+Screen::setEnableDragDrop(bool enabled)
+{
+ m_enableDragDrop = enabled;
+}
+
+String&
+Screen::getDraggingFilename() const
+{
+ return m_screen->getDraggingFilename();
+}
+
+void
+Screen::clearDraggingFilename()
+{
+ m_screen->clearDraggingFilename();
+}
+
+const String&
+Screen::getDropTarget() const
+{
+ return m_screen->getDropTarget();
+}
+
+void*
+Screen::getEventTarget() const
+{
+ return m_screen;
+}
+
+bool
+Screen::getClipboard(ClipboardID id, IClipboard* clipboard) const
+{
+ return m_screen->getClipboard(id, clipboard);
+}
+
+void
+Screen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
+{
+ m_screen->getShape(x, y, w, h);
+}
+
+void
+Screen::getCursorPos(SInt32& x, SInt32& y) const
+{
+ m_screen->getCursorPos(x, y);
+}
+
+void
+Screen::enablePrimary()
+{
+ // get notified of screen saver activation/deactivation
+ m_screen->openScreensaver(true);
+
+ // claim screen changed size
+ m_events->addEvent(Event(m_events->forIScreen().shapeChanged(), getEventTarget()));
+}
+
+void
+Screen::enableSecondary()
+{
+ // assume primary has all clipboards
+ for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
+ grabClipboard(id);
+ }
+
+ // disable the screen saver if synchronization is enabled
+ if (m_screenSaverSync) {
+ m_screen->openScreensaver(false);
+ }
+}
+
+void
+Screen::disablePrimary()
+{
+ // done with screen saver
+ m_screen->closeScreensaver();
+}
+
+void
+Screen::disableSecondary()
+{
+ // done with screen saver
+ m_screen->closeScreensaver();
+}
+
+void
+Screen::enterPrimary()
+{
+ // do nothing
+}
+
+void
+Screen::enterSecondary(KeyModifierMask)
+{
+ // do nothing
+}
+
+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();
+}
+
+void
+Screen::leaveSecondary()
+{
+ // release any keys we think are still down
+ m_screen->fakeAllKeysUp();
+}
+
+}