gtk_key_bindings_handler.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_
  5. #define UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_
  6. #include <string>
  7. #include <vector>
  8. #include "base/memory/raw_ptr.h"
  9. #include "ui/base/ime/linux/text_edit_command_auralinux.h"
  10. #include "ui/events/platform_event.h"
  11. #include "ui/gtk/gtk_compat.h"
  12. namespace ui {
  13. class Event;
  14. }
  15. namespace gtk {
  16. // This class is a convenience class for handling editor key bindings defined
  17. // in gtk keyboard theme.
  18. // In gtk, only GtkEntry and GtkTextView support customizing editor key bindings
  19. // through keyboard theme. And in gtk keyboard theme definition file, each key
  20. // binding must be bound to a specific class or object. So existing keyboard
  21. // themes only define editor key bindings exactly for GtkEntry and GtkTextView.
  22. // Then, the only way for us to intercept editor key bindings defined in
  23. // keyboard theme, is to create a GtkEntry or GtkTextView object and call
  24. // gtk_bindings_activate_event() against it for the key events. If a key event
  25. // matches a predefined key binding, corresponding signal will be emitted.
  26. // GtkTextView is used here because it supports more key bindings than GtkEntry,
  27. // but in order to minimize the side effect of using a GtkTextView object, a new
  28. // class derived from GtkTextView is used, which overrides all signals related
  29. // to key bindings, to make sure GtkTextView won't receive them.
  30. //
  31. // See third_party/blink/renderer/core/editing/commands/editor_command.cc for
  32. // detailed definition of Blink edit commands.
  33. class GtkKeyBindingsHandler {
  34. public:
  35. GtkKeyBindingsHandler();
  36. virtual ~GtkKeyBindingsHandler();
  37. // Matches a key event against predefined gtk key bindings, false will be
  38. // returned if the key event doesn't correspond to a predefined key binding.
  39. // Edit commands matched with |event| will be stored in |edit_commands|, if
  40. // non-nullptr.
  41. bool MatchEvent(const ui::Event& event,
  42. std::vector<ui::TextEditCommandAuraLinux>* commands);
  43. private:
  44. // Object structure of Handler class, which is derived from GtkTextView.
  45. struct Handler {
  46. // Starting in Gtk4, GtkTextView subclasses from GtkWidget instead of
  47. // GtkContainer. This class is only used on Gtk3, so to ensure ABI
  48. // compatibility, we always want the Gtk3 struct layout even when building
  49. // with Gtk4 headers. To facilitate this, we manually copy the class
  50. // hierarchy up to GtkWidget.
  51. GtkWidget widget;
  52. raw_ptr<void> container_private;
  53. raw_ptr<void> text_view_private;
  54. raw_ptr<GtkKeyBindingsHandler> owner;
  55. };
  56. // Class structure of Handler class.
  57. struct HandlerClass {
  58. // Class layout for types changes between GTK versions, but is stable within
  59. // the same major version. This class is only used on Gtk3, so manually
  60. // expand the class layout as it appears in Gtk3.
  61. GInitiallyUnownedClass parent_class;
  62. // GtkWidgetClass and GtkContainerClass
  63. guint pad0;
  64. void* pad1[95];
  65. unsigned int pad2 : 1;
  66. void* pad3[8];
  67. // GtkTextViewClass
  68. void (*populate_popup)(GtkTextView* text_view, GtkWidget* popup);
  69. void (*move_cursor)(GtkTextView* text_view,
  70. GtkMovementStep step,
  71. gint count,
  72. gboolean extend_selection);
  73. void (*set_anchor)(GtkTextView* text_view);
  74. void (*insert_at_cursor)(GtkTextView* text_view, const gchar* str);
  75. void (*delete_from_cursor)(GtkTextView* text_view,
  76. GtkDeleteType type,
  77. gint count);
  78. void (*backspace)(GtkTextView* text_view);
  79. void (*cut_clipboard)(GtkTextView* text_view);
  80. void (*copy_clipboard)(GtkTextView* text_view);
  81. void (*paste_clipboard)(GtkTextView* text_view);
  82. void (*toggle_overwrite)(GtkTextView* text_view);
  83. GtkTextBuffer* (*create_buffer)(GtkTextView* text_view);
  84. void (*draw_layer)(GtkTextView* text_view,
  85. GtkTextViewLayer layer,
  86. cairo_t* cr);
  87. gboolean (*extend_selection)(GtkTextView* text_view,
  88. GtkTextExtendSelection granularity,
  89. const GtkTextIter* location,
  90. GtkTextIter* start,
  91. GtkTextIter* end);
  92. void (*insert_emoji)(GtkTextView* text_view);
  93. void* pad4[4];
  94. };
  95. // Creates a new instance of Handler class.
  96. GtkWidget* CreateNewHandler();
  97. // Adds an edit command to the key event.
  98. void EditCommandMatched(ui::TextEditCommand command,
  99. const std::string& value);
  100. // Initializes Handler structure.
  101. static void HandlerInit(Handler* self);
  102. // Initializes HandlerClass structure.
  103. static void HandlerClassInit(HandlerClass* klass);
  104. // Registeres Handler class to GObject type system and return its type id.
  105. static GType HandlerGetType();
  106. // Gets the GtkKeyBindingsHandler object which owns the Handler object.
  107. static GtkKeyBindingsHandler* GetHandlerOwner(GtkTextView* text_view);
  108. // Handler of "backspace" signal.
  109. static void BackSpace(GtkTextView* text_view);
  110. // Handler of "copy-clipboard" signal.
  111. static void CopyClipboard(GtkTextView* text_view);
  112. // Handler of "cut-clipboard" signal.
  113. static void CutClipboard(GtkTextView* text_view);
  114. // Handler of "delete-from-cursor" signal.
  115. static void DeleteFromCursor(GtkTextView* text_view,
  116. GtkDeleteType type,
  117. gint count);
  118. // Handler of "insert-at-cursor" signal.
  119. static void InsertAtCursor(GtkTextView* text_view, const gchar* str);
  120. // Handler of "move-cursor" signal.
  121. static void MoveCursor(GtkTextView* text_view,
  122. GtkMovementStep step,
  123. gint count,
  124. gboolean extend_selection);
  125. // Handler of "move-viewport" signal.
  126. static void MoveViewport(GtkTextView* text_view,
  127. GtkScrollStep step,
  128. gint count);
  129. // Handler of "paste-clipboard" signal.
  130. static void PasteClipboard(GtkTextView* text_view);
  131. // Handler of "select-all" signal.
  132. static void SelectAll(GtkTextView* text_view, gboolean select);
  133. // Handler of "set-anchor" signal.
  134. static void SetAnchor(GtkTextView* text_view);
  135. // Handler of "toggle-cursor-visible" signal.
  136. static void ToggleCursorVisible(GtkTextView* text_view);
  137. // Handler of "toggle-overwrite" signal.
  138. static void ToggleOverwrite(GtkTextView* text_view);
  139. // Handler of "show-help" signal.
  140. static gboolean ShowHelp(GtkWidget* widget, GtkWidgetHelpType arg1);
  141. // Handler of "move-focus" signal.
  142. static void MoveFocus(GtkWidget* widget, GtkDirectionType arg1);
  143. GtkWidget* fake_window_;
  144. GtkWidget* handler_;
  145. // Buffer to store the match results.
  146. std::vector<ui::TextEditCommandAuraLinux> edit_commands_;
  147. };
  148. } // namespace gtk
  149. #endif // UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_