// // PDecor.hh for pekwm // Copyright © 2004-2009 Claes Nästén // // This program is licensed under the GNU GPL. // See the LICENSE file for more information. // #ifndef _PDECOR_HH_ #define _PDECOR_HH_ #ifdef HAVE_CONFIG_H #include "config.h" #endif // HAVE_CONFIG_H #include "Config.hh" #include "Theme.hh" // for Theme::FrameData inlines #include "PTexture.hh" // for border/image inlines #include "Util.hh" #include class ActionEvent; class PFont; class PWinObj; /** * Create window attributes. */ class CreateWindowParams { public: int depth; long mask; XSetWindowAttributes attr; Visual *visual; }; //! @brief PWinObj container class with fancy decor. class PDecor : public PWinObj { public: //! @brief Decor title button class. class Button : public PWinObj { public: Button(PWinObj *parent, Theme::PDecorButtonData *data, uint width, uint height); ~Button(void); ActionEvent *findAction(XButtonEvent *ev); ButtonState getState(void) const { return _state; } 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: //! Info bitmask enum. enum Info { INFO_MARKED = (1 << 1), INFO_ID = (1 << 2) }; TitleItem(void) : _count(0), _id(0), _info(0), _width(0) { } inline const std::wstring &getVisible(void) const { return _visible; } inline const std::wstring &getReal(void) const { return _real; } inline const std::wstring &getCustom(void) const { return _custom; } inline const std::wstring &getUser(void) const { return _user; } inline uint getCount(void) const { return _count; } inline uint getId(void) const { return _id; } inline bool isUserSet(void) const { return (_user.size() > 0); } inline bool isCustom(void) const { return (_custom.size() > 0); } inline uint getWidth(void) const { return _width; } inline void infoAdd(enum Info info) { _info |= info; } inline void infoRemove(enum Info info) { _info &= ~info; } inline bool infoIs(enum Info info) { return (_info&info); } void setReal(const std::wstring &real) { _real = real; if (! isUserSet() && ! isCustom()) { updateVisible(); } } void setCustom(const std::wstring &custom) { _custom = custom; if (_custom.size() > 0 && ! isUserSet()) { updateVisible(); } } void setUser(const std::wstring &user) { _user = user; updateVisible(); } void setCount(uint count) { _count = count; } void setId(uint id) { _id = id; } inline void setWidth(uint width) { _width = width; } void updateVisible(void); private: std::wstring _visible; //!< Visible version of title std::wstring _real; //!< Title from client std::wstring _custom; //!< Custom (title rule) set version of title std::wstring _user; //!< User set version of title uint _count; //!< Number of title uint _id; //!< ID of title uint _info; //!< Info bitmask for extra title info uint _width; }; PDecor(Theme *theme, const std::string decor_name = DEFAULT_DECOR_NAME, const Window child_window = None); 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); virtual void resize(uint width, uint height); virtual void moveResize(int x, int y, uint width, uint height); virtual void raise(void); virtual void lower(void); virtual void setFocused(bool focused); virtual void setWorkspace(uint workspace); virtual void 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) || (getBorderPosition(window) != BORDER_NO_POS) || ((_child) ? (*_child == window) : false)) { return true; } return false; } virtual bool operator != (const Window &window) { return !(*this == window); } // END - PWinObj interface. // START - PDecor interface. virtual bool allowMove(void) const { return true; } virtual void addChild(PWinObj *child, std::list::iterator *it = 0); 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(wchar_t *buf, uint size); virtual void setShaded(StateAction sa); virtual void setSkip(uint skip); // END - PDecor interface. static std::list::iterator pdecor_begin(void) { return _pdecor_list.begin(); } static std::list::iterator pdecor_end(void) { return _pdecor_list.end(); } inline bool isSkip(uint skip) const { return (_skip&skip); } 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::iterator begin(void) { return _child_list.begin(); } //! @brief Returns iterator to the last+1 child in PDecor. inline std::list::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 uint getTitleHeight(void) const; // common actions like doMove void doMove(int x_root, int y_root); 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); } void deiconify(void); 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) const { return _data->getFont(state); } uint getNearestHead(void); void checkSnap(void); void checkWOSnap(void); void checkEdgeSnap(void); bool setShape(void); 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 getParentWindowAttributes(CreateWindowParams ¶ms, Window child_window); void getChildWindowAttributes(CreateWindowParams ¶ms, Window child_window); void createParentWindow(CreateWindowParams ¶ms); void createTitle(CreateWindowParams ¶ms); void createBorder(CreateWindowParams ¶ms); void unloadDecor(void); ActionEvent *handleButtonPressButton(XButtonEvent *ev, PDecor::Button *button); ActionEvent *handleButtonPressBorder(XButtonEvent *ev); ActionEvent *handleButtonReleaseButton(XButtonEvent *ev, PDecor::Button *button); ActionEvent *handleButtonReleaseBorder(XButtonEvent *ev); 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 calcTabsGetAvailAndTabWidth(uint &width_avail, uint &tab_width, int &off); void calcTabsWidthSymetric(void); void calcTabsWidthAsymetric(void); void calcTabsWidthAsymetricGrow(uint width_avail, uint tab_width); void calcTabsWidthAsymetricShrink(uint width_avail, uint tab_width); protected: Theme *_theme; //!< Pointer to Theme used by PDecor. std::string _decor_name; /**< Name of decoration used. */ std::string _decor_name_override; /**< Overridden decoration name. */ PWinObj *_child; //!< Pointer to active child in PDecor. std::list _child_list; //!< List of children in PDecor. PDecor::Button *_button; /**< Active title button in PDecor. */ Window _button_press_win; /**< Active border window, for button release handling. */ // 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. // state switches, commonly not used by all decors bool _maximized_vert; bool _maximized_horz; bool _fullscreen; uint _skip; Window _border_win[BORDER_NO_POS]; /** Array of border windows. */ std::map _border_pos_map; private: Theme::PDecorData *_data; // decor state bool _border, _titlebar, _shaded; bool _need_shape; bool _need_client_shape; bool _dirty_resized; //!< Flag set when decor has been resized. uint _real_height; PWinObj _title_wo; std::list _button_list; Pixmap _title_bg; // variable decor data uint _title_active; std::list _title_list; uint _titles_left, _titles_right; // area where to put titles static std::list _pdecor_list; /**< List of PDecors */ }; #endif // _PDECOR_HH_