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

294 lines
7.7 KiB
C++
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief User state implementation
* \author Norman Feske
* \date 2006-08-27
*/
/*
2013-01-10 21:44:47 +01:00
* Copyright (C) 2006-2013 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 General Public License version 2.
*/
#include <input/event.h>
#include <input/keycodes.h>
2013-09-06 17:34:16 +02:00
2011-12-22 16:19:25 +01:00
#include "user_state.h"
using namespace Input;
/***************
** Utilities **
***************/
2013-09-06 17:34:16 +02:00
static inline bool _masked_key(Global_keys &global_keys, Keycode keycode) {
return global_keys.is_kill_key(keycode) || global_keys.is_xray_key(keycode); }
2011-12-22 16:19:25 +01:00
2013-09-06 17:34:16 +02:00
static inline bool _mouse_button(Keycode keycode) {
2011-12-22 16:19:25 +01:00
return keycode >= BTN_LEFT && keycode <= BTN_MIDDLE; }
/**************************
** User state interface **
**************************/
User_state::User_state(Global_keys &global_keys, Area view_stack_size, Menubar &menubar)
2013-09-06 17:34:16 +02:00
:
View_stack(view_stack_size, *this), _global_keys(global_keys), _key_cnt(0),
2013-09-06 17:34:16 +02:00
_menubar(menubar), _pointed_view(0), _input_receiver(0),
_global_key_sequence(false)
{ }
2011-12-22 16:19:25 +01:00
void User_state::handle_event(Input::Event ev)
2011-12-22 16:19:25 +01:00
{
2013-09-06 17:34:16 +02:00
Input::Keycode const keycode = ev.keycode();
Input::Event::Type const type = ev.type();
2011-12-22 16:19:25 +01:00
/*
* Mangle incoming events
*/
int ax = _mouse_pos.x(), ay = _mouse_pos.y();
2013-09-07 02:02:26 +02:00
int rx = 0, ry = 0; /* skip info about relative motion by default */
2011-12-22 16:19:25 +01:00
/* transparently handle absolute and relative motion events */
2013-09-06 17:34:16 +02:00
if (type == Event::MOTION) {
2011-12-22 16:19:25 +01:00
if ((ev.rx() || ev.ry()) && ev.ax() == 0 && ev.ay() == 0) {
2013-12-28 20:14:29 +01:00
ax = Genode::max(0, Genode::min((int)size().w(), ax + ev.rx()));
ay = Genode::max(0, Genode::min((int)size().h(), ay + ev.ry()));
2011-12-22 16:19:25 +01:00
} else {
ax = ev.ax();
ay = ev.ay();
}
}
/* propagate relative motion for wheel events */
2013-09-06 17:34:16 +02:00
if (type == Event::WHEEL) {
2011-12-22 16:19:25 +01:00
rx = ev.rx();
ry = ev.ry();
}
/* create the mangled event */
2013-09-06 17:34:16 +02:00
ev = Input::Event(type, keycode, ax, ay, rx, ry);
2011-12-22 16:19:25 +01:00
_mouse_pos = Point(ax, ay);
2011-12-22 16:19:25 +01:00
2013-09-07 02:02:26 +02:00
/* count keys */
if (type == Event::PRESS) _key_cnt++;
if (type == Event::RELEASE && _key_cnt > 0) _key_cnt--;
View const * const pointed_view = find_view(_mouse_pos);
2011-12-22 16:19:25 +01:00
/*
* Deliver a leave event if pointed-to session changed
*/
if (pointed_view && _pointed_view &&
2013-09-07 02:02:26 +02:00
!pointed_view->same_session_as(*_pointed_view)) {
2011-12-22 16:19:25 +01:00
Input::Event leave_ev(Input::Event::LEAVE, 0, ax, ay, 0, 0);
2013-09-07 02:02:26 +02:00
_pointed_view->session().submit_input_event(leave_ev);
2011-12-22 16:19:25 +01:00
}
_pointed_view = pointed_view;
2013-09-06 17:34:16 +02:00
/**
2013-09-07 02:02:26 +02:00
* Guard that, when 'enabled' is set to true, performs a whole-screen
* update when leaving the scope
2011-12-22 16:19:25 +01:00
*/
2013-09-06 17:34:16 +02:00
struct Update_all_guard
{
User_state &user_state;
bool update_menubar = false;
bool update_views = false;
char const *menu_title = "";
2013-09-06 17:34:16 +02:00
Update_all_guard(User_state &user_state)
: user_state(user_state) { }
2013-09-06 17:34:16 +02:00
~Update_all_guard()
{
Menubar_state state(user_state, "", "", BLACK);
2013-09-06 17:34:16 +02:00
if (user_state._input_receiver)
state = Menubar_state(user_state,
user_state._input_receiver->label().string(),
menu_title,
user_state._input_receiver->color());
if (update_menubar)
user_state._menubar.state(state);
if (update_menubar || update_views)
user_state.update_all_views();
2013-09-06 17:34:16 +02:00
}
} update_all_guard(*this);
2011-12-22 16:19:25 +01:00
2013-09-06 17:34:16 +02:00
/*
* Handle start of a key sequence
*/
2013-09-07 02:02:26 +02:00
if (type == Event::PRESS && _key_cnt == 1) {
/*
* Detect mouse press event in kill mode, used to select the session
* to lock out.
*/
if (kill() && keycode == Input::BTN_LEFT) {
if (pointed_view)
lock_out_session(pointed_view->session());
2013-09-07 02:02:26 +02:00
/* leave kill mode */
update_all_guard.update_menubar = true;
update_all_guard.update_views = true;
2013-09-07 02:02:26 +02:00
Mode::leave_kill();
return;
}
2011-12-22 16:19:25 +01:00
/* update focused view */
2013-09-06 17:34:16 +02:00
if (pointed_view != focused_view() && _mouse_button(keycode)) {
bool const focus_stays_in_session =
2013-09-07 02:02:26 +02:00
focused_view() && pointed_view &&
focused_view()->belongs_to(pointed_view->session());
2011-12-22 16:19:25 +01:00
/*
* Update the whole screen when the focus change results in
* changing the focus to another session.
2011-12-22 16:19:25 +01:00
*/
if (flat() && !focus_stays_in_session) {
update_all_guard.update_menubar = true;
update_all_guard.update_views = true;
}
2011-12-22 16:19:25 +01:00
/*
* Notify both the old focussed session and the new one.
*/
if (!focus_stays_in_session) {
2013-09-07 02:02:26 +02:00
if (focused_view()) {
Input::Event unfocus_ev(Input::Event::FOCUS, 0, ax, ay, 0, 0);
2013-09-07 02:02:26 +02:00
focused_view()->session().submit_input_event(unfocus_ev);
}
if (pointed_view) {
Input::Event focus_ev(Input::Event::FOCUS, 1, ax, ay, 0, 0);
2013-09-07 02:02:26 +02:00
pointed_view->session().submit_input_event(focus_ev);
}
}
update_all_guard.update_menubar = true;
2013-09-07 02:02:26 +02:00
if (!flat() || !focused_view() || !pointed_view)
update_all_guard.update_views = true;
2011-12-22 16:19:25 +01:00
2013-09-07 02:02:26 +02:00
focused_view(pointed_view);
2011-12-22 16:19:25 +01:00
}
2013-09-06 17:34:16 +02:00
/*
* If there exists a global rule for the pressed key, set the
* corresponding session as receiver of the input stream until the key
* count reaches zero. Otherwise, the input stream is directed to the
* pointed-at view.
*
* If we deliver a global key sequence, we temporarily change the focus
* to the global receiver. To reflect that change, we need to update
* the whole screen.
*/
Session * const global_receiver = _global_keys.global_receiver(keycode);
if (global_receiver) {
_global_key_sequence = true;
_input_receiver = global_receiver;
update_all_guard.menu_title = "";
update_all_guard.update_menubar = true;
update_all_guard.update_views = true;
2013-09-06 17:34:16 +02:00
}
2011-12-22 16:19:25 +01:00
2013-09-06 17:34:16 +02:00
/*
* No global rule matched, so the input stream gets directed to the
* focused view or refers to a built-in operation.
*/
2013-09-07 02:02:26 +02:00
if (!global_receiver && focused_view()) {
_input_receiver = &focused_view()->session();
update_all_guard.menu_title = focused_view()->title();
2011-12-22 16:19:25 +01:00
}
2013-09-06 17:34:16 +02:00
/*
* Toggle kill and xray modes. If one of those keys is pressed,
* suppress the delivery to clients.
*/
if (_global_keys.is_operation_key(keycode)) {
2011-12-22 16:19:25 +01:00
2013-09-07 02:02:26 +02:00
if (_global_keys.is_kill_key(keycode)) Mode::toggle_kill();
if (_global_keys.is_xray_key(keycode)) Mode::toggle_xray();
2011-12-22 16:19:25 +01:00
update_all_guard.update_menubar = true;
update_all_guard.update_views = true;
_input_receiver = 0;
2013-09-06 17:34:16 +02:00
}
2011-12-22 16:19:25 +01:00
}
/*
2013-09-07 02:02:26 +02:00
* Deliver event to session except when kill mode is activated
2011-12-22 16:19:25 +01:00
*/
if (kill()) return;
2013-09-06 17:34:16 +02:00
if (type == Event::MOTION || type == Event::WHEEL) {
2011-12-22 16:19:25 +01:00
if (_key_cnt == 0) {
/*
* In flat mode, we deliver motion events to the session of
* the pointed view. In xray mode, we deliver motion
* events only to the session with the focused view.
*/
if (flat() || (xray() && focused_view() == pointed_view))
if (pointed_view)
2013-09-07 02:02:26 +02:00
pointed_view->session().submit_input_event(ev);
2011-12-22 16:19:25 +01:00
2013-09-06 17:34:16 +02:00
} else if (_input_receiver)
2013-09-07 02:02:26 +02:00
_input_receiver->submit_input_event(ev);
2011-12-22 16:19:25 +01:00
}
/* deliver press/release event to session with focused view */
2013-09-06 17:34:16 +02:00
if (type == Event::PRESS || type == Event::RELEASE)
if (_input_receiver)
2013-09-07 02:02:26 +02:00
_input_receiver->submit_input_event(ev);
2013-09-06 17:34:16 +02:00
/*
* Detect end of global key sequence
*/
if (ev.type() == Event::RELEASE && _key_cnt == 0 && _global_key_sequence) {
_input_receiver = focused_view() ? &focused_view()->session() : 0;
update_all_guard.menu_title = focused_view() ? focused_view()->title() : "";
update_all_guard.update_menubar = true;
update_all_guard.update_views = true;
_global_key_sequence = false;
2013-09-06 17:34:16 +02:00
}
2011-12-22 16:19:25 +01:00
}
/********************
** Mode interface **
********************/
void User_state::forget(View const &view)
2011-12-22 16:19:25 +01:00
{
2013-09-07 02:02:26 +02:00
if (focused_view() == &view) {
Mode::forget(view);
_menubar.state(Menubar_state(*this, "", "", BLACK));
update_all_views();
2011-12-22 16:19:25 +01:00
}
2013-09-07 02:02:26 +02:00
if (_input_receiver && view.belongs_to(*_input_receiver))
2013-09-06 17:34:16 +02:00
_input_receiver = 0;
2013-09-07 02:02:26 +02:00
if (_pointed_view == &view)
2011-12-22 16:19:25 +01:00
_pointed_view = find_view(_mouse_pos);
}