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:
Norman Feske 2014-06-04 15:58:49 +02:00
parent d22cddd1e8
commit 24869bd3ff
12 changed files with 231 additions and 185 deletions

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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 **

View File

@ -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;

View File

@ -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);

View File

@ -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) { }

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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();

View File

@ -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;
}
/**

View File

@ -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);
}