// // PDecor.hh for pekwm // Copyright (C) 2004-2005 Claes Nasten // // 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 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::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 //! @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 _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 _button_list; Window _border_win[BORDER_NO_POS]; std::list _border_pix_list; Pixmap _title_bg; // variable decor data uint _title_active; std::list _title_list; uint _titles_left, _titles_right; // area where to put titles }; #endif // _PDECOR_HH_