Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: ui/base/ime/win/tsf_event_router.cc

Issue 11141019: Re-enable CJK omnibox suggest on Metro UI (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Address comments Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/base/ime/win/tsf_event_router.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "ui/base/ime/win/tsf_event_router.h" 5 #include "ui/base/ime/win/tsf_event_router.h"
6 6
7 #include <msctf.h> 7 #include <msctf.h>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/win/scoped_comptr.h" 12 #include "base/win/scoped_comptr.h"
13 #include "base/win/metro.h" 13 #include "base/win/metro.h"
14 14
15 namespace ui { 15 namespace ui {
16 16
17 class TsfEventRouterImpl : public TsfEventRouter, 17 class TsfEventRouterImpl : public TsfEventRouter,
18 public ITfUIElementSink, 18 public ITfUIElementSink,
19 public ITfTextEditSink { 19 public ITfTextEditSink {
20 public: 20 public:
21 TsfEventRouterImpl() 21 TsfEventRouterImpl()
22 : context_source_cookie_(TF_INVALID_COOKIE), 22 : observer_(NULL),
23 context_source_cookie_(TF_INVALID_COOKIE),
23 ui_source_cookie_(TF_INVALID_COOKIE), 24 ui_source_cookie_(TF_INVALID_COOKIE),
24 ref_count_(0) {} 25 ref_count_(0) {}
25 26
26 virtual ~TsfEventRouterImpl() {} 27 virtual ~TsfEventRouterImpl() {}
27 28
28 // ITfTextEditSink override. 29 // ITfTextEditSink override.
29 virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE { 30 virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
30 return InterlockedIncrement(&ref_count_); 31 return InterlockedIncrement(&ref_count_);
31 } 32 }
32 33
(...skipping 22 matching lines...) Expand all
55 AddRef(); 56 AddRef();
56 return S_OK; 57 return S_OK;
57 } 58 }
58 59
59 // ITfTextEditSink override. 60 // ITfTextEditSink override.
60 virtual STDMETHODIMP OnEndEdit(ITfContext* context, 61 virtual STDMETHODIMP OnEndEdit(ITfContext* context,
61 TfEditCookie read_only_cookie, 62 TfEditCookie read_only_cookie,
62 ITfEditRecord* edit_record) OVERRIDE { 63 ITfEditRecord* edit_record) OVERRIDE {
63 if (!edit_record || !context) 64 if (!edit_record || !context)
64 return E_INVALIDARG; 65 return E_INVALIDARG;
65 if (text_updated_callback_.is_null()) 66 if (!observer_)
66 return S_OK; 67 return S_OK;
67 68
68 // |edit_record| can be used to obtain updated ranges in terms of text 69 // |edit_record| can be used to obtain updated ranges in terms of text
69 // contents and/or text attributes. Here we are interested only in text 70 // contents and/or text attributes. Here we are interested only in text
70 // update so we use TF_GTP_INCL_TEXT and check if there is any range which 71 // update so we use TF_GTP_INCL_TEXT and check if there is any range which
71 // contains updated text. 72 // contains updated text.
72 base::win::ScopedComPtr<IEnumTfRanges> ranges; 73 base::win::ScopedComPtr<IEnumTfRanges> ranges;
73 if (FAILED(edit_record->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, 74 if (FAILED(edit_record->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT,
74 NULL, 75 NULL,
75 0, 76 0,
76 ranges.Receive()))) { 77 ranges.Receive()))) {
77 return S_OK; // don't care about failures. 78 return S_OK; // don't care about failures.
78 } 79 }
79 80
80 ULONG fetched_count = 0; 81 ULONG fetched_count = 0;
81 base::win::ScopedComPtr<ITfRange> range; 82 base::win::ScopedComPtr<ITfRange> range;
82 if (FAILED(ranges->Next(1, range.Receive(), &fetched_count))) 83 if (FAILED(ranges->Next(1, range.Receive(), &fetched_count)))
83 return S_OK; // don't care about failures. 84 return S_OK; // don't care about failures.
84 85
85 // |fetched_count| != 0 means there is at least one range that contains 86 // |fetched_count| != 0 means there is at least one range that contains
86 // updated texts. 87 // updated texts.
87 if (fetched_count != 0) 88 if (fetched_count != 0)
88 text_updated_callback_.Run(); 89 observer_->OnTextUpdated();
89 return S_OK; 90 return S_OK;
90 } 91 }
91 92
92 // ITfUiElementSink override. 93 // ITfUiElementSink override.
93 virtual STDMETHODIMP BeginUIElement(DWORD element_id, BOOL* is_show) { 94 virtual STDMETHODIMP BeginUIElement(DWORD element_id, BOOL* is_show) {
94 if (is_show) 95 if (is_show)
95 *is_show = TRUE; // without this the UI element will not be shown. 96 *is_show = TRUE; // without this the UI element will not be shown.
96 97
97 if (!IsCandidateWindowInternal(element_id)) 98 if (!IsCandidateWindowInternal(element_id))
98 return S_OK; 99 return S_OK;
99 100
100 std::pair<std::set<DWORD>::iterator, bool> insert_result = 101 std::pair<std::set<DWORD>::iterator, bool> insert_result =
101 open_candidate_window_ids_.insert(element_id); 102 open_candidate_window_ids_.insert(element_id);
102 103
103 if (candidat_window_count_changed_callback_.is_null()) 104 if (!observer_)
104 return S_OK; 105 return S_OK;
105 106
106 // Don't call if |element_id| is already handled. 107 // Don't call if |element_id| is already handled.
107 if (!insert_result.second) 108 if (!insert_result.second)
108 return S_OK; 109 return S_OK;
109 110
110 candidat_window_count_changed_callback_.Run( 111 observer_->OnCandidateWindowCountChanged(open_candidate_window_ids_.size());
111 open_candidate_window_ids_.size());
112 112
113 return S_OK; 113 return S_OK;
114 } 114 }
115 115
116 // ITfUiElementSink override. 116 // ITfUiElementSink override.
117 virtual STDMETHODIMP UpdateUIElement(DWORD element_id) { 117 virtual STDMETHODIMP UpdateUIElement(DWORD element_id) {
118 return S_OK; 118 return S_OK;
119 } 119 }
120 120
121 // ITfUiElementSink override. 121 // ITfUiElementSink override.
122 virtual STDMETHODIMP EndUIElement(DWORD element_id) { 122 virtual STDMETHODIMP EndUIElement(DWORD element_id) {
123 if (open_candidate_window_ids_.erase(element_id) == 0) 123 if (open_candidate_window_ids_.erase(element_id) == 0)
124 return S_OK; 124 return S_OK;
125 125
126 if (candidat_window_count_changed_callback_.is_null()) 126 if (!observer_)
127 return S_OK; 127 return S_OK;
128 128
129 candidat_window_count_changed_callback_.Run( 129 observer_->OnCandidateWindowCountChanged(open_candidate_window_ids_.size());
130 open_candidate_window_ids_.size());
131 130
132 return S_OK; 131 return S_OK;
133 } 132 }
134 133
135 // TsfEventRouter override. 134 // TsfEventRouter override.
136 virtual void SetManager(ITfThreadMgr* manager) OVERRIDE { 135 virtual void SetManager(ITfThreadMgr* manager, Observer* observer) OVERRIDE {
137 EnsureDeassociated(); 136 EnsureDeassociated();
138 if (manager) 137 if (manager && observer) {
139 Associate(manager); 138 Associate(manager, observer);
139 }
140 } 140 }
141 141
142 // TsfEventRouter override. 142 // TsfEventRouter override.
143 virtual bool IsImeComposing() OVERRIDE { 143 virtual bool IsImeComposing() OVERRIDE {
144 DCHECK(base::win::IsTsfAwareRequired()) 144 DCHECK(base::win::IsTsfAwareRequired())
145 << "Do not call without TSF environment."; 145 << "Do not call without TSF environment.";
146 if (!context_) 146 if (!context_)
147 return false; 147 return false;
148 return IsImeComposingInternal(context_); 148 return IsImeComposingInternal(context_);
149 } 149 }
150 150
151 // TsfEventRouter override.
152 virtual void SetTextUpdatedCallback(
153 const TextUpdatedCallback& callback) OVERRIDE {
154 text_updated_callback_ = callback;
155 }
156
157 // TsfEventRouter override.
158 virtual void SetCandidateWindowStatusChangedCallback(
159 const CandidateWindowCountChangedCallback& callback) OVERRIDE {
160 candidat_window_count_changed_callback_ = callback;
161 }
162
163 private: 151 private:
164 // Returns true if the given |context| is in composing. 152 // Returns true if the given |context| is in composing.
165 static bool IsImeComposingInternal(ITfContext* context) { 153 static bool IsImeComposingInternal(ITfContext* context) {
166 DCHECK(base::win::IsTsfAwareRequired()) 154 DCHECK(base::win::IsTsfAwareRequired())
167 << "Do not call without TSF environment."; 155 << "Do not call without TSF environment.";
168 DCHECK(context); 156 DCHECK(context);
169 base::win::ScopedComPtr<ITfContextComposition> context_composition; 157 base::win::ScopedComPtr<ITfContextComposition> context_composition;
170 if (FAILED(context_composition.QueryFrom(context))) 158 if (FAILED(context_composition.QueryFrom(context)))
171 return false; 159 return false;
172 base::win::ScopedComPtr<IEnumITfCompositionView> enum_composition_view; 160 base::win::ScopedComPtr<IEnumITfCompositionView> enum_composition_view;
(...skipping 12 matching lines...) Expand all
185 if (FAILED(ui_element_manager_->GetUIElement(element_id, 173 if (FAILED(ui_element_manager_->GetUIElement(element_id,
186 ui_element.Receive()))) { 174 ui_element.Receive()))) {
187 return false; 175 return false;
188 } 176 }
189 base::win::ScopedComPtr<ITfCandidateListUIElement> 177 base::win::ScopedComPtr<ITfCandidateListUIElement>
190 candidate_list_ui_element; 178 candidate_list_ui_element;
191 return SUCCEEDED(candidate_list_ui_element.QueryFrom(ui_element)); 179 return SUCCEEDED(candidate_list_ui_element.QueryFrom(ui_element));
192 } 180 }
193 181
194 // Associates this class with specified |manager|. 182 // Associates this class with specified |manager|.
195 void Associate(ITfThreadMgr* thread_manager) { 183 void Associate(ITfThreadMgr* thread_manager, Observer* observer) {
196 DCHECK(base::win::IsTsfAwareRequired()) 184 DCHECK(base::win::IsTsfAwareRequired())
197 << "Do not call without TSF environment."; 185 << "Do not call without TSF environment.";
198 DCHECK(thread_manager); 186 DCHECK(thread_manager);
199 187
200 base::win::ScopedComPtr<ITfDocumentMgr> document_manager; 188 base::win::ScopedComPtr<ITfDocumentMgr> document_manager;
201 if (FAILED(thread_manager->GetFocus(document_manager.Receive()))) 189 if (FAILED(thread_manager->GetFocus(document_manager.Receive())))
202 return; 190 return;
203 191
204 if (FAILED(document_manager->GetBase(context_.Receive()))) 192 if (FAILED(document_manager->GetBase(context_.Receive())))
205 return; 193 return;
206 if (FAILED(context_source_.QueryFrom(context_))) 194 if (FAILED(context_source_.QueryFrom(context_)))
207 return; 195 return;
208 context_source_->AdviseSink(IID_ITfTextEditSink, 196 context_source_->AdviseSink(IID_ITfTextEditSink,
209 static_cast<ITfTextEditSink*>(this), 197 static_cast<ITfTextEditSink*>(this),
210 &context_source_cookie_); 198 &context_source_cookie_);
211 199
212 if (FAILED(ui_element_manager_.QueryFrom(thread_manager))) 200 if (FAILED(ui_element_manager_.QueryFrom(thread_manager)))
213 return; 201 return;
214 if (FAILED(ui_source_.QueryFrom(ui_element_manager_))) 202 if (FAILED(ui_source_.QueryFrom(ui_element_manager_)))
215 return; 203 return;
216 ui_source_->AdviseSink(IID_ITfUIElementSink, 204 ui_source_->AdviseSink(IID_ITfUIElementSink,
217 static_cast<ITfUIElementSink*>(this), 205 static_cast<ITfUIElementSink*>(this),
218 &ui_source_cookie_); 206 &ui_source_cookie_);
207 observer_ = observer;
219 } 208 }
220 209
221 // Resets the association, this function is safe to call if there is no 210 // Resets the association, this function is safe to call if there is no
222 // associated thread manager. 211 // associated thread manager.
223 void EnsureDeassociated() { 212 void EnsureDeassociated() {
224 DCHECK(base::win::IsTsfAwareRequired()) 213 DCHECK(base::win::IsTsfAwareRequired())
225 << "Do not call without TSF environment."; 214 << "Do not call without TSF environment.";
226 215
227 context_.Release(); 216 context_.Release();
228 217
229 if (context_source_) { 218 if (context_source_) {
230 context_source_->UnadviseSink(context_source_cookie_); 219 context_source_->UnadviseSink(context_source_cookie_);
231 context_source_.Release(); 220 context_source_.Release();
232 } 221 }
233 context_source_cookie_ = TF_INVALID_COOKIE; 222 context_source_cookie_ = TF_INVALID_COOKIE;
234 223
235 ui_element_manager_.Release(); 224 ui_element_manager_.Release();
236 if (ui_source_) { 225 if (ui_source_) {
237 ui_source_->UnadviseSink(ui_source_cookie_); 226 ui_source_->UnadviseSink(ui_source_cookie_);
238 ui_source_.Release(); 227 ui_source_.Release();
239 } 228 }
240 ui_source_cookie_ = TF_INVALID_COOKIE; 229 ui_source_cookie_ = TF_INVALID_COOKIE;
230
231 observer_ = NULL;
241 } 232 }
242 233
243 // Callback function fired when the text contents are updated. 234 Observer* observer_;
244 TextUpdatedCallback text_updated_callback_;
245
246 CandidateWindowCountChangedCallback candidat_window_count_changed_callback_;
247 235
248 // A context associated with this class. 236 // A context associated with this class.
249 base::win::ScopedComPtr<ITfContext> context_; 237 base::win::ScopedComPtr<ITfContext> context_;
250 238
251 // The ITfSource associated with |context_|. 239 // The ITfSource associated with |context_|.
252 base::win::ScopedComPtr<ITfSource> context_source_; 240 base::win::ScopedComPtr<ITfSource> context_source_;
253 241
254 // The cookie for |context_source_|. 242 // The cookie for |context_source_|.
255 DWORD context_source_cookie_; 243 DWORD context_source_cookie_;
256 244
(...skipping 22 matching lines...) Expand all
279 } 267 }
280 268
281 TsfEventRouter::~TsfEventRouter() { 269 TsfEventRouter::~TsfEventRouter() {
282 } 270 }
283 271
284 TsfEventRouter* TsfEventRouter::Create() { 272 TsfEventRouter* TsfEventRouter::Create() {
285 return new TsfEventRouterImpl(); 273 return new TsfEventRouterImpl();
286 } 274 }
287 275
288 } // namespace ui 276 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/win/tsf_event_router.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698