wm: improve focus handling

This patch addresses the corner case where hovering changes while a
button is held, e.g., when accidentially moving the pointer out of a
application window's area during a drag-and-drop operation. The patch
makes the window manager aware of the drag/idle state. Only when idle,
the pointer position is propagated to the decorator now.
This commit is contained in:
Norman Feske 2018-04-27 15:16:42 +02:00 committed by Christian Helmuth
parent b748c4186d
commit 0b370671af
2 changed files with 31 additions and 8 deletions

View File

@ -178,6 +178,8 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>,
Decorator_content_callback &_content_callback;
unsigned _key_cnt = 0;
/* XXX don't allocate content-registry entries from heap */
Decorator_content_registry _content_registry { _heap };
@ -225,15 +227,21 @@ struct Wm::Decorator_nitpicker_session : Genode::Rpc_object<Nitpicker::Session>,
while (_nitpicker_session.input()->pending())
_nitpicker_session.input()->for_each_event([&] (Input::Event const &ev) {
if (ev.press()) _key_cnt++;
if (ev.release()) _key_cnt--;
ev.handle_absolute_motion([&] (int x, int y) {
_last_motion = LAST_MOTION_DECORATOR;
Reporter::Xml_generator xml(_pointer_reporter, [&] ()
{
xml.attribute("xpos", x);
xml.attribute("ypos", y);
});
/* update pointer model, but only when hovering */
if (_key_cnt == 0) {
Reporter::Xml_generator xml(_pointer_reporter, [&] ()
{
xml.attribute("xpos", x);
xml.attribute("ypos", y);
});
}
});
if (ev.hover_leave()) {

View File

@ -453,6 +453,7 @@ class Wm::Nitpicker::Session_component : public Rpc_object<Nitpicker::Session>,
bool _has_alpha = false;
Point const _initial_pointer_pos { -1, -1 };
Point _pointer_pos = _initial_pointer_pos;
unsigned _key_cnt = 0;
/*
* Command buffer
@ -537,23 +538,37 @@ class Wm::Nitpicker::Session_component : public Rpc_object<Nitpicker::Session>,
Input::Event const ev = events[i];
/* keep track of pointer position */
if (ev.press()) _key_cnt++;
if (ev.release()) _key_cnt--;
/* keep track of pointer position when hovering */
ev.handle_absolute_motion([&] (int x, int y) {
_pointer_pos = Point(x, y); });
/* propagate layout-affecting events to the layouter */
if (_click_into_unfocused_view(ev))
if (_click_into_unfocused_view(ev) && _key_cnt == 1)
_click_handler.handle_click(_pointer_pos);
/*
* Reset pointer model for the decorator once the pointer
* enters the application area of a window.
*/
if (ev.absolute_motion() && _first_motion) {
if (ev.absolute_motion() && _first_motion && _key_cnt == 0) {
_click_handler.handle_enter(_pointer_pos);
_first_motion = false;
}
/*
* We may leave the dragged state on another window than
* the clicked one. During the dragging, the decorator
* remained unaware of pointer movements. Now, when leaving
* the drag stage, we need to make the decorator aware of
* the most recent pointer position to update the hover
* model.
*/
if (ev.release() && _key_cnt == 0)
_click_handler.handle_enter(_pointer_pos);
if (ev.hover_leave())
_first_motion = true;