aboutsummaryrefslogtreecommitdiff
path: root/include/cru/platform/gui/xcb/InputMethod.h
blob: 0c928b24147e1a201c97211366795e9d8df3b964 (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
#pragma once

#include <cru/base/Base.h>
#include "../InputMethod.h"
#include "Base.h"

#include <xcb-imdkit/imclient.h>
#include <xcb/xcb.h>
#include <optional>

namespace cru::platform::gui::xcb {
class XcbUiApplication;
class XcbWindow;

class XcbXimInputMethodManager : public XcbResource {
  CRU_DEFINE_CLASS_LOG_TAG("cru::platform::gui::xcb::XcbXimInputMethodManager")

  friend XcbUiApplication;

 public:
  XcbXimInputMethodManager(XcbUiApplication* application);
  ~XcbXimInputMethodManager() override;

  xcb_xim_t* GetXcbXim();

 private:
  void DispatchCommit(xcb_xim_t* im, xcb_xic_t ic, std::string text);
  void DispatchComposition(xcb_xim_t* im, xcb_xic_t ic, CompositionText text);

  bool HandleXEvent(xcb_generic_event_t* event);
  void SetXimServerUnprocessedXEventCallback(
      std::function<void(xcb_key_press_event_t* event)> callback);

 private:
  XcbUiApplication* application_;
  xcb_xim_t* im_;
  std::function<void(xcb_key_press_event_t* event)> forward_event_callback_;
};

class XcbXimInputMethodContext : public XcbResource,
                                 public virtual IInputMethodContext {
  CRU_DEFINE_CLASS_LOG_TAG("cru::platform::gui::xcb::XcbXimInputMethodContext")

  friend XcbXimInputMethodManager;

 public:
  XcbXimInputMethodContext(XcbXimInputMethodManager* manager,
                           XcbWindow* window);
  ~XcbXimInputMethodContext() override;

  bool ShouldManuallyDrawCompositionText() override;

  void EnableIME() override;
  void DisableIME() override;

  void CompleteComposition() override;
  void CancelComposition() override;
  CompositionText GetCompositionText() override;

  // Set the candidate window left-top. Relative to window left-top. Use this
  // method to prepare typing.
  void SetCandidateWindowPosition(const Point& point) override;

  IEvent<std::nullptr_t>* CompositionStartEvent() override;
  IEvent<std::nullptr_t>* CompositionEndEvent() override;
  IEvent<std::nullptr_t>* CompositionEvent() override;
  IEvent<StringView>* TextEvent() override;

 private:
  void CreateIc(xcb_window_t window);
  void DestroyIc();

 private:
  XcbXimInputMethodManager* manager_;
  XcbWindow* window_;
  bool enabled_;
  std::optional<xcb_xic_t> ic_;
  CompositionText composition_text_;

  Event<std::nullptr_t> composition_start_event_;
  Event<std::nullptr_t> composition_end_event_;
  Event<std::nullptr_t> composition_event_;
  Event<StringView> text_event_;
};
}  // namespace cru::platform::gui::xcb