summaryrefslogtreecommitdiffstats
path: root/xbmc/windowing/wayland/XkbcommonKeymap.h
blob: 7718b029c6291f8232bec483a8e3c1ab62ada715 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 *  Copyright (C) 2017-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "input/XBMC_keysym.h"

#include <cstdint>
#include <memory>
#include <vector>

#include <xkbcommon/xkbcommon.h>

namespace KODI
{
namespace WINDOWING
{
namespace WAYLAND
{

/**
 * A wrapper class around an xkbcommon keymap and state tracker.
 *
 * This class knows about some common modifier combinations and keeps
 * track of the currently pressed keys and modifiers. It also has
 * some utility functions to transform hardware keycodes into
 * a common representation.
 *
 * Since this class is keeping track of all the pressed and depressed
 * modifiers, IT MUST ALWAYS BE KEPT UP TO DATE WITH ANY NEWLY
 * PRESSED MODIFIERS. Undefined behaviour will result if it is not
 * kept up to date.
 *
 * Instances can be easily created from keymap strings with \ref CXkbcommonContext
 */
class CXkbcommonKeymap
{
public:
  struct XkbKeymapDeleter
  {
    void operator()(xkb_keymap* keymap) const;
  };

  /**
   * Construct for known xkb_keymap
   */
  explicit CXkbcommonKeymap(std::unique_ptr<xkb_keymap, XkbKeymapDeleter> keymap);

  /**
   * Get xkb keysym for keycode - only a single keysym is supported
   */
  xkb_keysym_t KeysymForKeycode(xkb_keycode_t code) const;
  /**
   * Updates the currently depressed, latched, locked and group
   * modifiers for a keyboard being tracked.
   *
   * This function must be called whenever modifiers change, or the state will
   * be wrong and keysym translation will be off.
   */
  void UpdateMask(xkb_mod_mask_t depressed,
                  xkb_mod_mask_t latched,
                  xkb_mod_mask_t locked,
                  xkb_mod_mask_t group);
  /**
   * Gets the currently depressed, latched and locked modifiers
   * for the keyboard
   */
  xkb_mod_mask_t CurrentModifiers() const;
  /**
   * Get XBMCKey for provided keycode
   */
  XBMCKey XBMCKeyForKeycode(xkb_keycode_t code) const;
  /**
   * \ref CurrentModifiers with XBMC flags
   */
  XBMCMod ActiveXBMCModifiers() const;
  /**
   * Get Unicode codepoint/UTF32 code for provided keycode
   */
  std::uint32_t UnicodeCodepointForKeycode(xkb_keycode_t code) const;
  /**
   * Check whether a given keycode should have key repeat
   */
  bool ShouldKeycodeRepeat(xkb_keycode_t code) const;

  static XBMCKey XBMCKeyForKeysym(xkb_keysym_t sym);

private:
  struct XkbStateDeleter
  {
    void operator()(xkb_state* state) const;
  };
  static std::unique_ptr<xkb_state, XkbStateDeleter> CreateXkbStateFromKeymap(xkb_keymap* keymap);

  std::unique_ptr<xkb_keymap, XkbKeymapDeleter> m_keymap;
  std::unique_ptr<xkb_state, XkbStateDeleter> m_state;

  struct ModifierMapping
  {
    xkb_mod_index_t xkb;
    XBMCMod xbmc;
    ModifierMapping(xkb_mod_index_t xkb, XBMCMod xbmc)
    : xkb{xkb}, xbmc{xbmc}
    {}
  };
  std::vector<ModifierMapping> m_modifierMappings;
};

class CXkbcommonContext
{
public:
  explicit CXkbcommonContext(xkb_context_flags flags = XKB_CONTEXT_NO_FLAGS);

  /**
   * Opens a shared memory region and parses the data in it to an
   * xkbcommon keymap.
   *
   * This function does not own the file descriptor. It must not be closed
   * from this function.
   */
  std::unique_ptr<CXkbcommonKeymap> KeymapFromString(std::string const& keymap);
  std::unique_ptr<CXkbcommonKeymap> KeymapFromNames(const std::string &rules, const std::string &model, const std::string &layout, const std::string &variant, const std::string &options);

private:
  struct XkbContextDeleter
  {
    void operator()(xkb_context* ctx) const;
  };
  std::unique_ptr<xkb_context, XkbContextDeleter> m_context;
};


}
}
}