genode/repos/demo/include/scout/user_state.h
Norman Feske c629c54153 Make util/geometry.h C++20 friendly
- Move header to base/include to make it applicable for base types
  like 'Affinity' down the road.
- Represent 'Rect' as typle of point and area, which is the most
  common form of initialization, creates in valid 'Rect' by default.
- Turn Point, Area, and Rect into compound types, making x, y, w, h, at,
  area accessible without a method call
- 'Rect::Compound' function for constructing a 'Rect' from two points,
  replacing a former constructor
- Use result type 'Rect::Cut_remainder' instead of out parameters.

Fixes #5239
2024-06-20 12:54:30 +02:00

159 lines
3.2 KiB
C++

/*
* \brief User state manager
* \date 2005-11-16
* \author Norman Feske <norman.feske@genode-labs.com>
*/
/*
* Copyright (C) 2005-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.
*/
#ifndef _INCLUDE__SCOUT__USER_STATE_H_
#define _INCLUDE__SCOUT__USER_STATE_H_
#include <scout/window.h>
namespace Scout { class User_state; }
class Scout::User_state : public Parent_element
{
private:
/*
* Noncopyable
*/
User_state(User_state const &);
User_state &operator = (User_state const &);
Element *_mfocus; /* element that owns the current mouse focus */
Element *_active; /* currently activated element */
Window *_window;
Element *_root; /* root of element tree */
int _key_cnt; /* number of currently pressed keys */
Point _mouse_position { };
Point _view_position { };
/**
* Assign new mouse focus element
*/
void _assign_mfocus(Element *e, int force = 0)
{
/* return if mouse focus did not change */
if (!force && e == _mfocus) return;
/* tell old mouse focus to release focus */
if (_mfocus) _mfocus->mfocus(0);
/* assign new current mouse focus */
_mfocus = e;
/* notify new mouse focus */
if (_mfocus) _mfocus->mfocus(1);
}
public:
/**
* Constructor
*/
User_state(Window *window, Element *root, int vx, int vy)
:
_mfocus(0), _active(0), _window(window), _root(root),
_key_cnt(0), _view_position(Point(vx, vy))
{ }
/**
* Accessor functions
*/
Point mouse_position() const { return _mouse_position; }
Point view_position() const { return _view_position; }
/**
* Update the current view offset
*/
void update_view_offset()
{
_view_position = Point(_window->view_x(), _window->view_y());
}
/**
* Apply input event to mouse focus state
*/
void handle_event(Event const &ev)
{
_key_cnt += ev.type == Event::PRESS ? 1 : 0;
_key_cnt -= ev.type == Event::RELEASE ? 1 : 0;
if (_key_cnt < 0) _key_cnt = 0;
if (_active)
_active->handle_event(ev);
/* find element under the mouse cursor */
_mouse_position = ev.mouse_position;
Element *e = _root->find(_mouse_position);
switch (ev.type) {
case Event::PRESS:
if (_key_cnt != 1) break;
if (!e) break;
_active = e;
_active->handle_event(ev);
update_view_offset();
_assign_mfocus(_root->find(ev.mouse_position), 1);
break;
case Event::RELEASE:
if (_key_cnt == 0) {
update_view_offset();
_active = 0;
_assign_mfocus(e);
}
break;
case Event::MOTION:
if (!_active && e) e->handle_event(ev);
if (_key_cnt == 0)
_assign_mfocus(e);
break;
case Event::WHEEL:
if (_key_cnt == 0)
_window->ypos(_window->ypos() + 23 * ev.mouse_position.y);
break;
default:
break;
}
}
/********************
** Parent element **
********************/
void forget(Element const *e) override
{
if (_mfocus == e) _mfocus = 0;
if (_active == e) _active = 0;
}
};
#endif /* _INCLUDE__SCOUT__USER_STATE_H_ */