1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
// -*- mode: c++ -*-
//
// This file is part of libyacurs.
// Copyright (C) 2013 Rafael Ostertag
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
//
// $Id$
#ifndef EVENTQUEUE_H
#define EVENTQUEUE_H 1
#include <signal.h>
#include <list>
#include <map>
#include <queue>
#include "area.h"
#include "event.h"
#include "eventconnector.h"
#include "lockscreen.h"
#include "sigaction.h"
namespace YACURS {
/**
* @ingroup Event
*
* The Event Queue dispatches Events submitted to the respective
* connectors.
*
* It is started by calling EventQueue::run(). It will then wait for
* keyboard input or Unix Signals and dispatch, aka. `emit`, the Event
* to all Event Connectors for the given event.
*
* The Event Queue will terminate upon submission of @c EVT_QUIT.
*
* Libyacurs counts on the order events are connected, so that the
* EVT_REFRESH/EVT_DOUPDATE event sequence will call the last
* connected event handler last, thus ensuring the update will not
* suddenly display a main window before an recently opened dialog,
* for instance.
*
* EventQueue will also emit events for global conditions, such as
* screen refresh request when pressing Ctrl-L.
*
* @section Unix Signals
*
* EventQueue will emit events on following Unix Signals
*
* - SIGWINCH (@c EVT_SIGWINCH)
* - SIGALRM (@c EVT_SIGALRM)
* - SIGUSR1 (@c EVT_SIGUSR1)
* - SIGUSR2 (@c EVT_SIGUSR2)
* - SIGINT (@c EVT_SIGINT)
*
* @section Terminal Resize
*
* If supported by the curses implementation, it consists of following
* event sequence:
*
* - EVT_TERMRESETUP (handled in Curses)
* - EVT_SIGWINCH (only classes derived from WindowBase should connect.)
* - EVT_REFRESH
* - EVT_DOUPDATE
*
* @section Complete Refresh
*
* A complete refresh is initiated by pressing Ctrl-L or KEY_REFRESH
* on the keyboard. It consists of following event sequence:
*
* - EVT_FORCEREFRESH
* - EVT_REFRESH
* - EVT_DOUPDATE
*
*/
class EventQueue {
private:
/// Used by blocksignal()/unblocksignal()
static sigset_t block_sigmask;
/// Used by blocksignal()/unblocksignal()
static sigset_t tmp_old_sigmask;
/// Used by setup_signal()/restore_signal()
static sigset_t old_sigmask;
static INTERNAL::Sigaction* sigwinch;
static INTERNAL::Sigaction* sigalrm;
static INTERNAL::Sigaction* sigusr1;
static INTERNAL::Sigaction* sigusr2;
static INTERNAL::Sigaction* sigint;
static INTERNAL::Sigaction* sigterm;
static INTERNAL::Sigaction* sigquit;
static INTERNAL::Sigaction* sigtstp;
static INTERNAL::Sigaction* sigcont;
static INTERNAL::Sigaction* siginfo;
static bool signal_blocked;
static std::queue<Event*> evt_queue;
/**
* EventConnectors are not removed immediately, instead remove
* requests are queue up for processing later.
*/
static std::list<EventConnectorBase*> evtconn_rem_request;
static std::map<EventType, std::list<EventConnectorBase*> > evtconn_map;
/**
* LockScreen used on timeout
*/
static LockScreen* _lockscreen;
/**
* Timeout for keyboard input.
*
* If for _timeout seconds no key (event) is pressed
* (received), the lock screen kicks in, if any.
*/
static unsigned int _timeout;
static void setup_signal();
static void restore_signal();
#ifdef SA_SIGINFO
static void signal_handler(int signo, siginfo_t* info, void* d);
#else
static void signal_handler(int signo);
#endif // SA_SIGINFO
static void blocksignal();
static void unblocksignal();
static void proc_rem_request();
static void timeout_handler(Event& e);
public:
/**
* Connect an event connector.
*
* Connect a (member) function to an Event. Please note, that
* only one function per object and Event can be connected. If
* two or more member functions of the same object will be
* connected to a single Event, each call to connect
* overwrites previous connections.
*
* @note the last event connector registered will be called
* first.
*
* @note any pending disconnect will be cancelled and the
* connector unsuspended.
*
* @param ec event connector to register.
*/
static void connect_event(const EventConnectorBase& ec);
/**
* Disconnect an event connector.
*
* Disconnect the specified event connector.
*
* @note disconnecting does not immediately remove the
* connector. Instead it will be queued up for later
* removal. Until it is finally removed, it will be suspended.
* @note any pending removal will be cancelled by a
* (re-)connect and the connector will be unsuspended.
*
* @param ec event connector to disconnect.
*/
static void disconnect_event(const EventConnectorBase& ec);
/// Suspend event
static void suspend(const EventConnectorBase& ec);
/// Suspend all events equal to a given event
static void suspend_all(const EventType t);
/// Suspend all events except the one given
static void suspend_except(const EventConnectorBase& ec);
/// Unsuspend event
static void unsuspend(const EventConnectorBase& ec);
/// Unsuspend all events equal to a given event
static void unsuspend_all(const EventType t);
/// Unsuspend all events except the one given
static void unsuspend_except(const EventConnectorBase& ec);
/// Add an event to the qeue
static void submit(const EventType et);
static void submit(const Event& ev);
static void run();
static void cleanup();
static void lock_screen(LockScreen* ls);
static LockScreen* lock_screen();
static void timeout(unsigned int t);
static unsigned int timeout();
static void _dump_event_conn_map();
};
} // namespace YACURS
#endif // EVENTQUEUE_H
|