diff --git a/Kernel/KeyCode.h b/Kernel/KeyCode.h new file mode 100644 index 0000000000..52449dc0a7 --- /dev/null +++ b/Kernel/KeyCode.h @@ -0,0 +1,110 @@ +#pragma once + +#include + +enum KeyCode : byte { + Key_Invalid = 0, + Key_Escape, + Key_Tab, + Key_Backspace, + Key_Return, + Key_Insert, + Key_Delete, + Key_PrintScreen, + Key_SysRq, + Key_Home, + Key_End, + Key_Left, + Key_Up, + Key_Right, + Key_Down, + Key_PageUp, + Key_PageDown, + Key_Shift, + Key_Control, + Key_Alt, + Key_CapsLock, + Key_NumLock, + Key_ScrollLock, + Key_F1, + Key_F2, + Key_F3, + Key_F4, + Key_F5, + Key_F6, + Key_F7, + Key_F8, + Key_F9, + Key_F10, + Key_F11, + Key_F12, + Key_Space, + Key_ExclamationPoint, + Key_DoubleQuote, + Key_Hashtag, + Key_Dollar, + Key_Percent, + Key_Ampersand, + Key_Apostrophe, + Key_LeftParen, + Key_RightParen, + Key_Asterisk, + Key_Plus, + Key_Comma, + Key_Minus, + Key_Period, + Key_Slash, + Key_0, + Key_1, + Key_2, + Key_3, + Key_4, + Key_5, + Key_6, + Key_7, + Key_8, + Key_9, + Key_Colon, + Key_Semicolon, + Key_LessThan, + Key_Equal, + Key_GreaterThan, + Key_QuestionMark, + Key_AtSign, + Key_A, + Key_B, + Key_C, + Key_D, + Key_E, + Key_F, + Key_G, + Key_H, + Key_I, + Key_J, + Key_K, + Key_L, + Key_M, + Key_N, + Key_O, + Key_P, + Key_Q, + Key_R, + Key_S, + Key_T, + Key_U, + Key_V, + Key_W, + Key_X, + Key_Y, + Key_Z, + Key_LeftBracket, + Key_RightBracket, + Key_Backslash, + Key_Circumflex, + Key_Underscore, + Key_LeftBrace, + Key_RightBrace, + Key_Pipe, + Key_Tilde, + Key_Backtick, +}; diff --git a/Kernel/Keyboard.h b/Kernel/Keyboard.h index 614a66cd31..6cf580b801 100644 --- a/Kernel/Keyboard.h +++ b/Kernel/Keyboard.h @@ -5,116 +5,10 @@ #include #include #include "IRQHandler.h" +#include "KeyCode.h" class KeyboardClient; -enum KeyCode : byte { - Key_Invalid = 0, - Key_Escape, - Key_Tab, - Key_Backspace, - Key_Return, - Key_Insert, - Key_Delete, - Key_PrintScreen, - Key_SysRq, - Key_Home, - Key_End, - Key_Left, - Key_Up, - Key_Right, - Key_Down, - Key_PageUp, - Key_PageDown, - Key_Shift, - Key_Control, - Key_Alt, - Key_CapsLock, - Key_NumLock, - Key_ScrollLock, - Key_F1, - Key_F2, - Key_F3, - Key_F4, - Key_F5, - Key_F6, - Key_F7, - Key_F8, - Key_F9, - Key_F10, - Key_F11, - Key_F12, - Key_Space, - Key_ExclamationPoint, - Key_DoubleQuote, - Key_Hashtag, - Key_Dollar, - Key_Percent, - Key_Ampersand, - Key_Apostrophe, - Key_LeftParen, - Key_RightParen, - Key_Asterisk, - Key_Plus, - Key_Comma, - Key_Minus, - Key_Period, - Key_Slash, - Key_0, - Key_1, - Key_2, - Key_3, - Key_4, - Key_5, - Key_6, - Key_7, - Key_8, - Key_9, - Key_Colon, - Key_Semicolon, - Key_LessThan, - Key_Equal, - Key_GreaterThan, - Key_QuestionMark, - Key_AtSign, - Key_A, - Key_B, - Key_C, - Key_D, - Key_E, - Key_F, - Key_G, - Key_H, - Key_I, - Key_J, - Key_K, - Key_L, - Key_M, - Key_N, - Key_O, - Key_P, - Key_Q, - Key_R, - Key_S, - Key_T, - Key_U, - Key_V, - Key_W, - Key_X, - Key_Y, - Key_Z, - Key_LeftBracket, - Key_RightBracket, - Key_Backslash, - Key_Circumflex, - Key_Underscore, - Key_LeftBrace, - Key_RightBrace, - Key_Pipe, - Key_Tilde, - Key_Backtick, -}; - class Keyboard final : public IRQHandler, public CharacterDevice { AK_MAKE_ETERNAL public: diff --git a/LibGUI/GEvent.h b/LibGUI/GEvent.h index f697eef8f0..f0b385eeb9 100644 --- a/LibGUI/GEvent.h +++ b/LibGUI/GEvent.h @@ -99,16 +99,6 @@ enum class GMouseButton : byte { Middle = 4, }; -enum GKeyboardKey { - Invalid, - LeftArrow, - RightArrow, - UpArrow, - DownArrow, - Backspace, - Return, -}; - class GKeyEvent final : public GEvent { public: GKeyEvent(Type type, int key) diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp index 78858d7cde..00fa5fd4ba 100644 --- a/LibGUI/GEventLoop.cpp +++ b/LibGUI/GEventLoop.cpp @@ -83,6 +83,17 @@ void GEventLoop::handle_paint_event(const GUI_Event& event, GWindow& window) post_event(&window, make(event.paint.rect)); } +void GEventLoop::handle_key_event(const GUI_Event& event, GWindow& window) +{ + auto key_event = make(event.type == GUI_Event::Type::KeyDown ? GEvent::KeyDown : GEvent::KeyUp, event.key.key); + key_event->m_alt = event.key.alt; + key_event->m_ctrl = event.key.ctrl; + key_event->m_shift = event.key.shift; + if (event.key.character != '\0') + key_event->m_text = String(&event.key.character, 1); + post_event(&window, move(key_event)); +} + void GEventLoop::handle_mouse_event(const GUI_Event& event, GWindow& window) { GMouseEvent::Type type; @@ -149,6 +160,11 @@ void GEventLoop::wait_for_event() case GUI_Event::Type::WindowDeactivated: dbgprintf("WID=%x WindowDeactivated\n", event.window_id); break; + case GUI_Event::Type::KeyDown: + case GUI_Event::Type::KeyUp: + dbgprintf("WID=%x KeyEvent character=0x%b\n", event.window_id, event.key.character); + handle_key_event(event, *window); + break; } } } diff --git a/LibGUI/GEventLoop.h b/LibGUI/GEventLoop.h index 459b0d817f..b7150935c4 100644 --- a/LibGUI/GEventLoop.h +++ b/LibGUI/GEventLoop.h @@ -27,6 +27,7 @@ private: void wait_for_event(); void handle_paint_event(const GUI_Event&, GWindow&); void handle_mouse_event(const GUI_Event&, GWindow&); + void handle_key_event(const GUI_Event&, GWindow&); struct QueuedEvent { GObject* receiver { nullptr }; diff --git a/LibGUI/GTextBox.cpp b/LibGUI/GTextBox.cpp index cad25e171a..74a11324ea 100644 --- a/LibGUI/GTextBox.cpp +++ b/LibGUI/GTextBox.cpp @@ -3,6 +3,7 @@ #include #include #include +#include GTextBox::GTextBox(GWidget* parent) : GWidget(parent) @@ -91,21 +92,21 @@ void GTextBox::handle_backspace() void GTextBox::keydown_event(GKeyEvent& event) { switch (event.key()) { - case GKeyboardKey::LeftArrow: + case KeyCode::Key_Left: if (m_cursorPosition) --m_cursorPosition; m_cursorBlinkState = true; update(); return; - case GKeyboardKey::RightArrow: + case KeyCode::Key_Right: if (m_cursorPosition < m_text.length()) ++m_cursorPosition; m_cursorBlinkState = true; update(); return; - case GKeyboardKey::Backspace: + case KeyCode::Key_Backspace: return handle_backspace(); - case GKeyboardKey::Return: + case KeyCode::Key_Return: if (onReturnPressed) onReturnPressed(*this); return; diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index 0df190493c..650c92ea47 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -96,6 +96,12 @@ void GWindow::event(GEvent& event) ASSERT(rc == 0); } + if (event.is_key_event()) { + if (!m_focused_widget) + return; + return m_focused_widget->event(event); + } + return GObject::event(event); } @@ -128,3 +134,13 @@ void GWindow::set_main_widget(GWidget* widget) widget->set_window(this); update(); } + +void GWindow::set_focused_widget(GWidget* widget) +{ + if (m_focused_widget == widget) + return; + if (m_focused_widget) + m_focused_widget->update(); + m_focused_widget = widget; + m_focused_widget->update(); +} diff --git a/LibGUI/GWindow.h b/LibGUI/GWindow.h index 7f2bbd708f..fd1372e72d 100644 --- a/LibGUI/GWindow.h +++ b/LibGUI/GWindow.h @@ -38,6 +38,7 @@ public: GWidget* main_widget() { return m_main_widget; } const GWidget* main_widget() const { return m_main_widget; } void set_main_widget(GWidget*); + void set_focused_widget(GWidget*); void show(); @@ -47,5 +48,6 @@ private: RetainPtr m_backing; int m_window_id { -1 }; GWidget* m_main_widget { nullptr }; + GWidget* m_focused_widget { nullptr }; }; diff --git a/Userland/guitest2.cpp b/Userland/guitest2.cpp index cbba9a2bcc..3b50b8a64f 100644 --- a/Userland/guitest2.cpp +++ b/Userland/guitest2.cpp @@ -13,6 +13,7 @@ #include #include #include +#include static GWindow* make_font_test_window(); static GWindow* make_launcher_window(); @@ -107,5 +108,10 @@ GWindow* make_launcher_window() dummy_button->set_relative_rect({ 5, 80, 90, 20 }); dummy_button->set_caption("Dummy"); + auto* textbox = new GTextBox(widget); + textbox->set_relative_rect({ 5, 110, 90, 20 }); + + window->set_focused_widget(textbox); + return window; } diff --git a/WindowServer/WSWindow.cpp b/WindowServer/WSWindow.cpp index 6103119fa7..ff2432def0 100644 --- a/WindowServer/WSWindow.cpp +++ b/WindowServer/WSWindow.cpp @@ -90,6 +90,14 @@ void WSWindow::on_message(WSMessage& message) gui_event.key.ctrl = static_cast(message).ctrl(); gui_event.key.shift = static_cast(message).shift(); break; + case WSMessage::KeyUp: + gui_event.type = GUI_Event::Type::KeyUp; + gui_event.key.character = static_cast(message).character(); + gui_event.key.key = static_cast(message).key(); + gui_event.key.alt = static_cast(message).alt(); + gui_event.key.ctrl = static_cast(message).ctrl(); + gui_event.key.shift = static_cast(message).shift(); + break; case WSMessage::WM_ClientFinishedPaint: WSWindowManager::the().invalidate(*this, static_cast(message).rect()); return;