summaryrefslogtreecommitdiffstats
path: root/xbmc/windowing/wayland/SeatInputProcessing.h
blob: ce1f0ee759c256fc498b63993d1139a8b52d76fd (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
/*
 *  Copyright (C) 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 "InputProcessorKeyboard.h"
#include "InputProcessorPointer.h"
#include "InputProcessorTouch.h"
#include "Seat.h"

#include <cstdint>
#include <map>
#include <memory>

#include <wayland-client-protocol.hpp>

namespace KODI
{
namespace WINDOWING
{
namespace WAYLAND
{

enum class InputType
{
  POINTER,
  KEYBOARD,
  TOUCH
};

/**
 * Handler interface for input events from \ref CSeatInputProcessor
 */
class IInputHandler
{
public:
  /**
   * Handle input event
   * \param type input device type that caused the event
   * \param event XBMC event data
   */
  virtual void OnEvent(InputType type, XBMC_Event& event) {}
  /**
   * Handle focus enter
   * \param type input device type for which the surface has gained the focus
   */
  virtual void OnEnter(InputType type) {}
  /**
   * Handle focus leave
   * \param type input device type for which the surface has lost the focus
   */
  virtual void OnLeave(InputType type) {}
  /**
   * Handle request for setting the cursor
   *
   * When the client gains pointer focus for a surface, a cursor image must be
   * attached to the pointer. Otherwise the previous pointer image would
   * be used.
   *
   * This request is sent in addition to \ref OnEnter for \ref InputType::POINTER.
   *
   * \param seatGlobalName numeric Wayland global name of the seat the event occurred on
   * \param pointer pointer instance that needs its cursor set
   * \param serial Wayland protocol message serial that must be sent back in set_cursor
   */
  virtual void OnSetCursor(std::uint32_t seatGlobalName, std::uint32_t serial) {}

  virtual ~IInputHandler() = default;
};

/**
 * Receive events from all registered wl_seats and process them into Kodi events
 *
 * Multi-seat support is not currently implemented completely, but each seat has
 * separate state.
 */
class CSeatInputProcessing final : IInputHandlerPointer, IInputHandlerKeyboard
{
public:
  /**
   * Construct a seat input processor
   *
   * \param inputSurface Surface that events should be processed on (all other surfaces are ignored)
   * \param handler Mandatory handler for processed input events
   */
  CSeatInputProcessing(wayland::surface_t const& inputSurface, IInputHandler& handler);
  void AddSeat(CSeat* seat);
  void RemoveSeat(CSeat* seat);

  /**
   * Set the scale the coordinates should be interpreted at
   *
   * Wayland input events are always in surface coordinates, but Kodi only uses
   * buffer coordinates internally. Use this function to set the scaling
   * factor between the two and multiply the surface coordinates accordingly
   * for Kodi events.
   *
   * \param scale new buffer-to-surface pixel ratio
   */
  void SetCoordinateScale(std::int32_t scale);

private:
  wayland::surface_t m_inputSurface;
  IInputHandler& m_handler;

  void OnPointerEnter(std::uint32_t seatGlobalName, std::uint32_t serial) override;
  void OnPointerLeave() override;
  void OnPointerEvent(XBMC_Event& event) override;

  void OnKeyboardEnter() override;
  void OnKeyboardLeave() override;
  void OnKeyboardEvent(XBMC_Event& event) override;

  struct SeatState
  {
    CSeat* seat;
    std::unique_ptr<CInputProcessorKeyboard> keyboardProcessor;
    std::unique_ptr<CInputProcessorPointer> pointerProcessor;
    std::unique_ptr<CInputProcessorTouch> touchProcessor;

    SeatState(CSeat* seat)
    : seat{seat}
    {}
  };
  std::map<std::uint32_t, SeatState> m_seats;
};

}
}
}