summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-05 20:04:04 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-05 20:04:04 +0000
commit179caa6698de49c762ace7ecc8728d642222f8b9 (patch)
tree718fef5e6b13967dddc9bfade97224622924525b
parentc88a70fe5a69daf5d3d6e0599ed273d160b55c41 (diff)
downloadchromium_src-179caa6698de49c762ace7ecc8728d642222f8b9.zip
chromium_src-179caa6698de49c762ace7ecc8728d642222f8b9.tar.gz
chromium_src-179caa6698de49c762ace7ecc8728d642222f8b9.tar.bz2
Refactors HWNDView into two classes for reuse on GTK.
BUG=none TEST=none Review URL: http://codereview.chromium.org/108025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15327 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/views/controls/hwnd_view.cc207
-rw-r--r--chrome/views/controls/hwnd_view.h58
-rw-r--r--chrome/views/controls/native_view_host.cc74
-rw-r--r--chrome/views/controls/native_view_host.h103
-rw-r--r--chrome/views/views.vcproj8
6 files changed, 278 insertions, 174 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 8804cf7..5fe5813 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -2879,6 +2879,8 @@
'views/controls/native_control.h',
'views/controls/native_control_win.cc',
'views/controls/native_control_win.h',
+ 'views/controls/native_view_host.cc',
+ 'views/controls/native_view_host.h',
'views/controls/scroll_view.cc',
'views/controls/scroll_view.h',
'views/controls/scrollbar/bitmap_scroll_bar.cc',
diff --git a/chrome/views/controls/hwnd_view.cc b/chrome/views/controls/hwnd_view.cc
index bc8a7eb..b6ff61b 100644
--- a/chrome/views/controls/hwnd_view.cc
+++ b/chrome/views/controls/hwnd_view.cc
@@ -7,7 +7,6 @@
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/win_util.h"
#include "chrome/views/focus/focus_manager.h"
-#include "chrome/views/controls/scroll_view.h"
#include "chrome/views/widget/widget.h"
#include "base/logging.h"
@@ -15,173 +14,125 @@ namespace views {
static const char kViewClassName[] = "chrome/views/HWNDView";
-HWNDView::HWNDView() :
- hwnd_(0),
- installed_clip_(false),
- fast_resize_(false),
- focus_view_(NULL) {
- // HWNDs are 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);
+HWNDView::HWNDView() {
}
HWNDView::~HWNDView() {
}
void HWNDView::Attach(HWND hwnd) {
- DCHECK(hwnd_ == NULL);
+ DCHECK(native_view() == NULL);
DCHECK(hwnd) << "Impossible detatched tab case; See crbug.com/6316";
- hwnd_ = hwnd;
+ 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);
+ ShowWindow(hwnd, SW_HIDE);
// Need to set the HWND's parent before changing its size to avoid flashing.
- ::SetParent(hwnd_, GetWidget()->GetNativeView());
+ ::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_, focus_view_ ? focus_view_ : this);
+ FocusManager::InstallFocusSubclass(
+ hwnd, associated_focus_view() ? associated_focus_view() : this);
}
void HWNDView::Detach() {
- DCHECK(hwnd_);
- FocusManager::UninstallFocusSubclass(hwnd_);
- hwnd_ = NULL;
- installed_clip_ = false;
+ DCHECK(native_view());
+ FocusManager::UninstallFocusSubclass(native_view());
+ set_native_view(NULL);
+ set_installed_clip(false);
}
-void HWNDView::SetAssociatedFocusView(View* view) {
- DCHECK(!::IsWindow(hwnd_));
- focus_view_ = view;
+void HWNDView::Paint(ChromeCanvas* 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());
}
-HWND HWNDView::GetHWND() const {
- return hwnd_;
+std::string HWNDView::GetClassName() const {
+ return kViewClassName;
}
-void HWNDView::Layout() {
- if (!hwnd_)
+void HWNDView::ViewHierarchyChanged(bool is_add, View *parent, View *child) {
+ if (!native_view())
return;
- // Since HWNDs 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 HWND is really visible.
- int x = vis_bounds.x();
- int y = vis_bounds.y();
- HRGN clip_region = CreateRectRgn(x, y, x + vis_bounds.width(),
- y + vis_bounds.height());
- // NOTE: SetWindowRgn owns the region (as well as the deleting the
- // current region), as such we don't delete the old region.
- SetWindowRgn(hwnd_, clip_region, FALSE);
- installed_clip_ = true;
- } else if (installed_clip_) {
- // The whole HWND is visible but we installed a clip on the HWND,
- // uninstall it.
- SetWindowRgn(hwnd_, 0, FALSE);
- installed_clip_ = false;
- }
- }
-
- if (visible) {
- UINT swp_flags;
- 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(hwnd_))
- swp_flags = (swp_flags | SWP_SHOWWINDOW) & ~SWP_NOREDRAW;
-
- if (fast_resize_) {
- // In a fast resize, we move the window and clip it with SetWindowRgn.
- CRect rect;
- GetWindowRect(hwnd_, &rect);
- ::SetWindowPos(hwnd_, 0, top_left.x(), top_left.y(), rect.Width(),
- rect.Height(), swp_flags);
-
- HRGN clip_region = CreateRectRgn(0, 0, width(), height());
- SetWindowRgn(hwnd_, clip_region, FALSE);
- installed_clip_ = true;
- } else {
- ::SetWindowPos(hwnd_, 0, top_left.x(), top_left.y(), width(), height(),
- swp_flags);
- }
- } else if (::IsWindowVisible(hwnd_)) {
- // The window is currently visible, but its clipped by another view. Hide
- // it.
- ::SetWindowPos(hwnd_, 0, 0, 0, 0, 0,
- SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
- SWP_NOREDRAW | SWP_NOOWNERZORDER);
+ 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::VisibilityChanged(View* starting_from, bool is_visible) {
- Layout();
+void HWNDView::Focus() {
+ ::SetFocus(native_view());
}
-gfx::Size HWNDView::GetPreferredSize() {
- return preferred_size_;
+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::ViewHierarchyChanged(bool is_add, View *parent, View *child) {
- if (hwnd_) {
- Widget* widget = GetWidget();
- if (is_add && widget) {
- HWND parent_hwnd = ::GetParent(hwnd_);
- HWND widget_hwnd = widget->GetNativeView();
- if (parent_hwnd != widget_hwnd) {
- ::SetParent(hwnd_, widget_hwnd);
- }
- if (IsVisibleInRootView())
- ::ShowWindow(hwnd_, SW_SHOW);
- else
- ::ShowWindow(hwnd_, SW_HIDE);
- Layout();
- } else if (!is_add) {
- ::ShowWindow(hwnd_, SW_HIDE);
- ::SetParent(hwnd_, NULL);
- }
- }
+void HWNDView::UninstallClip() {
+ SetWindowRgn(native_view(), 0, FALSE);
}
-void HWNDView::VisibleBoundsInRootChanged() {
- Layout();
+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.
+ CRect rect;
+ GetWindowRect(native_view(), &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::Focus() {
- ::SetFocus(hwnd_);
-}
+void HWNDView::HideWidget() {
+ if (!::IsWindowVisible(native_view()))
+ return; // Currently not visible, nothing to do.
-void HWNDView::Paint(ChromeCanvas* 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;
+ // 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/chrome/views/controls/hwnd_view.h b/chrome/views/controls/hwnd_view.h
index 4667212..fc08b5d5 100644
--- a/chrome/views/controls/hwnd_view.h
+++ b/chrome/views/controls/hwnd_view.h
@@ -7,7 +7,7 @@
#include <string>
-#include "chrome/views/view.h"
+#include "chrome/views/controls/native_view_host.h"
namespace views {
@@ -21,15 +21,12 @@ namespace views {
// within thew View hierarchy and benefit from the sizing/layout.
//
/////////////////////////////////////////////////////////////////////////////
-class HWNDView : public View {
+// TODO: Rename this to NativeViewHostWin.
+class HWNDView : public NativeViewHost {
public:
HWNDView();
virtual ~HWNDView();
- virtual gfx::Size GetPreferredSize();
-
- void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }
-
// 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.
@@ -41,58 +38,27 @@ class HWNDView : public View {
// Detach the attached window handle. It will no longer be updated
void Detach();
- virtual void VisibilityChanged(View* starting_from, bool is_visible);
-
- HWND GetHWND() const;
-
- virtual void Layout();
+ // TODO(sky): convert this to native_view().
+ HWND GetHWND() const { return native_view(); }
virtual void Paint(ChromeCanvas* canvas);
// Overridden from View.
virtual std::string GetClassName() const;
- // A HWNDView 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
- // HWNDView directly wraps a native window as is, the associated view is this
- // View. In other cases where the HWNDView is part of another view (such as
- // TextField), the actual View is not the HWNDView and this method must be
- // called to set that.
- // This method must be called before Attach().
- void SetAssociatedFocusView(View* view);
-
- void set_fast_resize(bool fast_resize) { fast_resize_ = fast_resize; }
-
protected:
virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
- // Notification that our visible bounds relative to the root has changed.
- // This updates the bounds of the HWND.
- virtual void VisibleBoundsInRootChanged();
-
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:
- // The hosted window handle.
- HWND hwnd_;
-
- // 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.
- bool fast_resize_;
-
- // The view that should be given focus when this HWNDView is focused.
- View* focus_view_;
+ DISALLOW_COPY_AND_ASSIGN(HWNDView);
};
} // namespace views
diff --git a/chrome/views/controls/native_view_host.cc b/chrome/views/controls/native_view_host.cc
new file mode 100644
index 0000000..525aa497
--- /dev/null
+++ b/chrome/views/controls/native_view_host.cc
@@ -0,0 +1,74 @@
+// 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 "chrome/views/controls/native_view_host.h"
+
+#include "chrome/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::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/chrome/views/controls/native_view_host.h b/chrome/views/controls/native_view_host.h
new file mode 100644
index 0000000..e1e123f
--- /dev/null
+++ b/chrome/views/controls/native_view_host.h
@@ -0,0 +1,103 @@
+// 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 CHROME_VIEWS_CONTROLS_NATIVE_VIEW_HOST_H_
+#define CHROME_VIEWS_CONTROLS_NATIVE_VIEW_HOST_H_
+
+#include <string>
+
+#include "chrome/views/view.h"
+
+#include "base/gfx/native_widget_types.h"
+
+namespace views {
+
+// Base class for embedding native widgets in a view.
+class NativeViewHost : public View {
+ public:
+ NativeViewHost();
+ virtual ~NativeViewHost();
+
+ void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }
+
+ // Returns the preferred size set via set_preferred_size.
+ virtual gfx::Size GetPreferredSize();
+
+ // Overriden to invoke Layout.
+ virtual void VisibilityChanged(View* starting_from, bool is_visible);
+
+ // Invokes any of InstallClip, UninstallClip, ShowWidget or HideWidget
+ // depending upon what portion of the widget is view in the parent.
+ virtual void Layout();
+
+ // 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
+ // NativeViewHost directly wraps a native window as is, the associated view
+ // is this View. In other cases where the NativeViewHost is part of another
+ // 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_fast_resize(bool fast_resize) { fast_resize_ = fast_resize; }
+ bool fast_resize() const { return fast_resize_; }
+
+ // The embedded 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; }
+
+ // 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;
+
+ void set_installed_clip(bool installed_clip) {
+ installed_clip_ = installed_clip;
+ }
+ bool installed_clip() const { return installed_clip_; }
+
+ private:
+ gfx::NativeView native_view_;
+
+ // 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.
+ bool fast_resize_;
+
+ // The view that should be given focus when this NativeViewHost is focused.
+ View* focus_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewHost);
+};
+
+} // namespace views
+
+#endif // CHROME_VIEWS_CONTROLS_NATIVE_VIEW_HOST_H_
diff --git a/chrome/views/views.vcproj b/chrome/views/views.vcproj
index 0aba6df..8e5d2fe 100644
--- a/chrome/views/views.vcproj
+++ b/chrome/views/views.vcproj
@@ -511,6 +511,14 @@
>
</File>
<File
+ RelativePath=".\controls\native_view_host.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\controls\native_view_host.h"
+ >
+ </File>
+ <File
RelativePath=".\controls\scroll_view.cc"
>
</File>