window_layouter/decorator: drag-state corner cases

This patch complements the commit "nitpicker: defer hover changed while
dragging" with fixes of the window layouter and motif decorator.

- Handling of empty pointer model (after unhovering a decoration)
  instead of not updating it.

- Re-applying the hover model to the window layout when leaving the
  drag state. This addresses the corner case that the hover model
  changed during the drag operation (which is rightfully not handled
  while dragging).

- Letting the window layouter enter the drag state only if a dragged
  window is defined.

Issue #3973
This commit is contained in:
Norman Feske 2021-01-05 17:43:59 +01:00
parent 98798f18b5
commit d698e0876d
3 changed files with 26 additions and 43 deletions

View File

@ -296,31 +296,16 @@ void Decorator::Main::_handle_gui_sync()
if (_window_layout_update_needed && _window_layout.valid()) {
try {
Xml_node xml(_window_layout.local_addr<char>(),
_window_layout.size());
_window_stack.update_model(_window_layout.xml(), flush_window_stack_changes);
_window_stack.update_model(xml, flush_window_stack_changes);
model_updated = true;
model_updated = true;
/*
* A decorator element might have appeared or disappeared under
* the pointer.
*/
if (_pointer.valid())
update_hover_report(Xml_node(_pointer.local_addr<char>()),
_window_stack, _hover, _hover_reporter);
} catch (Xml_node::Invalid_syntax) {
/*
* An error occured with processing the XML model. Flush the
* internal representation with an empty window layout.
*/
_window_stack.update_model(Xml_node("<window_layout/>"),
flush_window_stack_changes);
}
/*
* A decorator element might have appeared or disappeared under
* the pointer.
*/
update_hover_report(_pointer.xml(),
_window_stack, _hover, _hover_reporter);
_window_layout_update_needed = false;
}
@ -359,9 +344,7 @@ void Decorator::Main::_handle_pointer_update()
{
_pointer.update();
if (_pointer.valid())
update_hover_report(Xml_node(_pointer.local_addr<char>()),
_window_stack, _hover, _hover_reporter);
update_hover_report(_pointer.xml(), _window_stack, _hover, _hover_reporter);
}

View File

@ -259,8 +259,10 @@ struct Window_layouter::Main : Operations,
* Update window layout because highlighting may have changed after the
* drag operation. E.g., if the window has not kept up with the
* dragging of a resize handle, the resize handle is no longer hovered.
*
* The call of '_handle_hover' implicitly triggers '_gen_window_layout'.
*/
_gen_window_layout();
_handle_hover();
_drag_state = Drag_state::SETTLING;
@ -308,10 +310,6 @@ struct Window_layouter::Main : Operations,
Signal_handler<Main> _decorator_margins_handler {
_env.ep(), *this, &Main::_handle_decorator_margins};
/**
* Install handler for responding to user input
*/
void _handle_input()
{
while (_input.pending())
@ -601,10 +599,11 @@ void Window_layouter::Main::_handle_hover()
/*
* An exception may occur during the 'Xml_node' construction if the hover
* model is malformed. Under this condition, we invalidate the hover state.
* model lacks a window. Under this condition, we invalidate the hover
* state.
*/
catch (...) {
_user_state.reset_hover();
/*

View File

@ -282,21 +282,22 @@ void Window_layouter::User_state::_handle_event(Input::Event const &e,
}
/* detect end of drag operation */
if (e.release() && _key_cnt == 0 && _dragged_window_id.valid()) {
if (e.release() && _key_cnt == 0) {
_drag_state = false;
/*
* Issue resize to 0x0 when releasing the the window closer
*/
if (_dragged_element == Window::Element::CLOSER) {
if (_dragged_window_id.valid()) {
if (_dragged_element == _hovered_element)
_operations.close(_dragged_window_id);
/*
* Issue resize to 0x0 when releasing the the window closer
*/
if (_dragged_element == Window::Element::CLOSER)
if (_dragged_element == _hovered_element)
_operations.close(_dragged_window_id);
_operations.finalize_drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
}
_operations.finalize_drag(_dragged_window_id, _dragged_element,
_pointer_clicked, _pointer_curr);
}
/* handle key sequences */