blob: 79c29210c58ef4a189b8072f2e7939ecf5ee1720 [file] [log] [blame]
// 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 "views/widget/native_widget_views.h"
#include "ui/gfx/compositor/compositor.h"
#include "views/desktop/desktop_window_view.h"
#include "views/view.h"
#include "views/views_delegate.h"
#include "views/widget/native_widget_view.h"
#include "views/widget/root_view.h"
#if defined(HAVE_IBUS)
#include "views/ime/input_method_ibus.h"
#else
#include "views/ime/mock_input_method.h"
#endif
namespace views {
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetViews, public:
NativeWidgetViews::NativeWidgetViews(internal::NativeWidgetDelegate* delegate)
: delegate_(delegate),
view_(NULL),
active_(false),
minimized_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
hosting_widget_(NULL),
ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) {
}
NativeWidgetViews::~NativeWidgetViews() {
delegate_->OnNativeWidgetDestroying();
delegate_->OnNativeWidgetDestroyed();
if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
delete delegate_;
view_.reset();
}
View* NativeWidgetViews::GetView() {
return view_.get();
}
const View* NativeWidgetViews::GetView() const {
return view_.get();
}
void NativeWidgetViews::OnActivate(bool active) {
if (active_ == active)
return;
active_ = active;
delegate_->OnNativeWidgetActivationChanged(active);
InputMethod* input_method = GetInputMethodNative();
// TODO(oshima): Focus change should be separated from window activation.
// This will be fixed when we have WM API.
if (active) {
input_method->OnFocus();
// See description of got_initial_focus_in_ for details on this.
GetWidget()->GetFocusManager()->RestoreFocusedView();
} else {
input_method->OnBlur();
GetWidget()->GetFocusManager()->StoreFocusedView();
}
view_->SchedulePaint();
}
bool NativeWidgetViews::OnKeyEvent(const KeyEvent& key_event) {
GetInputMethodNative()->DispatchKeyEvent(key_event);
return true;
}
void NativeWidgetViews::DispatchKeyEventPostIME(const KeyEvent& key) {
// TODO(oshima): GTK impl handles menu_key in special way. This may be
// necessary when running under NativeWidgetX.
delegate_->OnKeyEvent(key);
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetViews, NativeWidget implementation:
void NativeWidgetViews::InitNativeWidget(const Widget::InitParams& params) {
ownership_ = params.ownership;
View* parent_view = NULL;
if (params.parent_widget) {
hosting_widget_ = params.parent_widget;
parent_view = hosting_widget_->GetChildViewParent();
} else {
parent_view = ViewsDelegate::views_delegate->GetDefaultParentView();
hosting_widget_ = parent_view->GetWidget();
}
view_.reset(new internal::NativeWidgetView(this));
view_->SetBoundsRect(params.bounds);
view_->SetPaintToLayer(true);
parent_view->AddChildView(view_.get());
// TODO(beng): SetInitParams().
}
NonClientFrameView* NativeWidgetViews::CreateNonClientFrameView() {
return NULL;
}
void NativeWidgetViews::UpdateFrameAfterFrameChange() {
}
bool NativeWidgetViews::ShouldUseNativeFrame() const {
// NOTIMPLEMENTED();
return false;
}
void NativeWidgetViews::FrameTypeChanged() {
}
Widget* NativeWidgetViews::GetWidget() {
return delegate_->AsWidget();
}
const Widget* NativeWidgetViews::GetWidget() const {
return delegate_->AsWidget();
}
gfx::NativeView NativeWidgetViews::GetNativeView() const {
return GetParentNativeWidget()->GetNativeView();
}
gfx::NativeWindow NativeWidgetViews::GetNativeWindow() const {
return GetParentNativeWidget()->GetNativeWindow();
}
Widget* NativeWidgetViews::GetTopLevelWidget() {
if (view_->parent() == ViewsDelegate::views_delegate->GetDefaultParentView())
return GetWidget();
// During Widget destruction, this function may be called after |view_| is
// detached from a Widget, at which point this NativeWidget's Widget becomes
// the effective toplevel.
Widget* containing_widget = view_->GetWidget();
return containing_widget ? containing_widget->GetTopLevelWidget()
: GetWidget();
}
const ui::Compositor* NativeWidgetViews::GetCompositor() const {
return hosting_widget_->GetCompositor();
}
ui::Compositor* NativeWidgetViews::GetCompositor() {
return hosting_widget_->GetCompositor();
}
void NativeWidgetViews::MarkLayerDirty() {
view_->MarkLayerDirty();
}
void NativeWidgetViews::CalculateOffsetToAncestorWithLayer(gfx::Point* offset,
View** ancestor) {
view_->CalculateOffsetToAncestorWithLayer(offset, ancestor);
}
void NativeWidgetViews::ViewRemoved(View* view) {
internal::NativeWidgetPrivate* parent = GetParentNativeWidget();
if (parent)
parent->ViewRemoved(view);
}
void NativeWidgetViews::SetNativeWindowProperty(const char* name, void* value) {
NOTIMPLEMENTED();
}
void* NativeWidgetViews::GetNativeWindowProperty(const char* name) const {
NOTIMPLEMENTED();
return NULL;
}
TooltipManager* NativeWidgetViews::GetTooltipManager() const {
const internal::NativeWidgetPrivate* parent = GetParentNativeWidget();
return parent ? parent->GetTooltipManager() : NULL;
}
bool NativeWidgetViews::IsScreenReaderActive() const {
return GetParentNativeWidget()->IsScreenReaderActive();
}
void NativeWidgetViews::SendNativeAccessibilityEvent(
View* view,
ui::AccessibilityTypes::Event event_type) {
return GetParentNativeWidget()->SendNativeAccessibilityEvent(view,
event_type);
}
void NativeWidgetViews::SetMouseCapture() {
View* parent_root_view = GetParentNativeWidget()->GetWidget()->GetRootView();
static_cast<internal::RootView*>(parent_root_view)->set_capture_view(
view_.get());
GetParentNativeWidget()->SetMouseCapture();
}
void NativeWidgetViews::ReleaseMouseCapture() {
View* parent_root_view = GetParentNativeWidget()->GetWidget()->GetRootView();
static_cast<internal::RootView*>(parent_root_view)->set_capture_view(NULL);
GetParentNativeWidget()->ReleaseMouseCapture();
}
bool NativeWidgetViews::HasMouseCapture() const {
// NOTE: we may need to tweak this to only return true if the parent native
// widget's RootView has us as the capture view.
const internal::NativeWidgetPrivate* parent_widget = GetParentNativeWidget();
if (!parent_widget)
return false;
const internal::RootView* parent_root =
static_cast<const internal::RootView*>(parent_widget->GetWidget()->
GetRootView());
return parent_widget->HasMouseCapture() &&
view_.get() == parent_root->capture_view();
}
void NativeWidgetViews::SetKeyboardCapture() {
GetParentNativeWidget()->SetKeyboardCapture();
}
void NativeWidgetViews::ReleaseKeyboardCapture() {
GetParentNativeWidget()->ReleaseKeyboardCapture();
}
bool NativeWidgetViews::HasKeyboardCapture() const {
return GetParentNativeWidget()->HasKeyboardCapture();
}
InputMethod* NativeWidgetViews::GetInputMethodNative() {
if (!input_method_.get()) {
#if defined(HAVE_IBUS)
input_method_.reset(static_cast<InputMethod*>(new InputMethodIBus(this)));
#else
// TODO(suzhe|oshima): Figure out what to do on windows.
input_method_.reset(new MockInputMethod(this));
#endif
input_method_->Init(GetWidget());
}
return input_method_.get();
}
void NativeWidgetViews::ReplaceInputMethod(InputMethod* input_method) {
CHECK(input_method);
input_method_.reset(input_method);
input_method->set_delegate(this);
input_method->Init(GetWidget());
}
void NativeWidgetViews::CenterWindow(const gfx::Size& size) {
// TODO(beng): actually center.
GetView()->SetBounds(0, 0, size.width(), size.height());
}
void NativeWidgetViews::GetWindowBoundsAndMaximizedState(
gfx::Rect* bounds,
bool* maximized) const {
*bounds = GetView()->bounds();
*maximized = false;
}
void NativeWidgetViews::SetWindowTitle(const std::wstring& title) {
}
void NativeWidgetViews::SetWindowIcons(const SkBitmap& window_icon,
const SkBitmap& app_icon) {
}
void NativeWidgetViews::SetAccessibleName(const std::wstring& name) {
}
void NativeWidgetViews::SetAccessibleRole(ui::AccessibilityTypes::Role role) {
}
void NativeWidgetViews::SetAccessibleState(
ui::AccessibilityTypes::State state) {
}
void NativeWidgetViews::BecomeModal() {
NOTIMPLEMENTED();
}
gfx::Rect NativeWidgetViews::GetWindowScreenBounds() const {
if (GetWidget() == GetWidget()->GetTopLevelWidget())
return view_->bounds();
gfx::Point origin = view_->bounds().origin();
View::ConvertPointToScreen(view_->parent(), &origin);
return gfx::Rect(origin.x(), origin.y(), view_->width(), view_->height());
}
gfx::Rect NativeWidgetViews::GetClientAreaScreenBounds() const {
return GetWindowScreenBounds();
}
gfx::Rect NativeWidgetViews::GetRestoredBounds() const {
return GetWindowScreenBounds();
}
void NativeWidgetViews::SetBounds(const gfx::Rect& bounds) {
// |bounds| are supplied in the coordinates of the parent.
view_->SetBoundsRect(bounds);
}
void NativeWidgetViews::SetSize(const gfx::Size& size) {
view_->SetSize(size);
}
void NativeWidgetViews::SetBoundsConstrained(const gfx::Rect& bounds,
Widget* other_widget) {
// TODO(beng): honor other_widget.
SetBounds(bounds);
}
void NativeWidgetViews::MoveAbove(gfx::NativeView native_view) {
NOTIMPLEMENTED();
}
void NativeWidgetViews::MoveToTop() {
view_->parent()->ReorderChildView(view_.get(), -1);
}
void NativeWidgetViews::SetShape(gfx::NativeRegion region) {
NOTIMPLEMENTED();
}
void NativeWidgetViews::Close() {
Hide();
if (close_widget_factory_.empty()) {
MessageLoop::current()->PostTask(FROM_HERE,
close_widget_factory_.NewRunnableMethod(&NativeWidgetViews::CloseNow));
}
}
void NativeWidgetViews::CloseNow() {
// reset input_method before destroying widget.
input_method_.reset();
// TODO(beng): what about the other case??
if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
delete this;
}
void NativeWidgetViews::EnableClose(bool enable) {
}
void NativeWidgetViews::Show() {
view_->SetVisible(true);
GetWidget()->SetInitialFocus();
}
void NativeWidgetViews::Hide() {
view_->SetVisible(false);
}
void NativeWidgetViews::ShowWithState(ShowState state) {
Show();
}
void NativeWidgetViews::ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) {
Show();
}
bool NativeWidgetViews::IsVisible() const {
return view_->IsVisible();
}
void NativeWidgetViews::Activate() {
// Enable WidgetObserverTest.ActivationChange when this is implemented.
NOTIMPLEMENTED();
}
void NativeWidgetViews::Deactivate() {
NOTIMPLEMENTED();
}
bool NativeWidgetViews::IsActive() const {
return active_;
}
void NativeWidgetViews::SetAlwaysOnTop(bool on_top) {
NOTIMPLEMENTED();
}
void NativeWidgetViews::Maximize() {
NOTIMPLEMENTED();
}
void NativeWidgetViews::Minimize() {
gfx::Rect view_bounds = view_->bounds();
gfx::Rect parent_bounds = view_->parent()->bounds();
restored_bounds_ = view_bounds;
restored_transform_ = view_->GetTransform();
float aspect_ratio = static_cast<float>(view_bounds.width()) /
static_cast<float>(view_bounds.height());
int target_size = 100;
int target_height = target_size;
int target_width = static_cast<int>(aspect_ratio * target_height);
if (target_width > target_size) {
target_width = target_size;
target_height = static_cast<int>(target_width / aspect_ratio);
}
int target_x = 20;
int target_y = parent_bounds.height() - target_size - 20;
view_->SetBounds(
target_x, target_y, view_bounds.width(), view_bounds.height());
ui::Transform transform;
transform.SetScale((float)target_width / (float)view_bounds.width(),
(float)target_height / (float)view_bounds.height());
view_->SetTransform(transform);
minimized_ = true;
}
bool NativeWidgetViews::IsMaximized() const {
// NOTIMPLEMENTED();
return false;
}
bool NativeWidgetViews::IsMinimized() const {
return minimized_;
}
void NativeWidgetViews::Restore() {
minimized_ = false;
view_->SetBoundsRect(restored_bounds_);
view_->SetTransform(restored_transform_);
}
void NativeWidgetViews::SetFullscreen(bool fullscreen) {
NOTIMPLEMENTED();
}
bool NativeWidgetViews::IsFullscreen() const {
// NOTIMPLEMENTED();
return false;
}
void NativeWidgetViews::SetOpacity(unsigned char opacity) {
NOTIMPLEMENTED();
}
void NativeWidgetViews::SetUseDragFrame(bool use_drag_frame) {
NOTIMPLEMENTED();
}
bool NativeWidgetViews::IsAccessibleWidget() const {
NOTIMPLEMENTED();
return false;
}
void NativeWidgetViews::RunShellDrag(View* view,
const ui::OSExchangeData& data,
int operation) {
GetParentNativeWidget()->RunShellDrag(view, data, operation);
}
void NativeWidgetViews::SchedulePaintInRect(const gfx::Rect& rect) {
view_->SchedulePaintInternal(rect);
}
void NativeWidgetViews::SetCursor(gfx::NativeCursor cursor) {
GetParentNativeWidget()->SetCursor(cursor);
}
void NativeWidgetViews::ClearNativeFocus() {
GetParentNativeWidget()->ClearNativeFocus();
}
void NativeWidgetViews::FocusNativeView(gfx::NativeView native_view) {
GetParentNativeWidget()->FocusNativeView(native_view);
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetViews, private:
internal::NativeWidgetPrivate* NativeWidgetViews::GetParentNativeWidget() {
Widget* containing_widget = view_->GetWidget();
return containing_widget ? static_cast<internal::NativeWidgetPrivate*>(
containing_widget->native_widget()) :
NULL;
}
const internal::NativeWidgetPrivate*
NativeWidgetViews::GetParentNativeWidget() const {
const Widget* containing_widget = view_->GetWidget();
return containing_widget ? static_cast<const internal::NativeWidgetPrivate*>(
containing_widget->native_widget()) :
NULL;
}
} // namespace views