diff --git a/driver/input/consts.h b/driver/input/consts.h new file mode 100644 index 0000000..43f985a --- /dev/null +++ b/driver/input/consts.h @@ -0,0 +1,163 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// Key codes of the IBM PC (American) keyboard +typedef enum { + input_Key_Unknown = -1, // Unhandled key + input_Key_A = 0, // The A key + input_Key_B, // The B key + input_Key_C, // The C key + input_Key_D, // The D key + input_Key_E, // The E key + input_Key_F, // The F key + input_Key_G, // The G key + input_Key_H, // The H key + input_Key_I, // The I key + input_Key_J, // The J key + input_Key_K, // The K key + input_Key_L, // The L key + input_Key_M, // The M key + input_Key_N, // The N key + input_Key_O, // The O key + input_Key_P, // The P key + input_Key_Q, // The Q key + input_Key_R, // The R key + input_Key_S, // The S key + input_Key_T, // The T key + input_Key_U, // The U key + input_Key_V, // The V key + input_Key_W, // The W key + input_Key_X, // The X key + input_Key_Y, // The Y key + input_Key_Z, // The Z key + input_Key_Num0, // The 0 key + input_Key_Num1, // The 1 key + input_Key_Num2, // The 2 key + input_Key_Num3, // The 3 key + input_Key_Num4, // The 4 key + input_Key_Num5, // The 5 key + input_Key_Num6, // The 6 key + input_Key_Num7, // The 7 key + input_Key_Num8, // The 8 key + input_Key_Num9, // The 9 key + input_Key_Escape, // The Escape key + input_Key_LControl, // The left Control key + input_Key_LShift, // The left Shift key + input_Key_LAlt, // The left Alt key + input_Key_LSuper, // The left Super (Windows) key + input_Key_RControl, // The right Control key + input_Key_RShift, // The right Shift key + input_Key_RAlt, // The right Alt key + input_Key_RSuper, // The right Super (Windows) key + input_Key_Menu, // The Menu key + input_Key_LBracket, // The [ key + input_Key_RBracket, // The ] key + input_Key_Semicolon, // The ; key + input_Key_Comma, // The , key + input_Key_Period, // The . key + input_Key_Quote, // The ' key + input_Key_Slash, // The / key + input_Key_Backslash, // The \ key + input_Key_Tilde, // The ~ key + input_Key_Equal, // The = key + input_Key_Hyphen, // The - key (hyphen) + input_Key_Space, // The Space key + input_Key_Enter, // The Enter/Return keys + input_Key_Backspace, // The Backspace key + input_Key_Tab, // The Tabulation key + input_Key_PageUp, // The Page up key + input_Key_PageDown, // The Page down key + input_Key_End, // The End key + input_Key_Home, // The Home key + input_Key_Insert, // The Insert key + input_Key_Delete, // The Delete key + input_Key_Add, // The + key + input_Key_Subtract, // The - key (minus, usually from numpad) + input_Key_Multiply, // The * key + input_Key_Divide, // The / key + input_Key_Left, // Left arrow + input_Key_Right, // Right arrow + input_Key_Up, // Up arrow + input_Key_Down, // Down arrow + input_Key_Numpad0, // The numpad 0 key + input_Key_Numpad1, // The numpad 1 key + input_Key_Numpad2, // The numpad 2 key + input_Key_Numpad3, // The numpad 3 key + input_Key_Numpad4, // The numpad 4 key + input_Key_Numpad5, // The numpad 5 key + input_Key_Numpad6, // The numpad 6 key + input_Key_Numpad7, // The numpad 7 key + input_Key_Numpad8, // The numpad 8 key + input_Key_Numpad9, // The numpad 9 key + input_Key_F1, // The F1 key + input_Key_F2, // The F2 key + input_Key_F3, // The F3 key + input_Key_F4, // The F4 key + input_Key_F5, // The F5 key + input_Key_F6, // The F6 key + input_Key_F7, // The F7 key + input_Key_F8, // The F8 key + input_Key_F9, // The F9 key + input_Key_F10, // The F10 key + input_Key_F11, // The F11 key + input_Key_F12, // The F12 key + input_Key_F13, // The F13 key + input_Key_F14, // The F14 key + input_Key_F15, // The F15 key + input_Key_Pause, // The Pause key + + input_Key_Count, // Keep last - the total number of keyboard keys +} input_Key; + + +typedef enum { + input_MouseButton_Left, // Left mouse button + input_MouseButton_Right, // Right mouse button + input_MouseButton_Middle, // Middle (scrollwheel) button + input_MouseButton_4, // 4th mouse button + input_MouseButton_5, // 5th mouse button + + input_MouseButton_Count // Keep last - the number of mouse buttons +} input_MouseButton; + + +typedef enum { + input_EventType_MouseMoved, // Mouse has been moved (data event.MouseMove) + input_EventType_MouseButtonPressed, // Mouse button has been pressed (data event.MouseButton) + input_EventType_MouseButtonReleased, // Mouse button has been released (data event.MouseButton) + input_EventType_KeyPressed, // Keyboard key has been pressed (data event.Key) + input_EventType_KeyReleased, // Keyboard key has been released (data event.Key) + input_EventType_Count // Number of the event types +} input_EventType; + + +typedef struct { + input_EventType Type; + + union { + struct { + int X, Y; // New position of the mouse + } MouseMove; + + struct { + input_MouseButton Button; // Button + int X, Y; // Position of the mouse + } MouseButton; + + struct { + input_Key Key; // Key code + bool Control, Shift, Alt, Super; // Is the modifier keys pressed? + } Key; + }; +} input_Event; + + +#ifdef __cplusplus +} +#endif diff --git a/driver/input/input.c b/driver/input/input.c new file mode 100644 index 0000000..ccab4cf --- /dev/null +++ b/driver/input/input.c @@ -0,0 +1,53 @@ + +#include "input.h" +#include "source.h" +#include "internal.h" +#include "../../util/minmax.h" +#include + + +int __input_CursorX, __input_CursorY; +int __input_DesktopWidth, __input_DesktopHeight; +uint64_t __input_KeyMask[input_Key_Count / 64 + 1], __input_MouseMask[input_MouseButton_Count / 64 + 1]; +// FIXME you're supposed to disable interrupt/lock mutex accessing these variables + + +bool input_KeyPressed(input_Key key) { + return __input_KeyMask[key / 64] & (1ull << key % 64); +} + +bool input_MousePressed(input_MouseButton key) { + return __input_MouseMask[key / 64] & (1ull << key & 64); +} + +void input_MousePosition(int *x, int *y) { + *x = __input_CursorX; + *y = __input_CursorY; +} + +void input_DesktopSize(int *x, int *y) { + *x = __input_DesktopWidth; + *y = __input_DesktopHeight; +} + +void input_source_PressKey(input_Key key) { __input_KeyMask[key / 64] |= (1ull << key % 64); } +void input_source_ReleaseKey(input_Key key) { __input_KeyMask[key / 64] &= ~(1ull << key % 64); } + +void input_source_PressMouse(input_MouseButton key) { __input_MouseMask[key / 64] |= (1ull << key & 64); } +void input_source_ReleaseMouse(input_MouseButton key) { __input_MouseMask[key / 64] &= ~(1ull << key & 64); } + +void input_source_MoveMouse(int x, int y) { + __input_CursorX = intminmax(__input_CursorX + x, 0, __input_DesktopWidth); + __input_CursorY = intminmax(__input_CursorY + y, 0, __input_DesktopHeight); +} +void input_source_PositionMouse(int x, int y) { + __input_CursorX = intminmax(x, 0, __input_DesktopWidth); + __input_CursorY = intminmax(y, 0, __input_DesktopHeight); +} + +void input_source_SetDesktopSize(int x, int y) { + __input_DesktopWidth = x; + __input_DesktopHeight = y; + __input_CursorX = intminmax(__input_CursorX, 0, __input_DesktopWidth); + __input_CursorY = intminmax(__input_CursorY, 0, __input_DesktopHeight); +} diff --git a/driver/input/input.h b/driver/input/input.h new file mode 100644 index 0000000..38676b4 --- /dev/null +++ b/driver/input/input.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include "consts.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// input_KeyPressed tells if a given key is present and pressed. +bool input_KeyPressed(input_Key key); + +// input_MousePressed tells if a given mouse button is pressed. +bool input_MousePressed(input_MouseButton key); + +// input_MouseButton returns the mouse position. +void input_MousePosition(int *x, int *y); + +// input_DesktopSize returns the size of the rectangular area to which +// the mouse cursor is bounded. +// +// Don't use this to do anything not related to mouse position, e.g., get the screen size. +void input_DesktopSize(int *x, int *y); + + +#ifdef __cplusplus +} +#endif diff --git a/driver/input/internal.h b/driver/input/internal.h new file mode 100644 index 0000000..a0df6cc --- /dev/null +++ b/driver/input/internal.h @@ -0,0 +1,9 @@ +#pragma once + +#include "consts.h" +#include "stdint.h" + + +extern int __input_CursorX, __input_CursorY; +extern int __input_DesktopWidth, __input_DesktopHeight; +extern uint64_t __input_KeyMask[input_Key_Count / 64 + 1], __input_MouseMask[input_MouseButton_Count / 64 + 1]; // bitsets for keys and mouse buttons diff --git a/driver/input/source.h b/driver/input/source.h new file mode 100644 index 0000000..edb0293 --- /dev/null +++ b/driver/input/source.h @@ -0,0 +1,29 @@ +#pragma once + +// This file is intended only for input source devices like a PS/2 driver. + +#include +#include "consts.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +void input_source_PressKey(input_Key key); +void input_source_ReleaseKey(input_Key key); + +void input_source_PressMouse(input_MouseButton key); +void input_source_ReleaseMouse(input_MouseButton key); + +void input_source_MoveMouse(int x, int y); // Moves mouse cursor by a relative amount +void input_source_PositionMouse(int x, int y); // Moves mouse cursor to an absolute position + +// input_source_SetDesktopSize sets the size of the rectangular area to which +// the mouse cursor is bounded. +void input_source_SetDesktopSize(int x, int y); + + +#ifdef __cplusplus +} +#endif diff --git a/graphics/graphics.c b/graphics/graphics.c index 11d7c7a..25986a2 100644 --- a/graphics/graphics.c +++ b/graphics/graphics.c @@ -4,6 +4,8 @@ #include "color.h" #include "internal_helpers.h" #include "unifont.h" +#include "../driver/input/input.h" +#include "../driver/input/source.h" #include "../runtime/stdio.h" #include "../util/minmax.h" #include "../util/stack.h" @@ -40,7 +42,6 @@ uint32_t graphics_Doublebuffer[2048 * 1024]; #define MOUSE_OVERLAY_SIZE 32 xcursor_ChunkHeader_Image *graphics_Cursor; -int graphics_MouseCursorX, graphics_MouseCursorY; static int __lastMouseX, __lastMouseY; // Last of mouse **IMAGE** position static int __lastMouseSizeX, __lastMouseSizeY; static uint32_t __mouseOverlay[MOUSE_OVERLAY_SIZE * MOUSE_OVERLAY_SIZE]; @@ -121,8 +122,8 @@ void graphics_Init() { graphics_Framebuffer = (void *)graphics_Doublebuffer; graphics_CursorX = graphics_CursorY = 0; - graphics_MouseCursorX = graphics_SystemVideoMode.Width / 2; - graphics_MouseCursorY = graphics_SystemVideoMode.Height / 2; + input_source_SetDesktopSize(graphics_SystemVideoMode.Width, graphics_SystemVideoMode.Height); + input_source_PositionMouse(graphics_SystemVideoMode.Width / 2, graphics_SystemVideoMode.Height / 2); stack_InitBuffered(__invalidated, __invalidated_buffer, sizeof(__invalidated_buffer)); __invalidated_screen = false; @@ -178,8 +179,11 @@ static void __graphics__UpdateMouse() { if (!graphics_Cursor) return; - int imgX = graphics_MouseCursorX - graphics_Cursor->xhot + 1; - int imgY = graphics_MouseCursorY - graphics_Cursor->yhot + 1; + int x, y; + input_MousePosition(&x, &y); + + int imgX = x - graphics_Cursor->xhot + 1; + int imgY = y - graphics_Cursor->yhot + 1; if (imgX != __lastMouseX || imgY != __lastMouseY || graphics_Cursor->width != __lastMouseSizeX || graphics_Cursor->height != __lastMouseSizeY) { // moved __graphics_CopyBuffer32( __mouseOverlay, 0, 0, MOUSE_OVERLAY_SIZE, MOUSE_OVERLAY_SIZE, diff --git a/graphics/graphics.h b/graphics/graphics.h index 3cf10da..0c63e99 100644 --- a/graphics/graphics.h +++ b/graphics/graphics.h @@ -29,7 +29,6 @@ extern uint64_t graphics_FramebufferSize; extern HelosGraphics_Mode graphics_SystemVideoMode; // system video mode extern xcursor_ChunkHeader_Image *graphics_Cursor; // mouse cursor image -extern int graphics_MouseCursorX, graphics_MouseCursorY; // Init() must be called prior to ExitBootServices() diff --git a/kernel/kmain.c b/kernel/kmain.c index 77689a5..1b2bacb 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -11,6 +11,7 @@ #include "../interrupt/syscall.h" #include "../driver/irq/pic/pic.h" #include "../driver/irq/pic/ps2/ps2.h" +#include "../driver/input/source.h" #include "../execformat/pe/reloc.h" void execformat_pe_ReadSystemHeader(execformat_pe_PortableExecutable *pe); @@ -85,8 +86,7 @@ SYSV_ABI void kMain() { d = queue_PopByte(&irq_pic_ps2_QueueMouse); moveY = d - ((state << 3) & 0x100); - graphics_MouseCursorX = minmax(graphics_MouseCursorX + *((int *)&moveX), 0, graphics_SystemVideoMode.Width - 1); - graphics_MouseCursorY = minmax(graphics_MouseCursorY - *((int *)&moveY), 0, graphics_SystemVideoMode.Height - 1); + input_source_MoveMouse(moveX, -moveY); if (irq_pic_ps2_Mouse4Bytes) queue_PopByte(&irq_pic_ps2_QueueMouse); diff --git a/util/minmax.h b/util/minmax.h index 3e35bba..1b52a8d 100644 --- a/util/minmax.h +++ b/util/minmax.h @@ -32,3 +32,12 @@ static inline int intmax3(int x, int y, int z) { else return z; } + +static inline int intminmax(int x, int min, int max) { + if (x < min) + return min; + else if (x > max) + return max; + else + return x; +}