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

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

Issue 11305002: Support TSF related event handling on NativeTextField (Closed) Base URL: http://git.chromium.org/chromium/src.git@findbar_fix
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') | ui/views/controls/textfield/native_textfield_win.h » ('j') | 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 #include "ui/base/range/range.h"
14 #include "ui/base/win/atl_module.h" 15 #include "ui/base/win/atl_module.h"
15 16
16 namespace ui { 17 namespace ui {
17 18
18 19
19 // TsfEventRouter::TsfEventRouterDelegate ------------------------------------ 20 // TsfEventRouter::TsfEventRouterDelegate ------------------------------------
20 21
21 // The implementation class of ITfUIElementSink, whose member functions will be 22 // The implementation class of ITfUIElementSink, whose member functions will be
22 // called back by TSF when the UI element status is changed, for example when 23 // called back by TSF when the UI element status is changed, for example when
23 // the candidate window is opened or closed. This class also implements 24 // the candidate window is opened or closed. This class also implements
(...skipping 25 matching lines...) Expand all
49 // Sets |thread_manager| to be monitored. |thread_manager| can be NULL. 50 // Sets |thread_manager| to be monitored. |thread_manager| can be NULL.
50 void SetManager(ITfThreadMgr* thread_manager); 51 void SetManager(ITfThreadMgr* thread_manager);
51 52
52 // Returns true if the IME is composing text. 53 // Returns true if the IME is composing text.
53 bool IsImeComposing(); 54 bool IsImeComposing();
54 55
55 // Sets |router| to be forwarded TSF-related events. 56 // Sets |router| to be forwarded TSF-related events.
56 void SetRouter(TsfEventRouter* router); 57 void SetRouter(TsfEventRouter* router);
57 58
58 private: 59 private:
59 // Returns true if the given |context| is composing. 60 // Returns current composition range. Returns ui::Range::InvalidRange if there
60 static bool IsImeComposingInternal(ITfContext* context); 61 // is no composition.
62 static ui::Range GetCompositionRange(ITfContext* context);
61 63
62 // Returns true if the given |element_id| represents the candidate window. 64 // Returns true if the given |element_id| represents the candidate window.
63 bool IsCandidateWindowInternal(DWORD element_id); 65 bool IsCandidateWindowInternal(DWORD element_id);
64 66
65 // A context associated with this class. 67 // A context associated with this class.
66 base::win::ScopedComPtr<ITfContext> context_; 68 base::win::ScopedComPtr<ITfContext> context_;
67 69
68 // The ITfSource associated with |context_|. 70 // The ITfSource associated with |context_|.
69 base::win::ScopedComPtr<ITfSource> context_source_; 71 base::win::ScopedComPtr<ITfSource> context_source_;
70 72
71 // The cookie for |context_source_|. 73 // The cookie for |context_source_|.
72 DWORD context_source_cookie_; 74 DWORD context_source_cookie_;
73 75
74 // A UIElementMgr associated with this class. 76 // A UIElementMgr associated with this class.
75 base::win::ScopedComPtr<ITfUIElementMgr> ui_element_manager_; 77 base::win::ScopedComPtr<ITfUIElementMgr> ui_element_manager_;
76 78
77 // The ITfSouce associated with |ui_element_manager_|. 79 // The ITfSouce associated with |ui_element_manager_|.
78 base::win::ScopedComPtr<ITfSource> ui_source_; 80 base::win::ScopedComPtr<ITfSource> ui_source_;
79 81
80 // The set of currently opened candidate window ids. 82 // The set of currently opened candidate window ids.
81 std::set<DWORD> open_candidate_window_ids_; 83 std::set<DWORD> open_candidate_window_ids_;
82 84
83 // The cookie for |ui_source_|. 85 // The cookie for |ui_source_|.
84 DWORD ui_source_cookie_; 86 DWORD ui_source_cookie_;
85 87
86 TsfEventRouter* router_; 88 TsfEventRouter* router_;
89 ui::Range previous_composition_range_;
87 90
88 DISALLOW_COPY_AND_ASSIGN(TsfEventRouterDelegate); 91 DISALLOW_COPY_AND_ASSIGN(TsfEventRouterDelegate);
89 }; 92 };
90 93
91 TsfEventRouter::TsfEventRouterDelegate::TsfEventRouterDelegate() 94 TsfEventRouter::TsfEventRouterDelegate::TsfEventRouterDelegate()
92 : context_source_cookie_(TF_INVALID_COOKIE), 95 : context_source_cookie_(TF_INVALID_COOKIE),
93 ui_source_cookie_(TF_INVALID_COOKIE), 96 ui_source_cookie_(TF_INVALID_COOKIE),
94 router_(NULL) { 97 router_(NULL),
98 previous_composition_range_(ui::Range::InvalidRange()) {
95 } 99 }
96 100
97 TsfEventRouter::TsfEventRouterDelegate::~TsfEventRouterDelegate() {} 101 TsfEventRouter::TsfEventRouterDelegate::~TsfEventRouterDelegate() {}
98 102
99 void TsfEventRouter::TsfEventRouterDelegate::SetRouter(TsfEventRouter* router) { 103 void TsfEventRouter::TsfEventRouterDelegate::SetRouter(TsfEventRouter* router) {
100 router_ = router; 104 router_ = router;
101 } 105 }
102 106
103 STDMETHODIMP TsfEventRouter::TsfEventRouterDelegate::OnEndEdit( 107 STDMETHODIMP TsfEventRouter::TsfEventRouterDelegate::OnEndEdit(
104 ITfContext* context, 108 ITfContext* context,
(...skipping 11 matching lines...) Expand all
116 base::win::ScopedComPtr<IEnumTfRanges> ranges; 120 base::win::ScopedComPtr<IEnumTfRanges> ranges;
117 if (FAILED(edit_record->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, NULL, 0, 121 if (FAILED(edit_record->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, NULL, 0,
118 ranges.Receive()))) 122 ranges.Receive())))
119 return S_OK; // Don't care about failures. 123 return S_OK; // Don't care about failures.
120 124
121 ULONG fetched_count = 0; 125 ULONG fetched_count = 0;
122 base::win::ScopedComPtr<ITfRange> range; 126 base::win::ScopedComPtr<ITfRange> range;
123 if (FAILED(ranges->Next(1, range.Receive(), &fetched_count))) 127 if (FAILED(ranges->Next(1, range.Receive(), &fetched_count)))
124 return S_OK; // Don't care about failures. 128 return S_OK; // Don't care about failures.
125 129
130 const ui::Range composition_range = GetCompositionRange(context);
131
132 if (!previous_composition_range_.IsValid() && composition_range.IsValid())
133 router_->OnTsfStartComposition();
134
126 // |fetched_count| != 0 means there is at least one range that contains 135 // |fetched_count| != 0 means there is at least one range that contains
127 // updated text. 136 // updated text.
128 if (fetched_count != 0) 137 if (fetched_count != 0)
129 router_->OnTextUpdated(); 138 router_->OnTextUpdated(composition_range);
139
140 if (previous_composition_range_.IsValid() && !composition_range.IsValid())
141 router_->OnTsfEndComposition();
142
143 previous_composition_range_ = composition_range;
130 return S_OK; 144 return S_OK;
131 } 145 }
132 146
133 STDMETHODIMP TsfEventRouter::TsfEventRouterDelegate::BeginUIElement( 147 STDMETHODIMP TsfEventRouter::TsfEventRouterDelegate::BeginUIElement(
134 DWORD element_id, 148 DWORD element_id,
135 BOOL* is_show) { 149 BOOL* is_show) {
136 if (is_show) 150 if (is_show)
137 *is_show = TRUE; // Without this the UI element will not be shown. 151 *is_show = TRUE; // Without this the UI element will not be shown.
138 152
139 if (!IsCandidateWindowInternal(element_id)) 153 if (!IsCandidateWindowInternal(element_id))
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 205
192 if (FAILED(ui_element_manager_.QueryFrom(thread_manager)) || 206 if (FAILED(ui_element_manager_.QueryFrom(thread_manager)) ||
193 FAILED(ui_source_.QueryFrom(ui_element_manager_))) 207 FAILED(ui_source_.QueryFrom(ui_element_manager_)))
194 return; 208 return;
195 ui_source_->AdviseSink(IID_ITfUIElementSink, 209 ui_source_->AdviseSink(IID_ITfUIElementSink,
196 static_cast<ITfUIElementSink*>(this), 210 static_cast<ITfUIElementSink*>(this),
197 &ui_source_cookie_); 211 &ui_source_cookie_);
198 } 212 }
199 213
200 bool TsfEventRouter::TsfEventRouterDelegate::IsImeComposing() { 214 bool TsfEventRouter::TsfEventRouterDelegate::IsImeComposing() {
201 return context_ && IsImeComposingInternal(context_); 215 return context_ && GetCompositionRange(context_).IsValid();
202 } 216 }
203 217
204 // static 218 // static
205 bool TsfEventRouter::TsfEventRouterDelegate::IsImeComposingInternal( 219 ui::Range TsfEventRouter::TsfEventRouterDelegate::GetCompositionRange(
206 ITfContext* context) { 220 ITfContext* context) {
207 DCHECK(context); 221 DCHECK(context);
208 base::win::ScopedComPtr<ITfContextComposition> context_composition; 222 base::win::ScopedComPtr<ITfContextComposition> context_composition;
209 if (FAILED(context_composition.QueryFrom(context))) 223 if (FAILED(context_composition.QueryFrom(context)))
210 return false; 224 return ui::Range::InvalidRange();
211 base::win::ScopedComPtr<IEnumITfCompositionView> enum_composition_view; 225 base::win::ScopedComPtr<IEnumITfCompositionView> enum_composition_view;
212 if (FAILED(context_composition->EnumCompositions( 226 if (FAILED(context_composition->EnumCompositions(
213 enum_composition_view.Receive()))) 227 enum_composition_view.Receive())))
214 return false; 228 return ui::Range::InvalidRange();
215 base::win::ScopedComPtr<ITfCompositionView> composition_view; 229 base::win::ScopedComPtr<ITfCompositionView> composition_view;
216 return enum_composition_view->Next(1, composition_view.Receive(), 230 if (enum_composition_view->Next(1, composition_view.Receive(),
217 NULL) == S_OK; 231 NULL) != S_OK)
232 return ui::Range::InvalidRange();
233
234 base::win::ScopedComPtr<ITfRange> range;
235 if (FAILED(composition_view->GetRange(range.Receive())))
236 return ui::Range::InvalidRange();
237
238 base::win::ScopedComPtr<ITfRangeACP> range_acp;
239 if (FAILED(range_acp.QueryFrom(range)))
240 return ui::Range::InvalidRange();
241
242 LONG start = 0;
243 LONG length = 0;
244 if (FAILED(range_acp->GetExtent(&start, &length)))
245 return ui::Range::InvalidRange();
246
247 return ui::Range(start, start + length);
218 } 248 }
219 249
220 bool TsfEventRouter::TsfEventRouterDelegate::IsCandidateWindowInternal( 250 bool TsfEventRouter::TsfEventRouterDelegate::IsCandidateWindowInternal(
221 DWORD element_id) { 251 DWORD element_id) {
222 DCHECK(ui_element_manager_.get()); 252 DCHECK(ui_element_manager_.get());
223 base::win::ScopedComPtr<ITfUIElement> ui_element; 253 base::win::ScopedComPtr<ITfUIElement> ui_element;
224 if (FAILED(ui_element_manager_->GetUIElement(element_id, 254 if (FAILED(ui_element_manager_->GetUIElement(element_id,
225 ui_element.Receive()))) 255 ui_element.Receive())))
226 return false; 256 return false;
227 base::win::ScopedComPtr<ITfCandidateListUIElement> candidate_list_ui_element; 257 base::win::ScopedComPtr<ITfCandidateListUIElement> candidate_list_ui_element;
(...skipping 19 matching lines...) Expand all
247 } 277 }
248 } 278 }
249 279
250 TsfEventRouter::~TsfEventRouter() { 280 TsfEventRouter::~TsfEventRouter() {
251 if (delegate_) { 281 if (delegate_) {
252 delegate_->SetManager(NULL); 282 delegate_->SetManager(NULL);
253 delegate_->SetRouter(NULL); 283 delegate_->SetRouter(NULL);
254 } 284 }
255 } 285 }
256 286
287 bool TsfEventRouter::IsImeComposing() {
288 return delegate_->IsImeComposing();
289 }
290
291 void TsfEventRouter::OnCandidateWindowCountChanged(size_t window_count) {
292 observer_->OnCandidateWindowCountChanged(window_count);
293 }
294
295 void TsfEventRouter::OnTsfStartComposition() {
296 observer_->OnTsfStartComposition();
297 }
298
299 void TsfEventRouter::OnTextUpdated(const ui::Range& composition_range) {
300 observer_->OnTextUpdated(composition_range);
301 }
302
303 void TsfEventRouter::OnTsfEndComposition() {
304 observer_->OnTsfEndComposition();
305 }
306
257 void TsfEventRouter::SetManager(ITfThreadMgr* thread_manager) { 307 void TsfEventRouter::SetManager(ITfThreadMgr* thread_manager) {
258 delegate_->SetManager(thread_manager); 308 delegate_->SetManager(thread_manager);
259 } 309 }
260 310
261 bool TsfEventRouter::IsImeComposing() {
262 return delegate_->IsImeComposing();
263 }
264
265 void TsfEventRouter::OnTextUpdated() {
266 observer_->OnTextUpdated();
267 }
268
269 void TsfEventRouter::OnCandidateWindowCountChanged(size_t window_count) {
270 observer_->OnCandidateWindowCountChanged(window_count);
271 }
272
273 } // namespace ui 311 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/win/tsf_event_router.h ('k') | ui/views/controls/textfield/native_textfield_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698