mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:12:45 +00:00 
			
		
		
		
	WindowServer+Keymap+LibGUI: Add widget to display current keymap
This commit is contained in:
		
							parent
							
								
									68a01f0e27
								
							
						
					
					
						commit
						b9c558f6c6
					
				
					 14 changed files with 160 additions and 17 deletions
				
			
		|  | @ -32,7 +32,7 @@ DoubleClickSpeed=250 | ||||||
| Mode=stretch | Mode=stretch | ||||||
| 
 | 
 | ||||||
| [Applet] | [Applet] | ||||||
| Order=WorkspacePicker,CPUGraph,MemoryGraph,Network,ClipboardHistory,Audio | Order=WorkspacePicker,CPUGraph,MemoryGraph,Network,ClipboardHistory,Audio,Keymap | ||||||
| 
 | 
 | ||||||
| [Workspaces] | [Workspaces] | ||||||
| Rows=2 | Rows=2 | ||||||
|  |  | ||||||
|  | @ -3,3 +3,4 @@ add_subdirectory(ClipboardHistory) | ||||||
| add_subdirectory(Network) | add_subdirectory(Network) | ||||||
| add_subdirectory(ResourceGraph) | add_subdirectory(ResourceGraph) | ||||||
| add_subdirectory(WorkspacePicker) | add_subdirectory(WorkspacePicker) | ||||||
|  | add_subdirectory(Keymap) | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								Userland/Applets/Keymap/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Userland/Applets/Keymap/CMakeLists.txt
									
										
									
									
									
										Normal 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) | ||||||
							
								
								
									
										44
									
								
								Userland/Applets/Keymap/KeymapStatusWindow.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Userland/Applets/Keymap/KeymapStatusWindow.cpp
									
										
									
									
									
										Normal 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)); | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								Userland/Applets/Keymap/KeymapStatusWindow.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Userland/Applets/Keymap/KeymapStatusWindow.h
									
										
									
									
									
										Normal 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); | ||||||
|  | }; | ||||||
							
								
								
									
										30
									
								
								Userland/Applets/Keymap/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Userland/Applets/Keymap/main.cpp
									
										
									
									
									
										Normal 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(); | ||||||
|  | } | ||||||
|  | @ -67,6 +67,7 @@ public: | ||||||
|         WM_SuperKeyPressed, |         WM_SuperKeyPressed, | ||||||
|         WM_SuperSpaceKeyPressed, |         WM_SuperSpaceKeyPressed, | ||||||
|         WM_WorkspaceChanged, |         WM_WorkspaceChanged, | ||||||
|  |         WM_KeymapChanged, | ||||||
|         __End_WM_Events, |         __End_WM_Events, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | @ -228,6 +229,20 @@ private: | ||||||
|     const unsigned m_current_column; |     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 { | class MultiPaintEvent final : public Event { | ||||||
| public: | public: | ||||||
|     explicit MultiPaintEvent(Vector<Gfx::IntRect, 32> rects, Gfx::IntSize const& window_size) |     explicit MultiPaintEvent(Vector<Gfx::IntRect, 32> rects, Gfx::IntSize const& window_size) | ||||||
|  |  | ||||||
|  | @ -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)); |         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)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -35,6 +35,7 @@ private: | ||||||
|     virtual void super_key_pressed(i32) override; |     virtual void super_key_pressed(i32) override; | ||||||
|     virtual void super_space_key_pressed(i32) override; |     virtual void super_space_key_pressed(i32) override; | ||||||
|     virtual void workspace_changed(i32, u32, u32) override; |     virtual void workspace_changed(i32, u32, u32) override; | ||||||
|  |     virtual void keymap_changed(i32, String const&) override; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,17 +12,8 @@ | ||||||
| 
 | 
 | ||||||
| namespace WindowServer { | namespace WindowServer { | ||||||
| 
 | 
 | ||||||
| static KeymapSwitcher* s_the; |  | ||||||
| 
 |  | ||||||
| KeymapSwitcher& KeymapSwitcher::the() |  | ||||||
| { |  | ||||||
|     VERIFY(s_the); |  | ||||||
|     return *s_the; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeymapSwitcher::KeymapSwitcher() | KeymapSwitcher::KeymapSwitcher() | ||||||
| { | { | ||||||
|     s_the = this; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KeymapSwitcher::~KeymapSwitcher() | 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 json = JsonValue::from_string(proc_keymap->read_all()).release_value_but_fixme_should_propagate_errors(); | ||||||
|     auto const& keymap_object = json.as_object(); |     auto const& keymap_object = json.as_object(); | ||||||
|     VERIFY(keymap_object.has("keymap")); |     VERIFY(keymap_object.has("keymap")); | ||||||
|     auto keymap = keymap_object.get("keymap").to_string(); |     return keymap_object.get("keymap").to_string(); | ||||||
|     dbgln("Current keymap is: {}", keymap); |  | ||||||
| 
 |  | ||||||
|     return keymap; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KeymapSwitcher::setkeymap(const AK::String& keymap) | void KeymapSwitcher::setkeymap(const AK::String& keymap) | ||||||
|  | @ -94,6 +82,8 @@ void KeymapSwitcher::setkeymap(const AK::String& keymap) | ||||||
|         perror("posix_spawn"); |         perror("posix_spawn"); | ||||||
|         dbgln("Failed to call /bin/keymap, error: {} ({})", errno, strerror(errno)); |         dbgln("Failed to call /bin/keymap, error: {} ({})", errno, strerror(errno)); | ||||||
|     } |     } | ||||||
|  |     if (on_keymap_change) | ||||||
|  |         on_keymap_change(keymap); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -11,27 +11,29 @@ | ||||||
| #include <AK/WeakPtr.h> | #include <AK/WeakPtr.h> | ||||||
| #include <LibCore/Object.h> | #include <LibCore/Object.h> | ||||||
| #include <LibKeyboard/CharacterMap.h> | #include <LibKeyboard/CharacterMap.h> | ||||||
|  | #include <WindowServer/WMClientConnection.h> | ||||||
| 
 | 
 | ||||||
| namespace WindowServer { | namespace WindowServer { | ||||||
| 
 | 
 | ||||||
| class KeymapSwitcher final : public Core::Object { | class KeymapSwitcher final : public Core::Object { | ||||||
|     C_OBJECT(KeymapSwitcher) |     C_OBJECT(KeymapSwitcher) | ||||||
| public: | public: | ||||||
|     static KeymapSwitcher& the(); |  | ||||||
| 
 |  | ||||||
|     virtual ~KeymapSwitcher() override; |     virtual ~KeymapSwitcher() override; | ||||||
| 
 | 
 | ||||||
|     void refresh(); |     void refresh(); | ||||||
| 
 | 
 | ||||||
|     void next_keymap(); |     void next_keymap(); | ||||||
| 
 | 
 | ||||||
|  |     Function<void(String const& keymap)> on_keymap_change; | ||||||
|  | 
 | ||||||
|  |     String get_current_keymap() const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     KeymapSwitcher(); |     KeymapSwitcher(); | ||||||
| 
 | 
 | ||||||
|     Vector<AK::String> m_keymaps; |     Vector<AK::String> m_keymaps; | ||||||
| 
 | 
 | ||||||
|     void setkeymap(AK::String const&); |     void setkeymap(AK::String const&); | ||||||
|     String get_current_keymap() const; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ enum WMEventMask { | ||||||
|     WindowIconChanges = 1 << 2, |     WindowIconChanges = 1 << 2, | ||||||
|     WindowRemovals = 1 << 3, |     WindowRemovals = 1 << 3, | ||||||
|     WorkspaceChanges = 1 << 4, |     WorkspaceChanges = 1 << 4, | ||||||
|  |     KeymapChanged = 1 << 5, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class WindowTileType { | enum class WindowTileType { | ||||||
|  |  | ||||||
|  | @ -53,6 +53,18 @@ WindowManager::WindowManager(Gfx::PaletteImpl const& palette) | ||||||
| 
 | 
 | ||||||
|     reload_config(); |     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({}); |     Compositor::the().did_construct_window_manager({}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,4 +10,5 @@ endpoint WindowManagerClient | ||||||
|     super_key_pressed(i32 wm_id) =| |     super_key_pressed(i32 wm_id) =| | ||||||
|     super_space_key_pressed(i32 wm_id) =| |     super_space_key_pressed(i32 wm_id) =| | ||||||
|     workspace_changed(i32 wm_id, u32 row, u32 column) =| |     workspace_changed(i32 wm_id, u32 row, u32 column) =| | ||||||
|  |     keymap_changed(i32 wm_id, [UTF8] String keymap) =| | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timur Sultanov
						Timur Sultanov