Merge lp:~alan-griffiths/miral/Keymap into lp:miral

Proposed by Alan Griffiths
Status: Merged
Approved by: Gerry Boland
Approved revision: 411
Merged at revision: 405
Proposed branch: lp:~alan-griffiths/miral/Keymap
Merge into: lp:miral
Diff against target: 315 lines (+251/-0)
6 files modified
debian/libmiral1.symbols (+11/-0)
include/miral/keymap.h (+56/-0)
miral-shell/shell_main.cpp (+4/-0)
miral/CMakeLists.txt (+1/-0)
miral/keymap.cpp (+173/-0)
miral/symbols.map (+6/-0)
To merge this branch: bzr merge lp:~alan-griffiths/miral/Keymap
Reviewer Review Type Date Requested Status
Gerry Boland (community) Approve
Brandon Schaefer (community) Approve
Andreas Pokorny (community) Approve
Review via email: mp+308121@code.launchpad.net

Commit message

miral::Keymap - support for keyboard maps (either programatically Keymap::set_keymap(), or via config --keymap)

To post a comment you must log in.
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

yes this looks reasonable

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

lgtm

review: Approve
lp:~alan-griffiths/miral/Keymap updated
411. By Alan Griffiths

Mutex to permit multi-threaded operation

Revision history for this message
Gerry Boland (gerboland) wrote :

looks ok to me

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/libmiral1.symbols'
2--- debian/libmiral1.symbols 2016-10-05 16:54:07 +0000
3+++ debian/libmiral1.symbols 2016-10-12 10:30:39 +0000
4@@ -264,3 +264,14 @@
5 (c++)"vtable for miral::ActiveOutputsListener@MIRAL_0.1" 0.1.0
6 (c++)"vtable for miral::CanonicalWindowManagerPolicy@MIRAL_0.1" 0.1.0
7 (c++)"vtable for miral::WindowManagementPolicy@MIRAL_0.1" 0.1.0
8+ (c++)"miral::Keymap::set_keymap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_0.3" 0.3.0
9+ (c++)"miral::Keymap::Keymap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_0.3" 0.3.0
10+ (c++)"miral::Keymap::Keymap(miral::Keymap const&)@MIRAL_0.3" 0.3.0
11+ (c++)"miral::Keymap::Keymap()@MIRAL_0.3" 0.3.0
12+ (c++)"miral::Keymap::Keymap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_0.3" 0.3.0
13+ (c++)"miral::Keymap::Keymap(miral::Keymap const&)@MIRAL_0.3" 0.3.0
14+ (c++)"miral::Keymap::Keymap()@MIRAL_0.3" 0.3.0
15+ (c++)"miral::Keymap::~Keymap()@MIRAL_0.3" 0.3.0
16+ (c++)"miral::Keymap::~Keymap()@MIRAL_0.3" 0.3.0
17+ (c++)"miral::Keymap::operator=(miral::Keymap const&)@MIRAL_0.3" 0.3.0
18+ (c++)"miral::Keymap::operator()(mir::Server&) const@MIRAL_0.3" 0.3.0
19
20=== added file 'include/miral/keymap.h'
21--- include/miral/keymap.h 1970-01-01 00:00:00 +0000
22+++ include/miral/keymap.h 2016-10-12 10:30:39 +0000
23@@ -0,0 +1,56 @@
24+/*
25+ * Copyright © 2016 Canonical Ltd.
26+ *
27+ * This program is free software: you can redistribute it and/or modify it
28+ * under the terms of the GNU General Public License version 3,
29+ * as published by the Free Software Foundation.
30+ *
31+ * This program is distributed in the hope that it will be useful,
32+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34+ * GNU General Public License for more details.
35+ *
36+ * You should have received a copy of the GNU General Public License
37+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
38+ *
39+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
40+ */
41+
42+#ifndef MIRAL_KEYMAP_H
43+#define MIRAL_KEYMAP_H
44+
45+#include <memory>
46+#include <string>
47+
48+namespace mir { class Server; }
49+
50+namespace miral
51+{
52+/// Load a keymap
53+class Keymap
54+{
55+public:
56+
57+ /// Apply keymap from the config.
58+ Keymap();
59+
60+ /// Specify a keymap.
61+ /// Format is <language>[+<variant>]
62+ /// e.g. "uk" or "us+dvorak"
63+ explicit Keymap(std::string const& keymap);
64+ ~Keymap();
65+ Keymap(Keymap const& that);
66+ auto operator=(Keymap const& rhs) -> Keymap&;
67+
68+ void operator()(mir::Server& server) const;
69+
70+ /// Specify a new keymap.
71+ void set_keymap(std::string const& keymap);
72+
73+private:
74+ struct Self;
75+ std::shared_ptr<Self> self;
76+};
77+}
78+
79+#endif //MIRAL_KEYMAP_H
80
81=== modified file 'miral-shell/shell_main.cpp'
82--- miral-shell/shell_main.cpp 2016-09-28 10:38:36 +0000
83+++ miral-shell/shell_main.cpp 2016-10-12 10:30:39 +0000
84@@ -26,6 +26,7 @@
85 #include <miral/append_event_filter.h>
86 #include <miral/internal_client.h>
87 #include <miral/cursor_theme.h>
88+#include <miral/keymap.h>
89
90 #include <linux/input.h>
91
92@@ -68,6 +69,8 @@
93 return true;
94 };
95
96+ Keymap config_keymap;
97+
98 return runner.run_with(
99 {
100 CursorTheme{"default"},
101@@ -75,6 +78,7 @@
102 display_configuration_options,
103 launcher,
104 outputs_monitor,
105+ config_keymap,
106 AppendEventFilter{quit_on_ctrl_alt_bksp},
107 StartupInternalClient{"Intro", spinner}
108 });
109
110=== modified file 'miral/CMakeLists.txt'
111--- miral/CMakeLists.txt 2016-09-28 13:16:14 +0000
112+++ miral/CMakeLists.txt 2016-10-12 10:30:39 +0000
113@@ -32,6 +32,7 @@
114 application_info.cpp ${CMAKE_SOURCE_DIR}/include/miral/application_info.h
115 canonical_window_manager.cpp ${CMAKE_SOURCE_DIR}/include/miral/canonical_window_manager.h
116 cursor_theme.cpp ${CMAKE_SOURCE_DIR}/include/miral/cursor_theme.h
117+ keymap.cpp ${CMAKE_SOURCE_DIR}/include/miral/keymap.h
118 runner.cpp ${CMAKE_SOURCE_DIR}/include/miral/runner.h
119 display_configuration_option.cpp ${CMAKE_SOURCE_DIR}/include/miral/display_configuration_option.h
120 output.cpp ${CMAKE_SOURCE_DIR}/include/miral/output.h
121
122=== added file 'miral/keymap.cpp'
123--- miral/keymap.cpp 1970-01-01 00:00:00 +0000
124+++ miral/keymap.cpp 2016-10-12 10:30:39 +0000
125@@ -0,0 +1,173 @@
126+/*
127+ * Copyright © 2016 Canonical Ltd.
128+ *
129+ * This program is free software: you can redistribute it and/or modify it
130+ * under the terms of the GNU General Public License version 3,
131+ * as published by the Free Software Foundation.
132+ *
133+ * This program is distributed in the hope that it will be useful,
134+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
135+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
136+ * GNU General Public License for more details.
137+ *
138+ * You should have received a copy of the GNU General Public License
139+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
140+ *
141+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
142+ */
143+
144+#include "miral/keymap.h"
145+
146+#include <mir/input/input_device_observer.h>
147+#include <mir/input/input_device_hub.h>
148+#include <mir/input/device.h>
149+#include <mir/options/option.h>
150+#include <mir/server.h>
151+#include <mir/version.h>
152+
153+#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 1)
154+#include <mir/input/keymap.h>
155+#include <mir/input/keyboard_configuration.h>
156+#endif
157+
158+#define MIR_LOG_COMPONENT "miral::Keymap"
159+#include <mir/log.h>
160+
161+#include <algorithm>
162+#include <mutex>
163+#include <vector>
164+
165+namespace
166+{
167+char const* const keymap_option = "keymap";
168+char const* const keymap_default = "us";
169+}
170+
171+struct miral::Keymap::Self : mir::input::InputDeviceObserver
172+{
173+ Self(std::string const& keymap) : layout{}, variant{}
174+ {
175+ set_keymap(keymap);
176+ }
177+
178+ void set_keymap(std::string const& keymap)
179+ {
180+ std::lock_guard<decltype(mutex)> lock{mutex};
181+
182+ auto const i = keymap.find('+');
183+
184+ layout = keymap.substr(0, i);
185+
186+ if (i != std::string::npos)
187+ variant = keymap.substr(i + 1);
188+
189+ for (auto const& keyboard : keyboards)
190+ apply_keymap(keyboard);
191+ }
192+
193+ void device_added(std::shared_ptr<mir::input::Device> const& device) override
194+ {
195+ std::lock_guard<decltype(mutex)> lock{mutex};
196+
197+ if (mir::contains(device->capabilities(), mir::input::DeviceCapability::keyboard))
198+ add_keyboard(device);
199+ }
200+
201+ void device_changed(std::shared_ptr<mir::input::Device> const& device) override
202+ {
203+ std::lock_guard<decltype(mutex)> lock{mutex};
204+
205+ auto const keyboard = std::find(begin(keyboards), end(keyboards), device);
206+
207+ if (mir::contains(device->capabilities(), mir::input::DeviceCapability::keyboard))
208+ {
209+ if (keyboard == end(keyboards))
210+ add_keyboard(device);
211+ }
212+ else
213+ {
214+ if (keyboard != end(keyboards))
215+ keyboards.erase(keyboard);
216+ }
217+ }
218+
219+ void add_keyboard(std::shared_ptr<mir::input::Device> const& keyboard)
220+ {
221+ keyboards.push_back(keyboard);
222+ apply_keymap(keyboard);
223+ }
224+
225+#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 1)
226+ void apply_keymap(std::shared_ptr<mir::input::Device> const& keyboard)
227+ {
228+ auto const keyboard_config = keyboard->keyboard_configuration();
229+ mir::input::Keymap keymap;
230+
231+ if (keyboard_config.is_set())
232+ {
233+ keymap = keyboard_config.value().device_keymap;
234+ }
235+
236+ keymap.layout = layout;
237+ keymap.variant = variant;
238+ keyboard->apply_keyboard_configuration(std::move(keymap));
239+ }
240+#else
241+ void apply_keymap(std::shared_ptr<mir::input::Device> const&)
242+ {
243+ mir::log_warning("Cannot apply keymap - not supported for Mir versions prior to 0.24.1");
244+ }
245+#endif
246+
247+ void device_removed(std::shared_ptr<mir::input::Device> const& device) override
248+ {
249+ std::lock_guard<decltype(mutex)> lock{mutex};
250+
251+ if (mir::contains(device->capabilities(), mir::input::DeviceCapability::keyboard))
252+ keyboards.erase(std::find(begin(keyboards), end(keyboards), device));
253+ }
254+
255+ void changes_complete() override
256+ {
257+ }
258+
259+ std::mutex mutable mutex;
260+ std::string layout;
261+ std::string variant;
262+ std::vector<std::shared_ptr<mir::input::Device>> keyboards;
263+};
264+
265+miral::Keymap::Keymap() :
266+ self{std::make_shared<Self>(std::string{})}
267+{
268+}
269+
270+miral::Keymap::Keymap(std::string const& keymap) :
271+ self{std::make_shared<Self>(keymap)}
272+{
273+}
274+
275+miral::Keymap::~Keymap() = default;
276+
277+miral::Keymap::Keymap(Keymap const&) = default;
278+
279+auto miral::Keymap::operator=(Keymap const& rhs) -> Keymap& = default;
280+
281+void miral::Keymap::operator()(mir::Server& server) const
282+{
283+ if (self->layout.empty())
284+ server.add_configuration_option(keymap_option, "keymap <layout>[+<variant>], e,g, \"gb\" or \"cz+qwerty\"", keymap_default);
285+
286+ server.add_init_callback([this, &server]
287+ {
288+ if (self->layout.empty())
289+ self->set_keymap(server.get_options()->get<std::string>(keymap_option));
290+
291+ server.the_input_device_hub()->add_observer(self);
292+ });
293+}
294+
295+void miral::Keymap::set_keymap(std::string const& keymap)
296+{
297+ self->set_keymap(keymap);
298+}
299
300=== modified file 'miral/symbols.map'
301--- miral/symbols.map 2016-10-05 16:54:07 +0000
302+++ miral/symbols.map 2016-10-12 10:30:39 +0000
303@@ -304,6 +304,12 @@
304 # We need to specify the overload of miral::WindowManagerTools::modify_window
305 _ZN5miral18WindowManagerTools13modify_windowERKNS_6WindowERKNS_19WindowSpecificationE;
306 extern "C++" {
307+ miral::Keymap::?Keymap*;
308+ miral::Keymap::Keymap*;
309+ miral::Keymap::operator*;
310+ miral::Keymap::set_keymap*;
311 miral::WindowSpecification::userdata*;
312+ typeinfo?for?miral::Keymap;
313+ vtable?for?miral::Keymap;
314 };
315 } MIRAL_0.2;

Subscribers

People subscribed via source and target branches