diff --git a/repos/gems/src/app/backdrop/main.cc b/repos/gems/src/app/backdrop/main.cc index ff2da6a43c..5333e63455 100644 --- a/repos/gems/src/app/backdrop/main.cc +++ b/repos/gems/src/app/backdrop/main.cc @@ -47,6 +47,8 @@ struct Backdrop::Main Gui::Connection _gui { _env, "backdrop" }; + Gui::Rect _gui_win { }; + struct Buffer { Gui::Connection &gui; @@ -112,7 +114,7 @@ struct Backdrop::Main using Command = Gui::Session::Command; _gui.enqueue(_view_id); - Gui::Rect rect(Gui::Point(), _buffer->size()); + Gui::Rect rect(_gui_win.at, _buffer->size()); _gui.enqueue(_view_id, rect); _gui.enqueue(_view_id); _gui.execute(); @@ -139,8 +141,7 @@ struct Backdrop::Main { _gui.view(_view_id, { }); - _gui.mode_sigh(_config_handler); - + _gui.info_sigh(_config_handler); _config.sigh(_config_handler); _handle_config(); @@ -307,12 +308,14 @@ void Backdrop::Main::_handle_config() { _config.update(); - Framebuffer::Mode const phys_mode = _gui.mode(); - Framebuffer::Mode const mode { - .area = { _config.xml().attribute_value("width", phys_mode.area.w), - _config.xml().attribute_value("height", phys_mode.area.h) }, - .alpha = false - }; + _gui_win = _gui.window().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return Gui::Rect { { }, { 640, 480 } }; }); + + _gui_win.area = { _config.xml().attribute_value("width", _gui_win.w()), + _config.xml().attribute_value("height", _gui_win.h()) }; + + Framebuffer::Mode const mode { .area = _gui_win.area, .alpha = false }; _buffer.construct(_env, _gui, mode); diff --git a/repos/gems/src/app/decorator/main.cc b/repos/gems/src/app/decorator/main.cc index e23410579c..0013a91c66 100644 --- a/repos/gems/src/app/decorator/main.cc +++ b/repos/gems/src/app/decorator/main.cc @@ -56,9 +56,12 @@ struct Decorator::Main : Window_factory_base struct Canvas { - Framebuffer::Mode const mode; - Attached_dataspace fb_ds; - Decorator::Canvas canvas; + Env &_env; + Gui::Connection &_gui; + + Gui::Area const scr_area = _gui.panorama().convert( + [&] (Gui::Rect rect) { return rect.area; }, + [&] (Gui::Undefined) { return Gui::Area { 1, 1 }; }); /* * The GUI connection's buffer is split into two parts. The upper @@ -66,24 +69,24 @@ struct Decorator::Main : Window_factory_base * whereas the lower part contains the back buffer targeted by * the Decorator::Canvas. */ - static Framebuffer::Mode _doubled(Framebuffer::Mode const mode) + Dataspace_capability _buffer_ds() const { - return { .area = { .w = mode.area.w, .h = mode.area.h*2 }, - .alpha = mode.alpha }; + _gui.buffer({ .area = { .w = scr_area.w, .h = scr_area.h*2 }, + .alpha = false }); + return _gui.framebuffer.dataspace(); } + Attached_dataspace fb_ds { _env.rm(), _buffer_ds() }; + Pixel_rgb888 *_canvas_pixels_ptr() { - return fb_ds.local_addr() + mode.area.count(); + return fb_ds.local_addr() + scr_area.count(); } - Canvas(Env &env, Gui::Connection &gui) - : - mode(gui.mode()), - fb_ds(env.rm(), - (gui.buffer(_doubled(mode)), gui.framebuffer.dataspace())), - canvas(_canvas_pixels_ptr(), mode.area, env.ram(), env.rm()) - { } + Decorator::Canvas canvas { + _canvas_pixels_ptr(), scr_area, _env.ram(), _env.rm() }; + + Canvas(Env &env, Gui::Connection &gui) : _env(env), _gui(gui) { } }; Reconstructible _canvas { _env, _gui }; @@ -93,7 +96,7 @@ struct Decorator::Main : Window_factory_base if (!_canvas.constructed()) return; - Rect const canvas_rect { { }, _canvas->mode.area }; + Rect const canvas_rect { { }, _canvas->scr_area }; dirty.flush([&] (Rect const &r) { @@ -110,9 +113,7 @@ struct Decorator::Main : Window_factory_base { _canvas.construct(_env, _gui); - Area const canvas_area = _canvas->mode.area; - - _window_stack.mark_as_dirty(Rect(Point(0, 0), canvas_area)); + _window_stack.mark_as_dirty(Rect(Point(0, 0), _canvas->scr_area)); Dirty_rect dirty = _window_stack.draw(_canvas->canvas); @@ -195,7 +196,7 @@ struct Decorator::Main : Window_factory_base _config.sigh(_config_handler); _handle_config(); - _gui.mode_sigh(_mode_handler); + _gui.info_sigh(_mode_handler); _window_layout.sigh(_window_layout_handler); _pointer.sigh(_pointer_handler); diff --git a/repos/gems/src/app/phone_manager/main.cc b/repos/gems/src/app/phone_manager/main.cc index 9e8f23da72..a70cc48ea7 100644 --- a/repos/gems/src/app/phone_manager/main.cc +++ b/repos/gems/src/app/phone_manager/main.cc @@ -2007,7 +2007,7 @@ struct Sculpt::Main : Input_event_handler, _drivers.update_soc(_soc); _gui.input.sigh(_input_handler); - _gui.mode_sigh(_gui_mode_handler); + _gui.info_sigh(_gui_mode_handler); _handle_gui_mode(); _system_config.with_manual_config([&] (Xml_node const &system) { @@ -2078,12 +2078,6 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, return Area(win.attribute_value("width", 0U), win.attribute_value("height", 0U)); }; - Framebuffer::Mode const mode = _gui.mode(); - - /* suppress intermediate boot-time states before the framebuffer driver is up */ - if (mode.area.count() <= 1) - return; - _window_layout.generate([&] (Xml_generator &xml) { auto gen_window = [&] (Xml_node win, Rect rect) { @@ -2105,8 +2099,8 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, Area const size = win_size(win); Point const pos = _touch_keyboard.visible - ? Point(0, int(mode.area.h) - int(size.h)) - : Point(0, int(mode.area.h)); + ? Point(0, int(_screen_size.h) - int(size.h)) + : Point(0, int(_screen_size.h)); gen_window(win, Rect(pos, size)); }); @@ -2122,16 +2116,19 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, void Sculpt::Main::_handle_gui_mode() { - Framebuffer::Mode const mode = _gui.mode(); + auto const panorama = _gui.panorama(); - _screensaver.display_driver_ready(mode.area.count() > 1); + _screensaver.display_driver_ready(panorama.ok()); - if (mode.area.count() > 1) - _gui_mode_ready = true; - - _screen_size = mode.area; - _main_view.min_width = _screen_size.w; - _main_view.min_height = _screen_size.h; + panorama.with_result( + [&] (Gui::Rect const rect) { + _gui_mode_ready = true; + _screen_size = rect.area; + _main_view.min_width = _screen_size.w; + _main_view.min_height = _screen_size.h; + }, + [&] (Gui::Undefined) { } + ); generate_runtime_config(); _update_window_layout(); diff --git a/repos/gems/src/app/sculpt_manager/gui.cc b/repos/gems/src/app/sculpt_manager/gui.cc index abc69b182c..ea4b1813d9 100644 --- a/repos/gems/src/app/sculpt_manager/gui.cc +++ b/repos/gems/src/app/sculpt_manager/gui.cc @@ -145,11 +145,8 @@ struct Gui::Session_component : Rpc_object void execute() override { _gui_session.execute(); } - Framebuffer::Mode mode() override { - return _gui_session.mode(); } - - void mode_sigh(Signal_context_capability sigh) override { - _gui_session.mode_sigh(sigh); } + Info_result info() override { + return _gui_session.info(); } Buffer_result buffer(Framebuffer::Mode mode) override { return _gui_session.buffer(mode); } diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc index a205ac1260..5f78003f7c 100644 --- a/repos/gems/src/app/sculpt_manager/main.cc +++ b/repos/gems/src/app/sculpt_manager/main.cc @@ -104,7 +104,10 @@ struct Sculpt::Main : Input_event_handler, Gui::Connection _gui { _env, "input" }; - bool _gui_mode_ready = false; /* becomes true once the graphics driver is up */ + Gui::Connection::Panorama_result _panorama = Gui::Undefined { }; + + /* becomes true once the graphics driver is up */ + bool _gui_mode_ready() const { return _panorama.ok(); }; Gui::Root _gui_root { _env, _heap, *this, _global_input_seq_number }; @@ -953,8 +956,10 @@ struct Sculpt::Main : Input_event_handler, ev.handle_wheel([&] (int, int y) { dy = y*32; }); - if (ev.key_press(Input::KEY_PAGEUP)) dy = int(_gui.mode().area.h / 3); - if (ev.key_press(Input::KEY_PAGEDOWN)) dy = -int(_gui.mode().area.h / 3); + int const vscroll_step = int(_screen_size.h) / 3; + + if (ev.key_press(Input::KEY_PAGEUP)) dy = vscroll_step; + if (ev.key_press(Input::KEY_PAGEDOWN)) dy = -vscroll_step; if (dy != 0) { scroll_ypos += dy; @@ -1647,7 +1652,7 @@ struct Sculpt::Main : Input_event_handler, { _drivers.update_soc(_soc); _gui.input.sigh(_input_handler); - _gui.mode_sigh(_gui_mode_handler); + _gui.info_sigh(_gui_mode_handler); _handle_gui_mode(); _fb_config.trigger_update(); @@ -1680,7 +1685,7 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, Xml_node const &window_list) { /* skip window-layout handling (and decorator activity) while booting */ - if (!_gui_mode_ready) + if (!_gui_mode_ready()) return; struct Decorator_margins @@ -1726,18 +1731,16 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, if (panel_height == 0) return; - Framebuffer::Mode const mode = _gui.mode(); - /* suppress intermediate boot-time states before the framebuffer driver is up */ - if (mode.area.count() <= 1) + if (!_screen_size.valid()) return; /* area reserved for the panel */ - Rect const panel = Rect(Point(0, 0), Area(mode.area.w, panel_height)); + Rect const panel = Rect(Point(0, 0), Area(_screen_size.w, panel_height)); /* available space on the right of the menu */ Rect avail = Rect::compound(Point(0, panel.h()), - Point(mode.area.w - 1, mode.area.h - 1)); + Point(_screen_size.w - 1, _screen_size.h - 1)); Point const log_offset = _log_visible ? Point(0, 0) @@ -1745,8 +1748,8 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, Point const log_p1(avail.x2() - log_min_w - margins.right + 1 + log_offset.x, avail.y1() + margins.top); - Point const log_p2(mode.area.w - margins.right - 1 + log_offset.x, - mode.area.h - margins.bottom - 1); + Point const log_p2(_screen_size.w - margins.right - 1 + log_offset.x, + _screen_size.h - margins.bottom - 1); /* position of the inspect window */ Point const inspect_p1(avail.x1() + margins.left, avail.y1() + margins.top); @@ -1812,7 +1815,7 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, Area const size = win_size(win); Point const pos = _network_visible ? Point(log_p1.x - size.w, avail.y1()) - : Point(mode.area.w, avail.y1()); + : Point(_screen_size.w, avail.y1()); gen_window(win, Rect(pos, size)); }); @@ -1918,7 +1921,7 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, _with_window(window_list, logo_label, [&] (Xml_node const &win) { Area const size = win_size(win); - Point const pos(mode.area.w - size.w, mode.area.h - size.h); + Point const pos(_screen_size.w - size.w, _screen_size.h - size.h); gen_window(win, Rect(pos, size)); }); }); @@ -1945,10 +1948,11 @@ void Sculpt::Main::_update_window_layout(Xml_node const &decorator_margins, void Sculpt::Main::_handle_gui_mode() { - Framebuffer::Mode const mode = _gui.mode(); + _panorama = _gui.panorama(); - if (mode.area.count() > 1) - _gui_mode_ready = true; + _screen_size = _panorama.convert( + [&] (Gui::Rect rect) { return rect.area; }, + [&] (Gui::Undefined) { return Gui::Area { 1024, 768 }; }); _update_window_layout(); @@ -1956,7 +1960,7 @@ void Sculpt::Main::_handle_gui_mode() if (!_settings.manual_fonts_config) { - _font_size_px = (double)mode.area.h / 60.0; + _font_size_px = (double)_screen_size.h / 60.0; if (_settings.font_size == Settings::Font_size::SMALL) _font_size_px *= 0.85; if (_settings.font_size == Settings::Font_size::LARGE) _font_size_px *= 1.35; @@ -2011,7 +2015,6 @@ void Sculpt::Main::_handle_gui_mode() }); } - _screen_size = mode.area; _panel_dialog.min_width = _screen_size.w; unsigned const menu_width = max((unsigned)(_font_size_px*21.0), 320u); _diag_dialog.min_width = menu_width; diff --git a/repos/gems/src/app/window_layouter/main.cc b/repos/gems/src/app/window_layouter/main.cc index b6ac16d19e..f4a54e413a 100644 --- a/repos/gems/src/app/window_layouter/main.cc +++ b/repos/gems/src/app/window_layouter/main.cc @@ -325,9 +325,9 @@ struct Window_layouter::Main : Operations, void _handle_mode_change() { /* determine maximized window geometry */ - Framebuffer::Mode const mode = _gui.mode(); - - _screen_size = mode.area; + _screen_size = _gui.panorama().convert( + [&] (Gui::Rect rect) { return rect.area; }, + [&] (Gui::Undefined) { return Gui::Area { 1, 1 }; }); _update_window_layout(); } @@ -373,7 +373,7 @@ struct Window_layouter::Main : Operations, */ Main(Env &env) : _env(env) { - _gui.mode_sigh(_mode_change_handler); + _gui.info_sigh(_mode_change_handler); _handle_mode_change(); _drop_timer.sigh(_drop_timer_handler); diff --git a/repos/gems/src/lib/dialog/sandboxed_runtime.cc b/repos/gems/src/lib/dialog/sandboxed_runtime.cc index 9a3e737bc0..554f02369d 100644 --- a/repos/gems/src/lib/dialog/sandboxed_runtime.cc +++ b/repos/gems/src/lib/dialog/sandboxed_runtime.cc @@ -150,11 +150,8 @@ struct Sandboxed_runtime::Gui_session : Session_object void execute() override { _gui_session.execute(); } - Framebuffer::Mode mode() override { - return _gui_session.mode(); } - - void mode_sigh(Signal_context_capability sigh) override { - _gui_session.mode_sigh(sigh); } + Info_result info() override { + return _gui_session.info(); } Buffer_result buffer(Framebuffer::Mode mode) override { return _gui_session.buffer(mode); } diff --git a/repos/gems/src/server/gui_fader/main.cc b/repos/gems/src/server/gui_fader/main.cc index f9b391077f..1d713f8034 100644 --- a/repos/gems/src/server/gui_fader/main.cc +++ b/repos/gems/src/server/gui_fader/main.cc @@ -455,15 +455,7 @@ class Gui_fader::Gui_session_component return _gui.execute(); } - Framebuffer::Mode mode() override - { - return _gui.mode(); - } - - void mode_sigh(Genode::Signal_context_capability sigh) override - { - _gui.mode_sigh(sigh); - } + Info_result info() override { return _gui.info_rom_cap(); } Buffer_result buffer(Framebuffer::Mode mode) override { diff --git a/repos/gems/src/server/terminal/main.cc b/repos/gems/src/server/terminal/main.cc index 371c362059..555fa5b5e2 100644 --- a/repos/gems/src/server/terminal/main.cc +++ b/repos/gems/src/server/terminal/main.cc @@ -100,9 +100,16 @@ struct Terminal::Main : Character_consumer Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; + Gui::Rect _gui_window_rect() + { + return _gui.window().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return Gui::Rect { { }, { 1, 1 } }; }); + } + void _handle_mode_change() { - _fb_mode = _gui.mode(); + _win_rect = _gui_window_rect(); _handle_config(); } @@ -114,7 +121,7 @@ struct Terminal::Main : Character_consumer Constructible _fb_ds { }; - Framebuffer::Mode _fb_mode { }; + Gui::Rect _win_rect { }; Gui::View_id _view { }; @@ -143,7 +150,7 @@ struct Terminal::Main : Character_consumer bool _flush_scheduled = false; - Framebuffer::Mode _flushed_fb_mode { }; + Gui::Rect _flushed_win_rect { }; void _handle_flush() { @@ -151,7 +158,7 @@ struct Terminal::Main : Character_consumer if (_text_screen_surface.constructed() && _fb_ds.constructed()) { - Surface surface(_fb_ds->local_addr(), _fb_mode.area); + Surface surface(_fb_ds->local_addr(), _win_rect.area); Rect const dirty = _text_screen_surface->redraw(surface); @@ -159,14 +166,14 @@ struct Terminal::Main : Character_consumer } /* update view geometry after mode change */ - if (_fb_mode.area != _flushed_fb_mode.area) { + if (_win_rect != _flushed_win_rect) { using Command = Gui::Session::Command; - _gui.enqueue(_view, Rect(Point(0, 0), _fb_mode.area)); + _gui.enqueue(_view, _win_rect); _gui.enqueue(_view); _gui.execute(); - _flushed_fb_mode = _fb_mode; + _flushed_win_rect = _win_rect; } } @@ -215,14 +222,14 @@ struct Terminal::Main : Character_consumer _config.sigh(_config_handler); _gui.input.sigh(_input_handler); - _gui.mode_sigh(_mode_change_handler); + _gui.info_sigh(_mode_change_handler); - _fb_mode = { .area = _gui.mode().area, .alpha = false }; + _win_rect = _gui_window_rect(); /* apply initial size from config, if provided */ _config.xml().with_optional_sub_node("initial", [&] (Xml_node const &initial) { - _fb_mode.area = Area(initial.attribute_value("width", _fb_mode.area.w), - initial.attribute_value("height", _fb_mode.area.h)); + _win_rect.area = { initial.attribute_value("width", _win_rect.w()), + initial.attribute_value("height", _win_rect.h()) }; }); _handle_config(); @@ -259,9 +266,9 @@ void Terminal::Main::_handle_config() /* * Adapt terminal to font or framebuffer mode changes */ - _gui.buffer(_fb_mode); + _gui.buffer({ .area = _win_rect.area, .alpha = false }); - if (_fb_mode.area.count() > 0) + if (_win_rect.valid()) _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); /* @@ -276,7 +283,7 @@ void Terminal::Main::_handle_config() */ try { - Text_screen_surface::Geometry const new_geometry(_font->font(), _fb_mode.area); + Text_screen_surface::Geometry const new_geometry(_font->font(), _win_rect.area); bool const reconstruct = !_text_screen_surface.constructed() || _text_screen_surface->size() != new_geometry.size(); @@ -307,7 +314,7 @@ void Terminal::Main::_handle_config() : Position(); _text_screen_surface.construct(_heap, _font->font(), - _color_palette, _fb_mode.area); + _color_palette, _win_rect.area); if (snapshot.constructed()) _text_screen_surface->import(*snapshot); diff --git a/repos/gems/src/server/wm/decorator_gui.h b/repos/gems/src/server/wm/decorator_gui.h index 7a53342f6a..d85a06cf08 100644 --- a/repos/gems/src/server/wm/decorator_gui.h +++ b/repos/gems/src/server/wm/decorator_gui.h @@ -222,6 +222,11 @@ struct Wm::Decorator_gui_session : Session_object, return _dummy_input_component_cap; } + Info_result info() override + { + return _real_gui.session.info(); + } + View_result view(View_id id, View_attr const &attr) override { /* @@ -316,21 +321,6 @@ struct Wm::Decorator_gui_session : Session_object, _real_gui.execute(); } - Framebuffer::Mode mode() override - { - return _real_gui.session.mode(); - } - - void mode_sigh(Signal_context_capability sigh) override - { - /* - * Remember signal-context capability to keep NOVA from revoking - * transitive delegations of the capability. - */ - _mode_sigh = sigh; - _real_gui.session.mode_sigh(sigh); - } - Buffer_result buffer(Framebuffer::Mode mode) override { return _real_gui.session.buffer(mode); diff --git a/repos/gems/src/server/wm/direct_gui.h b/repos/gems/src/server/wm/direct_gui.h index 51d36f8668..76b0f134f8 100644 --- a/repos/gems/src/server/wm/direct_gui.h +++ b/repos/gems/src/server/wm/direct_gui.h @@ -104,14 +104,9 @@ class Wm::Direct_gui_session : public Session_object _session.execute(); } - Framebuffer::Mode mode() override + Info_result info() override { - return _session.mode(); - } - - void mode_sigh(Signal_context_capability sigh) override - { - _session.mode_sigh(sigh); + return _session.info(); } Buffer_result buffer(Framebuffer::Mode mode) override diff --git a/repos/gems/src/server/wm/gui.h b/repos/gems/src/server/wm/gui.h index 99cb8f8fc3..882c76879c 100644 --- a/repos/gems/src/server/wm/gui.h +++ b/repos/gems/src/server/wm/gui.h @@ -19,6 +19,7 @@ #include #include #include +#include /* local includes */ #include @@ -494,8 +495,16 @@ class Wm::Gui::Child_view : public View, private List::Element class Wm::Gui::Session_component : public Session_object, private List::Element, private Input_origin_changed_handler, - private Upgradeable + private Upgradeable, + private Dynamic_rom_session::Xml_producer { + public: + + struct Action : Interface + { + virtual void gen_screen_area_info(Xml_generator &) const = 0; + }; + private: friend class List; @@ -531,7 +540,8 @@ class Wm::Gui::Session_component : public Session_object, } }; - Env &_env; + Env &_env; + Action &_action; Constrained_ram_allocator _ram { _env.ram(), _ram_quota_guard(), _cap_quota_guard() }; @@ -561,15 +571,39 @@ class Wm::Gui::Session_component : public Session_object, Input_session _input_session { _env, _ram }; Click_handler &_click_handler; - Signal_context_capability _mode_sigh { }; - Area _requested_size { }; - bool _resize_requested = false; - bool _has_alpha = false; - Pointer::State _pointer_state; - Point const _initial_pointer_pos { -1, -1 }; - Point _pointer_pos = _initial_pointer_pos; - Point _virtual_pointer_pos { }; - unsigned _key_cnt = 0; + + struct Info_rom_session : Dynamic_rom_session + { + Session_component &_session; + + Info_rom_session(Session_component &session, auto &&... args) + : Dynamic_rom_session(args...), _session(session) { } + + void sigh(Signal_context_capability sigh) override + { + Dynamic_rom_session::sigh(sigh); + + /* + * We consider a window as resizable if the client shows interest + * in mode-change notifications. + */ + _session._resizeable = sigh.valid(); + for (Top_level_view *v = _session._top_level_views.first(); v; v = v->next()) + v->resizeable(_session._resizeable); + } + }; + + Constructible _info_rom { }; + + bool _resizeable = false; + Area _requested_size { }; + bool _resize_requested = false; + bool _has_alpha = false; + Pointer::State _pointer_state; + Point const _initial_pointer_pos { -1, -1 }; + Point _pointer_pos = _initial_pointer_pos; + Point _virtual_pointer_pos { }; + unsigned _key_cnt = 0; auto _with_view(View_id id, auto const &fn, auto const &missing_fn) -> decltype(missing_fn()) @@ -601,9 +635,6 @@ class Wm::Gui::Session_component : public Session_object, Signal_handler _input_handler { _env.ep(), *this, &Session_component::_handle_input }; - Signal_handler _mode_handler { - _env.ep(), *this, &Session_component::_handle_mode_change }; - Point _input_origin() const { if (Top_level_view const *v = _top_level_views.first()) @@ -714,14 +745,42 @@ class Wm::Gui::Session_component : public Session_object, } } - void _handle_mode_change() + /** + * Dynamic_rom_session::Xml_producer interface + */ + void produce_xml(Xml_generator &xml) override { - /* - * Inform a viewless client about the upstream - * mode change. - */ - if (_mode_sigh.valid() && !_top_level_views.first()) - Signal_transmitter(_mode_sigh).submit(); + _action.gen_screen_area_info(xml); + + auto virtual_capture_area = [&] + { + /* + * While resizing the window, return requested window size as + * mode + */ + if (_resize_requested) + return _requested_size; + + /* + * If the first top-level view has a defined size, use it + * as the size of the virtualized GUI session. + */ + if (Top_level_view const *v = _top_level_views.first()) + if (v->size().valid()) + return v->size(); + + return Area { }; + }; + + auto gen_attr = [&] (Area const area) + { + if (area.valid()) { + xml.attribute("width", area.w); + xml.attribute("height", area.h); + } + }; + + xml.node("capture", [&] { gen_attr(virtual_capture_area()); }); } /** @@ -827,6 +886,7 @@ class Wm::Gui::Session_component : public Session_object, public: Session_component(Env &env, + Action &action, Resources const &resources, Label const &label, Diag const diag, @@ -835,13 +895,13 @@ class Wm::Gui::Session_component : public Session_object, Click_handler &click_handler) : Session_object(env.ep(), resources, label, diag), - _env(env), + Xml_producer("panorama"), + _env(env), _action(action), _window_registry(window_registry), _click_handler(click_handler), _pointer_state(pointer_tracker) { _gui_input.sigh(_input_handler); - _real_gui.session.mode_sigh(_mode_handler); _input_session.event_queue().enabled(true); } @@ -933,8 +993,8 @@ class Wm::Gui::Session_component : public Session_object, _resize_requested = true; /* notify client */ - if (_mode_sigh.valid()) - Signal_transmitter(_mode_sigh).submit(); + if (_info_rom.constructed()) + _info_rom->trigger_update(); } void hidden(bool hidden) @@ -953,6 +1013,12 @@ class Wm::Gui::Session_component : public Session_object, */ Capability session() { return _real_gui.connection.cap(); } + void propagate_mode_change() + { + if (_info_rom.constructed()) + _info_rom->trigger_update(); + } + /*************************** ** GUI session interface ** @@ -1048,7 +1114,7 @@ class Wm::Gui::Session_component : public Session_object, }); if (result == View_result::OK && view_ptr) { - view_ptr->resizeable(_mode_sigh.valid()); + view_ptr->resizeable(_resizeable); _top_level_views.insert(view_ptr); } return result; @@ -1161,45 +1227,35 @@ class Wm::Gui::Session_component : public Session_object, _window_registry.flush(); } - Framebuffer::Mode mode() override + Info_result info() override { - Framebuffer::Mode const real_mode = _real_gui.session.mode(); + if (!_info_rom.constructed()) { + Cap_quota const needed_caps { 2 }; + if (!_cap_quota_guard().have_avail(needed_caps)) { + _starved_for_caps = true; + return Info_error::OUT_OF_CAPS; + } - /* - * While resizing the window, return requested window size as - * mode - */ - if (_resize_requested) - return Framebuffer::Mode { .area = _requested_size, - .alpha = real_mode.alpha }; + Ram_quota const needed_ram { 8*1024 }; + if (!_ram_quota_guard().have_avail(needed_ram)) { + _starved_for_ram = true; + return Info_error::OUT_OF_RAM; + } - /* - * If the first top-level view has a defined size, use it - * as the size of the virtualized GUI session. - */ - if (Top_level_view const *v = _top_level_views.first()) - if (v->size().valid()) - return Framebuffer::Mode { .area = v->size(), - .alpha = real_mode.alpha}; + try { + Dynamic_rom_session::Content_producer &rom_producer = *this; + _info_rom.construct(*this, _env.ep(), _ram, _env.rm(), rom_producer); + _info_rom->dataspace(); /* eagerly consume RAM and caps */ + } + catch (Out_of_ram) { _starved_for_ram = true; } + catch (Out_of_caps) { _starved_for_caps = true; } - /* - * If top-level view has yet been defined, return the real mode. - */ - return real_mode; - } - - void mode_sigh(Signal_context_capability sigh) override - { - _mode_sigh = sigh; - - /* - * We consider a window as resizable if the client shows interest - * in mode-change notifications. - */ - bool const resizeable = _mode_sigh.valid(); - - for (Top_level_view *v = _top_level_views.first(); v; v = v->next()) - v->resizeable(resizeable); + if (_starved_for_ram || _starved_for_caps) { + if (_starved_for_ram) return Info_error::OUT_OF_RAM; + if (_starved_for_caps) return Info_error::OUT_OF_CAPS; + } + } + return _info_rom->cap(); } Buffer_result buffer(Framebuffer::Mode mode) override @@ -1238,6 +1294,8 @@ class Wm::Gui::Root : public Rpc_object >, Env &_env; + Session_component::Action &_action; + Attached_rom_dataspace _config { _env, "config" }; Sliced_heap _sliced_heap { _env.ram(), _env.rm() }; @@ -1292,11 +1350,12 @@ class Wm::Gui::Root : public Rpc_object >, /** * Constructor */ - Root(Env &env, Window_registry &window_registry, + Root(Env &env, Session_component::Action &action, + Window_registry &window_registry, Pointer::Tracker &pointer_tracker, - Gui::Connection &focus_gui_session) + Gui::Connection &focus_gui_session) : - _env(env), + _env(env), _action(action), _pointer_tracker(pointer_tracker), _window_registry(window_registry), _focus_gui_session(focus_gui_session) @@ -1376,7 +1435,6 @@ class Wm::Gui::Root : public Rpc_object >, 1 + /* Input_session events dataspace (_input_session) */ 1 + /* Command buffer (_command_buffer) */ 1 + /* Input signal handler (_input_handler) */ - 1 + /* Mode signal handler (_mode_handler) */ 1; /* Content-view capability */ if (resources.cap_quota.value < needed_caps) @@ -1390,7 +1448,7 @@ class Wm::Gui::Root : public Rpc_object >, case ROLE_REGULAR: try { Session_component &session = *new (_sliced_heap) - Session_component(_env, resources, label, diag, + Session_component(_env, _action, resources, label, diag, _window_registry, _pointer_tracker, _click_handler); @@ -1586,6 +1644,12 @@ class Wm::Gui::Root : public Rpc_object >, if (s->has_win_id(win_id)) return s->request_resize(size); } + + void propagate_mode_change() + { + for (Session_component *s = _sessions.first(); s; s = s->next()) + s->propagate_mode_change(); + } }; #endif /* _GUI_H_ */ diff --git a/repos/gems/src/server/wm/layouter_gui.h b/repos/gems/src/server/wm/layouter_gui.h index 9fa01ba370..4bfc231c25 100644 --- a/repos/gems/src/server/wm/layouter_gui.h +++ b/repos/gems/src/server/wm/layouter_gui.h @@ -33,8 +33,6 @@ struct Wm::Layouter_gui_session : Session_object */ Gui::Connection _mode_sigh_gui; - Signal_context_capability _mode_sigh { }; - Attached_ram_dataspace _command_ds; Layouter_gui_session(Env &env, @@ -63,6 +61,11 @@ struct Wm::Layouter_gui_session : Session_object return _input_session_cap; } + Info_result info() override + { + return _mode_sigh_gui.info_rom_cap(); + } + View_result view(Gui::View_id, View_attr const &) override { return View_result::OK; @@ -94,19 +97,6 @@ struct Wm::Layouter_gui_session : Session_object void execute() override { } - Framebuffer::Mode mode() override { return _mode_sigh_gui.mode(); } - - void mode_sigh(Signal_context_capability sigh) override - { - /* - * Remember signal-context capability to keep NOVA from revoking - * transitive delegations of the capability. - */ - _mode_sigh = sigh; - - _mode_sigh_gui.mode_sigh(sigh); - } - Buffer_result buffer(Framebuffer::Mode) override { return Buffer_result::OK; } void focus(Capability) override { } diff --git a/repos/gems/src/server/wm/main.cc b/repos/gems/src/server/wm/main.cc index 6723cd073d..41feacea3a 100644 --- a/repos/gems/src/server/wm/main.cc +++ b/repos/gems/src/server/wm/main.cc @@ -24,7 +24,7 @@ namespace Wm { class Main; } -struct Wm::Main : Pointer::Tracker +struct Wm::Main : Pointer::Tracker, Gui::Session_component::Action { Env &_env; @@ -46,7 +46,28 @@ struct Wm::Main : Pointer::Tracker Gui::Connection _focus_gui_session { _env }; - Gui::Root _gui_root { _env, _window_registry, *this, _focus_gui_session }; + Gui::Area _screen_area { }; + + Signal_handler
_mode_handler { + _env.ep(), *this, &Main::_handle_mode }; + + void _handle_mode() + { + _focus_gui_session.with_info([&] (Xml_node const &info) { + _screen_area = Area::from_xml(info); }); + _gui_root.propagate_mode_change(); + } + + /** + * Gui::Session_component::Action interface + */ + void gen_screen_area_info(Xml_generator &xml) const override + { + xml.attribute("width", _screen_area.w); + xml.attribute("height", _screen_area.h); + } + + Gui::Root _gui_root { _env, *this, _window_registry, *this, _focus_gui_session }; static void _with_win_id_from_xml(Xml_node const &window, auto const &fn) { @@ -117,6 +138,8 @@ struct Wm::Main : Pointer::Tracker _focus_rom.sigh(_focus_handler); _resize_request_rom.sigh(_resize_request_handler); + _focus_gui_session.info_sigh(_mode_handler); + _handle_mode(); } }; diff --git a/repos/libports/src/app/pdf_view/main.cc b/repos/libports/src/app/pdf_view/main.cc index 1d2eaf1112..f9a456474a 100644 --- a/repos/libports/src/app/pdf_view/main.cc +++ b/repos/libports/src/app/pdf_view/main.cc @@ -91,13 +91,21 @@ class Pdf_view Gui::Connection _gui { _env }; - Framebuffer::Mode _nit_mode = _gui.mode(); - Framebuffer::Mode _fb_mode {}; + Gui::Rect _gui_window() + { + return _gui.window().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return Gui::Rect { { }, { 512, 512 } }; }); + } + + Gui::Rect _win_rect = _gui_window(); + + Framebuffer::Mode _fb_mode {}; Genode::Constructible _fb_ds { }; - Genode::Signal_handler _nit_mode_handler { - _env.ep(), *this, &Pdf_view::_handle_nit_mode }; + Genode::Signal_handler _gui_mode_handler { + _env.ep(), *this, &Pdf_view::_handle_gui_mode }; Genode::Signal_handler _input_handler { _env.ep(), *this, &Pdf_view::_handle_input_events }; @@ -110,10 +118,10 @@ class Pdf_view { using namespace Gui; - _nit_mode = _gui.mode(); + _win_rect = _gui_window(); - unsigned max_x = Genode::max(_nit_mode.area.w, _fb_mode.area.w); - unsigned max_y = Genode::max(_nit_mode.area.h, _fb_mode.area.h); + unsigned max_x = Genode::max(_win_rect.area.w, _fb_mode.area.w); + unsigned max_y = Genode::max(_win_rect.area.h, _fb_mode.area.h); if (max_x > _fb_mode.area.w || max_y > _fb_mode.area.h) { _fb_mode = Mode { .area = { max_x, max_y }, .alpha = false }; @@ -123,8 +131,8 @@ class Pdf_view _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); } - _pdfapp.scrw = _nit_mode.area.w; - _pdfapp.scrh = _nit_mode.area.h; + _pdfapp.scrw = _win_rect.area.w; + _pdfapp.scrh = _win_rect.area.h; /* * XXX replace heuristics with a meaningful computation @@ -132,17 +140,17 @@ class Pdf_view * The magic values are hand-tweaked manually to accommodating the * use case of showing slides. */ - _pdfapp.resolution = Genode::min(_nit_mode.area.w/5, - _nit_mode.area.h/4); + _pdfapp.resolution = Genode::min(_win_rect.area.w/5, + _win_rect.area.h/4); - _view.area(_nit_mode.area); + _view.area(_win_rect.area); _view.front(); } - void _handle_nit_mode() + void _handle_gui_mode() { _rebuffer(); - pdfapp_onresize(&_pdfapp, _nit_mode.area.w, _nit_mode.area.h); + pdfapp_onresize(&_pdfapp, _win_rect.area.w, _win_rect.area.h); } pdfapp_t _pdfapp { }; @@ -218,7 +226,7 @@ class Pdf_view */ Pdf_view(Genode::Env &env) : _env(env) { - _gui.mode_sigh(_nit_mode_handler); + _gui.info_sigh(_gui_mode_handler); _gui.input.sigh(_input_handler); pdfapp_init(&_pdfapp); @@ -291,12 +299,12 @@ void Pdf_view::show() int const tweaked_y_max = y_max - 2; /* center vertically if the dst buffer is higher than the image */ - if ((unsigned)_pdfapp.image->h < _nit_mode.area.h) - dst_line += dst_line_width*((_nit_mode.area.h - _pdfapp.image->h)/2); + if ((unsigned)_pdfapp.image->h < _win_rect.area.h) + dst_line += dst_line_width*((_win_rect.area.h - _pdfapp.image->h)/2); /* center horizontally if the dst buffer is wider than the image */ - if ((unsigned)_pdfapp.image->w < _nit_mode.area.w) - dst_line += (_nit_mode.area.w - _pdfapp.image->w)/2; + if ((unsigned)_pdfapp.image->w < _win_rect.area.w) + dst_line += (_win_rect.area.w - _pdfapp.image->w)/2; for (int y = 0; y < tweaked_y_max; y++) { copy_line_rgba(src_line, dst_line, x_max); @@ -304,7 +312,7 @@ void Pdf_view::show() dst_line += dst_line_width; } - _gui.framebuffer.refresh({ { 0, 0 }, _nit_mode.area }); + _gui.framebuffer.refresh({ { 0, 0 }, _win_rect.area }); } diff --git a/repos/os/include/gui_session/client.h b/repos/os/include/gui_session/client.h index 02823c1665..2228a8ef00 100644 --- a/repos/os/include/gui_session/client.h +++ b/repos/os/include/gui_session/client.h @@ -30,6 +30,9 @@ struct Gui::Session_client : Rpc_client Input::Session_capability input() override { return call(); } + Info_result info() override { + return call(); } + [[nodiscard]] View_result view(View_id id, View_attr const &attr) override { return call(id, attr); } @@ -53,12 +56,6 @@ struct Gui::Session_client : Rpc_client void execute() override { call(); } - Framebuffer::Mode mode() override { - return call(); } - - void mode_sigh(Signal_context_capability sigh) override { - call(sigh); } - [[nodiscard]] Buffer_result buffer(Framebuffer::Mode mode) override { return call(mode); } diff --git a/repos/os/include/gui_session/connection.h b/repos/os/include/gui_session/connection.h index 1167cb05e1..427cbcee2b 100644 --- a/repos/os/include/gui_session/connection.h +++ b/repos/os/include/gui_session/connection.h @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace Gui { @@ -52,6 +53,43 @@ class Gui::Connection : private Genode::Connection static constexpr Ram_quota _RAM_QUOTA { 96*1024 }; static constexpr Cap_quota _CAP_QUOTA { Session::CAP_QUOTA + 9 }; + Constructible _info_rom { }; + Constructible _info_ds { }; + + Rom_session_capability _info_rom_capability() + { + for (;;) { + using Error = Session::Info_error; + auto const result = _client.info(); + if (result == Error::OUT_OF_RAM) { upgrade_ram(8*1024); continue; } + if (result == Error::OUT_OF_CAPS) { upgrade_caps(2); continue; } + return result.convert( + [&] (Rom_session_capability cap) { return cap; }, + [&] (auto) /* handled above */ { return Rom_session_capability(); }); + } + } + + void _with_info_rom(auto const &fn) + { + if (!_info_ds.constructed()) + _info_rom.construct(_info_rom_capability()); + fn(*_info_rom); + } + + void _with_info_xml(auto const &fn) + { + _with_info_rom([&] (Rom_session_client &rom) { + if (!_info_ds.constructed() || rom.update() == false) + _info_ds.construct(_env.rm(), rom.dataspace()); + + try { + Xml_node xml(_info_ds->local_addr(), _info_ds->size()); + fn(xml); } + catch (Xml_node::Invalid_syntax) { + warning("Gui::info has invalid XML syntax"); } + }); + } + public: View_ids view_ids { }; @@ -199,14 +237,71 @@ class Gui::Connection : private Genode::Connection } /** - * Return physical screen mode + * Call 'fn' with mode information as 'Xml_node const &' argument */ - Framebuffer::Mode mode() { return _client.mode(); } + void with_info(auto const &fn) { _with_info_xml(fn); } + + Capability info_rom_cap() + { + Capability result { }; + _with_info_rom([&] (Rom_session_client &rom) { result = rom.rpc_cap(); }); + return result; + } + + using Panorama_result = Attempt; + + /** + * Return geometry of the total panorama + * + * The retured rectangle may be undefined for a client of the nitpicker + * GUI server in the absence of any capture client. + */ + Panorama_result panorama() + { + Gui::Rect result { }; + _with_info_xml([&] (Xml_node const &info) { + result = Rect::from_xml(info); }); + return result.valid() ? Panorama_result { result } + : Panorama_result { Undefined { } }; + } + + using Window_result = Attempt; + + /** + * Return suitable geometry of top-level view + * + * For nitpicker clients, the window is the bounding box of all capture + * clients. For window-manager clients, returned rectangle corresponds + * to the window size as defined by the layouter. + * + * The returned rectangle may be undefined when a client of the window + * manager has not defined a top-level view yet. + */ + Window_result window() + { + Rect result { }; + _with_info_xml([&] (Xml_node const &info) { + Rect bb { }; /* bounding box of all captured rects */ + unsigned count = 0; + info.for_each_sub_node("capture", [&] (Xml_node const &capture) { + bb = Rect::compound(bb, Rect::from_xml(capture)); + count++; + }); + result = (count == 1) ? bb : Rect::from_xml(info); + }); + return result.valid() ? Window_result { result } + : Window_result { Undefined { } }; + } /** * Register signal handler to be notified about mode changes */ - void mode_sigh(Signal_context_capability sigh) { _client.mode_sigh(sigh); } + void info_sigh(Signal_context_capability sigh) + { + _with_info_rom([&] (Rom_session_client &rom) { rom.sigh(sigh); }); + if (sigh.valid()) + Signal_transmitter(sigh).submit(); + } void focus(Capability focused) { _client.focus(focused); } }; diff --git a/repos/os/include/gui_session/gui_session.h b/repos/os/include/gui_session/gui_session.h index 5b7456d947..e65042ca91 100644 --- a/repos/os/include/gui_session/gui_session.h +++ b/repos/os/include/gui_session/gui_session.h @@ -19,6 +19,7 @@ #include #include #include +#include namespace Gui { @@ -44,6 +45,8 @@ namespace Gui { using Rect = Surface_base::Rect; using Point = Surface_base::Point; using Area = Surface_base::Area; + + struct Undefined { }; } @@ -171,6 +174,14 @@ struct Gui::Session : Genode::Session */ virtual Input::Session_capability input() = 0; + enum class Info_error { OUT_OF_RAM, OUT_OF_CAPS }; + using Info_result = Attempt, Info_error>; + + /** + * Request ROM session containing the mode information + */ + virtual Info_result info() = 0; + struct View_attr { Title title; @@ -233,16 +244,6 @@ struct Gui::Session : Genode::Session */ virtual void execute() = 0; - /** - * Return physical screen mode - */ - virtual Framebuffer::Mode mode() = 0; - - /** - * Register signal handler to be notified about mode changes - */ - virtual void mode_sigh(Signal_context_capability) = 0; - enum class Buffer_result { OK, OUT_OF_RAM, OUT_OF_CAPS }; /** @@ -284,6 +285,7 @@ struct Gui::Session : Genode::Session GENODE_RPC(Rpc_framebuffer, Framebuffer::Session_capability, framebuffer); GENODE_RPC(Rpc_input, Input::Session_capability, input); + GENODE_RPC(Rpc_info, Info_result, info); GENODE_RPC(Rpc_view, View_result, view, View_id, View_attr const &); GENODE_RPC(Rpc_child_view, Child_view_result, child_view, View_id, View_id, View_attr const &); GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_id); @@ -293,16 +295,13 @@ struct Gui::Session : Genode::Session GENODE_RPC(Rpc_command_dataspace, Dataspace_capability, command_dataspace); GENODE_RPC(Rpc_execute, void, execute); GENODE_RPC(Rpc_background, int, background, View_capability); - GENODE_RPC(Rpc_mode, Framebuffer::Mode, mode); - GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Signal_context_capability); GENODE_RPC(Rpc_focus, void, focus, Capability); GENODE_RPC(Rpc_buffer, Buffer_result, buffer, Framebuffer::Mode); - GENODE_RPC_INTERFACE(Rpc_framebuffer, Rpc_input, + GENODE_RPC_INTERFACE(Rpc_framebuffer, Rpc_input, Rpc_info, Rpc_view, Rpc_child_view, Rpc_destroy_view, Rpc_associate, Rpc_view_capability, Rpc_release_view_id, - Rpc_command_dataspace, Rpc_execute, Rpc_mode, - Rpc_mode_sigh, Rpc_buffer, Rpc_focus); + Rpc_command_dataspace, Rpc_execute, Rpc_buffer, Rpc_focus); }; #endif /* _INCLUDE__GUI_SESSION__GUI_SESSION_H_ */ diff --git a/repos/os/src/app/status_bar/main.cc b/repos/os/src/app/status_bar/main.cc index 4531ea8900..141c6a2aad 100644 --- a/repos/os/src/app/status_bar/main.cc +++ b/repos/os/src/app/status_bar/main.cc @@ -44,14 +44,16 @@ struct Status_bar::Buffer Gui::Connection &_gui; - Framebuffer::Mode const _nit_mode { _gui.mode() }; + Gui::Area const _scr_area = _gui.panorama().convert( + [&] (Gui::Rect rect) { return rect.area; }, + [&] (Gui::Undefined) { return Gui::Area { 1, 1 }; }); /* * Dimension nitpicker buffer depending on nitpicker's screen size. * The status bar is as wide as nitpicker's screen and has a fixed * height. */ - Framebuffer::Mode const _mode { .area = { _nit_mode.area.w, HEIGHT }, + Framebuffer::Mode const _mode { .area = { _scr_area.w, HEIGHT }, .alpha = false }; Dataspace_capability _init_buffer() @@ -198,7 +200,7 @@ struct Status_bar::Main { /* register signal handlers */ _focus_ds.sigh(_focus_handler); - _gui.mode_sigh(_mode_handler); + _gui.info_sigh(_mode_handler); /* import initial state */ _handle_mode(); diff --git a/repos/os/src/server/gui_fb/main.cc b/repos/os/src/server/gui_fb/main.cc index 2dda709b04..b9eda42db7 100644 --- a/repos/os/src/server/gui_fb/main.cc +++ b/repos/os/src/server/gui_fb/main.cc @@ -263,6 +263,15 @@ struct Gui_fb::Main : View_updater Attached_dataspace _input_ds { _env.rm(), _gui.input.dataspace() }; + Gui::Rect _gui_window() + { + return _gui.window().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return _gui.panorama().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return Gui::Rect { { }, { 1, 1 } }; }); }); + } + struct Initial_size { long const _width { 0 }; @@ -276,18 +285,18 @@ struct Gui_fb::Main : View_updater _height(config.attribute_value("initial_height", 0L)) { } - unsigned width(Framebuffer::Mode const &mode) const + unsigned width(Gui::Area const &gui_area) const { if (_width > 0) return (unsigned)_width; - if (_width < 0) return (unsigned)(mode.area.w + _width); - return mode.area.w; + if (_width < 0) return (unsigned)(gui_area.w + _width); + return gui_area.w; } - unsigned height(Framebuffer::Mode const &mode) const + unsigned height(Gui::Area const &gui_area) const { if (_height > 0) return (unsigned)_height; - if (_height < 0) return (unsigned)(mode.area.h + _height); - return mode.area.h; + if (_height < 0) return (unsigned)(gui_area.h + _height); + return gui_area.h; } bool valid() const { return _width != 0 && _height != 0; } @@ -296,9 +305,10 @@ struct Gui_fb::Main : View_updater Framebuffer::Mode _initial_mode() { + Gui::Area const gui_area = _gui_window().area; return { - .area = { _initial_size.width (_gui.mode()), - _initial_size.height(_gui.mode()) }, + .area = { _initial_size.width (gui_area), + _initial_size.height(gui_area) }, .alpha = false }; } @@ -348,7 +358,7 @@ struct Gui_fb::Main : View_updater /** * Return screen-coordinate origin, depening on the config and screen mode */ - static Point _coordinate_origin(Framebuffer::Mode mode, Xml_node config) + static Point _coordinate_origin(Gui::Area gui_area, Xml_node config) { char const * const attr = "origin"; @@ -359,9 +369,9 @@ struct Gui_fb::Main : View_updater Value const value = config.attribute_value(attr, Value()); if (value == "top_left") return Point(0, 0); - if (value == "top_right") return Point(mode.area.w, 0); - if (value == "bottom_left") return Point(0, mode.area.h); - if (value == "bottom_right") return Point(mode.area.w, mode.area.h); + if (value == "top_right") return Point(gui_area.w, 0); + if (value == "bottom_left") return Point(0, gui_area.h); + if (value == "bottom_right") return Point(gui_area.w, gui_area.h); warning("unsupported ", attr, " attribute value '", value, "'"); return Point(0, 0); @@ -371,9 +381,9 @@ struct Gui_fb::Main : View_updater { Xml_node const config = _config_rom.xml(); - Framebuffer::Mode const gui_mode = _gui.mode(); + Gui::Area const gui_area = _gui_window().area; - _position = _coordinate_origin(gui_mode, config) + Point::from_xml(config); + _position = _coordinate_origin(gui_area, config) + Point::from_xml(config); bool const attr = config.has_attribute("width") || config.has_attribute("height"); @@ -384,15 +394,12 @@ struct Gui_fb::Main : View_updater _initial_size.set = true; } - unsigned const gui_width = gui_mode.area.w; - unsigned const gui_height = gui_mode.area.h; - - long width = config.attribute_value("width", (long)gui_mode.area.w), - height = config.attribute_value("height", (long)gui_mode.area.h); + long width = config.attribute_value("width", long(gui_area.w)), + height = config.attribute_value("height", long(gui_area.h)); if (!_initial_size.set && _initial_size.valid()) { - width = _initial_size.width (gui_mode); - height = _initial_size.height(gui_mode); + width = _initial_size.width (gui_area); + height = _initial_size.height(gui_area); _initial_size.set = true; } else { @@ -401,8 +408,8 @@ struct Gui_fb::Main : View_updater * If configured width / height values are negative, the effective * width / height is deduced from the screen size. */ - if (width < 0) width = gui_width + width; - if (height < 0) height = gui_height + height; + if (width < 0) width = gui_area.w + width; + if (height < 0) height = gui_area.h + height; } _fb_session.size(Area((unsigned)width, (unsigned)height)); @@ -466,7 +473,7 @@ struct Gui_fb::Main : View_updater * Register signal handlers */ _config_rom.sigh(_config_update_handler); - _gui.mode_sigh(_mode_update_handler); + _gui.info_sigh(_mode_update_handler); _gui.input.sigh(_input_handler); } }; diff --git a/repos/os/src/server/nitpicker/capture_session.h b/repos/os/src/server/nitpicker/capture_session.h index 96cc857766..48b0e02f4d 100644 --- a/repos/os/src/server/nitpicker/capture_session.h +++ b/repos/os/src/server/nitpicker/capture_session.h @@ -86,15 +86,6 @@ class Nitpicker::Capture_session : public Session_object } }; - static void gen_attr(Xml_generator &xml, Rect const rect) - { - if (rect.x1()) xml.attribute("xpos", rect.x1()); - if (rect.y1()) xml.attribute("ypos", rect.y1()); - - xml.attribute("width", rect.w()); - xml.attribute("height", rect.h()); - } - private: Env &_env; @@ -185,6 +176,19 @@ class Nitpicker::Capture_session : public Session_object void apply_policy(Policy const &policy) { _policy = policy; } + void gen_capture_attr(Xml_generator &xml) const + { + xml.attribute("name", label()); + + gen_attr(xml, bounding_box()); + + unsigned const w_mm = _policy.w_mm.or_default(_buffer_attr.mm.w), + h_mm = _policy.h_mm.or_default(_buffer_attr.mm.h); + + if (w_mm) xml.attribute("width_mm", w_mm); + if (h_mm) xml.attribute("height_mm", h_mm); + } + /******************************* ** Capture session interface ** diff --git a/repos/os/src/server/nitpicker/domain_registry.h b/repos/os/src/server/nitpicker/domain_registry.h index 486f3c2cbd..5f68a580a7 100644 --- a/repos/os/src/server/nitpicker/domain_registry.h +++ b/repos/os/src/server/nitpicker/domain_registry.h @@ -99,7 +99,7 @@ class Nitpicker::Domain_registry return pos + _corner(panorama) + _offset; } - Rect screen_rect(Area screen_area) const + Rect screen_rect(Rect const panorama) const { /* align value to zero or to limit, depending on its sign */ auto aligned = [&] (unsigned limit, int v) @@ -107,9 +107,9 @@ class Nitpicker::Domain_registry return unsigned((v > 0) ? v : max(0, int(limit) + v)); }; - return { .at = _offset, - .area = { .w = aligned(screen_area.w, _area.x), - .h = aligned(screen_area.h, _area.y) } }; + return { .at = _offset + panorama.at, + .area = { .w = aligned(panorama.w(), _area.x), + .h = aligned(panorama.h(), _area.y) } }; } }; diff --git a/repos/os/src/server/nitpicker/gui_session.cc b/repos/os/src/server/nitpicker/gui_session.cc index ba705866a0..7651fb99f1 100644 --- a/repos/os/src/server/nitpicker/gui_session.cc +++ b/repos/os/src/server/nitpicker/gui_session.cc @@ -375,20 +375,6 @@ void Gui_session::execute() } -Framebuffer::Mode Gui_session::mode() -{ - Rect const screen = screen_rect(_view_stack.bounding_box().area); - - /* - * Return at least a size of 1x1 to spare the clients the need to handle - * the special case of 0x0, which can happen at boot time before the - * framebuffer driver is running. - */ - return { .area = { max(screen.w(), 1u), max(screen.h(), 1u) }, - .alpha = uses_alpha() }; -} - - Gui_session::Buffer_result Gui_session::buffer(Framebuffer::Mode mode) { /* check if the session quota suffices for the specified mode */ @@ -472,3 +458,13 @@ Dataspace_capability Gui_session::realloc_buffer(Framebuffer::Mode mode) return _texture.dataspace(); } + + +void Gui_session::produce_xml(Xml_generator &xml) +{ + Rect const domain_panorama = + _domain ? _domain->screen_rect(_view_stack.bounding_box()) + : Rect { }; + + _action.gen_capture_info(xml, domain_panorama); +} diff --git a/repos/os/src/server/nitpicker/gui_session.h b/repos/os/src/server/nitpicker/gui_session.h index 40d5b3c50f..ea653f03ed 100644 --- a/repos/os/src/server/nitpicker/gui_session.h +++ b/repos/os/src/server/nitpicker/gui_session.h @@ -20,6 +20,7 @@ #include #include #include +#include #include /* local includes */ @@ -42,8 +43,19 @@ namespace Nitpicker { class Nitpicker::Gui_session : public Session_object, public View_owner, public Buffer_provider, - private Session_list::Element + private Session_list::Element, + private Dynamic_rom_session::Xml_producer { + public: + + struct Action : Interface + { + /* + * \param rect domain-specific panorama rectangle + */ + virtual void gen_capture_info(Xml_generator &xml, Rect rect) const = 0; + }; + private: struct View_ref : Gui::View_ref @@ -85,7 +97,8 @@ class Nitpicker::Gui_session : public Session_object, Gui_session(Gui_session const &); Gui_session &operator = (Gui_session const &); - Env &_env; + Env &_env; + Action &_action; Constrained_ram_allocator _ram; @@ -110,7 +123,7 @@ class Nitpicker::Gui_session : public Session_object, Focus_updater &_focus_updater; Hover_updater &_hover_updater; - Signal_context_capability _mode_sigh { }; + Constructible _info_rom { }; View &_pointer_origin; @@ -183,9 +196,15 @@ class Nitpicker::Gui_session : public Session_object, [&] /* ID does not exist */ { return missing_fn(); }); } + /** + * Dynamic_rom_session::Xml_producer interface + */ + void produce_xml(Xml_generator &) override; + public: Gui_session(Env &env, + Action &action, Resources const &resources, Label const &label, Diag const &diag, @@ -198,7 +217,8 @@ class Nitpicker::Gui_session : public Session_object, Reporter &focus_reporter) : Session_object(env.ep(), resources, label, diag), - _env(env), + Xml_producer("panorama"), + _env(env), _action(action), _ram(env.ram(), _ram_quota_guard(), _cap_quota_guard()), _session_alloc(_ram, env.rm()), _framebuffer_session_component(env.ep(), view_stack, *this, *this), @@ -319,14 +339,6 @@ class Nitpicker::Gui_session : public Session_object, */ void visible(bool visible) { _visible = visible; } - /** - * Return session-local screen geometry - */ - Rect screen_rect(Area screen_area) const - { - return _domain ? _domain->screen_rect(screen_area) : Rect { }; - } - void reset_domain() { _domain = nullptr; } /** @@ -344,8 +356,8 @@ class Nitpicker::Gui_session : public Session_object, */ void notify_mode_change() { - if (_mode_sigh.valid()) - Signal_transmitter(_mode_sigh).submit(); + if (_info_rom.constructed()) + _info_rom->trigger_update(); } /** @@ -375,6 +387,30 @@ class Nitpicker::Gui_session : public Session_object, Input::Session_capability input() override { return _input_session_component.cap(); } + Info_result info() override + { + if (!_info_rom.constructed()) { + Cap_quota const needed_caps { 2 }; + if (!try_withdraw(needed_caps)) + return Info_error::OUT_OF_CAPS; + + bool out_of_caps = false, out_of_ram = false; + try { + Dynamic_rom_session::Content_producer &rom_producer = *this; + _info_rom.construct(_env.ep(), _ram, _env.rm(), rom_producer); + } + catch (Out_of_ram) { out_of_ram = true; } + catch (Out_of_caps) { out_of_caps = true; } + + if (out_of_ram || out_of_ram) { + replenish(needed_caps); + if (out_of_ram) return Info_error::OUT_OF_RAM; + if (out_of_caps) return Info_error::OUT_OF_CAPS; + } + } + return _info_rom->cap(); + } + View_result view(View_id, View_attr const &attr) override; Child_view_result child_view(View_id, View_id, View_attr const &attr) override; @@ -391,10 +427,6 @@ class Nitpicker::Gui_session : public Session_object, void execute() override; - Framebuffer::Mode mode() override; - - void mode_sigh(Signal_context_capability sigh) override { _mode_sigh = sigh; } - Buffer_result buffer(Framebuffer::Mode) override; void focus(Capability) override; diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 37c2c01c8a..1706852412 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -90,6 +90,7 @@ class Nitpicker::Gui_root : public Root_component private: Env &_env; + Gui_session::Action &_action; Attached_rom_dataspace const &_config; Session_list &_session_list; Domain_registry const &_domain_registry; @@ -118,7 +119,7 @@ class Nitpicker::Gui_root : public Root_component resources.cap_quota.value -= 2; Gui_session *session = new (md_alloc()) - Gui_session(_env, + Gui_session(_env, _action, resources, label, session_diag_from_args(args), _view_stack, _focus_updater, _hover_updater, _pointer_origin, @@ -170,6 +171,7 @@ class Nitpicker::Gui_root : public Root_component * Constructor */ Gui_root(Env &env, + Gui_session::Action &action, Attached_rom_dataspace const &config, Session_list &session_list, Domain_registry const &domain_registry, @@ -184,7 +186,7 @@ class Nitpicker::Gui_root : public Root_component Hover_updater &hover_updater) : Root_component(&env.ep().rpc_ep(), &md_alloc), - _env(env), _config(config), _session_list(session_list), + _env(env), _action(action), _config(config), _session_list(session_list), _domain_registry(domain_registry), _global_keys(global_keys), _view_stack(view_stack), _user_state(user_state), _pointer_origin(pointer_origin), @@ -346,14 +348,11 @@ class Nitpicker::Capture_root : public Root_component session.mark_as_damaged(rect); }); } - void report_displays(Xml_generator &xml) const + void report_displays(Xml_generator &xml, Rect const domain_panorama) const { - Capture_session::gen_attr(xml, _view_stack.bounding_box()); - + gen_attr(xml, domain_panorama); _sessions.for_each([&] (Capture_session const &capture) { - xml.node("capture", [&] { - xml.attribute("name", capture.label()); - Capture_session::gen_attr(xml, capture.bounding_box()); }); }); + xml.node("capture", [&] { capture.gen_capture_attr(xml); }); }); } }; @@ -411,7 +410,8 @@ struct Nitpicker::Main : Focus_updater, Hover_updater, Capture_session::Handler, Event_session::Handler, Capture_root::Action, - User_state::Action + User_state::Action, + Gui_session::Action { Env &_env; @@ -613,11 +613,19 @@ struct Nitpicker::Main : Focus_updater, Hover_updater, Constructible _focus_rom { }; - Gui_root _gui_root { _env, _config_rom, _session_list, *_domain_registry, + Gui_root _gui_root { _env, *this, _config_rom, _session_list, *_domain_registry, _global_keys, _view_stack, _user_state, _pointer_origin, _builtin_background, _sliced_heap, _focus_reporter, *this, *this }; + /** + * Gui_session::Action interface + */ + void gen_capture_info(Xml_generator &xml, Rect const domain_panorama) const override + { + _capture_root.report_displays(xml, domain_panorama); + } + Capture_root _capture_root { _env, *this, _sliced_heap, _view_stack, *this }; Event_root _event_root { _env, _sliced_heap, *this }; @@ -1041,7 +1049,7 @@ void Nitpicker::Main::_report_displays() if (_fb_screen.constructed()) xml.node("display", [&] { gen_attr(xml, _fb_screen->_rect); }); - _capture_root.report_displays(xml); + _capture_root.report_displays(xml, _view_stack.bounding_box()); }); } diff --git a/repos/os/src/server/vmm/virtio_gpu.cc b/repos/os/src/server/vmm/virtio_gpu.cc index 7b26d892dc..81f2025b17 100644 --- a/repos/os/src/server/vmm/virtio_gpu.cc +++ b/repos/os/src/server/vmm/virtio_gpu.cc @@ -43,15 +43,15 @@ void Vmm::Virtio_gpu_queue::notify(Virtio_gpu_device & dev) void Vmm::Virtio_gpu_control_request::_get_display_info() { - Framebuffer::Mode mode = _device.resize(); + Gui::Area const mode = _device.resize(); Display_info_response dir { _desc_range(1) }; memset((void*)dir.base(), 0, Display_info_response::SIZE); dir.write(Control_header::Type::OK_DISPLAY_INFO); dir.write(0); dir.write(0); - dir.write(mode.area.w); - dir.write(mode.area.h); + dir.write(mode.w); + dir.write(mode.h); dir.write(1); dir.write(0); } @@ -195,9 +195,9 @@ void Vmm::Virtio_gpu_control_request::_resource_flush() uint32_t x = rf.read(); uint32_t y = rf.read(); uint32_t w = min(rf.read(), - _device._fb_mode.area.w - x); + _device._gui_win.area.w - x); uint32_t h = min(rf.read(), - _device._fb_mode.area.h - y); + _device._gui_win.area.h - y); enum { BYTES_PER_PIXEL = Virtio_gpu_device::BYTES_PER_PIXEL }; @@ -218,9 +218,9 @@ void Vmm::Virtio_gpu_control_request::_resource_flush() (res.area.w * y + x) * BYTES_PER_PIXEL); void * dst = (void*)((addr_t)_device._fb_ds->local_addr() + - (_device._fb_mode.area.w * y + x) * BYTES_PER_PIXEL); + (_device._gui_win.area.w * y + x) * BYTES_PER_PIXEL); uint32_t line_src = res.area.w * BYTES_PER_PIXEL; - uint32_t line_dst = _device._fb_mode.area.w * BYTES_PER_PIXEL; + uint32_t line_dst = _device._gui_win.area.w * BYTES_PER_PIXEL; blit(src, line_src, dst, line_dst, w*BYTES_PER_PIXEL, h); _device._gui.framebuffer.refresh({ { int(x), int(y) }, { w, h } }); diff --git a/repos/os/src/server/vmm/virtio_gpu.h b/repos/os/src/server/vmm/virtio_gpu.h index 766a16a090..c5db7da971 100644 --- a/repos/os/src/server/vmm/virtio_gpu.h +++ b/repos/os/src/server/vmm/virtio_gpu.h @@ -296,8 +296,16 @@ class Vmm::Virtio_gpu_device : public Virtio_device Gui::Connection & _gui; Cpu::Signal_handler _handler; Constructible _fb_ds { }; - Framebuffer::Mode _fb_mode { _gui.mode() }; - Gui::Top_level_view _view { _gui, { { }, _fb_mode.area } }; + + Gui::Rect _request_gui_window() + { + return _gui.window().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return Gui::Rect { { }, { 640, 480 } }; }); + } + + Gui::Rect _gui_win = _request_gui_window(); + Gui::Top_level_view _view { _gui, _gui_win }; using Area = Genode::Area<>; using Rect = Genode::Rect<>; @@ -446,7 +454,7 @@ class Vmm::Virtio_gpu_device : public Virtio_device _env(env), _heap(heap), _ram_ds(ram_ds), _gui(gui), _handler(cpu, env.ep(), *this, &Virtio_gpu_device::_mode_change) { - _gui.mode_sigh(_handler); + _gui.info_sigh(_handler); } void buffer_notification() @@ -454,21 +462,21 @@ class Vmm::Virtio_gpu_device : public Virtio_device _buffer_notification(); } - Framebuffer::Mode resize() + Gui::Area resize() { _fb_ds.destruct(); - _fb_mode = _gui.mode(); - _gui.buffer(_fb_mode); + _gui_win = _request_gui_window(); + _gui.buffer({ .area = _gui_win.area, .alpha = false }); - if (_fb_mode.area.count() > 0) + if (_gui_win.valid()) _fb_ds.construct(_env.rm(), _gui.framebuffer.dataspace()); using Command = Gui::Session::Command; - _gui.enqueue(_view.id(), Rect(Point(0, 0), _fb_mode.area)); + _gui.enqueue(_view.id(), _gui_win); _gui.enqueue(_view.id()); _gui.execute(); - return _gui.mode(); + return _gui_win.area; } }; diff --git a/repos/ports/src/virtualbox5/frontend/console.cc b/repos/ports/src/virtualbox5/frontend/console.cc index e8ba72f4ca..e3cc5f410f 100644 --- a/repos/ports/src/virtualbox5/frontend/console.cc +++ b/repos/ports/src/virtualbox5/frontend/console.cc @@ -291,7 +291,13 @@ void GenodeConsole::_handle_mode_change() Genodefb *fb = dynamic_cast(pFramebuffer); - fb->update_mode(_gui.mode()); + Gui::Rect const gui_win = _gui.window().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return _gui.panorama().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return Gui::Rect { { }, { 800, 600 } }; }); }); + + fb->update_mode(gui_win); update_video_mode(); } @@ -340,7 +346,7 @@ void GenodeConsole::init_backends(IKeyboard * gKeyboard, IMouse * gMouse) HRESULT rc = i_getDisplay()->QueryFramebuffer(0, &pFramebuffer); Assert(SUCCEEDED(rc) && pFramebuffer); - _gui.mode_sigh(_mode_change_signal_dispatcher); + _gui.info_sigh(_mode_change_signal_dispatcher); _handle_mode_change(); } diff --git a/repos/ports/src/virtualbox5/frontend/fb.h b/repos/ports/src/virtualbox5/frontend/fb.h index 0197cfbcf8..34ed4ce607 100644 --- a/repos/ports/src/virtualbox5/frontend/fb.h +++ b/repos/ports/src/virtualbox5/frontend/fb.h @@ -34,13 +34,13 @@ class Genodefb : Genode::Env &_env; Gui::Connection &_gui; Gui::Top_level_view _view { _gui }; - Fb_Genode::Mode _fb_mode { .area = { 1024, 768 } }; + Gui::Rect _gui_win { .at = { }, .area = { 1024, 768 } }; /* * The mode currently used by the VM. Can be smaller than the * framebuffer mode. */ - Fb_Genode::Mode _virtual_fb_mode; + Gui::Area _virtual_fb_mode; void *_attach() { @@ -64,23 +64,23 @@ class Genodefb : { if (!_fb_base) return; - size_t const max_h = Genode::min(_fb_mode.area.h, _virtual_fb_mode.area.h); - size_t const num_pixels = _fb_mode.area.w * max_h; + size_t const max_h = Genode::min(_gui_win.area.h, _virtual_fb_mode.h); + size_t const num_pixels = _gui_win.area.w * max_h; memset(_fb_base, 0, num_pixels * sizeof(Genode::Pixel_rgb888)); - _gui.framebuffer.refresh({ { 0, 0 }, _virtual_fb_mode.area }); + _gui.framebuffer.refresh({ _gui_win.at, _virtual_fb_mode }); } void _adjust_buffer() { - _gui.buffer(_fb_mode); - _view.area(_fb_mode.area); + _gui.buffer({ .area = _gui_win.area, .alpha = false }); + _view.geometry(_gui_win); } - Fb_Genode::Mode _initial_setup() + Gui::Area _initial_setup() { _adjust_buffer(); _view.front(); - return _fb_mode; + return _gui_win.area; } public: @@ -96,14 +96,14 @@ class Genodefb : Assert(rc == VINF_SUCCESS); } - int w() const { return _fb_mode.area.w; } - int h() const { return _fb_mode.area.h; } + int w() const { return _gui_win.area.w; } + int h() const { return _gui_win.area.h; } - void update_mode(Fb_Genode::Mode mode) + void update_mode(Gui::Rect const gui_win) { Lock(); - _fb_mode = mode; + _gui_win = gui_win; if (_fb_base) _env.rm().detach(Genode::addr_t(_fb_base)); @@ -135,32 +135,32 @@ class Genodefb : /* save the new bitmap reference */ _display->QuerySourceBitmap(screen, _display_bitmap.asOutParam()); - bool const ok = (w <= (ULONG)_fb_mode.area.w) && - (h <= (ULONG)_fb_mode.area.h); + bool const ok = (w <= (ULONG)_gui_win.area.w) && + (h <= (ULONG)_gui_win.area.h); - bool const changed = (w != (ULONG)_virtual_fb_mode.area.w) || - (h != (ULONG)_virtual_fb_mode.area.h); + bool const changed = (w != (ULONG)_virtual_fb_mode.w) || + (h != (ULONG)_virtual_fb_mode.h); if (ok && changed) { Genode::log("fb resize : [", screen, "] ", - _virtual_fb_mode.area, " -> ", + _virtual_fb_mode, " -> ", w, "x", h, - " (host: ", _fb_mode.area, ")"); + " (host: ", _gui_win.area, ")"); - if ((w < (ULONG)_fb_mode.area.w) || - (h < (ULONG)_fb_mode.area.h)) { + if ((w < (ULONG)_gui_win.area.w) || + (h < (ULONG)_gui_win.area.h)) { /* clear the old content around the new, smaller area. */ _clear_screen(); } - _virtual_fb_mode = Fb_Genode::Mode { .area = { w, h } }; + _virtual_fb_mode = { w, h }; result = S_OK; } else if (changed) { Genode::log("fb resize : [", screen, "] ", - _virtual_fb_mode.area, " -> ", + _virtual_fb_mode, " -> ", w, "x", h, " ignored" - " (host: ", _fb_mode.area, ")"); + " (host: ", _gui_win.area, ")"); } Unlock(); @@ -213,8 +213,8 @@ class Genodefb : &ulBytesPerLine, &bitmapFormat); - Gui::Area const area_fb = Gui::Area(_fb_mode.area.w, - _fb_mode.area.h); + Gui::Area const area_fb = Gui::Area(_gui_win.area.w, + _gui_win.area.h); Gui::Area const area_vm = Gui::Area(ulWidth, ulHeight); using namespace Genode; @@ -251,7 +251,7 @@ class Genodefb : Lock(); - Gui::Area const area_fb = _fb_mode.area; + Gui::Area const area_fb = _gui_win.area; Gui::Area const area_vm = Gui::Area(width, height); using namespace Genode; @@ -290,8 +290,8 @@ class Genodefb : if (!supported) return E_POINTER; - *supported = ((width <= (ULONG)_fb_mode.area.w) && - (height <= (ULONG)_fb_mode.area.h)); + *supported = ((width <= (ULONG)_gui_win.area.w) && + (height <= (ULONG)_gui_win.area.h)); return S_OK; } diff --git a/repos/ports/src/virtualbox6/include/fb.h b/repos/ports/src/virtualbox6/include/fb.h index 3d2e990134..46d1076f90 100644 --- a/repos/ports/src/virtualbox6/include/fb.h +++ b/repos/ports/src/virtualbox6/include/fb.h @@ -33,13 +33,13 @@ class Genodefb : Genode::Env &_env; Gui::Connection &_gui; Gui::Top_level_view _view { _gui }; - Fb_Genode::Mode _fb_mode { .area = { 1024, 768 } }; + Gui::Rect _gui_win { { }, { 1024, 768 } }; /* * The mode currently used by the VM. Can be smaller than the * framebuffer mode. */ - Fb_Genode::Mode _virtual_fb_mode; + Gui::Area _virtual_fb_mode; void *_attach() { @@ -62,23 +62,23 @@ class Genodefb : { if (!_fb_base) return; - size_t const max_h = Genode::min(_fb_mode.area.h, _virtual_fb_mode.area.h); - size_t const num_pixels = _fb_mode.area.w * max_h; + size_t const max_h = Genode::min(_gui_win.area.h, _virtual_fb_mode.h); + size_t const num_pixels = _gui_win.area.w * max_h; memset(_fb_base, 0, num_pixels * sizeof(Genode::Pixel_rgb888)); - _gui.framebuffer.refresh({ { 0, 0 }, _virtual_fb_mode.area }); + _gui.framebuffer.refresh({ _gui_win.at, _virtual_fb_mode }); } void _adjust_buffer() { - _gui.buffer(_fb_mode); - _view.area(_fb_mode.area); + _gui.buffer({ .area = _gui_win.area, .alpha = false }); + _view.area(_gui_win.area); } - Fb_Genode::Mode _initial_setup() + Gui::Area _initial_setup() { _adjust_buffer(); _view.front(); - return _fb_mode; + return _gui_win.area; } public: @@ -98,14 +98,14 @@ class Genodefb : virtual ~Genodefb() { } - int w() const { return _fb_mode.area.w; } - int h() const { return _fb_mode.area.h; } + int w() const { return _gui_win.area.w; } + int h() const { return _gui_win.area.h; } - void update_mode(Fb_Genode::Mode mode) + void update_mode(Gui::Rect gui_win) { Lock(); - _fb_mode = mode; + _gui_win = gui_win; if (_fb_base) _env.rm().detach(Genode::addr_t(_fb_base)); @@ -137,32 +137,32 @@ class Genodefb : /* save the new bitmap reference */ _display->QuerySourceBitmap(screen, _display_bitmap.asOutParam()); - bool const ok = (w <= (ULONG)_fb_mode.area.w) && - (h <= (ULONG)_fb_mode.area.h); + bool const ok = (w <= (ULONG)_gui_win.area.w) && + (h <= (ULONG)_gui_win.area.h); - bool const changed = (w != (ULONG)_virtual_fb_mode.area.w) || - (h != (ULONG)_virtual_fb_mode.area.h); + bool const changed = (w != (ULONG)_virtual_fb_mode.w) || + (h != (ULONG)_virtual_fb_mode.h); if (ok && changed) { Genode::log("fb resize : [", screen, "] ", - _virtual_fb_mode.area, " -> ", + _virtual_fb_mode, " -> ", w, "x", h, - " (host: ", _fb_mode.area, ")"); + " (host: ", _gui_win.area, ")"); - if ((w < (ULONG)_fb_mode.area.w) || - (h < (ULONG)_fb_mode.area.h)) { + if ((w < (ULONG)_gui_win.area.w) || + (h < (ULONG)_gui_win.area.h)) { /* clear the old content around the new, smaller area. */ _clear_screen(); } - _virtual_fb_mode = Fb_Genode::Mode { .area = { w, h } }; + _virtual_fb_mode = { w, h }; result = S_OK; } else if (changed) { Genode::log("fb resize : [", screen, "] ", - _virtual_fb_mode.area, " -> ", + _virtual_fb_mode, " -> ", w, "x", h, " ignored" - " (host: ", _fb_mode.area, ")"); + " (host: ", _gui_win.area, ")"); } Unlock(); @@ -215,8 +215,8 @@ class Genodefb : &ulBytesPerLine, &bitmapFormat); - Gui::Area const area_fb = Gui::Area(_fb_mode.area.w, - _fb_mode.area.h); + Gui::Area const area_fb = Gui::Area(_gui_win.area.w, + _gui_win.area.h); Gui::Area const area_vm = Gui::Area(ulWidth, ulHeight); using namespace Genode; @@ -253,7 +253,7 @@ class Genodefb : Lock(); - Gui::Area const area_fb = _fb_mode.area; + Gui::Area const area_fb = _gui_win.area; Gui::Area const area_vm = Gui::Area(width, height); using namespace Genode; @@ -292,8 +292,8 @@ class Genodefb : if (!supported) return E_POINTER; - *supported = ((width <= (ULONG)_fb_mode.area.w) && - (height <= (ULONG)_fb_mode.area.h)); + *supported = ((width <= (ULONG)_gui_win.area.w) && + (height <= (ULONG)_gui_win.area.h)); return S_OK; } diff --git a/repos/ports/src/virtualbox6/main.cc b/repos/ports/src/virtualbox6/main.cc index 96a58a635c..62308f8cf8 100644 --- a/repos/ports/src/virtualbox6/main.cc +++ b/repos/ports/src/virtualbox6/main.cc @@ -302,7 +302,7 @@ struct Main : Event_handler Gui::Connection &gui = *new Registered(_gui_connections, _env, label.string()); gui.input.sigh(_input_handler); - gui.mode_sigh(_fb_mode_handler); + gui.info_sigh(_fb_mode_handler); Genodefb *fb = new Genodefb(_env, gui, _idisplay); @@ -438,7 +438,13 @@ void Main::_handle_fb_mode() Genodefb *fb = dynamic_cast(pFramebuffer); - fb->update_mode(gui.mode()); + Gui::Rect const gui_win = gui.window().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return gui.panorama().convert( + [&] (Gui::Rect rect) { return rect; }, + [&] (Gui::Undefined) { return Gui::Rect { { }, { 800, 600 } }; }); }); + + fb->update_mode(gui_win); if ((fb->w() <= 1) && (fb->h() <= 1)) { /* interpret a size of 0x0 as indication to quit VirtualBox */