aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/server/Server.h
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2018-04-25 18:07:30 -0400
committerLibravatarUnit 193 <unit193@ubuntu.com>2018-04-25 18:07:30 -0400
commit9b1b081cfdb1c0fb6457278775e0823f8bc10f62 (patch)
treece8840148d8445055ba9e4f12263b2208f234c16 /src/lib/server/Server.h
Import Upstream version 2.0.0+dfsgupstream/2.0.0+dfsg
Diffstat (limited to 'src/lib/server/Server.h')
-rw-r--r--src/lib/server/Server.h483
1 files changed, 483 insertions, 0 deletions
diff --git a/src/lib/server/Server.h b/src/lib/server/Server.h
new file mode 100644
index 0000000..609af21
--- /dev/null
+++ b/src/lib/server/Server.h
@@ -0,0 +1,483 @@
+/*
+ * barrier -- mouse and keyboard sharing utility
+ * Copyright (C) 2012-2016 Symless Ltd.
+ * Copyright (C) 2002 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/>.
+ */
+
+#pragma once
+
+#include "server/Config.h"
+#include "barrier/clipboard_types.h"
+#include "barrier/Clipboard.h"
+#include "barrier/key_types.h"
+#include "barrier/mouse_types.h"
+#include "barrier/INode.h"
+#include "barrier/DragInformation.h"
+#include "barrier/ServerArgs.h"
+#include "base/Event.h"
+#include "base/Stopwatch.h"
+#include "base/EventTypes.h"
+#include "common/stdmap.h"
+#include "common/stdset.h"
+#include "common/stdvector.h"
+
+class BaseClientProxy;
+class EventQueueTimer;
+class PrimaryClient;
+class InputFilter;
+namespace barrier { class Screen; }
+class IEventQueue;
+class Thread;
+class ClientListener;
+
+//! Barrier server
+/*!
+This class implements the top-level server algorithms for barrier.
+*/
+class Server : public INode {
+public:
+ //! Lock cursor to screen data
+ class LockCursorToScreenInfo {
+ public:
+ enum State { kOff, kOn, kToggle };
+
+ static LockCursorToScreenInfo* alloc(State state = kToggle);
+
+ public:
+ State m_state;
+ };
+
+ //! Switch to screen data
+ class SwitchToScreenInfo {
+ public:
+ static SwitchToScreenInfo* alloc(const String& screen);
+
+ public:
+ // this is a C-string; this type is a variable size structure
+ char m_screen[1];
+ };
+
+ //! Switch in direction data
+ class SwitchInDirectionInfo {
+ public:
+ static SwitchInDirectionInfo* alloc(EDirection direction);
+
+ public:
+ EDirection m_direction;
+ };
+
+ //! Screen connected data
+ class ScreenConnectedInfo {
+ public:
+ ScreenConnectedInfo(String screen) : m_screen(screen) { }
+
+ public:
+ String m_screen; // was char[1]
+ };
+
+ //! Keyboard broadcast data
+ class KeyboardBroadcastInfo {
+ public:
+ enum State { kOff, kOn, kToggle };
+
+ static KeyboardBroadcastInfo* alloc(State state = kToggle);
+ static KeyboardBroadcastInfo* alloc(State state,
+ const String& screens);
+
+ public:
+ State m_state;
+ char m_screens[1];
+ };
+
+ /*!
+ Start the server with the configuration \p config and the primary
+ client (local screen) \p primaryClient. The client retains
+ ownership of \p primaryClient.
+ */
+ Server(Config& config, PrimaryClient* primaryClient,
+ barrier::Screen* screen, IEventQueue* events, ServerArgs const& args);
+ ~Server();
+
+#ifdef TEST_ENV
+ Server() : m_mock(true), m_config(NULL) { }
+ void setActive(BaseClientProxy* active) { m_active = active; }
+#endif
+
+ //! @name manipulators
+ //@{
+
+ //! Set configuration
+ /*!
+ Change the server's configuration. Returns true iff the new
+ configuration was accepted (it must include the server's name).
+ This will disconnect any clients no longer in the configuration.
+ */
+ bool setConfig(const Config&);
+
+ //! Add a client
+ /*!
+ Adds \p client to the server. The client is adopted and will be
+ destroyed when the client disconnects or is disconnected.
+ */
+ void adoptClient(BaseClientProxy* client);
+
+ //! Disconnect clients
+ /*!
+ Disconnect clients. This tells them to disconnect but does not wait
+ for them to actually do so. The server sends the disconnected event
+ when they're all disconnected (or immediately if none are connected).
+ The caller can also just destroy this object to force the disconnection.
+ */
+ void disconnect();
+
+ //! Create a new thread and use it to send file to client
+ void sendFileToClient(const char* filename);
+
+ //! Received dragging information from client
+ void dragInfoReceived(UInt32 fileNum, String content);
+
+ //! Store ClientListener pointer
+ void setListener(ClientListener* p) { m_clientListener = p; }
+
+ //@}
+ //! @name accessors
+ //@{
+
+ //! Get number of connected clients
+ /*!
+ Returns the number of connected clients, including the server itself.
+ */
+ UInt32 getNumClients() const;
+
+ //! Get the list of connected clients
+ /*!
+ Set the \c list to the names of the currently connected clients.
+ */
+ void getClients(std::vector<String>& list) const;
+
+ //! Return true if recieved file size is valid
+ bool isReceivedFileSizeValid();
+
+ //! Return expected file data size
+ size_t& getExpectedFileSize() { return m_expectedFileSize; }
+
+ //! Return received file data
+ String& getReceivedFileData() { return m_receivedFileData; }
+
+ //! Return fake drag file list
+ DragFileList getFakeDragFileList() { return m_fakeDragFileList; }
+
+ //@}
+
+private:
+ // get canonical name of client
+ String getName(const BaseClientProxy*) const;
+
+ // get the sides of the primary screen that have neighbors
+ UInt32 getActivePrimarySides() const;
+
+ // returns true iff mouse should be locked to the current screen
+ // according to this object only, ignoring what the primary client
+ // says.
+ bool isLockedToScreenServer() const;
+
+ // returns true iff mouse should be locked to the current screen
+ // according to this object or the primary client.
+ bool isLockedToScreen() const;
+
+ // returns the jump zone of the client
+ SInt32 getJumpZoneSize(BaseClientProxy*) const;
+
+ // change the active screen
+ void switchScreen(BaseClientProxy*,
+ SInt32 x, SInt32 y, bool forScreenSaver);
+
+ // jump to screen
+ void jumpToScreen(BaseClientProxy*);
+
+ // convert pixel position to fraction, using x or y depending on the
+ // direction.
+ float mapToFraction(BaseClientProxy*, EDirection,
+ SInt32 x, SInt32 y) const;
+
+ // convert fraction to pixel position, writing only x or y depending
+ // on the direction.
+ void mapToPixel(BaseClientProxy*, EDirection, float f,
+ SInt32& x, SInt32& y) const;
+
+ // returns true if the client has a neighbor anywhere along the edge
+ // indicated by the direction.
+ bool hasAnyNeighbor(BaseClientProxy*, EDirection) const;
+
+ // lookup neighboring screen, mapping the coordinate independent of
+ // the direction to the neighbor's coordinate space.
+ BaseClientProxy* getNeighbor(BaseClientProxy*, EDirection,
+ SInt32& x, SInt32& y) const;
+
+ // lookup neighboring screen. given a position relative to the
+ // source screen, find the screen we should move onto and where.
+ // if the position is sufficiently far from the source then we
+ // cross multiple screens. if there is no suitable screen then
+ // return NULL and x,y are not modified.
+ BaseClientProxy* mapToNeighbor(BaseClientProxy*, EDirection,
+ SInt32& x, SInt32& y) const;
+
+ // adjusts x and y or neither to avoid ending up in a jump zone
+ // after entering the client in the given direction.
+ void avoidJumpZone(BaseClientProxy*, EDirection,
+ SInt32& x, SInt32& y) const;
+
+ // test if a switch is permitted. this includes testing user
+ // options like switch delay and tracking any state required to
+ // implement them. returns true iff a switch is permitted.
+ bool isSwitchOkay(BaseClientProxy* dst, EDirection,
+ SInt32 x, SInt32 y, SInt32 xActive, SInt32 yActive);
+
+ // update switch state due to a mouse move at \p x, \p y that
+ // doesn't switch screens.
+ void noSwitch(SInt32 x, SInt32 y);
+
+ // stop switch timers
+ void stopSwitch();
+
+ // start two tap switch timer
+ void startSwitchTwoTap();
+
+ // arm the two tap switch timer if \p x, \p y is outside the tap zone
+ void armSwitchTwoTap(SInt32 x, SInt32 y);
+
+ // stop the two tap switch timer
+ void stopSwitchTwoTap();
+
+ // returns true iff the two tap switch timer is started
+ bool isSwitchTwoTapStarted() const;
+
+ // returns true iff should switch because of two tap
+ bool shouldSwitchTwoTap() const;
+
+ // start delay switch timer
+ void startSwitchWait(SInt32 x, SInt32 y);
+
+ // stop delay switch timer
+ void stopSwitchWait();
+
+ // returns true iff the delay switch timer is started
+ bool isSwitchWaitStarted() const;
+
+ // returns the corner (EScreenSwitchCornerMasks) where x,y is on the
+ // given client. corners have the given size.
+ UInt32 getCorner(BaseClientProxy*,
+ SInt32 x, SInt32 y, SInt32 size) const;
+
+ // stop relative mouse moves
+ void stopRelativeMoves();
+
+ // send screen options to \c client
+ void sendOptions(BaseClientProxy* client) const;
+
+ // process options from configuration
+ void processOptions();
+
+ // event handlers
+ void handleShapeChanged(const Event&, void*);
+ void handleClipboardGrabbed(const Event&, void*);
+ void handleClipboardChanged(const Event&, void*);
+ void handleKeyDownEvent(const Event&, void*);
+ void handleKeyUpEvent(const Event&, void*);
+ void handleKeyRepeatEvent(const Event&, void*);
+ void handleButtonDownEvent(const Event&, void*);
+ void handleButtonUpEvent(const Event&, void*);
+ void handleMotionPrimaryEvent(const Event&, void*);
+ void handleMotionSecondaryEvent(const Event&, void*);
+ void handleWheelEvent(const Event&, void*);
+ void handleScreensaverActivatedEvent(const Event&, void*);
+ void handleScreensaverDeactivatedEvent(const Event&, void*);
+ void handleSwitchWaitTimeout(const Event&, void*);
+ void handleClientDisconnected(const Event&, void*);
+ void handleClientCloseTimeout(const Event&, void*);
+ void handleSwitchToScreenEvent(const Event&, void*);
+ void handleSwitchInDirectionEvent(const Event&, void*);
+ void handleKeyboardBroadcastEvent(const Event&,void*);
+ void handleLockCursorToScreenEvent(const Event&, void*);
+ void handleFakeInputBeginEvent(const Event&, void*);
+ void handleFakeInputEndEvent(const Event&, void*);
+ void handleFileChunkSendingEvent(const Event&, void*);
+ void handleFileRecieveCompletedEvent(const Event&, void*);
+
+ // event processing
+ void onClipboardChanged(BaseClientProxy* sender,
+ ClipboardID id, UInt32 seqNum);
+ void onScreensaver(bool activated);
+ void onKeyDown(KeyID, KeyModifierMask, KeyButton,
+ const char* screens);
+ void onKeyUp(KeyID, KeyModifierMask, KeyButton,
+ const char* screens);
+ void onKeyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton);
+ void onMouseDown(ButtonID);
+ void onMouseUp(ButtonID);
+ bool onMouseMovePrimary(SInt32 x, SInt32 y);
+ void onMouseMoveSecondary(SInt32 dx, SInt32 dy);
+ void onMouseWheel(SInt32 xDelta, SInt32 yDelta);
+ void onFileChunkSending(const void* data);
+ void onFileRecieveCompleted();
+
+ // add client to list and attach event handlers for client
+ bool addClient(BaseClientProxy*);
+
+ // remove client from list and detach event handlers for client
+ bool removeClient(BaseClientProxy*);
+
+ // close a client
+ void closeClient(BaseClientProxy*, const char* msg);
+
+ // close clients not in \p config
+ void closeClients(const Config& config);
+
+ // close all clients whether they've completed the handshake or not,
+ // except the primary client
+ void closeAllClients();
+
+ // remove clients from internal state
+ void removeActiveClient(BaseClientProxy*);
+ void removeOldClient(BaseClientProxy*);
+
+ // force the cursor off of \p client
+ void forceLeaveClient(BaseClientProxy* client);
+
+ // thread funciton for sending file
+ void sendFileThread(void*);
+
+ // thread function for writing file to drop directory
+ void writeToDropDirThread(void*);
+
+ // thread function for sending drag information
+ void sendDragInfoThread(void*);
+
+ // send drag info to new client screen
+ void sendDragInfo(BaseClientProxy* newScreen);
+
+public:
+ bool m_mock;
+
+private:
+ class ClipboardInfo {
+ public:
+ ClipboardInfo();
+
+ public:
+ Clipboard m_clipboard;
+ String m_clipboardData;
+ String m_clipboardOwner;
+ UInt32 m_clipboardSeqNum;
+ };
+
+ // the primary screen client
+ PrimaryClient* m_primaryClient;
+
+ // all clients (including the primary client) indexed by name
+ typedef std::map<String, BaseClientProxy*> ClientList;
+ typedef std::set<BaseClientProxy*> ClientSet;
+ ClientList m_clients;
+ ClientSet m_clientSet;
+
+ // all old connections that we're waiting to hangup
+ typedef std::map<BaseClientProxy*, EventQueueTimer*> OldClients;
+ OldClients m_oldClients;
+
+ // the client with focus
+ BaseClientProxy* m_active;
+
+ // the sequence number of enter messages
+ UInt32 m_seqNum;
+
+ // current mouse position (in absolute screen coordinates) on
+ // whichever screen is active
+ SInt32 m_x, m_y;
+
+ // last mouse deltas. this is needed to smooth out double tap
+ // on win32 which reports bogus mouse motion at the edge of
+ // the screen when using low level hooks, synthesizing motion
+ // in the opposite direction the mouse actually moved.
+ SInt32 m_xDelta, m_yDelta;
+ SInt32 m_xDelta2, m_yDelta2;
+
+ // current configuration
+ Config* m_config;
+
+ // input filter (from m_config);
+ InputFilter* m_inputFilter;
+
+ // clipboard cache
+ ClipboardInfo m_clipboards[kClipboardEnd];
+
+ // state saved when screen saver activates
+ BaseClientProxy* m_activeSaver;
+ SInt32 m_xSaver, m_ySaver;
+
+ // common state for screen switch tests. all tests are always
+ // trying to reach the same screen in the same direction.
+ EDirection m_switchDir;
+ BaseClientProxy* m_switchScreen;
+
+ // state for delayed screen switching
+ double m_switchWaitDelay;
+ EventQueueTimer* m_switchWaitTimer;
+ SInt32 m_switchWaitX, m_switchWaitY;
+
+ // state for double-tap screen switching
+ double m_switchTwoTapDelay;
+ Stopwatch m_switchTwoTapTimer;
+ bool m_switchTwoTapEngaged;
+ bool m_switchTwoTapArmed;
+ SInt32 m_switchTwoTapZone;
+
+ // modifiers needed before switching
+ bool m_switchNeedsShift;
+ bool m_switchNeedsControl;
+ bool m_switchNeedsAlt;
+
+ // relative mouse move option
+ bool m_relativeMoves;
+
+ // flag whether or not we have broadcasting enabled and the screens to
+ // which we should send broadcasted keys.
+ bool m_keyboardBroadcasting;
+ String m_keyboardBroadcastingScreens;
+
+ // screen locking (former scroll lock)
+ bool m_lockedToScreen;
+
+ // server screen
+ barrier::Screen* m_screen;
+
+ IEventQueue* m_events;
+
+ // file transfer
+ size_t m_expectedFileSize;
+ String m_receivedFileData;
+ DragFileList m_dragFileList;
+ DragFileList m_fakeDragFileList;
+ Thread* m_sendFileThread;
+ Thread* m_writeToDropDirThread;
+ String m_dragFileExt;
+ bool m_ignoreFileTransfer;
+ bool m_enableClipboard;
+
+ Thread* m_sendDragInfoThread;
+ bool m_waitDragInfoThread;
+
+ ClientListener* m_clientListener;
+ ServerArgs m_args;
+};