genode/repos/gems/src/app/floating_window_layouter/focus_history.h

124 lines
2.6 KiB
C++

/*
* \brief Focus history, used for swiching between recently focused windows
* \author Norman Feske
* \date 2016-02-02
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _FOCUS_HISTORY_H_
#define _FOCUS_HISTORY_H_
/* Genode includes */
#include <util/list.h>
namespace Floating_window_layouter { class Focus_history; }
class Floating_window_layouter::Focus_history
{
public:
struct Entry : Genode::List<Entry>::Element
{
Focus_history &focus_history;
Window_id const window_id;
Entry(Focus_history &focus_history, Window_id window_id);
inline ~Entry();
};
private:
Genode::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) {
PWRN("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();
}
};
Floating_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);
}
Floating_window_layouter::Focus_history::Entry::~Entry()
{
focus_history._remove_if_present(*this);
}
#endif /* _FOCUS_HISTORY_H_ */