WindowServer+Keymap+LibGUI: Add widget to display current keymap

This commit is contained in:
Timur Sultanov 2022-01-19 14:44:56 +03:00 committed by Andreas Kling
parent 68a01f0e27
commit b9c558f6c6
Notes: sideshowbarker 2024-07-19 01:59:31 +09:00
14 changed files with 160 additions and 17 deletions

View file

@ -32,7 +32,7 @@ DoubleClickSpeed=250
Mode=stretch
[Applet]
Order=WorkspacePicker,CPUGraph,MemoryGraph,Network,ClipboardHistory,Audio
Order=WorkspacePicker,CPUGraph,MemoryGraph,Network,ClipboardHistory,Audio,Keymap
[Workspaces]
Rows=2

View file

@ -3,3 +3,4 @@ add_subdirectory(ClipboardHistory)
add_subdirectory(Network)
add_subdirectory(ResourceGraph)
add_subdirectory(WorkspacePicker)
add_subdirectory(Keymap)

View file

@ -0,0 +1,13 @@
serenity_component(
Keymap.Applet
REQUIRED
TARGETS Keymap.Applet
)
set(SOURCES
KeymapStatusWindow.cpp
main.cpp
)
serenity_bin(Keymap.Applet)
target_link_libraries(Keymap.Applet LibGUI LibCore LibGfx LibMain LibKeyboard)

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2021, Timur Sultanov <SultanovTS@yandex.ru>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "KeymapStatusWindow.h"
#include <LibGUI/Painter.h>
#include <LibGUI/WindowManagerServerConnection.h>
#include <LibKeyboard/CharacterMap.h>
KeymapStatusWindow::KeymapStatusWindow()
{
set_window_type(GUI::WindowType::Applet);
set_has_alpha_channel(true);
m_label = &set_main_widget<GUI::Label>();
auto current_keymap = MUST(Keyboard::CharacterMap::fetch_system_map());
auto current_keymap_name = current_keymap.character_map_name();
m_label->set_tooltip(current_keymap_name);
m_label->set_text(current_keymap_name.substring(0, 2));
}
KeymapStatusWindow::~KeymapStatusWindow()
{
}
void KeymapStatusWindow::wm_event(GUI::WMEvent& event)
{
if (event.type() == GUI::WMEvent::WM_KeymapChanged) {
auto& keymap_event = static_cast<GUI::WMKeymapChangedEvent&>(event);
auto keymap = keymap_event.keymap();
set_keymap_text(keymap);
}
}
void KeymapStatusWindow::set_keymap_text(const String& keymap)
{
GUI::Painter painter(*m_label);
painter.clear_rect(m_label->rect(), Color::from_rgba(0));
m_label->set_tooltip(keymap);
m_label->set_text(keymap.substring(0, 2));
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2021, Timur Sultanov <SultanovTS@yandex.ru>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGUI/Label.h>
#include <LibGUI/Window.h>
class KeymapStatusWidget;
class KeymapStatusWindow final : public GUI::Window {
C_OBJECT(KeymapStatusWindow)
public:
virtual ~KeymapStatusWindow() override;
private:
void wm_event(GUI::WMEvent&) override;
KeymapStatusWindow();
RefPtr<GUI::Label> m_label;
void set_keymap_text(String const& keymap);
};

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021, Timur Sultanov <SultanovTS@yandex.ru>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "KeymapStatusWindow.h"
#include <LibCore/System.h>
#include <LibGUI/Application.h>
#include <LibGUI/WindowManagerServerConnection.h>
#include <LibMain/Main.h>
#include <WindowServer/Window.h>
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
TRY(Core::System::pledge("stdio recvfd sendfd rpath unix getkeymap"));
auto app = TRY(GUI::Application::try_create(arguments));
auto window = TRY(KeymapStatusWindow::try_create());
window->set_has_alpha_channel(true);
window->set_title("Keymap");
window->resize(16, 16);
window->show();
window->make_window_manager(WindowServer::WMEventMask::KeymapChanged);
TRY(Core::System::pledge("stdio recvfd sendfd rpath getkeymap"));
return app->exec();
}

View file

@ -67,6 +67,7 @@ public:
WM_SuperKeyPressed,
WM_SuperSpaceKeyPressed,
WM_WorkspaceChanged,
WM_KeymapChanged,
__End_WM_Events,
};
@ -228,6 +229,20 @@ private:
const unsigned m_current_column;
};
class WMKeymapChangedEvent : public WMEvent {
public:
explicit WMKeymapChangedEvent(int client_id, String const& keymap)
: WMEvent(Event::Type::WM_KeymapChanged, client_id, 0)
, m_keymap(keymap)
{
}
String const& keymap() const { return m_keymap; }
private:
const String m_keymap;
};
class MultiPaintEvent final : public Event {
public:
explicit MultiPaintEvent(Vector<Gfx::IntRect, 32> rects, Gfx::IntSize const& window_size)

View file

@ -70,4 +70,10 @@ void WindowManagerServerConnection::workspace_changed(i32 wm_id, u32 row, u32 co
Core::EventLoop::current().post_event(*window, make<WMWorkspaceChangedEvent>(wm_id, row, column));
}
void WindowManagerServerConnection::keymap_changed(i32 wm_id, String const& keymap)
{
if (auto* window = Window::from_window_id(wm_id))
Core::EventLoop::current().post_event(*window, make<WMKeymapChangedEvent>(wm_id, keymap));
}
}

View file

@ -35,6 +35,7 @@ private:
virtual void super_key_pressed(i32) override;
virtual void super_space_key_pressed(i32) override;
virtual void workspace_changed(i32, u32, u32) override;
virtual void keymap_changed(i32, String const&) override;
};
}

View file

@ -12,17 +12,8 @@
namespace WindowServer {
static KeymapSwitcher* s_the;
KeymapSwitcher& KeymapSwitcher::the()
{
VERIFY(s_the);
return *s_the;
}
KeymapSwitcher::KeymapSwitcher()
{
s_the = this;
}
KeymapSwitcher::~KeymapSwitcher()
@ -80,10 +71,7 @@ String KeymapSwitcher::get_current_keymap() const
auto json = JsonValue::from_string(proc_keymap->read_all()).release_value_but_fixme_should_propagate_errors();
auto const& keymap_object = json.as_object();
VERIFY(keymap_object.has("keymap"));
auto keymap = keymap_object.get("keymap").to_string();
dbgln("Current keymap is: {}", keymap);
return keymap;
return keymap_object.get("keymap").to_string();
}
void KeymapSwitcher::setkeymap(const AK::String& keymap)
@ -94,6 +82,8 @@ void KeymapSwitcher::setkeymap(const AK::String& keymap)
perror("posix_spawn");
dbgln("Failed to call /bin/keymap, error: {} ({})", errno, strerror(errno));
}
if (on_keymap_change)
on_keymap_change(keymap);
}
}

View file

@ -11,27 +11,29 @@
#include <AK/WeakPtr.h>
#include <LibCore/Object.h>
#include <LibKeyboard/CharacterMap.h>
#include <WindowServer/WMClientConnection.h>
namespace WindowServer {
class KeymapSwitcher final : public Core::Object {
C_OBJECT(KeymapSwitcher)
public:
static KeymapSwitcher& the();
virtual ~KeymapSwitcher() override;
void refresh();
void next_keymap();
Function<void(String const& keymap)> on_keymap_change;
String get_current_keymap() const;
private:
KeymapSwitcher();
Vector<AK::String> m_keymaps;
void setkeymap(AK::String const&);
String get_current_keymap() const;
};
}

View file

@ -36,6 +36,7 @@ enum WMEventMask {
WindowIconChanges = 1 << 2,
WindowRemovals = 1 << 3,
WorkspaceChanges = 1 << 4,
KeymapChanged = 1 << 5,
};
enum class WindowTileType {

View file

@ -53,6 +53,18 @@ WindowManager::WindowManager(Gfx::PaletteImpl const& palette)
reload_config();
m_keymap_switcher->on_keymap_change = [&](String const& keymap) {
for_each_window_manager([&keymap](WMClientConnection& conn) {
if (!(conn.event_mask() & WMEventMask::KeymapChanged))
return IterationDecision::Continue;
if (conn.window_id() < 0)
return IterationDecision::Continue;
conn.async_keymap_changed(conn.window_id(), keymap);
return IterationDecision::Continue;
});
};
Compositor::the().did_construct_window_manager({});
}

View file

@ -10,4 +10,5 @@ endpoint WindowManagerClient
super_key_pressed(i32 wm_id) =|
super_space_key_pressed(i32 wm_id) =|
workspace_changed(i32 wm_id, u32 row, u32 column) =|
keymap_changed(i32 wm_id, [UTF8] String keymap) =|
}