312 lines
6.4 KiB
C++
312 lines
6.4 KiB
C++
/*
|
|
* synergy -- mouse and keyboard sharing utility
|
|
* 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 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.
|
|
*/
|
|
|
|
#ifndef CXWINDOWSSCREEN_H
|
|
#define CXWINDOWSSCREEN_H
|
|
|
|
#include "IScreen.h"
|
|
#include "CMutex.h"
|
|
#include "CStopwatch.h"
|
|
#include "stdvector.h"
|
|
#if defined(X_DISPLAY_MISSING)
|
|
# error X11 is required to build synergy
|
|
#else
|
|
# include <X11/Xlib.h>
|
|
#endif
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
class IJob;
|
|
class IScreenEventHandler;
|
|
class IScreenReceiver;
|
|
class CXWindowsClipboard;
|
|
class CXWindowsScreenSaver;
|
|
|
|
/*!
|
|
\class CEvent
|
|
\brief User event data
|
|
An architecture dependent type holding user event data.
|
|
*/
|
|
// X11 event
|
|
class CEvent {
|
|
public:
|
|
XEvent m_event;
|
|
SInt32 m_result;
|
|
};
|
|
|
|
//! Implementation of IScreen for X11
|
|
class CXWindowsScreen : public IScreen {
|
|
public:
|
|
CXWindowsScreen(IScreenReceiver*, IScreenEventHandler*);
|
|
virtual ~CXWindowsScreen();
|
|
|
|
//! @name manipulators
|
|
//@{
|
|
|
|
//! Add timer
|
|
/*!
|
|
Add a job to invoke every timeout seconds. The job is
|
|
called with the display locked. If a job timeout expires twice
|
|
or more before the job can be called then the job is called
|
|
just once. The caller retains ownership of the job.
|
|
*/
|
|
void addTimer(IJob*, double timeout);
|
|
|
|
//! Remove timer
|
|
/*!
|
|
Remove a job. The caller retains ownership of the job.
|
|
*/
|
|
void removeTimer(IJob*);
|
|
|
|
//! Install a one-shot timer
|
|
/*!
|
|
Installs a one-shot timer for \c timeout seconds and returns the
|
|
id of the timer (which will be passed to the receiver's
|
|
\c onTimerExpired()).
|
|
*/
|
|
UInt32 addOneShotTimer(double timeout);
|
|
|
|
//! Set window
|
|
/*!
|
|
Set the window (created by the subclass). This performs some
|
|
initialization and saves the window in case it's needed later.
|
|
*/
|
|
void setWindow(Window);
|
|
|
|
//@}
|
|
//! @name accessors
|
|
//@{
|
|
|
|
//! Get window
|
|
/*!
|
|
Returns the root window of the screen.
|
|
*/
|
|
Window getRoot() const;
|
|
|
|
//! Get transparent cursor
|
|
/*!
|
|
Returns a cursor that is transparent everywhere.
|
|
*/
|
|
Cursor getBlankCursor() const;
|
|
|
|
//@}
|
|
|
|
// IScreen overrides
|
|
void open();
|
|
void mainLoop();
|
|
void exitMainLoop();
|
|
void close();
|
|
bool setClipboard(ClipboardID, const IClipboard*);
|
|
void checkClipboards();
|
|
void openScreensaver(bool notify);
|
|
void closeScreensaver();
|
|
void screensaver(bool activate);
|
|
void syncDesktop();
|
|
bool getClipboard(ClipboardID, IClipboard*) const;
|
|
void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
|
void getCursorPos(SInt32&, SInt32&) const;
|
|
void getCursorCenter(SInt32&, SInt32&) const;
|
|
|
|
private:
|
|
// update screen size cache
|
|
void updateScreenShape();
|
|
|
|
// process events before dispatching to receiver
|
|
bool onPreDispatch(CEvent* event);
|
|
|
|
// create the transparent cursor
|
|
void createBlankCursor();
|
|
|
|
// remove a timer without locking
|
|
void removeTimerNoLock(IJob*);
|
|
|
|
// process timers
|
|
bool processTimers();
|
|
|
|
// determine the clipboard from the X selection. returns
|
|
// kClipboardEnd if no such clipboard.
|
|
ClipboardID getClipboardID(Atom selection) const;
|
|
|
|
// continue processing a selection request
|
|
void processClipboardRequest(Window window,
|
|
Time time, Atom property);
|
|
|
|
// terminate a selection request
|
|
void destroyClipboardRequest(Window window);
|
|
|
|
// X I/O error handler
|
|
static int ioErrorHandler(Display*);
|
|
|
|
private:
|
|
// a priority queue will direct access to the elements
|
|
template <class T, class Container = std::vector<T>,
|
|
class Compare = std::greater<typename Container::value_type> >
|
|
class CPriorityQueue {
|
|
public:
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::size_type size_type;
|
|
typedef typename Container::iterator iterator;
|
|
typedef Container container_type;
|
|
|
|
CPriorityQueue() { }
|
|
CPriorityQueue(Container& swappedIn);
|
|
~CPriorityQueue() { }
|
|
|
|
// manipulators
|
|
|
|
void push(const value_type& v)
|
|
{
|
|
c.push_back(v);
|
|
std::push_heap(c.begin(), c.end(), comp);
|
|
}
|
|
|
|
void pop()
|
|
{
|
|
std::pop_heap(c.begin(), c.end(), comp);
|
|
c.pop_back();
|
|
}
|
|
|
|
iterator begin()
|
|
{
|
|
return c.begin();
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return c.end();
|
|
}
|
|
|
|
void swap(CPriorityQueue<T, Container, Compare>& q)
|
|
{
|
|
c.swap(q.c);
|
|
}
|
|
|
|
void swap(Container& c2)
|
|
{
|
|
c.swap(c2);
|
|
std::make_heap(c.begin(), c.end(), comp);
|
|
}
|
|
|
|
// accessors
|
|
|
|
bool empty() const
|
|
{
|
|
return c.empty();
|
|
}
|
|
|
|
size_type size() const
|
|
{
|
|
return c.size();
|
|
}
|
|
|
|
const value_type&
|
|
top() const
|
|
{
|
|
return c.front();
|
|
}
|
|
|
|
private:
|
|
Container c;
|
|
Compare comp;
|
|
};
|
|
|
|
// a timer priority queue element
|
|
class CTimer {
|
|
public:
|
|
CTimer(IJob* job, double startTime, double resetTime);
|
|
~CTimer();
|
|
|
|
// manipulators
|
|
|
|
void run();
|
|
|
|
void reset();
|
|
|
|
CTimer& operator-=(double);
|
|
|
|
// accessors
|
|
|
|
IJob* getJob() const
|
|
{
|
|
return m_job;
|
|
}
|
|
|
|
operator double() const;
|
|
|
|
bool operator<(const CTimer&) const;
|
|
|
|
private:
|
|
IJob* m_job;
|
|
double m_timeout;
|
|
double m_time;
|
|
double m_startTime;
|
|
};
|
|
|
|
private:
|
|
friend class CDisplayLock;
|
|
|
|
typedef CPriorityQueue<CTimer> CTimerPriorityQueue;
|
|
|
|
// X is not thread safe
|
|
CMutex m_mutex;
|
|
|
|
Display* m_display;
|
|
Window m_root;
|
|
bool m_stop;
|
|
|
|
IScreenReceiver* m_receiver;
|
|
IScreenEventHandler* m_eventHandler;
|
|
Window m_window;
|
|
|
|
SInt32 m_x, m_y;
|
|
SInt32 m_w, m_h;
|
|
SInt32 m_xCenter, m_yCenter;
|
|
|
|
// clipboards
|
|
CXWindowsClipboard* m_clipboard[kClipboardEnd];
|
|
|
|
// the transparent cursor
|
|
Cursor m_cursor;
|
|
|
|
// screen saver stuff
|
|
CXWindowsScreenSaver* m_screensaver;
|
|
bool m_screensaverNotify;
|
|
Atom m_atomScreensaver;
|
|
|
|
// timers, the stopwatch used to time, and a mutex for the timers
|
|
CTimerPriorityQueue m_timers;
|
|
CStopwatch m_time;
|
|
CMutex m_timersMutex;
|
|
CTimer* m_oneShotTimer;
|
|
|
|
// pointer to (singleton) screen. this is only needed by
|
|
// ioErrorHandler().
|
|
static CXWindowsScreen* s_screen;
|
|
};
|
|
|
|
//! Convenience object to lock/unlock a CXWindowsScreen
|
|
class CDisplayLock {
|
|
public:
|
|
CDisplayLock(const CXWindowsScreen*);
|
|
~CDisplayLock();
|
|
|
|
operator Display*() const;
|
|
|
|
private:
|
|
const CMutex* m_mutex;
|
|
Display* m_display;
|
|
};
|
|
|
|
#endif
|