wm/layouter: respond to external focus requests
This commit is contained in:
parent
cdb87a7c4f
commit
e27ebd0368
|
@ -134,6 +134,7 @@ append config {
|
||||||
<config>
|
<config>
|
||||||
<rom>
|
<rom>
|
||||||
<policy label="layouter -> window_list" report="wm -> window_list"/>
|
<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="decorator -> window_layout" report="layouter -> window_layout"/>
|
||||||
<policy label="wm -> resize_request" report="layouter -> resize_request"/>
|
<policy label="wm -> resize_request" report="layouter -> resize_request"/>
|
||||||
<policy label="decorator -> pointer" report="wm -> pointer"/>
|
<policy label="decorator -> pointer" report="wm -> pointer"/>
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <base/signal.h>
|
#include <base/signal.h>
|
||||||
#include <os/attached_rom_dataspace.h>
|
#include <os/attached_rom_dataspace.h>
|
||||||
#include <os/reporter.h>
|
#include <os/reporter.h>
|
||||||
|
#include <os/session_policy.h>
|
||||||
#include <nitpicker_session/connection.h>
|
#include <nitpicker_session/connection.h>
|
||||||
#include <input_session/client.h>
|
#include <input_session/client.h>
|
||||||
#include <input/event.h>
|
#include <input/event.h>
|
||||||
|
@ -69,6 +70,7 @@ class Floating_window_layouter::Window : public List<Window>::Element
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef String<256> Title;
|
typedef String<256> Title;
|
||||||
|
typedef String<256> Label;
|
||||||
|
|
||||||
struct Element
|
struct Element
|
||||||
{
|
{
|
||||||
|
@ -105,6 +107,8 @@ class Floating_window_layouter::Window : public List<Window>::Element
|
||||||
|
|
||||||
Title _title;
|
Title _title;
|
||||||
|
|
||||||
|
Label _label;
|
||||||
|
|
||||||
Rect _geometry;
|
Rect _geometry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,6 +155,8 @@ class Floating_window_layouter::Window : public List<Window>::Element
|
||||||
|
|
||||||
void title(Title const &title) { _title = title; }
|
void title(Title const &title) { _title = title; }
|
||||||
|
|
||||||
|
void label(Label const &label) { _label = label; }
|
||||||
|
|
||||||
void geometry(Rect geometry) { _geometry = geometry; }
|
void geometry(Rect geometry) { _geometry = geometry; }
|
||||||
|
|
||||||
Point position() const { return _geometry.p1(); }
|
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; }
|
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
|
* Return true if user drags a window border
|
||||||
*/
|
*/
|
||||||
|
@ -210,8 +218,22 @@ class Floating_window_layouter::Window : public List<Window>::Element
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xml.node("window", [&]() {
|
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("xpos", _geometry.x1());
|
||||||
xml.attribute("ypos", _geometry.y1());
|
xml.attribute("ypos", _geometry.y1());
|
||||||
xml.attribute("width", _geometry.w());
|
xml.attribute("width", _geometry.w());
|
||||||
|
@ -319,6 +341,21 @@ struct Floating_window_layouter::Main
|
||||||
Attached_rom_dataspace window_list { "window_list" };
|
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
|
* Install handler for responding to hover changes
|
||||||
*/
|
*/
|
||||||
|
@ -366,6 +403,8 @@ struct Floating_window_layouter::Main
|
||||||
{
|
{
|
||||||
window_list.sigh(window_list_dispatcher);
|
window_list.sigh(window_list_dispatcher);
|
||||||
|
|
||||||
|
focus_request.sigh(focus_request_dispatcher);
|
||||||
|
|
||||||
hover.sigh(hover_dispatcher);
|
hover.sigh(hover_dispatcher);
|
||||||
|
|
||||||
input.sigh(input_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->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")
|
win->has_alpha(node.has_attribute("has_alpha")
|
||||||
&& node.attribute("has_alpha").has_value("yes"));
|
&& node.attribute("has_alpha").has_value("yes"));
|
||||||
win->is_hidden(node.has_attribute("hidden")
|
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)
|
void Floating_window_layouter::Main::handle_hover_update(unsigned)
|
||||||
{
|
{
|
||||||
hover.update();
|
hover.update();
|
||||||
|
|
|
@ -54,11 +54,14 @@ struct Wm::Main
|
||||||
/* list of present windows, to be consumed by the layouter */
|
/* list of present windows, to be consumed by the layouter */
|
||||||
Reporter window_list_reporter = { "window_list" };
|
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 };
|
Window_registry window_registry { *env()->heap(), window_list_reporter };
|
||||||
|
|
||||||
Nitpicker::Root nitpicker_root { ep, window_registry,
|
Nitpicker::Root nitpicker_root { ep, window_registry,
|
||||||
*env()->heap(), env()->ram_session_cap(),
|
*env()->heap(), env()->ram_session_cap(),
|
||||||
pointer_reporter };
|
pointer_reporter, focus_request_reporter };
|
||||||
|
|
||||||
Nitpicker::Connection focus_nitpicker_session;
|
Nitpicker::Connection focus_nitpicker_session;
|
||||||
|
|
||||||
|
@ -125,6 +128,8 @@ struct Wm::Main
|
||||||
window_list_reporter.enabled(true);
|
window_list_reporter.enabled(true);
|
||||||
Genode::Reporter::Xml_generator xml(window_list_reporter, [&] () { });
|
Genode::Reporter::Xml_generator xml(window_list_reporter, [&] () { });
|
||||||
|
|
||||||
|
focus_request_reporter.enabled(true);
|
||||||
|
|
||||||
focus_rom.sigh(focus_dispatcher);
|
focus_rom.sigh(focus_dispatcher);
|
||||||
resize_request_rom.sigh(resize_request_dispatcher);
|
resize_request_rom.sigh(resize_request_dispatcher);
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,23 +228,8 @@ class Wm::Nitpicker::Top_level_view : public View,
|
||||||
*/
|
*/
|
||||||
Rect _content_geometry;
|
Rect _content_geometry;
|
||||||
|
|
||||||
/*
|
Title _window_title;
|
||||||
* The window title is the concatenation of the session label with
|
Session_label _session_label;
|
||||||
* 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;
|
|
||||||
|
|
||||||
typedef Nitpicker::Session::Command Command;
|
typedef Nitpicker::Session::Command Command;
|
||||||
|
|
||||||
|
@ -257,7 +242,7 @@ class Wm::Nitpicker::Top_level_view : public View,
|
||||||
:
|
:
|
||||||
View(real_nitpicker, session_label, has_alpha),
|
View(real_nitpicker, session_label, has_alpha),
|
||||||
_window_registry(window_registry),
|
_window_registry(window_registry),
|
||||||
_window_title(session_label, "")
|
_session_label(session_label)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~Top_level_view()
|
~Top_level_view()
|
||||||
|
@ -280,6 +265,7 @@ class Wm::Nitpicker::Top_level_view : public View,
|
||||||
if (!_win_id.valid()) {
|
if (!_win_id.valid()) {
|
||||||
_win_id = _window_registry.create();
|
_win_id = _window_registry.create();
|
||||||
_window_registry.title(_win_id, _window_title.string());
|
_window_registry.title(_win_id, _window_title.string());
|
||||||
|
_window_registry.label(_win_id, _session_label);
|
||||||
_window_registry.has_alpha(_win_id, View::has_alpha());
|
_window_registry.has_alpha(_win_id, View::has_alpha());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +280,7 @@ class Wm::Nitpicker::Top_level_view : public View,
|
||||||
{
|
{
|
||||||
View::title(title);
|
View::title(title);
|
||||||
|
|
||||||
_window_title = Window_title(_session_label, title);
|
_window_title = Title(title);
|
||||||
|
|
||||||
if (_win_id.valid())
|
if (_win_id.valid())
|
||||||
_window_registry.title(_win_id, _window_title.string());
|
_window_registry.title(_win_id, _window_title.string());
|
||||||
|
@ -773,6 +759,8 @@ class Wm::Nitpicker::Session_component : public Rpc_object<Nitpicker::Session>,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Session_label session_label() const { return _session_label; }
|
||||||
|
|
||||||
bool matches_session_label(char const *selector) const
|
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 &_pointer_reporter;
|
||||||
|
|
||||||
|
Reporter &_focus_request_reporter;
|
||||||
|
|
||||||
|
unsigned _focus_request_cnt = 0;
|
||||||
|
|
||||||
Last_motion _last_motion = LAST_MOTION_DECORATOR;
|
Last_motion _last_motion = LAST_MOTION_DECORATOR;
|
||||||
|
|
||||||
Window_registry &_window_registry;
|
Window_registry &_window_registry;
|
||||||
|
@ -1043,10 +1035,11 @@ class Wm::Nitpicker::Root : public Genode::Rpc_object<Genode::Typed_root<Session
|
||||||
Root(Entrypoint &ep,
|
Root(Entrypoint &ep,
|
||||||
Window_registry &window_registry, Allocator &md_alloc,
|
Window_registry &window_registry, Allocator &md_alloc,
|
||||||
Ram_session_capability ram,
|
Ram_session_capability ram,
|
||||||
Reporter &pointer_reporter)
|
Reporter &pointer_reporter, Reporter &focus_request_reporter)
|
||||||
:
|
:
|
||||||
_ep(ep), _md_alloc(md_alloc), _ram(ram),
|
_ep(ep), _md_alloc(md_alloc), _ram(ram),
|
||||||
_pointer_reporter(pointer_reporter),
|
_pointer_reporter(pointer_reporter),
|
||||||
|
_focus_request_reporter(focus_request_reporter),
|
||||||
_window_registry(window_registry)
|
_window_registry(window_registry)
|
||||||
{
|
{
|
||||||
_window_layouter_input.event_queue().enabled(true);
|
_window_layouter_input.event_queue().enabled(true);
|
||||||
|
@ -1208,7 +1201,14 @@ class Wm::Nitpicker::Root : public Genode::Rpc_object<Genode::Typed_root<Session
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Session::SESSION_CONTROL_TO_FRONT:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <base/allocator.h>
|
#include <base/allocator.h>
|
||||||
#include <os/surface.h>
|
#include <os/surface.h>
|
||||||
#include <os/reporter.h>
|
#include <os/reporter.h>
|
||||||
|
#include <os/session_policy.h>
|
||||||
|
|
||||||
/* gems includes */
|
/* gems includes */
|
||||||
#include <gems/local_reporter.h>
|
#include <gems/local_reporter.h>
|
||||||
|
@ -60,7 +61,8 @@ class Wm::Window_registry
|
||||||
{
|
{
|
||||||
public:
|
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 };
|
enum Has_alpha { HAS_ALPHA, HAS_NO_ALPHA };
|
||||||
|
|
||||||
|
@ -72,6 +74,8 @@ class Wm::Window_registry
|
||||||
|
|
||||||
Title _title;
|
Title _title;
|
||||||
|
|
||||||
|
Session_label _label;
|
||||||
|
|
||||||
Area _size;
|
Area _size;
|
||||||
|
|
||||||
Has_alpha _has_alpha = HAS_NO_ALPHA;
|
Has_alpha _has_alpha = HAS_NO_ALPHA;
|
||||||
|
@ -89,15 +93,17 @@ class Wm::Window_registry
|
||||||
/*
|
/*
|
||||||
* Accessors for setting attributes
|
* Accessors for setting attributes
|
||||||
*/
|
*/
|
||||||
void attr(Title const &title) { _title = title; }
|
void attr(Title const &title) { _title = title; }
|
||||||
void attr(Area size) { _size = size; }
|
void attr(Session_label const &label) { _label = label; }
|
||||||
void attr(Has_alpha has_alpha) { _has_alpha = has_alpha; }
|
void attr(Area size) { _size = size; }
|
||||||
void attr(Is_hidden is_hidden) { _is_hidden = is_hidden; }
|
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
|
void generate_window_list_entry_xml(Xml_generator &xml) const
|
||||||
{
|
{
|
||||||
xml.node("window", [&] () {
|
xml.node("window", [&] () {
|
||||||
xml.attribute("id", _id.value);
|
xml.attribute("id", _id.value);
|
||||||
|
xml.attribute("label", _label.string());
|
||||||
xml.attribute("title", _title.string());
|
xml.attribute("title", _title.string());
|
||||||
xml.attribute("width", _size.w());
|
xml.attribute("width", _size.w());
|
||||||
xml.attribute("height", _size.h());
|
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 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)
|
void has_alpha(Id id, bool has_alpha)
|
||||||
{
|
{
|
||||||
_set_attr(id, has_alpha ? Window::HAS_ALPHA : Window::HAS_NO_ALPHA);
|
_set_attr(id, has_alpha ? Window::HAS_ALPHA : Window::HAS_NO_ALPHA);
|
||||||
|
|
|
@ -103,6 +103,7 @@ proc qt5_start_nodes { feature_arg } {
|
||||||
<config>
|
<config>
|
||||||
<rom>
|
<rom>
|
||||||
<policy label="layouter -> window_list" report="wm -> window_list"/>
|
<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="decorator -> window_layout" report="layouter -> window_layout"/>
|
||||||
<policy label="wm -> resize_request" report="layouter -> resize_request"/>
|
<policy label="wm -> resize_request" report="layouter -> resize_request"/>
|
||||||
<policy label="decorator -> pointer" report="wm -> pointer"/>
|
<policy label="decorator -> pointer" report="wm -> pointer"/>
|
||||||
|
|
Loading…
Reference in New Issue