mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
wm/layouter: respond to external focus requests
This commit is contained in:
parent
cdb87a7c4f
commit
e27ebd0368
@ -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"/>
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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"/>
|
||||
|
Loading…
Reference in New Issue
Block a user