Two new atoms were introduces to keep track of the ordering within Frames
_PEKWM_FRAME_ORDER and which client is the active one _PEKWM_FRAME_ACTIVE.
Restart tests on my PC seems to be working ok.
| src/Frame.cc | |
| 407 | @@ -407,13 +407,32 @@ |
| 407 | |
| 408 | //! @brief Adds child to the frame. |
| 409 | void |
| 410 | Frame::addChild (PWinObj *child) |
| 411 | Frame::addChild (PWinObj *child, std::list<PWinObj*>::iterator *it) |
| 412 | { |
| 413 | PDecor::addChild(child); |
| 414 | PDecor::addChild(child, it); |
| 415 | AtomUtil::setLong(child->getWindow(), Atoms::getAtom(PEKWM_FRAME_ID), _id); |
| 416 | child->lower(); |
| 417 | } |
| 418 | |
| 419 | /** |
| 420 | * Add child preserving order from the previous pekwm run. |
| 421 | */ |
| 422 | void |
| 423 | Frame::addChildOrdered (Client *child) |
| 424 | { |
| 425 | Client *client; |
| 426 | |
| 427 | list<PWinObj*>::iterator it(_child_list.begin()); |
| 428 | for (; it != _child_list.end(); ++it) { |
| 429 | client = static_cast<Client*>(*it); |
| 430 | if (child->getInitialFrameOrder() < client->getInitialFrameOrder()) { |
| 431 | break; |
| 432 | } |
| 433 | } |
| 434 | |
| 435 | addChild(child, &it); |
| 436 | } |
| 437 | |
| 438 | //! @brief Removes child from the frame. |
| 439 | void |
| 440 | Frame::removeChild (PWinObj *child, bool do_delete) |
| ... | |
| 476 | @@ -457,21 +476,29 @@ |
| 476 | Workspaces::instance()->updateClientStackingList(true, true); |
| 477 | } |
| 478 | |
| 460 | //! @brief |
| 480 | /** |
| 481 | * Called when child order is updated, re-sets the titles and updates |
| 482 | * the _PEKWM_FRAME hints. |
| 483 | */ |
| 484 | void |
| 485 | Frame::updatedChildOrder(void) |
| 486 | { |
| 487 | titleClear(); |
| 488 | |
| 489 | Client *client; |
| 490 | list<PWinObj*>::iterator it(_child_list.begin()); |
| 472 | for (; it != _child_list.end(); ++it) { |
| 473 | titleAdd(static_cast<Client*>(*it)->getTitle()); |
| 493 | for (long num = 0; it != _child_list.end(); ++num, ++it) { |
| 494 | client = static_cast<Client*>(*it); |
| 495 | client->setPekwmFrameOrder(num); |
| 496 | titleAdd(client->getTitle()); |
| 497 | } |
| 498 | |
| 499 | updatedActiveChild(); |
| 500 | } |
| 501 | |
| 483 | //! @brief |
| 503 | /** |
| 504 | * Set the active title and update the _PEKWM_FRAME hints. |
| 505 | */ |
| 506 | void |
| 507 | Frame::updatedActiveChild(void) |
| 508 | { |
| ... | |
| 506 | @@ -479,9 +506,9 @@ |
| 506 | |
| 507 | list<PWinObj*>::iterator it(_child_list.begin()); |
| 508 | for (uint i = 0; it != _child_list.end(); ++i, ++it) { |
| 509 | static_cast<Client*>(*it)->setPekwmFrameActive(_child == *it); |
| 510 | if (_child == *it) { |
| 511 | titleSetActive(i); |
| 485 | break; |
| 513 | } |
| 514 | } |
| 515 | |
| ... | |
| src/Frame.hh | |
| 55 | @@ -55,7 +55,7 @@ |
| 55 | #endif // HAVE_SHAPE |
| 56 | |
| 57 | // START - PDecor interface. |
| 58 | virtual void addChild(PWinObj *child); |
| 59 | virtual void addChild(PWinObj *child, std::list<PWinObj*>::iterator *it = 0); |
| 60 | virtual void removeChild(PWinObj *child, bool do_delete = true); |
| 61 | virtual void activateChild(PWinObj *child); |
| 62 | |
| ... | |
| 68 | @@ -68,6 +68,8 @@ |
| 68 | virtual void setSkip(uint skip); |
| 69 | // END - PDecor interface. |
| 70 | |
| 71 | void addChildOrdered(Client *child); |
| 72 | |
| 73 | static Frame *findFrameFromWindow(Window win); |
| 74 | static Frame *findFrameFromID(uint id); |
| 75 | |
| ... | |
| src/Atoms.cc | |
| 64 | @@ -64,6 +64,8 @@ |
| 64 | |
| 65 | // pekwm atoms |
| 66 | "_PEKWM_FRAME_ID", |
| 67 | "_PEKWM_FRAME_ORDER", |
| 68 | "_PEKWM_FRAME_ACTIVE", |
| 69 | "_PEKWM_FRAME_DECOR", |
| 70 | "_PEKWM_FRAME_SKIP", |
| 71 | "_PEKWM_TITLE", |
| ... | |
| src/Atoms.hh | |
| 67 | @@ -67,6 +67,8 @@ |
| 67 | |
| 68 | // pekwm atom names |
| 69 | PEKWM_FRAME_ID, |
| 70 | PEKWM_FRAME_ORDER, |
| 71 | PEKWM_FRAME_ACTIVE, |
| 72 | PEKWM_FRAME_DECOR, |
| 73 | PEKWM_FRAME_SKIP, |
| 74 | PEKWM_TITLE, |
| ... | |
| src/PDecor.cc | |
| 993 | @@ -993,10 +993,14 @@ |
| 993 | |
| 994 | //! @brief Adds a child to the decor, reparenting the window |
| 995 | void |
| 996 | PDecor::addChild(PWinObj *child) |
| 997 | PDecor::addChild(PWinObj *child, std::list<PWinObj*>::iterator *it) |
| 998 | { |
| 999 | child->reparent(this, borderLeft(), borderTop() + getTitleHeight()); |
| 1000 | _child_list.push_back(child); |
| 1001 | if (it == 0) { |
| 1002 | _child_list.push_back(child); |
| 1003 | } else { |
| 1004 | _child_list.insert(*it, child); |
| 1005 | } |
| 1006 | |
| 1007 | updatedChildOrder(); |
| 1008 | |
| ... | |
| src/PDecor.hh | |
| 151 | @@ -151,7 +151,7 @@ |
| 151 | // END - PWinObj interface. |
| 152 | |
| 153 | // START - PDecor interface. |
| 154 | virtual void addChild(PWinObj *child); |
| 155 | virtual void addChild(PWinObj *child, std::list<PWinObj*>::iterator *it = 0); |
| 156 | virtual void removeChild(PWinObj *child, bool do_delete = true); |
| 157 | virtual void activateChild(PWinObj *child); |
| 158 | |
| ... | |
| src/Client.cc | |
| 187 | @@ -187,6 +187,7 @@ |
| 187 | // don't want to spread the giveInputFocuses |
| 188 | bool do_focus = is_new ? Config::instance()->isFocusNew() : false; |
| 189 | bool do_autogroup = true; |
| 190 | bool is_active = getPekwmFrameActive(); |
| 191 | |
| 192 | // If pekwm is already running, check against autoproperty then |
| 193 | // tagged frame. If starting up, check if it has a FRAME_ID and if not |
| ... | |
| 213 | @@ -212,8 +213,10 @@ |
| 213 | _parent = Frame::findFrameFromID(id); |
| 214 | if (_parent) { |
| 215 | Frame *frame = static_cast<Frame*>(_parent); |
| 215 | frame->addChild(this); |
| 216 | frame->activateChild(this); |
| 218 | frame->addChildOrdered(this); |
| 219 | if (is_active) { |
| 220 | frame->activateChild(this); |
| 221 | } |
| 222 | do_focus = frame->isFocused(); |
| 223 | } |
| 224 | } |
| ... | |
| 855 | @@ -852,6 +855,8 @@ |
| 855 | if (AtomUtil::getString(_window, Atoms::getAtom(PEKWM_TITLE), str)) { |
| 856 | _title.setUser(Util::to_wide_str(str)); |
| 857 | } |
| 858 | |
| 859 | _state.initial_frame_order = getPekwmFrameOrder(); |
| 860 | } |
| 861 | |
| 862 | //! @brief Read _NET_WM_ICON from client window. |
| ... | |
| 1670 | @@ -1665,3 +1670,44 @@ |
| 1670 | delete _strut; |
| 1671 | _strut = 0; |
| 1672 | } |
| 1673 | |
| 1674 | /** |
| 1675 | * Get _PEKWM_FRAME_ORDER hint from client, return < 0 on failure. |
| 1676 | */ |
| 1677 | long |
| 1678 | Client::getPekwmFrameOrder(void) |
| 1679 | { |
| 1680 | long num = -1; |
| 1681 | AtomUtil::getLong(_window, Atoms::getAtom(PEKWM_FRAME_ORDER), num); |
| 1682 | return num; |
| 1683 | } |
| 1684 | |
| 1685 | /** |
| 1686 | * Update _PEKWM_FRAME_ORDER hint on client window. |
| 1687 | */ |
| 1688 | void |
| 1689 | Client::setPekwmFrameOrder(long num) |
| 1690 | { |
| 1691 | AtomUtil::setLong(_window, Atoms::getAtom(PEKWM_FRAME_ORDER), num); |
| 1692 | } |
| 1693 | |
| 1694 | /** |
| 1695 | * Get _PEKWM_FRAME_ACTIVE hint from client window, return true if |
| 1696 | * client is treated as active. |
| 1697 | */ |
| 1698 | bool |
| 1699 | Client::getPekwmFrameActive(void) |
| 1700 | { |
| 1701 | long act = 0; |
| 1702 | return (AtomUtil::getLong(_window, Atoms::getAtom(PEKWM_FRAME_ACTIVE), act) |
| 1703 | && act == 1); |
| 1704 | } |
| 1705 | |
| 1706 | /** |
| 1707 | * Set _PEKWM_FRAME_ACTIVE hint on client window. |
| 1708 | */ |
| 1709 | void |
| 1710 | Client::setPekwmFrameActive(bool act) |
| 1711 | { |
| 1712 | AtomUtil::setLong(_window, Atoms::getAtom(PEKWM_FRAME_ACTIVE), act ? 1 : 0); |
| 1713 | } |
| ... | |
| src/Client.hh | |
| 158 | @@ -158,6 +158,7 @@ |
| 158 | inline bool isShaded(void) const { return _state.shaded; } |
| 159 | inline bool isFullscreen(void) const { return _state.fullscreen; } |
| 160 | inline bool isPlaced(void) const { return _state.placed; } |
| 161 | inline uint getInitialFrameOrder(void) const { return _state.initial_frame_order; } |
| 162 | inline uint getSkip(void) const { return _state.skip; } |
| 163 | inline bool isSkip(Skip skip) const { return (_state.skip&skip); } |
| 164 | inline uint getDecorState(void) const { return _state.decor; } |
| ... | |
| 260 | @@ -259,6 +260,11 @@ |
| 260 | void readName(void); |
| 261 | void readIconName(void); |
| 262 | void removeStrutHint(void); |
| 263 | |
| 264 | long getPekwmFrameOrder(void); |
| 265 | void setPekwmFrameOrder(long num); |
| 266 | bool getPekwmFrameActive(void); |
| 267 | void setPekwmFrameActive(bool active); |
| 268 | |
| 269 | private: |
| 270 | bool titleApplyRule(std::wstring &wtitle); |
| ... | |
| 333 | @@ -327,7 +333,8 @@ |
| 333 | public: |
| 334 | State(void) |
| 335 | : maximized_vert(false), maximized_horz(false), shaded(false), fullscreen(false), |
| 330 | placed(false), skip(0), decor(DECOR_TITLEBAR|DECOR_BORDER), |
| 337 | placed(false), initial_frame_order(0), |
| 338 | skip(0), decor(DECOR_TITLEBAR|DECOR_BORDER), |
| 339 | cfg_deny(CFG_DENY_NO), demands_attention(true) { } |
| 340 | ~State(void) { } |
| 341 | |
| ... | |
| 344 | @@ -337,6 +344,7 @@ |
| 344 | |
| 345 | // pekwm states |
| 346 | bool placed; |
| 347 | uint initial_frame_order; /**< Initial frame position */ |
| 348 | uint skip, decor, cfg_deny; |
| 349 | bool demands_attention; /**< If true, the client requires attention from the user. */ |
| 350 | } _state; |
| ... | |