/* * \brief Window registry * \author Norman Feske * \date 2014-05-02 */ /* * Copyright (C) 2014 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #ifndef _WINDOW_REGISTRY_H_ #define _WINDOW_REGISTRY_H_ /* Genode includes */ #include #include #include #include #include /* gems includes */ #include namespace Wm { class Window_registry; } namespace Wm { using Genode::Allocator; using Genode::List; using Genode::Xml_generator; using Genode::Reporter; typedef Genode::Surface_base::Area Area; typedef Genode::Surface_base::Point Point; typedef Genode::Surface_base::Rect Rect; } class Wm::Window_registry { public: struct Id { unsigned value; Id(unsigned value) : value(value) { } Id() /* invalid */ : value(0) { } bool operator == (Id const &other) const { return value == other.value; } bool valid() const { return value != 0; } }; class Window : public List::Element { public: typedef Genode::String<200> Title; enum Has_alpha { HAS_ALPHA, HAS_NO_ALPHA }; enum Is_hidden { IS_HIDDEN, IS_NOT_HIDDEN }; private: Id const _id; Title _title; Area _size; Has_alpha _has_alpha = HAS_NO_ALPHA; Is_hidden _is_hidden = IS_NOT_HIDDEN; friend class Window_registry; Window(Id id) : _id(id) { } public: Id id() const { return _id; } /* * Accessors for setting attributes */ void attr(Title const &title) { _title = title; } void attr(Area size) { _size = size; } void attr(Has_alpha has_alpha) { _has_alpha = has_alpha; } void attr(Is_hidden is_hidden) { _is_hidden = is_hidden; } void generate_window_list_entry_xml(Xml_generator &xml) const { xml.node("window", [&] () { xml.attribute("id", _id.value); xml.attribute("title", _title.string()); xml.attribute("width", _size.w()); xml.attribute("height", _size.h()); if (_has_alpha == HAS_ALPHA) xml.attribute("has_alpha", "yes"); if (_is_hidden == IS_HIDDEN) xml.attribute("hidden", "yes"); }); } }; private: Allocator &_alloc; Reporter &_window_list_reporter; enum { MAX_WINDOWS = 1024 }; Genode::Bit_allocator _window_ids; List _windows; Window *_lookup(Id id) { for (Window *w = _windows.first(); w; w = w->next()) if (w->id() == id) return w; return 0; } void _report_updated_window_list_model() const { Reporter::Xml_generator xml(_window_list_reporter, [&] () { for (Window const *w = _windows.first(); w; w = w->next()) w->generate_window_list_entry_xml(xml); }); } template void _set_attr(Id const id, ATTR const &value) { Window * const win = _lookup(id); if (!win) { PWRN("lookup for window ID %d failed", id.value); return; } win->attr(value); _report_updated_window_list_model(); } public: Window_registry(Allocator &alloc, Reporter &window_list_reporter) : _alloc(alloc), _window_list_reporter(window_list_reporter) { /* preserve ID 0 to represent an invalid ID */ _window_ids.alloc(); } Id create() { Window * const win = new (_alloc) Window(_window_ids.alloc()); _windows.insert(win); /* * Even though we change the window-list model by adding a * window, we don't call '_report_updated_window_list_model' here * because the window does not have any useful properties before * the 'size' function has been called. * * XXX should we pass the initial size as argument to this function? */ return win->id(); } void destroy(Id id) { Window * const win = _lookup(id); if (!win) return; _windows.remove(win); Genode::destroy(&_alloc, win); _report_updated_window_list_model(); } void size(Id id, Area size) { _set_attr(id, size); } void title(Id id, Window::Title title) { _set_attr(id, title); } void has_alpha(Id id, bool has_alpha) { _set_attr(id, has_alpha ? Window::HAS_ALPHA : Window::HAS_NO_ALPHA); } void is_hidden(Id id, bool is_hidden) { _set_attr(id, is_hidden ? Window::IS_HIDDEN : Window::IS_NOT_HIDDEN); } }; #endif /* _WINDOW_REGISTRY_H_ */