genode/repos/gems/src/app/themed_decorator/window.cc
Norman Feske dec2d897c3 themed_decorator: fix jumping windows
The decorator's detection of the hovered window element was inaccurate,
which resulted in "jumping" windows in some situations, ultimately
caused by a combination of three different mechanisms.

First, when moving the pointer into the area of a window, the decorator
would detect the hovering of the left border whenever the distance of
the pointer from the border was less than the half of the theme texture
(e.g., 64x64 pixels for the default theme). However, if the left border
margin is set to a small value (e.g., 1), there is an overlap of the
sensitive resize border area and the content. Hence, chances were quite
high that - when moving the pointer from the left into the window - the
hover report would contain the hovering of the left border.

Second, the window manager tries to hide pointer movements from the
decorator if possible. It informs the decorator of the pointer position
if any decoration is hovered or if a new window is hovered. But it does
not expose pointer movements within a window to the decorator. For this
reason, the decorator would not update the hover report as long as the
pointer stays within a once hovered window. In the situation described
above, the hover report would still contain the stale information about
the hovering of the left resize border.

Third, when the user clicks on the window, the decorator examines the
most recent hover report and - in the situation described above - finds
the left border hovered. Consequently, it initiates a window-drag
operation. While resizing the window with the left border, the window
layouter pins the right border of the window to its current position.
All window-size changes of the client will be applied towards the left
(dragged) border. In the case of the top view, which continuously
resizes the window by itself, the window would "jump". In reality, it
actually tries to respond an interactive resize operation. The window
layouter cannot guess that the client is not responding to window
layouter's resize request but is acting independently.

This patch fixes the jumping window problem for the case where the
pointer hovers the overlapping area of the resize border and the
content. However, when trying the to interactively resize the top window
via the bottom-left corner, the "jumping" can still be observed.

Fixes #3303
2019-07-09 08:55:24 +02:00

65 lines
1.8 KiB
C++

/*
* \brief Example window decorator that mimics the Motif look
* \author Norman Feske
* \date 2014-01-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include "window.h"
Decorator::Window_base::Hover Decorator::Window::hover(Point abs_pos) const
{
Hover hover;
if (!_decor_geometry().contains(abs_pos))
return hover;
hover.window_id = id();
/* omit the decoration checks below whenever the content is hovered */
if (geometry().contains(abs_pos))
return hover;
Rect const closer_geometry =
_theme.absolute(_theme.element_geometry(Theme::ELEMENT_TYPE_CLOSER),
outer_geometry());
if (closer_geometry.contains(abs_pos)) {
hover.closer = true;
return hover;
}
Rect const maximizer_geometry =
_theme.absolute(_theme.element_geometry(Theme::ELEMENT_TYPE_MAXIMIZER),
outer_geometry());
if (maximizer_geometry.contains(abs_pos)) {
hover.maximizer = true;
return hover;
}
Rect const title_geometry = _theme.absolute(_theme.title_geometry(),
outer_geometry());
if (title_geometry.contains(abs_pos)) {
hover.title = true;
return hover;
}
int const x = abs_pos.x();
int const y = abs_pos.y();
Area const theme_size = _theme.background_size();
hover.left_sizer = x < outer_geometry().x1() + (int)theme_size.w()/2;
hover.right_sizer = x > outer_geometry().x2() - (int)theme_size.w()/2;
hover.top_sizer = y < outer_geometry().y1() + (int)theme_size.h()/2;
hover.bottom_sizer = y > outer_geometry().y2() - (int)theme_size.h()/2;
return hover;
}