Chromium Code Reviews| Index: chrome/browser/chromeos/login/webui_login_view.cc |
| diff --git a/chrome/browser/chromeos/login/webui_login_view.cc b/chrome/browser/chromeos/login/webui_login_view.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..260980ea07d2386b6d12c0df2c19764f2412f8f8 |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/login/webui_login_view.cc |
| @@ -0,0 +1,313 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/chromeos/login/webui_login_view.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/logging.h" |
| +#include "chrome/browser/chromeos/login/login_utils.h" |
| +#include "chrome/browser/chromeos/login/proxy_settings_dialog.h" |
| +#include "chrome/browser/chromeos/status/clock_menu_button.h" |
| +#include "chrome/browser/chromeos/status/input_method_menu_button.h" |
| +#include "chrome/browser/chromeos/status/network_menu_button.h" |
| +#include "chrome/browser/chromeos/status/status_area_view.h" |
| +#include "chrome/browser/chromeos/wm_ipc.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/browser/profiles/profile_manager.h" |
| +#include "chrome/browser/renderer_host/render_widget_host_view_views.h" |
| +#include "chrome/browser/ui/touch/frame/keyboard_container_view.h" |
| +#include "chrome/browser/ui/views/dom_view.h" |
| +#include "chrome/browser/ui/views/tab_contents/tab_contents_view_touch.h" |
| +#include "content/browser/renderer_host/render_view_host.h" |
| +#include "content/browser/tab_contents/tab_contents.h" |
| +#include "content/common/notification_service.h" |
| +#include "googleurl/src/gurl.h" |
| +#include "ui/base/x/x11_util.h" |
| +#include "ui/gfx/transform.h" |
| +#include "views/controls/textfield/textfield.h" |
| +#include "views/widget/widget.h" |
| + |
| +// X Windows headers have "#define Status int". That interferes with |
| +// NetworkLibrary header which defines enum "Status". |
|
Nikita (slow)
2011/05/18 20:22:12
This issue is absolete. Please remove comment and
rharrison
2011/05/19 00:31:43
Done.
|
| +#include <X11/cursorfont.h> // NOLINT |
| +#include <X11/Xcursor/Xcursor.h> // NOLINT |
| + |
| +namespace { |
| + |
| +const int kKeyboardHeight = 300; |
| +const int kKeyboardSlideDuration = 500; // In milliseconds |
| + |
| +// This gets rid of the ugly X default cursor. |
| +static void ResetXCursor() { |
|
Nikita (slow)
2011/05/18 20:22:12
background_view.cc has the same code.
Please move
rharrison
2011/05/19 00:31:43
Done.
|
| + // TODO(sky): nuke this once new window manager is in place. |
| + Display* display = ui::GetXDisplay(); |
| + Cursor cursor = XCreateFontCursor(display, XC_left_ptr); |
| + XID root_window = ui::GetX11RootWindow(); |
| + XSetWindowAttributes attr; |
| + attr.cursor = cursor; |
| + XChangeWindowAttributes(display, root_window, CWCursor, &attr); |
| +} |
| + |
| +PropertyAccessor<bool>* GetFocusedStateAccessor() { |
| + static PropertyAccessor<bool> state; |
| + return &state; |
| +} |
| + |
| +bool TabContentsHasFocus(const TabContents* contents) { |
| + views::View* view = static_cast<TabContentsViewTouch*>(contents->view()); |
| + return view->Contains(view->GetFocusManager()->GetFocusedView()); |
| +} |
| + |
| +} // namespace |
| + |
| +namespace chromeos { |
| + |
| +// static |
| +const char WebUILoginView::kViewClassName[] = |
| + "browser/chromeos/login/WebUILoginView"; |
| + |
| +// WebUILoginView public: ------------------------------------------------------ |
| + |
| +WebUILoginView::WebUILoginView() |
| + : profile_(NULL), |
| + status_area_(NULL), |
| + did_paint_(false), |
| + webui_login_(NULL), |
| + keyboard_showing_(false), |
| + focus_listener_added_(false), |
| + keyboard_(NULL) { |
| +} |
| + |
| +void WebUILoginView::Init(const GURL& login_url) { |
| + CHECK(!login_url.is_empty()); |
| + profile_ = ProfileManager::GetDefaultProfile(); |
| + if (!profile_->GetExtensionService()) { |
|
Nikita (slow)
2011/05/18 20:22:12
Are you sure that you need this block?
Extensions
rharrison
2011/05/19 00:31:43
Since we are not in a proper logged in browser I d
Nikita (slow)
2011/05/19 03:53:33
Let's clarify 2 things:
1. Is keyboard extension a
rharrison
2011/05/19 16:45:28
I think it is a component extension. I misundersto
|
| + if (profile_->IsOffTheRecord()) |
| + profile_ = profile_->GetOriginalProfile(); |
| + profile_->InitExtensions(false); |
| + } |
| + |
| + webui_login_ = new DOMView(); |
| + AddChildView(webui_login_); |
| + webui_login_->Init(profile_, NULL); |
| + webui_login_->LoadURL(login_url); |
| + webui_login_->SetVisible(true); |
| + |
| + InitStatusArea(); |
| + |
| + registrar_.Add(this, |
| + NotificationType::FOCUS_CHANGED_IN_PAGE, |
| + NotificationService::AllSources()); |
| + registrar_.Add(this, |
| + NotificationType::TAB_CONTENTS_DESTROYED, |
| + NotificationService::AllSources()); |
| +} |
| + |
| +// static |
| +views::Widget* WebUILoginView::CreateWindowContainingView( |
| + const gfx::Rect& bounds, |
| + const GURL& login_url, |
| + WebUILoginView** view) { |
| + ResetXCursor(); |
| + |
| + views::Widget* window = new views::Widget; |
| + views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); |
| + params.bounds = bounds; |
| + window->Init(params); |
| + *view = new WebUILoginView(); |
| + (*view)->Init(login_url); |
| + |
| + window->SetContentsView(*view); |
| + |
| + (*view)->UpdateWindowType(); |
| + |
| + // This keeps the window from flashing at startup. |
| + GdkWindow* gdk_window = window->GetNativeView()->window; |
| + gdk_window_set_back_pixmap(gdk_window, NULL, false); |
| + |
| + return window; |
| +} |
| + |
| +std::string WebUILoginView::GetClassName() const { |
| + return kViewClassName; |
| +} |
| + |
| +gfx::NativeWindow WebUILoginView::GetNativeWindow() const { |
| + return GetWidget()->GetNativeWindow(); |
| +} |
| + |
| +void WebUILoginView::FocusWillChange(views::View* focused_before, |
| + views::View* focused_now) { |
|
oshima
2011/05/18 18:24:54
indent
rharrison
2011/05/19 00:31:43
Done.
|
| + VirtualKeyboardType before = DecideKeyboardStateForView(focused_before); |
| + VirtualKeyboardType now = DecideKeyboardStateForView(focused_now); |
| + if (before != now) { |
| + // TODO(varunjain): support other types of keyboard. |
| + UpdateKeyboardAndLayout(now == GENERIC); |
| + } |
| +} |
| + |
| +void WebUILoginView::SetStatusAreaVisible(bool visible) { |
| + status_area_->SetVisible(visible); |
| +} |
| + |
| +void WebUILoginView::SetStatusAreaEnabled(bool enable) { |
| + status_area_->MakeButtonsActive(enable); |
| +} |
| + |
| +// WebUILoginView protected: --------------------------------------------------- |
| + |
| +void WebUILoginView::OnPaint(gfx::Canvas* canvas) { |
| + views::View::OnPaint(canvas); |
| + if (!did_paint_) { |
| + did_paint_ = true; |
| + UpdateWindowType(); |
| + } |
| +} |
| + |
| +void WebUILoginView::Layout() { |
| + const int kCornerPadding = 5; |
| + gfx::Size status_area_size = status_area_->GetPreferredSize(); |
| + status_area_->SetBounds( |
| + width() - status_area_size.width() - kCornerPadding, |
| + kCornerPadding, |
| + status_area_size.width(), |
| + status_area_size.height()); |
| + |
| + if (webui_login_) |
| + webui_login_->SetBoundsRect(bounds()); |
| + |
| + if (!keyboard_) |
|
Nikita (slow)
2011/05/18 20:22:12
It's touch specific while it shouldn't be.
Since w
rharrison
2011/05/19 00:31:43
Done.
|
| + return; |
| + |
| + keyboard_->SetVisible(keyboard_showing_); |
| + gfx::Rect keyboard_bounds = bounds(); |
| + keyboard_bounds.set_y(keyboard_bounds.height() - kKeyboardHeight); |
| + keyboard_bounds.set_height(kKeyboardHeight); |
| + keyboard_->SetBoundsRect(keyboard_bounds); |
| +} |
| + |
| +void WebUILoginView::ChildPreferredSizeChanged(View* child) { |
| + Layout(); |
| + SchedulePaint(); |
| +} |
| + |
| +bool WebUILoginView::ShouldOpenButtonOptions( |
| + const views::View* button_view) const { |
| + if (button_view == status_area_->network_view()) { |
| + return true; |
| + } |
|
oshima
2011/05/18 18:24:54
nuke {}
rharrison
2011/05/19 00:31:43
Done.
|
| + if (button_view == status_area_->clock_view() || |
| + button_view == status_area_->input_method_view()) { |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +void WebUILoginView::OpenButtonOptions(const views::View* button_view) { |
| + if (button_view == status_area_->network_view()) { |
| + if (proxy_settings_dialog_.get() == NULL) { |
| + proxy_settings_dialog_.reset(new ProxySettingsDialog( |
| + this, GetNativeWindow())); |
| + } |
| + proxy_settings_dialog_->Show(); |
| + } |
| +} |
| + |
| +StatusAreaHost::ScreenMode WebUILoginView::GetScreenMode() const { |
| + return kLoginMode; |
| +} |
| + |
| +StatusAreaHost::TextStyle WebUILoginView::GetTextStyle() const { |
| + return kWhitePlain; |
| +} |
| + |
| +// Overridden from LoginHtmlDialog::Delegate: |
| +void WebUILoginView::OnLocaleChanged() { |
|
Nikita (slow)
2011/05/18 20:22:12
Generic question: are you planning to have UI lang
rharrison
2011/05/19 00:31:43
I had not thought about it. I think we will have t
|
| + // Proxy settings dialog contains localized strings. |
| + proxy_settings_dialog_.reset(); |
| + SchedulePaint(); |
| +} |
| + |
| +// WebUILoginView private: ----------------------------------------------------- |
| + |
| +void WebUILoginView::InitStatusArea() { |
| + DCHECK(status_area_ == NULL); |
| + status_area_ = new StatusAreaView(this); |
| + status_area_->Init(); |
| + AddChildView(status_area_); |
| +} |
| + |
| +void WebUILoginView::UpdateWindowType() { |
| + std::vector<int> params; |
| + WmIpc::instance()->SetWindowType( |
| + GTK_WIDGET(GetNativeWindow()), |
| + WM_IPC_WINDOW_LOGIN_WEBUI, |
| + ¶ms); |
| +} |
| + |
| +void WebUILoginView::InitVirtualKeyboard() { |
| + if (keyboard_) |
| + return; |
| + |
| + keyboard_ = new KeyboardContainerView(profile_, NULL); |
| + keyboard_->SetVisible(false); |
| + AddChildView(keyboard_); |
| +} |
| + |
| +void WebUILoginView::UpdateKeyboardAndLayout(bool should_show_keyboard) { |
| + if (should_show_keyboard) |
| + InitVirtualKeyboard(); |
| + |
| + if (should_show_keyboard == keyboard_showing_) |
| + return; |
| + |
| + DCHECK(keyboard_); |
| + |
| + keyboard_showing_ = should_show_keyboard; |
| + Layout(); |
| +} |
| + |
| +WebUILoginView::VirtualKeyboardType |
| + WebUILoginView::DecideKeyboardStateForView(views::View* view) { |
| + if (!view) |
| + return NONE; |
| + |
| + std::string cname = GetClassName(); |
|
oshima
2011/05/18 18:24:54
isn't this view->GetClassName?
rharrison
2011/05/19 00:31:43
yes
|
| + if (cname == views::Textfield::kViewClassName) { |
| + return GENERIC; |
| + } else if (cname == RenderWidgetHostViewViews::kViewClassName) { |
| + TabContents* contents = webui_login_->tab_contents(); |
| + bool* editable = contents ? GetFocusedStateAccessor()->GetProperty( |
| + contents->property_bag()) : NULL; |
| + if (editable && *editable) |
| + return GENERIC; |
| + } |
| + return NONE; |
| +} |
| + |
| +void WebUILoginView::Observe(NotificationType type, |
| + const NotificationSource& source, |
| + const NotificationDetails& details) { |
| + if (type == NotificationType::FOCUS_CHANGED_IN_PAGE) { |
| + // Only modify the keyboard state if the currently active tab sent the |
| + // notification. |
| + const TabContents* current_tab = webui_login_->tab_contents(); |
| + TabContents* source_tab = Source<TabContents>(source).ptr(); |
| + const bool editable = *Details<const bool>(details).ptr(); |
| + |
| + if (current_tab == source_tab && TabContentsHasFocus(source_tab)) |
| + UpdateKeyboardAndLayout(editable); |
| + |
| + // Save the state of the focused field so that the keyboard visibility |
| + // can be determined after tab switching. |
| + GetFocusedStateAccessor()->SetProperty( |
| + source_tab->property_bag(), editable); |
| + } else if (type == NotificationType::TAB_CONTENTS_DESTROYED) { |
| + GetFocusedStateAccessor()->DeleteProperty( |
| + Source<TabContents>(source).ptr()->property_bag()); |
| + } |
| +} |
| + |
| +} // namespace chromeos |