mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-22 02:16:44 +00:00
wm/layouter: Raise window on click
This commit is contained in:
parent
b4ebefd616
commit
69da1fa1ed
@ -267,12 +267,14 @@ struct Floating_window_layouter::Main
|
|||||||
|
|
||||||
List<Window> windows;
|
List<Window> windows;
|
||||||
|
|
||||||
|
unsigned hovered_window_id = 0;
|
||||||
unsigned focused_window_id = 0;
|
unsigned focused_window_id = 0;
|
||||||
unsigned key_cnt = 0;
|
unsigned key_cnt = 0;
|
||||||
|
|
||||||
Window::Element hovered_element = Window::Element::UNDEFINED;
|
Window::Element hovered_element = Window::Element::UNDEFINED;
|
||||||
|
|
||||||
bool drag_state = false;
|
bool drag_state = false;
|
||||||
|
bool drag_init_done = true;
|
||||||
|
|
||||||
Window *lookup_window_by_id(unsigned id)
|
Window *lookup_window_by_id(unsigned id)
|
||||||
{
|
{
|
||||||
@ -400,10 +402,11 @@ void Floating_window_layouter::Main::generate_window_layout_model()
|
|||||||
{
|
{
|
||||||
for (Window *w = windows.first(); w; w = w->next()) {
|
for (Window *w = windows.first(); w; w = w->next()) {
|
||||||
|
|
||||||
|
bool const is_hovered = w->has_id(hovered_window_id);
|
||||||
bool const is_focused = w->has_id(focused_window_id);
|
bool const is_focused = w->has_id(focused_window_id);
|
||||||
|
|
||||||
Window::Element const highlight =
|
Window::Element const highlight =
|
||||||
is_focused ? hovered_element : Window::Element::UNDEFINED;
|
is_hovered ? hovered_element : Window::Element::UNDEFINED;
|
||||||
|
|
||||||
w->serialize(xml, is_focused, highlight);
|
w->serialize(xml, is_focused, highlight);
|
||||||
}
|
}
|
||||||
@ -476,6 +479,8 @@ void Floating_window_layouter::Main::initiate_window_drag(Window &window)
|
|||||||
{
|
{
|
||||||
window.initiate_drag_operation(hovered_element);
|
window.initiate_drag_operation(hovered_element);
|
||||||
|
|
||||||
|
drag_init_done = true;
|
||||||
|
|
||||||
/* bring focused window to front */
|
/* bring focused window to front */
|
||||||
if (&window != windows.first()) {
|
if (&window != windows.first()) {
|
||||||
windows.remove(&window);
|
windows.remove(&window);
|
||||||
@ -526,9 +531,10 @@ void Floating_window_layouter::Main::handle_hover_update(unsigned)
|
|||||||
* when the model is updated and we are still in dragged state, we can
|
* when the model is updated and we are still in dragged state, we can
|
||||||
* finally initiate the window-drag operation for the now-known window.
|
* finally initiate the window-drag operation for the now-known window.
|
||||||
*/
|
*/
|
||||||
if (id && drag_state && dragged_window_id == 0)
|
if (id && !drag_init_done && dragged_window_id == 0)
|
||||||
{
|
{
|
||||||
dragged_window_id = id;
|
dragged_window_id = id;
|
||||||
|
hovered_window_id = id;
|
||||||
focused_window_id = id;
|
focused_window_id = id;
|
||||||
|
|
||||||
Window *window = lookup_window_by_id(id);
|
Window *window = lookup_window_by_id(id);
|
||||||
@ -539,18 +545,18 @@ void Floating_window_layouter::Main::handle_hover_update(unsigned)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drag_state && (id != focused_window_id || hovered != hovered_element)) {
|
if (!drag_state && (id != hovered_window_id || hovered != hovered_element)) {
|
||||||
|
|
||||||
focused_window_id = id;
|
hovered_window_id = id;
|
||||||
hovered_element = hovered;
|
hovered_element = hovered;
|
||||||
generate_window_layout_model();
|
generate_window_layout_model();
|
||||||
generate_focus_model();
|
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
||||||
/* reset focused window if pointer does not hover over any window */
|
/* reset focused window if pointer does not hover over any window */
|
||||||
if (!drag_state) {
|
if (!drag_state) {
|
||||||
hovered_element = Window::Element::UNDEFINED;
|
hovered_element = Window::Element::UNDEFINED;
|
||||||
|
hovered_window_id = 0;
|
||||||
generate_window_layout_model();
|
generate_window_layout_model();
|
||||||
generate_focus_model();
|
generate_focus_model();
|
||||||
}
|
}
|
||||||
@ -563,7 +569,7 @@ void Floating_window_layouter::Main::handle_input(unsigned)
|
|||||||
bool need_regenerate_window_layout_model = false;
|
bool need_regenerate_window_layout_model = false;
|
||||||
bool need_regenerate_resize_request_model = false;
|
bool need_regenerate_resize_request_model = false;
|
||||||
|
|
||||||
Window *focused_window = lookup_window_by_id(focused_window_id);
|
Window *hovered_window = lookup_window_by_id(hovered_window_id);
|
||||||
|
|
||||||
while (input.is_pending()) {
|
while (input.is_pending()) {
|
||||||
|
|
||||||
@ -587,19 +593,25 @@ void Floating_window_layouter::Main::handle_input(unsigned)
|
|||||||
&& e.keycode() == Input::BTN_LEFT) {
|
&& e.keycode() == Input::BTN_LEFT) {
|
||||||
|
|
||||||
drag_state = true;
|
drag_state = true;
|
||||||
dragged_window_id = focused_window_id;
|
drag_init_done = false;
|
||||||
|
dragged_window_id = hovered_window_id;
|
||||||
pointer_clicked = pointer_curr;
|
pointer_clicked = pointer_curr;
|
||||||
pointer_last = pointer_clicked;
|
pointer_last = pointer_clicked;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the focused window is known at the time of the press
|
* If the hovered window is known at the time of the press
|
||||||
* event, we can initiate the drag operation immediately.
|
* event, we can initiate the drag operation immediately.
|
||||||
* Otherwise, we the initiation is deferred to the next
|
* Otherwise, we the initiation is deferred to the next
|
||||||
* update of the hover model.
|
* update of the hover model.
|
||||||
*/
|
*/
|
||||||
if (focused_window) {
|
if (hovered_window) {
|
||||||
initiate_window_drag(*focused_window);
|
initiate_window_drag(*hovered_window);
|
||||||
need_regenerate_window_layout_model = true;
|
need_regenerate_window_layout_model = true;
|
||||||
|
|
||||||
|
if (focused_window_id != hovered_window_id) {
|
||||||
|
focused_window_id = hovered_window_id;
|
||||||
|
generate_focus_model();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,10 +85,61 @@ struct Wm::Main
|
|||||||
|
|
||||||
Input::Session_component window_layouter_input;
|
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 };
|
||||||
|
|
||||||
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(),
|
||||||
|
click_handler };
|
||||||
|
|
||||||
Decorator_nitpicker_service decorator_nitpicker_service {
|
Decorator_nitpicker_service decorator_nitpicker_service {
|
||||||
ep, *env()->heap(), env()->ram_session_cap(), pointer_reporter,
|
ep, *env()->heap(), env()->ram_session_cap(), pointer_reporter,
|
||||||
|
@ -52,6 +52,7 @@ namespace Wm { namespace Nitpicker {
|
|||||||
|
|
||||||
using namespace ::Nitpicker;
|
using namespace ::Nitpicker;
|
||||||
|
|
||||||
|
class Click_handler;
|
||||||
class View_handle_ctx;
|
class View_handle_ctx;
|
||||||
class View;
|
class View;
|
||||||
class Top_level_view;
|
class Top_level_view;
|
||||||
@ -66,6 +67,22 @@ namespace Wm { namespace Nitpicker {
|
|||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used for propagating clicks into unfocused windows to the layouter
|
||||||
|
*
|
||||||
|
* The click handler is invoked only for those click events that are of
|
||||||
|
* interest to the layouter. In particular, a click into an unfocused window
|
||||||
|
* may trigger the layouter to raise the window and change the focus. However,
|
||||||
|
* clicks into an already focused window should be of no interest to the
|
||||||
|
* layouter. So we hide them from the layouter.
|
||||||
|
*/
|
||||||
|
struct Wm::Nitpicker::Click_handler
|
||||||
|
{
|
||||||
|
virtual void handle_click(Point pos) = 0;
|
||||||
|
virtual void handle_enter(Point pos) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Nitpicker::View { GENODE_RPC_INTERFACE(); };
|
struct Nitpicker::View { GENODE_RPC_INTERFACE(); };
|
||||||
|
|
||||||
|
|
||||||
@ -423,6 +440,7 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
|||||||
List<Child_view> _child_views;
|
List<Child_view> _child_views;
|
||||||
Input::Session_component _input_session;
|
Input::Session_component _input_session;
|
||||||
Input::Session_capability _input_session_cap;
|
Input::Session_capability _input_session_cap;
|
||||||
|
Click_handler &_click_handler;
|
||||||
Signal_context_capability _mode_sigh;
|
Signal_context_capability _mode_sigh;
|
||||||
Area _requested_size;
|
Area _requested_size;
|
||||||
|
|
||||||
@ -495,6 +513,22 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
|||||||
return Input::Event();
|
return Input::Event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _is_click_into_unfocused_view(Input::Event const ev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* XXX check if unfocused
|
||||||
|
*
|
||||||
|
* Right now, we report more butten events to the layouter
|
||||||
|
* than the layouter really needs.
|
||||||
|
*/
|
||||||
|
if (ev.type() == Input::Event::PRESS && ev.keycode() == Input::BTN_LEFT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _first_motion = true;
|
||||||
|
|
||||||
void _input_handler(unsigned)
|
void _input_handler(unsigned)
|
||||||
{
|
{
|
||||||
Point const input_origin = _input_origin();
|
Point const input_origin = _input_origin();
|
||||||
@ -508,8 +542,29 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
|||||||
|
|
||||||
/* we trust nitpicker to return a valid number of events */
|
/* we trust nitpicker to return a valid number of events */
|
||||||
|
|
||||||
for (size_t i = 0; i < num_events; i++)
|
for (size_t i = 0; i < num_events; i++) {
|
||||||
_input_session.submit(_translate_event(events[i], input_origin));
|
|
||||||
|
Input::Event const ev = events[i];
|
||||||
|
|
||||||
|
/* propagate layout-affecting events to the layouter */
|
||||||
|
if (_is_click_into_unfocused_view(ev))
|
||||||
|
_click_handler.handle_click(Point(ev.ax(), ev.ay()));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset pointer model for the decorator once the pointer
|
||||||
|
* enters the application area of a window.
|
||||||
|
*/
|
||||||
|
if (ev.type() == Input::Event::MOTION && _first_motion) {
|
||||||
|
_click_handler.handle_enter(Point(ev.ax(), ev.ay()));
|
||||||
|
_first_motion = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.type() == Input::Event::LEAVE)
|
||||||
|
_first_motion = true;
|
||||||
|
|
||||||
|
/* submit event to the client */
|
||||||
|
_input_session.submit(_translate_event(ev, input_origin));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,7 +709,8 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
|||||||
Entrypoint &ep,
|
Entrypoint &ep,
|
||||||
Allocator &session_alloc,
|
Allocator &session_alloc,
|
||||||
Session_label const &session_label,
|
Session_label const &session_label,
|
||||||
bool const direct)
|
bool const direct,
|
||||||
|
Click_handler &click_handler)
|
||||||
:
|
:
|
||||||
_session_label(session_label),
|
_session_label(session_label),
|
||||||
_ram(ram),
|
_ram(ram),
|
||||||
@ -664,6 +720,7 @@ class Wm::Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
|||||||
_top_level_view_alloc(&session_alloc),
|
_top_level_view_alloc(&session_alloc),
|
||||||
_child_view_alloc(&session_alloc),
|
_child_view_alloc(&session_alloc),
|
||||||
_input_session_cap(_ep.manage(_input_session)),
|
_input_session_cap(_ep.manage(_input_session)),
|
||||||
|
_click_handler(click_handler),
|
||||||
_view_handle_registry(session_alloc)
|
_view_handle_registry(session_alloc)
|
||||||
{
|
{
|
||||||
_nitpicker_input.sigh(_input_dispatcher);
|
_nitpicker_input.sigh(_input_dispatcher);
|
||||||
@ -879,6 +936,8 @@ class Wm::Nitpicker::Root : public Genode::Root_component<Session_component>,
|
|||||||
|
|
||||||
Window_registry &_window_registry;
|
Window_registry &_window_registry;
|
||||||
|
|
||||||
|
Click_handler &_click_handler;
|
||||||
|
|
||||||
List<Session_component> _sessions;
|
List<Session_component> _sessions;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -900,7 +959,8 @@ class Wm::Nitpicker::Root : public Genode::Root_component<Session_component>,
|
|||||||
|
|
||||||
Session_component *session = new (md_alloc())
|
Session_component *session = new (md_alloc())
|
||||||
Session_component(_ram, _window_registry,
|
Session_component(_ram, _window_registry,
|
||||||
_ep, *md_alloc(), session_label, direct);
|
_ep, *md_alloc(), session_label, direct,
|
||||||
|
_click_handler);
|
||||||
|
|
||||||
_sessions.insert(session);
|
_sessions.insert(session);
|
||||||
|
|
||||||
@ -925,10 +985,12 @@ class Wm::Nitpicker::Root : public Genode::Root_component<Session_component>,
|
|||||||
*/
|
*/
|
||||||
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,
|
||||||
|
Click_handler &click_handler)
|
||||||
:
|
:
|
||||||
Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
|
Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
|
||||||
_ep(ep), _ram(ram), _window_registry(window_registry)
|
_ep(ep), _ram(ram), _window_registry(window_registry),
|
||||||
|
_click_handler(click_handler)
|
||||||
{
|
{
|
||||||
Genode::env()->parent()->announce(_ep.manage(*this));
|
Genode::env()->parent()->announce(_ep.manage(*this));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user