barrier/platform/CXWindowsScreen.h
2002-07-12 20:41:23 +00:00

290 lines
6.4 KiB
C++

#ifndef CXWINDOWSSCREEN_H
#define CXWINDOWSSCREEN_H
#include "ClipboardTypes.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 IClipboard;
class IJob;
class IScreenSaver;
class CXWindowsClipboard;
class CXWindowsScreenSaver;
class CEvent {
public:
XEvent m_event;
SInt32 m_result;
};
class CXWindowsScreen {
public:
CXWindowsScreen();
virtual ~CXWindowsScreen();
// manipulators
// add/remove 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);
void removeTimer(IJob*);
protected:
class CDisplayLock {
public:
CDisplayLock(const CXWindowsScreen*);
~CDisplayLock();
operator Display*() const;
private:
const CMutex* m_mutex;
Display* m_display;
};
friend class CDisplayLock;
// runs an event loop and returns when exitMainLoop() is called
void mainLoop();
// force mainLoop() to return
void exitMainLoop();
// open the X display. calls onOpenDisplay() after opening the display,
// getting the screen, its size, and root window. then it starts the
// event thread.
void openDisplay();
// destroy the window and close the display. calls onCloseDisplay()
// after the event thread has been shut down but before the display
// is closed.
void closeDisplay();
// get the Display*. only use this when you know the display is
// locked but don't have the CDisplayLock available.
Display* getDisplay() const;
// get the opened screen and its root window. to get the display
// create a CDisplayLock object passing this. while the object
// exists no other threads may access the display. do not save
// the Display* beyond the lifetime of the CDisplayLock.
int getScreen() const;
Window getRoot() const;
// initialize the clipboards
void initClipboards(Window);
// update screen size cache
void updateScreenShape();
// get the shape of the screen
void getScreenShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const;
// get the current cursor position
void getCursorPos(SInt32& x, SInt32& y) const;
// get the cursor center position
void getCursorCenter(SInt32& x, SInt32& y) const;
// get a cursor that is transparent everywhere
Cursor getBlankCursor() const;
// set the contents of the clipboard (i.e. primary selection)
bool setDisplayClipboard(ClipboardID,
const IClipboard* clipboard);
// copy the clipboard contents to clipboard
bool getDisplayClipboard(ClipboardID,
IClipboard* clipboard) const;
// get the screen saver object
CXWindowsScreenSaver*
getScreenSaver() const;
// called for each event before event translation and dispatch. return
// true to skip translation and dispatch. subclasses should call the
// superclass's version first and return true if it returns true.
virtual bool onPreDispatch(const CEvent* event) = 0;
// called by mainLoop(). iff the event was handled return true and
// store the result, if any, in m_result, which defaults to zero.
virtual bool onEvent(CEvent* event) = 0;
// called if the display is unexpectedly closing. default does nothing.
virtual void onUnexpectedClose();
// called when a clipboard is lost
virtual void onLostClipboard(ClipboardID) = 0;
private:
// 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 timeout);
~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;
};
private:
typedef CPriorityQueue<CTimer> CTimerPriorityQueue;
Display* m_display;
int m_screen;
Window m_root;
SInt32 m_x, m_y;
SInt32 m_w, m_h;
bool m_stop;
// clipboards
CXWindowsClipboard* m_clipboard[kClipboardEnd];
// the transparent cursor
Cursor m_cursor;
// screen saver
CXWindowsScreenSaver* m_screenSaver;
// timers, the stopwatch used to time, and a mutex for the timers
CTimerPriorityQueue m_timers;
CStopwatch m_time;
CMutex m_timersMutex;
// X is not thread safe
CMutex m_mutex;
// pointer to (singleton) screen. this is only needed by
// ioErrorHandler().
static CXWindowsScreen* s_screen;
};
#endif