genode/repos/os/src/server/nitpicker/user_state.h

269 lines
6.8 KiB
C
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief Nitpicker user state handling
* \author Norman Feske
* \date 2006-08-09
*
* This class comprehends the policy of user interaction.
* It manages the toggling of Nitpicker's different modes
* and routes input events to corresponding client sessions.
*/
/*
* Copyright (C) 2006-2017 Genode Labs GmbH
2011-12-22 16:19:25 +01:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
2011-12-22 16:19:25 +01:00
*/
#ifndef _USER_STATE_H_
#define _USER_STATE_H_
#include <util/xml_generator.h>
#include "focus.h"
2011-12-22 16:19:25 +01:00
#include "view_stack.h"
2013-09-06 17:34:16 +02:00
#include "global_keys.h"
2011-12-22 16:19:25 +01:00
namespace Nitpicker { class User_state; }
class Nitpicker::User_state
2011-12-22 16:19:25 +01:00
{
private:
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
/*
* Noncopyable
*/
User_state(User_state const &);
User_state &operator = (User_state const &);
2013-09-06 17:34:16 +02:00
/*
* Number of currently pressed keys. This counter is used to determine
* if the user is dragging an item.
*/
unsigned _key_cnt = 0;
View_owner *_focused = nullptr;
View_owner *_next_focused = nullptr;
/*
* True while a global key sequence is processed
*/
bool _global_key_sequence = false;
/*
* True if the input focus should change directly whenever the user
* clicks on an unfocused client. This is the traditional behaviour
* of nitpicker. This builtin policy is now superseded by the use of an
* external focus-management component (e.g., nit_focus).
*/
bool _focus_via_click = true;
/**
* Input-focus information propagated to the view stack
*/
Focus &_focus;
/**
2013-09-06 17:34:16 +02:00
* Policy for the routing of global keys
*/
Global_keys &_global_keys;
/**
* View stack, used to determine the hovered view and pointer boundary
*/
View_stack &_view_stack;
2011-12-22 16:19:25 +01:00
/*
* Current pointer position
2011-12-22 16:19:25 +01:00
*/
Point _pointer_pos;
2011-12-22 16:19:25 +01:00
/*
* Currently pointed-at view owner
2011-12-22 16:19:25 +01:00
*/
View_owner *_hovered = nullptr;
2011-12-22 16:19:25 +01:00
2013-09-06 17:34:16 +02:00
/*
* View owner that receives the current stream of input events
2013-09-06 17:34:16 +02:00
*/
View_owner *_input_receiver = nullptr;
2013-09-06 17:34:16 +02:00
/**
* View owner that was last clicked-on by the user
*/
View_owner *_last_clicked = nullptr;
/**
* Number of clicks, used to detect whether a focus-relevant click
* happened during '_handle_input_event'.
*/
unsigned _clicked_count = 0;
/**
* Version supplement for the "clicked" report
*
* The value allows the receiver of the report to detect the situation
* where two consecutive clicks refer to the same client but both
* events require a distinct focus response, i.e., if the focus (focus
* ROM) was changed in-between both clicks by other means than a click.
*/
unsigned _last_clicked_version = 0;
/*
* If set, a "clicked" report is generated even if the clicked-on view
* is the same as the previously clicked-on view.
*/
bool _last_clicked_redeliver = false;
/**
* Array for tracking the state of each key
*/
struct Key_array
{
struct State { bool pressed = false; };
State _states[Input::KEY_MAX + 1];
void pressed(Input::Keycode key, bool pressed)
{
if (key <= Input::KEY_MAX)
_states[key].pressed = pressed;
}
bool pressed(Input::Keycode key) const
{
return (key <= Input::KEY_MAX) && _states[key].pressed;
}
void report_state(Genode::Xml_generator &xml) const
{
for (unsigned i = 0; i <= Input::KEY_MAX; i++)
if (_states[i].pressed)
xml.node("pressed", [&] () {
xml.attribute("key", Input::key_name((Input::Keycode)i)); });
}
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
} _key_array { };
void _focus_view_owner_via_click(View_owner &);
2011-12-22 16:19:25 +01:00
void _handle_input_event(Input::Event);
2011-12-22 16:19:25 +01:00
bool _key_pressed() const { return _key_cnt > 0; }
2011-12-22 16:19:25 +01:00
/**
* Apply pending focus-change request that was issued during drag state
2011-12-22 16:19:25 +01:00
*/
void _apply_pending_focus_change()
{
/*
* Defer focus changes to a point where no drag operation is in
* flight because otherwise, the involved sessions would obtain
* inconsistent press and release events. However, focus changes
* during global key sequences are fine.
*/
if (_key_pressed() && !_global_key_sequence)
return;
if (_focused != _next_focused) {
_focused = _next_focused;
/*
* Enforce the generation of a new "clicked" report for any click
* that follows a focus change. This is needed in situations
* where the focus is defined by clicks as well as other means
* (e.g., the appearance of a lock screen).
*/
_last_clicked_redeliver = true;
/* propagate changed focus to view stack */
if (_focused)
_focus.assign(*_focused);
else
_focus.reset();
}
}
public:
2011-12-22 16:19:25 +01:00
/**
* Constructor
*
* \param focus exported focus information, to be consumed by the
* view stack to tailor its view drawing operations
*/
User_state(Focus &focus, Global_keys &global_keys, View_stack &view_stack,
Point initial_pointer_pos)
:
_focus(focus), _global_keys(global_keys), _view_stack(view_stack),
_pointer_pos(initial_pointer_pos)
{ }
/****************************************
** Interface used by the main program **
****************************************/
struct Handle_input_result
{
bool const hover_changed;
bool const focus_changed;
bool const key_state_affected;
bool const button_activity;
bool const motion_activity;
bool const key_pressed;
bool const last_clicked_changed;
};
Handle_input_result handle_input_events(Input::Event const *ev_buf,
unsigned num_ev);
2011-12-22 16:19:25 +01:00
/**
* Discard all references to specified view owner
2011-12-22 16:19:25 +01:00
*/
struct Handle_forget_result
{
bool const hover_changed;
bool const focus_changed;
};
Handle_forget_result forget(View_owner const &);
void report_keystate(Xml_generator &) const;
void report_pointer_position(Xml_generator &) const;
void report_hovered_view_owner(Xml_generator &, bool motion_active) const;
void report_focused_view_owner(Xml_generator &, bool button_active) const;
void report_last_clicked_view_owner(Xml_generator &) const;
Point pointer_pos() { return _pointer_pos; }
/**
* Enable/disable direct focus changes by clicking on a client
*/
void focus_via_click(bool enabled) { _focus_via_click = enabled; }
/**
* Set input focus to specified view owner
*
* This method is used when nitpicker's focus is managed by an
* external focus-policy component like 'nit_focus'.
*
* The focus change is not applied immediately but deferred to the
* next call of 'handle_input_events' (which happens periodically).
*/
void focus(View_owner &owner)
{
/*
* The focus change is not applied immediately but deferred to the
* next call of '_apply_pending_focus_change' via the periodic
* call of 'handle_input_events'.
*/
_next_focused = &owner;
}
void reset_focus() { _next_focused = nullptr; }
2011-12-22 16:19:25 +01:00
};
#endif /* _USER_STATE_H_ */