mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 03:45:24 +00:00
nitpicker: Support for session-focus management
This patch introduces a focus-management facility to the nitpicker session interface. As a side effect of this change, we remove the notion of a "focused view". There can only be a "focused session". This makes sense because input is directed to sessions, not views. Issue #1168
This commit is contained in:
parent
d22cddd1e8
commit
24869bd3ff
@ -25,26 +25,29 @@ struct Nitpicker::Session_client : public Genode::Rpc_client<Session>
|
||||
explicit Session_client(Session_capability session)
|
||||
: Rpc_client<Session>(session) { }
|
||||
|
||||
Framebuffer::Session_capability framebuffer_session() {
|
||||
Framebuffer::Session_capability framebuffer_session() override {
|
||||
return call<Rpc_framebuffer_session>(); }
|
||||
|
||||
Input::Session_capability input_session() {
|
||||
Input::Session_capability input_session() override {
|
||||
return call<Rpc_input_session>(); }
|
||||
|
||||
View_capability create_view(View_capability parent = View_capability()) {
|
||||
View_capability create_view(View_capability parent = View_capability()) override {
|
||||
return call<Rpc_create_view>(parent); }
|
||||
|
||||
void destroy_view(View_capability view) {
|
||||
void destroy_view(View_capability view) override {
|
||||
call<Rpc_destroy_view>(view); }
|
||||
|
||||
int background(View_capability view) {
|
||||
int background(View_capability view) override {
|
||||
return call<Rpc_background>(view); }
|
||||
|
||||
Framebuffer::Mode mode() {
|
||||
Framebuffer::Mode mode() override {
|
||||
return call<Rpc_mode>(); }
|
||||
|
||||
void buffer(Framebuffer::Mode mode, bool alpha) {
|
||||
void buffer(Framebuffer::Mode mode, bool alpha) override {
|
||||
call<Rpc_buffer>(mode, alpha); }
|
||||
|
||||
void focus(Nitpicker::Session_capability session) override {
|
||||
call<Rpc_focus>(session); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__NITPICKER_SESSION__CLIENT_H_ */
|
||||
|
@ -85,6 +85,20 @@ struct Nitpicker::Session : Genode::Session
|
||||
*/
|
||||
virtual void buffer(Framebuffer::Mode mode, bool use_alpha) = 0;
|
||||
|
||||
/**
|
||||
* Set focused session
|
||||
*
|
||||
* Normally, the focused session is defined by the user by clicking on a
|
||||
* view. The 'focus' function allows a client to set the focus without user
|
||||
* action. However, the change of the focus is performed only is the
|
||||
* currently focused session belongs to a child or the same process as the
|
||||
* called session. This relationship is checked by comparing the session
|
||||
* labels of the currently focused session and the caller. This way, a
|
||||
* common parent can manage the focus among its child processes. But a
|
||||
* session cannot steal the focus from an unrelated session.
|
||||
*/
|
||||
virtual void focus(Genode::Capability<Session> focused) = 0;
|
||||
|
||||
/**
|
||||
* Return number of bytes needed for virtual framebuffer of specified size
|
||||
*/
|
||||
@ -108,12 +122,13 @@ struct Nitpicker::Session : Genode::Session
|
||||
GENODE_RPC(Rpc_destroy_view, void, destroy_view, View_capability);
|
||||
GENODE_RPC(Rpc_background, int, background, View_capability);
|
||||
GENODE_RPC(Rpc_mode, Framebuffer::Mode, mode);
|
||||
GENODE_RPC(Rpc_focus, void, focus, Genode::Capability<Session>);
|
||||
GENODE_RPC_THROW(Rpc_buffer, void, buffer, GENODE_TYPE_LIST(Out_of_metadata),
|
||||
Framebuffer::Mode, bool);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_framebuffer_session, Rpc_input_session,
|
||||
Rpc_create_view, Rpc_destroy_view, Rpc_background,
|
||||
Rpc_mode, Rpc_buffer);
|
||||
Rpc_mode, Rpc_buffer, Rpc_focus);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__NITPICKER_SESSION__NITPICKER_SESSION_H_ */
|
||||
|
@ -216,33 +216,33 @@ namespace Nitpicker {
|
||||
** Nitpicker session interface **
|
||||
*********************************/
|
||||
|
||||
Framebuffer::Session_capability framebuffer_session()
|
||||
Framebuffer::Session_capability framebuffer_session() override
|
||||
{
|
||||
return _nitpicker.framebuffer_session();
|
||||
}
|
||||
|
||||
Input::Session_capability input_session()
|
||||
Input::Session_capability input_session() override
|
||||
{
|
||||
return _proxy_input_cap;
|
||||
}
|
||||
|
||||
View_capability create_view(View_capability)
|
||||
View_capability create_view(View_capability) override
|
||||
{
|
||||
return _proxy_view_cap;
|
||||
}
|
||||
|
||||
void destroy_view(View_capability view)
|
||||
void destroy_view(View_capability view) override
|
||||
{
|
||||
_nitpicker.destroy_view(_nitpicker_view);
|
||||
}
|
||||
|
||||
int background(View_capability view)
|
||||
int background(View_capability view) override
|
||||
{
|
||||
/* not forwarding to real nitpicker session */
|
||||
return 0;
|
||||
}
|
||||
|
||||
Framebuffer::Mode mode()
|
||||
Framebuffer::Mode mode() override
|
||||
{
|
||||
int mode_width = (_max_width > -1) ?
|
||||
_max_width :
|
||||
@ -256,11 +256,13 @@ namespace Nitpicker {
|
||||
_nitpicker.mode().format());
|
||||
}
|
||||
|
||||
void buffer(Framebuffer::Mode mode, bool use_alpha)
|
||||
void buffer(Framebuffer::Mode mode, bool use_alpha) override
|
||||
{
|
||||
_nitpicker.buffer(mode, use_alpha);
|
||||
}
|
||||
|
||||
void focus(Capability<Session>) override { }
|
||||
|
||||
|
||||
/**********************************
|
||||
** Input::Transformer interface **
|
||||
|
@ -100,9 +100,8 @@ class Chunky_menubar : public Texture<PT>,
|
||||
Color(r / 4, g / 4, b / 4));
|
||||
|
||||
/* draw label */
|
||||
draw_label(_canvas, view_rect.center(label_size(session_label.string(),
|
||||
view_title.string())), session_label.string(),
|
||||
WHITE, view_title.string(), session_color);
|
||||
draw_label(_canvas, view_rect.center(label_size(session_label.string(), "")),
|
||||
session_label.string(), WHITE, "", session_color);
|
||||
}
|
||||
|
||||
using Menubar::state;
|
||||
|
@ -456,6 +456,8 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
|
||||
View_stack &_view_stack;
|
||||
|
||||
Mode &_mode;
|
||||
|
||||
List<View_component> _view_list;
|
||||
|
||||
/* capabilities for sub sessions */
|
||||
@ -487,6 +489,38 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
_buffer_size = 0;
|
||||
}
|
||||
|
||||
bool _focus_change_permitted() const
|
||||
{
|
||||
::Session * const focused_session = _mode.focused_session();
|
||||
|
||||
/*
|
||||
* If no session is focused, we allow any client to assign it. This
|
||||
* is useful for programs such as an initial login window that
|
||||
* should receive input events without prior manual selection via
|
||||
* the mouse.
|
||||
*
|
||||
* In principle, a client could steal the focus during time between
|
||||
* a currently focused session gets closed and before the user
|
||||
* manually picks a new session. However, in practice, the focus
|
||||
* policy during application startup and exit is managed by a
|
||||
* window manager that sits between nitpicker and the application.
|
||||
*/
|
||||
if (!focused_session)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Check if the currently focused session label belongs to a
|
||||
* session subordinated to the caller, i.e., it originated from
|
||||
* a child of the caller or from the same process. This is the
|
||||
* case if the first part of the focused session label is
|
||||
* identical to the caller's label.
|
||||
*/
|
||||
char const * const focused_label = focused_session->label().string();
|
||||
char const * const caller_label = label().string();
|
||||
|
||||
return strcmp(focused_label, caller_label, Genode::strlen(caller_label)) == 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -494,6 +528,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
*/
|
||||
Session_component(Session_label const &label,
|
||||
View_stack &view_stack,
|
||||
Mode &mode,
|
||||
Rpc_entrypoint &ep,
|
||||
Framebuffer::Session &framebuffer,
|
||||
int v_offset,
|
||||
@ -506,7 +541,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
_buffer_alloc(&buffer_alloc, ram_quota),
|
||||
_framebuffer(framebuffer),
|
||||
_framebuffer_session_component(view_stack, *this, framebuffer, *this),
|
||||
_ep(ep), _view_stack(view_stack),
|
||||
_ep(ep), _view_stack(view_stack), _mode(mode),
|
||||
_framebuffer_session_cap(_ep.manage(&_framebuffer_session_component)),
|
||||
_input_session_cap(_ep.manage(&_input_session_component)),
|
||||
_provides_default_bg(provides_default_bg)
|
||||
@ -560,13 +595,13 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
** Nitpicker session interface **
|
||||
*********************************/
|
||||
|
||||
Framebuffer::Session_capability framebuffer_session() {
|
||||
Framebuffer::Session_capability framebuffer_session() override {
|
||||
return _framebuffer_session_cap; }
|
||||
|
||||
Input::Session_capability input_session() {
|
||||
Input::Session_capability input_session() override {
|
||||
return _input_session_cap; }
|
||||
|
||||
View_capability create_view(View_capability parent_cap)
|
||||
View_capability create_view(View_capability parent_cap) override
|
||||
{
|
||||
/* lookup parent view */
|
||||
View_component *parent_view =
|
||||
@ -590,7 +625,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
return _ep.manage(view);
|
||||
}
|
||||
|
||||
void destroy_view(View_capability view_cap)
|
||||
void destroy_view(View_capability view_cap) override
|
||||
{
|
||||
View_component *vc = dynamic_cast<View_component *>(_ep.lookup_and_lock(view_cap));
|
||||
if (!vc) return;
|
||||
@ -601,7 +636,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
destroy(env()->heap(), vc);
|
||||
}
|
||||
|
||||
int background(View_capability view_cap)
|
||||
int background(View_capability view_cap) override
|
||||
{
|
||||
if (_provides_default_bg) {
|
||||
Object_pool<View_component>::Guard vc(_ep.lookup_and_lock(view_cap));
|
||||
@ -623,7 +658,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
return 0;
|
||||
}
|
||||
|
||||
Framebuffer::Mode mode()
|
||||
Framebuffer::Mode mode() override
|
||||
{
|
||||
unsigned const width = _framebuffer.mode().width();
|
||||
unsigned const height = _framebuffer.mode().height()
|
||||
@ -633,7 +668,7 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
_framebuffer.mode().format());
|
||||
}
|
||||
|
||||
void buffer(Framebuffer::Mode mode, bool use_alpha)
|
||||
void buffer(Framebuffer::Mode mode, bool use_alpha) override
|
||||
{
|
||||
/* check if the session quota suffices for the specified mode */
|
||||
if (_buffer_alloc.quota() < ram_quota(mode, use_alpha))
|
||||
@ -642,6 +677,28 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
|
||||
_framebuffer_session_component.notify_mode_change(mode, use_alpha);
|
||||
}
|
||||
|
||||
void focus(Genode::Capability<Nitpicker::Session> session_cap) override
|
||||
{
|
||||
/* check permission by comparing session labels */
|
||||
if (!_focus_change_permitted()) {
|
||||
PWRN("unauthorized focus change requesed by %s", label().string());
|
||||
return;
|
||||
}
|
||||
|
||||
/* prevent focus changes during drag operations */
|
||||
if (_mode.drag())
|
||||
return;
|
||||
|
||||
/* lookup targeted session object */
|
||||
Session_component * const session =
|
||||
session_cap.valid() ? dynamic_cast<Session_component *>(_ep.lookup_and_lock(session_cap)) : 0;
|
||||
|
||||
_mode.focused_session(session);
|
||||
|
||||
if (session)
|
||||
session->release();
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
** Buffer_provider interface **
|
||||
@ -684,6 +741,7 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
|
||||
Global_keys &_global_keys;
|
||||
Framebuffer::Mode _scr_mode;
|
||||
View_stack &_view_stack;
|
||||
Mode &_mode;
|
||||
Framebuffer::Session &_framebuffer;
|
||||
int _default_v_offset;
|
||||
|
||||
@ -712,7 +770,7 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
|
||||
bool const provides_default_bg = (strcmp(label.string(), "backdrop") == 0);
|
||||
|
||||
Session_component *session = new (md_alloc())
|
||||
Session_component(Session_label(args), _view_stack, *ep(),
|
||||
Session_component(Session_label(args), _view_stack, _mode, *ep(),
|
||||
_framebuffer, v_offset, provides_default_bg,
|
||||
stay_top, *md_alloc(), unused_quota);
|
||||
|
||||
@ -733,6 +791,7 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
_session_list.remove(session);
|
||||
_global_keys.apply_config(_session_list);
|
||||
_mode.forget(*session);
|
||||
|
||||
destroy(md_alloc(), session);
|
||||
}
|
||||
@ -744,13 +803,13 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
|
||||
*/
|
||||
Root(Session_list &session_list, Global_keys &global_keys,
|
||||
Rpc_entrypoint &session_ep, View_stack &view_stack,
|
||||
Allocator &md_alloc,
|
||||
Mode &mode, Allocator &md_alloc,
|
||||
Framebuffer::Session &framebuffer,
|
||||
int default_v_offset)
|
||||
:
|
||||
Root_component<Session_component>(&session_ep, &md_alloc),
|
||||
_session_list(session_list), _global_keys(global_keys),
|
||||
_view_stack(view_stack),
|
||||
_view_stack(view_stack), _mode(mode),
|
||||
_framebuffer(framebuffer),
|
||||
_default_v_offset(default_v_offset)
|
||||
{ }
|
||||
@ -843,7 +902,8 @@ struct Nitpicker::Main
|
||||
Genode::Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() };
|
||||
|
||||
Root<PT> np_root = { session_list, global_keys, ep.rpc_ep(), user_state,
|
||||
sliced_heap, framebuffer, Framebuffer_screen::MENUBAR_HEIGHT };
|
||||
user_state, sliced_heap, framebuffer,
|
||||
Framebuffer_screen::MENUBAR_HEIGHT };
|
||||
|
||||
Genode::Reporter pointer_reporter = { "pointer" };
|
||||
|
||||
@ -874,7 +934,7 @@ struct Nitpicker::Main
|
||||
{
|
||||
// tmp_fb = &framebuffer;
|
||||
|
||||
fb_screen->menubar.state(Menubar_state(user_state, "", "", BLACK));
|
||||
fb_screen->menubar.state(Menubar_state(user_state, "", BLACK));
|
||||
|
||||
user_state.default_background(background);
|
||||
user_state.stack(mouse_cursor);
|
||||
|
@ -21,15 +21,12 @@
|
||||
struct Menubar_state
|
||||
{
|
||||
Genode::String<128> session_label;
|
||||
Genode::String<128> view_title;
|
||||
Mode mode;
|
||||
Color session_color;
|
||||
|
||||
Menubar_state(Mode mode, char const *session_label,
|
||||
char const *view_title, Color session_color)
|
||||
Menubar_state(Mode mode, char const *session_label, Color session_color)
|
||||
:
|
||||
session_label(session_label), view_title(view_title),
|
||||
mode(mode), session_color(session_color)
|
||||
session_label(session_label), mode(mode), session_color(session_color)
|
||||
{ }
|
||||
|
||||
Menubar_state() : session_color(BLACK) { }
|
||||
|
@ -14,26 +14,26 @@
|
||||
#ifndef _MODE_H_
|
||||
#define _MODE_H_
|
||||
|
||||
class View;
|
||||
class Canvas_base;
|
||||
class Session;
|
||||
|
||||
class Mode
|
||||
{
|
||||
private:
|
||||
|
||||
bool _xray;
|
||||
bool _kill;
|
||||
bool _xray = false;
|
||||
bool _kill = false;
|
||||
|
||||
/*
|
||||
* Last clicked view. This view is receiving keyboard input, except
|
||||
* for global keys.
|
||||
* Number of currently pressed keys.
|
||||
* This counter is used to determine if the user
|
||||
* is dragging an item.
|
||||
*/
|
||||
View const *_focused_view;
|
||||
unsigned _key_cnt = 0;
|
||||
|
||||
Session *_focused_session = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
Mode(): _xray(false), _kill(false), _focused_view(0) { }
|
||||
|
||||
virtual ~Mode() { }
|
||||
|
||||
/**
|
||||
@ -42,20 +42,30 @@ class Mode
|
||||
bool xray() const { return _xray; }
|
||||
bool kill() const { return _kill; }
|
||||
bool flat() const { return !_xray && !_kill; }
|
||||
bool drag() const { return _key_cnt > 0; }
|
||||
|
||||
void leave_kill() { _kill = false; }
|
||||
void leave_kill() { _kill = false; }
|
||||
void toggle_kill() { _kill = !_kill; }
|
||||
void toggle_xray() { _xray = !_xray; }
|
||||
|
||||
View const *focused_view() const { return _focused_view; }
|
||||
void inc_key_cnt() { _key_cnt++; }
|
||||
void dec_key_cnt() { _key_cnt--; }
|
||||
|
||||
void focused_view(View const *view) { _focused_view = view; }
|
||||
bool has_key_cnt(unsigned cnt) const { return cnt == _key_cnt; }
|
||||
|
||||
Session *focused_session() { return _focused_session; }
|
||||
|
||||
virtual void focused_session(Session *session) { _focused_session = session; }
|
||||
|
||||
bool is_focused(Session const &session) const { return &session == _focused_session; }
|
||||
|
||||
/**
|
||||
* Discard all references to specified view
|
||||
*/
|
||||
virtual void forget(View const &v) {
|
||||
if (&v == _focused_view) _focused_view = 0; }
|
||||
virtual void forget(Session const &session)
|
||||
{
|
||||
if (is_focused(session)) _focused_session = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -37,12 +37,24 @@ static inline bool _mouse_button(Keycode keycode) {
|
||||
|
||||
User_state::User_state(Global_keys &global_keys, Area view_stack_size, Menubar &menubar)
|
||||
:
|
||||
View_stack(view_stack_size, *this), _global_keys(global_keys), _key_cnt(0),
|
||||
_menubar(menubar), _pointed_view(0), _input_receiver(0),
|
||||
_global_key_sequence(false)
|
||||
View_stack(view_stack_size, *this), _global_keys(global_keys), _menubar(menubar)
|
||||
{ }
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
void User_state::handle_event(Input::Event ev)
|
||||
{
|
||||
Input::Keycode const keycode = ev.keycode();
|
||||
@ -77,22 +89,22 @@ void User_state::handle_event(Input::Event ev)
|
||||
_mouse_pos = Point(ax, ay);
|
||||
|
||||
/* count keys */
|
||||
if (type == Event::PRESS) _key_cnt++;
|
||||
if (type == Event::RELEASE && _key_cnt > 0) _key_cnt--;
|
||||
if (type == Event::PRESS) Mode::inc_key_cnt();
|
||||
if (type == Event::RELEASE && Mode::drag()) Mode::dec_key_cnt();
|
||||
|
||||
View const * const pointed_view = find_view(_mouse_pos);
|
||||
View const * const pointed_view = find_view(_mouse_pos);
|
||||
Session * const pointed_session = pointed_view ? &pointed_view->session() : 0;
|
||||
|
||||
/*
|
||||
* Deliver a leave event if pointed-to session changed
|
||||
*/
|
||||
if (pointed_view && _pointed_view &&
|
||||
!pointed_view->same_session_as(*_pointed_view)) {
|
||||
if (_pointed_session && (pointed_session != _pointed_session)) {
|
||||
|
||||
Input::Event leave_ev(Input::Event::LEAVE, 0, ax, ay, 0, 0);
|
||||
_pointed_view->session().submit_input_event(leave_ev);
|
||||
_pointed_session->submit_input_event(leave_ev);
|
||||
}
|
||||
|
||||
_pointed_view = pointed_view;
|
||||
_pointed_session = pointed_session;
|
||||
|
||||
/**
|
||||
* Guard that, when 'enabled' is set to true, performs a whole-screen
|
||||
@ -101,96 +113,63 @@ void User_state::handle_event(Input::Event ev)
|
||||
struct Update_all_guard
|
||||
{
|
||||
User_state &user_state;
|
||||
bool update_menubar = false;
|
||||
bool update_views = false;
|
||||
char const *menu_title = "";
|
||||
bool update = false;
|
||||
|
||||
Update_all_guard(User_state &user_state)
|
||||
: user_state(user_state) { }
|
||||
|
||||
~Update_all_guard()
|
||||
{
|
||||
Menubar_state state(user_state, "", "", BLACK);
|
||||
|
||||
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();
|
||||
if (update)
|
||||
user_state._update_all();
|
||||
}
|
||||
} update_all_guard(*this);
|
||||
|
||||
/*
|
||||
* Handle start of a key sequence
|
||||
*/
|
||||
if (type == Event::PRESS && _key_cnt == 1) {
|
||||
if (type == Event::PRESS && Mode::has_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());
|
||||
if (_pointed_session)
|
||||
lock_out_session(*_pointed_session);
|
||||
|
||||
/* leave kill mode */
|
||||
update_all_guard.update_menubar = true;
|
||||
update_all_guard.update_views = true;
|
||||
update_all_guard.update = true;
|
||||
Mode::leave_kill();
|
||||
return;
|
||||
}
|
||||
|
||||
/* update focused view */
|
||||
if (pointed_view != focused_view() && _mouse_button(keycode)) {
|
||||
/* update focused session */
|
||||
if (pointed_session != Mode::focused_session() && _mouse_button(keycode)) {
|
||||
|
||||
bool const focus_stays_in_session =
|
||||
focused_view() && pointed_view &&
|
||||
focused_view()->belongs_to(pointed_view->session());
|
||||
update_all_guard.update = true;
|
||||
|
||||
/*
|
||||
* Update the whole screen when the focus change results in
|
||||
* changing the focus to another session.
|
||||
* Notify both the old focused session and the new one.
|
||||
*/
|
||||
if (flat() && !focus_stays_in_session) {
|
||||
update_all_guard.update_menubar = true;
|
||||
update_all_guard.update_views = true;
|
||||
if (Mode::focused_session()) {
|
||||
Input::Event unfocus_ev(Input::Event::FOCUS, 0, ax, ay, 0, 0);
|
||||
Mode::focused_session()->submit_input_event(unfocus_ev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify both the old focussed session and the new one.
|
||||
*/
|
||||
if (!focus_stays_in_session) {
|
||||
|
||||
if (focused_view()) {
|
||||
Input::Event unfocus_ev(Input::Event::FOCUS, 0, ax, ay, 0, 0);
|
||||
focused_view()->session().submit_input_event(unfocus_ev);
|
||||
}
|
||||
|
||||
if (pointed_view) {
|
||||
Input::Event focus_ev(Input::Event::FOCUS, 1, ax, ay, 0, 0);
|
||||
pointed_view->session().submit_input_event(focus_ev);
|
||||
}
|
||||
if (_pointed_session) {
|
||||
Input::Event focus_ev(Input::Event::FOCUS, 1, ax, ay, 0, 0);
|
||||
pointed_session->submit_input_event(focus_ev);
|
||||
}
|
||||
|
||||
update_all_guard.update_menubar = true;
|
||||
|
||||
if (!flat() || !focused_view() || !pointed_view)
|
||||
update_all_guard.update_views = true;
|
||||
|
||||
focused_view(pointed_view);
|
||||
focused_session(_pointed_session);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* pointed-at session.
|
||||
*
|
||||
* If we deliver a global key sequence, we temporarily change the focus
|
||||
* to the global receiver. To reflect that change, we need to update
|
||||
@ -198,20 +177,17 @@ void User_state::handle_event(Input::Event ev)
|
||||
*/
|
||||
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;
|
||||
_global_key_sequence = true;
|
||||
_input_receiver = global_receiver;
|
||||
update_all_guard.update = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* No global rule matched, so the input stream gets directed to the
|
||||
* focused view or refers to a built-in operation.
|
||||
* focused session or refers to a built-in operation.
|
||||
*/
|
||||
if (!global_receiver && focused_view()) {
|
||||
_input_receiver = &focused_view()->session();
|
||||
update_all_guard.menu_title = focused_view()->title();
|
||||
if (!global_receiver) {
|
||||
_input_receiver = Mode::focused_session();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -220,13 +196,14 @@ void User_state::handle_event(Input::Event ev)
|
||||
*/
|
||||
if (_global_keys.is_operation_key(keycode)) {
|
||||
|
||||
if (_global_keys.is_kill_key(keycode)) Mode::toggle_kill();
|
||||
if (_global_keys.is_kill_key(keycode)) {
|
||||
Mode::toggle_kill();
|
||||
_input_receiver = 0;
|
||||
}
|
||||
|
||||
if (_global_keys.is_xray_key(keycode)) Mode::toggle_xray();
|
||||
|
||||
update_all_guard.update_menubar = true;
|
||||
update_all_guard.update_views = true;
|
||||
|
||||
_input_receiver = 0;
|
||||
update_all_guard.update = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,22 +214,22 @@ void User_state::handle_event(Input::Event ev)
|
||||
|
||||
if (type == Event::MOTION || type == Event::WHEEL) {
|
||||
|
||||
if (_key_cnt == 0) {
|
||||
if (Mode::has_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.
|
||||
* In flat mode, we deliver motion events to the pointed-at
|
||||
* session. In xray mode, we deliver motion events only to the
|
||||
* focused session.
|
||||
*/
|
||||
if (flat() || (xray() && focused_view() == pointed_view))
|
||||
if (pointed_view)
|
||||
pointed_view->session().submit_input_event(ev);
|
||||
if (flat() || (xray() && Mode::focused_session() == pointed_session))
|
||||
if (pointed_session)
|
||||
pointed_session->submit_input_event(ev);
|
||||
|
||||
} else if (_input_receiver)
|
||||
_input_receiver->submit_input_event(ev);
|
||||
}
|
||||
|
||||
/* deliver press/release event to session with focused view */
|
||||
/* deliver press/release event to focused session */
|
||||
if (type == Event::PRESS || type == Event::RELEASE)
|
||||
if (_input_receiver)
|
||||
_input_receiver->submit_input_event(ev);
|
||||
@ -260,13 +237,11 @@ void User_state::handle_event(Input::Event ev)
|
||||
/*
|
||||
* Detect end of global key sequence
|
||||
*/
|
||||
if (ev.type() == Event::RELEASE && _key_cnt == 0 && _global_key_sequence) {
|
||||
if (ev.type() == Event::RELEASE && Mode::has_key_cnt(0) && _global_key_sequence) {
|
||||
|
||||
_input_receiver = focused_view() ? &focused_view()->session() : 0;
|
||||
_input_receiver = Mode::focused_session();
|
||||
|
||||
update_all_guard.menu_title = focused_view() ? focused_view()->title() : "";
|
||||
update_all_guard.update_menubar = true;
|
||||
update_all_guard.update_views = true;
|
||||
update_all_guard.update = true;
|
||||
|
||||
_global_key_sequence = false;
|
||||
}
|
||||
@ -277,17 +252,23 @@ void User_state::handle_event(Input::Event ev)
|
||||
** Mode interface **
|
||||
********************/
|
||||
|
||||
void User_state::forget(View const &view)
|
||||
void User_state::forget(Session const &session)
|
||||
{
|
||||
if (focused_view() == &view) {
|
||||
Mode::forget(view);
|
||||
_menubar.state(Menubar_state(*this, "", "", BLACK));
|
||||
update_all_views();
|
||||
}
|
||||
if (_input_receiver && view.belongs_to(*_input_receiver))
|
||||
_input_receiver = 0;
|
||||
Mode::forget(session);
|
||||
|
||||
if (_pointed_view == &view)
|
||||
_pointed_view = find_view(_mouse_pos);
|
||||
if (_pointed_session == &session) {
|
||||
View * const pointed_view = find_view(_mouse_pos);
|
||||
_pointed_session = pointed_view ? &pointed_view->session() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void User_state::focused_session(Session *session)
|
||||
{
|
||||
Mode::focused_session(session);
|
||||
|
||||
if (!_global_key_sequence)
|
||||
_input_receiver = session;
|
||||
|
||||
_update_all();
|
||||
}
|
||||
|
@ -32,17 +32,10 @@ class User_state : public Mode, public View_stack
|
||||
*/
|
||||
Global_keys &_global_keys;
|
||||
|
||||
/*
|
||||
* Number of currently pressed keys.
|
||||
* This counter is used to determine if the user
|
||||
* is dragging an item.
|
||||
*/
|
||||
unsigned _key_cnt;
|
||||
|
||||
/*
|
||||
* Menubar to display trusted labeling information
|
||||
* according to the current Mitpicker mode and the
|
||||
* focused view.
|
||||
* focused session.
|
||||
*/
|
||||
Menubar &_menubar;
|
||||
|
||||
@ -52,19 +45,21 @@ class User_state : public Mode, public View_stack
|
||||
Point _mouse_pos;
|
||||
|
||||
/*
|
||||
* Currently pointed-at view
|
||||
* Currently pointed-at session
|
||||
*/
|
||||
View const *_pointed_view;
|
||||
Session *_pointed_session = nullptr;
|
||||
|
||||
/*
|
||||
* Session that receives the current stream of input events
|
||||
*/
|
||||
Session *_input_receiver;
|
||||
Session *_input_receiver = nullptr;
|
||||
|
||||
/*
|
||||
* True while a global key sequence is processed
|
||||
*/
|
||||
bool _global_key_sequence;
|
||||
bool _global_key_sequence = false;
|
||||
|
||||
void _update_all();
|
||||
|
||||
public:
|
||||
|
||||
@ -89,7 +84,8 @@ class User_state : public Mode, public View_stack
|
||||
/**
|
||||
* Mode interface
|
||||
*/
|
||||
void forget(View const &) override;
|
||||
void forget(Session const &) override;
|
||||
void focused_session(Session *) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -80,8 +80,7 @@ void View::frame(Canvas_base &canvas, Mode const &mode) const
|
||||
void View::draw(Canvas_base &canvas, Mode const &mode) const
|
||||
{
|
||||
/* is this the currently focused view? */
|
||||
bool const view_is_focused = mode.focused_view()
|
||||
&& mode.focused_view()->belongs_to(_session);
|
||||
bool const session_is_focused = mode.is_focused(_session);
|
||||
|
||||
Color const frame_color = _session.color();
|
||||
|
||||
@ -89,7 +88,7 @@ void View::draw(Canvas_base &canvas, Mode const &mode) const
|
||||
* Use dimming in x-ray and kill mode, but do not dim the focused view in
|
||||
* x-ray mode.
|
||||
*/
|
||||
Texture_painter::Mode const op = mode.flat() || (mode.xray() && view_is_focused)
|
||||
Texture_painter::Mode const op = mode.flat() || (mode.xray() && session_is_focused)
|
||||
? Texture_painter::SOLID : Texture_painter::MIXED;
|
||||
|
||||
Rect const view_rect = abs_geometry();
|
||||
|
@ -140,11 +140,7 @@ class View : public Same_buffer_list_elem,
|
||||
*/
|
||||
virtual int frame_size(Mode const &mode) const
|
||||
{
|
||||
if (mode.focused_view()
|
||||
&& mode.focused_view()->belongs_to(_session))
|
||||
return 5;
|
||||
|
||||
return 3;
|
||||
return mode.is_focused(_session) ? 5 : 3;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,11 +40,10 @@ static View const *last_stay_top_view(View const *view)
|
||||
template <typename VIEW>
|
||||
VIEW *View_stack::_next_view(VIEW &view) const
|
||||
{
|
||||
Session * const active_session = _mode.focused_view() ?
|
||||
&_mode.focused_view()->session() : 0;
|
||||
Session * const focused_session = _mode.focused_session();
|
||||
|
||||
View * const active_background = active_session ?
|
||||
active_session->background() : 0;
|
||||
View * const active_background = focused_session ?
|
||||
focused_session->background() : 0;
|
||||
|
||||
for (VIEW *next_view = &view; ;) {
|
||||
|
||||
@ -298,16 +297,5 @@ void View_stack::remove_view(View const &view, bool redraw)
|
||||
/* exclude view from view stack */
|
||||
_views.remove(&view);
|
||||
|
||||
/*
|
||||
* Reset focused and pointed-at view if necessary
|
||||
*
|
||||
* Thus must be done after calling '_views.remove' because the new focused
|
||||
* pointer is determined by traversing the view stack. If the to-be-removed
|
||||
* view would still be there, we would re-assign the old pointed-to view as
|
||||
* the current one, resulting in a dangling pointer right after the view
|
||||
* gets destructed by the caller of 'removed_view'.
|
||||
*/
|
||||
_mode.forget(view);
|
||||
|
||||
_dirty_rect.mark_as_dirty(rect);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user