mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
gui_session: provide mode info as XML
In multi-monitor scenarios, the mode is no longer a single rectangular area but a panorama with potentially many captured rectangles. This patch replaces the former 'mode' and 'mode_sigh' RPC by a new 'info' ROM accessor. Issue #5353
This commit is contained in:
parent
d29cb0a15d
commit
318d641266
@ -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<Command::Background>(_view_id);
|
||||
Gui::Rect rect(Gui::Point(), _buffer->size());
|
||||
Gui::Rect rect(_gui_win.at, _buffer->size());
|
||||
_gui.enqueue<Command::Geometry>(_view_id, rect);
|
||||
_gui.enqueue<Command::Back>(_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>(
|
||||
[&] (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);
|
||||
|
||||
|
@ -56,9 +56,12 @@ struct Decorator::Main : Window_factory_base
|
||||
|
||||
struct Canvas
|
||||
{
|
||||
Framebuffer::Mode const mode;
|
||||
Attached_dataspace fb_ds;
|
||||
Decorator::Canvas<Pixel_rgb888> canvas;
|
||||
Env &_env;
|
||||
Gui::Connection &_gui;
|
||||
|
||||
Gui::Area const scr_area = _gui.panorama().convert<Gui::Area>(
|
||||
[&] (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<Pixel_rgb888>() + mode.area.count();
|
||||
return fb_ds.local_addr<Pixel_rgb888>() + 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<Pixel_rgb888> canvas {
|
||||
_canvas_pixels_ptr(), scr_area, _env.ram(), _env.rm() };
|
||||
|
||||
Canvas(Env &env, Gui::Connection &gui) : _env(env), _gui(gui) { }
|
||||
};
|
||||
|
||||
Reconstructible<Canvas> _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);
|
||||
|
@ -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();
|
||||
|
@ -145,11 +145,8 @@ struct Gui::Session_component : Rpc_object<Gui::Session>
|
||||
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); }
|
||||
|
@ -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::Area>(
|
||||
[&] (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;
|
||||
|
@ -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::Area>(
|
||||
[&] (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);
|
||||
|
@ -150,11 +150,8 @@ struct Sandboxed_runtime::Gui_session : Session_object<Gui::Session>
|
||||
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); }
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -100,9 +100,16 @@ struct Terminal::Main : Character_consumer
|
||||
Signal_handler<Main> _config_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
|
||||
Gui::Rect _gui_window_rect()
|
||||
{
|
||||
return _gui.window().convert<Gui::Rect>(
|
||||
[&] (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<Attached_dataspace> _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<PT> surface(_fb_ds->local_addr<PT>(), _fb_mode.area);
|
||||
Surface<PT> surface(_fb_ds->local_addr<PT>(), _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<Command::Geometry>(_view, Rect(Point(0, 0), _fb_mode.area));
|
||||
_gui.enqueue<Command::Geometry>(_view, _win_rect);
|
||||
_gui.enqueue<Command::Front>(_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<PT>::Geometry const new_geometry(_font->font(), _fb_mode.area);
|
||||
Text_screen_surface<PT>::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);
|
||||
|
@ -222,6 +222,11 @@ struct Wm::Decorator_gui_session : Session_object<Gui::Session>,
|
||||
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<Gui::Session>,
|
||||
_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);
|
||||
|
@ -104,14 +104,9 @@ class Wm::Direct_gui_session : public Session_object<Gui::Session>
|
||||
_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
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <gui_session/connection.h>
|
||||
#include <input_session/capability.h>
|
||||
#include <input/component.h>
|
||||
#include <os/dynamic_rom_session.h>
|
||||
|
||||
/* local includes */
|
||||
#include <window_registry.h>
|
||||
@ -494,8 +495,16 @@ class Wm::Gui::Child_view : public View, private List<Child_view>::Element
|
||||
class Wm::Gui::Session_component : public Session_object<Gui::Session>,
|
||||
private List<Session_component>::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<Session_component>;
|
||||
@ -531,7 +540,8 @@ class Wm::Gui::Session_component : public Session_object<Gui::Session>,
|
||||
}
|
||||
};
|
||||
|
||||
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<Gui::Session>,
|
||||
|
||||
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_session> _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<Gui::Session>,
|
||||
Signal_handler<Session_component> _input_handler {
|
||||
_env.ep(), *this, &Session_component::_handle_input };
|
||||
|
||||
Signal_handler<Session_component> _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<Gui::Session>,
|
||||
}
|
||||
}
|
||||
|
||||
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<Gui::Session>,
|
||||
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<Gui::Session>,
|
||||
Click_handler &click_handler)
|
||||
:
|
||||
Session_object<Gui::Session>(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<Gui::Session>,
|
||||
_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<Gui::Session>,
|
||||
*/
|
||||
Capability<Session> 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<Gui::Session>,
|
||||
});
|
||||
|
||||
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<Gui::Session>,
|
||||
_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<Typed_root<Gui::Session> >,
|
||||
|
||||
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<Typed_root<Gui::Session> >,
|
||||
/**
|
||||
* 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<Typed_root<Gui::Session> >,
|
||||
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<Typed_root<Gui::Session> >,
|
||||
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<Typed_root<Gui::Session> >,
|
||||
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_ */
|
||||
|
@ -33,8 +33,6 @@ struct Wm::Layouter_gui_session : Session_object<Gui::Session>
|
||||
*/
|
||||
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<Gui::Session>
|
||||
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<Gui::Session>
|
||||
|
||||
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<Gui::Session>) override { }
|
||||
|
@ -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<Main> _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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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>(
|
||||
[&] (Gui::Rect rect) { return rect; },
|
||||
[&] (Gui::Undefined) { return Gui::Rect { { }, { 512, 512 } }; });
|
||||
}
|
||||
|
||||
Gui::Rect _win_rect = _gui_window();
|
||||
|
||||
Framebuffer::Mode _fb_mode {};
|
||||
|
||||
Genode::Constructible<Genode::Attached_dataspace> _fb_ds { };
|
||||
|
||||
Genode::Signal_handler<Pdf_view> _nit_mode_handler {
|
||||
_env.ep(), *this, &Pdf_view::_handle_nit_mode };
|
||||
Genode::Signal_handler<Pdf_view> _gui_mode_handler {
|
||||
_env.ep(), *this, &Pdf_view::_handle_gui_mode };
|
||||
|
||||
Genode::Signal_handler<Pdf_view> _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 });
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,9 @@ struct Gui::Session_client : Rpc_client<Session>
|
||||
Input::Session_capability input() override {
|
||||
return call<Rpc_input>(); }
|
||||
|
||||
Info_result info() override {
|
||||
return call<Rpc_info>(); }
|
||||
|
||||
[[nodiscard]] View_result view(View_id id, View_attr const &attr) override {
|
||||
return call<Rpc_view>(id, attr); }
|
||||
|
||||
@ -53,12 +56,6 @@ struct Gui::Session_client : Rpc_client<Session>
|
||||
|
||||
void execute() override { call<Rpc_execute>(); }
|
||||
|
||||
Framebuffer::Mode mode() override {
|
||||
return call<Rpc_mode>(); }
|
||||
|
||||
void mode_sigh(Signal_context_capability sigh) override {
|
||||
call<Rpc_mode_sigh>(sigh); }
|
||||
|
||||
[[nodiscard]] Buffer_result buffer(Framebuffer::Mode mode) override {
|
||||
return call<Rpc_buffer>(mode); }
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <gui_session/client.h>
|
||||
#include <framebuffer_session/client.h>
|
||||
#include <input_session/client.h>
|
||||
#include <rom_session/client.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Gui {
|
||||
@ -52,6 +53,43 @@ class Gui::Connection : private Genode::Connection<Session>
|
||||
static constexpr Ram_quota _RAM_QUOTA { 96*1024 };
|
||||
static constexpr Cap_quota _CAP_QUOTA { Session::CAP_QUOTA + 9 };
|
||||
|
||||
Constructible<Rom_session_client> _info_rom { };
|
||||
Constructible<Attached_dataspace> _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>(
|
||||
[&] (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<char>(), _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<Session>
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<Rom_session> info_rom_cap()
|
||||
{
|
||||
Capability<Rom_session> result { };
|
||||
_with_info_rom([&] (Rom_session_client &rom) { result = rom.rpc_cap(); });
|
||||
return result;
|
||||
}
|
||||
|
||||
using Panorama_result = Attempt<Gui::Rect, Gui::Undefined>;
|
||||
|
||||
/**
|
||||
* 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<Rect, Gui::Undefined>;
|
||||
|
||||
/**
|
||||
* 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<Session> focused) { _client.focus(focused); }
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <os/surface.h>
|
||||
#include <framebuffer_session/capability.h>
|
||||
#include <input_session/capability.h>
|
||||
#include <rom_session/rom_session.h>
|
||||
|
||||
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<Capability<Rom_session>, 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<Session>);
|
||||
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_ */
|
||||
|
@ -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::Area>(
|
||||
[&] (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();
|
||||
|
@ -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>(
|
||||
[&] (Gui::Rect rect) { return rect; },
|
||||
[&] (Gui::Undefined) { return _gui.panorama().convert<Gui::Rect>(
|
||||
[&] (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);
|
||||
}
|
||||
};
|
||||
|
@ -86,15 +86,6 @@ class Nitpicker::Capture_session : public Session_object<Capture::Session>
|
||||
}
|
||||
};
|
||||
|
||||
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<Capture::Session>
|
||||
|
||||
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 **
|
||||
|
@ -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) } };
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <base/heap.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <os/reporter.h>
|
||||
#include <os/dynamic_rom_session.h>
|
||||
#include <gui_session/gui_session.h>
|
||||
|
||||
/* local includes */
|
||||
@ -42,8 +43,19 @@ namespace Nitpicker {
|
||||
class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
||||
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(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<Gui::Session>,
|
||||
Focus_updater &_focus_updater;
|
||||
Hover_updater &_hover_updater;
|
||||
|
||||
Signal_context_capability _mode_sigh { };
|
||||
Constructible<Dynamic_rom_session> _info_rom { };
|
||||
|
||||
View &_pointer_origin;
|
||||
|
||||
@ -183,9 +196,15 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
||||
[&] /* 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<Gui::Session>,
|
||||
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<Gui::Session>,
|
||||
*/
|
||||
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<Gui::Session>,
|
||||
*/
|
||||
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<Gui::Session>,
|
||||
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<Gui::Session>,
|
||||
|
||||
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<Gui::Session>) override;
|
||||
|
@ -90,6 +90,7 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>
|
||||
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<Gui_session>
|
||||
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<Gui_session>
|
||||
* 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<Gui_session>
|
||||
Hover_updater &hover_updater)
|
||||
:
|
||||
Root_component<Gui_session>(&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<Capture_session>
|
||||
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<Attached_rom_dataspace> _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());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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>(Control_header::Type::OK_DISPLAY_INFO);
|
||||
|
||||
dir.write<Display_info_response::X>(0);
|
||||
dir.write<Display_info_response::Y>(0);
|
||||
dir.write<Display_info_response::Width>(mode.area.w);
|
||||
dir.write<Display_info_response::Height>(mode.area.h);
|
||||
dir.write<Display_info_response::Width>(mode.w);
|
||||
dir.write<Display_info_response::Height>(mode.h);
|
||||
dir.write<Display_info_response::Enabled>(1);
|
||||
dir.write<Display_info_response::Flags>(0);
|
||||
}
|
||||
@ -195,9 +195,9 @@ void Vmm::Virtio_gpu_control_request::_resource_flush()
|
||||
uint32_t x = rf.read<Resource_flush::X>();
|
||||
uint32_t y = rf.read<Resource_flush::Y>();
|
||||
uint32_t w = min(rf.read<Resource_flush::Width>(),
|
||||
_device._fb_mode.area.w - x);
|
||||
_device._gui_win.area.w - x);
|
||||
uint32_t h = min(rf.read<Resource_flush::Height>(),
|
||||
_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<void>() +
|
||||
(_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 } });
|
||||
|
@ -296,8 +296,16 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
|
||||
Gui::Connection & _gui;
|
||||
Cpu::Signal_handler<Virtio_gpu_device> _handler;
|
||||
Constructible<Attached_dataspace> _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>(
|
||||
[&] (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<Virtio_gpu_queue, 2>
|
||||
_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<Virtio_gpu_queue, 2>
|
||||
_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<Command::Geometry>(_view.id(), Rect(Point(0, 0), _fb_mode.area));
|
||||
_gui.enqueue<Command::Geometry>(_view.id(), _gui_win);
|
||||
_gui.enqueue<Command::Front>(_view.id());
|
||||
_gui.execute();
|
||||
return _gui.mode();
|
||||
return _gui_win.area;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -291,7 +291,13 @@ void GenodeConsole::_handle_mode_change()
|
||||
|
||||
Genodefb *fb = dynamic_cast<Genodefb *>(pFramebuffer);
|
||||
|
||||
fb->update_mode(_gui.mode());
|
||||
Gui::Rect const gui_win = _gui.window().convert<Gui::Rect>(
|
||||
[&] (Gui::Rect rect) { return rect; },
|
||||
[&] (Gui::Undefined) { return _gui.panorama().convert<Gui::Rect>(
|
||||
[&] (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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ struct Main : Event_handler
|
||||
Gui::Connection &gui = *new Registered<Gui::Connection>(_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<Genodefb *>(pFramebuffer);
|
||||
|
||||
fb->update_mode(gui.mode());
|
||||
Gui::Rect const gui_win = gui.window().convert<Gui::Rect>(
|
||||
[&] (Gui::Rect rect) { return rect; },
|
||||
[&] (Gui::Undefined) { return gui.panorama().convert<Gui::Rect>(
|
||||
[&] (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 */
|
||||
|
Loading…
Reference in New Issue
Block a user