summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/input_method/ibus_controller.h
blob: 49aac00cdd000a3f911964a57a1ee59c6fe969ca (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_IBUS_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_IBUS_CONTROLLER_H_

#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/logging.h"  // DCHECK
#include "base/string_split.h"

namespace chromeos {
namespace input_method {

// A structure which represents an input method. All methods in this class have
// to be in chromeos_input_method.h since Chrome also creates an instance of
// the class.
struct InputMethodDescriptor {
  InputMethodDescriptor() {
  }

  // Do not call this function directly. Use CreateInputMethodDescriptor() in
  // chromeos_input_method.cc whenever possible.
  InputMethodDescriptor(const std::string& in_id,
                        const std::string& in_display_name,
                        const std::string& in_keyboard_layout,
                        const std::string& in_virtual_keyboard_layouts,
                        const std::string& in_language_code)
      : virtual_keyboard_layouts_(in_virtual_keyboard_layouts),
        id(in_id),
        display_name(in_display_name),
        keyboard_layout(in_keyboard_layout),
        language_code(in_language_code) {
    DCHECK(keyboard_layout.find(",") == std::string::npos);
  }

  bool operator==(const InputMethodDescriptor& other) const {
    return (id == other.id);
  }

  // Debug print function.
  std::string ToString() const {
    std::stringstream stream;
    stream << "id=" << id
           << ", display_name=" << display_name
           << ", keyboard_layout=" << keyboard_layout
           << ", virtual_keyboard_layouts=" << virtual_keyboard_layouts_
           << ", language_code=" << language_code;
    return stream.str();
  }

  // TODO(yusukes): When libcros is moved to Chrome, do the following:
  // 1. Change the type of the virtual_keyboard_layouts_ variable to
  //    std::vector<std::string> and rename it back to virtual_keyboard_layouts.
  // 2. Remove the virtual_keyboard_layouts() function.
  // We can't do them right now because it will break ABI compatibility...
  std::vector<std::string> virtual_keyboard_layouts() const {
    std::vector<std::string> layout_names;
    base::SplitString(virtual_keyboard_layouts_, ',', &layout_names);
    return layout_names;
  }

  // Preferred virtual keyboard layouts for the input method. Comma separated
  // layout names in order of priority, such as "handwriting,us", could appear.
  // Note: DO NOT ACCESS THIS VARIABLE DIRECTLY. USE virtual_keyboard_layouts()
  // INSTEAD. SEE THE TODO ABOVE.
  std::string virtual_keyboard_layouts_;

  // An ID that identifies an input method engine (e.g., "t:latn-post",
  // "pinyin", "hangul").
  std::string id;
  // An input method name which can be used in the UI (e.g., "Pinyin").
  std::string display_name;
  // A preferred physical keyboard layout for the input method (e.g., "us",
  // "us(dvorak)", "jp"). Comma separated layout names do NOT appear.
  std::string keyboard_layout;
  // Language codes like "ko", "ja", "zh_CN", and "t".
  // "t" is used for languages in the "Others" category.
  std::string language_code;
};
typedef std::vector<InputMethodDescriptor> InputMethodDescriptors;

// A structure which represents a property for an input method engine. For
// details, please check a comment for the LanguageRegisterImePropertiesFunction
// typedef below.
// TODO(yusukes): Rename this struct. "InputMethodProperty" might be better?
struct ImeProperty {
  ImeProperty(const std::string& in_key,
              const std::string& in_label,
              bool in_is_selection_item,
              bool in_is_selection_item_checked,
              int in_selection_item_id)
      : key(in_key),
        label(in_label),
        is_selection_item(in_is_selection_item),
        is_selection_item_checked(in_is_selection_item_checked),
        selection_item_id(in_selection_item_id) {
    DCHECK(!key.empty());
  }

  ImeProperty()
      : is_selection_item(false),
        is_selection_item_checked(false),
        selection_item_id(kInvalidSelectionItemId) {
  }

  // Debug print function.
  std::string ToString() const {
    std::stringstream stream;
    stream << "key=" << key
           << ", label=" << label
           << ", is_selection_item=" << is_selection_item
           << ", is_selection_item_checked=" << is_selection_item_checked
           << ", selection_item_id=" << selection_item_id;
    return stream.str();
  }

  std::string key;  // A key which identifies the property. Non-empty string.
                    // (e.g. "InputMode.HalfWidthKatakana")
  // DEPRECATED: TODO(yusukes): Remove this when it's ready.
  std::string deprecated_icon_path;
  std::string label;  // A description of the property. Non-empty string.
                      // (e.g. "Switch to full punctuation mode", "Hiragana")
  bool is_selection_item;  // true if the property is a selection item.
  bool is_selection_item_checked;  // true if |is_selection_item| is true and
                                   // the selection_item is selected.
  int selection_item_id;  // A group ID (>= 0) of the selection item.
                          // kInvalidSelectionItemId if |is_selection_item| is
                          // false.
  static const int kInvalidSelectionItemId = -1;
};
typedef std::vector<ImeProperty> ImePropertyList;

// A structure which represents a value of an input method configuration item.
// This struct is used by SetImeConfig().
// TODO(yusukes): Rename this struct. "InputMethodConfigValue" might be better?
struct ImeConfigValue {
  ImeConfigValue()
      : type(kValueTypeString),
        int_value(0),
        bool_value(false) {
  }

  // Debug print function.
  std::string ToString() const {
    std::stringstream stream;
    stream << "type=" << type;
    switch (type) {
      case kValueTypeString:
        stream << ", string_value=" << string_value;
        break;
      case kValueTypeInt:
        stream << ", int_value=" << int_value;
        break;
      case kValueTypeBool:
        stream << ", bool_value=" << (bool_value ? "true" : "false");
        break;
      case kValueTypeStringList:
        stream << ", string_list_value=";
        for (size_t i = 0; i < string_list_value.size(); ++i) {
          if (i) {
            stream << ",";
          }
          stream << string_list_value[i];
        }
        break;
    }
    return stream.str();
  }

  enum ValueType {
    kValueTypeString = 0,
    kValueTypeInt,
    kValueTypeBool,
    kValueTypeStringList,
  };

  // A value is stored on |string_value| member if |type| is kValueTypeString.
  // The same is true for other enum values.
  ValueType type;

  std::string string_value;
  int int_value;
  bool bool_value;
  std::vector<std::string> string_list_value;
};

typedef std::vector<std::pair<double, double> > HandwritingStroke;

// IBusController is used to interact with the IBus daemon.
class IBusController {
 public:
  class Observer {
   public:
    virtual ~Observer() {}

    // Called when current input method is changed by a user.
    virtual void  OnCurrentInputMethodChanged(
        const InputMethodDescriptor& current_input_method) = 0;

    // Called when "RegisterProperties" signal is sent from
    // ibus-daemon. The signal contains a list of properties for a
    // specific input method engine. For example, Japanese input method
    // might have the following properties:
    //
    // ----------------------------------
    //   key: InputMode.Hiragana
    //   label: Hiragana
    //   is_selection_item: true
    //   is_selection_item_checked: true
    //   selection_item_id: 1
    // ----------------------------------
    //   key: InputMode.Katakana
    //   label: Katakana
    //   is_selection_item: true
    //   is_selection_item_checked: false
    //   selection_item_id: 1
    // ----------------------------------
    //   ...
    // ----------------------------------
    virtual void OnRegisterImeProperties(const ImePropertyList& prop_list) = 0;

    // Called when "UpdateProperty" signal is sent from ibus-daemon. The
    // signal contains one or more properties which is updated
    // recently. Keys the signal contains are a subset of keys registered
    // by the "RegisterProperties" signal above. For example, Japanese
    // input method might send the following properties:
    //
    // ----------------------------------
    //   key: InputMode.Hiragana
    //   label: Hiragana
    //   is_selection_item: true
    //   is_selection_item_checked: false
    //   selection_item_id: ...
    // ----------------------------------
    //   key: InputMode.Katakana
    //   label: Katakana
    //   is_selection_item: true
    //   is_selection_item_checked: true
    //   selection_item_id: ...
    // ----------------------------------
    //
    // Note: Please do not use selection_item_ids in |prop_list|. Dummy
    //       values are filled in the field.
    virtual void OnUpdateImeProperty(const ImePropertyList& prop_list) = 0;

    // Called when ibus connects or disconnects.
    virtual void OnConnectionChange(bool connected) = 0;
  };

  // Creates an instance of the class. The constructor is unused.
  static IBusController* Create();

  virtual ~IBusController();

  // Connects to the IBus daemon.
  virtual void Connect() = 0;

  // Adds and removes observers for IBus UI notifications. Clients must be
  // sure to remove the observer before they go away. To capture the
  // initial connection change, you should add an observer before calling
  // Connect().
  virtual void AddObserver(Observer* observer) = 0;
  virtual void RemoveObserver(Observer* observer) = 0;

  // Stops ibus-daemon. Returns true on success.
  virtual bool StopInputMethodProcess() = 0;

  // Changes the current input method engine to |name|. Returns true on
  // success.  Examples of names: "pinyin", "m17n:ar:kbd",
  // "xkb:us:dvorak:eng".
  virtual bool ChangeInputMethod(const std::string& name) = 0;

  // Sets whether the input method property specified by |key| is activated.
  // If |activated| is true, activates the property. If |activated| is false,
  // deactivates the property.
  // TODO(yusukes): "SetInputMethodPropertyActivated" might be better?
  virtual void SetImePropertyActivated(const std::string& key,
                                       bool activated) = 0;

  // Sets a configuration of ibus-daemon or IBus engines to |value|.
  // Returns true if the configuration is successfully set.
  //
  // To set 'panel/custom_font', |section| should be "panel", and
  // |config_name| should be "custom_font".
  // TODO(yusukes): "SetInputMethodConfig" might be better?
  virtual bool SetImeConfig(const std::string& section,
                            const std::string& config_name,
                            const ImeConfigValue& value) = 0;

  // Sends a handwriting stroke to ibus-daemon. The std::pair contains x
  // and y coordinates. (0.0, 0.0) represents the top-left corner of a
  // handwriting area, and (1.0, 1.0) does the bottom-right. For example,
  // the second stroke for U+30ED (Katakana character Ro) would be
  // something like [(0,0), (1,0), (1,1)].  stroke.size() should always be
  // >= 2 (i.e. a single dot is not allowed).
  virtual void SendHandwritingStroke(const HandwritingStroke& stroke) = 0;

  // Clears the last N handwriting strokes. Pass zero for clearing all strokes.
  // TODO(yusukes): Currently ibus-daemon only accepts 0 for |n_strokes|.
  virtual void CancelHandwriting(int n_strokes) = 0;
};

// Gets all input method engines that are supported, including ones not
// active.  Caller has to delete the returned list. This function never
// returns NULL.
InputMethodDescriptors* GetSupportedInputMethodDescriptors();

//
// FUNCTIONS BELOW ARE ONLY FOR UNIT TESTS. DO NOT USE THEM.
//
bool InputMethodIdIsWhitelisted(const std::string& input_method_id);
bool XkbLayoutIsSupported(const std::string& xkb_layout);
InputMethodDescriptor CreateInputMethodDescriptor(
    const std::string& id,
    const std::string& display_name,
    const std::string& raw_layout,
    const std::string& language_code);

}  // namespace input_method
}  // namespace chromeos

#endif  // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_IBUS_CONTROLLER_H_