mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:17:45 +00:00
GWindow: Add SerenityKeys minimum functionality
This commit is contained in:
parent
9ac95d1867
commit
72264661fd
6 changed files with 109 additions and 4 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include <LibGUI/GButton.h>
|
#include <LibGUI/GButton.h>
|
||||||
#include <LibGUI/GBoxLayout.h>
|
#include <LibGUI/GBoxLayout.h>
|
||||||
#include <LibGUI/GDesktop.h>
|
#include <LibGUI/GDesktop.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
virtual void click() = 0;
|
virtual void click() = 0;
|
||||||
virtual const char* class_name() const override { return "GAbstractButton"; }
|
virtual const char* class_name() const override { return "GAbstractButton"; }
|
||||||
virtual bool accepts_focus() const override { return true; }
|
virtual bool accepts_focus() const override { return true; }
|
||||||
|
virtual bool accepts_keyboard_select() const { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit GAbstractButton(GWidget* parent);
|
explicit GAbstractButton(GWidget* parent);
|
||||||
|
|
|
@ -64,6 +64,10 @@ void GButton::click()
|
||||||
on_click(*this);
|
on_click(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*bool GButton::accepts_keyboard_select() const {
|
||||||
|
return is_enabled();
|
||||||
|
}*/
|
||||||
|
|
||||||
void GButton::set_action(GAction& action)
|
void GButton::set_action(GAction& action)
|
||||||
{
|
{
|
||||||
m_action = action.make_weak_ptr();
|
m_action = action.make_weak_ptr();
|
||||||
|
|
|
@ -106,6 +106,7 @@ public:
|
||||||
void update(const Rect&);
|
void update(const Rect&);
|
||||||
|
|
||||||
virtual bool accepts_focus() const { return false; }
|
virtual bool accepts_focus() const { return false; }
|
||||||
|
virtual bool accepts_keyboard_select() const { return false; }
|
||||||
|
|
||||||
bool is_focused() const;
|
bool is_focused() const;
|
||||||
void set_focus(bool);
|
void set_focus(bool);
|
||||||
|
|
|
@ -230,6 +230,19 @@ void GWindow::event(CEvent& event)
|
||||||
for (auto& rect : rects)
|
for (auto& rect : rects)
|
||||||
m_main_widget->event(*make<GPaintEvent>(rect));
|
m_main_widget->event(*make<GPaintEvent>(rect));
|
||||||
|
|
||||||
|
if (m_keybind_mode) {
|
||||||
|
//If we're in keybind mode indicate widgets in m_potential_keybind_widgets
|
||||||
|
GPainter painter(*m_main_widget);
|
||||||
|
painter.draw_text(Rect(20,20,20,20), m_entered_keybind.characters(), TextAlignment::TopLeft, Color::Green);
|
||||||
|
|
||||||
|
for (auto& keypair: m_hashed_potential_keybind_widgets) {
|
||||||
|
auto widget = keypair.value;
|
||||||
|
auto rect = Rect(widget->x()-5, widget->y()-5, 12, 12);
|
||||||
|
painter.draw_text(rect, keypair.key.characters(), TextAlignment::TopLeft, Color::Black);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (m_double_buffering_enabled)
|
if (m_double_buffering_enabled)
|
||||||
flip(rects);
|
flip(rects);
|
||||||
else if (created_new_backing_store)
|
else if (created_new_backing_store)
|
||||||
|
@ -251,10 +264,44 @@ void GWindow::event(CEvent& event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type() == GEvent::KeyUp || event.type() == GEvent::KeyDown) {
|
if (event.type() == GEvent::KeyUp || event.type() == GEvent::KeyDown) {
|
||||||
|
auto keyevent = static_cast<GKeyEvent&>(event);
|
||||||
|
if (keyevent.logo() && event.type() == GEvent::KeyUp) {
|
||||||
|
if (m_keybind_mode) {
|
||||||
|
m_keybind_mode = false;
|
||||||
|
} else {
|
||||||
|
m_keybind_mode = true;
|
||||||
|
find_keyboard_selectable();
|
||||||
|
m_entered_keybind = "";
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_keybind_mode) {
|
||||||
|
StringBuilder builder;
|
||||||
|
//Y u no work
|
||||||
|
builder.append(m_entered_keybind);
|
||||||
|
builder.append(keyevent.text());
|
||||||
|
m_entered_keybind = builder.to_string();
|
||||||
|
|
||||||
|
auto found_widget = m_hashed_potential_keybind_widgets.find(m_entered_keybind);
|
||||||
|
if (found_widget != m_hashed_potential_keybind_widgets.end()) {
|
||||||
|
m_keybind_mode = false;
|
||||||
|
const auto& point = Point();
|
||||||
|
auto event = make<GMouseEvent>(GEvent::MouseDown, point, 0, GMouseButton::Left, 0, 0);
|
||||||
|
found_widget->value->event(*event);
|
||||||
|
event = make<GMouseEvent>(GEvent::MouseUp, point, 0, GMouseButton::Left, 0, 0);
|
||||||
|
found_widget->value->event(*event);
|
||||||
|
//Call click on the found widget
|
||||||
|
}
|
||||||
|
//m_entered_keybind.append(keyevent.text());
|
||||||
|
update();
|
||||||
|
} else {
|
||||||
if (m_focused_widget)
|
if (m_focused_widget)
|
||||||
return m_focused_widget->event(event);
|
return m_focused_widget->event(event);
|
||||||
if (m_main_widget)
|
if (m_main_widget)
|
||||||
return m_main_widget->event(event);
|
return m_main_widget->event(event);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +343,44 @@ void GWindow::event(CEvent& event)
|
||||||
CObject::event(event);
|
CObject::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GWindow::find_keyboard_selectable() {
|
||||||
|
m_potential_keybind_widgets.clear();
|
||||||
|
m_hashed_potential_keybind_widgets.clear();
|
||||||
|
find_keyboard_selectable_children(m_main_widget);
|
||||||
|
|
||||||
|
size_t buffer_length = ceil_div(m_potential_keybind_widgets.size(), ('z'-'a'))+1;
|
||||||
|
char keybind_buffer[buffer_length];
|
||||||
|
for (size_t i = 0; i < buffer_length-1; i++) {
|
||||||
|
keybind_buffer[i] = 'a';
|
||||||
|
}
|
||||||
|
keybind_buffer[buffer_length-1] = '\0';
|
||||||
|
|
||||||
|
for (auto& widget: m_potential_keybind_widgets) {
|
||||||
|
m_hashed_potential_keybind_widgets.set(String(keybind_buffer), widget);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < buffer_length-1; i++) {
|
||||||
|
if (keybind_buffer[i] >= 'z') {
|
||||||
|
keybind_buffer[i] = 'a';
|
||||||
|
} else {
|
||||||
|
keybind_buffer[i]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GWindow::find_keyboard_selectable_children(GWidget* widget) {
|
||||||
|
//Rather than painting immediately we need a step to collect all the keybinds first
|
||||||
|
widget -> for_each_child_widget([&] (auto& child) {
|
||||||
|
if (child.accepts_keyboard_select()) {
|
||||||
|
//auto rect = Rect(child.x()-5, child.y()-5, 10, 10);
|
||||||
|
m_potential_keybind_widgets.append(&child);
|
||||||
|
find_keyboard_selectable_children(&child);
|
||||||
|
}
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool GWindow::is_visible() const
|
bool GWindow::is_visible() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -305,6 +390,10 @@ void GWindow::update(const Rect& a_rect)
|
||||||
{
|
{
|
||||||
if (!m_window_id)
|
if (!m_window_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//We probably shouldn't clear the buffer on updates
|
||||||
|
//find_keyboard_selectable();
|
||||||
|
|
||||||
for (auto& pending_rect : m_pending_paint_event_rects) {
|
for (auto& pending_rect : m_pending_paint_event_rects) {
|
||||||
if (pending_rect.contains(a_rect)) {
|
if (pending_rect.contains(a_rect)) {
|
||||||
#ifdef UPDATE_COALESCING_DEBUG
|
#ifdef UPDATE_COALESCING_DEBUG
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/StringBuilder.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <LibCore/CObject.h>
|
#include <LibCore/CObject.h>
|
||||||
#include <LibGUI/GWindowType.h>
|
#include <LibGUI/GWindowType.h>
|
||||||
#include <SharedGraphics/GraphicsBitmap.h>
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
#include <SharedGraphics/Rect.h>
|
#include <SharedGraphics/Rect.h>
|
||||||
|
|
||||||
|
class GPainter;
|
||||||
class GWidget;
|
class GWidget;
|
||||||
class GWMEvent;
|
class GWMEvent;
|
||||||
|
|
||||||
|
@ -130,6 +133,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
virtual bool is_window() const override final { return true; }
|
virtual bool is_window() const override final { return true; }
|
||||||
|
|
||||||
|
void find_keyboard_selectable();
|
||||||
|
void find_keyboard_selectable_children(GWidget* widget);
|
||||||
Retained<GraphicsBitmap> create_backing_bitmap(const Size&);
|
Retained<GraphicsBitmap> create_backing_bitmap(const Size&);
|
||||||
void set_current_backing_bitmap(GraphicsBitmap&, bool flush_immediately = false);
|
void set_current_backing_bitmap(GraphicsBitmap&, bool flush_immediately = false);
|
||||||
void flip(const Vector<Rect, 32>& dirty_rects);
|
void flip(const Vector<Rect, 32>& dirty_rects);
|
||||||
|
@ -159,4 +164,8 @@ private:
|
||||||
bool m_resizable { true };
|
bool m_resizable { true };
|
||||||
bool m_fullscreen { false };
|
bool m_fullscreen { false };
|
||||||
bool m_show_titlebar { true };
|
bool m_show_titlebar { true };
|
||||||
|
bool m_keybind_mode { false };
|
||||||
|
String m_entered_keybind;
|
||||||
|
Vector<GWidget*> m_potential_keybind_widgets;
|
||||||
|
HashMap<String, GWidget*> m_hashed_potential_keybind_widgets;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue