d18f8eea2b
This patch adds the missing propagation of the maximized state from the layout rules to the internal representation of a window. Without this patch this state could be toggled by clicking on the maximizer button only.
240 lines
6.2 KiB
C++
240 lines
6.2 KiB
C++
/*
|
|
* \brief Assignment of window-manager clients to target area
|
|
* \author Norman Feske
|
|
* \date 2018-09-27
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 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 _ASSIGN_H_
|
|
#define _ASSIGN_H_
|
|
|
|
/* Genode includes */
|
|
#include <util/list_model.h>
|
|
#include <base/registry.h>
|
|
#include <os/buffered_xml.h>
|
|
|
|
/* local includes */
|
|
#include <types.h>
|
|
#include <target.h>
|
|
#include <decorator_margins.h>
|
|
|
|
namespace Window_layouter { class Assign; }
|
|
|
|
|
|
class Window_layouter::Assign : public List_model<Assign>::Element
|
|
{
|
|
public:
|
|
|
|
/*
|
|
* Used for associating windows with assignments. Hosted in 'Window'
|
|
* objects.
|
|
*/
|
|
struct Member : Registry<Member>::Element
|
|
{
|
|
Window &window;
|
|
|
|
Member(Registry<Member> ®istry, Window &window)
|
|
: Registry<Member>::Element(registry, *this), window(window) { }
|
|
};
|
|
|
|
typedef String<80> Label;
|
|
|
|
private:
|
|
|
|
Registry<Member> _members { };
|
|
|
|
Label const _label;
|
|
Label const _label_prefix;
|
|
Label const _label_suffix;
|
|
|
|
Target::Name _target_name { };
|
|
|
|
bool _pos_defined = false;
|
|
bool _xpos_any = false;
|
|
bool _ypos_any = false;
|
|
bool _size_defined = false;
|
|
bool _maximized = false;
|
|
|
|
Point _pos { };
|
|
Area _size { };
|
|
|
|
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()))
|
|
{ }
|
|
|
|
void update(Xml_node assign)
|
|
{
|
|
_target_name = assign.attribute_value("target", Target::Name());
|
|
_pos_defined = assign.has_attribute("xpos") && assign.has_attribute("ypos");
|
|
_size_defined = assign.has_attribute("width") && assign.has_attribute("height");
|
|
_maximized = assign.attribute_value("maximized", false);
|
|
_xpos_any = assign.attribute_value("xpos", String<20>()) == "any";
|
|
_ypos_any = assign.attribute_value("ypos", String<20>()) == "any";
|
|
_pos = point_attribute(assign);
|
|
_size = area_attribute(assign);
|
|
}
|
|
|
|
/*
|
|
* Used by 'Assign_list::update_from_xml'
|
|
*/
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Calculate window geometry
|
|
*/
|
|
Rect window_geometry(unsigned win_id, Area client_size, Rect target_geometry,
|
|
Decorator_margins const &decorator_margins) const
|
|
{
|
|
if (!_pos_defined)
|
|
return target_geometry;
|
|
|
|
Point const any_pos(150*win_id % 800, 30 + (100*win_id % 500));
|
|
|
|
Point const pos(_xpos_any ? any_pos.x() : _pos.x(),
|
|
_ypos_any ? any_pos.y() : _pos.y());
|
|
|
|
Rect const inner(pos, _size_defined ? _size : client_size);
|
|
Rect const outer = decorator_margins.outer_geometry(inner);
|
|
|
|
return Rect(outer.p1() + target_geometry.p1(), outer.area());
|
|
}
|
|
|
|
bool maximized() const { return _maximized; }
|
|
|
|
/**
|
|
* Call 'fn' with 'Registry<Member>' if label matches assignment
|
|
*
|
|
* This method is used for associating assignments to windows.
|
|
*/
|
|
template <typename FN>
|
|
void with_matching_members_registry(Label const &label, FN 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 = 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)
|
|
fn(_members);
|
|
}
|
|
|
|
Target::Name target_name() const { return _target_name; }
|
|
|
|
/**
|
|
* Used to generate <assign> nodes of windows captured via wildcard
|
|
*/
|
|
template <typename FN>
|
|
void for_each_wildcard_member(FN const &fn) const
|
|
{
|
|
/* skip non-wildcards */
|
|
if (_label.valid())
|
|
return;
|
|
|
|
_members.for_each([&] (Assign::Member const &member) { fn(member); });
|
|
}
|
|
|
|
/**
|
|
* Used to bring wildcard-matching windows to front
|
|
*/
|
|
template <typename FN>
|
|
void for_each_wildcard_member(FN const &fn)
|
|
{
|
|
if (_label.valid())
|
|
return;
|
|
|
|
_members.for_each([&] (Assign::Member &member) { fn(member); });
|
|
}
|
|
|
|
bool floating() const { return _pos_defined; }
|
|
|
|
bool wildcard() const { return !_label.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);
|
|
|
|
xml.attribute("target", _target_name);
|
|
}
|
|
|
|
void gen_geometry_attr(Xml_generator &xml) const
|
|
{
|
|
if (_pos_defined) {
|
|
if (_xpos_any) xml.attribute("xpos", "any");
|
|
else xml.attribute("xpos", _pos.x());
|
|
|
|
if (_ypos_any) xml.attribute("ypos", "any");
|
|
else xml.attribute("ypos", _pos.y());
|
|
}
|
|
|
|
if (_size_defined) {
|
|
xml.attribute("width", _size.w());
|
|
xml.attribute("height", _size.h());
|
|
}
|
|
|
|
if (_maximized)
|
|
xml.attribute("maximized", "yes");
|
|
}
|
|
|
|
struct Window_state
|
|
{
|
|
Rect geometry;
|
|
bool maximized;
|
|
};
|
|
|
|
void gen_geometry_attr(Xml_generator &xml, Window_state const &window) const
|
|
{
|
|
Rect const rect = window.maximized ? Rect(_pos, _size) : window.geometry;
|
|
|
|
if (_pos_defined) {
|
|
xml.attribute("xpos", rect.x1());
|
|
xml.attribute("ypos", rect.y1());
|
|
xml.attribute("width", rect.w());
|
|
xml.attribute("height", rect.h());
|
|
}
|
|
|
|
if (window.maximized)
|
|
xml.attribute("maximized", "yes");
|
|
}
|
|
|
|
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); }
|
|
};
|
|
|
|
#endif /* _ASSIGN_H_ */
|