| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef UI_BASE_IME_WIN_TSF_TEXT_STORE_H_ | 5 #ifndef WIN8_METRO_DRIVER_IME_TEXT_STORE_H_ |
| 6 #define UI_BASE_IME_WIN_TSF_TEXT_STORE_H_ | 6 #define WIN8_METRO_DRIVER_IME_TEXT_STORE_H_ |
| 7 | 7 |
| 8 #include <inputscope.h> |
| 8 #include <msctf.h> | 9 #include <msctf.h> |
| 10 |
| 9 #include <deque> | 11 #include <deque> |
| 12 #include <vector> |
| 10 | 13 |
| 11 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
| 12 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
| 13 #include "base/strings/string16.h" | 16 #include "base/strings/string16.h" |
| 14 #include "base/win/scoped_comptr.h" | 17 #include "base/win/scoped_comptr.h" |
| 15 #include "ui/base/ime/composition_underline.h" | 18 #include "ui/metro_viewer/ime_types.h" |
| 16 #include "ui/base/ui_export.h" | |
| 17 #include "ui/gfx/range/range.h" | |
| 18 | 19 |
| 19 namespace ui { | 20 namespace metro_driver { |
| 20 class TextInputClient; | |
| 21 | 21 |
| 22 // TSFTextStore is used to interact with the input method via TSF manager. | 22 class TextStoreDelegate; |
| 23 // TSFTextStore have a string buffer which is manipulated by TSF manager through | 23 |
| 24 // TextStore is used to interact with the input method via TSF manager. |
| 25 // TextStore have a string buffer which is manipulated by TSF manager through |
| 24 // ITextStoreACP interface methods such as SetText(). | 26 // ITextStoreACP interface methods such as SetText(). |
| 25 // When the input method updates the composition, TSFTextStore calls | 27 // When the input method updates the composition, TextStore calls |
| 26 // TextInputClient::SetCompositionText(). And when the input method finishes the | 28 // TextInputClient::SetCompositionText(). And when the input method finishes the |
| 27 // composition, TSFTextStore calls TextInputClient::InsertText() and clears the | 29 // composition, TextStore calls TextInputClient::InsertText() and clears the |
| 28 // buffer. | 30 // buffer. |
| 29 // | 31 // |
| 30 // How TSFTextStore works: | 32 // How TextStore works: |
| 31 // - The user enters "a". | 33 // - The user enters "a". |
| 32 // - The input method set composition as "a". | 34 // - The input method set composition as "a". |
| 33 // - TSF manager calls TSFTextStore::RequestLock(). | 35 // - TSF manager calls TextStore::RequestLock(). |
| 34 // - TSFTextStore callbacks ITextStoreACPSink::OnLockGranted(). | 36 // - TextStore callbacks ITextStoreACPSink::OnLockGranted(). |
| 35 // - In OnLockGranted(), TSF manager calls | 37 // - In OnLockGranted(), TSF manager calls |
| 36 // - TSFTextStore::OnStartComposition() | 38 // - TextStore::OnStartComposition() |
| 37 // - TSFTextStore::SetText() | 39 // - TextStore::SetText() |
| 38 // The string buffer is set as "a". | 40 // The string buffer is set as "a". |
| 39 // - TSFTextStore::OnUpdateComposition() | 41 // - TextStore::OnUpdateComposition() |
| 40 // - TSFTextStore::OnEndEdit() | 42 // - TextStore::OnEndEdit() |
| 41 // TSFTextStore can get the composition information such as underlines. | 43 // TextStore can get the composition information such as underlines. |
| 42 // - TSFTextStore calls TextInputClient::SetCompositionText(). | 44 // - TextStore calls TextInputClient::SetCompositionText(). |
| 43 // "a" is shown with an underline as composition string. | 45 // "a" is shown with an underline as composition string. |
| 44 // - The user enters <space>. | 46 // - The user enters <space>. |
| 45 // - The input method set composition as "A". | 47 // - The input method set composition as "A". |
| 46 // - TSF manager calls TSFTextStore::RequestLock(). | 48 // - TSF manager calls TextStore::RequestLock(). |
| 47 // - TSFTextStore callbacks ITextStoreACPSink::OnLockGranted(). | 49 // - TextStore callbacks ITextStoreACPSink::OnLockGranted(). |
| 48 // - In OnLockGranted(), TSF manager calls | 50 // - In OnLockGranted(), TSF manager calls |
| 49 // - TSFTextStore::SetText() | 51 // - TextStore::SetText() |
| 50 // The string buffer is set as "A". | 52 // The string buffer is set as "A". |
| 51 // - TSFTextStore::OnUpdateComposition() | 53 // - TextStore::OnUpdateComposition() |
| 52 // - TSFTextStore::OnEndEdit() | 54 // - TextStore::OnEndEdit() |
| 53 // - TSFTextStore calls TextInputClient::SetCompositionText(). | 55 // - TextStore calls TextInputClient::SetCompositionText(). |
| 54 // "A" is shown with an underline as composition string. | 56 // "A" is shown with an underline as composition string. |
| 55 // - The user enters <enter>. | 57 // - The user enters <enter>. |
| 56 // - The input method commits "A". | 58 // - The input method commits "A". |
| 57 // - TSF manager calls TSFTextStore::RequestLock(). | 59 // - TSF manager calls TextStore::RequestLock(). |
| 58 // - TSFTextStore callbacks ITextStoreACPSink::OnLockGranted(). | 60 // - TextStore callbacks ITextStoreACPSink::OnLockGranted(). |
| 59 // - In OnLockGranted(), TSF manager calls | 61 // - In OnLockGranted(), TSF manager calls |
| 60 // - TSFTextStore::OnEndComposition() | 62 // - TextStore::OnEndComposition() |
| 61 // - TSFTextStore::OnEndEdit() | 63 // - TextStore::OnEndEdit() |
| 62 // TSFTextStore knows "A" is committed. | 64 // TextStore knows "A" is committed. |
| 63 // - TSFTextStore calls TextInputClient::InsertText(). | 65 // - TextStore calls TextInputClient::InsertText(). |
| 64 // "A" is shown as committed string. | 66 // "A" is shown as committed string. |
| 65 // - TSFTextStore clears the string buffer. | 67 // - TextStore clears the string buffer. |
| 66 // - TSFTextStore calls OnSelectionChange(), OnLayoutChange() and | 68 // - TextStore calls OnSelectionChange(), OnLayoutChange() and |
| 67 // OnTextChange() of ITextStoreACPSink to let TSF manager know that the | 69 // OnTextChange() of ITextStoreACPSink to let TSF manager know that the |
| 68 // string buffer has been changed. | 70 // string buffer has been changed. |
| 69 // | 71 // |
| 70 // About the locking scheme: | 72 // About the locking scheme: |
| 71 // When TSF manager manipulates the string buffer it calls RequestLock() to get | 73 // When TSF manager manipulates the string buffer it calls RequestLock() to get |
| 72 // the lock of the document. If TSFTextStore can grant the lock request, it | 74 // the lock of the document. If TextStore can grant the lock request, it |
| 73 // callbacks ITextStoreACPSink::OnLockGranted(). | 75 // callbacks ITextStoreACPSink::OnLockGranted(). |
| 74 // RequestLock() is called from only one thread, but called recursively in | 76 // RequestLock() is called from only one thread, but called recursively in |
| 75 // OnLockGranted() or OnSelectionChange() or OnLayoutChange() or OnTextChange(). | 77 // OnLockGranted() or OnSelectionChange() or OnLayoutChange() or OnTextChange(). |
| 76 // If the document is locked and the lock request is asynchronous, TSFTextStore | 78 // If the document is locked and the lock request is asynchronous, TextStore |
| 77 // queues the request. The queued requests will be handled after the current | 79 // queues the request. The queued requests will be handled after the current |
| 78 // lock is removed. | 80 // lock is removed. |
| 79 // More information about document locks can be found here: | 81 // More information about document locks can be found here: |
| 80 // http://msdn.microsoft.com/en-us/library/ms538064 | 82 // http://msdn.microsoft.com/en-us/library/ms538064 |
| 81 // | 83 // |
| 82 // More information about TSF can be found here: | 84 // More information about TSF can be found here: |
| 83 // http://msdn.microsoft.com/en-us/library/ms629032 | 85 // http://msdn.microsoft.com/en-us/library/ms629032 |
| 84 class UI_EXPORT TSFTextStore : public ITextStoreACP, | 86 class TextStore : public ITextStoreACP, |
| 85 public ITfContextOwnerCompositionSink, | 87 public ITfContextOwnerCompositionSink, |
| 86 public ITfTextEditSink { | 88 public ITfTextEditSink { |
| 87 public: | 89 public: |
| 88 TSFTextStore(); | 90 TextStore(HWND window_handle, |
| 89 virtual ~TSFTextStore(); | 91 const std::vector<InputScope>& input_scopes, |
| 92 TextStoreDelegate* delegate); |
| 93 virtual ~TextStore(); |
| 90 | 94 |
| 91 // ITextStoreACP: | 95 // ITextStoreACP: |
| 92 STDMETHOD_(ULONG, AddRef)() OVERRIDE; | 96 STDMETHOD_(ULONG, AddRef)() OVERRIDE; |
| 93 STDMETHOD_(ULONG, Release)() OVERRIDE; | 97 STDMETHOD_(ULONG, Release)() OVERRIDE; |
| 94 STDMETHOD(QueryInterface)(REFIID iid, void** ppv) OVERRIDE; | 98 STDMETHOD(QueryInterface)(REFIID iid, void** ppv) OVERRIDE; |
| 95 STDMETHOD(AdviseSink)(REFIID iid, IUnknown* unknown, DWORD mask) OVERRIDE; | 99 STDMETHOD(AdviseSink)(REFIID iid, IUnknown* unknown, DWORD mask) OVERRIDE; |
| 96 STDMETHOD(FindNextAttrTransition)(LONG acp_start, | 100 STDMETHOD(FindNextAttrTransition)(LONG acp_start, |
| 97 LONG acp_halt, | 101 LONG acp_halt, |
| 98 ULONG num_filter_attributes, | 102 ULONG num_filter_attributes, |
| 99 const TS_ATTRID* filter_attributes, | 103 const TS_ATTRID* filter_attributes, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 STDMETHOD(UnadviseSink)(IUnknown* unknown) OVERRIDE; | 190 STDMETHOD(UnadviseSink)(IUnknown* unknown) OVERRIDE; |
| 187 | 191 |
| 188 // ITfContextOwnerCompositionSink: | 192 // ITfContextOwnerCompositionSink: |
| 189 STDMETHOD(OnStartComposition)(ITfCompositionView* composition_view, | 193 STDMETHOD(OnStartComposition)(ITfCompositionView* composition_view, |
| 190 BOOL* ok) OVERRIDE; | 194 BOOL* ok) OVERRIDE; |
| 191 STDMETHOD(OnUpdateComposition)(ITfCompositionView* composition_view, | 195 STDMETHOD(OnUpdateComposition)(ITfCompositionView* composition_view, |
| 192 ITfRange* range) OVERRIDE; | 196 ITfRange* range) OVERRIDE; |
| 193 STDMETHOD(OnEndComposition)(ITfCompositionView* composition_view) OVERRIDE; | 197 STDMETHOD(OnEndComposition)(ITfCompositionView* composition_view) OVERRIDE; |
| 194 | 198 |
| 195 // ITfTextEditSink: | 199 // ITfTextEditSink: |
| 196 STDMETHOD(OnEndEdit)(ITfContext* context, TfEditCookie read_only_edit_cookie, | 200 STDMETHOD(OnEndEdit)(ITfContext* context, |
| 201 TfEditCookie read_only_edit_cookie, |
| 197 ITfEditRecord* edit_record) OVERRIDE; | 202 ITfEditRecord* edit_record) OVERRIDE; |
| 198 | 203 |
| 199 // Sets currently focused TextInputClient. | |
| 200 void SetFocusedTextInputClient(HWND focused_window, | |
| 201 TextInputClient* text_input_client); | |
| 202 // Removes currently focused TextInputClient. | |
| 203 void RemoveFocusedTextInputClient(TextInputClient* text_input_client); | |
| 204 | |
| 205 // Cancels the ongoing composition if exists. | 204 // Cancels the ongoing composition if exists. |
| 206 bool CancelComposition(); | 205 bool CancelComposition(); |
| 207 | 206 |
| 208 // Confirms the ongoing composition if exists. | 207 // Confirms the ongoing composition if exists. |
| 209 bool ConfirmComposition(); | 208 bool ConfirmComposition(); |
| 210 | 209 |
| 211 // Sends OnLayoutChange() via |text_store_acp_sink_|. | 210 // Sends OnLayoutChange() via |text_store_acp_sink_|. |
| 212 void SendOnLayoutChange(); | 211 void SendOnLayoutChange(); |
| 213 | 212 |
| 214 private: | 213 private: |
| 215 friend class TSFTextStoreTest; | |
| 216 friend class TSFTextStoreTestCallback; | |
| 217 | |
| 218 // Checks if the document has a read-only lock. | 214 // Checks if the document has a read-only lock. |
| 219 bool HasReadLock() const; | 215 bool HasReadLock() const; |
| 220 | 216 |
| 221 // Checks if the document has a read and write lock. | 217 // Checks if the document has a read and write lock. |
| 222 bool HasReadWriteLock() const; | 218 bool HasReadWriteLock() const; |
| 223 | 219 |
| 224 // Gets the display attribute structure. | 220 // Gets the display attribute structure. |
| 225 bool GetDisplayAttribute(TfGuidAtom guid_atom, | 221 bool GetDisplayAttribute(TfGuidAtom guid_atom, |
| 226 TF_DISPLAYATTRIBUTE* attribute); | 222 TF_DISPLAYATTRIBUTE* attribute); |
| 227 | 223 |
| 228 // Gets the committed string size and underline information of the context. | 224 // Gets the committed string size and underline information of the context. |
| 229 bool GetCompositionStatus(ITfContext* context, | 225 bool GetCompositionStatus( |
| 230 const TfEditCookie read_only_edit_cookie, | 226 ITfContext* context, |
| 231 size_t* committed_size, | 227 const TfEditCookie read_only_edit_cookie, |
| 232 CompositionUnderlines* undelines); | 228 size_t* committed_size, |
| 229 std::vector<metro_viewer::UnderlineInfo>* undelines); |
| 233 | 230 |
| 234 // The refrence count of this instance. | 231 // The refrence count of this instance. |
| 235 volatile LONG ref_count_; | 232 volatile LONG ref_count_; |
| 236 | 233 |
| 237 // A pointer of ITextStoreACPSink, this instance is given in AdviseSink. | 234 // A pointer of ITextStoreACPSink, this instance is given in AdviseSink. |
| 238 base::win::ScopedComPtr<ITextStoreACPSink> text_store_acp_sink_; | 235 base::win::ScopedComPtr<ITextStoreACPSink> text_store_acp_sink_; |
| 239 | 236 |
| 240 // The current mask of |text_store_acp_sink_|. | 237 // The current mask of |text_store_acp_sink_|. |
| 241 DWORD text_store_acp_sink_mask_; | 238 DWORD text_store_acp_sink_mask_; |
| 242 | 239 |
| 243 // HWND of the current view window which is set in SetFocusedTextInputClient. | 240 // HWND of the attached window. |
| 244 HWND window_handle_; | 241 HWND window_handle_; |
| 245 | 242 |
| 246 // Current TextInputClient which is set in SetFocusedTextInputClient. | 243 // The delegate attached to this text store. |
| 247 TextInputClient* text_input_client_; | 244 TextStoreDelegate* delegate_; |
| 248 | 245 |
| 249 // |string_buffer_| contains committed string and composition string. | 246 // |string_buffer_| contains committed string and composition string. |
| 250 // Example: "aoi" is committed, and "umi" is under composition. | 247 // Example: "aoi" is committed, and "umi" is under composition. |
| 251 // |string_buffer_|: "aoiumi" | 248 // |string_buffer_|: "aoiumi" |
| 252 // |committed_size_|: 3 | 249 // |committed_size_|: 3 |
| 253 string16 string_buffer_; | 250 string16 string_buffer_; |
| 254 size_t committed_size_; | 251 size_t committed_size_; |
| 255 | 252 |
| 256 // |selection_start_| and |selection_end_| indicates the selection range. | 253 // |selection_start_| and |selection_end_| indicates the selection range. |
| 257 // Example: "iue" is selected | 254 // Example: "iue" is selected |
| 258 // |string_buffer_|: "aiueo" | 255 // |string_buffer_|: "aiueo" |
| 259 // |selection_.start()|: 1 | 256 // |selection_start_|: 1 |
| 260 // |selection_.end()|: 4 | 257 // |selection_end_|: 4 |
| 261 gfx::Range selection_; | 258 size_t selection_start_; |
| 259 size_t selection_end_; |
| 262 | 260 |
| 263 // |start_offset| and |end_offset| of |composition_undelines_| indicates | 261 // |start_offset| and |end_offset| of |composition_undelines_| indicates |
| 264 // the offsets in |string_buffer_|. | 262 // the offsets in |string_buffer_|. |
| 265 // Example: "aoi" is committed. There are two underlines in "umi" and "no". | 263 // Example: "aoi" is committed. There are two underlines in "umi" and "no". |
| 266 // |string_buffer_|: "aoiumino" | 264 // |string_buffer_|: "aoiumino" |
| 267 // |committed_size_|: 3 | 265 // |committed_size_|: 3 |
| 268 // composition_undelines_.underlines[0].start_offset: 3 | 266 // underlines_[0].start_offset: 3 |
| 269 // composition_undelines_.underlines[0].end_offset: 6 | 267 // underlines_[0].end_offset: 6 |
| 270 // composition_undelines_.underlines[1].start_offset: 6 | 268 // underlines_[1].start_offset: 6 |
| 271 // composition_undelines_.underlines[1].end_offset: 8 | 269 // underlines_[1].end_offset: 8 |
| 272 CompositionUnderlines composition_undelines_; | 270 std::vector<metro_viewer::UnderlineInfo> underlines_; |
| 273 | 271 |
| 274 // |edit_flag_| indicates that the status is edited during | 272 // |edit_flag_| indicates that the status is edited during |
| 275 // ITextStoreACPSink::OnLockGranted(). | 273 // ITextStoreACPSink::OnLockGranted(). |
| 276 bool edit_flag_; | 274 bool edit_flag_; |
| 277 | 275 |
| 278 // The type of current lock. | 276 // The type of current lock. |
| 279 // 0: No lock. | 277 // 0: No lock. |
| 280 // TS_LF_READ: read-only lock. | 278 // TS_LF_READ: read-only lock. |
| 281 // TS_LF_READWRITE: read/write lock. | 279 // TS_LF_READWRITE: read/write lock. |
| 282 DWORD current_lock_type_; | 280 DWORD current_lock_type_; |
| 283 | 281 |
| 284 // Queue of the lock request used in RequestLock(). | 282 // Queue of the lock request used in RequestLock(). |
| 285 std::deque<DWORD> lock_queue_; | 283 std::deque<DWORD> lock_queue_; |
| 286 | 284 |
| 287 // Category manager and Display attribute manager are used to obtain the | 285 // Category manager and Display attribute manager are used to obtain the |
| 288 // attributes of the composition string. | 286 // attributes of the composition string. |
| 289 base::win::ScopedComPtr<ITfCategoryMgr> category_manager_; | 287 base::win::ScopedComPtr<ITfCategoryMgr> category_manager_; |
| 290 base::win::ScopedComPtr<ITfDisplayAttributeMgr> display_attribute_manager_; | 288 base::win::ScopedComPtr<ITfDisplayAttributeMgr> display_attribute_manager_; |
| 289 base::win::ScopedComPtr<IUnknown> input_scope_; |
| 291 | 290 |
| 292 DISALLOW_COPY_AND_ASSIGN(TSFTextStore); | 291 DISALLOW_COPY_AND_ASSIGN(TextStore); |
| 293 }; | 292 }; |
| 294 | 293 |
| 295 } // namespace ui | 294 } // namespace metro_driver |
| 296 | 295 |
| 297 #endif // UI_BASE_IME_WIN_TSF_TEXT_STORE_H_ | 296 #endif // WIN8_METRO_DRIVER_IME_TEXT_STORE_H_ |
| OLD | NEW |