@@ -6,4 +6,5 @@ input_session
|
|||||||
timer_session
|
timer_session
|
||||||
framebuffer_session
|
framebuffer_session
|
||||||
gui_session
|
gui_session
|
||||||
|
capture_session
|
||||||
report_session
|
report_session
|
||||||
|
|||||||
@@ -60,11 +60,14 @@ class Nitpicker::Canvas : public Canvas_base, public Surface_base::Flusher
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Point const _offset;
|
||||||
Surface<PT> _surface;
|
Surface<PT> _surface;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Canvas(PT *base, Area size) : _surface(base, size)
|
Canvas(PT *base, Point offset, Area size)
|
||||||
|
:
|
||||||
|
_offset(offset), _surface(base, size)
|
||||||
{
|
{
|
||||||
_surface.flusher(this);
|
_surface.flusher(this);
|
||||||
}
|
}
|
||||||
@@ -76,13 +79,20 @@ class Nitpicker::Canvas : public Canvas_base, public Surface_base::Flusher
|
|||||||
|
|
||||||
Area size() const override { return _surface.size(); }
|
Area size() const override { return _surface.size(); }
|
||||||
|
|
||||||
Rect clip() const override { return _surface.clip(); }
|
Rect clip() const override
|
||||||
|
{
|
||||||
|
Rect const clip_rect = _surface.clip();
|
||||||
|
return Rect(clip_rect.p1() + _offset, clip_rect.area());
|
||||||
|
}
|
||||||
|
|
||||||
void clip(Rect rect) override { _surface.clip(rect); }
|
void clip(Rect rect) override
|
||||||
|
{
|
||||||
|
_surface.clip(Rect(rect.p1() - _offset, rect.area()));
|
||||||
|
}
|
||||||
|
|
||||||
void draw_box(Rect rect, Color color) override
|
void draw_box(Rect rect, Color color) override
|
||||||
{
|
{
|
||||||
Box_painter::paint(_surface, rect, color);
|
Box_painter::paint(_surface, Rect(rect.p1() - _offset, rect.area()), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_texture(Point pos, Texture_base const &texture_base,
|
void draw_texture(Point pos, Texture_base const &texture_base,
|
||||||
@@ -90,13 +100,14 @@ class Nitpicker::Canvas : public Canvas_base, public Surface_base::Flusher
|
|||||||
bool allow_alpha) override
|
bool allow_alpha) override
|
||||||
{
|
{
|
||||||
Texture<PT> const &texture = static_cast<Texture<PT> const &>(texture_base);
|
Texture<PT> const &texture = static_cast<Texture<PT> const &>(texture_base);
|
||||||
Texture_painter::paint(_surface, texture, mix_color, pos, mode,
|
Texture_painter::paint(_surface, texture, mix_color, pos - _offset, mode,
|
||||||
allow_alpha);
|
allow_alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_text(Point pos, Font const &font,
|
void draw_text(Point pos, Font const &font,
|
||||||
Color color, char const *string) override
|
Color color, char const *string) override
|
||||||
{
|
{
|
||||||
|
pos = pos - _offset;
|
||||||
Text_painter::paint(_surface, Text_painter::Position(pos.x(), pos.y()),
|
Text_painter::paint(_surface, Text_painter::Position(pos.x(), pos.y()),
|
||||||
font, color, string);
|
font, color, string);
|
||||||
}
|
}
|
||||||
|
|||||||
163
repos/os/src/server/nitpicker/capture_session.h
Normal file
163
repos/os/src/server/nitpicker/capture_session.h
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* \brief Capture session component
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2020-06-27
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CAPTURE_SESSION_H_
|
||||||
|
#define _CAPTURE_SESSION_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <base/session_object.h>
|
||||||
|
#include <capture_session/capture_session.h>
|
||||||
|
|
||||||
|
namespace Nitpicker { class Capture_session; }
|
||||||
|
|
||||||
|
|
||||||
|
class Nitpicker::Capture_session : public Session_object<Capture::Session>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct Handler : Interface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Prompt nitpicker to adjust the screen size depending on all
|
||||||
|
* present capture buffers.
|
||||||
|
*/
|
||||||
|
virtual void capture_buffer_size_changed() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Env &_env;
|
||||||
|
|
||||||
|
Constrained_ram_allocator _ram;
|
||||||
|
|
||||||
|
Handler &_handler;
|
||||||
|
|
||||||
|
View_stack const &_view_stack;
|
||||||
|
|
||||||
|
Area _buffer_size { };
|
||||||
|
|
||||||
|
Constructible<Attached_ram_dataspace> _buffer { };
|
||||||
|
|
||||||
|
Signal_context_capability _screen_size_sigh { };
|
||||||
|
|
||||||
|
using Dirty_rect = Genode::Dirty_rect<Rect, Affected_rects::NUM_RECTS>;
|
||||||
|
|
||||||
|
Dirty_rect _dirty_rect { };
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Capture_session(Env &env,
|
||||||
|
Resources const &resources,
|
||||||
|
Label const &label,
|
||||||
|
Diag const &diag,
|
||||||
|
Handler &handler,
|
||||||
|
View_stack const &view_stack)
|
||||||
|
:
|
||||||
|
Session_object(env.ep(), resources, label, diag),
|
||||||
|
_env(env),
|
||||||
|
_ram(env.ram(), _ram_quota_guard(), _cap_quota_guard()),
|
||||||
|
_handler(handler),
|
||||||
|
_view_stack(view_stack)
|
||||||
|
{
|
||||||
|
_dirty_rect.mark_as_dirty(Rect(Point(0, 0), view_stack.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
~Capture_session() { }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
** Interface used by 'Nitpicker::Main' **
|
||||||
|
*****************************************/
|
||||||
|
|
||||||
|
Area buffer_size() const { return _buffer_size; }
|
||||||
|
|
||||||
|
void mark_as_damaged(Rect rect)
|
||||||
|
{
|
||||||
|
// XXX not called yet
|
||||||
|
_dirty_rect.mark_as_dirty(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen_size_changed()
|
||||||
|
{
|
||||||
|
if (_screen_size_sigh.valid())
|
||||||
|
Signal_transmitter(_screen_size_sigh).submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
** Capture session interface **
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
Area screen_size() const override { return _view_stack.size(); }
|
||||||
|
|
||||||
|
void screen_size_sigh(Signal_context_capability sigh) override
|
||||||
|
{
|
||||||
|
_screen_size_sigh = sigh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer(Area size) override
|
||||||
|
{
|
||||||
|
_buffer_size = Area { };
|
||||||
|
|
||||||
|
if (size.count() == 0) {
|
||||||
|
_buffer.destruct();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_buffer.construct(_ram, _env.rm(), buffer_bytes(size));
|
||||||
|
_buffer_size = size;
|
||||||
|
_handler.capture_buffer_size_changed();
|
||||||
|
} catch (...) {
|
||||||
|
_handler.capture_buffer_size_changed();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dataspace_capability dataspace() override
|
||||||
|
{
|
||||||
|
if (_buffer.constructed())
|
||||||
|
return _buffer->cap();
|
||||||
|
|
||||||
|
return Dataspace_capability();
|
||||||
|
}
|
||||||
|
|
||||||
|
Affected_rects capture_at(Point pos) override
|
||||||
|
{
|
||||||
|
if (!_buffer.constructed())
|
||||||
|
return Affected_rects { };
|
||||||
|
|
||||||
|
using Pixel = Pixel_rgb888;
|
||||||
|
|
||||||
|
Canvas<Pixel> canvas = { _buffer->local_addr<Pixel>(), pos, _buffer_size };
|
||||||
|
|
||||||
|
Rect const buffer_rect(Point(0, 0), _buffer_size);
|
||||||
|
|
||||||
|
Affected_rects affected { };
|
||||||
|
unsigned i = 0;
|
||||||
|
_dirty_rect.flush([&] (Rect const &rect) {
|
||||||
|
|
||||||
|
_view_stack.draw(canvas, rect);
|
||||||
|
|
||||||
|
if (i < Affected_rects::NUM_RECTS) {
|
||||||
|
Rect const translated(rect.p1() - pos, rect.area());
|
||||||
|
Rect const clipped = Rect::intersect(translated, buffer_rect);
|
||||||
|
affected.rects[i++] = clipped;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return affected;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _CAPTURE_SESSION_H_ */
|
||||||
@@ -411,7 +411,7 @@ void Gui_session::execute()
|
|||||||
|
|
||||||
Framebuffer::Mode Gui_session::mode()
|
Framebuffer::Mode Gui_session::mode()
|
||||||
{
|
{
|
||||||
return Framebuffer::Mode { .area = screen_area(_screen_size) };
|
return Framebuffer::Mode { .area = screen_area(_view_stack.size()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -93,8 +93,6 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
|||||||
|
|
||||||
Sliced_heap _session_alloc;
|
Sliced_heap _session_alloc;
|
||||||
|
|
||||||
Area const &_screen_size;
|
|
||||||
|
|
||||||
Framebuffer::Session_component _framebuffer_session_component;
|
Framebuffer::Session_component _framebuffer_session_component;
|
||||||
|
|
||||||
bool const _input_session_accounted = (
|
bool const _input_session_accounted = (
|
||||||
@@ -179,7 +177,6 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
|||||||
Focus_updater &focus_updater,
|
Focus_updater &focus_updater,
|
||||||
View &pointer_origin,
|
View &pointer_origin,
|
||||||
View &builtin_background,
|
View &builtin_background,
|
||||||
Area const &screen_size,
|
|
||||||
bool provides_default_bg,
|
bool provides_default_bg,
|
||||||
Reporter &focus_reporter,
|
Reporter &focus_reporter,
|
||||||
Visibility_controller &visibility_controller)
|
Visibility_controller &visibility_controller)
|
||||||
@@ -188,7 +185,6 @@ class Nitpicker::Gui_session : public Session_object<Gui::Session>,
|
|||||||
_env(env),
|
_env(env),
|
||||||
_ram(env.ram(), _ram_quota_guard(), _cap_quota_guard()),
|
_ram(env.ram(), _ram_quota_guard(), _cap_quota_guard()),
|
||||||
_session_alloc(_ram, env.rm()),
|
_session_alloc(_ram, env.rm()),
|
||||||
_screen_size(screen_size),
|
|
||||||
_framebuffer_session_component(view_stack, *this, *this),
|
_framebuffer_session_component(view_stack, *this, *this),
|
||||||
_view_stack(view_stack), _focus_updater(focus_updater),
|
_view_stack(view_stack), _focus_updater(focus_updater),
|
||||||
_pointer_origin(pointer_origin),
|
_pointer_origin(pointer_origin),
|
||||||
|
|||||||
@@ -31,9 +31,11 @@
|
|||||||
#include "clip_guard.h"
|
#include "clip_guard.h"
|
||||||
#include "pointer_origin.h"
|
#include "pointer_origin.h"
|
||||||
#include "domain_registry.h"
|
#include "domain_registry.h"
|
||||||
|
#include "capture_session.h"
|
||||||
|
|
||||||
namespace Nitpicker {
|
namespace Nitpicker {
|
||||||
class Gui_root;
|
class Gui_root;
|
||||||
|
class Capture_root;
|
||||||
struct Main;
|
struct Main;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +77,6 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>,
|
|||||||
User_state &_user_state;
|
User_state &_user_state;
|
||||||
View &_pointer_origin;
|
View &_pointer_origin;
|
||||||
View &_builtin_background;
|
View &_builtin_background;
|
||||||
Area const &_screen_size;
|
|
||||||
Reporter &_focus_reporter;
|
Reporter &_focus_reporter;
|
||||||
Reporter &_hover_reporter;
|
Reporter &_hover_reporter;
|
||||||
Focus_updater &_focus_updater;
|
Focus_updater &_focus_updater;
|
||||||
@@ -93,8 +94,8 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>,
|
|||||||
session_resources_from_args(args), label,
|
session_resources_from_args(args), label,
|
||||||
session_diag_from_args(args),
|
session_diag_from_args(args),
|
||||||
_view_stack, _focus_updater, _pointer_origin,
|
_view_stack, _focus_updater, _pointer_origin,
|
||||||
_builtin_background, _screen_size,
|
_builtin_background, provides_default_bg,
|
||||||
provides_default_bg, _focus_reporter, *this);
|
_focus_reporter, *this);
|
||||||
|
|
||||||
session->apply_session_policy(_config.xml(), _domain_registry);
|
session->apply_session_policy(_config.xml(), _domain_registry);
|
||||||
_session_list.insert(session);
|
_session_list.insert(session);
|
||||||
@@ -152,7 +153,6 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>,
|
|||||||
View &pointer_origin,
|
View &pointer_origin,
|
||||||
View &builtin_background,
|
View &builtin_background,
|
||||||
Allocator &md_alloc,
|
Allocator &md_alloc,
|
||||||
Area const &screen_size,
|
|
||||||
Reporter &focus_reporter,
|
Reporter &focus_reporter,
|
||||||
Reporter &hover_reporter,
|
Reporter &hover_reporter,
|
||||||
Focus_updater &focus_updater)
|
Focus_updater &focus_updater)
|
||||||
@@ -163,8 +163,8 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>,
|
|||||||
_view_stack(view_stack), _user_state(user_state),
|
_view_stack(view_stack), _user_state(user_state),
|
||||||
_pointer_origin(pointer_origin),
|
_pointer_origin(pointer_origin),
|
||||||
_builtin_background(builtin_background),
|
_builtin_background(builtin_background),
|
||||||
_screen_size(screen_size), _focus_reporter(focus_reporter),
|
_focus_reporter(focus_reporter), _hover_reporter(hover_reporter),
|
||||||
_hover_reporter(hover_reporter), _focus_updater(focus_updater)
|
_focus_updater(focus_updater)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
@@ -196,7 +196,92 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>,
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Nitpicker::Main : Focus_updater, View_stack::Damage
|
/*******************************************
|
||||||
|
** Implementation of the capture service **
|
||||||
|
*******************************************/
|
||||||
|
|
||||||
|
class Nitpicker::Capture_root : public Root_component<Capture_session>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
using Sessions = Registry<Registered<Capture_session>>;
|
||||||
|
|
||||||
|
Env &_env;
|
||||||
|
Sessions _sessions { };
|
||||||
|
View_stack const &_view_stack;
|
||||||
|
Capture_session::Handler &_handler;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Capture_session *_create_session(const char *args) override
|
||||||
|
{
|
||||||
|
return new (md_alloc())
|
||||||
|
Registered<Capture_session>(_sessions, _env,
|
||||||
|
session_resources_from_args(args),
|
||||||
|
session_label_from_args(args),
|
||||||
|
session_diag_from_args(args),
|
||||||
|
_handler, _view_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _upgrade_session(Capture_session *s, const char *args) override
|
||||||
|
{
|
||||||
|
s->upgrade(ram_quota_from_args(args));
|
||||||
|
s->upgrade(cap_quota_from_args(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _destroy_session(Capture_session *session) override
|
||||||
|
{
|
||||||
|
Genode::destroy(md_alloc(), session);
|
||||||
|
|
||||||
|
/* shrink screen according to the remaining output back ends */
|
||||||
|
_handler.capture_buffer_size_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Capture_root(Env &env,
|
||||||
|
Allocator &md_alloc,
|
||||||
|
View_stack const &view_stack,
|
||||||
|
Capture_session::Handler &handler)
|
||||||
|
:
|
||||||
|
Root_component<Capture_session>(&env.ep().rpc_ep(), &md_alloc),
|
||||||
|
_env(env), _view_stack(view_stack), _handler(handler)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the size of the bounding box of all capture pixel buffers
|
||||||
|
*/
|
||||||
|
Area bounding_box() const
|
||||||
|
{
|
||||||
|
Area result { 0, 0 };
|
||||||
|
_sessions.for_each([&] (Capture_session const &session) {
|
||||||
|
result = max_area(result, session.buffer_size()); });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify all capture clients about the changed screen size
|
||||||
|
*/
|
||||||
|
void screen_size_changed()
|
||||||
|
{
|
||||||
|
_sessions.for_each([&] (Capture_session &session) {
|
||||||
|
session.screen_size_changed(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_as_damaged(Rect rect)
|
||||||
|
{
|
||||||
|
_sessions.for_each([&] (Capture_session &session) {
|
||||||
|
session.mark_as_damaged(rect); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Nitpicker::Main : Focus_updater,
|
||||||
|
View_stack::Damage,
|
||||||
|
Capture_session::Handler
|
||||||
{
|
{
|
||||||
Env &_env;
|
Env &_env;
|
||||||
|
|
||||||
@@ -222,7 +307,7 @@ struct Nitpicker::Main : Focus_updater, View_stack::Damage
|
|||||||
|
|
||||||
Attached_dataspace fb_ds;
|
Attached_dataspace fb_ds;
|
||||||
|
|
||||||
Canvas<PT> screen = { fb_ds.local_addr<PT>(), mode.area };
|
Canvas<PT> screen = { fb_ds.local_addr<PT>(), Point(0, 0), mode.area };
|
||||||
|
|
||||||
Area size = screen.size();
|
Area size = screen.size();
|
||||||
|
|
||||||
@@ -241,23 +326,7 @@ struct Nitpicker::Main : Focus_updater, View_stack::Damage
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Reconstructible<Framebuffer_screen> _fb_screen = { _env.rm(), _framebuffer };
|
Constructible<Framebuffer_screen> _fb_screen { };
|
||||||
|
|
||||||
/**
|
|
||||||
* View_stack::Damage interface
|
|
||||||
*/
|
|
||||||
void mark_as_damaged(Rect rect) override
|
|
||||||
{
|
|
||||||
if (_fb_screen.constructed()) {
|
|
||||||
_fb_screen->dirty_rect.mark_as_dirty(rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Point _initial_pointer_pos()
|
|
||||||
{
|
|
||||||
Area const scr_size = _fb_screen->screen.size();
|
|
||||||
return Point(scr_size.w()/2, scr_size.h()/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handle_fb_mode();
|
void _handle_fb_mode();
|
||||||
void _report_displays();
|
void _report_displays();
|
||||||
@@ -285,8 +354,8 @@ struct Nitpicker::Main : Focus_updater, View_stack::Damage
|
|||||||
Tff_font const _font { _binary_default_tff_start, _glyph_buffer };
|
Tff_font const _font { _binary_default_tff_start, _glyph_buffer };
|
||||||
|
|
||||||
Focus _focus { };
|
Focus _focus { };
|
||||||
View_stack _view_stack { _fb_screen->screen.size(), _focus, _font, *this };
|
View_stack _view_stack { _focus, _font, *this };
|
||||||
User_state _user_state { _focus, _global_keys, _view_stack, _initial_pointer_pos() };
|
User_state _user_state { _focus, _global_keys, _view_stack };
|
||||||
|
|
||||||
View_owner _global_view_owner { };
|
View_owner _global_view_owner { };
|
||||||
|
|
||||||
@@ -313,11 +382,61 @@ struct Nitpicker::Main : Focus_updater, View_stack::Damage
|
|||||||
|
|
||||||
Constructible<Attached_rom_dataspace> _focus_rom { };
|
Constructible<Attached_rom_dataspace> _focus_rom { };
|
||||||
|
|
||||||
Gui_root _root { _env, _config_rom, _session_list, *_domain_registry,
|
Gui_root _gui_root { _env, _config_rom, _session_list, *_domain_registry,
|
||||||
_global_keys, _view_stack, _user_state, _pointer_origin,
|
_global_keys, _view_stack, _user_state, _pointer_origin,
|
||||||
_builtin_background, _sliced_heap, _fb_screen->size,
|
_builtin_background, _sliced_heap,
|
||||||
_focus_reporter, _hover_reporter, *this };
|
_focus_reporter, _hover_reporter, *this };
|
||||||
|
|
||||||
|
Capture_root _capture_root { _env, _sliced_heap, _view_stack, *this };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View_stack::Damage interface
|
||||||
|
*/
|
||||||
|
void mark_as_damaged(Rect rect) override
|
||||||
|
{
|
||||||
|
if (_fb_screen.constructed()) {
|
||||||
|
_fb_screen->dirty_rect.mark_as_dirty(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
_capture_root.mark_as_damaged(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture_session::Handler interface
|
||||||
|
*/
|
||||||
|
void capture_buffer_size_changed() override
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Determine the new screen size, which is the bounding box of all
|
||||||
|
* present output back ends.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Area new_size { 0, 0 };
|
||||||
|
|
||||||
|
if (_fb_screen.constructed())
|
||||||
|
new_size = max_area(new_size, _fb_screen->size);
|
||||||
|
|
||||||
|
new_size = max_area(new_size, _capture_root.bounding_box());
|
||||||
|
|
||||||
|
bool const size_changed = (new_size != _view_stack.size());
|
||||||
|
|
||||||
|
if (size_changed) {
|
||||||
|
_view_stack.size(new_size);
|
||||||
|
_user_state.sanitize_pointer_position();
|
||||||
|
_update_pointer_position();
|
||||||
|
_capture_root.screen_size_changed();
|
||||||
|
|
||||||
|
/* redraw */
|
||||||
|
_view_stack.update_all_views();
|
||||||
|
|
||||||
|
/* notify clients about the change screen mode */
|
||||||
|
for (Gui_session *s = _session_list.first(); s; s = s->next())
|
||||||
|
s->notify_mode_change();
|
||||||
|
|
||||||
|
_report_displays();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Focus_updater interface
|
* Focus_updater interface
|
||||||
*
|
*
|
||||||
@@ -380,20 +499,30 @@ struct Nitpicker::Main : Focus_updater, View_stack::Damage
|
|||||||
*/
|
*/
|
||||||
bool _motion_activity = false;
|
bool _motion_activity = false;
|
||||||
|
|
||||||
|
void _update_pointer_position()
|
||||||
|
{
|
||||||
|
_view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area()));
|
||||||
|
}
|
||||||
|
|
||||||
Main(Env &env) : _env(env)
|
Main(Env &env) : _env(env)
|
||||||
{
|
{
|
||||||
_view_stack.default_background(_builtin_background);
|
_view_stack.default_background(_builtin_background);
|
||||||
_view_stack.stack(_pointer_origin);
|
_view_stack.stack(_pointer_origin);
|
||||||
_view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area()));
|
|
||||||
_view_stack.stack(_builtin_background);
|
_view_stack.stack(_builtin_background);
|
||||||
|
_update_pointer_position();
|
||||||
|
|
||||||
_config_rom.sigh(_config_handler);
|
_config_rom.sigh(_config_handler);
|
||||||
_handle_config();
|
_handle_config();
|
||||||
|
|
||||||
_framebuffer.sync_sigh(_input_handler);
|
_framebuffer.sync_sigh(_input_handler);
|
||||||
|
|
||||||
|
_handle_fb_mode();
|
||||||
_framebuffer.mode_sigh(_fb_mode_handler);
|
_framebuffer.mode_sigh(_fb_mode_handler);
|
||||||
|
|
||||||
_env.parent().announce(_env.ep().manage(_root));
|
_env.parent().announce(_env.ep().manage(_gui_root));
|
||||||
|
|
||||||
|
if (_config_rom.xml().has_sub_node("capture"))
|
||||||
|
_env.parent().announce(_env.ep().manage(_capture_root));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detect initial motion activity such that the first hover report
|
* Detect initial motion activity such that the first hover report
|
||||||
@@ -478,20 +607,20 @@ void Nitpicker::Main::_handle_input()
|
|||||||
|
|
||||||
/* update pointer position */
|
/* update pointer position */
|
||||||
if (result.motion_activity)
|
if (result.motion_activity)
|
||||||
_view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area()));
|
_update_pointer_position();
|
||||||
|
|
||||||
/* perform redraw */
|
/* perform redraw */
|
||||||
{
|
if (_fb_screen.constructed()) {
|
||||||
/* call 'Dirty_rect::flush' on a copy to preserve the state */
|
/* call 'Dirty_rect::flush' on a copy to preserve the state */
|
||||||
Dirty_rect dirty_rect = _fb_screen->dirty_rect;
|
Dirty_rect dirty_rect = _fb_screen->dirty_rect;
|
||||||
dirty_rect.flush([&] (Rect const &rect) {
|
dirty_rect.flush([&] (Rect const &rect) {
|
||||||
_view_stack.draw(_fb_screen->screen, rect); });
|
_view_stack.draw(_fb_screen->screen, rect); });
|
||||||
}
|
|
||||||
|
|
||||||
/* flush pixels to the framebuffer, reset dirty_rect */
|
/* flush pixels to the framebuffer, reset dirty_rect */
|
||||||
_fb_screen->dirty_rect.flush([&] (Rect const &rect) {
|
_fb_screen->dirty_rect.flush([&] (Rect const &rect) {
|
||||||
_framebuffer.refresh(rect.x1(), rect.y1(),
|
_framebuffer.refresh(rect.x1(), rect.y1(),
|
||||||
rect.w(), rect.h()); });
|
rect.w(), rect.h()); });
|
||||||
|
}
|
||||||
|
|
||||||
/* deliver framebuffer synchronization events */
|
/* deliver framebuffer synchronization events */
|
||||||
for (Gui_session *s = _session_list.first(); s; s = s->next())
|
for (Gui_session *s = _session_list.first(); s; s = s->next())
|
||||||
@@ -611,10 +740,12 @@ void Nitpicker::Main::_report_displays()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Reporter::Xml_generator xml(_displays_reporter, [&] () {
|
Reporter::Xml_generator xml(_displays_reporter, [&] () {
|
||||||
|
if (_fb_screen.constructed()) {
|
||||||
xml.node("display", [&] () {
|
xml.node("display", [&] () {
|
||||||
xml.attribute("width", _fb_screen->size.w());
|
xml.attribute("width", _fb_screen->size.w());
|
||||||
xml.attribute("height", _fb_screen->size.h());
|
xml.attribute("height", _fb_screen->size.h());
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,17 +755,7 @@ void Nitpicker::Main::_handle_fb_mode()
|
|||||||
/* reconstruct framebuffer screen and menu bar */
|
/* reconstruct framebuffer screen and menu bar */
|
||||||
_fb_screen.construct(_env.rm(), _framebuffer);
|
_fb_screen.construct(_env.rm(), _framebuffer);
|
||||||
|
|
||||||
/* let the view stack use the new size */
|
capture_buffer_size_changed();
|
||||||
_view_stack.size(_fb_screen->mode.area);
|
|
||||||
|
|
||||||
/* redraw */
|
|
||||||
_view_stack.update_all_views();
|
|
||||||
|
|
||||||
/* notify clients about the change screen mode */
|
|
||||||
for (Gui_session *s = _session_list.first(); s; s = s->next())
|
|
||||||
s->notify_mode_change();
|
|
||||||
|
|
||||||
_report_displays();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ namespace Nitpicker {
|
|||||||
|
|
||||||
class Gui_session;
|
class Gui_session;
|
||||||
class View_stack;
|
class View_stack;
|
||||||
|
|
||||||
|
static inline Area max_area(Area a1, Area a2)
|
||||||
|
{
|
||||||
|
return Area(max(a1.w(), a2.w()), max(a1.h(), a2.h()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _TYPES_H_ */
|
#endif /* _TYPES_H_ */
|
||||||
|
|||||||
@@ -75,10 +75,16 @@ class Nitpicker::User_state
|
|||||||
*/
|
*/
|
||||||
View_stack &_view_stack;
|
View_stack &_view_stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True once the initial screen size becomes known and used as the
|
||||||
|
* initial (centered) pointer position.
|
||||||
|
*/
|
||||||
|
bool _initial_pointer_position_defined = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Current pointer position
|
* Current pointer position
|
||||||
*/
|
*/
|
||||||
Point _pointer_pos;
|
Point _pointer_pos { };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Currently pointed-at view owner
|
* Currently pointed-at view owner
|
||||||
@@ -194,13 +200,30 @@ class Nitpicker::User_state
|
|||||||
* \param focus exported focus information, to be consumed by the
|
* \param focus exported focus information, to be consumed by the
|
||||||
* view stack to tailor its view drawing operations
|
* view stack to tailor its view drawing operations
|
||||||
*/
|
*/
|
||||||
User_state(Focus &focus, Global_keys &global_keys, View_stack &view_stack,
|
User_state(Focus &focus, Global_keys &global_keys, View_stack &view_stack)
|
||||||
Point initial_pointer_pos)
|
|
||||||
:
|
:
|
||||||
_focus(focus), _global_keys(global_keys), _view_stack(view_stack),
|
_focus(focus), _global_keys(global_keys), _view_stack(view_stack)
|
||||||
_pointer_pos(initial_pointer_pos)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever the view-stack size has changed
|
||||||
|
*/
|
||||||
|
void sanitize_pointer_position()
|
||||||
|
{
|
||||||
|
Area const screen_size = _view_stack.size();
|
||||||
|
|
||||||
|
/* center pointer initially */
|
||||||
|
if (!_initial_pointer_position_defined) {
|
||||||
|
_pointer_pos = Point(screen_size.w()/2, screen_size.h()/2);
|
||||||
|
_initial_pointer_position_defined = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure that pointer remains within screen boundaries */
|
||||||
|
if (screen_size.count() > 0)
|
||||||
|
_pointer_pos = Point(min((int)screen_size.w() - 1, _pointer_pos.x()),
|
||||||
|
min((int)screen_size.h() - 1, _pointer_pos.y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
** Interface used by the main program **
|
** Interface used by the main program **
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class Nitpicker::View_stack
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Area _size;
|
Area _size { };
|
||||||
Focus &_focus;
|
Focus &_focus;
|
||||||
Font const &_font;
|
Font const &_font;
|
||||||
List<View_stack_elem> _views { };
|
List<View_stack_elem> _views { };
|
||||||
@@ -91,9 +91,9 @@ class Nitpicker::View_stack
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
View_stack(Area size, Focus &focus, Font const &font, Damage &damage)
|
View_stack(Focus &focus, Font const &font, Damage &damage)
|
||||||
:
|
:
|
||||||
_size(size), _focus(focus), _font(font), _damage(damage)
|
_focus(focus), _font(font), _damage(damage)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user