Skip to content

Commit

Permalink
(#620) Enabling keyboard LEDs when the modifier state changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkae committed Jun 27, 2024
1 parent 0980da3 commit b361733
Show file tree
Hide file tree
Showing 41 changed files with 1,038 additions and 23 deletions.
6 changes: 3 additions & 3 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ Description: Display server for Ubuntu - Nvidia driver metapackage
.
This package depends on a full set of graphics and input drivers for Nvidia systems.

Package: mir-platform-input-evdev10
Package: mir-platform-input-evdev11
Section: libs
Architecture: linux-any
Multi-Arch: same
Expand Down Expand Up @@ -423,7 +423,7 @@ Multi-Arch: same
Pre-Depends: ${misc:Pre-Depends}
Depends: ${misc:Depends},
mir-platform-graphics-gbm-kms22,
mir-platform-input-evdev10,
mir-platform-input-evdev11,
mir-platform-rendering-egl-generic,
Description: Display server for Ubuntu - gbm-kms driver metapackage
Mir is a display server running on linux systems, with a focus on efficiency,
Expand All @@ -439,7 +439,7 @@ Multi-Arch: same
Pre-Depends: ${misc:Pre-Depends}
Depends: ${misc:Depends},
mir-platform-graphics-eglstream-kms22,
mir-platform-input-evdev10,
mir-platform-input-evdev11,
Description: Display server for Ubuntu - eglstream-kms driver metapackage
Mir is a display server running on linux systems, with a focus on efficiency,
robust operation and a well-defined driver model.
Expand Down
1 change: 0 additions & 1 deletion debian/mir-platform-input-evdev10.install

This file was deleted.

1 change: 1 addition & 0 deletions debian/mir-platform-input-evdev11.install
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
usr/lib/*/mir/server-platform/input-evdev.so.11
40 changes: 40 additions & 0 deletions include/common/mir/input/keyboard_leds.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright © Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2 or 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef MIR_INPUT_KEYBOARD_LEDS_H
#define MIR_INPUT_KEYBOARD_LEDS_H

#include "mir/flags.h"
#include <cstdint>

namespace mir
{
namespace input
{
enum class KeyboardLed : uint32_t
{
caps_lock = (1 << 0),
num_lock = (1 << 1),
scroll_lock = (1 << 2)
};

KeyboardLed mir_enable_enum_bit_operators(KeyboardLed);
using KeyboardLeds = mir::Flags<KeyboardLed>;

}
}

#endif //MIR_INPUT_KEYBOARD_LEDS_H
3 changes: 3 additions & 0 deletions include/platform/mir/input/input_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef MIR_INPUT_INPUT_DEVICE_H_
#define MIR_INPUT_INPUT_DEVICE_H_

#include "mir/input/keyboard_leds.h"
#include "mir/module_deleter.h"
#include "mir/optional_value.h"

Expand Down Expand Up @@ -66,6 +67,8 @@ class InputDevice

virtual optional_value<TouchscreenSettings> get_touchscreen_settings() const = 0;
virtual void apply_settings(TouchscreenSettings const&) = 0;

virtual void set_leds(KeyboardLeds leds) = 0;
protected:
InputDevice(InputDevice const&) = delete;
InputDevice& operator=(InputDevice const&) = delete;
Expand Down
1 change: 1 addition & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ add_library(mircommon SHARED
${PROJECT_SOURCE_DIR}/include/common/mir/input/mir_touchpad_config.h
${PROJECT_SOURCE_DIR}/include/common/mir/input/mir_touchscreen_config.h
${PROJECT_SOURCE_DIR}/include/common/mir/input/mir_keyboard_config.h
${PROJECT_SOURCE_DIR}/include/common/mir/input/keyboard_leds.h
${MIR_COMMON_SOURCES}
)

Expand Down
1 change: 0 additions & 1 deletion src/common/events/event_builders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

#include "mir/events/event_private.h"
#include "mir/events/window_placement_event.h"
#include "mir/input/xkb_mapper.h"

#include <boost/throw_exception.hpp>

Expand Down
2 changes: 1 addition & 1 deletion src/common/input/xkb_mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "mir/input/xkb_mapper.h"
#include "mir/input/xkb_mapper_deprecated.h"
#include "mir/input/keymap.h"
#include "mir/events/event_private.h"
#include "mir/events/event_builders.h"
Expand Down
94 changes: 94 additions & 0 deletions src/include/common/mir/input/key_mapper_deprecated.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright © Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2 or 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef MIR_INPUT_KEY_MAPPER_H_
#define MIR_INPUT_KEY_MAPPER_H_

#include "mir_toolkit/client_types.h"
#include "mir_toolkit/event.h"
#include "mir/events/xkb_modifiers.h"

#include <vector>
#include <memory>

namespace mir
{
namespace input
{
class Keymap;

/**
* Deprecated. KeyMapper exists only to not break ABI. Please use KeyMapper from mirserver instead.
*
* The key mapping interface KeyMapper allows configuring a key map for each device individually or a single
* key map shared by all devices.
*
* The key mapping tables can either be provided as xkbcommon text buffers in the XKB_KEYMAP_FORMAT_TEXT_V1 format, or
* as xkbcommon configuration tuples using the mir::input::Keymap structure.
*/
class KeyMapper
{
public:
KeyMapper() = default;
virtual ~KeyMapper() = default;

/// Update the key state of device \a id, with the given sequence of pressed scan codes.
virtual void set_key_state(MirInputDeviceId id, std::vector<uint32_t> const& key_state) = 0;

/**
* Set a keymap for the device \a id
*/
virtual void set_keymap_for_device(MirInputDeviceId id, std::shared_ptr<Keymap> map) = 0;

/**
* Remove the specific keymap defined for device identified via the \a id.
*
* After this call key codes in events processed for device \a id will not be evaluated.
*/
virtual void clear_keymap_for_device(MirInputDeviceId id) = 0;

/**
* Set a default keymap for all devices.
*/
virtual void set_keymap_for_all_devices(std::shared_ptr<Keymap> map) = 0;

/*
* Remove all keymap configurations
*
* After this call no key code will be evaluated.
*/
virtual void clear_all_keymaps() = 0;

/**
* Map the given event based on the key maps configured.
*
* This includes mapping scan codes in key events onto the respective key code, and also replacing modifier
* masks in input events with the modifier mask evaluated by this Keymapper.
*/
virtual void map_event(MirEvent& event) = 0;
virtual MirInputEventModifiers modifiers() const = 0;
virtual MirInputEventModifiers device_modifiers(MirInputDeviceId id) const = 0;
virtual auto xkb_modifiers() const -> MirXkbModifiers = 0;

protected:
KeyMapper(KeyMapper const&) = delete;
KeyMapper& operator=(KeyMapper const&) = delete;
};

}
}

#endif
146 changes: 146 additions & 0 deletions src/include/common/mir/input/xkb_mapper_deprecated.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright © Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2 or 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef MIR_INPUT_RECEIVER_XKB_MAPPER_H_
#define MIR_INPUT_RECEIVER_XKB_MAPPER_H_

#include "mir/input/key_mapper_deprecated.h"
#include "mir/input/keymap.h"
#include "mir/optional_value.h"
#include "mir/events/xkb_modifiers.h"

#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-compose.h>
#include <mutex>
#include <optional>
#include <unordered_map>
#include <unordered_set>

namespace mir
{
namespace input
{

using XKBContextPtr = std::unique_ptr<xkb_context, void(*)(xkb_context*)>;
XKBContextPtr make_unique_context();

using XKBStatePtr = std::unique_ptr<xkb_state, void(*)(xkb_state*)>;
using XKBComposeTablePtr = std::unique_ptr<xkb_compose_table, void(*)(xkb_compose_table*)>;
using XKBComposeStatePtr = std::unique_ptr<xkb_compose_state, void(*)(xkb_compose_state*)>;

namespace receiver
{

/**
* Deprecated. XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead
*/
class XKBMapper : public KeyMapper
{
public:
[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
XKBMapper();

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
void set_key_state(MirInputDeviceId id, std::vector<uint32_t> const& key_state) override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
void set_keymap_for_device(MirInputDeviceId id, std::shared_ptr<Keymap> map) override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
void set_keymap_for_all_devices(std::shared_ptr<Keymap> map) override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
void clear_keymap_for_device(MirInputDeviceId id) override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
void clear_all_keymaps() override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
void map_event(MirEvent& event) override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
MirInputEventModifiers modifiers() const override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
MirInputEventModifiers device_modifiers(MirInputDeviceId di) const override;

[[deprecated("XKBMapper exists only to not break ABI. Please use XKBMapper from mirserver instead")]]
auto xkb_modifiers() const -> MirXkbModifiers override;

protected:
XKBMapper(XKBMapper const&) = delete;
XKBMapper& operator=(XKBMapper const&) = delete;

private:
void set_keymap(MirInputDeviceId id, std::shared_ptr<Keymap> new_keymap);
void set_keymap(std::shared_ptr<Keymap> new_keymap);
void update_modifier();

std::mutex mutable guard;

struct ComposeState
{
ComposeState(XKBComposeTablePtr const& table);
xkb_keysym_t update_state(xkb_keysym_t mapped_key, MirKeyboardAction action, std::string& text);
private:
XKBComposeStatePtr state;
std::unordered_set<xkb_keysym_t> consumed_keys;
mir::optional_value<std::tuple<xkb_keysym_t,xkb_keysym_t>> last_composed_key;
};

struct XkbMappingState
{
explicit XkbMappingState(std::shared_ptr<Keymap> keymap, std::shared_ptr<xkb_keymap> compiled_keymap);
void set_key_state(std::vector<uint32_t> const& key_state);

bool update_and_map(MirEvent& event, ComposeState* compose_state);
MirInputEventModifiers modifiers() const;
auto xkb_modifiers() const -> MirXkbModifiers;
private:
/// Returns a pair containing the keysym for the given scancode and if any XKB modifiers have been changed
auto update_state(
uint32_t scan_code,
MirKeyboardAction direction,
ComposeState* compose_state,
std::string& text) -> std::pair<xkb_keysym_t, bool>;
void press_modifier(MirInputEventModifiers mod);
void release_modifier(MirInputEventModifiers mod);

std::shared_ptr<Keymap> const keymap;
std::shared_ptr<xkb_keymap> const compiled_keymap;
XKBStatePtr state;
MirInputEventModifiers modifier_state{0};
};

XkbMappingState* get_keymapping_state(MirInputDeviceId id);
ComposeState* get_compose_state(MirInputDeviceId id);

XKBContextPtr context;
std::shared_ptr<Keymap> default_keymap;
std::shared_ptr<xkb_keymap> default_compiled_keymap;
XKBComposeTablePtr compose_table;
MirXkbModifiers xkb_modifiers_;
std::optional<MirInputDeviceId> last_device_id;

mir::optional_value<MirInputEventModifiers> modifier_state;
std::unordered_map<MirInputDeviceId, std::unique_ptr<XkbMappingState>> device_mapping;
std::unordered_map<MirInputDeviceId, std::unique_ptr<ComposeState>> device_composing;
};
}
}
}

#endif // MIR_INPUT_RECEIVER_XKB_MAPPER_H_
3 changes: 3 additions & 0 deletions src/include/server/mir/input/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define MIR_INPUT_DEVICE_H_

#include "mir/input/device_capability.h"
#include "mir/input/keyboard_leds.h"
#include "mir_toolkit/event.h"
#include "mir/optional_value.h"

Expand Down Expand Up @@ -54,6 +55,8 @@ class Device

virtual optional_value<MirTouchscreenConfig> touchscreen_configuration() const = 0;
virtual void apply_touchscreen_configuration(MirTouchscreenConfig const&) = 0;

virtual void set_leds(KeyboardLeds leds) = 0;
private:
Device(Device const&) = delete;
Device& operator=(Device const&) = delete;
Expand Down
Loading

0 comments on commit b361733

Please sign in to comment.