window_layouter: modernized coding style

Replace the use of pointers and the copying of XML nodes by the 'with_'
pattern. Use plain struct where appropriate, replace constructors by { }
initialization. Use C++20 function template syntax. Replace accessors by
public constants where possible. Follow 'from_xml' convention. Follow
usual 'Action' interface naming.

Issue #5390
This commit is contained in:
Norman Feske 2024-11-29 15:45:11 +01:00 committed by Christian Helmuth
parent ca1b22b0aa
commit dbcc21c109
14 changed files with 427 additions and 569 deletions

View File

@ -1,86 +0,0 @@
/*
* \brief Action triggered by the user
* \author Norman Feske
* \date 2016-02-01
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ACTION_H_
#define _ACTION_H_
#include <target.h>
namespace Window_layouter { class Action; }
/**
* Result of the application of a key event to the key-sequence tracker
*/
class Window_layouter::Action
{
public:
enum Type {
NONE,
NEXT_WINDOW,
PREV_WINDOW,
RAISE_WINDOW,
TOGGLE_FULLSCREEN,
CLOSE,
NEXT_WORKSPACE,
PREV_WORKSPACE,
MARK,
DETACH,
ATTACH,
COLUMN,
ROW,
REMOVE,
NEXT_COLUMN,
PREV_COLUMN,
NEXT_ROW,
PREV_ROW,
NEXT_TAB,
PREV_TAB,
TOOGLE_OVERLAY,
SCREEN,
RELEASE_GRAB,
};
private:
Type _type;
Target::Name _target;
template <Genode::size_t N>
static Type _type_by_string(String<N> const &string)
{
if (string == "next_window") return NEXT_WINDOW;
if (string == "prev_window") return PREV_WINDOW;
if (string == "raise_window") return RAISE_WINDOW;
if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN;
if (string == "screen") return SCREEN;
if (string == "release_grab") return RELEASE_GRAB;
Genode::warning("cannot convert \"", string, "\" to action type");
return NONE;
}
public:
Action(Type type) : _type(type), _target() { }
template <Genode::size_t N>
Action(String<N> const &string, Target::Name const &arg)
: _type(_type_by_string(string)), _target(arg) { }
Type type() const { return _type; }
Target::Name target_name() const { return _target; }
};
#endif /* _ACTION_H_ */

View File

@ -42,17 +42,63 @@ class Window_layouter::Assign : public List_model<Assign>::Element
: Registry<Member>::Element(registry, *this), window(window) { }
};
using Label = String<80>;
Target::Name target_name { };
private:
Registry<Member> _members { };
struct Label
{
using Value = String<80>;
Value exact, prefix, suffix;
static Label from_xml(Xml_node const &node)
{
return { .exact = node.attribute_value("label", Value()),
.prefix = node.attribute_value("label_prefix", Value()),
.suffix = node.attribute_value("label_suffix", Value()) };
}
bool operator == (Label const &other) const
{
return exact == other.exact
&& prefix == other.prefix
&& suffix == other.suffix;
}
bool matches(Value const &label) const
{
if (exact.valid() && label == exact)
return true;
if (exact.valid())
return false;
bool const prefix_matches =
prefix.valid() &&
!strcmp(label.string(), prefix.string(), prefix.length() - 1);
bool suffix_matches = false;
if (label.length() >= suffix.length()) {
size_t const offset = label.length() - suffix.length();
suffix_matches = !strcmp(label.string() + offset, suffix.string());
}
return (!prefix.valid() || prefix_matches)
&& (!suffix.valid() || suffix_matches);
}
void gen_attr(Xml_generator &xml) const
{
if (exact .valid()) xml.attribute("label", exact);
if (prefix.valid()) xml.attribute("label_prefix", prefix);
if (suffix.valid()) xml.attribute("label_suffix", suffix);
}
};
Label const _label;
Label const _label_prefix;
Label const _label_suffix;
bool _pos_defined = false;
bool _xpos_any = false;
@ -66,12 +112,7 @@ class Window_layouter::Assign : public List_model<Assign>::Element
public:
Assign(Xml_node assign)
:
_label (assign.attribute_value("label", Label())),
_label_prefix(assign.attribute_value("label_prefix", Label())),
_label_suffix(assign.attribute_value("label_suffix", Label()))
{ }
Assign(Xml_node assign) : _label(Label::from_xml(assign)) { }
void update(Xml_node assign)
{
@ -89,19 +130,12 @@ class Window_layouter::Assign : public List_model<Assign>::Element
/**
* List_model::Element
*/
bool matches(Xml_node node) const
{
return node.attribute_value("label", Label()) == _label
&& node.attribute_value("label_prefix", Label()) == _label_prefix
&& node.attribute_value("label_suffix", Label()) == _label_suffix;
}
bool matches(Xml_node node) const { return Label::from_xml(node) == _label; }
/**
* List_model::Element
*/
static bool type_matches(Xml_node const &node)
{
return node.has_type("assign");
static bool type_matches(Xml_node const &node) { return node.has_type("assign");
}
/**
@ -136,38 +170,19 @@ class Window_layouter::Assign : public List_model<Assign>::Element
*
* This method is used for associating assignments to windows.
*/
template <typename FN>
void with_matching_members_registry(Label const &label, FN const &fn)
void with_matching_members_registry(Label::Value const &label, auto const &fn)
{
bool const label_matches = (_label.valid() && label == _label);
bool const prefix_matches =
_label_prefix.valid() &&
!strcmp(label.string(),
_label_prefix.string(), _label_prefix.length() - 1);
bool suffix_matches = false;
if (label.length() >= _label_suffix.length()) {
unsigned const offset = (unsigned)(label.length() - _label_suffix.length());
suffix_matches = !strcmp(_label.string() + offset, _label_suffix.string());
}
bool const wildcard_matches = !_label.valid()
&& (!_label_prefix.valid() || prefix_matches)
&& (!_label_suffix.valid() || suffix_matches);
if (label_matches || wildcard_matches)
if (_label.matches(label))
fn(_members);
}
/**
* Used to generate <assign> nodes of windows captured via wildcard
*/
template <typename FN>
void for_each_wildcard_member(FN const &fn) const
void for_each_wildcard_member(auto const &fn) const
{
/* skip non-wildcards */
if (_label.valid())
if (_label.exact.valid())
return;
_members.for_each([&] (Assign::Member const &member) { fn(member); });
@ -176,10 +191,9 @@ class Window_layouter::Assign : public List_model<Assign>::Element
/**
* Used to bring wildcard-matching windows to front
*/
template <typename FN>
void for_each_wildcard_member(FN const &fn)
void for_each_wildcard_member(auto const &fn)
{
if (_label.valid())
if (_label.exact.valid())
return;
_members.for_each([&] (Assign::Member &member) { fn(member); });
@ -187,17 +201,14 @@ class Window_layouter::Assign : public List_model<Assign>::Element
bool floating() const { return _pos_defined; }
bool wildcard() const { return !_label.valid(); }
bool wildcard() const { return !_label.exact.valid(); }
/**
* Generate <assign> node
*/
void gen_assign_attr(Xml_generator &xml) const
{
if (_label.valid()) xml.attribute("label", _label);
if (_label_prefix.valid()) xml.attribute("label_prefix", _label_prefix);
if (_label_suffix.valid()) xml.attribute("label_suffix", _label_suffix);
_label.gen_attr(xml);
xml.attribute("target", target_name);
}
@ -247,11 +258,8 @@ class Window_layouter::Assign : public List_model<Assign>::Element
xml.attribute("visible", "no");
}
template <typename FN>
void for_each_member(FN const &fn) { _members.for_each(fn); }
template <typename FN>
void for_each_member(FN const &fn) const { _members.for_each(fn); }
void for_each_member(auto const &fn) { _members.for_each(fn); }
void for_each_member(auto const &fn) const { _members.for_each(fn); }
};
#endif /* _ASSIGN_H_ */

View File

@ -55,21 +55,19 @@ class Window_layouter::Assign_list : Noncopyable
auto fn = [&] (Registry<Assign::Member> &registry) {
window.assignment(registry); };
assign.with_matching_members_registry(window.label(), fn);
assign.with_matching_members_registry(window.label, fn);
});
});
}
template <typename FN>
void for_each_wildcard_member(FN const &fn) const
void for_each_wildcard_member(auto const &fn) const
{
_assignments.for_each([&] (Assign const &assign) {
assign.for_each_wildcard_member([&] (Assign::Member const &member) {
fn(assign, member); }); });
}
template <typename FN>
void for_each_wildcard_assigned_window(FN const &fn)
void for_each_wildcard_assigned_window(auto const &fn)
{
_assignments.for_each([&] (Assign &assign) {
assign.for_each_wildcard_member([&] (Assign::Member &member) {

View File

@ -0,0 +1,52 @@
/*
* \brief Command triggered via the keyboard
* \author Norman Feske
* \date 2016-02-01
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _COMMAND_H_
#define _COMMAND_H_
#include <target.h>
namespace Window_layouter { class Command; }
struct Window_layouter::Command
{
enum Type { NONE, NEXT_WINDOW, PREV_WINDOW, RAISE_WINDOW, TOGGLE_FULLSCREEN,
NEXT_TAB, PREV_TAB, SCREEN, RELEASE_GRAB, };
Type type;
Target::Name target;
static Command from_xml(Xml_node const &node)
{
auto from_string = [] (auto const &string) -> Type
{
if (string == "next_window") return NEXT_WINDOW;
if (string == "prev_window") return PREV_WINDOW;
if (string == "raise_window") return RAISE_WINDOW;
if (string == "toggle_fullscreen") return TOGGLE_FULLSCREEN;
if (string == "screen") return SCREEN;
if (string == "release_grab") return RELEASE_GRAB;
warning("cannot convert \"", string, "\" to action type");
return NONE;
};
return {
.type = from_string(node.attribute_value("action", String<32>())),
.target = node.attribute_value("target", Name())
};
}
};
#endif /* _COMMAND_H_ */

View File

@ -24,13 +24,13 @@ struct Window_layouter::Decorator_margins
{
unsigned top, bottom, left, right;
Decorator_margins(Xml_node node)
:
top (node.attribute_value("top", 0U)),
bottom(node.attribute_value("bottom", 0U)),
left (node.attribute_value("left", 0U)),
right (node.attribute_value("right", 0U))
{ }
static Decorator_margins from_xml(Xml_node const &node)
{
return { .top = node.attribute_value("top", 0U),
.bottom = node.attribute_value("bottom", 0U),
.left = node.attribute_value("left", 0U),
.right = node.attribute_value("right", 0U) };
}
/**
* Convert outer geometry to inner geometry

View File

@ -15,7 +15,7 @@
#define _KEY_SEQUENCE_TRACKER_H_
/* local includes */
#include "action.h"
#include <command.h>
namespace Window_layouter { class Key_sequence_tracker; }
@ -28,20 +28,18 @@ class Window_layouter::Key_sequence_tracker
{
struct Entry
{
enum Type { PRESS, RELEASE };
bool press;
Type type = PRESS;
Input::Keycode keycode = Input::KEY_UNKNOWN;
Entry() { }
Entry(Type type, Input::Keycode keycode)
: type(type), keycode(keycode) { }
Input::Keycode key;
bool operator == (Entry const &other) const
{
return other.type == type && other.keycode == keycode;
return other.press == press && other.key == key;
}
void print(Output &out) const
{
Genode::print(out, press ? "press " : "release ", Input::key_name(key));
}
};
@ -50,7 +48,7 @@ class Window_layouter::Key_sequence_tracker
* sequence.
*/
enum { MAX_ENTRIES = 64 };
Entry entries[MAX_ENTRIES];
Entry entries[MAX_ENTRIES] { };
unsigned pos = 0;
@ -91,82 +89,69 @@ class Window_layouter::Key_sequence_tracker
}
void reset() { pos = 0; }
void print(Output &out) const
{
Genode::print(out, "[", pos, "]: ");
for (unsigned i = 0; i < pos; i++)
Genode::print(out, " ", entries[i]);
}
};
Stack _stack { };
Xml_node _matching_sub_node(Xml_node curr, Stack::Entry entry)
void _with_matching_sub_node(Xml_node const &curr, Stack::Entry entry,
auto const &fn, auto const &no_match_fn) const
{
char const *node_type = entry.type == Stack::Entry::PRESS
? "press" : "release";
auto const node_type = entry.press ? "press" : "release";
using Key_name = String<32>;
Key_name const key(Input::key_name(entry.keycode));
Xml_node result("<none/>");
Key_name const key(Input::key_name(entry.key));
bool done = false; /* process the first match only */
curr.for_each_sub_node(node_type, [&] (Xml_node const &node) {
if (!done && node.attribute_value("key", Key_name()) == key) {
fn(node);
done = true; } });
if (node.attribute_value("key", Key_name()) != key)
return;
/* set 'result' only once, so we return the first match */
if (result.has_type("none"))
result = node;
});
return result;
if (!done)
no_match_fn();
}
void _with_match_rec(unsigned const pos, Xml_node const &node, auto const &fn) const
{
if (pos == _stack.pos) {
fn(node);
return;
}
/* recursion is bounded by Stack::MAX_ENTRIES */
_with_matching_sub_node(node, _stack.entries[pos],
[&] (Xml_node const &sub_node) {
if (pos < _stack.pos)
_with_match_rec(pos + 1, sub_node, fn); },
[&] { });
};
/**
* Lookup XML node that matches the state of the key sequence
* Call 'fn' with XML node that matches the state of the key sequence
*
* Traverse the nested '<press>' and '<release>' nodes of the
* configuration according to the history of events of the current
* sequence.
*
* \return XML node of the type '<press>' or '<release>'.
* If the configuration does not contain a matching node, the
* method returns a dummy node '<none>'.
*/
Xml_node _xml_by_path(Xml_node config)
void _with_xml_by_path(Xml_node const &config, auto const &fn) const
{
Xml_node curr = config;
/*
* Each iteration corresponds to a nesting level
*/
for (unsigned i = 0; i < _stack.pos; i++) {
Stack::Entry const entry = _stack.entries[i];
Xml_node const match = _matching_sub_node(curr, entry);
if (match.has_type("none"))
return match;
curr = match;
}
return curr;
_with_match_rec(0, config, fn);
}
/**
* Execute action denoted in the specific XML node
* Execute command denoted in the specific XML node
*/
template <typename FUNC>
void _execute_action(Xml_node node, FUNC const &func)
void _execute_command(Xml_node node, auto const &fn)
{
if (!node.has_attribute("action"))
return;
using Action = String<32>;
Action action = node.attribute_value("action", Action());
using Name = Window_layouter::Target::Name;
Name const target = node.attribute_value("target", Name());
func(Window_layouter::Action(action, target));
if (node.has_attribute("action"))
fn(Command::from_xml(node));
}
public:
@ -179,13 +164,12 @@ class Window_layouter::Key_sequence_tracker
/**
* Apply event to key sequence
*
* \param func functor to be called if the event leads to a node in
* the key-sequence configuration and the node is
* equipped with an 'action' attribute. The functor is
* called with an 'Action' as argument.
* \param fn functor to be called if the event leads to a node in
* the key-sequence configuration and the node is
* equipped with an 'action' attribute. The functor is
* called with an 'Action' as argument.
*/
template <typename FUNC>
void apply(Input::Event const &ev, Xml_node config, FUNC const &func)
void apply(Input::Event const &ev, Xml_node const &config, auto const &fn)
{
/*
* If the sequence contains a press-release combination for
@ -194,44 +178,44 @@ class Window_layouter::Key_sequence_tracker
* once.
*/
ev.handle_press([&] (Input::Keycode key, Codepoint) {
_stack.flush(Stack::Entry(Stack::Entry::PRESS, key));
_stack.flush(Stack::Entry(Stack::Entry::RELEASE, key));
_stack.flush(Stack::Entry { .press = true, .key = key });
_stack.flush(Stack::Entry { .press = false, .key = key });
});
Xml_node curr_node = _xml_by_path(config);
_with_xml_by_path(config, [&] (Xml_node const &curr_node) {
ev.handle_press([&] (Input::Keycode key, Codepoint) {
ev.handle_press([&] (Input::Keycode key, Codepoint) {
Stack::Entry const entry(Stack::Entry::PRESS, key);
Stack::Entry const press { .press = true, .key = key };
_execute_action(_matching_sub_node(curr_node, entry), func);
_stack.push(entry);
});
_with_matching_sub_node(curr_node, press,
[&] (Xml_node const &node) { _execute_command(node, fn); },
[&] { });
ev.handle_release([&] (Input::Keycode key) {
_stack.push(press);
});
Stack::Entry const entry(Stack::Entry::RELEASE, key);
ev.handle_release([&] (Input::Keycode key) {
Xml_node const next_node = _matching_sub_node(curr_node, entry);
Stack::Entry const release { .press = false, .key = key };
/*
* If there exists a specific path for the release event,
* follow the path. Otherwise, we remove the released key from
* the sequence.
*/
if (!next_node.has_type("none")) {
_execute_action(next_node, func);
_stack.push(entry);
} else {
Stack::Entry entry(Stack::Entry::PRESS, key);
_stack.flush(entry);
}
/*
* If there exists a specific path for the release event,
* follow the path. Otherwise, we remove the released key
* from the sequence.
*/
_with_matching_sub_node(curr_node, release,
[&] (Xml_node const &next_node) {
_execute_command(next_node, fn);
_stack.push(release);
},
[&] /* no match */ {
Stack::Entry const press { .press = true, .key = key };
_stack.flush(press);
});
});
});
}
};
#endif /* _KEY_SEQUENCE_TRACKER_H_ */

View File

@ -28,7 +28,7 @@ class Window_layouter::Layout_rules : Noncopyable
{
public:
struct Change_handler : Interface
struct Action : Interface
{
virtual void layout_rules_changed() = 0;
};
@ -39,7 +39,7 @@ class Window_layouter::Layout_rules : Noncopyable
Allocator &_alloc;
Change_handler &_change_handler;
Action &_action;
Constructible<Buffered_xml> _config_rules { };
@ -49,19 +49,19 @@ class Window_layouter::Layout_rules : Noncopyable
Attached_rom_dataspace rom;
Change_handler &_change_handler;
Action &_action;
void _handle()
{
rom.update();
_change_handler.layout_rules_changed();
_action.layout_rules_changed();
}
Signal_handler<Rom_rules> _handler;
Rom_rules(Env &env, Change_handler &change_handler)
Rom_rules(Env &env, Action &action)
:
rom(env, node_type()), _change_handler(change_handler),
rom(env, node_type()), _action(action),
_handler(env.ep(), *this, &Rom_rules::_handle)
{
rom.sigh(_handler);
@ -73,9 +73,9 @@ class Window_layouter::Layout_rules : Noncopyable
public:
Layout_rules(Env &env, Allocator &alloc, Change_handler &change_handler)
Layout_rules(Env &env, Allocator &alloc, Action &action)
:
_env(env), _alloc(alloc), _change_handler(change_handler)
_env(env), _alloc(alloc), _action(action)
{ }
void update_config(Xml_node config)
@ -83,14 +83,14 @@ class Window_layouter::Layout_rules : Noncopyable
bool const use_rules_from_rom =
(config.attribute_value(Rom_rules::node_type(), String<10>()) == "rom");
_rom_rules.conditional(use_rules_from_rom, _env, _change_handler);
_rom_rules.conditional(use_rules_from_rom, _env, _action);
_config_rules.destruct();
if (config.has_sub_node(Rom_rules::node_type()))
_config_rules.construct(_alloc, config.sub_node(Rom_rules::node_type()));
_change_handler.layout_rules_changed();
_action.layout_rules_changed();
}
/**
@ -102,8 +102,7 @@ class Window_layouter::Layout_rules : Noncopyable
* definitions are present, the rules ROM - if valid - takes
* precedence over the configuration's '<rules>' node.
*/
template <typename FN>
void with_rules(FN const &fn) const
void with_rules(auto const &fn) const
{
if (_rom_rules.constructed()) {
Xml_node const rules = _rom_rules->rom.xml();

View File

@ -30,14 +30,13 @@
#include <assign_list.h>
#include <target_list.h>
#include <user_state.h>
#include <operations.h>
namespace Window_layouter { struct Main; }
struct Window_layouter::Main : Operations,
Layout_rules::Change_handler,
Window_list::Change_handler
struct Window_layouter::Main : User_state::Action,
Layout_rules::Action,
Window_list::Action
{
Env &_env;
@ -63,7 +62,7 @@ struct Window_layouter::Main : Operations,
Layout_rules _layout_rules { _env, _heap, *this };
Decorator_margins _decorator_margins { Xml_node("<floating/>") };
Decorator_margins _decorator_margins { };
Window_list _window_list {
_env, _heap, *this, _focus_history, _decorator_margins };
@ -104,17 +103,17 @@ struct Window_layouter::Main : Operations,
_assign_list.for_each([&] (Assign &assign) {
_target_list.for_each([&] (Target const &target) {
if (target.name() != assign.target_name)
if (target.name != assign.target_name)
return;
assign.for_each_member([&] (Assign::Member &member) {
member.window.floating(assign.floating());
member.window.target_area(target.geometry().area);
member.window.target_area(target.rect.area);
Rect const rect = assign.window_geometry(member.window.id().value,
Rect const rect = assign.window_geometry(member.window.id.value,
member.window.client_size(),
target.geometry().area,
target.rect.area,
_decorator_margins);
member.window.outer_geometry(rect);
member.window.maximized(assign.maximized());
@ -135,7 +134,7 @@ struct Window_layouter::Main : Operations,
}
/**
* Layout_rules::Change_handler interface
* Layout_rules::Action interface
*/
void layout_rules_changed() override
{
@ -145,7 +144,7 @@ struct Window_layouter::Main : Operations,
}
/**
* Window_list::Change_handler interface
* Window_list::Action interface
*/
void window_list_changed() override { _update_window_layout(); }
@ -165,9 +164,9 @@ struct Window_layouter::Main : Operations,
User_state _user_state { *this, _focus_history };
/**************************
** Operations interface **
**************************/
/**********************************
** User_state::Action interface **
**********************************/
void close(Window_id id) override
{
@ -226,11 +225,11 @@ struct Window_layouter::Main : Operations,
_assign_list.for_each([&] (Assign &assign) {
Window *window_ptr = nullptr;
assign.for_each_member([&] (Assign::Member &member) {
if (member.window.id() == id)
if (member.window.id == id)
window_ptr = &member.window; });
if (window_ptr) {
assign.target_name = to.name();
window_ptr->warp(from.geometry().at - to.geometry().at);
assign.target_name = to.name;
window_ptr->warp(from.rect.at - to.rect.at);
}
});
}
@ -240,7 +239,7 @@ struct Window_layouter::Main : Operations,
/* change of screen under the dragged window */
if (_drag.dragging())
_with_target_change(_drag.window_id, name, [&] (Target const &from, Target const &to) {
if (from.geometry() == to.geometry())
if (from.rect == to.rect)
_retarget_window(_drag.window_id, from, to); });
_gen_rules_with_frontmost_screen(name);
@ -253,7 +252,7 @@ struct Window_layouter::Main : Operations,
bool const moving = _moving(id, element);
_target_list.with_target_at(curr, [&] (Target const &pointed) {
_drag = { Drag::State::DRAGGING, moving, id, curr, pointed.geometry() }; });
_drag = { Drag::State::DRAGGING, moving, id, curr, pointed.rect }; });
to_front(id);
@ -319,8 +318,8 @@ struct Window_layouter::Main : Operations,
bool const moving = _moving(id, element);
if (moving) {
_target_list.with_target_at(curr, [&] (Target const &pointed) {
_drag = { Drag::State::SETTLING, moving, id, curr, pointed.geometry() };
_with_target_change(id, pointed.name(), [&] (Target const &from, Target const &to) {
_drag = { Drag::State::SETTLING, moving, id, curr, pointed.rect };
_with_target_change(id, pointed.name, [&] (Target const &from, Target const &to) {
_retarget_window(id, from, to); });
});
}
@ -359,8 +358,8 @@ struct Window_layouter::Main : Operations,
_decorator_margins_rom.update();
Xml_node const margins = _decorator_margins_rom.xml();
if (margins.has_sub_node("floating"))
_decorator_margins = Decorator_margins(margins.sub_node("floating"));
margins.with_optional_sub_node("floating", [&] (Xml_node const floating) {
_decorator_margins = Decorator_margins::from_xml(floating); });
/* respond to change by adapting the maximized window geometry */
_handle_mode_change();
@ -424,8 +423,7 @@ struct Window_layouter::Main : Operations,
_gen_rules_with_frontmost_screen(Target::Name());
}
template <typename FN>
void _gen_rules_assignments(Xml_generator &, FN const &);
void _gen_rules_assignments(Xml_generator &, auto const &);
/**
* Constructor
@ -461,11 +459,11 @@ void Window_layouter::Main::_gen_window_layout()
/* update hover and focus state of each window */
_window_list.for_each_window([&] (Window &window) {
window.focused(window.has_id(_user_state.focused_window_id()));
window.focused(window.id == _user_state.focused_window_id());
bool const hovered = window.has_id(_user_state.hover_state().window_id);
bool const hovered = (window.id == _user_state.hover_state().window_id);
window.hovered(hovered ? _user_state.hover_state().element
: Window::Element::UNDEFINED);
: Window::Element { });
});
_window_layout_reporter.generate([&] (Xml_generator &xml) {
@ -502,8 +500,7 @@ void Window_layouter::Main::_gen_focus()
}
template <typename FN>
void Window_layouter::Main::_gen_rules_assignments(Xml_generator &xml, FN const &filter)
void Window_layouter::Main::_gen_rules_assignments(Xml_generator &xml, auto const &filter_fn)
{
auto gen_window_geometry = [] (Xml_generator &xml,
Assign const &assign, Window const &window) {
@ -517,11 +514,11 @@ void Window_layouter::Main::_gen_rules_assignments(Xml_generator &xml, FN const
/* turn wildcard assignments into exact assignments */
auto fn = [&] (Assign const &assign, Assign::Member const &member) {
if (!filter(member.window))
if (!filter_fn(member.window))
return;
xml.node("assign", [&] () {
xml.attribute("label", member.window.label());
xml.attribute("label", member.window.label);
xml.attribute("target", assign.target_name);
gen_window_geometry(xml, assign, member.window);
});
@ -546,7 +543,7 @@ void Window_layouter::Main::_gen_rules_assignments(Xml_generator &xml, FN const
assign.for_each_member([&] (Assign::Member const &member) {
if (geometry_generated || !filter(member.window))
if (geometry_generated || !filter_fn(member.window))
return;
xml.node("assign", [&] () {
@ -618,69 +615,20 @@ void Window_layouter::Main::_gen_rules_with_frontmost_screen(Target::Name const
}
/**
* Determine window element that corresponds to hover model
*/
static Window_layouter::Window::Element
_element_from_hover_model(Genode::Xml_node hover_window_xml)
{
using Type = Window_layouter::Window::Element::Type;
bool const left_sizer = hover_window_xml.has_sub_node("left_sizer"),
right_sizer = hover_window_xml.has_sub_node("right_sizer"),
top_sizer = hover_window_xml.has_sub_node("top_sizer"),
bottom_sizer = hover_window_xml.has_sub_node("bottom_sizer");
if (left_sizer && top_sizer) return Type::TOP_LEFT;
if (left_sizer && bottom_sizer) return Type::BOTTOM_LEFT;
if (left_sizer) return Type::LEFT;
if (right_sizer && top_sizer) return Type::TOP_RIGHT;
if (right_sizer && bottom_sizer) return Type::BOTTOM_RIGHT;
if (right_sizer) return Type::RIGHT;
if (top_sizer) return Type::TOP;
if (bottom_sizer) return Type::BOTTOM;
if (hover_window_xml.has_sub_node("title")) return Type::TITLE;
if (hover_window_xml.has_sub_node("closer")) return Type::CLOSER;
if (hover_window_xml.has_sub_node("maximizer")) return Type::MAXIMIZER;
if (hover_window_xml.has_sub_node("minimizer")) return Type::MINIMIZER;
return Type::UNDEFINED;
}
void Window_layouter::Main::_handle_hover()
{
_hover.update();
User_state::Hover_state const orig_hover_state = _user_state.hover_state();
try {
Xml_node const hover_window_xml = _hover.xml().sub_node("window");
_user_state.hover({ hover_window_xml.attribute_value("id", 0U) },
_element_from_hover_model(hover_window_xml));
}
/*
* An exception may occur during the 'Xml_node' construction if the hover
* model lacks a window. Under this condition, we invalidate the hover
* state.
*/
catch (...) {
_user_state.reset_hover();
/*
* Don't generate a focus-model update here. In a situation where the
* pointer has moved over a native GUI view (outside the realm of
* the window manager), the hover model as generated by the decorator
* naturally becomes empty. If we posted a focus update, this would
* steal the focus away from the native GUI view.
*/
}
_hover.xml().with_sub_node("window",
[&] (Xml_node const &hover) {
_user_state.hover({ hover.attribute_value("id", 0U) },
Window::Element::from_xml(hover));
},
[&] /* the hover model lacks a window */ {
_user_state.reset_hover();
});
/*
* Propagate changed hovering to the decorator
@ -698,7 +646,7 @@ void Window_layouter::Main::_handle_focus_request()
{
_focus_request.update();
int const id = (int)_focus_request.xml().attribute_value("id", 0L);
int const id = _focus_request.xml().attribute_value("id", 0);
/* don't apply the same focus request twice */
if (id == _handled_focus_request_id)
@ -718,9 +666,9 @@ void Window_layouter::Main::_handle_focus_request()
_window_list.for_each_window([&] (Window &window) {
if (label_matches(prefix, window.label())) {
if (label_matches(prefix, window.label)) {
window.to_front_cnt(next_to_front_cnt);
_user_state.focused_window_id(window.id());
_user_state.focused_window_id(window.id);
stacking_order_changed = true;
}
});

View File

@ -1,38 +0,0 @@
/*
* \brief Window layouter
* \author Norman Feske
* \date 2015-12-31
*/
/*
* Copyright (C) 2015-2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _OPERATIONS_H_
#define _OPERATIONS_H_
/* Genode includes */
#include <util/interface.h>
/* local includes */
#include "window.h"
namespace Window_layouter { struct Operations; }
struct Window_layouter::Operations : Interface
{
virtual void close(Window_id) = 0;
virtual void toggle_fullscreen(Window_id) = 0;
virtual void focus(Window_id) = 0;
virtual void release_grab() = 0;
virtual void to_front(Window_id) = 0;
virtual void drag(Window_id, Window::Element, Point clicked, Point curr) = 0;
virtual void finalize_drag(Window_id, Window::Element, Point clicked, Point final) = 0;
virtual void screen(Target::Name const &) = 0;
};
#endif /* _OPERATIONS_H_ */

View File

@ -20,38 +20,27 @@
namespace Window_layouter { class Target; }
class Window_layouter::Target : Noncopyable
struct Window_layouter::Target : Noncopyable
{
public:
using Name = String<64>;
using Name = String<64>;
struct Visible { bool value; };
struct Visible { bool value; };
Name const name;
unsigned const layer;
Rect const rect;
bool const visible;
private:
Target(Xml_node target, Rect rect, Visible visible)
:
name (target.attribute_value("name", Name())),
layer(target.attribute_value("layer", 9999U)),
rect (rect),
visible(visible.value)
{ }
Name const _name;
unsigned const _layer;
Rect const _geometry;
bool const _visible;
public:
Target(Xml_node target, Rect geometry, Visible visible)
:
_name (target.attribute_value("name", Name())),
_layer(target.attribute_value("layer", 9999U)),
_geometry(geometry),
_visible(visible.value)
{ }
/* needed to use class as 'Registered<Target>' */
virtual ~Target() { }
Name name() const { return _name; }
unsigned layer() const { return _layer; }
Rect geometry() const { return _geometry; }
bool visible() const { return _visible; }
/* needed to use class as 'Registered<Target>' */
virtual ~Target() { }
};
#endif /* _TARGET_H_ */

View File

@ -144,8 +144,8 @@ class Window_layouter::Target_list
/* search targets for next matching layer */
unsigned layer = MAX_LAYER;
_targets.for_each([&] (Target const &target) {
if (target.layer() >= min_layer && target.layer() <= layer)
layer = target.layer(); });
if (target.layer >= min_layer && target.layer <= layer)
layer = target.layer; });
Rect const drag_origin_boundary = drag.dragging() && drag.moving
? target_boundary(assignments, drag.window_id)
@ -153,31 +153,31 @@ class Window_layouter::Target_list
/* search target by name */
_targets.for_each([&] (Target const &target) {
if (target.layer() != layer)
if (target.layer != layer)
return;
if (!target.visible())
if (!target.visible)
return;
if (assignments.target_empty(target.name()) && !drag.moving_at_target_rect(target.geometry()))
if (assignments.target_empty(target.name) && !drag.moving_at_target_rect(target.rect))
return;
Rect const boundary = target.geometry();
Rect const boundary = target.rect;
xml.node("boundary", [&] {
xml.attribute("name", target.name());
xml.attribute("name", target.name);
generate(xml, boundary);
/* in-flux window node for the currently dragged window */
if (drag.moving_at_target_rect(target.geometry()))
if (drag.moving_at_target_rect(target.rect))
assignments.for_each([&] (Assign const &assign) {
assign.for_each_member([&] (Assign::Member const &member) {
if (drag.moving_window(member.window.id()))
if (drag.moving_window(member.window.id))
member.window.generate(xml, drag_origin_boundary); }); });
/* visit all windows on the layer, except for the dragged one */
assignments.for_each_visible(target.name(), [&] (Assign const &assign) {
assignments.for_each_visible(target.name, [&] (Assign const &assign) {
assign.for_each_member([&] (Assign::Member const &member) {
if (!drag.moving_window(member.window.id()))
if (!drag.moving_window(member.window.id))
member.window.generate(xml, boundary); }); });
});
});
@ -291,7 +291,7 @@ class Window_layouter::Target_list
{
Target const *ptr = nullptr;
for_each([&] (Target const &target) {
if (target.name() == name)
if (target.name == name)
ptr = &target; });
if (ptr)
fn(*ptr);
@ -301,7 +301,7 @@ class Window_layouter::Target_list
{
Target const *ptr = nullptr;
for_each([&] (Target const &target) {
if (target.visible() && target.geometry().contains(at))
if (target.visible && target.rect.contains(at))
ptr = &target; });
if (ptr)
fn(*ptr);
@ -311,9 +311,9 @@ class Window_layouter::Target_list
{
Target const *ptr = nullptr;
_targets.for_each([&] (Target const &target) {
assignments.for_each_visible(target.name(), [&] (Assign const &assign) {
assignments.for_each_visible(target.name, [&] (Assign const &assign) {
assign.for_each_member([&] (Assign::Member const &member) {
if (member.window.id() == id)
if (member.window.id == id)
ptr = &target; }); }); });
if (ptr)
fn(*ptr);
@ -326,10 +326,9 @@ class Window_layouter::Target_list
{
Rect result { };
with_target(assignments, id, [&] (Target const &target) {
result = target.geometry(); });
result = target.rect; });
return result;
}
};
#endif /* _TARGET_LIST_H_ */

View File

@ -15,8 +15,7 @@
#define _USER_STATE_H_
/* local includes */
#include "operations.h"
#include "key_sequence_tracker.h"
#include <key_sequence_tracker.h>
namespace Window_layouter { class User_state; }
@ -25,15 +24,22 @@ class Window_layouter::User_state
{
public:
struct Action : Interface
{
virtual void close(Window_id) = 0;
virtual void toggle_fullscreen(Window_id) = 0;
virtual void focus(Window_id) = 0;
virtual void release_grab() = 0;
virtual void to_front(Window_id) = 0;
virtual void drag(Window_id, Window::Element, Point clicked, Point curr) = 0;
virtual void finalize_drag(Window_id, Window::Element, Point clicked, Point final) = 0;
virtual void screen(Target::Name const &) = 0;
};
struct Hover_state
{
Window_id window_id;
Window::Element element { Window::Element::UNDEFINED };
Hover_state(Window_id id, Window::Element element)
:
window_id(id), element(element)
{ }
Window::Element element;
bool operator != (Hover_state const &other) const
{
@ -44,16 +50,18 @@ class Window_layouter::User_state
private:
Action &_action;
Window_id _hovered_window_id { };
Window_id _focused_window_id { };
Window_id _dragged_window_id { };
unsigned _key_cnt = 0;
unsigned _key_cnt = 0;
Key_sequence_tracker _key_sequence_tracker { };
Window::Element _hovered_element = Window::Element::UNDEFINED;
Window::Element _dragged_element = Window::Element::UNDEFINED;
Window::Element _hovered_element { };
Window::Element _dragged_element { };
/*
* True while drag operation in progress
@ -77,8 +85,6 @@ class Window_layouter::User_state
*/
Point _pointer_curr { };
Operations &_operations;
Focus_history &_focus_history;
/*
@ -107,16 +113,16 @@ class Window_layouter::User_state
/*
* Toggle maximized (fullscreen) state
*/
if (_hovered_element == Window::Element::MAXIMIZER) {
if (_hovered_element.maximizer()) {
_dragged_window_id = _hovered_window_id;
_focused_window_id = _hovered_window_id;
_focus_history.focus(_focused_window_id);
_operations.toggle_fullscreen(_hovered_window_id);
_action.toggle_fullscreen(_hovered_window_id);
_hovered_element = Window::Element::UNDEFINED;
_hovered_window_id = Window_id();
_hovered_element = { };
_hovered_window_id = { };
return;
}
@ -128,19 +134,19 @@ class Window_layouter::User_state
_focused_window_id = _hovered_window_id;
_focus_history.focus(_focused_window_id);
_operations.to_front(_hovered_window_id);
_operations.focus(_hovered_window_id);
_action.to_front(_hovered_window_id);
_action.focus(_hovered_window_id);
}
_operations.drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
_action.drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
}
public:
User_state(Operations &operations, Focus_history &focus_history)
User_state(Action &action, Focus_history &focus_history)
:
_operations(operations), _focus_history(focus_history)
_action(action), _focus_history(focus_history)
{ }
void handle_input(Input::Event const events[], unsigned num_events,
@ -155,8 +161,8 @@ class Window_layouter::User_state
* Issue drag operation when in dragged state
*/
if (_drag_state && _drag_init_done && (_pointer_curr != pointer_last))
_operations.drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
_action.drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
}
void hover(Window_id window_id, Window::Element element)
@ -186,15 +192,13 @@ class Window_layouter::User_state
/*
* Let focus follows the pointer
*
* XXX obtain policy from config
*/
if (!_drag_state && _hovered_window_id.valid()
&& _hovered_window_id != last_hovered_window_id) {
_focused_window_id = _hovered_window_id;
_focus_history.focus(_focused_window_id);
_operations.focus(_focused_window_id);
_action.focus(_focused_window_id);
}
}
@ -204,8 +208,8 @@ class Window_layouter::User_state
if (_drag_state)
return;
_hovered_element = Window::Element::UNDEFINED;
_hovered_window_id = Window_id();
_hovered_element = { };
_hovered_window_id = { };
}
Window_id focused_window_id() const { return _focused_window_id; }
@ -225,8 +229,8 @@ void Window_layouter::User_state::_handle_event(Input::Event const &e,
if (e.absolute_motion() || e.focus_enter()) {
if (_drag_state && _drag_init_done)
_operations.drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
_action.drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
}
/* track number of pressed buttons/keys */
@ -277,12 +281,12 @@ void Window_layouter::User_state::_handle_event(Input::Event const &e,
/*
* Issue resize to 0x0 when releasing the the window closer
*/
if (_dragged_element == Window::Element::CLOSER)
if (_dragged_element.closer())
if (_dragged_element == _hovered_element)
_operations.close(_dragged_window_id);
_action.close(_dragged_window_id);
_operations.finalize_drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
_action.finalize_drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
}
}
@ -292,38 +296,38 @@ void Window_layouter::User_state::_handle_event(Input::Event const &e,
if (e.press() && _key_cnt == 1)
_key_sequence_tracker.reset();
_key_sequence_tracker.apply(e, config, [&] (Action action) {
_key_sequence_tracker.apply(e, config, [&] (Command const &command) {
switch (action.type()) {
switch (command.type) {
case Action::TOGGLE_FULLSCREEN:
_operations.toggle_fullscreen(_focused_window_id);
case Command::TOGGLE_FULLSCREEN:
_action.toggle_fullscreen(_focused_window_id);
return;
case Action::RAISE_WINDOW:
_operations.to_front(_focused_window_id);
case Command::RAISE_WINDOW:
_action.to_front(_focused_window_id);
return;
case Action::NEXT_WINDOW:
case Command::NEXT_WINDOW:
_focused_window_id = _focus_history.next(_focused_window_id);
_operations.focus(_focused_window_id);
_action.focus(_focused_window_id);
return;
case Action::PREV_WINDOW:
case Command::PREV_WINDOW:
_focused_window_id = _focus_history.prev(_focused_window_id);
_operations.focus(_focused_window_id);
_action.focus(_focused_window_id);
return;
case Action::SCREEN:
_operations.screen(action.target_name());
case Command::SCREEN:
_action.screen(command.target);
return;
case Action::RELEASE_GRAB:
_operations.release_grab();
case Command::RELEASE_GRAB:
_action.release_grab();
return;
default:
warning("action ", (int)action.type(), " unhanded");
warning("command ", (int)command.type, " unhanded");
}
});
}

View File

@ -58,7 +58,29 @@ class Window_layouter::Window : public List_model<Window>::Element
return "";
}
Element(Type type) : type(type) { }
static Element from_xml(Xml_node const &hover)
{
bool const left = hover.has_sub_node("left_sizer"),
right = hover.has_sub_node("right_sizer"),
top = hover.has_sub_node("top_sizer"),
bottom = hover.has_sub_node("bottom_sizer");
if (top && left) return { TOP_LEFT };
if (bottom && left) return { BOTTOM_LEFT };
if (left) return { LEFT };
if (top && right) return { TOP_RIGHT };
if (bottom && right) return { BOTTOM_RIGHT };
if (right) return { RIGHT };
if (top) return { TOP };
if (bottom) return { BOTTOM };
if (hover.has_sub_node("title")) return { TITLE };
if (hover.has_sub_node("closer")) return { CLOSER };
if (hover.has_sub_node("maximizer")) return { MAXIMIZER };
if (hover.has_sub_node("minimizer")) return { MINIMIZER };
return { UNDEFINED };
}
bool operator != (Element const &other) const { return other.type != type; }
bool operator == (Element const &other) const { return other.type == type; }
@ -71,16 +93,29 @@ class Window_layouter::Window : public List_model<Window>::Element
|| type == BOTTOM_LEFT || type == BOTTOM_RIGHT
|| type == MAXIMIZER;
}
bool _any_of(Type t1, Type t2, Type t3) const
{
return type == t1 || type == t2 || type == t3;
}
bool left() const { return _any_of(LEFT, TOP_LEFT, BOTTOM_LEFT); }
bool right() const { return _any_of(RIGHT, TOP_RIGHT, BOTTOM_RIGHT); }
bool top() const { return _any_of(TOP, TOP_LEFT, TOP_RIGHT); }
bool bottom() const { return _any_of(BOTTOM, BOTTOM_LEFT, BOTTOM_RIGHT); }
bool maximizer() const { return type == MAXIMIZER; }
bool closer() const { return type == CLOSER; }
};
Window_id const id;
Label const label;
private:
Window_id const _id;
Title _title { };
Label const _label;
Decorator_margins const &_decorator_margins;
Rect _geometry { };
@ -172,10 +207,13 @@ class Window_layouter::Window : public List_model<Window>::Element
Focus_history::Entry _focus_history_entry;
bool _drag_left_border = false;
bool _drag_right_border = false;
bool _drag_top_border = false;
bool _drag_bottom_border = false;
struct Dragged_border
{
bool left, right, top, bottom;
bool any() const { return left || right || top || bottom; };
} _dragged_border { };
/**
* Called when the user starts dragging a window element
@ -185,22 +223,10 @@ class Window_layouter::Window : public List_model<Window>::Element
_dragged_element = element;
if (_resizeable) {
_drag_left_border = (element.type == Window::Element::LEFT)
|| (element.type == Window::Element::TOP_LEFT)
|| (element.type == Window::Element::BOTTOM_LEFT);
_drag_right_border = (element.type == Window::Element::RIGHT)
|| (element.type == Window::Element::TOP_RIGHT)
|| (element.type == Window::Element::BOTTOM_RIGHT);
_drag_top_border = (element.type == Window::Element::TOP)
|| (element.type == Window::Element::TOP_LEFT)
|| (element.type == Window::Element::TOP_RIGHT);
_drag_bottom_border = (element.type == Window::Element::BOTTOM)
|| (element.type == Window::Element::BOTTOM_LEFT)
|| (element.type == Window::Element::BOTTOM_RIGHT);
_dragged_border.left = element.left();
_dragged_border.right = element.right();
_dragged_border.top = element.top();
_dragged_border.bottom = element.bottom();
}
_orig_geometry = _geometry;
@ -217,7 +243,7 @@ class Window_layouter::Window : public List_model<Window>::Element
void _apply_drag_operation(Point offset)
{
/* move window */
if (!_drag_border()) {
if (!_dragged_border.any()) {
_drag_geometry = Rect(_orig_geometry.p1() + offset,
_orig_geometry.area);
return;
@ -233,25 +259,16 @@ class Window_layouter::Window : public List_model<Window>::Element
auto clamped = [] (int v, int lowest, int highest) { return min(max(v, lowest), highest); };
if (_drag_left_border) x1 = clamped(min(x1 + offset.x, x2), inner.x1(), outer.x2());
if (_drag_right_border) x2 = clamped(max(x2 + offset.x, x1), outer.x1(), inner.x2());
if (_drag_top_border) y1 = clamped(min(y1 + offset.y, y2), inner.y1(), outer.y2());
if (_drag_bottom_border) y2 = clamped(max(y2 + offset.y, y1), outer.y1(), inner.y2());
if (_dragged_border.left) x1 = clamped(min(x1 + offset.x, x2), inner.x1(), outer.x2());
if (_dragged_border.right) x2 = clamped(max(x2 + offset.x, x1), outer.x1(), inner.x2());
if (_dragged_border.top) y1 = clamped(min(y1 + offset.y, y2), inner.y1(), outer.y2());
if (_dragged_border.bottom) y2 = clamped(max(y2 + offset.y, y1), outer.y1(), inner.y2());
_drag_geometry = Rect::compound(Point { x1, y1 }, Point { x2, y2 });
_dragged_size = _drag_geometry.area;
}
/**
* Return true if user drags a window border
*/
bool _drag_border() const
{
return _drag_left_border || _drag_right_border
|| _drag_top_border || _drag_bottom_border;
}
Constructible<Assign::Member> _assign_member { };
public:
@ -260,21 +277,15 @@ class Window_layouter::Window : public List_model<Window>::Element
Focus_history &focus_history,
Decorator_margins const &decorator_margins)
:
_id(id), _label(label),
id(id), label(label),
_decorator_margins(decorator_margins),
_client_size(initial_size),
_dragged_size(initial_size),
_focus_history_entry(focus_history, _id)
_focus_history_entry(focus_history, id)
{ }
bool has_id(Window_id id) const { return id == _id; }
Window_id id() const { return _id; }
void title(Title const &title) { _title = title; }
Label label() const { return _label; }
bool dragged() const { return _dragged; }
Rect effective_inner_geometry() const
@ -286,14 +297,14 @@ class Window_layouter::Window : public List_model<Window>::Element
x2 = _orig_geometry.x2(), y2 = _orig_geometry.y2();
/* move window */
if (!_drag_border())
if (!_dragged_border.any())
return _drag_geometry;
/* resize window */
if (_drag_left_border) x1 = x2 - _client_size.w + 1;
if (_drag_right_border) x2 = x1 + _client_size.w - 1;
if (_drag_top_border) y1 = y2 - _client_size.h + 1;
if (_drag_bottom_border) y2 = y1 + _client_size.h - 1;
if (_dragged_border.left) x1 = x2 - _client_size.w + 1;
if (_dragged_border.right) x2 = x1 + _client_size.w - 1;
if (_dragged_border.top) y1 = y2 - _client_size.h + 1;
if (_dragged_border.bottom) y2 = y1 + _client_size.h - 1;
return Rect::compound(Point(x1, y1), Point(x2, y2));
}
@ -335,8 +346,6 @@ class Window_layouter::Window : public List_model<Window>::Element
bool resizeable() const { return _resizeable; }
bool label_matches(Label const &label) const { return label == _label; }
/**
* Define window size
*
@ -370,7 +379,7 @@ class Window_layouter::Window : public List_model<Window>::Element
return;
xml.node("window", [&] () {
xml.attribute("id", _id.value);
xml.attribute("id", id.value);
xml.attribute("width", size.w);
xml.attribute("height", size.h);
});
@ -384,14 +393,14 @@ class Window_layouter::Window : public List_model<Window>::Element
xml.node("window", [&]() {
xml.attribute("id", _id.value);
xml.attribute("id", id.value);
/* present concatenation of label and title in the window's title bar */
{
bool const has_title = strlen(_title.string()) > 0;
String<Label::capacity()> const
title(_label, (has_title ? " " : ""), _title);
title(label, (has_title ? " " : ""), _title);
xml.attribute("title", title);
}
@ -471,13 +480,10 @@ class Window_layouter::Window : public List_model<Window>::Element
void finalize_drag_operation()
{
_drag_left_border = false;
_drag_right_border = false;
_drag_top_border = false;
_drag_bottom_border = false;
_geometry = effective_inner_geometry();
_dragged_size = _geometry.area;
_dragged = false;
_dragged_border = { };
_geometry = effective_inner_geometry();
_dragged_size = _geometry.area;
_dragged = false;
}
void to_front_cnt(unsigned to_front_cnt) { _to_front_cnt = to_front_cnt; }
@ -520,7 +526,7 @@ class Window_layouter::Window : public List_model<Window>::Element
*/
bool matches(Xml_node const &node) const
{
return node.attribute_value("id", 0U) == _id.value;
return node.attribute_value("id", 0U) == id.value;
}
/**

View File

@ -25,7 +25,7 @@ class Window_layouter::Window_list
{
public:
struct Change_handler : Interface
struct Action : Interface
{
virtual void window_list_changed() = 0;
};
@ -34,7 +34,7 @@ class Window_layouter::Window_list
Env &_env;
Allocator &_alloc;
Change_handler &_change_handler;
Action &_action;
Focus_history &_focus_history;
Decorator_margins const &_decorator_margins;
@ -79,20 +79,20 @@ class Window_layouter::Window_list
);
/* notify main program */
_change_handler.window_list_changed();
_action.window_list_changed();
}
public:
Window_list(Env &env,
Allocator &alloc,
Change_handler &change_handler,
Action &action,
Focus_history &focus_history,
Decorator_margins const &decorator_margins)
:
_env(env),
_alloc(alloc),
_change_handler(change_handler),
_action(action),
_focus_history(focus_history),
_decorator_margins(decorator_margins)
{
@ -107,27 +107,22 @@ class Window_layouter::Window_list
win.dissolve_from_assignment(); });
}
template <typename FN>
void with_window(Window_id id, FN const &fn)
void with_window(Window_id id, auto const &fn)
{
_list.for_each([&] (Window &win) {
if (win.has_id(id))
if (win.id == id)
fn(win); });
}
template <typename FN>
void with_window(Window_id id, FN const &fn) const
void with_window(Window_id id, auto const &fn) const
{
_list.for_each([&] (Window const &win) {
if (win.has_id(id))
if (win.id == id)
fn(win); });
}
template <typename FN>
void for_each_window(FN const &fn) { _list.for_each(fn); }
template <typename FN>
void for_each_window(FN const &fn) const { _list.for_each(fn); }
void for_each_window(auto const &fn) { _list.for_each(fn); }
void for_each_window(auto const &fn) const { _list.for_each(fn); }
};
#endif /* _WINDOW_LIST_H_ */