20#include "pedigree/kernel/LockGuard.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/compiler.h"
23#include "pedigree/kernel/machine/InputManager.h"
24#include "pedigree/kernel/process/Scheduler.h"
25#include "pedigree/kernel/process/TerminationDeferral.h"
26#include "pedigree/kernel/process/Thread.h"
27#include "pedigree/kernel/processor/Processor.h"
28#include "pedigree/kernel/processor/ProcessorInformation.h"
29#include "pedigree/kernel/utilities/Iterator.h"
30#include "pedigree/kernel/utilities/utility.h"
33#define MOUSE_REDUCE_FACTOR 1
37#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
38InputManager::CallbackPinHook InputManager::m_CallbackPinHook =
nullptr;
49 m_pCallbackDispatchThread(nullptr)
63 reinterpret_cast<void*
>(
this));
64 m_pThread->setName(
"InputManager worker thread");
66 WARNING(
"InputManager: No thread support, no worker thread will be active");
89 FATAL(
"InputManager shut down with a pinned callback.");
99 for (
auto item : callbacks) {
102 for (
auto notification : notifications) {
110 note->data.key.key = key;
118 note->data.rawkey.
scancode = scancode;
119 note->data.rawkey.
keyUp = bKeyUp;
126 note->type = MachineKey;
127 note->data.machinekey.
scancode = scancode;
128 note->data.machinekey.
keyUp = bKeyUp;
135 relX /= MOUSE_REDUCE_FACTOR;
136 relY /= MOUSE_REDUCE_FACTOR;
137 relZ /= MOUSE_REDUCE_FACTOR;
141 note->data.pointy.relx = relX;
142 note->data.pointy.rely = relY;
143 note->data.pointy.relz = relZ;
144 for (
size_t i = 0; i < 64; i++)
145 note->data.pointy.buttons[i] =
static_cast<uint64_t
>(buttonBitmap) & (uint64_t{1} << i);
151 uint32_t buttonBitmap) {
153 note->type = AbsoluteMouse;
154 note->data.absolute.x = x > 0x7fff ? 0x7fff : x;
155 note->data.absolute.y = y > 0x7fff ? 0x7fff : y;
156 note->data.absolute.wheel = wheel;
157 for (
size_t i = 0; i < 64; i++)
158 note->data.absolute.buttons[i] =
static_cast<uint64_t
>(buttonBitmap) & (uint64_t{1} << i);
165 note->type = Joystick;
166 note->data.pointy.relx = relX;
167 note->data.pointy.rely = relY;
168 note->data.pointy.relz = relZ;
169 for (
size_t i = 0; i < 64; i++)
170 note->data.pointy.buttons[i] =
static_cast<uint64_t
>(buttonBitmap) & (uint64_t{1} << i);
178 bool accepted =
false;
182 if (note->type == Mouse) {
184 if (queued->type != Mouse) {
188 queued->data.pointy.relx += note->data.pointy.relx;
189 queued->data.pointy.rely += note->data.pointy.rely;
190 queued->data.pointy.relz += note->data.pointy.relz;
193 for (
size_t i = 0; i < 64; ++i)
194 queued->data.pointy.buttons[i] = note->data.pointy.buttons[i];
198 }
else if (note->type == AbsoluteMouse) {
203 bool sameButtons = latest && latest->type == AbsoluteMouse;
204 for (
size_t i = 0; i < 64 && sameButtons; ++i) {
205 sameButtons = latest->data.absolute.buttons[i] == note->data.absolute.buttons[i];
208 latest->data.absolute.x = note->data.absolute.x;
209 latest->data.absolute.y = note->data.absolute.y;
210 latest->data.absolute.wheel += note->data.absolute.wheel;
227 if (note->type ==
Key) {
228 WARNING(
"InputManager: dropping key event with no consumer");
236 struct SynchronousCallback {
244 if (item && (item->filter & note->type)) {
245 callbacks.
pushBack({item->func, item->meta});
250 for (
auto callback : callbacks) {
251 note->meta = callback.meta;
252 callback.func(*note);
264 item->
func = callback;
281 removeCallbacks(callback, meta);
286 if ((callback == (*it)->func) && (meta == (*it)->meta)) {
299void InputManager::removeCallbacks(callback_t callback,
void* meta) {
309 CallbackItem* item = *it;
310 const bool matches = item->func == callback && item->meta == meta;
316 item->enabled =
false;
318 if (callbackContext) {
319 if (!item->inFlight) {
326 if (!item->draining) {
327 item->deferredRemoval =
true;
332 item->deferredRemoval =
false;
333 item->draining =
true;
341 for (
auto item : deleteNow) {
344 for (
auto item : drain) {
349void InputManager::drainCallback(CallbackItem* item) {
351 bool complete =
false;
353 auto waitGuard = item->drainWaiters.acquire();
355 if (!item->inFlight) {
360 const WaitQueue::WakeReason reason =
362 reinterpret_cast<uintptr_t
>(item->func));
372 bool deleteItem =
false;
374 if (!item->removers) {
375 FATAL(
"InputManager callback remover underflow.");
378 if (!item->removers) {
420 if (item && item->enabled && (item->filter & note->type)) {
432 if (!callbacks.
count()) {
433 if (note->type ==
Key) {
434 WARNING(
"InputManager: dropping key event with no consumer");
442 for (
auto item : callbacks) {
444 void* meta =
nullptr;
455#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
456 CallbackPinHook hook = __atomic_load_n(&m_CallbackPinHook, __ATOMIC_ACQUIRE);
466 bool deleteDeferred =
false;
468 auto completionGuard = item->drainWaiters.acquire();
469 bool wakeDrainer =
false;
474 if (!item->inFlight) {
475 FATAL(
"InputManager callback pin underflow.");
478 if (!item->inFlight) {
479 wakeDrainer = item->draining;
480 deleteDeferred = item->deferredRemoval;
481 if (deleteDeferred) {
497 if (deleteDeferred) {
510#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
511void InputManager::setCallbackPinHook(CallbackPinHook hook) {
512 __atomic_store_n(&m_CallbackPinHook, hook, __ATOMIC_RELEASE);
::Iterator< T, node_t > Iterator
static ProcessorInformation & information()
static Scheduler & instance()
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
bool acquire(bool recurse=false, bool safe=true)
@ Continue
No unwind necessary, carry on as normal.
A vector / dynamic array.
void pushBack(const T &value)