wm: decouple decorator and layouter from wm

This commit is contained in:
Norman Feske 2015-06-03 11:20:58 +02:00 committed by Christian Helmuth
parent a3d78d3779
commit c74a4fbbe2
10 changed files with 422 additions and 551 deletions

View File

@ -125,12 +125,53 @@ append config {
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="report_rom">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Report"/>
<service name="ROM"/>
</provides>
<config>
<rom>
<policy label="layouter -> window_list" report="wm -> window_list"/>
<policy label="decorator -> window_layout" report="layouter -> window_layout"/>
<policy label="wm -> resize_request" report="layouter -> resize_request"/>
<policy label="decorator -> pointer" report="wm -> pointer"/>
<policy label="layouter -> hover" report="decorator -> hover"/>
<policy label="wm -> focus" report="layouter -> focus"/>
</rom>
</config>
</start>
<start name="wm" priority="-1">
<resource name="RAM" quantum="32M"/>
<provides><service name="Nitpicker"/></provides>
<resource name="RAM" quantum="6M"/>
<provides>
<service name="Nitpicker"/>
</provides>
<config>
<policy label="decorator" role="decorator"/>
<policy label="layouter" role="layouter"/>
</config>
<route>
<any-service>
<child name="nitpicker"/> <parent/> <any-child/>
<child name="nitpicker"/> <child name="report_rom"/> <parent/> <any-child/>
</any-service>
</route>
</start>
<start name="layouter" priority="-1">
<binary name="floating_window_layouter"/>
<resource name="RAM" quantum="4M"/>
<route>
<any-service>
<child name="wm"/> <child name="report_rom"/> <parent/> <any-child/>
</any-service>
</route>
</start>
<start name="decorator" priority="-1">
<binary name="decorator"/>
<resource name="RAM" quantum="8M"/>
<route>
<any-service>
<child name="wm"/> <child name="report_rom"/> <parent/> <any-child/>
</any-service>
</route>
</start>

View File

@ -16,7 +16,8 @@
#include <base/signal.h>
#include <os/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <input_session/connection.h>
#include <nitpicker_session/connection.h>
#include <input_session/client.h>
#include <input/event.h>
#include <input/keycodes.h>
#include <rom_session/connection.h>
@ -307,7 +308,6 @@ struct Floating_window_layouter::Main
Attached_rom_dataspace hover { "hover" };
/**
* Install handler for responding to user input
*/
@ -316,7 +316,9 @@ struct Floating_window_layouter::Main
Signal_dispatcher<Main> input_dispatcher = {
sig_rec, *this, &Main::handle_input };
Input::Connection input;
Nitpicker::Connection nitpicker;
Input::Session_client input { nitpicker.input_session() };
Attached_dataspace input_ds { input.dataspace() };

View File

@ -1,5 +1,5 @@
/*
* \brief Local nitpicker service provided to decorator
* \brief Nitpicker service provided to decorator
* \author Norman Feske
* \date 2014-02-14
*/
@ -16,8 +16,10 @@
/* Genode includes */
#include <util/string.h>
#include <ram_session/client.h>
#include <os/server.h>
#include <os/attached_dataspace.h>
#include <os/reporter.h>
#include <nitpicker_session/connection.h>
#include <input_session/client.h>
#include <input/event.h>
@ -25,6 +27,7 @@
/* local includes */
#include <window_registry.h>
#include <last_motion.h>
namespace Wm { class Main;
using Genode::size_t;
@ -37,6 +40,7 @@ namespace Wm { class Main;
using Genode::Attached_dataspace;
using Genode::Attached_ram_dataspace;
using Genode::Signal_rpc_member;
using Genode::Reporter;
}
@ -163,7 +167,9 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>
Attached_dataspace _nitpicker_input_ds { _nitpicker_input.dataspace() };
Local_reporter &_pointer_reporter;
Reporter &_pointer_reporter;
Last_motion &_last_motion;
Input::Session_component &_window_layouter_input;
@ -186,12 +192,14 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>
*/
Decorator_nitpicker_session(Ram_session_capability ram,
Entrypoint &ep, Allocator &md_alloc,
Local_reporter &pointer_reporter,
Reporter &pointer_reporter,
Last_motion &last_motion,
Input::Session_component &window_layouter_input,
Decorator_content_callback &content_callback)
:
_ram(ram),
_pointer_reporter(pointer_reporter),
_last_motion(last_motion),
_window_layouter_input(window_layouter_input),
_content_callback(content_callback),
_ep(ep), _md_alloc(md_alloc)
@ -215,7 +223,10 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>
Input::Event const &ev = events[i];
if (ev.type() == Input::Event::MOTION) {
Local_reporter::Xml_generator xml(_pointer_reporter, [&] ()
_last_motion = LAST_MOTION_DECORATOR;
Reporter::Xml_generator xml(_pointer_reporter, [&] ()
{
xml.attribute("xpos", ev.ax());
xml.attribute("ypos", ev.ay());
@ -224,10 +235,19 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>
if (ev.type() == Input::Event::LEAVE) {
Local_reporter::Xml_generator xml(_pointer_reporter, [&] ()
{
/* report empty pointer model */
});
/*
* Invalidate pointer as reported to the decorator if the
* pointer moved from a window decoration to a position
* with no window known to the window manager. If the last
* motion referred to one of the regular client session,
* this is not needed because the respective session will
* update the pointer model with the entered position
* already.
*/
if (_last_motion == LAST_MOTION_DECORATOR) {
Reporter::Xml_generator xml(_pointer_reporter, [&] ()
{ });
}
}
_window_layouter_input.submit(ev);
@ -418,56 +438,4 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>
void focus(Genode::Capability<Nitpicker::Session>) { }
};
struct Wm::Decorator_nitpicker_service : Genode::Service, Genode::Noncopyable
{
private:
Entrypoint &_ep;
Allocator &_md_alloc;
Ram_session_capability _ram;
Local_reporter &_pointer_reporter;
Input::Session_component &_window_layouter_input;
Decorator_content_callback &_content_callback;
public:
Decorator_nitpicker_service(Entrypoint &ep, Allocator &md_alloc,
Ram_session_capability ram,
Local_reporter &pointer_reporter,
Input::Session_component &window_layouter_input,
Decorator_content_callback &content_callback)
:
Service("Nitpicker"),
_ep(ep), _md_alloc(md_alloc),
_ram(ram), _pointer_reporter(pointer_reporter),
_window_layouter_input(window_layouter_input),
_content_callback(content_callback)
{ }
Genode::Session_capability
session(const char *, Genode::Affinity const &) override
{
Decorator_nitpicker_session *s = new (_md_alloc)
Decorator_nitpicker_session(_ram, _ep, _md_alloc,
_pointer_reporter,
_window_layouter_input,
_content_callback);
return _ep.manage(*s);
}
void upgrade(Genode::Session_capability session, const char *args) override
{
typedef typename Object_pool<Decorator_nitpicker_session>::Guard Object_guard;
Object_guard np_session(_ep.rpc_ep().lookup_and_lock(session));
if (np_session)
np_session->upgrade(args);
}
void close(Genode::Session_capability) { }
};
#endif /* _DECORATOR_NITPICKER_H_ */

View File

@ -1,128 +0,0 @@
/*
* \brief Slave for drawing window decorations
* \author Norman Feske
* \date 2014-02-14
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _DECORATOR_SLAVE_H_
#define _DECORATOR_SLAVE_H_
namespace Wm {
class Decorator_slave;
using Genode::Rom_session_capability;
using Genode::Capability;
}
class Wm::Decorator_slave
{
private:
Genode::Ram_session &_ram;
class Policy : public Genode::Slave_policy
{
private:
Genode::Service &_nitpicker_service;
Single_session_service _window_layout_rom_service;
Single_session_service _pointer_rom_service;
Single_session_service _hover_report_service;
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = {
"CAP", "LOG", "SIGNAL", "RM", 0 };
return permitted_services;
};
public:
Policy(Genode::Rpc_entrypoint &entrypoint,
Genode::Ram_session &ram,
Genode::Service &nitpicker_service,
Rom_session_capability window_layout_rom,
Rom_session_capability pointer_rom,
Genode::Capability<Report::Session> hover_report)
:
Slave_policy("decorator", entrypoint, &ram),
_nitpicker_service(nitpicker_service),
_window_layout_rom_service("ROM", window_layout_rom),
_pointer_rom_service("ROM", pointer_rom),
_hover_report_service("Report", hover_report)
{ }
Genode::Service *resolve_session_request(const char *service_name,
const char *args) override
{
using Genode::strcmp;
if (strcmp(service_name, "Nitpicker") == 0)
return &_nitpicker_service;
char label[128];
Arg_string::find_arg(args, "label").string(label, sizeof(label), "");
if (strcmp(service_name, "ROM") == 0) {
if (strcmp(label, "decorator -> window_layout") == 0)
return &_window_layout_rom_service;
if (strcmp(label, "decorator -> pointer") == 0)
return &_pointer_rom_service;
}
if (strcmp(service_name, "Report") == 0) {
if (strcmp(label, "decorator -> hover") == 0)
return &_hover_report_service;
}
return Genode::Slave_policy::resolve_session_request(service_name, args);
}
};
Genode::size_t const _ep_stack_size = 4*1024*sizeof(Genode::addr_t);
Genode::Rpc_entrypoint _ep;
Policy _policy;
Genode::size_t const _quota = 4*1024*1024;
Genode::Slave _slave;
public:
/**
* Constructor
*
* \param ram RAM session for paying nitpicker sessions created
* by the decorator
*/
Decorator_slave(Genode::Cap_session &cap,
Genode::Service &nitpicker_service,
Genode::Ram_session &ram,
Rom_session_capability window_layout_rom,
Rom_session_capability pointer_rom,
Genode::Capability<Report::Session> hover_report)
:
_ram(ram),
_ep(&cap, _ep_stack_size, "decorator"),
_policy(_ep, ram, nitpicker_service, window_layout_rom,
pointer_rom, hover_report),
_slave(_ep, _policy, _quota)
{ }
};
#endif /* _DECORATOR_SLAVE_H_ */

View File

@ -0,0 +1,22 @@
/*
* \brief Type of client that receive the last motion event
* \author Norman Feske
* \date 2014-06-10
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _LAST_MOTION_H_
#define _LAST_MOTION_H_
namespace Wm {
enum Last_motion { LAST_MOTION_NITPICKER, LAST_MOTION_DECORATOR };
}
#endif /* _LAST_MOTION_H_ */

View File

@ -0,0 +1,93 @@
/*
* \brief Nitpicker service provided to layouter
* \author Norman Feske
* \date 2015-06-06
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _LAYOUTER_NITPICKER_H_
#define _LAYOUTER_NITPICKER_H_
/* Genode includes */
#include <os/server.h>
#include <input/component.h>
namespace Wm { using Server::Entrypoint; }
namespace Wm {
struct Layouter_nitpicker_session;
struct Layouter_nitpicker_service;
}
struct Wm::Layouter_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>
{
typedef Nitpicker::View_capability View_capability;
typedef Nitpicker::Session::View_handle View_handle;
Input::Session_capability input_session_cap;
Attached_ram_dataspace command_ds;
Layouter_nitpicker_session(Genode::Ram_session &ram,
Input::Session_capability input_session_cap)
:
input_session_cap(input_session_cap),
command_ds(&ram, 4096)
{ }
/*********************************
** Nitpicker session interface **
*********************************/
Framebuffer::Session_capability framebuffer_session() override
{
return Framebuffer::Session_capability();
}
Input::Session_capability input_session() override
{
return input_session_cap;
}
View_handle create_view(View_handle) override { return View_handle(); }
void destroy_view(View_handle) override { }
View_handle view_handle(View_capability, View_handle) override
{
return View_handle();
}
View_capability view_capability(View_handle) override
{
return View_capability();
}
void release_view_handle(View_handle) override { }
Genode::Dataspace_capability command_dataspace() override
{
return command_ds.cap();
}
void execute() override { }
Framebuffer::Mode mode() override { return Framebuffer::Mode(); }
void mode_sigh(Genode::Signal_context_capability) override { }
void buffer(Framebuffer::Mode, bool) override { }
void focus(Genode::Capability<Nitpicker::Session>) { }
};
#endif /* _LAYOUTER_NITPICKER_H_ */

View File

@ -16,19 +16,11 @@
#include <nitpicker_session/client.h>
#include <framebuffer_session/client.h>
#include <cap_session/connection.h>
#include <os/attached_dataspace.h>
#include <os/attached_rom_dataspace.h>
#include <util/volatile_object.h>
#include <util/xml_node.h>
/* gems includes */
#include <gems/single_session_service.h>
#include <gems/report_rom_slave.h>
#include <gems/local_reporter.h>
/* local includes */
#include <decorator_nitpicker.h>
#include <decorator_slave.h>
#include <window_layouter_slave.h>
#include <nitpicker.h>
namespace Wm {
@ -40,6 +32,7 @@ namespace Wm {
using Genode::Rom_session_client;
using Genode::Rom_connection;
using Genode::Xml_node;
using Genode::Attached_rom_dataspace;
}
@ -49,127 +42,34 @@ struct Wm::Main
Genode::Cap_connection cap;
char const *report_rom_config =
"<config> <rom>"
" <policy label=\"window_list\" report=\"window_list\"/>"
" <policy label=\"window_layout\" report=\"window_layout\"/>"
" <policy label=\"resize_request\" report=\"resize_request\"/>"
" <policy label=\"pointer\" report=\"pointer\"/>"
" <policy label=\"hover\" report=\"hover\"/>"
" <policy label=\"focus\" report=\"focus\"/>"
"</rom> </config>";
/* currently focused window, reported by the layouter */
Attached_rom_dataspace focus_rom { "focus" };
Report_rom_slave report_rom_slave = { cap, *env()->ram_session(), report_rom_config };
/* resize requests, issued by the layouter */
Attached_rom_dataspace resize_request_rom { "resize_request" };
Rom_session_capability window_list_rom = report_rom_slave.rom_session("window_list");
Rom_session_capability window_layout_rom = report_rom_slave.rom_session("window_layout");
Rom_session_capability pointer_rom = report_rom_slave.rom_session("pointer");
Rom_session_capability hover_rom = report_rom_slave.rom_session("hover");
/* pointer position to be consumed by the layouter */
Reporter pointer_reporter = { "pointer" };
Rom_session_client focus_rom { report_rom_slave.rom_session("focus") };
Rom_session_client resize_request_rom { report_rom_slave.rom_session("resize_request") };
/* pointer position reported by nitpicker */
Capability<Report::Session> pointer_report = report_rom_slave.report_session("pointer");
Local_reporter pointer_reporter = { "pointer", pointer_report };
/* hovered element reported by decorator */
Capability<Report::Session> hover_report = report_rom_slave.report_session("hover");
Capability<Report::Session> window_list_report = report_rom_slave.report_session("window_list");
Local_reporter window_list_reporter = { "window_list", window_list_report };
Capability<Report::Session> window_layout_report = report_rom_slave.report_session("window_layout");
Capability<Report::Session> resize_request_report = report_rom_slave.report_session("resize_request");
Capability<Report::Session> focus_report = report_rom_slave.report_session("focus");
Input::Session_component window_layouter_input;
/* handler that forwards clicks into unfocused windows to the layouter */
struct Click_handler : Nitpicker::Click_handler
{
Input::Session_component &window_layouter_input;
Local_reporter &pointer_reporter;
void _submit_button_event(Input::Event::Type type, Nitpicker::Point pos)
{
window_layouter_input.submit(Input::Event(type, Input::BTN_LEFT,
pos.x(), pos.y(), 0, 0));
}
void handle_enter(Nitpicker::Point pos) override
{
Local_reporter::Xml_generator xml(pointer_reporter, [&] ()
{
xml.attribute("xpos", pos.x());
xml.attribute("ypos", pos.y());
});
}
void handle_click(Nitpicker::Point pos) override
{
/*
* Propagate clicked-at position to decorator such that it can
* update its hover model.
*/
Local_reporter::Xml_generator xml(pointer_reporter, [&] ()
{
xml.attribute("xpos", pos.x());
xml.attribute("ypos", pos.y());
});
/*
* Supply artificial mouse click to the decorator's input session
* (which is routed to the layouter).
*/
_submit_button_event(Input::Event::PRESS, pos);
_submit_button_event(Input::Event::RELEASE, pos);
}
Click_handler(Input::Session_component &window_layouter_input,
Local_reporter &pointer_reporter)
:
window_layouter_input(window_layouter_input),
pointer_reporter(pointer_reporter)
{ }
} click_handler { window_layouter_input, pointer_reporter };
/* list of present windows, to be consumed by the layouter */
Reporter window_list_reporter = { "window_list" };
Window_registry window_registry { *env()->heap(), window_list_reporter };
Nitpicker::Root nitpicker_root { ep, window_registry,
*env()->heap(), env()->ram_session_cap(),
click_handler };
Decorator_nitpicker_service decorator_nitpicker_service {
ep, *env()->heap(), env()->ram_session_cap(), pointer_reporter,
window_layouter_input, nitpicker_root };
Window_layouter_slave window_layouter_slave = {
cap, *env()->ram_session(), window_list_rom, hover_rom,
ep.manage(window_layouter_input), window_layout_report,
resize_request_report, focus_report };
Decorator_slave decorator_slave = {
cap, decorator_nitpicker_service, *env()->ram_session(),
window_layout_rom, pointer_rom, hover_report };
Genode::Lazy_volatile_object<Attached_dataspace> focus_ds;
pointer_reporter };
Nitpicker::Connection focus_nitpicker_session;
void handle_focus_update(unsigned)
{
try {
if (!focus_ds.is_constructed() || focus_rom.update() == false) {
if (focus_ds.is_constructed())
focus_ds->invalidate();
focus_ds.construct(focus_rom.dataspace());
}
focus_rom.update();
unsigned long win_id = 0;
Xml_node(focus_ds->local_addr<char>()).sub_node("window")
Xml_node(focus_rom.local_addr<char>()).sub_node("window")
.attribute("id").value(&win_id);
if (win_id) {
@ -186,21 +86,15 @@ struct Wm::Main
Genode::Signal_rpc_member<Main> focus_dispatcher = { ep, *this, &Main::handle_focus_update };
Genode::Lazy_volatile_object<Attached_dataspace> resize_request_ds;
void handle_resize_request_update(unsigned)
{
try {
if (!resize_request_ds.is_constructed() || resize_request_rom.update() == false) {
if (resize_request_ds.is_constructed())
resize_request_ds->invalidate();
resize_request_ds.construct(resize_request_rom.dataspace());
}
resize_request_rom.update();
char const * const node_type = "window";
Xml_node window =
Xml_node(resize_request_ds->local_addr<char>()).sub_node(node_type);
Xml_node(resize_request_rom.local_addr<char>()).sub_node(node_type);
for (;;) {
unsigned long win_id = 0, width = 0, height = 0;
@ -225,10 +119,11 @@ struct Wm::Main
Main(Server::Entrypoint &ep) : ep(ep)
{
window_layouter_input.event_queue().enabled(true);
pointer_reporter.enabled(true);
/* initially report an empty window list */
Local_reporter::Xml_generator xml(window_list_reporter, [&] () { });
window_list_reporter.enabled(true);
Genode::Reporter::Xml_generator xml(window_list_reporter, [&] () { });
focus_rom.sigh(focus_dispatcher);
resize_request_rom.sigh(resize_request_dispatcher);

View File

@ -21,6 +21,8 @@
#include <os/surface.h>
#include <os/attached_ram_dataspace.h>
#include <os/session_policy.h>
#include <os/reporter.h>
#include <os/session_policy.h>
#include <cap_session/connection.h>
#include <root/component.h>
#include <nitpicker_session/connection.h>
@ -29,6 +31,8 @@
/* local includes */
#include <window_registry.h>
#include <decorator_nitpicker.h>
#include <layouter_nitpicker.h>
namespace Wm {
@ -46,6 +50,8 @@ namespace Wm {
using Genode::Attached_ram_dataspace;
using Genode::Signal_context_capability;
using Genode::Signal_transmitter;
using Genode::Reporter;
using Genode::Capability;
}
namespace Wm { namespace Nitpicker {
@ -57,7 +63,6 @@ namespace Wm { namespace Nitpicker {
class View;
class Top_level_view;
class Child_view;
class Direct_view;
class Session_component;
class Root;
@ -391,37 +396,8 @@ class Wm::Nitpicker::Child_view : public View,
};
class Wm::Nitpicker::Direct_view : public View
{
public:
Direct_view(Nitpicker::Session_client &real_nitpicker,
Session_label const &session_label,
bool const direct)
:
View(real_nitpicker, session_label)
{
if (!direct)
return;
typedef Nitpicker::Session::Command Command;
_real_handle = _real_nitpicker.create_view();
_real_nitpicker.enqueue<Command::Geometry>(_real_handle,
Rect(Point(0, 0), Area(0, 0)));
_real_nitpicker.enqueue<Command::To_back>(_real_handle);
_real_nitpicker.execute();
}
bool belongs_to_win_id(Window_registry::Id id) const override { return false; }
void _propagate_view_geometry() override { }
Point input_anchor_position() const override { return Point(); }
};
class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
public List<Session_component>::Element
class Wm::Nitpicker::Session_component : public Rpc_object<Nitpicker::Session>,
public List<Session_component>::Element
{
private:
@ -431,7 +407,6 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
Ram_session_client _ram;
Nitpicker::Connection _session { _session_label.string() };
Direct_view _direct_view;
Window_registry &_window_registry;
Entrypoint &_ep;
Tslab<Top_level_view, 4000> _top_level_view_alloc;
@ -570,20 +545,6 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
View &_create_view_object(View_handle parent_handle)
{
/*
* If the session operates in direct mode, we subordinate all
* top-level views of the session to the 'direct_parent' pseudo
* view, which is located at the screen origin.
*/
if (!parent_handle.valid() && _direct_view.real_handle().valid()) {
Child_view *view = new (_child_view_alloc)
Child_view(_session, _session_label, _direct_view.weak_ptr());
_child_views.insert(view);
return *view;
}
/*
* Create child view
*/
@ -709,12 +670,10 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
Entrypoint &ep,
Allocator &session_alloc,
Session_label const &session_label,
bool const direct,
Click_handler &click_handler)
:
_session_label(session_label),
_ram(ram),
_direct_view(_session, session_label, direct),
_window_registry(window_registry),
_ep(ep),
_top_level_view_alloc(&session_alloc),
@ -923,60 +882,94 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
};
class Wm::Nitpicker::Root : public Genode::Root_component<Session_component>,
class Wm::Nitpicker::Root : public Genode::Rpc_object<Genode::Typed_root<Session> >,
public Decorator_content_callback
{
private:
Entrypoint &_ep;
Allocator &_md_alloc;
Ram_session_capability _ram;
enum { STACK_SIZE = 1024*sizeof(long) };
Reporter &_pointer_reporter;
Last_motion _last_motion = LAST_MOTION_DECORATOR;
Window_registry &_window_registry;
Click_handler &_click_handler;
Input::Session_component _window_layouter_input;
Input::Session_capability _window_layouter_input_cap {
_ep.manage(_window_layouter_input) };
/* handler that forwards clicks into unfocused windows to the layouter */
struct Click_handler : Nitpicker::Click_handler
{
Input::Session_component &window_layouter_input;
Reporter &pointer_reporter;
Last_motion &last_motion;
void _submit_button_event(Input::Event::Type type, Nitpicker::Point pos)
{
window_layouter_input.submit(Input::Event(type, Input::BTN_LEFT,
pos.x(), pos.y(), 0, 0));
}
void handle_enter(Nitpicker::Point pos) override
{
last_motion = LAST_MOTION_NITPICKER;
Reporter::Xml_generator xml(pointer_reporter, [&] ()
{
xml.attribute("xpos", pos.x());
xml.attribute("ypos", pos.y());
});
}
void handle_click(Nitpicker::Point pos) override
{
/*
* Propagate clicked-at position to decorator such that it can
* update its hover model.
*/
Reporter::Xml_generator xml(pointer_reporter, [&] ()
{
xml.attribute("xpos", pos.x());
xml.attribute("ypos", pos.y());
});
/*
* Supply artificial mouse click to the decorator's input session
* (which is routed to the layouter).
*/
_submit_button_event(Input::Event::PRESS, pos);
_submit_button_event(Input::Event::RELEASE, pos);
}
Click_handler(Input::Session_component &window_layouter_input,
Reporter &pointer_reporter,
Last_motion &last_motion)
:
window_layouter_input(window_layouter_input),
pointer_reporter(pointer_reporter),
last_motion(last_motion)
{ }
} _click_handler { _window_layouter_input, _pointer_reporter,
_last_motion };
/**
* List of regular sessions
*/
List<Session_component> _sessions;
protected:
Layouter_nitpicker_session *_layouter_session = nullptr;
Session_component *_create_session(const char *args) override
{
bool direct = false;
Session_label session_label(args);
/*
* Determine session policy
*/
try {
Genode::Xml_node policy = Genode::Session_policy(session_label);
direct = policy.attribute("direct").has_value("yes");
}
catch (...) { }
Session_component *session = new (md_alloc())
Session_component(_ram, _window_registry,
_ep, *md_alloc(), session_label, direct,
_click_handler);
_sessions.insert(session);
return session;
}
void _destroy_session(Session_component *session) override
{
_sessions.remove(session);
Root_component<Session_component>::_destroy_session(session);
}
void _upgrade_session(Session_component *s, const char *args) override
{
s->upgrade(args);
}
Decorator_nitpicker_session *_decorator_session = nullptr;
public:
@ -986,16 +979,136 @@ class Wm::Nitpicker::Root : public Genode::Root_component<Session_component>,
Root(Entrypoint &ep,
Window_registry &window_registry, Allocator &md_alloc,
Ram_session_capability ram,
Click_handler &click_handler)
Reporter &pointer_reporter)
:
Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
_ep(ep), _ram(ram), _window_registry(window_registry),
_click_handler(click_handler)
_ep(ep), _md_alloc(md_alloc), _ram(ram),
_pointer_reporter(pointer_reporter),
_window_registry(window_registry)
{
_window_layouter_input.event_queue().enabled(true);
Genode::env()->parent()->announce(_ep.manage(*this));
}
/********************
** Root interface **
********************/
Genode::Session_capability session(Session_args const &args,
Affinity const &affinity) override
{
Genode::Session_label session_label(args.string());
enum Role { ROLE_DECORATOR, ROLE_LAYOUTER, ROLE_REGULAR };
Role role = ROLE_REGULAR;
/*
* Determine session policy
*/
try {
Genode::Xml_node policy = Genode::Session_policy(session_label);
char const *role_attr = "role";
if (policy.has_attribute(role_attr)) {
if (policy.attribute(role_attr).has_value("layouter"))
role = ROLE_LAYOUTER;
if (policy.attribute(role_attr).has_value("decorator"))
role = ROLE_DECORATOR;
}
}
catch (...) { }
switch (role) {
case ROLE_REGULAR:
{
auto session = new (_md_alloc)
Session_component(_ram, _window_registry,
_ep, _md_alloc, session_label,
_click_handler);
_sessions.insert(session);
return _ep.manage(*session);
}
case ROLE_DECORATOR:
{
_decorator_session = new (_md_alloc)
Decorator_nitpicker_session(_ram, _ep, _md_alloc,
_pointer_reporter,
_last_motion,
_window_layouter_input,
*this);
return _ep.manage(*_decorator_session);
}
case ROLE_LAYOUTER:
{
_layouter_session = new (_md_alloc)
Layouter_nitpicker_session(*Genode::env()->ram_session(),
_window_layouter_input_cap);
return _ep.manage(*_layouter_session);
}
}
return Session_capability();
}
void upgrade(Genode::Session_capability session_cap, Upgrade_args const &args) override
{
if (!args.is_valid_string()) throw Root::Invalid_args();
Rpc_object_base *session = _ep.rpc_ep().lookup_and_lock(session_cap);
if (!session) {
PDBG("session lookup failed");
return;
}
Session_component *regular_session =
dynamic_cast<Session_component *>(session);
if (regular_session)
regular_session->upgrade(args.string());
Decorator_nitpicker_session *decorator_session =
dynamic_cast<Decorator_nitpicker_session *>(session);
if (decorator_session)
decorator_session->upgrade(args.string());
session->release();
}
void close(Genode::Session_capability session_cap) override
{
Rpc_object_base *session = _ep.rpc_ep().lookup_and_lock(session_cap);
Session_component *regular_session = dynamic_cast<Session_component *>(session);
if (regular_session) {
_sessions.remove(regular_session);
_ep.dissolve(*regular_session);
Genode::destroy(_md_alloc, regular_session);
return;
}
if (session == _decorator_session) {
_ep.dissolve(*_decorator_session);
Genode::destroy(_md_alloc, _decorator_session);
_decorator_session = nullptr;
}
if (session == _layouter_session) {
_ep.dissolve(*_layouter_session);
Genode::destroy(_md_alloc, _layouter_session);
_layouter_session = nullptr;
}
}
/******************************************
** Decorator_content_callback interface **
******************************************/
@ -1024,8 +1137,9 @@ class Wm::Nitpicker::Root : public Genode::Root_component<Session_component>,
/*
* Try to create physical views for its child views.
*/
for (Session_component *s = _sessions.first(); s; s = s->next())
for (Session_component *s = _sessions.first(); s; s = s->next()) {
s->try_to_init_real_child_views();
}
/*
* Apply the stacking order to the child views that belong to the

View File

@ -1,137 +0,0 @@
/*
* \brief Slave for managing the window layout
* \author Norman Feske
* \date 2014-02-14
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _WINDOW_LAYOUTER_SLAVE_H_
#define _WINDOW_LAYOUTER_SLAVE_H_
namespace Wm {
class Window_layouter_slave;
using Genode::Rom_session_capability;
using Genode::Capability;
}
class Wm::Window_layouter_slave
{
private:
Genode::Ram_session &_ram;
class Policy : public Genode::Slave_policy
{
private:
Single_session_service _window_list_rom_service;
Single_session_service _hover_rom_service;
Single_session_service _input_service;
Single_session_service _window_layout_report_service;
Single_session_service _resize_request_report_service;
Single_session_service _focus_report_service;
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = {
"CAP", "LOG", "SIGNAL", "RM", "Timer", 0 };
return permitted_services;
};
public:
Policy(Genode::Rpc_entrypoint &entrypoint,
Genode::Ram_session &ram,
Rom_session_capability window_list_rom,
Rom_session_capability hover_rom,
Input::Session_capability input,
Capability<Report::Session> window_layout_report,
Capability<Report::Session> resize_request_report,
Capability<Report::Session> focus_report)
:
Slave_policy("floating_window_layouter", entrypoint, &ram),
_window_list_rom_service("ROM", window_list_rom),
_hover_rom_service("ROM", hover_rom),
_input_service("Input", input),
_window_layout_report_service("Report", window_layout_report),
_resize_request_report_service("Report", resize_request_report),
_focus_report_service("Report", focus_report)
{ }
Genode::Service *resolve_session_request(const char *service_name,
const char *args) override
{
using Genode::strcmp;
char label[128];
Arg_string::find_arg(args, "label").string(label, sizeof(label), "");
if (strcmp(service_name, "ROM") == 0) {
if (strcmp(label, "floating_window_layouter -> window_list") == 0)
return &_window_list_rom_service;
if (strcmp(label, "floating_window_layouter -> hover") == 0)
return &_hover_rom_service;
}
if (strcmp(service_name, "Report") == 0) {
if (strcmp(label, "floating_window_layouter -> window_layout") == 0)
return &_window_layout_report_service;
if (strcmp(label, "floating_window_layouter -> resize_request") == 0)
return &_resize_request_report_service;
if (strcmp(label, "floating_window_layouter -> focus") == 0)
return &_focus_report_service;
}
if (strcmp(service_name, "Input") == 0)
return &_input_service;
return Genode::Slave_policy::resolve_session_request(service_name, args);
}
};
Genode::size_t const _ep_stack_size = 4*1024*sizeof(Genode::addr_t);
Genode::Rpc_entrypoint _ep;
Policy _policy;
Genode::size_t const _quota = 1*1024*1024;
Genode::Slave _slave;
public:
/**
* Constructor
*/
Window_layouter_slave(Genode::Cap_session &cap,
Genode::Ram_session &ram,
Rom_session_capability window_list_rom,
Rom_session_capability hover_rom,
Input::Session_capability input,
Capability<Report::Session> window_layout_report,
Capability<Report::Session> resize_request_report,
Capability<Report::Session> focus_report)
:
_ram(ram),
_ep(&cap, _ep_stack_size, "floating_window_layouter"),
_policy(_ep, ram, window_list_rom, hover_rom, input,
window_layout_report, resize_request_report, focus_report),
_slave(_ep, _policy, _quota)
{ }
};
#endif /* _WINDOW_LAYOUTER_SLAVE_H_ */

View File

@ -17,9 +17,9 @@
/* Genode includes */
#include <util/bit_allocator.h>
#include <util/list.h>
#include <util/xml_generator.h>
#include <base/allocator.h>
#include <os/surface.h>
#include <os/reporter.h>
/* gems includes */
#include <gems/local_reporter.h>
@ -31,6 +31,7 @@ namespace Wm {
using Genode::Allocator;
using Genode::List;
using Genode::Xml_generator;
using Genode::Reporter;
typedef Genode::Surface_base::Area Area;
typedef Genode::Surface_base::Point Point;
@ -96,8 +97,8 @@ class Wm::Window_registry
private:
Allocator &_alloc;
Local_reporter &_window_list_reporter;
Allocator &_alloc;
Reporter &_window_list_reporter;
enum { MAX_WINDOWS = 1024 };
@ -116,7 +117,7 @@ class Wm::Window_registry
void _report_updated_window_list_model() const
{
Local_reporter::Xml_generator xml(_window_list_reporter, [&] ()
Reporter::Xml_generator xml(_window_list_reporter, [&] ()
{
for (Window const *w = _windows.first(); w; w = w->next())
w->generate_window_list_entry_xml(xml);
@ -140,7 +141,7 @@ class Wm::Window_registry
public:
Window_registry(Allocator &alloc, Local_reporter &window_list_reporter)
Window_registry(Allocator &alloc, Reporter &window_list_reporter)
:
_alloc(alloc), _window_list_reporter(window_list_reporter)
{