genode/repos/gems/src/app/window_layouter/focus_history.h
Norman Feske a973d9902b gems: flexible window layouter
This commit replaces the former floating_window_layouter with a new
window_layouter component that supports the subdivision of screen space
into columns and rows, the concept of layers, and the principle ability
to store window layout information across reboots. The latter is
accomplished by reflecting the component's internal state as a 'rules'
report to the outside.

Fixes #3031
2018-11-16 14:53:20 +01:00

124 lines
2.5 KiB
C++

/*
* \brief Focus history, used for swiching between recently focused windows
* \author Norman Feske
* \date 2016-02-02
*/
/*
* Copyright (C) 2016-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 _FOCUS_HISTORY_H_
#define _FOCUS_HISTORY_H_
/* Genode includes */
#include <util/list.h>
namespace Window_layouter { class Focus_history; }
class Window_layouter::Focus_history
{
public:
struct Entry : List<Entry>::Element
{
Focus_history &focus_history;
Window_id const window_id;
Entry(Focus_history &focus_history, Window_id window_id);
inline ~Entry();
};
private:
List<Entry> _entries { };
Entry *_lookup(Window_id window_id)
{
for (Entry *e = _entries.first(); e; e = e->next())
if (e->window_id == window_id)
return e;
return nullptr;
}
void _remove_if_present(Entry &entry)
{
_entries.remove(&entry);
}
public:
void focus(Window_id window_id)
{
Entry * const entry = _lookup(window_id);
if (!entry) {
warning("unexpected lookup failure for focus history entry");
return;
}
_remove_if_present(*entry);
/* insert entry at the beginning (most recently focused) */
_entries.insert(entry);
}
Window_id next(Window_id window_id)
{
Entry * const first = _entries.first();
if (!first)
return Window_id();
Entry * const entry = _lookup(window_id);
if (!entry)
return Window_id();
Entry * const next = entry->next();
return next ? next->window_id : first->window_id;
}
Window_id prev(Window_id window_id)
{
Entry *curr = _entries.first();
if (!curr)
return Window_id();
/* if argument refers to the first window, cycle to the last one */
if (curr->window_id == window_id) {
/* determine last list element */
for (; curr->next(); curr = curr->next());
return curr->window_id;
}
/* traverse list, looking for the predecessor of the window */
for (; curr->next(); curr = curr->next())
if (curr->next()->window_id == window_id)
return curr->window_id;
return Window_id();
}
};
Window_layouter::Focus_history::Entry::Entry(Focus_history &focus_history,
Window_id window_id)
:
focus_history(focus_history), window_id(window_id)
{
focus_history._entries.insert(this);
}
Window_layouter::Focus_history::Entry::~Entry()
{
focus_history._remove_if_present(*this);
}
#endif /* _FOCUS_HISTORY_H_ */