summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'ui/gfx')
-rw-r--r--ui/gfx/canvas_paint_win.h2
-rw-r--r--ui/gfx/display.cc2
-rw-r--r--ui/gfx/font_smoothing_win.cc6
-rw-r--r--ui/gfx/platform_font_win.cc6
-rw-r--r--ui/gfx/render_text.cc6
-rw-r--r--ui/gfx/render_text_linux.cc10
-rw-r--r--ui/gfx/render_text_win.cc12
-rw-r--r--ui/gfx/screen_win.cc2
-rw-r--r--ui/gfx/switches.cc5
-rw-r--r--ui/gfx/switches.h3
-rw-r--r--ui/gfx/sys_color_change_listener.cc8
-rw-r--r--ui/gfx/utf16_indexing.cc55
-rw-r--r--ui/gfx/utf16_indexing.h49
-rw-r--r--ui/gfx/utf16_indexing_unittest.cc32
-rw-r--r--ui/gfx/win/dpi.cc (renamed from ui/gfx/dpi_win.cc)6
-rw-r--r--ui/gfx/win/dpi.h (renamed from ui/gfx/dpi_win.h)0
-rw-r--r--ui/gfx/win/hwnd_util.cc214
-rw-r--r--ui/gfx/win/hwnd_util.h54
-rw-r--r--ui/gfx/win/scoped_set_map_mode.h40
-rw-r--r--ui/gfx/win/singleton_hwnd.cc55
-rw-r--r--ui/gfx/win/singleton_hwnd.h61
-rw-r--r--ui/gfx/win/window_impl.cc272
-rw-r--r--ui/gfx/win/window_impl.h123
23 files changed, 989 insertions, 34 deletions
diff --git a/ui/gfx/canvas_paint_win.h b/ui/gfx/canvas_paint_win.h
index ed31a6e..c5d3aee 100644
--- a/ui/gfx/canvas_paint_win.h
+++ b/ui/gfx/canvas_paint_win.h
@@ -7,8 +7,8 @@
#include "skia/ext/platform_canvas.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/dpi_win.h"
#include "ui/gfx/size.h"
+#include "ui/gfx/win/dpi.h"
namespace gfx {
diff --git a/ui/gfx/display.cc b/ui/gfx/display.cc
index 02d97a9..d3f0745 100644
--- a/ui/gfx/display.cc
+++ b/ui/gfx/display.cc
@@ -8,11 +8,11 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
-#include "ui/base/ui_base_switches.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/point_f.h"
#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/switches.h"
namespace gfx {
namespace {
diff --git a/ui/gfx/font_smoothing_win.cc b/ui/gfx/font_smoothing_win.cc
index a4be729..b181fb5 100644
--- a/ui/gfx/font_smoothing_win.cc
+++ b/ui/gfx/font_smoothing_win.cc
@@ -5,13 +5,13 @@
#include "ui/gfx/font_smoothing_win.h"
#include "base/memory/singleton.h"
-#include "ui/base/win/singleton_hwnd.h"
+#include "ui/gfx/win/singleton_hwnd.h"
namespace {
// Helper class to cache font smoothing settings and listen for notifications
// to re-query them from the system.
-class CachedFontSmoothingSettings : public ui::SingletonHwnd::Observer {
+class CachedFontSmoothingSettings : public gfx::SingletonHwnd::Observer {
public:
static CachedFontSmoothingSettings* GetInstance();
@@ -66,7 +66,7 @@ void CachedFontSmoothingSettings::GetFontSmoothingSettings(
need_to_query_settings_ = false;
}
if (!observer_added_) {
- ui::SingletonHwnd::GetInstance()->AddObserver(this);
+ gfx::SingletonHwnd::GetInstance()->AddObserver(this);
observer_added_ = true;
}
*smoothing_enabled = smoothing_enabled_;
diff --git a/ui/gfx/platform_font_win.cc b/ui/gfx/platform_font_win.cc
index 4a792f6..2d4c006 100644
--- a/ui/gfx/platform_font_win.cc
+++ b/ui/gfx/platform_font_win.cc
@@ -17,9 +17,9 @@
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "base/win/win_util.h"
-#include "ui/base/win/scoped_set_map_mode.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
+#include "ui/gfx/win/scoped_set_map_mode.h"
namespace {
@@ -229,7 +229,7 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) {
{
base::win::ScopedGetDC screen_dc(NULL);
base::win::ScopedSelectObject scoped_font(screen_dc, font);
- ui::ScopedSetMapMode mode(screen_dc, MM_TEXT);
+ gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT);
GetTextMetrics(screen_dc, &font_metrics);
}
@@ -284,7 +284,7 @@ int PlatformFontWin::HFontRef::GetDluBaseX() {
base::win::ScopedGetDC screen_dc(NULL);
base::win::ScopedSelectObject font(screen_dc, hfont_);
- ui::ScopedSetMapMode mode(screen_dc, MM_TEXT);
+ gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT);
// Yes, this is how Microsoft recommends calculating the dialog unit
// conversions. See: http://support.microsoft.com/kb/125681
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 06640e0..c4335b4 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -13,12 +13,12 @@
#include "third_party/icu/source/common/unicode/utf16.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
-#include "ui/base/text/utf16_indexing.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/text_constants.h"
#include "ui/gfx/text_elider.h"
+#include "ui/gfx/utf16_indexing.h"
namespace gfx {
@@ -952,7 +952,7 @@ void RenderText::UpdateLayoutText() {
if (obscured_) {
size_t obscured_text_length =
- static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, text_.length()));
+ static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, text_.length()));
layout_text_.assign(obscured_text_length, kPasswordReplacementChar);
if (obscured_reveal_index_ >= 0 &&
@@ -966,7 +966,7 @@ void RenderText::UpdateLayoutText() {
// Gets the index in |layout_text_| to be replaced.
const size_t cp_start =
- static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, start));
+ static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, start));
if (layout_text_.length() > cp_start)
layout_text_.replace(cp_start, 1, text_.substr(start, end - start));
}
diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc
index c6cf4f2..9ad2a3d 100644
--- a/ui/gfx/render_text_linux.cc
+++ b/ui/gfx/render_text_linux.cc
@@ -12,11 +12,11 @@
#include "base/i18n/break_iterator.h"
#include "base/logging.h"
#include "third_party/skia/include/core/SkTypeface.h"
-#include "ui/base/text/utf16_indexing.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_render_params_linux.h"
#include "ui/gfx/pango_util.h"
+#include "ui/gfx/utf16_indexing.h"
namespace gfx {
@@ -252,7 +252,7 @@ std::vector<Rect> RenderTextLinux::GetSubstringBounds(const gfx::Range& range) {
size_t RenderTextLinux::TextIndexToLayoutIndex(size_t index) const {
DCHECK(layout_);
- ptrdiff_t offset = ui::UTF16IndexToOffset(text(), 0, index);
+ ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index);
// Clamp layout indices to the length of the text actually used for layout.
offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1));
const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset);
@@ -263,7 +263,7 @@ size_t RenderTextLinux::LayoutIndexToTextIndex(size_t index) const {
DCHECK(layout_);
const char* layout_pointer = layout_text_ + index;
const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer);
- return ui::UTF16OffsetToIndex(text(), 0, offset);
+ return gfx::UTF16OffsetToIndex(text(), 0, offset);
}
bool RenderTextLinux::IsCursorablePosition(size_t position) {
@@ -271,11 +271,11 @@ bool RenderTextLinux::IsCursorablePosition(size_t position) {
return true;
if (position >= text().length())
return position == text().length();
- if (!ui::IsValidCodePointIndex(text(), position))
+ if (!gfx::IsValidCodePointIndex(text(), position))
return false;
EnsureLayout();
- ptrdiff_t offset = ui::UTF16IndexToOffset(text(), 0, position);
+ ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, position);
// Check that the index corresponds with a valid text code point, that it is
// marked as a legitimate cursor position by Pango, and that it is not
// truncated from layout text (its glyph is shown on screen).
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index 2415060..2eff381 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -14,11 +14,11 @@
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "third_party/icu/source/common/unicode/uchar.h"
-#include "ui/base/text/utf16_indexing.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_fallback_win.h"
#include "ui/gfx/font_smoothing_win.h"
#include "ui/gfx/platform_font_win.h"
+#include "ui/gfx/utf16_indexing.h"
namespace gfx {
@@ -413,7 +413,7 @@ std::vector<Rect> RenderTextWin::GetSubstringBounds(const gfx::Range& range) {
size_t RenderTextWin::TextIndexToLayoutIndex(size_t index) const {
DCHECK_LE(index, text().length());
- ptrdiff_t i = obscured() ? ui::UTF16IndexToOffset(text(), 0, index) : index;
+ ptrdiff_t i = obscured() ? gfx::UTF16IndexToOffset(text(), 0, index) : index;
CHECK_GE(i, 0);
// Clamp layout indices to the length of the text actually used for layout.
return std::min<size_t>(GetLayoutText().length(), i);
@@ -424,7 +424,7 @@ size_t RenderTextWin::LayoutIndexToTextIndex(size_t index) const {
return index;
DCHECK_LE(index, GetLayoutText().length());
- const size_t text_index = ui::UTF16OffsetToIndex(text(), 0, index);
+ const size_t text_index = gfx::UTF16OffsetToIndex(text(), 0, index);
DCHECK_LE(text_index, text().length());
return text_index;
}
@@ -439,7 +439,7 @@ bool RenderTextWin::IsCursorablePosition(size_t position) {
// and that its glyph has distinct bounds (not mid-multi-character-grapheme).
// An example of a multi-character-grapheme that is not a surrogate-pair is:
// \x0915\x093f - (ki) - one of many Devanagari biconsonantal conjuncts.
- return ui::IsValidCodePointIndex(text(), position) &&
+ return gfx::IsValidCodePointIndex(text(), position) &&
position < LayoutIndexToTextIndex(GetLayoutText().length()) &&
GetGlyphBounds(position) != GetGlyphBounds(position - 1);
}
@@ -599,7 +599,7 @@ void RenderTextWin::ItemizeLogicalText() {
// Clamp run lengths to avoid exceeding the maximum supported glyph count.
if ((run_break - run->range.start()) > max_run_length) {
run_break = run->range.start() + max_run_length;
- if (!ui::IsValidCodePointIndex(layout_text, run_break))
+ if (!gfx::IsValidCodePointIndex(layout_text, run_break))
--run_break;
}
@@ -619,7 +619,7 @@ void RenderTextWin::ItemizeLogicalText() {
}
}
- DCHECK(ui::IsValidCodePointIndex(layout_text, run_break));
+ DCHECK(gfx::IsValidCodePointIndex(layout_text, run_break));
style.UpdatePosition(LayoutIndexToTextIndex(run_break));
if (script_item_break == run_break)
diff --git a/ui/gfx/screen_win.cc b/ui/gfx/screen_win.cc
index 7ae5306..7903cc5 100644
--- a/ui/gfx/screen_win.cc
+++ b/ui/gfx/screen_win.cc
@@ -11,7 +11,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/win/win_util.h"
#include "ui/gfx/display.h"
-#include "ui/gfx/dpi_win.h"
+#include "ui/gfx/win/dpi.h"
namespace {
diff --git a/ui/gfx/switches.cc b/ui/gfx/switches.cc
index a278f46..2f2eb9a 100644
--- a/ui/gfx/switches.cc
+++ b/ui/gfx/switches.cc
@@ -4,7 +4,6 @@
#include "ui/gfx/switches.h"
-namespace gfx {
namespace switches {
// Let text glyphs have X-positions that aren't snapped to the pixel grid in
@@ -17,8 +16,10 @@ const char kEnableBrowserTextSubpixelPositioning[] =
const char kEnableWebkitTextSubpixelPositioning[] =
"enable-webkit-text-subpixel-positioning";
+// Overrides the device scale factor for the browser UI and the contents.
+const char kForceDeviceScaleFactor[] = "force-device-scale-factor";
+
// Enables/Disables High DPI support (windows)
const char kHighDPISupport[] = "high-dpi-support";
} // namespace switches
-} // namespace gfx
diff --git a/ui/gfx/switches.h b/ui/gfx/switches.h
index f8069d0..e3cd9e7 100644
--- a/ui/gfx/switches.h
+++ b/ui/gfx/switches.h
@@ -7,14 +7,13 @@
#include "ui/gfx/gfx_export.h"
-namespace gfx {
namespace switches {
UI_EXPORT extern const char kEnableBrowserTextSubpixelPositioning[];
UI_EXPORT extern const char kEnableWebkitTextSubpixelPositioning[];
+UI_EXPORT extern const char kForceDeviceScaleFactor[];
UI_EXPORT extern const char kHighDPISupport[];
} // namespace switches
-} // namespace gfx
#endif // UI_GFX_SWITCHES_H_
diff --git a/ui/gfx/sys_color_change_listener.cc b/ui/gfx/sys_color_change_listener.cc
index 7a9fc84..d5646b3 100644
--- a/ui/gfx/sys_color_change_listener.cc
+++ b/ui/gfx/sys_color_change_listener.cc
@@ -13,7 +13,7 @@
#include "base/memory/singleton.h"
#include "base/observer_list.h"
#if defined(OS_WIN)
-#include "ui/base/win/singleton_hwnd.h"
+#include "ui/gfx/win/singleton_hwnd.h"
#endif
namespace gfx {
@@ -48,7 +48,7 @@ bool IsInvertedColorScheme() {
}
#if defined(OS_WIN)
-class SysColorChangeObserver : public ui::SingletonHwnd::Observer {
+class SysColorChangeObserver : public gfx::SingletonHwnd::Observer {
public:
static SysColorChangeObserver* GetInstance();
@@ -75,11 +75,11 @@ SysColorChangeObserver* SysColorChangeObserver::GetInstance() {
}
SysColorChangeObserver::SysColorChangeObserver() {
- ui::SingletonHwnd::GetInstance()->AddObserver(this);
+ gfx::SingletonHwnd::GetInstance()->AddObserver(this);
}
SysColorChangeObserver::~SysColorChangeObserver() {
- ui::SingletonHwnd::GetInstance()->RemoveObserver(this);
+ gfx::SingletonHwnd::GetInstance()->RemoveObserver(this);
}
void SysColorChangeObserver::AddListener(SysColorChangeListener* listener) {
diff --git a/ui/gfx/utf16_indexing.cc b/ui/gfx/utf16_indexing.cc
new file mode 100644
index 0000000..6af10c1
--- /dev/null
+++ b/ui/gfx/utf16_indexing.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 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 "ui/gfx/utf16_indexing.h"
+
+#include "base/logging.h"
+#include "base/third_party/icu/icu_utf.h"
+
+namespace gfx {
+
+bool IsValidCodePointIndex(const string16& s, size_t index) {
+ return index == 0 || index == s.length() ||
+ !(CBU16_IS_TRAIL(s[index]) && CBU16_IS_LEAD(s[index - 1]));
+}
+
+ptrdiff_t UTF16IndexToOffset(const string16& s, size_t base, size_t pos) {
+ // The indices point between UTF-16 words (range 0 to s.length() inclusive).
+ // In order to consistently handle indices that point to the middle of a
+ // surrogate pair, we count the first word in that surrogate pair and not
+ // the second. The test "s[i] is not the second half of a surrogate pair" is
+ // "IsValidCodePointIndex(s, i)".
+ DCHECK_LE(base, s.length());
+ DCHECK_LE(pos, s.length());
+ ptrdiff_t delta = 0;
+ while (base < pos)
+ delta += IsValidCodePointIndex(s, base++) ? 1 : 0;
+ while (pos < base)
+ delta -= IsValidCodePointIndex(s, pos++) ? 1 : 0;
+ return delta;
+}
+
+size_t UTF16OffsetToIndex(const string16& s, size_t base, ptrdiff_t offset) {
+ DCHECK_LE(base, s.length());
+ // As in UTF16IndexToOffset, we count the first half of a surrogate pair, not
+ // the second. When stepping from pos to pos+1 we check s[pos:pos+1] == s[pos]
+ // (Python syntax), hence pos++. When stepping from pos to pos-1 we check
+ // s[pos-1], hence --pos.
+ size_t pos = base;
+ while (offset > 0 && pos < s.length())
+ offset -= IsValidCodePointIndex(s, pos++) ? 1 : 0;
+ while (offset < 0 && pos > 0)
+ offset += IsValidCodePointIndex(s, --pos) ? 1 : 0;
+ // If offset != 0 then we ran off the edge of the string, which is a contract
+ // violation but is handled anyway (by clamping) in release for safety.
+ DCHECK_EQ(offset, 0);
+ // Since the second half of a surrogate pair has "length" zero, there is an
+ // ambiguity in the returned position. Resolve it by always returning a valid
+ // index.
+ if (!IsValidCodePointIndex(s, pos))
+ ++pos;
+ return pos;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/utf16_indexing.h b/ui/gfx/utf16_indexing.h
new file mode 100644
index 0000000..7f56384
--- /dev/null
+++ b/ui/gfx/utf16_indexing.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 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 UI_GFX_UTF16_INDEXING_H_
+#define UI_GFX_UTF16_INDEXING_H_
+
+#include "base/strings/string16.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// Returns false if s[index-1] is a high surrogate and s[index] is a low
+// surrogate, true otherwise.
+UI_EXPORT bool IsValidCodePointIndex(const string16& s, size_t index);
+
+// |UTF16IndexToOffset| returns the number of code points between |base| and
+// |pos| in the given string. |UTF16OffsetToIndex| returns the index that is
+// |offset| code points away from the given |base| index. These functions are
+// named after glib's |g_utf8_pointer_to_offset| and |g_utf8_offset_to_pointer|,
+// which perform the same function for UTF-8. As in glib, it is an error to
+// pass an |offset| that walks off the edge of the string.
+//
+// These functions attempt to deal with invalid use of UTF-16 surrogates in a
+// way that makes as much sense as possible: unpaired surrogates are treated as
+// single characters, and if an argument index points to the middle of a valid
+// surrogate pair, it is treated as though it pointed to the end of that pair.
+// The index returned by |UTF16OffsetToIndex| never points to the middle of a
+// surrogate pair.
+//
+// The following identities hold:
+// If |s| contains no surrogate pairs, then
+// UTF16IndexToOffset(s, base, pos) == pos - base
+// UTF16OffsetToIndex(s, base, offset) == base + offset
+// If |pos| does not point to the middle of a surrogate pair, then
+// UTF16OffsetToIndex(s, base, UTF16IndexToOffset(s, base, pos)) == pos
+// Always,
+// UTF16IndexToOffset(s, base, UTF16OffsetToIndex(s, base, ofs)) == ofs
+// UTF16IndexToOffset(s, i, j) == -UTF16IndexToOffset(s, j, i)
+UI_EXPORT ptrdiff_t UTF16IndexToOffset(const string16& s,
+ size_t base,
+ size_t pos);
+UI_EXPORT size_t UTF16OffsetToIndex(const string16& s,
+ size_t base,
+ ptrdiff_t offset);
+
+} // namespace gfx
+
+#endif // UI_GFX_UTF16_INDEXING_H_
diff --git a/ui/gfx/utf16_indexing_unittest.cc b/ui/gfx/utf16_indexing_unittest.cc
new file mode 100644
index 0000000..da2f8f5b
--- /dev/null
+++ b/ui/gfx/utf16_indexing_unittest.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 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 "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/utf16_indexing.h"
+
+namespace gfx {
+
+TEST(UTF16IndexingTest, IndexOffsetConversions) {
+ // Valid surrogate pair surrounded by unpaired surrogates
+ const char16 foo[] = {0xDC00, 0xD800, 0xD800, 0xDFFF, 0xDFFF, 0xDBFF, 0};
+ const string16 s(foo);
+ const size_t the_invalid_index = 3;
+ for (size_t i = 0; i <= s.length(); ++i)
+ EXPECT_EQ(i != the_invalid_index, IsValidCodePointIndex(s, i));
+ for (size_t i = 0; i <= s.length(); ++i) {
+ for (size_t j = i; j <= s.length(); ++j) {
+ ptrdiff_t offset = static_cast<ptrdiff_t>(j - i);
+ if (i <= the_invalid_index && j > the_invalid_index)
+ --offset;
+ EXPECT_EQ(offset, UTF16IndexToOffset(s, i, j));
+ EXPECT_EQ(-offset, UTF16IndexToOffset(s, j, i));
+ size_t adjusted_j = (j == the_invalid_index) ? j + 1 : j;
+ EXPECT_EQ(adjusted_j, UTF16OffsetToIndex(s, i, offset));
+ size_t adjusted_i = (i == the_invalid_index) ? i + 1 : i;
+ EXPECT_EQ(adjusted_i, UTF16OffsetToIndex(s, j, -offset));
+ }
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gfx/dpi_win.cc b/ui/gfx/win/dpi.cc
index 51972d2..98d23bd 100644
--- a/ui/gfx/dpi_win.cc
+++ b/ui/gfx/win/dpi.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gfx/dpi_win.h"
+#include "ui/gfx/win/dpi.h"
#include <windows.h>
#include "base/command_line.h"
@@ -25,9 +25,9 @@ int kDefaultDPIY = 96;
bool IsHighDPIEnabled() {
// Default is disabled.
if (CommandLine::ForCurrentProcess()->HasSwitch(
- gfx::switches::kHighDPISupport)) {
+ switches::kHighDPISupport)) {
return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- gfx::switches::kHighDPISupport).compare("1") == 0;
+ switches::kHighDPISupport).compare("1") == 0;
}
return false;
}
diff --git a/ui/gfx/dpi_win.h b/ui/gfx/win/dpi.h
index a056f53..a056f53 100644
--- a/ui/gfx/dpi_win.h
+++ b/ui/gfx/win/dpi.h
diff --git a/ui/gfx/win/hwnd_util.cc b/ui/gfx/win/hwnd_util.cc
new file mode 100644
index 0000000..91f0ddd
--- /dev/null
+++ b/ui/gfx/win/hwnd_util.cc
@@ -0,0 +1,214 @@
+// Copyright (c) 2012 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 "ui/gfx/win/hwnd_util.h"
+
+#include "base/i18n/rtl.h"
+#include "base/strings/string_util.h"
+#include "base/win/metro.h"
+#include "base/win/win_util.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+
+namespace gfx {
+
+namespace {
+
+// Adjust the window to fit.
+void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) {
+ if (fit_to_monitor) {
+ // Get the monitor.
+ HMONITOR hmon = MonitorFromRect(&bounds, MONITOR_DEFAULTTONEAREST);
+ if (hmon) {
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ base::win::GetMonitorInfoWrapper(hmon, &mi);
+ Rect window_rect(bounds);
+ Rect monitor_rect(mi.rcWork);
+ Rect new_window_rect = window_rect;
+ new_window_rect.AdjustToFit(monitor_rect);
+ if (new_window_rect != window_rect) {
+ // Window doesn't fit on monitor, move and possibly resize.
+ SetWindowPos(hwnd, 0, new_window_rect.x(), new_window_rect.y(),
+ new_window_rect.width(), new_window_rect.height(),
+ SWP_NOACTIVATE | SWP_NOZORDER);
+ return;
+ }
+ // Else fall through.
+ } else {
+ NOTREACHED() << "Unable to find default monitor";
+ // Fall through.
+ }
+ } // Else fall through.
+
+ // The window is not being fit to monitor, or the window fits on the monitor
+ // as is, or we have no monitor info; reset the bounds.
+ ::SetWindowPos(hwnd, 0, bounds.left, bounds.top,
+ bounds.right - bounds.left, bounds.bottom - bounds.top,
+ SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+} // namespace
+
+string16 GetClassName(HWND window) {
+ // GetClassNameW will return a truncated result (properly null terminated) if
+ // the given buffer is not large enough. So, it is not possible to determine
+ // that we got the entire class name if the result is exactly equal to the
+ // size of the buffer minus one.
+ DWORD buffer_size = MAX_PATH;
+ while (true) {
+ std::wstring output;
+ DWORD size_ret =
+ GetClassNameW(window, WriteInto(&output, buffer_size), buffer_size);
+ if (size_ret == 0)
+ break;
+ if (size_ret < (buffer_size - 1)) {
+ output.resize(size_ret);
+ return output;
+ }
+ buffer_size *= 2;
+ }
+ return std::wstring(); // error
+}
+
+#pragma warning(push)
+#pragma warning(disable:4312 4244)
+
+WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) {
+ // The reason we don't return the SetwindowLongPtr() value is that it returns
+ // the orignal window procedure and not the current one. I don't know if it is
+ // a bug or an intended feature.
+ WNDPROC oldwindow_proc =
+ reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC));
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc));
+ return oldwindow_proc;
+}
+
+void* SetWindowUserData(HWND hwnd, void* user_data) {
+ return
+ reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA,
+ reinterpret_cast<LONG_PTR>(user_data)));
+}
+
+void* GetWindowUserData(HWND hwnd) {
+ DWORD process_id = 0;
+ DWORD thread_id = GetWindowThreadProcessId(hwnd, &process_id);
+ // A window outside the current process needs to be ignored.
+ if (process_id != ::GetCurrentProcessId())
+ return NULL;
+ return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+}
+
+#pragma warning(pop)
+
+bool DoesWindowBelongToActiveWindow(HWND window) {
+ DCHECK(window);
+ HWND top_window = ::GetAncestor(window, GA_ROOT);
+ if (!top_window)
+ return false;
+
+ HWND active_top_window = ::GetAncestor(::GetForegroundWindow(), GA_ROOT);
+ return (top_window == active_top_window);
+}
+
+void CenterAndSizeWindow(HWND parent,
+ HWND window,
+ const Size& pref) {
+ DCHECK(window && pref.width() > 0 && pref.height() > 0);
+
+ // Calculate the ideal bounds.
+ RECT window_bounds;
+ RECT center_bounds = {0};
+ if (parent) {
+ // If there is a parent, center over the parents bounds.
+ ::GetWindowRect(parent, &center_bounds);
+ }
+
+ if (::IsRectEmpty(&center_bounds)) {
+ // No parent or no parent rect. Center over the monitor the window is on.
+ HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
+ if (monitor) {
+ MONITORINFO mi = {0};
+ mi.cbSize = sizeof(mi);
+ base::win::GetMonitorInfoWrapper(monitor, &mi);
+ center_bounds = mi.rcWork;
+ } else {
+ NOTREACHED() << "Unable to get default monitor";
+ }
+ }
+
+ window_bounds.left = center_bounds.left;
+ if (pref.width() < (center_bounds.right - center_bounds.left)) {
+ window_bounds.left +=
+ (center_bounds.right - center_bounds.left - pref.width()) / 2;
+ }
+ window_bounds.right = window_bounds.left + pref.width();
+
+ window_bounds.top = center_bounds.top;
+ if (pref.height() < (center_bounds.bottom - center_bounds.top)) {
+ window_bounds.top +=
+ (center_bounds.bottom - center_bounds.top - pref.height()) / 2;
+ }
+ window_bounds.bottom = window_bounds.top + pref.height();
+
+ // If we're centering a child window, we are positioning in client
+ // coordinates, and as such we need to offset the target rectangle by the
+ // position of the parent window.
+ if (::GetWindowLong(window, GWL_STYLE) & WS_CHILD) {
+ DCHECK(parent && ::GetParent(window) == parent);
+ POINT topleft = { window_bounds.left, window_bounds.top };
+ ::MapWindowPoints(HWND_DESKTOP, parent, &topleft, 1);
+ window_bounds.left = topleft.x;
+ window_bounds.top = topleft.y;
+ window_bounds.right = window_bounds.left + pref.width();
+ window_bounds.bottom = window_bounds.top + pref.height();
+ }
+
+ AdjustWindowToFit(window, window_bounds, !parent);
+}
+
+void CheckWindowCreated(HWND hwnd) {
+ if (!hwnd)
+ LOG_GETLASTERROR(FATAL);
+}
+
+void ShowSystemMenu(HWND window) {
+ RECT rect;
+ GetWindowRect(window, &rect);
+ Point point = Point(rect.left, rect.top);
+ static const int kSystemMenuOffset = 10;
+ point.Offset(kSystemMenuOffset, kSystemMenuOffset);
+ ShowSystemMenuAtPoint(window, point);
+}
+
+void ShowSystemMenuAtPoint(HWND window, const Point& point) {
+ // In the Metro process, we never want to show the system menu.
+ if (base::win::IsMetroProcess())
+ return;
+ UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
+ if (base::i18n::IsRTL())
+ flags |= TPM_RIGHTALIGN;
+ HMENU menu = GetSystemMenu(window, FALSE);
+ const int command =
+ TrackPopupMenu(menu, flags, point.x(), point.y(), 0, window, NULL);
+ if (command)
+ SendMessage(window, WM_SYSCOMMAND, command, 0);
+}
+
+extern "C" {
+ typedef HWND (*RootWindow)();
+}
+
+HWND GetWindowToParentTo(bool get_real_hwnd) {
+ HMODULE metro = base::win::GetMetroModule();
+ if (!metro)
+ return get_real_hwnd ? ::GetDesktopWindow() : HWND_DESKTOP;
+ // In windows 8 metro-mode the root window is not the desktop.
+ RootWindow root_window =
+ reinterpret_cast<RootWindow>(::GetProcAddress(metro, "GetRootWindow"));
+ return root_window();
+}
+
+} // namespace gfx
diff --git a/ui/gfx/win/hwnd_util.h b/ui/gfx/win/hwnd_util.h
new file mode 100644
index 0000000..70e5f8f
--- /dev/null
+++ b/ui/gfx/win/hwnd_util.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 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 UI_GFX_WIN_HWND_UTIL_H_
+#define UI_GFX_WIN_HWND_UTIL_H_
+
+#include <windows.h>
+
+#include "base/strings/string16.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+class Point;
+class Size;
+
+// A version of the GetClassNameW API that returns the class name in an
+// string16. An empty result indicates a failure to get the class name.
+UI_EXPORT string16 GetClassName(HWND hwnd);
+
+// Useful for subclassing a HWND. Returns the previous window procedure.
+UI_EXPORT WNDPROC SetWindowProc(HWND hwnd, WNDPROC wndproc);
+
+// Pointer-friendly wrappers around Get/SetWindowLong(..., GWLP_USERDATA, ...)
+// Returns the previously set value.
+UI_EXPORT void* SetWindowUserData(HWND hwnd, void* user_data);
+UI_EXPORT void* GetWindowUserData(HWND hwnd);
+
+// Returns true if the specified window is the current active top window or one
+// of its children.
+UI_EXPORT bool DoesWindowBelongToActiveWindow(HWND window);
+
+// Sizes the window to have a window size of |pref|, then centers the window
+// over |parent|, ensuring the window fits on screen.
+UI_EXPORT void CenterAndSizeWindow(HWND parent,
+ HWND window,
+ const gfx::Size& pref);
+
+// If |hwnd| is NULL logs various thing and CHECKs. Invoke right after calling
+// CreateWindow.
+UI_EXPORT void CheckWindowCreated(HWND hwnd);
+
+// Shows |window|'s system menu (at a specified |point| in screen coordinates).
+UI_EXPORT void ShowSystemMenu(HWND window);
+UI_EXPORT void ShowSystemMenuAtPoint(HWND window, const gfx::Point& point);
+
+// Returns the window you can use to parent a top level window.
+// Note that in some cases we create child windows not parented to its final
+// container so in those cases you should pass true in |get_real_hwnd|.
+UI_EXPORT HWND GetWindowToParentTo(bool get_real_hwnd);
+
+} // namespace gfx
+
+#endif // UI_GFX_WIN_HWND_UTIL_H_
diff --git a/ui/gfx/win/scoped_set_map_mode.h b/ui/gfx/win/scoped_set_map_mode.h
new file mode 100644
index 0000000..910837d
--- /dev/null
+++ b/ui/gfx/win/scoped_set_map_mode.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 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 UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_
+#define UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_
+
+#include <windows.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+namespace gfx {
+
+// Helper class for setting and restore the map mode on a DC.
+class ScopedSetMapMode {
+ public:
+ ScopedSetMapMode(HDC hdc, int map_mode)
+ : hdc_(hdc),
+ old_map_mode_(SetMapMode(hdc, map_mode)) {
+ DCHECK(hdc_);
+ DCHECK_NE(map_mode, 0);
+ DCHECK_NE(old_map_mode_, 0);
+ }
+
+ ~ScopedSetMapMode() {
+ const int mode = SetMapMode(hdc_, old_map_mode_);
+ DCHECK_NE(mode, 0);
+ }
+
+ private:
+ HDC hdc_;
+ int old_map_mode_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSetMapMode);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_
diff --git a/ui/gfx/win/singleton_hwnd.cc b/ui/gfx/win/singleton_hwnd.cc
new file mode 100644
index 0000000..37993e8
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 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 "ui/gfx/win/singleton_hwnd.h"
+
+#include "base/memory/singleton.h"
+#include "base/message_loop/message_loop.h"
+
+namespace gfx {
+
+// static
+SingletonHwnd* SingletonHwnd::GetInstance() {
+ return Singleton<SingletonHwnd>::get();
+}
+
+void SingletonHwnd::AddObserver(Observer* observer) {
+ if (!hwnd()) {
+ if (!base::MessageLoop::current() ||
+ base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
+ // Creating this window in (e.g.) a renderer inhibits shutdown on
+ // Windows. See http://crbug.com/230122 and http://crbug.com/236039.
+ DLOG(ERROR) << "Cannot create windows on non-UI thread!";
+ return;
+ }
+ WindowImpl::Init(NULL, Rect());
+ }
+ observer_list_.AddObserver(observer);
+}
+
+void SingletonHwnd::RemoveObserver(Observer* observer) {
+ if (!hwnd())
+ return;
+ observer_list_.RemoveObserver(observer);
+}
+
+BOOL SingletonHwnd::ProcessWindowMessage(HWND window,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ LRESULT& result,
+ DWORD msg_map_id) {
+ FOR_EACH_OBSERVER(Observer,
+ observer_list_,
+ OnWndProc(window, message, wparam, lparam));
+ return false;
+}
+
+SingletonHwnd::SingletonHwnd() {
+}
+
+SingletonHwnd::~SingletonHwnd() {
+}
+
+} // namespace gfx
diff --git a/ui/gfx/win/singleton_hwnd.h b/ui/gfx/win/singleton_hwnd.h
new file mode 100644
index 0000000..96af6e7
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 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 UI_GFX_WIN_SINGLETON_HWND_H_
+#define UI_GFX_WIN_SINGLETON_HWND_H_
+
+#include <windows.h>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/observer_list.h"
+#include "ui/gfx/win/window_impl.h"
+
+template<typename T> struct DefaultSingletonTraits;
+
+namespace gfx {
+
+// Singleton message-only HWND that allows interested clients to receive WM_*
+// notifications.
+class SingletonHwnd : public WindowImpl {
+ public:
+ static SingletonHwnd* GetInstance();
+
+ // Observer interface for receiving Windows WM_* notifications.
+ class Observer {
+ public:
+ virtual void OnWndProc(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam) = 0;
+ };
+
+ // Add/remove observer to receive WM_* notifications.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Windows callback for WM_* notifications.
+ virtual BOOL ProcessWindowMessage(HWND window,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ LRESULT& result,
+ DWORD msg_map_id) OVERRIDE;
+
+ private:
+ friend struct DefaultSingletonTraits<SingletonHwnd>;
+
+ SingletonHwnd();
+ ~SingletonHwnd();
+
+ // List of registered observers.
+ ObserverList<Observer> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(SingletonHwnd);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_WIN_SINGLETON_HWND_H_
diff --git a/ui/gfx/win/window_impl.cc b/ui/gfx/win/window_impl.cc
new file mode 100644
index 0000000..e2e6af0
--- /dev/null
+++ b/ui/gfx/win/window_impl.cc
@@ -0,0 +1,272 @@
+// Copyright (c) 2012 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 "ui/gfx/win/window_impl.h"
+
+#include <list>
+
+#include "base/debug/alias.h"
+#include "base/memory/singleton.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/lock.h"
+#include "base/win/wrapped_window_proc.h"
+#include "ui/gfx/win/hwnd_util.h"
+
+namespace gfx {
+
+static const DWORD kWindowDefaultChildStyle =
+ WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
+static const DWORD kWindowDefaultExStyle = 0;
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowImpl class tracking.
+
+// Several external scripts rely explicitly on this base class name for
+// acquiring the window handle and will break if this is modified!
+// static
+const wchar_t* const WindowImpl::kBaseClassName = L"Chrome_WidgetWin_";
+
+// WindowImpl class information used for registering unique windows.
+struct ClassInfo {
+ UINT style;
+ HICON icon;
+
+ ClassInfo(int style, HICON icon)
+ : style(style),
+ icon(icon) {}
+
+ // Compares two ClassInfos. Returns true if all members match.
+ bool Equals(const ClassInfo& other) const {
+ return (other.style == style && other.icon == icon);
+ }
+};
+
+// WARNING: this class may be used on multiple threads.
+class ClassRegistrar {
+ public:
+ ~ClassRegistrar();
+
+ static ClassRegistrar* GetInstance();
+
+ // Returns the atom identifying the class matching |class_info|,
+ // creating and registering a new class if the class is not yet known.
+ ATOM RetrieveClassAtom(const ClassInfo& class_info);
+
+ private:
+ // Represents a registered window class.
+ struct RegisteredClass {
+ RegisteredClass(const ClassInfo& info, ATOM atom);
+
+ // Info used to create the class.
+ ClassInfo info;
+
+ // The atom identifying the window class.
+ ATOM atom;
+ };
+
+ ClassRegistrar();
+ friend struct DefaultSingletonTraits<ClassRegistrar>;
+
+ typedef std::list<RegisteredClass> RegisteredClasses;
+ RegisteredClasses registered_classes_;
+
+ // Counter of how many classes have been registered so far.
+ int registered_count_;
+
+ base::Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClassRegistrar);
+};
+
+ClassRegistrar::~ClassRegistrar() {}
+
+// static
+ClassRegistrar* ClassRegistrar::GetInstance() {
+ return Singleton<ClassRegistrar,
+ LeakySingletonTraits<ClassRegistrar> >::get();
+}
+
+ATOM ClassRegistrar::RetrieveClassAtom(const ClassInfo& class_info) {
+ base::AutoLock auto_lock(lock_);
+ for (RegisteredClasses::const_iterator i = registered_classes_.begin();
+ i != registered_classes_.end(); ++i) {
+ if (class_info.Equals(i->info))
+ return i->atom;
+ }
+
+ // No class found, need to register one.
+ string16 name = string16(WindowImpl::kBaseClassName) +
+ base::IntToString16(registered_count_++);
+
+ WNDCLASSEX window_class;
+ base::win::InitializeWindowClass(
+ name.c_str(),
+ &base::win::WrappedWindowProc<WindowImpl::WndProc>,
+ class_info.style,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ class_info.icon,
+ class_info.icon,
+ &window_class);
+ HMODULE instance = window_class.hInstance;
+ ATOM atom = RegisterClassEx(&window_class);
+ CHECK(atom) << GetLastError();
+
+ registered_classes_.push_back(RegisteredClass(class_info, atom));
+
+ return atom;
+}
+
+ClassRegistrar::RegisteredClass::RegisteredClass(const ClassInfo& info,
+ ATOM atom)
+ : info(info),
+ atom(atom) {}
+
+ClassRegistrar::ClassRegistrar() : registered_count_(0) {}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowImpl, public
+
+WindowImpl::WindowImpl()
+ : window_style_(0),
+ window_ex_style_(kWindowDefaultExStyle),
+ class_style_(CS_DBLCLKS),
+ hwnd_(NULL),
+ got_create_(false),
+ got_valid_hwnd_(false),
+ destroyed_(NULL) {
+}
+
+WindowImpl::~WindowImpl() {
+ if (destroyed_)
+ *destroyed_ = true;
+ ClearUserData();
+}
+
+void WindowImpl::Init(HWND parent, const Rect& bounds) {
+ if (window_style_ == 0)
+ window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle;
+
+ if (parent == HWND_DESKTOP) {
+ // Only non-child windows can have HWND_DESKTOP (0) as their parent.
+ CHECK((window_style_ & WS_CHILD) == 0);
+ parent = GetWindowToParentTo(false);
+ } else if (parent == ::GetDesktopWindow()) {
+ // Any type of window can have the "Desktop Window" as their parent.
+ parent = GetWindowToParentTo(true);
+ } else if (parent != HWND_MESSAGE) {
+ CHECK(::IsWindow(parent));
+ }
+
+ int x, y, width, height;
+ if (bounds.IsEmpty()) {
+ x = y = width = height = CW_USEDEFAULT;
+ } else {
+ x = bounds.x();
+ y = bounds.y();
+ width = bounds.width();
+ height = bounds.height();
+ }
+
+ ATOM atom = GetWindowClassAtom();
+ bool destroyed = false;
+ destroyed_ = &destroyed;
+ HWND hwnd = CreateWindowEx(window_ex_style_,
+ reinterpret_cast<wchar_t*>(atom), NULL,
+ window_style_, x, y, width, height,
+ parent, NULL, NULL, this);
+
+ // First nccalcszie (during CreateWindow) for captioned windows is
+ // deliberately ignored so force a second one here to get the right
+ // non-client set up.
+ if (hwnd && (window_style_ & WS_CAPTION)) {
+ SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
+ }
+
+ if (!hwnd_ && GetLastError() == 0) {
+ base::debug::Alias(&destroyed);
+ base::debug::Alias(&hwnd);
+ bool got_create = got_create_;
+ base::debug::Alias(&got_create);
+ bool got_valid_hwnd = got_valid_hwnd_;
+ base::debug::Alias(&got_valid_hwnd);
+ WNDCLASSEX class_info;
+ memset(&class_info, 0, sizeof(WNDCLASSEX));
+ class_info.cbSize = sizeof(WNDCLASSEX);
+ BOOL got_class = GetClassInfoEx(GetModuleHandle(NULL),
+ reinterpret_cast<wchar_t*>(atom),
+ &class_info);
+ base::debug::Alias(&got_class);
+ bool procs_match = got_class && class_info.lpfnWndProc ==
+ base::win::WrappedWindowProc<&WindowImpl::WndProc>;
+ base::debug::Alias(&procs_match);
+ CHECK(false);
+ }
+ if (!destroyed)
+ destroyed_ = NULL;
+
+ CheckWindowCreated(hwnd_);
+
+ // The window procedure should have set the data for us.
+ CHECK_EQ(this, GetWindowUserData(hwnd));
+}
+
+HICON WindowImpl::GetDefaultWindowIcon() const {
+ return NULL;
+}
+
+LRESULT WindowImpl::OnWndProc(UINT message, WPARAM w_param, LPARAM l_param) {
+ LRESULT result = 0;
+
+ // Handle the message if it's in our message map; otherwise, let the system
+ // handle it.
+ if (!ProcessWindowMessage(hwnd_, message, w_param, l_param, result))
+ result = DefWindowProc(hwnd_, message, w_param, l_param);
+
+ return result;
+}
+
+void WindowImpl::ClearUserData() {
+ if (::IsWindow(hwnd_))
+ gfx::SetWindowUserData(hwnd_, NULL);
+}
+
+// static
+LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ if (message == WM_NCCREATE) {
+ CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(l_param);
+ WindowImpl* window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams);
+ DCHECK(window);
+ gfx::SetWindowUserData(hwnd, window);
+ window->hwnd_ = hwnd;
+ window->got_create_ = true;
+ if (hwnd)
+ window->got_valid_hwnd_ = true;
+ return TRUE;
+ }
+
+ WindowImpl* window = reinterpret_cast<WindowImpl*>(GetWindowUserData(hwnd));
+ if (!window)
+ return 0;
+
+ return window->OnWndProc(message, w_param, l_param);
+}
+
+ATOM WindowImpl::GetWindowClassAtom() {
+ HICON icon = GetDefaultWindowIcon();
+ ClassInfo class_info(initial_class_style(), icon);
+ return ClassRegistrar::GetInstance()->RetrieveClassAtom(class_info);
+}
+
+} // namespace gfx
diff --git a/ui/gfx/win/window_impl.h b/ui/gfx/win/window_impl.h
new file mode 100644
index 0000000..2b0018e
--- /dev/null
+++ b/ui/gfx/win/window_impl.h
@@ -0,0 +1,123 @@
+// Copyright (c) 2012 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 UI_GFX_WIN_WINDOW_IMPL_H_
+#define UI_GFX_WIN_WINDOW_IMPL_H_
+
+#include <atlbase.h>
+#include <atlapp.h>
+#include <atlmisc.h>
+#include <atlcrack.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
+
+namespace gfx {
+
+// An interface implemented by classes that use message maps.
+// ProcessWindowMessage is implemented by the BEGIN_MESSAGE_MAP_EX macro.
+class MessageMapInterface {
+ public:
+ // Processes one message from the window's message queue.
+ virtual BOOL ProcessWindowMessage(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param,
+ LRESULT& result,
+ DWORD msg_map_id = 0) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// WindowImpl
+// A convenience class that encapsulates the details of creating and
+// destroying a HWND. This class also hosts the windows procedure used by all
+// Windows.
+//
+///////////////////////////////////////////////////////////////////////////////
+class UI_EXPORT WindowImpl : public MessageMapInterface {
+ public:
+ WindowImpl();
+ virtual ~WindowImpl();
+
+ // Initializes the Window with a parent and an initial desired size.
+ void Init(HWND parent, const gfx::Rect& bounds);
+
+ // Returns the default window icon to use for windows of this type.
+ virtual HICON GetDefaultWindowIcon() const;
+
+ // Returns the HWND associated with this Window.
+ HWND hwnd() const { return hwnd_; }
+
+ // Sets the window styles. This is ONLY used when the window is created.
+ // In other words, if you invoke this after invoking Init, nothing happens.
+ void set_window_style(DWORD style) { window_style_ = style; }
+ DWORD window_style() const { return window_style_; }
+
+ // Sets the extended window styles. See comment about |set_window_style|.
+ void set_window_ex_style(DWORD style) { window_ex_style_ = style; }
+ DWORD window_ex_style() const { return window_ex_style_; }
+
+ // Sets the class style to use. The default is CS_DBLCLKS.
+ void set_initial_class_style(UINT class_style) {
+ // We dynamically generate the class name, so don't register it globally!
+ DCHECK_EQ((class_style & CS_GLOBALCLASS), 0u);
+ class_style_ = class_style;
+ }
+ UINT initial_class_style() const { return class_style_; }
+
+ protected:
+ // Handles the WndProc callback for this object.
+ virtual LRESULT OnWndProc(UINT message, WPARAM w_param, LPARAM l_param);
+
+ // Subclasses must call this method from their destructors to ensure that
+ // this object is properly disassociated from the HWND during destruction,
+ // otherwise it's possible this object may still exist while a subclass is
+ // destroyed.
+ void ClearUserData();
+
+ private:
+ friend class ClassRegistrar;
+
+ // The window procedure used by all Windows.
+ static LRESULT CALLBACK WndProc(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param);
+
+ // Gets the window class atom to use when creating the corresponding HWND.
+ // If necessary, this registers the window class.
+ ATOM GetWindowClassAtom();
+
+ // All classes registered by WindowImpl start with this name.
+ static const wchar_t* const kBaseClassName;
+
+ // Window Styles used when creating the window.
+ DWORD window_style_;
+
+ // Window Extended Styles used when creating the window.
+ DWORD window_ex_style_;
+
+ // Style of the class to use.
+ UINT class_style_;
+
+ // Our hwnd.
+ HWND hwnd_;
+
+ // For debugging.
+ // TODO(sky): nuke this when get crash data.
+ bool got_create_;
+ bool got_valid_hwnd_;
+ bool* destroyed_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowImpl);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_WIN_WINDOW_IMPL_H_