Chromium Code Reviews| 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 #include "chrome/browser/chromeos/input_method/candidate_window_controller_impl. h" | 5 #include "chrome/browser/chromeos/input_method/candidate_window_controller_impl. h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "ash/shell.h" | 10 #include "ash/shell.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 | 29 |
| 30 CandidateWindowControllerImpl::CandidateWindowControllerImpl() | 30 CandidateWindowControllerImpl::CandidateWindowControllerImpl() |
| 31 : candidate_window_view_(NULL), | 31 : candidate_window_view_(NULL), |
| 32 infolist_window_(NULL) { | 32 infolist_window_(NULL) { |
| 33 IBusBridge::Get()->SetCandidateWindowHandler(this); | 33 IBusBridge::Get()->SetCandidateWindowHandler(this); |
| 34 CreateView(); | 34 CreateView(); |
| 35 } | 35 } |
| 36 | 36 |
| 37 CandidateWindowControllerImpl::~CandidateWindowControllerImpl() { | 37 CandidateWindowControllerImpl::~CandidateWindowControllerImpl() { |
| 38 IBusBridge::Get()->SetCandidateWindowHandler(NULL); | 38 IBusBridge::Get()->SetCandidateWindowHandler(NULL); |
| 39 candidate_window_view_->RemoveObserver(this); | 39 if (candidate_window_view_) { |
| 40 candidate_window_view_->RemoveObserver(this); | |
| 41 candidate_window_view_->GetWidget()->RemoveObserver(this); | |
| 42 } | |
| 40 } | 43 } |
| 41 | 44 |
| 42 void CandidateWindowControllerImpl::CreateView() { | 45 void CandidateWindowControllerImpl::CreateView() { |
|
Hiro Komatsu
2013/12/27 07:13:34
Let's delete this function.
Jun Mukai
2013/12/27 11:01:13
Done.
| |
| 43 // Create a non-decorated frame. | |
| 44 frame_.reset(new views::Widget); | |
| 45 // The size is initially zero. | |
| 46 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); | |
| 47 // |frame_| is owned by controller impl so | |
| 48 // they should use WIDGET_OWNS_NATIVE_WIDGET ownership. | |
| 49 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 50 // Show the candidate window always on top | |
| 51 params.parent = ash::Shell::GetContainer( | |
| 52 ash::Shell::GetTargetRootWindow(), | |
| 53 ash::internal::kShellWindowId_InputMethodContainer); | |
| 54 frame_->Init(params); | |
| 55 | |
| 56 views::corewm::SetWindowVisibilityAnimationType( | |
| 57 frame_->GetNativeView(), | |
| 58 views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); | |
| 59 | |
| 60 // Create the candidate window. | |
| 61 candidate_window_view_ = new CandidateWindowView(frame_.get()); | |
| 62 candidate_window_view_->Init(); | |
| 63 candidate_window_view_->AddObserver(this); | |
| 64 | |
| 65 frame_->SetContentsView(candidate_window_view_); | |
| 66 | |
| 67 // Create the mode indicator controller. | 46 // Create the mode indicator controller. |
| 68 mode_indicator_controller_.reset( | 47 mode_indicator_controller_.reset( |
| 69 new ModeIndicatorController(InputMethodManager::Get())); | 48 new ModeIndicatorController(InputMethodManager::Get())); |
| 70 } | 49 } |
| 71 | 50 |
| 51 void CandidateWindowControllerImpl::InitCandidateWindowView() { | |
| 52 if (candidate_window_view_) | |
| 53 return; | |
| 54 | |
| 55 candidate_window_view_ = new CandidateWindowView(ash::Shell::GetContainer( | |
| 56 ash::Shell::GetTargetRootWindow(), | |
| 57 ash::internal::kShellWindowId_InputMethodContainer)); | |
| 58 candidate_window_view_->AddObserver(this); | |
| 59 candidate_window_view_->SetCursorBounds(cursor_bounds_, composition_head_); | |
| 60 views::Widget* widget = candidate_window_view_->InitWidget(); | |
| 61 widget->AddObserver(this); | |
| 62 widget->Show(); | |
| 63 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | |
| 64 CandidateWindowOpened()); | |
| 65 } | |
| 66 | |
| 72 void CandidateWindowControllerImpl::Hide() { | 67 void CandidateWindowControllerImpl::Hide() { |
| 73 // To hide the candidate window we have to call HideLookupTable and | 68 if (candidate_window_view_) |
| 74 // HideAuxiliaryText. Without calling HideAuxiliaryText the | 69 candidate_window_view_->GetWidget()->Close(); |
| 75 // auxiliary text area will remain. | |
| 76 candidate_window_view_->HideLookupTable(); | |
| 77 candidate_window_view_->HideAuxiliaryText(); | |
| 78 if (infolist_window_) | 70 if (infolist_window_) |
| 79 infolist_window_->HideImmediately(); | 71 infolist_window_->HideImmediately(); |
| 80 } | 72 } |
| 81 | 73 |
| 82 void CandidateWindowControllerImpl::SetCursorBounds( | 74 void CandidateWindowControllerImpl::SetCursorBounds( |
| 83 const gfx::Rect& cursor_bounds, | 75 const gfx::Rect& cursor_bounds, |
| 84 const gfx::Rect& composition_head) { | 76 const gfx::Rect& composition_head) { |
| 85 // A workaround for http://crosbug.com/6460. We should ignore very short Y | 77 // A workaround for http://crosbug.com/6460. We should ignore very short Y |
| 86 // move to prevent the window from shaking up and down. | 78 // move to prevent the window from shaking up and down. |
| 87 const int kKeepPositionThreshold = 2; // px | 79 const int kKeepPositionThreshold = 2; // px |
| 88 const gfx::Rect& last_bounds = | 80 gfx::Rect last_bounds; |
| 89 candidate_window_view_->cursor_bounds(); | 81 if (candidate_window_view_) |
| 82 last_bounds = candidate_window_view_->GetAnchorRect(); | |
| 83 | |
| 90 const int delta_y = abs(last_bounds.y() - cursor_bounds.y()); | 84 const int delta_y = abs(last_bounds.y() - cursor_bounds.y()); |
| 91 if ((last_bounds.x() == cursor_bounds.x()) && | 85 if ((last_bounds.x() == cursor_bounds.x()) && |
| 92 (delta_y <= kKeepPositionThreshold)) { | 86 (delta_y <= kKeepPositionThreshold)) { |
| 93 DVLOG(1) << "Ignored set_cursor_bounds signal to prevent window shake"; | 87 DVLOG(1) << "Ignored set_cursor_bounds signal to prevent window shake"; |
| 94 return; | 88 return; |
| 95 } | 89 } |
| 96 | 90 |
| 91 cursor_bounds_ = cursor_bounds; | |
| 92 composition_head_ = composition_head; | |
| 93 | |
| 97 // Remember the cursor bounds. | 94 // Remember the cursor bounds. |
| 98 candidate_window_view_->set_cursor_bounds(cursor_bounds); | 95 if (candidate_window_view_) |
| 99 candidate_window_view_->set_composition_head_bounds(composition_head); | 96 candidate_window_view_->SetCursorBounds(cursor_bounds, composition_head); |
| 100 // Move the window per the cursor bounds. | |
| 101 candidate_window_view_->ResizeAndMoveParentFrame(); | |
| 102 if (infolist_window_) | 97 if (infolist_window_) |
| 103 infolist_window_->GetWidget()->SetBounds(GetInfolistBounds()); | 98 infolist_window_->GetWidget()->SetBounds(GetInfolistBounds()); |
| 104 | 99 |
| 105 // Mode indicator controller also needs the cursor bounds. | 100 // Mode indicator controller also needs the cursor bounds. |
| 106 mode_indicator_controller_->SetCursorBounds(cursor_bounds); | 101 mode_indicator_controller_->SetCursorBounds(cursor_bounds); |
| 107 } | 102 } |
| 108 | 103 |
| 109 void CandidateWindowControllerImpl::UpdateAuxiliaryText( | 104 void CandidateWindowControllerImpl::UpdateAuxiliaryText( |
| 110 const std::string& utf8_text, | 105 const std::string& utf8_text, |
| 111 bool visible) { | 106 bool visible) { |
| 112 // If it's not visible, hide the auxiliary text and return. | 107 // If it's not visible, hide the auxiliary text and return. |
| 113 if (!visible) { | 108 if (!visible) { |
| 114 candidate_window_view_->HideAuxiliaryText(); | 109 if (candidate_window_view_) |
| 110 candidate_window_view_->HideAuxiliaryText(); | |
| 115 return; | 111 return; |
| 116 } | 112 } |
| 113 | |
| 114 if (!candidate_window_view_) | |
| 115 InitCandidateWindowView(); | |
| 116 | |
| 117 candidate_window_view_->UpdateAuxiliaryText(utf8_text); | 117 candidate_window_view_->UpdateAuxiliaryText(utf8_text); |
| 118 candidate_window_view_->ShowAuxiliaryText(); | 118 candidate_window_view_->ShowAuxiliaryText(); |
| 119 } | 119 } |
| 120 | 120 |
| 121 void CandidateWindowControllerImpl::FocusStateChanged(bool is_focused) { | 121 void CandidateWindowControllerImpl::FocusStateChanged(bool is_focused) { |
| 122 mode_indicator_controller_->FocusStateChanged(is_focused); | 122 mode_indicator_controller_->FocusStateChanged(is_focused); |
| 123 } | 123 } |
| 124 | 124 |
| 125 // static | 125 // static |
| 126 void CandidateWindowControllerImpl::ConvertLookupTableToInfolistEntry( | 126 void CandidateWindowControllerImpl::ConvertLookupTableToInfolistEntry( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 149 } | 149 } |
| 150 infolist_entries->push_back(entry); | 150 infolist_entries->push_back(entry); |
| 151 } | 151 } |
| 152 } | 152 } |
| 153 | 153 |
| 154 void CandidateWindowControllerImpl::UpdateLookupTable( | 154 void CandidateWindowControllerImpl::UpdateLookupTable( |
| 155 const CandidateWindow& candidate_window, | 155 const CandidateWindow& candidate_window, |
| 156 bool visible) { | 156 bool visible) { |
| 157 // If it's not visible, hide the lookup table and return. | 157 // If it's not visible, hide the lookup table and return. |
| 158 if (!visible) { | 158 if (!visible) { |
| 159 candidate_window_view_->HideLookupTable(); | 159 if (candidate_window_view_) |
| 160 candidate_window_view_->HideLookupTable(); | |
| 160 if (infolist_window_) | 161 if (infolist_window_) |
| 161 infolist_window_->HideImmediately(); | 162 infolist_window_->HideImmediately(); |
| 162 // TODO(nona): Introduce unittests for crbug.com/170036. | 163 // TODO(nona): Introduce unittests for crbug.com/170036. |
| 163 latest_infolist_entries_.clear(); | 164 latest_infolist_entries_.clear(); |
| 164 return; | 165 return; |
| 165 } | 166 } |
| 166 | 167 |
| 168 if (!candidate_window_view_) | |
| 169 InitCandidateWindowView(); | |
| 167 candidate_window_view_->UpdateCandidates(candidate_window); | 170 candidate_window_view_->UpdateCandidates(candidate_window); |
| 168 candidate_window_view_->ShowLookupTable(); | 171 candidate_window_view_->ShowLookupTable(); |
| 169 | 172 |
| 170 bool has_highlighted = false; | 173 bool has_highlighted = false; |
| 171 std::vector<InfolistEntry> infolist_entries; | 174 std::vector<InfolistEntry> infolist_entries; |
| 172 ConvertLookupTableToInfolistEntry(candidate_window, &infolist_entries, | 175 ConvertLookupTableToInfolistEntry(candidate_window, &infolist_entries, |
| 173 &has_highlighted); | 176 &has_highlighted); |
| 174 | 177 |
| 175 // If there is no change, just return. | 178 // If there is no change, just return. |
| 176 if (latest_infolist_entries_ == infolist_entries) | 179 if (latest_infolist_entries_ == infolist_entries) |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 202 ash::internal::kShellWindowId_InputMethodContainer), | 205 ash::internal::kShellWindowId_InputMethodContainer), |
| 203 GetInfolistBounds()); | 206 GetInfolistBounds()); |
| 204 infolist_window_->GetWidget()->AddObserver(this); | 207 infolist_window_->GetWidget()->AddObserver(this); |
| 205 } | 208 } |
| 206 infolist_window_->ShowWithDelay(); | 209 infolist_window_->ShowWithDelay(); |
| 207 } | 210 } |
| 208 | 211 |
| 209 gfx::Rect CandidateWindowControllerImpl::GetInfolistBounds() { | 212 gfx::Rect CandidateWindowControllerImpl::GetInfolistBounds() { |
| 210 gfx::Rect new_bounds(infolist_window_->GetPreferredSize()); | 213 gfx::Rect new_bounds(infolist_window_->GetPreferredSize()); |
| 211 // Infolist has to be in the same display of the candidate window. | 214 // Infolist has to be in the same display of the candidate window. |
| 212 gfx::NativeWindow native_frame = frame_->GetNativeWindow(); | 215 gfx::NativeWindow native_frame = |
| 216 candidate_window_view_->GetWidget()->GetNativeWindow(); | |
| 213 new_bounds.set_origin(GetInfolistWindowPosition( | 217 new_bounds.set_origin(GetInfolistWindowPosition( |
| 214 frame_->GetClientAreaBoundsInScreen(), | 218 candidate_window_view_->GetWidget()->GetClientAreaBoundsInScreen(), |
| 215 gfx::Screen::GetScreenFor(native_frame)->GetDisplayNearestWindow( | 219 gfx::Screen::GetScreenFor(native_frame)->GetDisplayNearestWindow( |
| 216 native_frame).work_area(), | 220 native_frame).work_area(), |
| 217 new_bounds.size())); | 221 new_bounds.size())); |
| 218 return new_bounds; | 222 return new_bounds; |
| 219 } | 223 } |
| 220 | 224 |
| 221 void CandidateWindowControllerImpl::UpdatePreeditText( | 225 void CandidateWindowControllerImpl::UpdatePreeditText( |
| 222 const std::string& utf8_text, unsigned int cursor, bool visible) { | 226 const std::string& utf8_text, unsigned int cursor, bool visible) { |
| 223 // If it's not visible, hide the preedit text and return. | 227 // If it's not visible, hide the preedit text and return. |
| 224 if (!visible || utf8_text.empty()) { | 228 if (!visible || utf8_text.empty()) { |
| 225 candidate_window_view_->HidePreeditText(); | 229 if (candidate_window_view_) |
| 230 candidate_window_view_->HidePreeditText(); | |
| 226 return; | 231 return; |
| 227 } | 232 } |
| 233 if (!candidate_window_view_) | |
| 234 InitCandidateWindowView(); | |
|
Hiro Komatsu
2013/12/27 07:13:34
When the only composition text is updated, the ca
Jun Mukai
2013/12/27 11:01:13
This is only for the preedit in the candidate wind
| |
| 228 candidate_window_view_->UpdatePreeditText(utf8_text); | 235 candidate_window_view_->UpdatePreeditText(utf8_text); |
| 229 candidate_window_view_->ShowPreeditText(); | 236 candidate_window_view_->ShowPreeditText(); |
| 230 } | 237 } |
| 231 | 238 |
| 232 void CandidateWindowControllerImpl::OnCandidateCommitted(int index) { | 239 void CandidateWindowControllerImpl::OnCandidateCommitted(int index) { |
| 233 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | 240 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, |
| 234 CandidateClicked(index)); | 241 CandidateClicked(index)); |
| 235 } | 242 } |
| 236 | 243 |
| 237 void CandidateWindowControllerImpl::OnCandidateWindowOpened() { | |
| 238 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | |
| 239 CandidateWindowOpened()); | |
| 240 } | |
| 241 | |
| 242 void CandidateWindowControllerImpl::OnCandidateWindowClosed() { | |
| 243 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | |
| 244 CandidateWindowClosed()); | |
| 245 } | |
| 246 | |
| 247 void CandidateWindowControllerImpl::OnWidgetClosing(views::Widget* widget) { | 244 void CandidateWindowControllerImpl::OnWidgetClosing(views::Widget* widget) { |
| 248 if (infolist_window_ && widget == infolist_window_->GetWidget()) { | 245 if (infolist_window_ && widget == infolist_window_->GetWidget()) { |
| 249 widget->RemoveObserver(this); | 246 widget->RemoveObserver(this); |
| 250 infolist_window_ = NULL; | 247 infolist_window_ = NULL; |
| 248 } else if (candidate_window_view_ && | |
| 249 widget == candidate_window_view_->GetWidget()) { | |
| 250 widget->RemoveObserver(this); | |
| 251 candidate_window_view_->RemoveObserver(this); | |
| 252 candidate_window_view_ = NULL; | |
| 253 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | |
| 254 CandidateWindowClosed()); | |
| 251 } | 255 } |
| 252 } | 256 } |
| 253 | 257 |
| 254 void CandidateWindowControllerImpl::AddObserver( | 258 void CandidateWindowControllerImpl::AddObserver( |
| 255 CandidateWindowController::Observer* observer) { | 259 CandidateWindowController::Observer* observer) { |
| 256 observers_.AddObserver(observer); | 260 observers_.AddObserver(observer); |
| 257 } | 261 } |
| 258 | 262 |
| 259 void CandidateWindowControllerImpl::RemoveObserver( | 263 void CandidateWindowControllerImpl::RemoveObserver( |
| 260 CandidateWindowController::Observer* observer) { | 264 CandidateWindowController::Observer* observer) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 275 | 279 |
| 276 if (candidate_window_view_rect.y() + infolist_window_size.height() > | 280 if (candidate_window_view_rect.y() + infolist_window_size.height() > |
| 277 screen_rect.bottom()) | 281 screen_rect.bottom()) |
| 278 result.set_y(screen_rect.bottom() - infolist_window_size.height()); | 282 result.set_y(screen_rect.bottom() - infolist_window_size.height()); |
| 279 | 283 |
| 280 return result; | 284 return result; |
| 281 } | 285 } |
| 282 | 286 |
| 283 } // namespace input_method | 287 } // namespace input_method |
| 284 } // namespace chromeos | 288 } // namespace chromeos |
| OLD | NEW |