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 **
|
|
|
|
**************************/
|
|
|
|
|
2014-02-11 15:11:31 +01:00
|
|
|
User_state::User_state(Global_keys &global_keys, Area view_stack_size, Menubar &menubar)
|
2013-09-06 17:34:16 +02:00
|
|
|
:
|
2014-06-04 15:58:49 +02:00
|
|
|
View_stack(view_stack_size, *this), _global_keys(global_keys), _menubar(menubar)
|
2013-09-06 17:34:16 +02:00
|
|
|
{ }
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
void User_state::_update_all()
|
|
|
|
{
|
|
|
|
Menubar_state state(*this, "", BLACK);
|
|
|
|
|
|
|
|
if (_input_receiver)
|
|
|
|
state = Menubar_state(*this,
|
|
|
|
_input_receiver->label().string(),
|
|
|
|
_input_receiver->color());
|
|
|
|
|
|
|
|
_menubar.state(state);
|
|
|
|
update_all_views();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-30 13:51:45 +02: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
|
|
|
|
2013-12-28 22:29:30 +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 */
|
2014-06-04 15:58:49 +02:00
|
|
|
if (type == Event::PRESS) Mode::inc_key_cnt();
|
|
|
|
if (type == Event::RELEASE && Mode::drag()) Mode::dec_key_cnt();
|
2013-09-07 02:02:26 +02:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
View const * const pointed_view = find_view(_mouse_pos);
|
|
|
|
Session * const pointed_session = pointed_view ? &pointed_view->session() : 0;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Deliver a leave event if pointed-to session changed
|
|
|
|
*/
|
2014-06-04 15:58:49 +02:00
|
|
|
if (_pointed_session && (pointed_session != _pointed_session)) {
|
2013-09-07 02:02:26 +02:00
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
Input::Event leave_ev(Input::Event::LEAVE, 0, ax, ay, 0, 0);
|
2014-06-04 15:58:49 +02:00
|
|
|
_pointed_session->submit_input_event(leave_ev);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
_pointed_session = pointed_session;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
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
|
|
|
|
{
|
2014-02-11 15:11:31 +01:00
|
|
|
User_state &user_state;
|
2014-06-04 15:58:49 +02:00
|
|
|
bool update = false;
|
2013-09-06 17:34:16 +02:00
|
|
|
|
2014-04-30 13:51:45 +02:00
|
|
|
Update_all_guard(User_state &user_state)
|
|
|
|
: user_state(user_state) { }
|
2013-09-06 17:34:16 +02:00
|
|
|
|
|
|
|
~Update_all_guard()
|
|
|
|
{
|
2014-06-04 15:58:49 +02:00
|
|
|
if (update)
|
|
|
|
user_state._update_all();
|
2013-09-06 17:34:16 +02:00
|
|
|
}
|
2014-04-30 13:51:45 +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
|
|
|
|
*/
|
2014-06-04 15:58:49 +02:00
|
|
|
if (type == Event::PRESS && Mode::has_key_cnt(1)) {
|
2013-09-07 02:02:26 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Detect mouse press event in kill mode, used to select the session
|
|
|
|
* to lock out.
|
|
|
|
*/
|
|
|
|
if (kill() && keycode == Input::BTN_LEFT) {
|
2014-06-04 15:58:49 +02:00
|
|
|
if (_pointed_session)
|
|
|
|
lock_out_session(*_pointed_session);
|
2013-09-07 02:02:26 +02:00
|
|
|
|
|
|
|
/* leave kill mode */
|
2014-06-04 15:58:49 +02:00
|
|
|
update_all_guard.update = true;
|
2013-09-07 02:02:26 +02:00
|
|
|
Mode::leave_kill();
|
|
|
|
return;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
/* update focused session */
|
|
|
|
if (pointed_session != Mode::focused_session() && _mouse_button(keycode)) {
|
2013-01-12 23:34:49 +01:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
update_all_guard.update = true;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/*
|
2014-06-04 15:58:49 +02:00
|
|
|
* Notify both the old focused session and the new one.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2014-06-04 15:58:49 +02:00
|
|
|
if (Mode::focused_session()) {
|
|
|
|
Input::Event unfocus_ev(Input::Event::FOCUS, 0, ax, ay, 0, 0);
|
|
|
|
Mode::focused_session()->submit_input_event(unfocus_ev);
|
2014-02-14 14:31:03 +01:00
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
if (_pointed_session) {
|
|
|
|
Input::Event focus_ev(Input::Event::FOCUS, 1, ax, ay, 0, 0);
|
|
|
|
pointed_session->submit_input_event(focus_ev);
|
2013-01-12 23:34:49 +01:00
|
|
|
}
|
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
focused_session(_pointed_session);
|
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
|
2014-06-04 15:58:49 +02:00
|
|
|
* pointed-at session.
|
2013-09-06 17:34:16 +02:00
|
|
|
*
|
|
|
|
* 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) {
|
2014-06-04 15:58:49 +02:00
|
|
|
_global_key_sequence = true;
|
|
|
|
_input_receiver = global_receiver;
|
|
|
|
update_all_guard.update = 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
|
2014-06-04 15:58:49 +02:00
|
|
|
* focused session or refers to a built-in operation.
|
2013-09-06 17:34:16 +02:00
|
|
|
*/
|
2014-06-04 15:58:49 +02:00
|
|
|
if (!global_receiver) {
|
|
|
|
_input_receiver = Mode::focused_session();
|
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
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
if (_global_keys.is_kill_key(keycode)) {
|
|
|
|
Mode::toggle_kill();
|
|
|
|
_input_receiver = 0;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
if (_global_keys.is_xray_key(keycode)) Mode::toggle_xray();
|
2014-02-14 14:31:03 +01:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
update_all_guard.update = true;
|
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
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
if (Mode::has_key_cnt(0)) {
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/*
|
2014-06-04 15:58:49 +02:00
|
|
|
* In flat mode, we deliver motion events to the pointed-at
|
|
|
|
* session. In xray mode, we deliver motion events only to the
|
|
|
|
* focused session.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2014-06-04 15:58:49 +02:00
|
|
|
if (flat() || (xray() && Mode::focused_session() == pointed_session))
|
|
|
|
if (pointed_session)
|
|
|
|
pointed_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
|
|
|
}
|
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
/* deliver press/release event to focused session */
|
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
|
|
|
|
*/
|
2014-06-04 15:58:49 +02:00
|
|
|
if (ev.type() == Event::RELEASE && Mode::has_key_cnt(0) && _global_key_sequence) {
|
2014-02-14 14:31:03 +01:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
_input_receiver = Mode::focused_session();
|
2014-02-14 14:31:03 +01:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
update_all_guard.update = true;
|
2014-02-14 14:31:03 +01:00
|
|
|
|
|
|
|
_global_key_sequence = false;
|
2013-09-06 17:34:16 +02:00
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************
|
|
|
|
** Mode interface **
|
|
|
|
********************/
|
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
void User_state::forget(Session const &session)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2014-06-04 15:58:49 +02:00
|
|
|
Mode::forget(session);
|
2013-09-07 02:02:26 +02:00
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
if (_pointed_session == &session) {
|
|
|
|
View * const pointed_view = find_view(_mouse_pos);
|
|
|
|
_pointed_session = pointed_view ? &pointed_view->session() : nullptr;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
2014-06-04 15:58:49 +02:00
|
|
|
|
|
|
|
void User_state::focused_session(Session *session)
|
|
|
|
{
|
|
|
|
Mode::focused_session(session);
|
|
|
|
|
|
|
|
if (!_global_key_sequence)
|
|
|
|
_input_receiver = session;
|
|
|
|
|
|
|
|
_update_all();
|
|
|
|
}
|