Skip to content

Commit 7b5371d

Browse files
authored
Add 'parent_frame' entry for each client (herbstluftwm#1088)
The 'parent_frame' child of a client provides the frame object that holds the client. This fixes #6.
1 parent 5b8605d commit 7b5371d

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Current git version
1212
order of existing tags.
1313
* New child object 'focused_client' for each tag object.
1414
* New child object 'focused_frame' for the tiling object of each tag object.
15+
* New child object 'parent_frame' for each client providing the frame the client sits in
1516
* New command 'mirror'
1617
* New command 'apply_tmp_rule'
1718
* The 'apply_rules' command now reports parse errors

src/client.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
#include "clientmanager.h"
1010
#include "decoration.h"
1111
#include "ewmh.h"
12+
#include "frametree.h"
1213
#include "globals.h"
1314
#include "hook.h"
1415
#include "ipc-protocol.h"
1516
#include "keymanager.h"
17+
#include "layout.h"
1618
#include "monitor.h"
1719
#include "monitormanager.h"
1820
#include "mousemanager.h"
@@ -41,6 +43,7 @@ Client::Client(Window window, bool visible_already, ClientManager& cm)
4143
, minimized_(this, "minimized", false)
4244
, title_(this, "title", "")
4345
, tag_str_(this, "tag", &Client::tagName)
46+
, parent_frame_(*this, "parent_frame", &Client::parentFrame)
4447
, window_id_str(this, "winid", "")
4548
, keyMask_(this, "keymask", RegexStr::fromStr(""))
4649
, keysInactive_(this, "keys_inactive", RegexStr::fromStr(""))
@@ -93,6 +96,7 @@ Client::Client(Window window, bool visible_already, ClientManager& cm)
9396

9497
init_from_X();
9598
visible_.setDoc("whether this client is rendered currently");
99+
parent_frame_.setDoc("the frame contaning this client if the client is tiled");
96100
}
97101

98102
void Client::init_from_X() {
@@ -580,6 +584,15 @@ string Client::getWindowInstance()
580584
return ewmh.X().getInstance(window_);
581585
}
582586

587+
FrameLeaf* Client::parentFrame()
588+
{
589+
if (is_client_floated()) {
590+
return nullptr;
591+
} else {
592+
return tag_->frame->findFrameWithClient(this).get();
593+
}
594+
}
595+
583596
void Client::requestRedraw()
584597
{
585598
if (tag_) {

src/client.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <X11/Xlib.h>
66

77
#include "attribute_.h"
8+
#include "child.h"
89
#include "object.h"
910
#include "regexstr.h"
1011
#include "theme.h"
@@ -14,6 +15,7 @@
1415
class Decoration;
1516
class DecTriple;
1617
class Ewmh;
18+
class FrameLeaf;
1719
class Slice;
1820
class HSTag;
1921
class Monitor;
@@ -60,6 +62,7 @@ class Client : public Object {
6062
Attribute_<bool> minimized_;
6163
Attribute_<std::string> title_; // or also called window title; this is never NULL
6264
DynAttribute_<std::string> tag_str_;
65+
DynChild_<FrameLeaf> parent_frame_;
6366
Attribute_<std::string> window_id_str;
6467
Attribute_<RegexStr> keyMask_; // regex for key bindings that are active on this window
6568
Attribute_<RegexStr> keysInactive_; // regex for key bindings that are inactive on this window
@@ -125,6 +128,7 @@ class Client : public Object {
125128
std::string getWindowClass();
126129
std::string getWindowInstance();
127130
std::string triggerRelayoutMonitor();
131+
FrameLeaf* parentFrame();
128132
void requestRedraw();
129133
friend Decoration;
130134
ClientManager& manager;

tests/test_clients.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,3 +282,38 @@ def test_minimize_only_floating_client(hlwm):
282282
hlwm.call(f'set_attr clients.{winid}.minimized on')
283283

284284
assert hlwm.get_attr('tags.focus.floating_focused') == 'false'
285+
286+
287+
def test_parent_frame_attribute_one_split(hlwm):
288+
c1, c2 = hlwm.create_clients(2)
289+
hlwm.call('split explode')
290+
291+
assert hlwm.attr.clients[c1].parent_frame.index() == '0'
292+
assert hlwm.attr.clients[c2].parent_frame.index() == '1'
293+
294+
295+
def test_parent_frame_attribute_no_split(hlwm):
296+
c1, c2 = hlwm.create_clients(2)
297+
298+
assert hlwm.attr.clients[c1].parent_frame.index() == ''
299+
assert hlwm.attr.clients[c2].parent_frame.index() == ''
300+
301+
302+
def test_parent_frame_attribute_window_floating(hlwm):
303+
winid, _ = hlwm.create_client()
304+
# do it in a loop to verify that we don't have typos in the assert
305+
for value in ['on', 'off']:
306+
hlwm.attr.clients[winid].floating = value
307+
308+
assert ('parent_frame' in hlwm.list_children(f'clients.{winid}')) \
309+
== (value == 'off')
310+
311+
312+
def test_parent_frame_attribute_tag_floating(hlwm):
313+
winid, _ = hlwm.create_client()
314+
# do it in a loop to verify that we don't have typos in the assert
315+
for value in ['on', 'off']:
316+
hlwm.attr.tags.focus.floating = value
317+
318+
assert ('parent_frame' in hlwm.list_children(f'clients.{winid}')) \
319+
== (value == 'off')

0 commit comments

Comments
 (0)