//
// PDecor.hh for pekwm
// Copyright (C) 2004-2005 Claes Nasten <pekdon{@}pekdon{.}net>
//
// This program is licensed under the GNU GPL.
// See the LICENSE file for more information.
//
#include "../config.h"
#ifndef _PDECOR_HH_
#define _PDECOR_HH_
#include "Theme.hh" // for Theme::FrameData inlines
#include "PTexture.hh" // for border/image inlines
#include <list>
class ActionEvent;
class PFont;
class PWinObj;
//! @brief PWinObj container class with fancy decor.
class PDecor : public PWinObj
{
public:
//! @brief Decor title button class.
class Button : public PWinObj {
public:
Button(Display *dpy, PWinObj *parent, Theme::PDecorButtonData *data);
~Button(void);
ActionEvent *findAction(XButtonEvent *ev);
void setState(ButtonState state);
//! @brief Returns wheter the button is positioned relative the left title edge.
inline bool isLeft(void) const { return _left; }
private:
Theme::PDecorButtonData *_data;
ButtonState _state;
Pixmap _bg;
bool _left;
};
//! @brief Decor title item class.
class TitleItem {
public:
TitleItem(void) : _count(0), _user_set(false), _rule_applied(false) { }
~TitleItem(void) { }
inline const std::string &getReal(void) const { return _real; }
inline std::string &getWReal(void) { return _real; }
inline const std::string &getVisible(void) const { return _visible; }
inline std::string &getWVisible(void) { return _visible; }
inline uint getCount(void) const { return _count; }
inline bool isUserSet(void) const { return _user_set; }
inline bool isRuleApplied(void) const { return _rule_applied; }
inline uint getWidth(void) const { return _width; }
inline void setReal(const std::string &real) { _real = real; }
inline void setVisible(const std::string &visible) { _visible = visible; }
inline void setCount(uint count) { _count = count; }
inline void setUserSet(bool user_set) { _user_set = user_set; }
inline void setRuleApplied(bool applied) { _rule_applied = applied; }
inline void setWidth(uint width) { _width = width; }
private:
std::string _real, _visible;
uint _count;
bool _user_set, _rule_applied;
uint _width;
};
PDecor(Display *dpy, Theme *theme, const std::string decor_name = DEFAULT_DECOR_NAME);
virtual ~PDecor(void);
// START - PWinObj interface.
virtual void mapWindow(void);
virtual void mapWindowRaised(void);
virtual void unmapWindow(void);
virtual void move(int x, int y, bool do_virtual = true);
virtual void moveVirtual(int x, int y);
virtual void resize(uint width, uint height);
virtual void raise(void);
virtual void lower(void);
virtual void setFocused(bool focused);
virtual void setWorkspace(uint workspace);
virtual bool giveInputFocus(void);
virtual ActionEvent *handleButtonPress(XButtonEvent *ev);
virtual ActionEvent *handleButtonRelease(XButtonEvent *ev);
virtual ActionEvent *handleMotionEvent(XMotionEvent *ev);
virtual ActionEvent *handleEnterEvent(XCrossingEvent *ev);
virtual ActionEvent *handleLeaveEvent(XCrossingEvent *ev);
virtual bool operator == (const Window &window) {
if ((_window == window) || (_title_wo == window) ||
(findButton(window) != NULL) ||
(getBorderPosition(window) != BORDER_NO_POS) ||
((_child != NULL) ? (*_child == window) : false)) {
return true;
}
return false;
}
virtual bool operator != (const Window &window) {
return !(*this == window);
}
// END - PWinObj interface.
// START - PDecor interface.
virtual void addChild(PWinObj *child);
virtual void removeChild(PWinObj *child, bool do_delete = true);
virtual void activateChild(PWinObj *child);
virtual void updatedChildOrder(void) { }
virtual void updatedActiveChild(void) { }
virtual void getDecorInfo(char *buf, uint size);
virtual void setShaded(StateAction sa);
// END - PDecor interface.
void addDecor(PDecor *decor);
bool setDecor(const std::string &name);
void setDecorOverride(StateAction sa, const std::string &name);
void loadDecor(void);
//! @brief Returns title Window.
inline Window getTitleWindow(void) const { return _title_wo.getWindow(); }
PDecor::Button *findButton(Window win);
//! @brief Returns height of PDecor ignoring shaded state.
inline uint getRealHeight(void) const {
return (_shaded ? _real_height : _gm.height);
}
//! @brief Returns last click x root position.
inline int getPointerX(void) const { return _pointer_x; }
//! @brief Returns last click y root position.
inline int getPointerY(void) const { return _pointer_y; }
//! @brief Returns last click x window position.
inline int getClickX(void) const { return _click_x; }
//! @brief Returns last click y window position.
inline int getClickY(void) const { return _click_y; }
//! @brief Returns width of child container.
inline uint getChildWidth(void) const {
if ((borderLeft() + borderRight()) >= _gm.width) {
return 1;
}
return (_gm.width - borderLeft() - borderRight());
}
//! @brief Returns height of child container.
inline uint getChildHeight(void) const {
if ((borderTop() + borderBottom() + getTitleHeight()) >= getRealHeight()) {
return 1;
}
return (getRealHeight() - borderTop() - borderBottom() - getTitleHeight());
}
// child list actions
//! @brief Returns number of children in PDecor.
inline uint size(void) const { return _child_list.size(); }
//! @brief Returns iterator to the first child in PDecor.
inline std::list<PWinObj*>::iterator begin(void) {
return _child_list.begin();
}
//! @brief Returns iterator to the last+1 child in PDecor.
inline std::list<PWinObj*>::iterator end(void) { return _child_list.end(); }
//! @brief Returns pointer to active PWinObj.
inline PWinObj *getActiveChild(void) { return _child; }
PWinObj *getChildFromPos(int x);
void activateChildNum(uint num);
void activateChildRel(int off); // +/- relative from active
void moveChildRel(int off); // +/- relative from active
// title
//! @brief Adds TitleItem to title list.
inline void titleAdd(PDecor::TitleItem *ct) { _title_list.push_back(ct); }
//! @brief Removes all TitleItems from title list.
inline void titleClear(void) { _title_list.clear(); }
//! @brief Sets active TitleItem.
void titleSetActive(uint num) {
_title_active = (num > _title_list.size()) ? 0 : num;
}
// move and resize relative to the child instead of decor
void moveChild(int x, int y);
void resizeChild(uint width, uint height);
// decor state
//! @brief Returns wheter we have a border or not.
inline bool hasBorder(void) const { return _border; }
//! @brief Returns wheter we have a titlebar or not.
inline bool hasTitlebar(void) const { return _titlebar; }
//! @brief Returns wheter we are shaded or not.
inline bool isShaded(void) const { return _shaded; }
void setBorder(StateAction sa);
void setTitlebar(StateAction sa);
// decor element sizes
//! @brief Returns title height, 0 if titlebar disabled.
inline uint getTitleHeight(void) const {
return (_titlebar ? _data->getTitleHeight() : 0);
}
// common actions like doMove
void doMove(XMotionEvent *ev);
void doKeyboardMoveResize(void);
//! @brief Returns border position Window win is at.
inline BorderPosition getBorderPosition(Window win) const {
for (uint i = 0; i < BORDER_NO_POS; ++i) {
if (_border_win[i] == win) {
return BorderPosition(i);
}
}
return BORDER_NO_POS;
}
inline uint borderTop(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_TOP)->getHeight() : 0);
}
inline uint borderTopLeft(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_TOP_LEFT)->getWidth() : 0);
}
inline uint borderTopLeftHeight(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_TOP_LEFT)->getHeight() : 0);
}
inline uint borderTopRight(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_TOP_RIGHT)->getWidth() : 0);
}
inline uint borderTopRightHeight(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_TOP_RIGHT)->getHeight() : 0);
}
inline uint borderBottom(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_BOTTOM)->getHeight() : 0);
}
inline uint borderBottomLeft(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_BOTTOM_LEFT)->getWidth() : 0);
}
inline uint borderBottomLeftHeight(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_BOTTOM_LEFT)->getHeight() : 0);
}
inline uint borderBottomRight(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_BOTTOM_RIGHT)->getWidth() : 0);
}
inline uint borderBottomRightHeight(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_BOTTOM_RIGHT)->getHeight() : 0);
}
inline uint borderLeft(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_LEFT)->getWidth() : 0);
}
inline uint borderRight(void) const {
return (_border ? _data->getBorderTexture(getFocusedState(false), BORDER_RIGHT)->getWidth() : 0);
}
protected:
// START - PDecor interface.
virtual void renderTitle(void);
virtual void renderButtons(void);
virtual void renderBorder(void);
virtual void setBorderShape(void); // shapes border corners
virtual void applyBorderShape(void); // applies shape onto window
virtual void loadTheme(void) { } // called after loadDecor, render child
virtual int resizeHorzStep(int diff) const { return diff; }
virtual int resizeVertStep(int diff) const { return diff; }
// END - PDecor interface.
void resizeTitle(void);
//! @brief Returns font used at FocusedState state.
inline PFont *getFont(FocusedState state) { return _data->getFont(state); }
uint getNearestHead(void);
void checkSnap(void);
void checkWOSnap(void);
void checkEdgeSnap(void);
#ifdef HAVE_SHAPE
bool setShape(bool remove);
#endif // HAVE_SHAPE
void alignChild(PWinObj *child);
void drawOutline(const Geometry &gm);
inline FocusedState getFocusedState(bool selected) const {
if (selected) {
return (_focused) ? FOCUSED_STATE_FOCUSED_SELECTED : FOCUSED_STATE_UNFOCUSED_SELECTED;
} else {
return (_focused) ? FOCUSED_STATE_FOCUSED : FOCUSED_STATE_UNFOCUSED;
}
}
private:
void unloadDecor(void);
EdgeType doMoveEdgeFind(int x, int y);
void doMoveEdgeAction(XMotionEvent *ev, EdgeType edge);
void placeButtons(void);
void placeBorder(void);
void shapeBorder(void);
void restackBorder(void); // shaded, borderless, no border visible
bool updateDecorName(void);
PWinObj *getChildRel(int off); // +/- relative from active
void getBorderSize(BorderPosition pos, uint &width, uint &height);
uint calcTitleWidth(void);
void calcTabsWidth(void);
void calcTabsWidthSymetric(void);
void calcTabsWidthAsymetric(void);
protected:
Theme *_theme; //!< Pointer to Theme used by PDecor.
PWinObj *_child; //!< Pointer to active child in PDecor.
std::list<PWinObj*> _child_list; //!< List of children in PDecor.
PDecor::Button *_button; //!< Active title button in PDecor.
// used for treshold calculation
int _pointer_x; //!< Last click x root position.
int _pointer_y; //!< Last click y root position.
int _click_x; //!< Last click x window position.
int _click_y; //!< Last click y window position.
// how the decor should behave
bool _decor_cfg_keep_empty; //!< Boolean to configure allowing empty PDecors.
bool _decor_cfg_child_move_overloaded; //!< Boolean to set wheter ::move is overloaded.
// button{press,release} handling cfg
bool _decor_cfg_bpr_replay_pointer; //!< Boolean to configure wheter to call XReplayPointer on clicks.
MouseActionListName _decor_cfg_bpr_al_child; //!< What list to search for child actions.
MouseActionListName _decor_cfg_bpr_al_title; //!< What list to search for title actions.
static const std::string DEFAULT_DECOR_NAME; //!< Default decor name in normal state.
static const std::string DEFAULT_DECOR_NAME_BORDERLESS; //!< Default decor name in borderless state.
static const std::string DEFAULT_DECOR_NAME_TITLEBARLESS; //!< Default decor name in titlebarless state.
private:
Theme::PDecorData *_data;
std::string _decor_name, _decor_name_override;
// decor state
bool _border, _titlebar, _shaded;
bool _need_shape;
bool _need_client_shape;
uint _real_height;
PWinObj _title_wo;
std::list<PDecor::Button*> _button_list;
Window _border_win[BORDER_NO_POS];
std::list<Pixmap> _border_pix_list;
Pixmap _title_bg;
// variable decor data
uint _title_active;
std::list<PDecor::TitleItem*> _title_list;
uint _titles_left, _titles_right; // area where to put titles
};
#endif // _PDECOR_HH_
syntax highlighted by Code2HTML, v. 0.9.1