diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-29 06:02:19 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-29 06:02:19 +0000 |
commit | 17dee5e7005a82e08d11be50d56477939124a6b7 (patch) | |
tree | 7133a5d7a086ce238057cb82e0e81d332dafba8f /views | |
parent | bf0136d62bfe02f57821ce026c04b6e8204eb482 (diff) | |
download | chromium_src-17dee5e7005a82e08d11be50d56477939124a6b7.zip chromium_src-17dee5e7005a82e08d11be50d56477939124a6b7.tar.gz chromium_src-17dee5e7005a82e08d11be50d56477939124a6b7.tar.bz2 |
Refactors HWNDView, NativeViewHostGtk and NativeViewHost so that they match the NativeControl pattern established for NativeButtons. NativeViewHost is a platform-neutral class that clients instantiate. Behind the scenes the platform instantiates the appropriate NativeViewHostWrapper implementation, either NativeViewHostGtk (as before) or NativeViewHostWin (replaces HWNDView).
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/114059
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17169 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
29 files changed, 684 insertions, 566 deletions
diff --git a/views/controls/button/native_button_gtk.cc b/views/controls/button/native_button_gtk.cc index 3f10897..63da111 100644 --- a/views/controls/button/native_button_gtk.cc +++ b/views/controls/button/native_button_gtk.cc @@ -11,6 +11,7 @@ #include "views/controls/button/checkbox.h" #include "views/controls/button/native_button.h" #include "views/controls/button/radio_button.h" +#include "views/controls/native/native_view_host_gtk.h" #include "views/widget/widget.h" namespace views { @@ -21,7 +22,7 @@ NativeButtonGtk::NativeButtonGtk(NativeButton* native_button) // Associates the actual GtkWidget with the native_button so the native_button // is the one considered as having the focus (not the wrapper) when the // GtkWidget is focused directly (with a click for example). - SetAssociatedFocusView(native_button); + set_focus_view(native_button); } NativeButtonGtk::~NativeButtonGtk() { @@ -90,7 +91,7 @@ void NativeButtonGtk::NativeControlCreated(GtkWidget* widget) { // static void NativeButtonGtk::CallClicked(GtkButton* widget) { - View* view = GetViewForNative(GTK_WIDGET(widget)); + View* view = NativeViewHostGtk::GetViewForNative(GTK_WIDGET(widget)); if (view) static_cast<NativeButtonGtk*>(view)->OnClicked(); } diff --git a/views/controls/button/native_button_win.cc b/views/controls/button/native_button_win.cc index 5dd70d3..8d51907 100644 --- a/views/controls/button/native_button_win.cc +++ b/views/controls/button/native_button_win.cc @@ -23,7 +23,7 @@ NativeButtonWin::NativeButtonWin(NativeButton* native_button) // Associates the actual HWND with the native_button so the native_button is // the one considered as having the focus (not the wrapper) when the HWND is // focused directly (with a click for example). - SetAssociatedFocusView(native_button); + set_focus_view(native_button); } NativeButtonWin::~NativeButtonWin() { @@ -33,11 +33,11 @@ NativeButtonWin::~NativeButtonWin() { // NativeButtonWin, NativeButtonWrapper implementation: void NativeButtonWin::UpdateLabel() { - SetWindowText(GetHWND(), native_button_->label().c_str()); + SetWindowText(native_view(), native_button_->label().c_str()); } void NativeButtonWin::UpdateFont() { - SendMessage(GetHWND(), WM_SETFONT, + SendMessage(native_view(), WM_SETFONT, reinterpret_cast<WPARAM>(native_button_->font().hfont()), FALSE); } @@ -48,7 +48,7 @@ void NativeButtonWin::UpdateEnabled() { void NativeButtonWin::UpdateDefault() { if (!IsCheckbox()) { - SendMessage(GetHWND(), BM_SETSTYLE, + SendMessage(native_view(), BM_SETSTYLE, native_button_->is_default() ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON, true); } @@ -68,7 +68,7 @@ void NativeButtonWin::SetFocus() { gfx::Size NativeButtonWin::GetPreferredSize() { SIZE sz = {0}; - SendMessage(GetHWND(), BCM_GETIDEALSIZE, 0, reinterpret_cast<LPARAM>(&sz)); + SendMessage(native_view(), BCM_GETIDEALSIZE, 0, reinterpret_cast<LPARAM>(&sz)); return gfx::Size(sz.cx, sz.cy); } @@ -142,12 +142,12 @@ gfx::Size NativeCheckboxWin::GetPreferredSize() { // NativeCheckboxWin, NativeButtonWrapper implementation: void NativeCheckboxWin::UpdateChecked() { - SendMessage(GetHWND(), BM_SETCHECK, + SendMessage(native_view(), BM_SETCHECK, checkbox_->checked() ? BST_CHECKED : BST_UNCHECKED, 0); } void NativeCheckboxWin::SetPushed(bool pushed) { - SendMessage(GetHWND(), BM_SETSTATE, pushed, 0); + SendMessage(native_view(), BM_SETSTATE, pushed, 0); } bool NativeCheckboxWin::OnKeyDown(int vkey) { diff --git a/views/controls/hwnd_view.cc b/views/controls/hwnd_view.cc deleted file mode 100644 index 77269f2..0000000 --- a/views/controls/hwnd_view.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2006-2008 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/controls/hwnd_view.h" - -#include "app/gfx/canvas.h" -#include "base/logging.h" -#include "views/focus/focus_manager.h" -#include "views/widget/widget.h" - -namespace views { - -static const char kViewClassName[] = "views/HWNDView"; - -HWNDView::HWNDView() : NativeViewHost() { -} - -HWNDView::~HWNDView() { -} - -void HWNDView::Attach(HWND hwnd) { - DCHECK(native_view() == NULL); - DCHECK(hwnd) << "Impossible detatched tab case; See crbug.com/6316"; - - set_native_view(hwnd); - - // First hide the new window. We don't want anything to draw (like sub-hwnd - // borders), when we change the parent below. - ShowWindow(hwnd, SW_HIDE); - - // Need to set the HWND's parent before changing its size to avoid flashing. - ::SetParent(hwnd, GetWidget()->GetNativeView()); - Layout(); - - // Register with the focus manager so the associated view is focused when the - // native control gets the focus. - FocusManager::InstallFocusSubclass( - hwnd, associated_focus_view() ? associated_focus_view() : this); -} - -void HWNDView::Detach() { - DCHECK(native_view()); - FocusManager::UninstallFocusSubclass(native_view()); - set_native_view(NULL); - set_installed_clip(false); -} - -void HWNDView::Paint(gfx::Canvas* canvas) { - // The area behind our window is black, so during a fast resize (where our - // content doesn't draw over the full size of our HWND, and the HWND - // background color doesn't show up), we need to cover that blackness with - // something so that fast resizes don't result in black flash. - // - // It would be nice if this used some approximation of the page's - // current background color. - if (installed_clip()) - canvas->FillRectInt(SkColorSetRGB(255, 255, 255), 0, 0, width(), height()); -} - -std::string HWNDView::GetClassName() const { - return kViewClassName; -} - -void HWNDView::ViewHierarchyChanged(bool is_add, View *parent, View *child) { - if (!native_view()) - return; - - Widget* widget = GetWidget(); - if (is_add && widget) { - HWND parent_hwnd = ::GetParent(native_view()); - HWND widget_hwnd = widget->GetNativeView(); - if (parent_hwnd != widget_hwnd) - ::SetParent(native_view(), widget_hwnd); - if (IsVisibleInRootView()) - ::ShowWindow(native_view(), SW_SHOW); - else - ::ShowWindow(native_view(), SW_HIDE); - Layout(); - } else if (!is_add) { - ::ShowWindow(native_view(), SW_HIDE); - ::SetParent(native_view(), NULL); - } -} - -void HWNDView::Focus() { - ::SetFocus(native_view()); -} - -void HWNDView::InstallClip(int x, int y, int w, int h) { - HRGN clip_region = CreateRectRgn(x, y, x + w, y + h); - // NOTE: SetWindowRgn owns the region (as well as the deleting the - // current region), as such we don't delete the old region. - SetWindowRgn(native_view(), clip_region, FALSE); -} - -void HWNDView::UninstallClip() { - SetWindowRgn(native_view(), 0, FALSE); -} - -void HWNDView::ShowWidget(int x, int y, int w, int h) { - UINT swp_flags = SWP_DEFERERASE | - SWP_NOACTIVATE | - SWP_NOCOPYBITS | - SWP_NOOWNERZORDER | - SWP_NOZORDER; - // Only send the SHOWWINDOW flag if we're invisible, to avoid flashing. - if (!::IsWindowVisible(native_view())) - swp_flags = (swp_flags | SWP_SHOWWINDOW) & ~SWP_NOREDRAW; - - if (fast_resize()) { - // In a fast resize, we move the window and clip it with SetWindowRgn. - RECT win_rect; - GetWindowRect(native_view(), &win_rect); - gfx::Rect rect(win_rect); - ::SetWindowPos(native_view(), 0, x, y, rect.width(), rect.height(), - swp_flags); - - HRGN clip_region = CreateRectRgn(0, 0, w, h); - SetWindowRgn(native_view(), clip_region, FALSE); - set_installed_clip(true); - } else { - ::SetWindowPos(native_view(), 0, x, y, w, h, swp_flags); - } -} - -void HWNDView::HideWidget() { - if (!::IsWindowVisible(native_view())) - return; // Currently not visible, nothing to do. - - // The window is currently visible, but its clipped by another view. Hide - // it. - ::SetWindowPos(native_view(), 0, 0, 0, 0, 0, - SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | - SWP_NOREDRAW | SWP_NOOWNERZORDER); -} - -} // namespace views diff --git a/views/controls/hwnd_view.h b/views/controls/hwnd_view.h deleted file mode 100644 index 1ad1ef6..0000000 --- a/views/controls/hwnd_view.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#ifndef VIEWS_CONTROLS_HWND_VIEW_H_ -#define VIEWS_CONTROLS_HWND_VIEW_H_ - -#include <string> - -#include "views/controls/native_view_host.h" - -namespace views { - -///////////////////////////////////////////////////////////////////////////// -// -// HWNDView class -// -// The HWNDView class hosts a native window handle (HWND) sizing it -// according to the bounds of the view. This is useful whenever you need to -// show a UI control that has a HWND (e.g. a native windows Edit control) -// within thew View hierarchy and benefit from the sizing/layout. -// -///////////////////////////////////////////////////////////////////////////// -// TODO: Rename this to NativeViewHostWin. -class HWNDView : public NativeViewHost { - public: - HWNDView(); - virtual ~HWNDView(); - - // Attach a window handle to this View, making the window it represents - // subject to sizing according to this View's parent container's Layout - // Manager's sizing heuristics. - // - // This object should be added to the view hierarchy before calling this - // function, which will expect the parent to be valid. - void Attach(HWND hwnd); - - // Detach the attached window handle. It will no longer be updated - void Detach(); - - // TODO(sky): convert this to native_view(). - HWND GetHWND() const { return native_view(); } - - virtual void Paint(gfx::Canvas* canvas); - - // Overridden from View. - virtual std::string GetClassName() const; - - protected: - virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child); - - virtual void Focus(); - - // NativeHostView overrides. - virtual void InstallClip(int x, int y, int w, int h); - virtual void UninstallClip(); - virtual void ShowWidget(int x, int y, int w, int h); - virtual void HideWidget(); - - private: - DISALLOW_COPY_AND_ASSIGN(HWNDView); -}; - -} // namespace views - -#endif // VIEWS_CONTROLS_HWND_VIEW_H_ diff --git a/views/controls/native/native_view_host.cc b/views/controls/native/native_view_host.cc new file mode 100644 index 0000000..18ba870 --- /dev/null +++ b/views/controls/native/native_view_host.cc @@ -0,0 +1,137 @@ +// Copyright (c) 2009 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/controls/native/native_view_host.h" + +#include "base/logging.h" +#include "app/gfx/canvas.h" +#include "views/controls/native/native_view_host_wrapper.h" +#include "views/widget/widget.h" + +namespace views { + +// static +const char NativeViewHost::kViewClassName[] = "views/NativeViewHost"; + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHost, public: + +NativeViewHost::NativeViewHost() + : native_view_(NULL), + native_wrapper_(NULL), + fast_resize_(false), + focus_view_(NULL) { + // The native widget is placed relative to the root. As such, we need to + // know when the position of any ancestor changes, or our visibility relative + // to other views changed as it'll effect our position relative to the root. + SetNotifyWhenVisibleBoundsInRootChanges(true); +} + +NativeViewHost::~NativeViewHost() { +} + +void NativeViewHost::Attach(gfx::NativeView native_view) { + DCHECK(!native_view_); + native_view_ = native_view; + native_wrapper_->NativeViewAttached(); +} + +void NativeViewHost::Detach() { + DCHECK(native_view_); + native_wrapper_->NativeViewDetaching(); + native_view_ = NULL; +} + +void NativeViewHost::SetPreferredSize(const gfx::Size& size) { + preferred_size_ = size; + PreferredSizeChanged(); +} + +void NativeViewHost::NativeViewDestroyed() { + // TODO(beng): figure out if this should/could call Detach instead since as it + // stands right now this object is left in an inconsistent state. + native_view_ = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHost, View overrides: + +gfx::Size NativeViewHost::GetPreferredSize() { + return preferred_size_; +} + +void NativeViewHost::Layout() { + if (!native_view_ || !native_wrapper_) + return; + + // Since widgets know nothing about the View hierarchy (they are direct + // children of the Widget that hosts our View hierarchy) they need to be + // positioned in the coordinate system of the Widget, not the current + // view. + gfx::Point top_left; + ConvertPointToWidget(this, &top_left); + + gfx::Rect vis_bounds = GetVisibleBounds(); + bool visible = !vis_bounds.IsEmpty(); + + if (visible && !fast_resize_ && native_wrapper_) { + if (vis_bounds.size() != size()) { + // Only a portion of the Widget is really visible. + int x = vis_bounds.x(); + int y = vis_bounds.y(); + native_wrapper_->InstallClip(x, y, vis_bounds.width(), + vis_bounds.height()); + } else if (native_wrapper_->HasInstalledClip()) { + // The whole widget is visible but we installed a clip on the widget, + // uninstall it. + native_wrapper_->UninstallClip(); + } + } + + if (visible) + native_wrapper_->ShowWidget(top_left.x(), top_left.y(), width(), height()); + else + native_wrapper_->HideWidget(); +} + +void NativeViewHost::Paint(gfx::Canvas* canvas) { + // The area behind our window is black, so during a fast resize (where our + // content doesn't draw over the full size of our native view, and the native + // view background color doesn't show up), we need to cover that blackness + // with something so that fast resizes don't result in black flash. + // + // It would be nice if this used some approximation of the page's + // current background color. + if (native_wrapper_->HasInstalledClip()) + canvas->FillRectInt(SK_ColorWHITE, 0, 0, width(), height()); +} + +void NativeViewHost::VisibilityChanged(View* starting_from, bool is_visible) { + Layout(); +} + +void NativeViewHost::VisibleBoundsInRootChanged() { + Layout(); +} + +void NativeViewHost::ViewHierarchyChanged(bool is_add, View* parent, + View* child) { + if (is_add && GetWidget()) { + if (!native_wrapper_) + native_wrapper_ = NativeViewHostWrapper::CreateWrapper(this); + native_wrapper_->AddedToWidget(); + } else if (!is_add) { + native_wrapper_->RemovedFromWidget(); + } +} + +std::string NativeViewHost::GetClassName() const { + return kViewClassName; +} + +void NativeViewHost::Focus() { + native_wrapper_->SetFocus(); +} + +} // namespace views diff --git a/views/controls/native_view_host.h b/views/controls/native/native_view_host.h index 15cf98e..c9dce23 100644 --- a/views/controls/native_view_host.h +++ b/views/controls/native/native_view_host.h @@ -13,21 +13,34 @@ namespace views { -// Base class for embedding native widgets in a view. +class NativeViewHostWrapper; + +// A View type that hosts a gfx::NativeView. The bounds of the native view are +// kept in sync with the bounds of this view as it is moved and sized. +// Under the hood, a platform-specific NativeViewHostWrapper implementation does +// the platform-specific work of manipulating the underlying OS widget type. class NativeViewHost : public View { public: + // The NativeViewHost's class name. + static const char kViewClassName[]; + NativeViewHost(); virtual ~NativeViewHost(); - void SetPreferredSize(const gfx::Size& size); - virtual gfx::Size GetPreferredSize(); + // Attach a gfx::NativeView to this View. Its bounds will be kept in sync + // with the bounds of this View until Detach is called. + // + // Because native views are positioned in the coordinates of their parent + // native view, this function should only be called after this View has been + // added to a View hierarchy hosted within a valid Widget. + void Attach(gfx::NativeView native_view); - // Overriden to invoke Layout. - virtual void VisibilityChanged(View* starting_from, bool is_visible); + // Detach the attached window handle. Its bounds and visibility will no longer + // be manipulated by this View. + void Detach(); - // Invokes any of InstallClip, UninstallClip, ShowWidget or HideWidget - // depending upon what portion of the widget is view in the parent. - virtual void Layout(); + // Sets a preferred size for the native view attached to this View. + void SetPreferredSize(const gfx::Size& size); // A NativeViewHost has an associated focus View so that the focus of the // native control and of the View are kept in sync. In simple cases where the @@ -36,58 +49,48 @@ class NativeViewHost : public View { // view (such as TextField), the actual View is not the NativeViewHost and // this method must be called to set that. // This method must be called before Attach(). - void SetAssociatedFocusView(View* view) { focus_view_ = view; } - View* associated_focus_view() { return focus_view_; } + void set_focus_view(View* view) { focus_view_ = view; } + View* focus_view() { return focus_view_; } + // Fast resizing will move the native view and clip its visible region, this + // will result in white areas and will not resize the content (so scrollbars + // will be all wrong and content will flow offscreen). Only use this + // when you're doing extremely quick, high-framerate vertical resizes + // and don't care about accuracy. Make sure you do a real resize at the + // end. USE WITH CAUTION. void set_fast_resize(bool fast_resize) { fast_resize_ = fast_resize; } bool fast_resize() const { return fast_resize_; } - // The embedded native view. + // Accessor for |native_view_|. gfx::NativeView native_view() const { return native_view_; } - protected: - // Notification that our visible bounds relative to the root has changed. - // Invokes Layout to make sure the widget is positioned correctly. - virtual void VisibleBoundsInRootChanged(); - - // Sets the native view. Subclasses will typically invoke Layout after setting - // the widget. - void set_native_view(gfx::NativeView widget) { native_view_ = widget; } + void NativeViewDestroyed(); - // Installs a clip on the native widget. - virtual void InstallClip(int x, int y, int w, int h) = 0; - - // Removes the clip installed on the native widget by way of InstallClip. - virtual void UninstallClip() = 0; - - // Shows the widget at the specified position (relative to the parent widget). - virtual void ShowWidget(int x, int y, int w, int h) = 0; - - // Hides the widget. NOTE: this may be invoked when the widget is already - // hidden. - virtual void HideWidget() = 0; + // Overridden from View: + virtual gfx::Size GetPreferredSize(); + virtual void Layout(); + virtual void Paint(gfx::Canvas* canvas); + virtual void VisibilityChanged(View* starting_from, bool is_visible); - void set_installed_clip(bool installed_clip) { - installed_clip_ = installed_clip; - } - bool installed_clip() const { return installed_clip_; } + protected: + virtual void VisibleBoundsInRootChanged(); + virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); + virtual std::string GetClassName() const; + virtual void Focus(); private: + // The attached native view. gfx::NativeView native_view_; + // A platform-specific wrapper that does the OS-level manipulation of the + // attached gfx::NativeView. + NativeViewHostWrapper* native_wrapper_; + // The preferred size of this View gfx::Size preferred_size_; - // Have we installed a region on the HWND used to clip to only the visible - // portion of the HWND? - bool installed_clip_; - - // Fast resizing will move the hwnd and clip its window region, this will - // result in white areas and will not resize the content (so scrollbars - // will be all wrong and content will flow offscreen). Only use this - // when you're doing extremely quick, high-framerate vertical resizes - // and don't care about accuracy. Make sure you do a real resize at the - // end. USE WITH CAUTION. + // True if the native view is being resized using the fast method described + // in the setter/accessor above. bool fast_resize_; // The view that should be given focus when this NativeViewHost is focused. diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc new file mode 100644 index 0000000..643fa30 --- /dev/null +++ b/views/controls/native/native_view_host_gtk.cc @@ -0,0 +1,173 @@ +// Copyright (c) 2009 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/controls/native/native_view_host_gtk.h" + +#include <gtk/gtk.h> + +#include "base/logging.h" +#include "views/controls/native/native_view_host.h" +#include "views/widget/widget_gtk.h" + +namespace views { + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHostGtk, public: + +NativeViewHostWin::NativeViewHostWin(NativeViewHost* host) + : host_(host), + installed_clip_(false), + destroy_signal_id_(0) { +} + +NativeViewHostGtk::~NativeViewHostGtk() { +} + +// static +View* NativeViewHostGtk::GetViewForNative(GtkWidget* widget) { + gpointer user_data = g_object_get_data(G_OBJECT(widget), "chrome-view"); + return static_cast<View*>(user_data); +} + +// static +void NativeViewHostGtk::SetViewForNative(GtkWidget* widget, View* view) { + g_object_set_data(G_OBJECT(widget), "chrome-view", view); +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHostGtk, NativeViewHostWrapper implementation: + +void NativeViewHostGtk::NativeViewAttached() { + DCHECK(host_->native_view()); + + // Adds a mapping between the GtkWidget and us. + SetViewForNative(host_->native_view(), host_); + + destroy_signal_id_ = g_signal_connect(G_OBJECT(host_->native_view()), + "destroy", G_CALLBACK(CallDestroy), + NULL); + + // First hide the new window. We don't want anything to draw (like sub-hwnd + // borders), when we change the parent below. + gtk_widget_hide(host_->native_view()); + + // Set the parent. + static_cast<WidgetGtk*>(host_->GetWidget())->AddChild(host_->native_view()); + host_->Layout(); + + // TODO(port): figure out focus. + // FocusManager::InstallFocusSubclass( + // hwnd, associated_focus_view()_ ? associated_focus_view() : this); +} + +void NativeViewHostGtk::NativeViewDetaching() { + DCHECK(host_->native_view()); + + g_signal_handler_disconnect(G_OBJECT(host_->native_view()), + destroy_signal_id_); + destroy_signal_id_ = 0; + + // TODO(port): focus. + // FocusManager::UninstallFocusSubclass(native_view()); + installed_clip_ = false; +} + +void NativeViewHostGtk::AddedToWidget() { + WidgetGtk* parent_widget = static_cast<WidgetGtk*>(host_->GetWidget()); + GtkWidget* widget_parent = gtk_widget_get_parent(host_->native_view()); + GtkWidget* parent_widget_widget = parent_widget->child_widget_parent(); + if (widget_parent != parent_widget_widget) { + g_object_ref(host_->native_view()); + if (widget_parent) + gtk_container_remove(GTK_CONTAINER(widget_parent), host_->native_view()); + gtk_container_add(GTK_CONTAINER(parent_widget_widget), + host_->native_view()); + g_object_unref(host_->native_view()); + } + if (host_->IsVisibleInRootView()) + gtk_widget_show(host_->native_view()); + else + gtk_widget_hide(host_->native_view()); + host_->Layout(); +} + +void NativeViewHostGtk::RemovedFromWidget() { + WidgetGtk* parent_widget = static_cast<WidgetGtk*>(host_->GetWidget()); + gtk_widget_hide(host_->native_view()); + if (parent_widget) { + gtk_container_remove(GTK_CONTAINER(parent_widget->child_widget_parent()), + host_->native_view()); + } +} + +void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) { + DCHECK(w > 0 && h > 0); + + bool has_window = + (GTK_WIDGET_FLAGS(host_->native_view()) & GTK_NO_WINDOW) == 0; + if (!has_window) { + // Clip is only supported on GtkWidgets that have windows. If this becomes + // an issue (as it may be in the options dialog) we'll need to wrap the + // widget in a GtkFixed with a window. We have to do this as not all widgets + // support turning on GTK_NO_WINDOW (for example, buttons don't appear to + // draw anything when they have a window). + NOTREACHED(); + return; + } + DCHECK(has_window); + // Unset the current region. + gdk_window_shape_combine_region(host_->native_view()->window, NULL, 0, 0); + + // Set a new region. + // TODO: using shapes is a bit expensive. Should investigated if there is + // another more efficient way to accomplish this. + GdkRectangle clip_rect = { x, y, w, h }; + GdkRegion* clip_region = gdk_region_rectangle(&clip_rect); + gdk_window_shape_combine_region(host_->native_view()->window, clip_region, x, + y); + gdk_region_destroy(clip_region); + installed_clip_ = true; +} + +void NativeViewHostGtk::UninstallClip() { + gtk_widget_shape_combine_mask(host_->native_view(), NULL, 0, 0); + installed_clip_ = false; +} + +void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) { + WidgetGtk* parent = static_cast<WidgetGtk*>(host_->GetWidget()); + parent->PositionChild(host_->native_view(), x, y, w, h); + gtk_widget_show(host_->native_view()); +} + +void NativeViewHostGtk::HideWidget() { + gtk_widget_hide(host_->native_view()); +} + +void NativeViewHostGtk::SetFocus() { + NOTIMPLEMENTED(); +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHostGtk, private: + +// static +void NativeViewHostGtk::CallDestroy(GtkObject* object) { + View* view = GetViewForNative(GTK_WIDGET(object)); + if (!view) + return; + + return static_cast<NativeViewHost*>(view)->NativeViewDestroyed(); +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHostWrapper, public: + +// static +NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( + NativeViewHost* host) { + return new NativeViewHostGtk(host); +} + +} // namespace views diff --git a/views/controls/native_view_host_gtk.h b/views/controls/native/native_view_host_gtk.h index 1b383af..40a6a65 100644 --- a/views/controls/native_view_host_gtk.h +++ b/views/controls/native/native_view_host_gtk.h @@ -8,50 +8,47 @@ #include <gtk/gtk.h> #include <string> -#include "views/controls/native_view_host.h" +#include "base/logging.h" +#include "views/controls/native/native_view_host_wrapper.h" namespace views { -class NativeViewHostGtk : public NativeViewHost { +class View; + +class NativeViewHostGtk : public NativeViewHostWrapper { public: - NativeViewHostGtk(); + explicit NativeViewHostGtk(NativeViewHost* host); virtual ~NativeViewHostGtk(); // Sets and retrieves the View associated with a particular widget. + // TODO(beng): move to NativeViewHost, and have take gfx::NativeViews. static View* GetViewForNative(GtkWidget* widget); static void SetViewForNative(GtkWidget* widget, View* view); - // Attach a widget to this View, making the window it represents - // subject to sizing according to this View's parent container's Layout - // Manager's sizing heuristics. - // - // This object should be added to the view hierarchy before calling this - // function, which will expect the parent to be valid. - - // TODO: figure out ownership! - void Attach(gfx::NativeView w); - - // Detach the attached widget handle. It will no longer be updated - void Detach(); - - protected: - virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child); - - virtual void Focus(); - - // NativeHostView overrides. + // Overridden from NativeViewHostWrapper: + virtual void NativeViewAttached(); + virtual void NativeViewDetaching(); + virtual void AddedToWidget(); + virtual void RemovedFromWidget(); virtual void InstallClip(int x, int y, int w, int h); + virtual bool HasInstalledClip(); virtual void UninstallClip(); virtual void ShowWidget(int x, int y, int w, int h); virtual void HideWidget(); + virtual void SetFocus(); private: + // Our associated NativeViewHost. + NativeViewHost* host_; + + // Have we installed a region on the gfx::NativeView used to clip to only the + // visible portion of the gfx::NativeView ? + bool installed_clip_; + // Signal handle id for 'destroy' signal. gulong destroy_signal_id_; // Invoked from the 'destroy' signal. - void OnDestroy(); - static void CallDestroy(GtkObject* object); DISALLOW_COPY_AND_ASSIGN(NativeViewHostGtk); @@ -60,3 +57,4 @@ class NativeViewHostGtk : public NativeViewHost { } // namespace views #endif // VIEWS_CONTROLS_NATIVE_HOST_VIEW_GTK_H_ + diff --git a/views/controls/native/native_view_host_win.cc b/views/controls/native/native_view_host_win.cc new file mode 100644 index 0000000..0cbaaa7 --- /dev/null +++ b/views/controls/native/native_view_host_win.cc @@ -0,0 +1,135 @@ +// Copyright (c) 2006-2008 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/controls/native/native_view_host_win.h" + +#include "app/gfx/canvas.h" +#include "base/logging.h" +#include "views/controls/native/native_view_host.h" +#include "views/focus/focus_manager.h" +#include "views/widget/widget.h" + +namespace views { + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHostWin, public: + +NativeViewHostWin::NativeViewHostWin(NativeViewHost* host) + : host_(host), + installed_clip_(false) { +} + +NativeViewHostWin::~NativeViewHostWin() { +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHostWin, NativeViewHostWrapper implementation: + +void NativeViewHostWin::NativeViewAttached() { + DCHECK(host_->native_view()) + << "Impossible detatched tab case; See crbug.com/6316"; + + // First hide the new window. We don't want anything to draw (like sub-hwnd + // borders), when we change the parent below. + ShowWindow(host_->native_view(), SW_HIDE); + + // Need to set the HWND's parent before changing its size to avoid flashing. + SetParent(host_->native_view(), host_->GetWidget()->GetNativeView()); + host_->Layout(); + + // Register with the focus manager so the associated view is focused when the + // native control gets the focus. + View* focus_view = host_->focus_view() ? host_->focus_view() : host_; + FocusManager::InstallFocusSubclass(host_->native_view(), focus_view); +} + +void NativeViewHostWin::NativeViewDetaching() { + DCHECK(host_->native_view()); + FocusManager::UninstallFocusSubclass(host_->native_view()); + installed_clip_ = false; +} + +void NativeViewHostWin::AddedToWidget() { + HWND parent_hwnd = GetParent(host_->native_view()); + HWND widget_hwnd = host_->GetWidget()->GetNativeView(); + if (parent_hwnd != widget_hwnd) + SetParent(host_->native_view(), widget_hwnd); + if (host_->IsVisibleInRootView()) + ShowWindow(host_->native_view(), SW_SHOW); + else + ShowWindow(host_->native_view(), SW_HIDE); + host_->Layout(); +} + +void NativeViewHostWin::RemovedFromWidget() { + ShowWindow(host_->native_view(), SW_HIDE); + SetParent(host_->native_view(), NULL); +} + +void NativeViewHostWin::InstallClip(int x, int y, int w, int h) { + HRGN clip_region = CreateRectRgn(x, y, x + w, y + h); + // NOTE: SetWindowRgn owns the region (as well as the deleting the + // current region), as such we don't delete the old region. + SetWindowRgn(host_->native_view(), clip_region, FALSE); + installed_clip_ = true; +} + +bool NativeViewHostWin::HasInstalledClip() { + return installed_clip_; +} + +void NativeViewHostWin::UninstallClip() { + SetWindowRgn(host_->native_view(), 0, FALSE); + installed_clip_ = false; +} + +void NativeViewHostWin::ShowWidget(int x, int y, int w, int h) { + UINT swp_flags = SWP_DEFERERASE | + SWP_NOACTIVATE | + SWP_NOCOPYBITS | + SWP_NOOWNERZORDER | + SWP_NOZORDER; + // Only send the SHOWWINDOW flag if we're invisible, to avoid flashing. + if (!IsWindowVisible(host_->native_view())) + swp_flags = (swp_flags | SWP_SHOWWINDOW) & ~SWP_NOREDRAW; + + if (host_->fast_resize()) { + // In a fast resize, we move the window and clip it with SetWindowRgn. + RECT win_rect; + GetWindowRect(host_->native_view(), &win_rect); + gfx::Rect rect(win_rect); + SetWindowPos(host_->native_view(), 0, x, y, rect.width(), rect.height(), + swp_flags); + + InstallClip(0, 0, w, h); + } else { + SetWindowPos(host_->native_view(), 0, x, y, w, h, swp_flags); + } +} + +void NativeViewHostWin::HideWidget() { + if (!IsWindowVisible(host_->native_view())) + return; // Currently not visible, nothing to do. + + // The window is currently visible, but its clipped by another view. Hide + // it. + SetWindowPos(host_->native_view(), 0, 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | + SWP_NOREDRAW | SWP_NOOWNERZORDER); +} + +void NativeViewHostWin::SetFocus() { + ::SetFocus(host_->native_view()); +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeViewHostWrapper, public: + +// static +NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( + NativeViewHost* host) { + return new NativeViewHostWin(host); +} + +} // namespace views diff --git a/views/controls/native/native_view_host_win.h b/views/controls/native/native_view_host_win.h new file mode 100644 index 0000000..51bc616 --- /dev/null +++ b/views/controls/native/native_view_host_win.h @@ -0,0 +1,46 @@ +// Copyright (c) 2006-2008 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. + +#ifndef VIEWS_CONTROLS_HWND_VIEW_H_ +#define VIEWS_CONTROLS_HWND_VIEW_H_ + +#include "base/logging.h" +#include "views/controls/native/native_view_host_wrapper.h" + +namespace views { + +class NativeViewHost; + +// A Windows implementation of NativeViewHostWrapper +class NativeViewHostWin : public NativeViewHostWrapper { + public: + explicit NativeViewHostWin(NativeViewHost* host); + virtual ~NativeViewHostWin(); + + // Overridden from NativeViewHostWrapper: + virtual void NativeViewAttached(); + virtual void NativeViewDetaching(); + virtual void AddedToWidget(); + virtual void RemovedFromWidget(); + virtual void InstallClip(int x, int y, int w, int h); + virtual bool HasInstalledClip(); + virtual void UninstallClip(); + virtual void ShowWidget(int x, int y, int w, int h); + virtual void HideWidget(); + virtual void SetFocus(); + + private: + // Our associated NativeViewHost. + NativeViewHost* host_; + + // Have we installed a region on the gfx::NativeView used to clip to only the + // visible portion of the gfx::NativeView ? + bool installed_clip_; + + DISALLOW_COPY_AND_ASSIGN(NativeViewHostWin); +}; + +} // namespace views + +#endif // VIEWS_CONTROLS_HWND_VIEW_H_ diff --git a/views/controls/native/native_view_host_wrapper.h b/views/controls/native/native_view_host_wrapper.h new file mode 100644 index 0000000..4b14403 --- /dev/null +++ b/views/controls/native/native_view_host_wrapper.h @@ -0,0 +1,62 @@ +// Copyright (c) 2009 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. + +#ifndef VIEWS_CONTROLS_NATIVE_NATIVE_VIEW_HOST_WRAPPER_H_ +#define VIEWS_CONTROLS_NATIVE_NATIVE_VIEW_HOST_WRAPPER_H_ + +namespace views { + +class NativeViewHost; + +// An interface that implemented by an object that wraps a gfx::NativeView on +// a specific platform, used to perform platform specific operations on that +// native view when attached, detached, moved and sized. +class NativeViewHostWrapper { + public: + // Called when a gfx::NativeView has been attached to the associated + // NativeViewHost, allowing the wrapper to perform platform-specific + // initialization. + virtual void NativeViewAttached() = 0; + + // Called before the attached gfx::NativeView is detached from the + // NativeViewHost, allowing the wrapper to perform platform-specific + // cleanup. + virtual void NativeViewDetaching() = 0; + + // Called when our associated NativeViewHost is added to a View hierarchy + // rooted at a valid Widget. + virtual void AddedToWidget() = 0; + + // Called when our associated NativeViewHost is removed from a View hierarchy + // rooted at a valid Widget. + virtual void RemovedFromWidget() = 0; + + // Installs a clip on the gfx::NativeView. + virtual void InstallClip(int x, int y, int w, int h) = 0; + + // Whether or not a clip has been installed on the wrapped gfx::NativeView. + virtual bool HasInstalledClip() = 0; + + // Removes the clip installed on the gfx::NativeView by way of InstallClip. + virtual void UninstallClip() = 0; + + // Shows the gfx::NativeView at the specified position (relative to the parent + // native view). + virtual void ShowWidget(int x, int y, int w, int h) = 0; + + // Hides the gfx::NativeView. NOTE: this may be invoked when the native view + // is already hidden. + virtual void HideWidget() = 0; + + // Sets focus to the gfx::NativeView. + virtual void SetFocus() = 0; + + // Creates a platform-specific instance of an object implementing this + // interface. + static NativeViewHostWrapper* CreateWrapper(NativeViewHost* host); +}; + +} // namespace views + +#endif // VIEWS_CONTROLS_NATIVE_NATIVE_VIEW_HOST_WRAPPER_H_ diff --git a/views/controls/native_control.cc b/views/controls/native_control.cc index d5293b2..cbb375a 100644 --- a/views/controls/native_control.cc +++ b/views/controls/native_control.cc @@ -15,7 +15,7 @@ #include "base/win_util.h" #include "views/background.h" #include "views/border.h" -#include "views/controls/hwnd_view.h" +#include "views/controls/native/native_view_host.h" #include "views/focus/focus_manager.h" #include "views/widget/widget.h" #include "base/gfx/native_theme.h" @@ -182,7 +182,7 @@ NativeControl::~NativeControl() { void NativeControl::ValidateNativeControl() { if (hwnd_view_ == NULL) { - hwnd_view_ = new HWNDView(); + hwnd_view_ = new NativeViewHost; AddChildView(hwnd_view_); } @@ -202,7 +202,7 @@ void NativeControl::ValidateNativeControl() { void NativeControl::ViewHierarchyChanged(bool is_add, View *parent, View *child) { - if (is_add && GetWidget()) { + if (is_add && child == this && GetWidget()) { ValidateNativeControl(); Layout(); } diff --git a/views/controls/native_control.h b/views/controls/native_control.h index 22c0fa4..f6f9752 100644 --- a/views/controls/native_control.h +++ b/views/controls/native_control.h @@ -15,7 +15,7 @@ class CPoint; namespace views { -class HWNDView; +class NativeViewHost; class NativeControlContainer; //////////////////////////////////////////////////////////////////////////////// @@ -111,7 +111,7 @@ class NativeControl : public View { // This variable is protected to provide subclassers direct access. However // subclassers should always check for NULL since this variable is only // initialized in ValidateNativeControl(). - HWNDView* hwnd_view_; + NativeViewHost* hwnd_view_; // Fixed size information. -1 for a size means no fixed size. int fixed_width_; diff --git a/views/controls/native_control_gtk.cc b/views/controls/native_control_gtk.cc index 11781f6..cae4476 100644 --- a/views/controls/native_control_gtk.cc +++ b/views/controls/native_control_gtk.cc @@ -10,7 +10,7 @@ namespace views { -NativeControlGtk::NativeControlGtk() : NativeViewHostGtk() { +NativeControlGtk::NativeControlGtk() { } NativeControlGtk::~NativeControlGtk() { @@ -38,7 +38,7 @@ void NativeControlGtk::ViewHierarchyChanged(bool is_add, View* parent, CreateNativeControl(); // Call the base class to hide the view if we're being removed. - NativeViewHostGtk::ViewHierarchyChanged(is_add, parent, child); + NativeViewHost::ViewHierarchyChanged(is_add, parent, child); } void NativeControlGtk::VisibilityChanged(View* starting_from, bool is_visible) { diff --git a/views/controls/native_control_gtk.h b/views/controls/native_control_gtk.h index fb766c7..2f0ffab 100644 --- a/views/controls/native_control_gtk.h +++ b/views/controls/native_control_gtk.h @@ -5,12 +5,12 @@ #ifndef VIEWS_CONTROLS_NATIVE_CONTROL_GTK_H_ #define VIEWS_CONTROLS_NATIVE_CONTROL_GTK_H_ -#include "views/controls/native_view_host_gtk.h" +#include "views/controls/native/native_view_host.h" namespace views { // A View that hosts a native control. -class NativeControlGtk : public NativeViewHostGtk { +class NativeControlGtk : public NativeViewHost { public: NativeControlGtk(); virtual ~NativeControlGtk(); diff --git a/views/controls/native_control_win.cc b/views/controls/native_control_win.cc index c1ddadf..eb188af 100644 --- a/views/controls/native_control_win.cc +++ b/views/controls/native_control_win.cc @@ -23,11 +23,11 @@ WNDPROC NativeControlWin::original_wndproc_ = NULL; //////////////////////////////////////////////////////////////////////////////// // NativeControlWin, public: -NativeControlWin::NativeControlWin() : HWNDView() { +NativeControlWin::NativeControlWin() { } NativeControlWin::~NativeControlWin() { - HWND hwnd = GetHWND(); + HWND hwnd = native_view(); if (hwnd) { // Destroy the hwnd if it still exists. Otherwise we won't have shut things // down correctly, leading to leaking and crashing if another message @@ -47,7 +47,7 @@ bool NativeControlWin::ProcessMessage(UINT message, WPARAM w_param, case WM_CTLCOLORBTN: case WM_CTLCOLORSTATIC: *result = GetControlColor(message, reinterpret_cast<HDC>(w_param), - GetHWND()); + native_view()); return true; } return false; @@ -59,37 +59,37 @@ bool NativeControlWin::ProcessMessage(UINT message, WPARAM w_param, void NativeControlWin::SetEnabled(bool enabled) { if (IsEnabled() != enabled) { View::SetEnabled(enabled); - if (GetHWND()) - EnableWindow(GetHWND(), IsEnabled()); + if (native_view()) + EnableWindow(native_view(), IsEnabled()); } } void NativeControlWin::ViewHierarchyChanged(bool is_add, View* parent, View* child) { + // Call the base class to hide the view if we're being removed. + NativeViewHost::ViewHierarchyChanged(is_add, parent, child); + // Create the HWND when we're added to a valid Widget. Many controls need a // parent HWND to function properly. - if (is_add && GetWidget() && !GetHWND()) + if (is_add && GetWidget() && !native_view()) CreateNativeControl(); - - // Call the base class to hide the view if we're being removed. - HWNDView::ViewHierarchyChanged(is_add, parent, child); } void NativeControlWin::VisibilityChanged(View* starting_from, bool is_visible) { if (!is_visible) { // We destroy the child control HWND when we become invisible because of the // performance cost of maintaining many HWNDs. - HWND hwnd = GetHWND(); + HWND hwnd = native_view(); Detach(); DestroyWindow(hwnd); - } else if (!GetHWND()) { + } else if (!native_view()) { CreateNativeControl(); } } void NativeControlWin::Focus() { - DCHECK(GetHWND()); - SetFocus(GetHWND()); + DCHECK(native_view()); + SetFocus(native_view()); } //////////////////////////////////////////////////////////////////////////////// @@ -123,13 +123,13 @@ void NativeControlWin::NativeControlCreated(HWND native_control) { SetProp(native_control, kNativeControlOriginalWndProcKey, original_wndproc_); Attach(native_control); - // GetHWND() is now valid. + // native_view() is now valid. // Update the newly created HWND with any resident enabled state. - EnableWindow(GetHWND(), IsEnabled()); + EnableWindow(native_view(), IsEnabled()); // This message ensures that the focus border is shown. - SendMessage(GetHWND(), WM_CHANGEUISTATE, + SendMessage(native_view(), WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0); } diff --git a/views/controls/native_control_win.h b/views/controls/native_control_win.h index 6f9923f..eee4ded8 100644 --- a/views/controls/native_control_win.h +++ b/views/controls/native_control_win.h @@ -5,12 +5,12 @@ #ifndef VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_ #define VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_ -#include "views/controls/hwnd_view.h" +#include "views/controls/native/native_view_host.h" namespace views { // A View that hosts a native Windows control. -class NativeControlWin : public HWNDView { +class NativeControlWin : public NativeViewHost { public: static const wchar_t* kNativeControlWinKey; @@ -60,7 +60,7 @@ class NativeControlWin : public HWNDView { // MUST be called by the subclass implementation of |CreateNativeControl| // immediately after creating the control HWND, otherwise it won't be attached - // to the HWNDView and will be effectively orphaned. + // to the NativeViewHost and will be effectively orphaned. virtual void NativeControlCreated(HWND native_control); // Returns additional extended style flags. When subclasses call diff --git a/views/controls/native_view_host.cc b/views/controls/native_view_host.cc deleted file mode 100644 index 0e00aee..0000000 --- a/views/controls/native_view_host.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2009 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/controls/native_view_host.h" - -#include "views/widget/widget.h" -#include "base/logging.h" - -namespace views { - -NativeViewHost::NativeViewHost() - : native_view_(NULL), - installed_clip_(false), - fast_resize_(false), - focus_view_(NULL) { - // The native widget is placed relative to the root. As such, we need to - // know when the position of any ancestor changes, or our visibility relative - // to other views changed as it'll effect our position relative to the root. - SetNotifyWhenVisibleBoundsInRootChanges(true); -} - -NativeViewHost::~NativeViewHost() { -} - -gfx::Size NativeViewHost::GetPreferredSize() { - return preferred_size_; -} - -void NativeViewHost::SetPreferredSize(const gfx::Size& size) { - preferred_size_ = size; - PreferredSizeChanged(); -} - -void NativeViewHost::Layout() { - if (!native_view_) - return; - - // Since widgets know nothing about the View hierarchy (they are direct - // children of the Widget that hosts our View hierarchy) they need to be - // positioned in the coordinate system of the Widget, not the current - // view. - gfx::Point top_left; - ConvertPointToWidget(this, &top_left); - - gfx::Rect vis_bounds = GetVisibleBounds(); - bool visible = !vis_bounds.IsEmpty(); - - if (visible && !fast_resize_) { - if (vis_bounds.size() != size()) { - // Only a portion of the Widget is really visible. - int x = vis_bounds.x(); - int y = vis_bounds.y(); - InstallClip(x, y, vis_bounds.width(), vis_bounds.height()); - installed_clip_ = true; - } else if (installed_clip_) { - // The whole widget is visible but we installed a clip on the widget, - // uninstall it. - UninstallClip(); - installed_clip_ = false; - } - } - - if (visible) { - ShowWidget(top_left.x(), top_left.y(), width(), height()); - } else { - HideWidget(); - } -} - -void NativeViewHost::VisibilityChanged(View* starting_from, bool is_visible) { - Layout(); -} - -void NativeViewHost::VisibleBoundsInRootChanged() { - Layout(); -} - -} // namespace views diff --git a/views/controls/native_view_host_gtk.cc b/views/controls/native_view_host_gtk.cc deleted file mode 100644 index 3f3952d..0000000 --- a/views/controls/native_view_host_gtk.cc +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) 2009 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/controls/native_view_host_gtk.h" - -#include <gtk/gtk.h> - -#include "base/logging.h" -#include "views/widget/widget_gtk.h" - -namespace views { - -NativeViewHostGtk::NativeViewHostGtk() - : NativeViewHost(), - destroy_signal_id_(0) { -} - -NativeViewHostGtk::~NativeViewHostGtk() { -} - -// static -View* NativeViewHostGtk::GetViewForNative(GtkWidget* widget) { - gpointer user_data = g_object_get_data(G_OBJECT(widget), "chrome-view"); - return static_cast<View*>(user_data); -} - -// static -void NativeViewHostGtk::SetViewForNative(GtkWidget* widget, View* view) { - g_object_set_data(G_OBJECT(widget), "chrome-view", view); -} - -void NativeViewHostGtk::Attach(GtkWidget* widget) { - DCHECK(native_view() == NULL); - DCHECK(widget); - - // Adds a mapping between the GtkWidget and us. - SetViewForNative(widget, this); - - destroy_signal_id_ = g_signal_connect(G_OBJECT(widget), "destroy", - G_CALLBACK(CallDestroy), NULL); - - set_native_view(widget); - - // First hide the new window. We don't want anything to draw (like sub-hwnd - // borders), when we change the parent below. - gtk_widget_hide(widget); - - // Set the parent. - static_cast<WidgetGtk*>(GetWidget())->AddChild(widget); - Layout(); - - // TODO: figure out focus. - // FocusManager::InstallFocusSubclass( - // hwnd, associated_focus_view()_ ? associated_focus_view() : this); -} - -void NativeViewHostGtk::Detach() { - DCHECK(native_view()); - - g_signal_handler_disconnect(G_OBJECT(native_view()), destroy_signal_id_); - destroy_signal_id_ = 0; - - // TODO: focus. - // FocusManager::UninstallFocusSubclass(native_view()); - set_native_view(NULL); - set_installed_clip(false); -} - -void NativeViewHostGtk::ViewHierarchyChanged(bool is_add, View* parent, - View* child) { - if (!native_view()) - return; - - WidgetGtk* parent_widget = static_cast<WidgetGtk*>(GetWidget()); - if (is_add && parent_widget) { - GtkWidget* widget_parent = gtk_widget_get_parent(native_view()); - GtkWidget* parent_widget_widget = parent_widget->child_widget_parent(); - if (widget_parent != parent_widget_widget) { - g_object_ref(native_view()); - if (widget_parent) - gtk_container_remove(GTK_CONTAINER(widget_parent), native_view()); - gtk_container_add(GTK_CONTAINER(parent_widget_widget), native_view()); - g_object_unref(native_view()); - } - if (IsVisibleInRootView()) - gtk_widget_show(native_view()); - else - gtk_widget_hide(native_view()); - Layout(); - } else if (!is_add) { - gtk_widget_hide(native_view()); - if (parent_widget) { - gtk_container_remove(GTK_CONTAINER(parent_widget->child_widget_parent()), - native_view()); - } - } -} - -void NativeViewHostGtk::Focus() { - NOTIMPLEMENTED(); -} - -void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) { - DCHECK(w > 0 && h > 0); - - bool has_window = (GTK_WIDGET_FLAGS(native_view()) & GTK_NO_WINDOW) == 0; - if (!has_window) { - // Clip is only supported on GtkWidgets that have windows. If this becomes - // an issue (as it may be in the options dialog) we'll need to wrap the - // widget in a GtkFixed with a window. We have to do this as not all widgets - // support turning on GTK_NO_WINDOW (for example, buttons don't appear to - // draw anything when they have a window). - NOTREACHED(); - return; - } - DCHECK(has_window); - // Unset the current region. - gdk_window_shape_combine_region(native_view()->window, NULL, 0, 0); - - // Set a new region. - // TODO: using shapes is a bit expensive. Should investigated if there is - // another more efficient way to accomplish this. - GdkRectangle clip_rect = { x, y, w, h }; - GdkRegion* clip_region = gdk_region_rectangle(&clip_rect); - gdk_window_shape_combine_region(native_view()->window, clip_region, x, y); - gdk_region_destroy(clip_region); -} - -void NativeViewHostGtk::UninstallClip() { - gtk_widget_shape_combine_mask(native_view(), NULL, 0, 0); -} - -void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) { - WidgetGtk* parent = static_cast<WidgetGtk*>(GetWidget()); - parent->PositionChild(native_view(), x, y, w, h); - gtk_widget_show(native_view()); -} - -void NativeViewHostGtk::HideWidget() { - gtk_widget_hide(native_view()); -} - -void NativeViewHostGtk::OnDestroy() { - set_native_view(NULL); -} - -// static -void NativeViewHostGtk::CallDestroy(GtkObject* object) { - View* view = GetViewForNative(GTK_WIDGET(object)); - if (!view) - return; - - return static_cast<NativeViewHostGtk*>(view)->OnDestroy(); -} - -} // namespace views diff --git a/views/controls/scrollbar/native_scroll_bar.cc b/views/controls/scrollbar/native_scroll_bar.cc index 52ddd91..15cfa8f 100644 --- a/views/controls/scrollbar/native_scroll_bar.cc +++ b/views/controls/scrollbar/native_scroll_bar.cc @@ -13,7 +13,7 @@ #include <string> #include "base/message_loop.h" -#include "views/controls/hwnd_view.h" +#include "views/controls/native/native_view_host.h" #include "views/widget/widget.h" namespace views { @@ -231,7 +231,7 @@ void NativeScrollBar::ViewHierarchyChanged(bool is_add, View *parent, View *child) { Widget* widget; if (is_add && (widget = GetWidget()) && !sb_view_) { - sb_view_ = new HWNDView(); + sb_view_ = new NativeViewHost; AddChildView(sb_view_); sb_container_ = new ScrollBarContainer(this); sb_view_->Attach(*sb_container_); diff --git a/views/controls/scrollbar/native_scroll_bar.h b/views/controls/scrollbar/native_scroll_bar.h index 2747bce..85a0453 100644 --- a/views/controls/scrollbar/native_scroll_bar.h +++ b/views/controls/scrollbar/native_scroll_bar.h @@ -11,7 +11,7 @@ namespace views { -class HWNDView; +class NativeViewHost; class ScrollBarContainer; ///////////////////////////////////////////////////////////////////////////// @@ -53,7 +53,7 @@ class NativeScrollBar : public ScrollBar { #if defined(OS_WIN) // The sb_view_ takes care of keeping sb_container in sync with the // view hierarchy - HWNDView* sb_view_; + NativeViewHost* sb_view_; #endif // defined(OS_WIN) // sb_container_ is a custom hwnd that we use to wrap the real diff --git a/views/controls/separator.cc b/views/controls/separator.cc index f331ce8..af0962f 100644 --- a/views/controls/separator.cc +++ b/views/controls/separator.cc @@ -4,7 +4,7 @@ #include "views/controls/separator.h" -#include "views/controls/hwnd_view.h" +#include "views/controls/native/native_view_host.h" namespace views { diff --git a/views/controls/table/table_view.cc b/views/controls/table/table_view.cc index 5650f9f..d114b2d6 100644 --- a/views/controls/table/table_view.cc +++ b/views/controls/table/table_view.cc @@ -21,7 +21,7 @@ #include "skia/ext/skia_utils_win.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColorFilter.h" -#include "views/controls/hwnd_view.h" +#include "views/controls/native/native_view_host.h" namespace views { diff --git a/views/controls/textfield/native_textfield_win.cc b/views/controls/textfield/native_textfield_win.cc index 33fc104..401116c 100644 --- a/views/controls/textfield/native_textfield_win.cc +++ b/views/controls/textfield/native_textfield_win.cc @@ -12,8 +12,8 @@ #include "base/win_util.h" #include "grit/app_strings.h" #include "skia/ext/skia_utils_win.h" -#include "views/controls/hwnd_view.h" #include "views/controls/menu/menu_win.h" +#include "views/controls/native/native_view_host.h" #include "views/controls/textfield/native_textfield_win.h" #include "views/controls/textfield/textfield.h" #include "views/focus/focus_util_win.h" @@ -111,9 +111,9 @@ NativeTextfieldWin::NativeTextfieldWin(Textfield* textfield) IDS_APP_SELECT_ALL, l10n_util::GetString(IDS_APP_SELECT_ALL)); - container_view_ = new HWNDView; + container_view_ = new NativeViewHost; textfield_->AddChildView(container_view_); - container_view_->SetAssociatedFocusView(textfield_); + container_view_->set_focus_view(textfield_); container_view_->Attach(m_hWnd); } diff --git a/views/controls/textfield/native_textfield_win.h b/views/controls/textfield/native_textfield_win.h index 6e8a12f..194614a 100644 --- a/views/controls/textfield/native_textfield_win.h +++ b/views/controls/textfield/native_textfield_win.h @@ -17,7 +17,7 @@ namespace views { -class HWNDView; +class NativeViewHost; class Textfield; static const int kDefaultEditStyle = WS_CHILD | WS_VISIBLE; @@ -192,7 +192,7 @@ class NativeTextfieldWin int ime_composition_length_; // TODO(beng): remove this when we are a subclass of NativeControlWin. - HWNDView* container_view_; + NativeViewHost* container_view_; COLORREF bg_color_; diff --git a/views/controls/textfield/textfield.cc b/views/controls/textfield/textfield.cc index b7d64e6..38f2a80 100644 --- a/views/controls/textfield/textfield.cc +++ b/views/controls/textfield/textfield.cc @@ -162,6 +162,7 @@ bool Textfield::IsKeystrokeEnter(const Keystroke& key) { #if defined(OS_WIN) return key.key == VK_RETURN; #else + // TODO(port): figure out VK_constants NOTIMPLEMENTED(); return false; #endif @@ -172,6 +173,7 @@ bool Textfield::IsKeystrokeEscape(const Keystroke& key) { #if defined(OS_WIN) return key.key == VK_ESCAPE; #else + // TODO(port): figure out VK_constants NOTIMPLEMENTED(); return false; #endif diff --git a/views/focus/focus_manager.h b/views/focus/focus_manager.h index 92c5480..133c027 100644 --- a/views/focus/focus_manager.h +++ b/views/focus/focus_manager.h @@ -29,7 +29,7 @@ // focus. This is used in NativeControl for example, where a View wraps an // actual native window. // This is already done for you if you subclass the NativeControl class or if -// you use the HWNDView class. +// you use the NativeViewHost class. // // When creating a top window, if it derives from WidgetWin, the // |has_own_focus_manager| of the Init method lets you specify whether that diff --git a/views/view_unittest.cc b/views/view_unittest.cc index 2ccf8b5..cd0184e 100644 --- a/views/view_unittest.cc +++ b/views/view_unittest.cc @@ -713,7 +713,7 @@ class ButtonTest : public NativeButton { } HWND GetHWND() { - return static_cast<NativeButtonWin*>(native_wrapper_)->GetHWND(); + return static_cast<NativeButtonWin*>(native_wrapper_)->native_view(); } }; @@ -723,7 +723,7 @@ class CheckboxTest : public Checkbox { } HWND GetHWND() { - return static_cast<NativeCheckboxWin*>(native_wrapper_)->GetHWND(); + return static_cast<NativeCheckboxWin*>(native_wrapper_)->native_view(); } }; diff --git a/views/views.gyp b/views/views.gyp index 5633572..69ed7a1 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -87,8 +87,6 @@ 'controls/button/text_button.h', 'controls/combo_box.cc', 'controls/combo_box.h', - 'controls/hwnd_view.cc', - 'controls/hwnd_view.h', 'controls/image_view.cc', 'controls/image_view.h', 'controls/label.cc', @@ -113,10 +111,13 @@ 'controls/native_control_gtk.h', 'controls/native_control_win.cc', 'controls/native_control_win.h', - 'controls/native_view_host.cc', - 'controls/native_view_host.h', - 'controls/native_view_host_gtk.cc', - 'controls/native_view_host_gtk.h', + 'controls/native/native_view_host.cc', + 'controls/native/native_view_host.h', + 'controls/native/native_view_host_gtk.cc', + 'controls/native/native_view_host_gtk.h', + 'controls/native/native_view_host_win.cc', + 'controls/native/native_view_host_win.h', + 'controls/native/native_view_host_wrapper.h', 'controls/scroll_view.cc', 'controls/scroll_view.h', 'controls/scrollbar/bitmap_scroll_bar.cc', |