wm/layouter: respond to external focus requests

This commit is contained in:
Norman Feske 2015-09-29 20:16:28 +02:00 committed by Christian Helmuth
parent cdb87a7c4f
commit e27ebd0368
6 changed files with 153 additions and 30 deletions

View File

@ -134,6 +134,7 @@ append config {
<config>
<rom>
<policy label="layouter -> window_list" report="wm -> window_list"/>
<policy label="layouter -> focus_request" report="wm -> focus_request"/>
<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"/>

View File

@ -16,6 +16,7 @@
#include <base/signal.h>
#include <os/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <os/session_policy.h>
#include <nitpicker_session/connection.h>
#include <input_session/client.h>
#include <input/event.h>
@ -69,6 +70,7 @@ class Floating_window_layouter::Window : public List<Window>::Element
public:
typedef String<256> Title;
typedef String<256> Label;
struct Element
{
@ -105,6 +107,8 @@ class Floating_window_layouter::Window : public List<Window>::Element
Title _title;
Label _label;
Rect _geometry;
/**
@ -151,6 +155,8 @@ class Floating_window_layouter::Window : public List<Window>::Element
void title(Title const &title) { _title = title; }
void label(Label const &label) { _label = label; }
void geometry(Rect geometry) { _geometry = geometry; }
Point position() const { return _geometry.p1(); }
@ -161,6 +167,8 @@ class Floating_window_layouter::Window : public List<Window>::Element
void is_hidden(bool is_hidden) { _is_hidden = is_hidden; }
bool label_matches(Label const &label) const { return label == _label; }
/**
* Return true if user drags a window border
*/
@ -210,8 +218,22 @@ class Floating_window_layouter::Window : public List<Window>::Element
return;
xml.node("window", [&]() {
xml.attribute("id", _id);
xml.attribute("title", _title.string());
xml.attribute("id", _id);
/* present concatenation of label and title in the window's title bar */
{
bool const has_title = Genode::strlen(_title.string()) > 0;
char buf[Label::capacity()];
Genode::snprintf(buf, sizeof(buf), "%s%s%s",
_label.string(),
has_title ? " " : "",
_title.string());
xml.attribute("title", buf);
}
xml.attribute("xpos", _geometry.x1());
xml.attribute("ypos", _geometry.y1());
xml.attribute("width", _geometry.w());
@ -319,6 +341,21 @@ struct Floating_window_layouter::Main
Attached_rom_dataspace window_list { "window_list" };
/**
* Install handler for responding to focus requests
*/
void handle_focus_request_update(unsigned);
void _apply_focus_request();
int handled_focus_request_id = 0;
Signal_dispatcher<Main> focus_request_dispatcher = {
sig_rec, *this, &Main::handle_focus_request_update };
Attached_rom_dataspace focus_request { "focus_request" };
/**
* Install handler for responding to hover changes
*/
@ -366,6 +403,8 @@ struct Floating_window_layouter::Main
{
window_list.sigh(window_list_dispatcher);
focus_request.sigh(focus_request_dispatcher);
hover.sigh(hover_dispatcher);
input.sigh(input_dispatcher);
@ -413,7 +452,8 @@ void Floating_window_layouter::Main::import_window_list(Xml_node window_list_xml
}
win->size(area_attribute(node));
win->title(string_attribute(node, "title", Window::Title("untitled")));
win->label(string_attribute(node, "label", Window::Label("")));
win->title(string_attribute(node, "title", Window::Title("")));
win->has_alpha(node.has_attribute("has_alpha")
&& node.attribute("has_alpha").has_value("yes"));
win->is_hidden(node.has_attribute("hidden")
@ -531,6 +571,74 @@ void Floating_window_layouter::Main::handle_window_list_update(unsigned)
}
void Floating_window_layouter::Main::_apply_focus_request()
{
try {
Xml_node node(focus_request.local_addr<char>());
Window::Label const label = node.attribute_value("label", Window::Label(""));
int const id = node.attribute_value("id", 0L);
/* don't apply the same focus request twice */
if (id == handled_focus_request_id)
return;
bool focus_redefined = false;
/*
* Move all windows that match the requested label to the front while
* maintaining their ordering.
*/
Window *at = nullptr;
for (Window *w = windows.first(); w; w = w->next()) {
if (!w->label_matches(label))
continue;
focus_redefined = true;
/*
* Move window to behind the previous window that we moved to
* front. If 'w' is the first window that matches the selector,
* move it to the front ('at' argument of 'insert' is 0).
*/
windows.remove(w);
windows.insert(w, at);
/*
* Bring top-most window to the front of nitpicker's global view
* stack and set the focus to the top-most window.
*/
if (at == nullptr) {
w->topped();
focused_window_id = w->id();
generate_focus_model();
}
at = w;
}
if (focus_redefined)
handled_focus_request_id = id;
}
catch (...) {
PERR("Error while handling focus request"); }
}
void Floating_window_layouter::Main::handle_focus_request_update(unsigned)
{
focus_request.update();
_apply_focus_request();
generate_window_layout_model();
}
void Floating_window_layouter::Main::handle_hover_update(unsigned)
{
hover.update();

View File

@ -54,11 +54,14 @@ struct Wm::Main
/* list of present windows, to be consumed by the layouter */
Reporter window_list_reporter = { "window_list" };
/* request to the layouter to set the focus */
Reporter focus_request_reporter = { "focus_request" };
Window_registry window_registry { *env()->heap(), window_list_reporter };
Nitpicker::Root nitpicker_root { ep, window_registry,
*env()->heap(), env()->ram_session_cap(),
pointer_reporter };
pointer_reporter, focus_request_reporter };
Nitpicker::Connection focus_nitpicker_session;
@ -125,6 +128,8 @@ struct Wm::Main
window_list_reporter.enabled(true);
Genode::Reporter::Xml_generator xml(window_list_reporter, [&] () { });
focus_request_reporter.enabled(true);
focus_rom.sigh(focus_dispatcher);
resize_request_rom.sigh(resize_request_dispatcher);
}

View File

@ -228,23 +228,8 @@ class Wm::Nitpicker::Top_level_view : public View,
*/
Rect _content_geometry;
/*
* The window title is the concatenation of the session label with
* view title.
*/
struct Window_title : Title
{
Window_title(Session_label const session_label, Title const &title)
{
bool const has_title = Genode::strlen(title.string()) > 0;
char buf[256];
Genode::snprintf(buf, sizeof(buf), "%s%s%s",
session_label.string(),
has_title ? " " : "", title.string());
*static_cast<Title *>(this) = Title(buf);
}
} _window_title;
Title _window_title;
Session_label _session_label;
typedef Nitpicker::Session::Command Command;
@ -257,7 +242,7 @@ class Wm::Nitpicker::Top_level_view : public View,
:
View(real_nitpicker, session_label, has_alpha),
_window_registry(window_registry),
_window_title(session_label, "")
_session_label(session_label)
{ }
~Top_level_view()
@ -280,6 +265,7 @@ class Wm::Nitpicker::Top_level_view : public View,
if (!_win_id.valid()) {
_win_id = _window_registry.create();
_window_registry.title(_win_id, _window_title.string());
_window_registry.label(_win_id, _session_label);
_window_registry.has_alpha(_win_id, View::has_alpha());
}
@ -294,7 +280,7 @@ class Wm::Nitpicker::Top_level_view : public View,
{
View::title(title);
_window_title = Window_title(_session_label, title);
_window_title = Title(title);
if (_win_id.valid())
_window_registry.title(_win_id, _window_title.string());
@ -773,6 +759,8 @@ class Wm::Nitpicker::Session_component : public Rpc_object<Nitpicker::Session>,
return false;
}
Session_label session_label() const { return _session_label; }
bool matches_session_label(char const *selector) const
{
/*
@ -961,6 +949,10 @@ class Wm::Nitpicker::Root : public Genode::Rpc_object<Genode::Typed_root<Session
Reporter &_pointer_reporter;
Reporter &_focus_request_reporter;
unsigned _focus_request_cnt = 0;
Last_motion _last_motion = LAST_MOTION_DECORATOR;
Window_registry &_window_registry;
@ -1043,10 +1035,11 @@ class Wm::Nitpicker::Root : public Genode::Rpc_object<Genode::Typed_root<Session
Root(Entrypoint &ep,
Window_registry &window_registry, Allocator &md_alloc,
Ram_session_capability ram,
Reporter &pointer_reporter)
Reporter &pointer_reporter, Reporter &focus_request_reporter)
:
_ep(ep), _md_alloc(md_alloc), _ram(ram),
_pointer_reporter(pointer_reporter),
_focus_request_reporter(focus_request_reporter),
_window_registry(window_registry)
{
_window_layouter_input.event_queue().enabled(true);
@ -1208,7 +1201,14 @@ class Wm::Nitpicker::Root : public Genode::Rpc_object<Genode::Typed_root<Session
break;
case Session::SESSION_CONTROL_TO_FRONT:
PWRN("SESSION_CONTROL_TO_FRONT not implemented");
/* post focus request to the layouter */
Genode::Reporter::Xml_generator
xml(_focus_request_reporter, [&] () {
xml.attribute("label", s->session_label().string());
xml.attribute("id", ++_focus_request_cnt);
});
break;
}
}

View File

@ -20,6 +20,7 @@
#include <base/allocator.h>
#include <os/surface.h>
#include <os/reporter.h>
#include <os/session_policy.h>
/* gems includes */
#include <gems/local_reporter.h>
@ -60,7 +61,8 @@ class Wm::Window_registry
{
public:
typedef Genode::String<200> Title;
typedef Genode::String<200> Title;
typedef Genode::Session_label Session_label;
enum Has_alpha { HAS_ALPHA, HAS_NO_ALPHA };
@ -72,6 +74,8 @@ class Wm::Window_registry
Title _title;
Session_label _label;
Area _size;
Has_alpha _has_alpha = HAS_NO_ALPHA;
@ -89,15 +93,17 @@ class Wm::Window_registry
/*
* Accessors for setting attributes
*/
void attr(Title const &title) { _title = title; }
void attr(Area size) { _size = size; }
void attr(Has_alpha has_alpha) { _has_alpha = has_alpha; }
void attr(Is_hidden is_hidden) { _is_hidden = is_hidden; }
void attr(Title const &title) { _title = title; }
void attr(Session_label const &label) { _label = label; }
void attr(Area size) { _size = size; }
void attr(Has_alpha has_alpha) { _has_alpha = has_alpha; }
void attr(Is_hidden is_hidden) { _is_hidden = is_hidden; }
void generate_window_list_entry_xml(Xml_generator &xml) const
{
xml.node("window", [&] () {
xml.attribute("id", _id.value);
xml.attribute("label", _label.string());
xml.attribute("title", _title.string());
xml.attribute("width", _size.w());
xml.attribute("height", _size.h());
@ -200,6 +206,8 @@ class Wm::Window_registry
void title(Id id, Window::Title title) { _set_attr(id, title); }
void label(Id id, Window::Session_label label) { _set_attr(id, label); }
void has_alpha(Id id, bool has_alpha)
{
_set_attr(id, has_alpha ? Window::HAS_ALPHA : Window::HAS_NO_ALPHA);

View File

@ -103,6 +103,7 @@ proc qt5_start_nodes { feature_arg } {
<config>
<rom>
<policy label="layouter -> window_list" report="wm -> window_list"/>
<policy label="layouter -> focus_request" report="wm -> focus_request"/>
<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"/>