| 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 13 matching lines...) Expand all Loading... |
| 24 namespace input_method { | 24 namespace input_method { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 } // namespace | 28 } // namespace |
| 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(); | |
| 35 } | |
| 36 | |
| 37 CandidateWindowControllerImpl::~CandidateWindowControllerImpl() { | |
| 38 IBusBridge::Get()->SetCandidateWindowHandler(NULL); | |
| 39 candidate_window_view_->RemoveObserver(this); | |
| 40 } | |
| 41 | |
| 42 void CandidateWindowControllerImpl::CreateView() { | |
| 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. | 34 // Create the mode indicator controller. |
| 68 mode_indicator_controller_.reset( | 35 mode_indicator_controller_.reset( |
| 69 new ModeIndicatorController(InputMethodManager::Get())); | 36 new ModeIndicatorController(InputMethodManager::Get())); |
| 70 } | 37 } |
| 71 | 38 |
| 39 CandidateWindowControllerImpl::~CandidateWindowControllerImpl() { |
| 40 IBusBridge::Get()->SetCandidateWindowHandler(NULL); |
| 41 if (candidate_window_view_) { |
| 42 candidate_window_view_->RemoveObserver(this); |
| 43 candidate_window_view_->GetWidget()->RemoveObserver(this); |
| 44 } |
| 45 } |
| 46 |
| 47 void CandidateWindowControllerImpl::InitCandidateWindowView() { |
| 48 if (candidate_window_view_) |
| 49 return; |
| 50 |
| 51 candidate_window_view_ = new CandidateWindowView(ash::Shell::GetContainer( |
| 52 ash::Shell::GetTargetRootWindow(), |
| 53 ash::internal::kShellWindowId_InputMethodContainer)); |
| 54 candidate_window_view_->AddObserver(this); |
| 55 candidate_window_view_->SetCursorBounds(cursor_bounds_, composition_head_); |
| 56 views::Widget* widget = candidate_window_view_->InitWidget(); |
| 57 widget->AddObserver(this); |
| 58 widget->Show(); |
| 59 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, |
| 60 CandidateWindowOpened()); |
| 61 } |
| 62 |
| 72 void CandidateWindowControllerImpl::Hide() { | 63 void CandidateWindowControllerImpl::Hide() { |
| 73 // To hide the candidate window we have to call HideLookupTable and | 64 if (candidate_window_view_) |
| 74 // HideAuxiliaryText. Without calling HideAuxiliaryText the | 65 candidate_window_view_->GetWidget()->Close(); |
| 75 // auxiliary text area will remain. | |
| 76 candidate_window_view_->HideLookupTable(); | |
| 77 if (infolist_window_) | 66 if (infolist_window_) |
| 78 infolist_window_->HideImmediately(); | 67 infolist_window_->HideImmediately(); |
| 79 } | 68 } |
| 80 | 69 |
| 81 void CandidateWindowControllerImpl::SetCursorBounds( | 70 void CandidateWindowControllerImpl::SetCursorBounds( |
| 82 const gfx::Rect& cursor_bounds, | 71 const gfx::Rect& cursor_bounds, |
| 83 const gfx::Rect& composition_head) { | 72 const gfx::Rect& composition_head) { |
| 84 // A workaround for http://crosbug.com/6460. We should ignore very short Y | 73 // A workaround for http://crosbug.com/6460. We should ignore very short Y |
| 85 // move to prevent the window from shaking up and down. | 74 // move to prevent the window from shaking up and down. |
| 86 const int kKeepPositionThreshold = 2; // px | 75 const int kKeepPositionThreshold = 2; // px |
| 87 const gfx::Rect& last_bounds = | 76 gfx::Rect last_bounds; |
| 88 candidate_window_view_->cursor_bounds(); | 77 if (candidate_window_view_) |
| 78 last_bounds = candidate_window_view_->GetAnchorRect(); |
| 79 |
| 89 const int delta_y = abs(last_bounds.y() - cursor_bounds.y()); | 80 const int delta_y = abs(last_bounds.y() - cursor_bounds.y()); |
| 90 if ((last_bounds.x() == cursor_bounds.x()) && | 81 if ((last_bounds.x() == cursor_bounds.x()) && |
| 91 (delta_y <= kKeepPositionThreshold)) { | 82 (delta_y <= kKeepPositionThreshold)) { |
| 92 DVLOG(1) << "Ignored set_cursor_bounds signal to prevent window shake"; | 83 DVLOG(1) << "Ignored set_cursor_bounds signal to prevent window shake"; |
| 93 return; | 84 return; |
| 94 } | 85 } |
| 95 | 86 |
| 87 cursor_bounds_ = cursor_bounds; |
| 88 composition_head_ = composition_head; |
| 89 |
| 96 // Remember the cursor bounds. | 90 // Remember the cursor bounds. |
| 97 candidate_window_view_->set_cursor_bounds(cursor_bounds); | 91 if (candidate_window_view_) |
| 98 candidate_window_view_->set_composition_head_bounds(composition_head); | 92 candidate_window_view_->SetCursorBounds(cursor_bounds, composition_head); |
| 99 // Move the window per the cursor bounds. | |
| 100 candidate_window_view_->ResizeAndMoveParentFrame(); | |
| 101 | 93 |
| 102 // Mode indicator controller also needs the cursor bounds. | 94 // Mode indicator controller also needs the cursor bounds. |
| 103 mode_indicator_controller_->SetCursorBounds(cursor_bounds); | 95 mode_indicator_controller_->SetCursorBounds(cursor_bounds); |
| 104 } | 96 } |
| 105 | 97 |
| 106 void CandidateWindowControllerImpl::FocusStateChanged(bool is_focused) { | 98 void CandidateWindowControllerImpl::FocusStateChanged(bool is_focused) { |
| 107 mode_indicator_controller_->FocusStateChanged(is_focused); | 99 mode_indicator_controller_->FocusStateChanged(is_focused); |
| 108 } | 100 } |
| 109 | 101 |
| 110 // static | 102 // static |
| (...skipping 23 matching lines...) Expand all Loading... |
| 134 } | 126 } |
| 135 infolist_entries->push_back(entry); | 127 infolist_entries->push_back(entry); |
| 136 } | 128 } |
| 137 } | 129 } |
| 138 | 130 |
| 139 void CandidateWindowControllerImpl::UpdateLookupTable( | 131 void CandidateWindowControllerImpl::UpdateLookupTable( |
| 140 const CandidateWindow& candidate_window, | 132 const CandidateWindow& candidate_window, |
| 141 bool visible) { | 133 bool visible) { |
| 142 // If it's not visible, hide the lookup table and return. | 134 // If it's not visible, hide the lookup table and return. |
| 143 if (!visible) { | 135 if (!visible) { |
| 144 candidate_window_view_->HideLookupTable(); | 136 if (candidate_window_view_) |
| 137 candidate_window_view_->HideLookupTable(); |
| 145 if (infolist_window_) | 138 if (infolist_window_) |
| 146 infolist_window_->HideImmediately(); | 139 infolist_window_->HideImmediately(); |
| 147 // TODO(nona): Introduce unittests for crbug.com/170036. | 140 // TODO(nona): Introduce unittests for crbug.com/170036. |
| 148 latest_infolist_entries_.clear(); | 141 latest_infolist_entries_.clear(); |
| 149 return; | 142 return; |
| 150 } | 143 } |
| 151 | 144 |
| 145 if (!candidate_window_view_) |
| 146 InitCandidateWindowView(); |
| 152 candidate_window_view_->UpdateCandidates(candidate_window); | 147 candidate_window_view_->UpdateCandidates(candidate_window); |
| 153 candidate_window_view_->ShowLookupTable(); | 148 candidate_window_view_->ShowLookupTable(); |
| 154 | 149 |
| 155 bool has_highlighted = false; | 150 bool has_highlighted = false; |
| 156 std::vector<InfolistEntry> infolist_entries; | 151 std::vector<InfolistEntry> infolist_entries; |
| 157 ConvertLookupTableToInfolistEntry(candidate_window, &infolist_entries, | 152 ConvertLookupTableToInfolistEntry(candidate_window, &infolist_entries, |
| 158 &has_highlighted); | 153 &has_highlighted); |
| 159 | 154 |
| 160 // If there is no change, just return. | 155 // If there is no change, just return. |
| 161 if (latest_infolist_entries_ == infolist_entries) | 156 if (latest_infolist_entries_ == infolist_entries) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 184 infolist_window_->InitWidget(); | 179 infolist_window_->InitWidget(); |
| 185 infolist_window_->GetWidget()->AddObserver(this); | 180 infolist_window_->GetWidget()->AddObserver(this); |
| 186 } | 181 } |
| 187 infolist_window_->ShowWithDelay(); | 182 infolist_window_->ShowWithDelay(); |
| 188 } | 183 } |
| 189 | 184 |
| 190 void CandidateWindowControllerImpl::UpdatePreeditText( | 185 void CandidateWindowControllerImpl::UpdatePreeditText( |
| 191 const std::string& utf8_text, unsigned int cursor, bool visible) { | 186 const std::string& utf8_text, unsigned int cursor, bool visible) { |
| 192 // If it's not visible, hide the preedit text and return. | 187 // If it's not visible, hide the preedit text and return. |
| 193 if (!visible || utf8_text.empty()) { | 188 if (!visible || utf8_text.empty()) { |
| 194 candidate_window_view_->HidePreeditText(); | 189 if (candidate_window_view_) |
| 190 candidate_window_view_->HidePreeditText(); |
| 195 return; | 191 return; |
| 196 } | 192 } |
| 193 if (!candidate_window_view_) |
| 194 InitCandidateWindowView(); |
| 197 candidate_window_view_->UpdatePreeditText(utf8_text); | 195 candidate_window_view_->UpdatePreeditText(utf8_text); |
| 198 candidate_window_view_->ShowPreeditText(); | 196 candidate_window_view_->ShowPreeditText(); |
| 199 } | 197 } |
| 200 | 198 |
| 201 void CandidateWindowControllerImpl::OnCandidateCommitted(int index) { | 199 void CandidateWindowControllerImpl::OnCandidateCommitted(int index) { |
| 202 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | 200 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, |
| 203 CandidateClicked(index)); | 201 CandidateClicked(index)); |
| 204 } | 202 } |
| 205 | 203 |
| 206 void CandidateWindowControllerImpl::OnCandidateWindowOpened() { | |
| 207 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | |
| 208 CandidateWindowOpened()); | |
| 209 } | |
| 210 | |
| 211 void CandidateWindowControllerImpl::OnCandidateWindowClosed() { | |
| 212 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, | |
| 213 CandidateWindowClosed()); | |
| 214 } | |
| 215 | |
| 216 void CandidateWindowControllerImpl::OnWidgetClosing(views::Widget* widget) { | 204 void CandidateWindowControllerImpl::OnWidgetClosing(views::Widget* widget) { |
| 217 if (infolist_window_ && widget == infolist_window_->GetWidget()) { | 205 if (infolist_window_ && widget == infolist_window_->GetWidget()) { |
| 218 widget->RemoveObserver(this); | 206 widget->RemoveObserver(this); |
| 219 infolist_window_ = NULL; | 207 infolist_window_ = NULL; |
| 208 } else if (candidate_window_view_ && |
| 209 widget == candidate_window_view_->GetWidget()) { |
| 210 widget->RemoveObserver(this); |
| 211 candidate_window_view_->RemoveObserver(this); |
| 212 candidate_window_view_ = NULL; |
| 213 FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, |
| 214 CandidateWindowClosed()); |
| 220 } | 215 } |
| 221 } | 216 } |
| 222 | 217 |
| 223 void CandidateWindowControllerImpl::AddObserver( | 218 void CandidateWindowControllerImpl::AddObserver( |
| 224 CandidateWindowController::Observer* observer) { | 219 CandidateWindowController::Observer* observer) { |
| 225 observers_.AddObserver(observer); | 220 observers_.AddObserver(observer); |
| 226 } | 221 } |
| 227 | 222 |
| 228 void CandidateWindowControllerImpl::RemoveObserver( | 223 void CandidateWindowControllerImpl::RemoveObserver( |
| 229 CandidateWindowController::Observer* observer) { | 224 CandidateWindowController::Observer* observer) { |
| 230 observers_.RemoveObserver(observer); | 225 observers_.RemoveObserver(observer); |
| 231 } | 226 } |
| 232 | 227 |
| 233 } // namespace input_method | 228 } // namespace input_method |
| 234 } // namespace chromeos | 229 } // namespace chromeos |
| OLD | NEW |