mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
283 lines
8.5 KiB
C++
283 lines
8.5 KiB
C++
|
//
|
||
|
// Screen.hh for pekwm
|
||
|
// Copyright © 2003-2009 Claes Nästén <me{@}pekdon{.}net>
|
||
|
//
|
||
|
// This program is licensed under the GNU GPL.
|
||
|
// See the LICENSE file for more information.
|
||
|
//
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif // HAVE_CONFIG_H
|
||
|
|
||
|
#ifndef _SCREENINFO_HH_
|
||
|
#define _SCREENINFO_HH_
|
||
|
|
||
|
#include "pekwm.hh"
|
||
|
|
||
|
extern "C" {
|
||
|
#include <X11/Xlib.h>
|
||
|
#ifdef HAVE_XINERAMA
|
||
|
#include <X11/extensions/Xinerama.h>
|
||
|
#endif // HAVE_XINERAMA
|
||
|
|
||
|
extern bool xerrors_ignore; /**< If true, ignore X errors. */
|
||
|
extern unsigned int xerrors_count; /**< Number of X errors occured. */
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
#define setXErrorsIgnore(X) xerrors_ignore = (X)
|
||
|
#else // ! DEBUG
|
||
|
#define setXErrorsIgnore(X)
|
||
|
#endif // DEBUG
|
||
|
|
||
|
}
|
||
|
|
||
|
#include <vector>
|
||
|
#include <list>
|
||
|
#include <map>
|
||
|
|
||
|
/**
|
||
|
* Class holding information about screen edge allocation.
|
||
|
*/
|
||
|
class Strut {
|
||
|
public:
|
||
|
Strut(long l=0, long r=0, long t=0, long b=0, int nhead=-1)
|
||
|
: left(l), right(r), top(t), bottom(b), head(nhead) { };
|
||
|
~Strut(void) { };
|
||
|
public: // member variables
|
||
|
long left; /**< Pixels allocated on the left of the head. */
|
||
|
long right; /**<Pixels allocated on the right of the head. */
|
||
|
long top; /**< Pixels allocated on the top of the head.*/
|
||
|
long bottom; /**< Pixels allocated on the bottom of the head.*/
|
||
|
int head; /**< Which head is the strut valid for */
|
||
|
|
||
|
/** Assign values from array of longs. */
|
||
|
inline void operator=(const long *s) {
|
||
|
left = s[0];
|
||
|
right = s[1];
|
||
|
top = s[2];
|
||
|
bottom = s[3];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//! Output head, used to share same code with Xinerama and RandR
|
||
|
class Head {
|
||
|
public:
|
||
|
Head(int nx, int ny, uint nwidth, uint nheight) : x(nx), y(ny), width(nwidth), height(nheight) { };
|
||
|
|
||
|
public:
|
||
|
int x;
|
||
|
int y;
|
||
|
uint width;
|
||
|
uint height;
|
||
|
|
||
|
Strut strut;
|
||
|
};
|
||
|
|
||
|
//! @brief Display information class.
|
||
|
class PScreen
|
||
|
{
|
||
|
//! Bits 1-15 are modifier masks, but bits 13 and 14 aren't named in X11/X.h.
|
||
|
static const unsigned KbdLayoutMask1 = 1<<13;
|
||
|
static const unsigned KbdLayoutMask2 = 1<<14;
|
||
|
|
||
|
public:
|
||
|
//! @brief Visual wrapper class.
|
||
|
class PVisual {
|
||
|
public:
|
||
|
PVisual(Visual *x_visual);
|
||
|
~PVisual(void);
|
||
|
|
||
|
//! @brief Returns pointer to X Visual.
|
||
|
inline Visual *getXVisual(void) { return _x_visual; }
|
||
|
|
||
|
inline int getRShift(void) const { return _r_shift; }
|
||
|
inline int getRPrec(void) const { return _r_prec; }
|
||
|
inline int getGShift(void) const { return _g_shift; }
|
||
|
inline int getGPrec(void) const { return _g_prec; }
|
||
|
inline int getBShift(void) const { return _b_shift; }
|
||
|
inline int getBPrec(void) const { return _b_prec; }
|
||
|
|
||
|
private:
|
||
|
void getShiftPrecFromMask(ulong mask, int &shift, int &prec);
|
||
|
|
||
|
private:
|
||
|
Visual *_x_visual; //!< Pointer to X Visual.
|
||
|
|
||
|
int _r_shift; //!< Red shift, alternative red_mask representation.
|
||
|
int _r_prec; //!< Red prec, alternative red_mask representation.
|
||
|
int _g_shift; //!< Green shift, alternative green_mask representation.
|
||
|
int _g_prec; //!< Green prec, alternative green_mask representation.
|
||
|
int _b_shift; //!< Blue shift, alternative blue_mask representation.
|
||
|
int _b_prec; //!< Blue prec, alternative blue_mask representation.
|
||
|
};
|
||
|
|
||
|
PScreen(Display *dpy, bool honour_randr = true);
|
||
|
~PScreen(void);
|
||
|
|
||
|
static PScreen* instance(void) { return _instance; }
|
||
|
|
||
|
inline static Display* getDpy(void) { return _dpy; }
|
||
|
inline int getScreenNum(void) const { return _screen; }
|
||
|
inline Window getRoot(void) const { return _root; }
|
||
|
|
||
|
const Geometry &getScreenGeometry(void) const { return _screen_gm; }
|
||
|
inline uint getWidth(void) const { return _screen_gm.width; }
|
||
|
inline uint getHeight(void) const { return _screen_gm.height; }
|
||
|
|
||
|
inline int getDepth(void) const { return _depth; }
|
||
|
inline PScreen::PVisual *getVisual(void) { return _visual; }
|
||
|
inline GC getGC(void) { return DefaultGC(_dpy, _screen); }
|
||
|
inline Colormap getColormap(void) const { return _colormap; }
|
||
|
|
||
|
inline ulong getWhitePixel(void)
|
||
|
const { return WhitePixel(_dpy, _screen); }
|
||
|
inline ulong getBlackPixel(void)
|
||
|
const { return BlackPixel(_dpy, _screen); }
|
||
|
|
||
|
/**
|
||
|
* Remove state modifiers such as NumLock from state.
|
||
|
*/
|
||
|
static void stripStateModifiers(unsigned int *state) {
|
||
|
*state &= ~(_num_lock | _scroll_lock | LockMask | KbdLayoutMask1 | KbdLayoutMask2);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove button modifiers from state.
|
||
|
*/
|
||
|
static void stripButtonModifiers(unsigned int *state) {
|
||
|
*state &= ~(Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask);
|
||
|
}
|
||
|
|
||
|
void setLockKeys(void);
|
||
|
inline uint getNumLock(void) const { return _num_lock; }
|
||
|
inline uint getScrollLock(void) const { return _scroll_lock; }
|
||
|
|
||
|
inline bool hasExtensionShape(void) const { return _has_extension_shape; }
|
||
|
inline int getEventShape(void) const { return _event_shape; }
|
||
|
|
||
|
void updateGeometry(uint width, uint height);
|
||
|
#ifdef HAVE_XRANDR
|
||
|
inline bool hasExtensionXRandr(void) const { return _has_extension_xrandr; }
|
||
|
inline int getEventXRandr(void) const { return _event_xrandr; }
|
||
|
#endif // HAVE_XRANDR
|
||
|
|
||
|
bool getNextEvent(XEvent &ev);
|
||
|
bool grabServer(void);
|
||
|
bool ungrabServer(bool sync);
|
||
|
bool grabKeyboard(Window win);
|
||
|
bool ungrabKeyboard(void);
|
||
|
bool grabPointer(Window win, uint event_mask, Cursor cursor);
|
||
|
bool ungrabPointer(void);
|
||
|
|
||
|
uint getNearestHead(int x, int y);
|
||
|
uint getCurrHead(void);
|
||
|
bool getHeadInfo(uint head, Geometry &head_info);
|
||
|
Geometry getHeadGeometry(uint head);
|
||
|
void getHeadInfoWithEdge(uint head, Geometry &head_info);
|
||
|
inline int getNumHeads(void) const { return _heads.size(); }
|
||
|
|
||
|
inline Time getLastEventTime(void) const { return _last_event_time; }
|
||
|
inline void setLastEventTime(Time t) { _last_event_time = t; }
|
||
|
|
||
|
inline Window getLastClickID(void) { return _last_click_id; }
|
||
|
inline void setLastClickID(Window id) { _last_click_id = id; }
|
||
|
|
||
|
inline Time getLastClickTime(uint button) {
|
||
|
if (button < BUTTON_NO) {
|
||
|
return _last_click_time[button];
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
inline void setLastClickTime(uint button, Time time) {
|
||
|
if (button < BUTTON_NO) {
|
||
|
_last_click_time[button] = time;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline bool isDoubleClick(Window id, uint button, Time time, Time dc_time) {
|
||
|
if ((_last_click_id == id) &&
|
||
|
((time - getLastClickTime(button)) < dc_time)) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void getMousePosition(int &x, int &y);
|
||
|
uint getButtonFromState(uint state);
|
||
|
|
||
|
void addStrut(Strut *strut);
|
||
|
void removeStrut(Strut *rem_strut);
|
||
|
void updateStrut(void);
|
||
|
inline Strut *getStrut(void) { return &_strut; }
|
||
|
|
||
|
uint getMaskFromKeycode(KeyCode keycode);
|
||
|
KeyCode getKeycodeFromMask(uint mask);
|
||
|
|
||
|
inline static void removeMotionEvents(void) {
|
||
|
XEvent xev;
|
||
|
while (XCheckMaskEvent(_dpy, PointerMotionMask, &xev))
|
||
|
;
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
static const uint MODIFIER_TO_MASK[]; /**< Modifier from (XModifierKeymap) to mask table. */
|
||
|
static const uint MODIFIER_TO_MASK_NUM; /**< Number of entries in MODIFIER_TO_MASK. */
|
||
|
|
||
|
private:
|
||
|
// squared distance because computing with sqrt is expensive
|
||
|
|
||
|
// gets the squared distance between 2 points
|
||
|
inline uint calcDistance(int x1, int y1, int x2, int y2) {
|
||
|
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
|
||
|
}
|
||
|
// gets the squared distance between 2 points with either x or y the same
|
||
|
inline uint calcDistance(int p1, int p2) { return (p1 - p2) * (p1 - p2); }
|
||
|
|
||
|
void initHeads(void);
|
||
|
void initHeadsRandr(void);
|
||
|
void initHeadsXinerama(void);
|
||
|
|
||
|
private:
|
||
|
static Display *_dpy;
|
||
|
bool _honour_randr; /**< Boolean flag if randr should be honoured. */
|
||
|
int _fd;
|
||
|
|
||
|
int _screen, _depth;
|
||
|
|
||
|
Geometry _screen_gm; /**< Screen geometry, no head information. */
|
||
|
|
||
|
Window _root;
|
||
|
PScreen::PVisual *_visual;
|
||
|
Colormap _colormap;
|
||
|
XModifierKeymap *_modifier_map; /**< Key to modifier mappings. */
|
||
|
|
||
|
static uint _num_lock;
|
||
|
static uint _scroll_lock;
|
||
|
|
||
|
bool _has_extension_shape;
|
||
|
int _event_shape;
|
||
|
|
||
|
bool _has_extension_xinerama;
|
||
|
|
||
|
bool _has_extension_xrandr;
|
||
|
int _event_xrandr;
|
||
|
|
||
|
std::vector<Head> _heads; //! Array of head information
|
||
|
uint _last_head; //! Last accessed head
|
||
|
|
||
|
uint _server_grabs;
|
||
|
|
||
|
Time _last_event_time;
|
||
|
// information for dobule clicks
|
||
|
Window _last_click_id;
|
||
|
Time _last_click_time[BUTTON_NO - 1];
|
||
|
|
||
|
Strut _strut;
|
||
|
std::list<Strut*> _strut_list;
|
||
|
|
||
|
static PScreen *_instance;
|
||
|
};
|
||
|
|
||
|
#endif // _SCREENINFO_HH_
|