Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(818)

Side by Side Diff: ui/views/corewm/cursor_height_provider_win.cc

Issue 225403022: Fixed positioning of tooltips in multi monitor setups. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Unhardcoded cursor size hence simplifying DIP to screen conversions Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/corewm/cursor_height_provider_win.h"
6
7 #include <windows.h>
8
9 #include "base/basictypes.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/win/scoped_hdc.h"
12
13 namespace {
14 const uint32 bits_per_uint32 = 32;
15 // All bits are 1 for transparent portion of monochromatic mask.
16 const uint32 transparent_mask = 0xffffffff;
17 // This is height of default pointer arrow in Windows 7.
18 const int default_height = 20;
19
20 /**
21 * Gets the vertical offset between specified cursor's hotpoint and it's bottom.
22 *
23 * Gets the cursor image data and extract cursor's visible height.
24 * Based on that get's what should be the vertical offset between cursor's
25 * hot point and the tooltip.
26 */
27 class CursorVisibleHeightCalculator {
28 public:
29 explicit CursorVisibleHeightCalculator(HCURSOR cursor_handle);
30 int visible_height() const { return visible_height_; }
31
32 private:
33 /**
34 * Extracts the cursor data and calculates the visible height.
35 */
36 void Init(HCURSOR cursor_handle);
37
38 /**
39 * Fills the BITMAPINFO structure for specified bitmap @p handle.
40 * @param handle Handle to bitmap that's being examined.
41 * @param info Pointer to BITMAPINFO structure that'll receive the output.
42 * @return true if no error occured.
43 */
44 bool GetBitmapInfo(HBITMAP handle, BITMAPINFO* info);
45
46 /**
47 * Fills the bitmap_data_ member with pixel data for bitmap
48 * specified by @p handle in format described through @p info.
49 * @param handle Handle to bitmap that's being examined.
50 * @param info BITMAPINFO structure that describes the output format.
51 * @return true if no error occured.
52 */
53 bool GetBitmapData(HBITMAP handle, const BITMAPINFO& info);
54
55 /**
56 * Checks if the row on specified index is fully transparent.
57 * @param y row index.
58 * @return true if the row is considered transparent.
59 */
60 bool IsRowTransparent(uint32 y) const;
61
62 base::win::ScopedGetDC hdc_;
63 // Row size in DWORDs.
64 uint32 row_size_;
65 // Since bitmap is padded to full DWORD OR it with this bitmask
66 // to remove the padding noise.
67 uint32 last_byte_mask_;
68 // Pointer that receives memory block containing bitmap pixel data.
69 scoped_ptr<uint32> bitmap_data_;
70 int visible_height_;
71 };
72
73 CursorVisibleHeightCalculator::CursorVisibleHeightCalculator(
74 HCURSOR cursor_handle)
75 : hdc_(NULL),
76 row_size_(0),
77 last_byte_mask_(0),
78 visible_height_(default_height) {
79 Init(cursor_handle);
80 }
81
82 void CursorVisibleHeightCalculator::Init(HCURSOR cursor_handle) {
83 ICONINFO icon = {0};
84 GetIconInfo(cursor_handle, &icon);
85
86 BITMAPINFO info = {0};
87 if (!GetBitmapInfo(icon.hbmMask, &info))
88 return;
89
90 // Rows are padded to full DWORDs. OR with this mask will set them to 1
91 // to simplify matching with |transparent_mask|.
92 last_byte_mask_ = ~0;
93 last_byte_mask_ = last_byte_mask_
94 << (sizeof(last_byte_mask_) * 8 -
95 (info.bmiHeader.biWidth % bits_per_uint32));
96
97 row_size_ = (info.bmiHeader.biWidth + bits_per_uint32 - 1) / bits_per_uint32;
98 if (!GetBitmapData(icon.hbmMask, info))
99 return;
100 const int cursor_height = GetSystemMetrics(SM_CYCURSOR);
101 int i = info.bmiHeader.biHeight - cursor_height;
102 for (; i < info.bmiHeader.biHeight; ++i) {
103 if (!IsRowTransparent(i)) {
104 i--;
105 break;
106 }
107 }
108 bitmap_data_.reset();
109 visible_height_ = info.bmiHeader.biHeight - i - icon.yHotspot;
110 }
111
112 bool CursorVisibleHeightCalculator::GetBitmapInfo(HBITMAP handle,
113 BITMAPINFO* info) {
114 info->bmiHeader.biSize = sizeof(info->bmiHeader);
115 info->bmiHeader.biBitCount = 0;
116
117 int result = GetDIBits(hdc_, handle, 0, 0, NULL, info, DIB_RGB_COLORS);
118 return result != 0;
119 }
120
121 bool CursorVisibleHeightCalculator::GetBitmapData(HBITMAP handle,
122 const BITMAPINFO& info) {
123 // Masks are monochromatic.
124 DCHECK_EQ(info.bmiHeader.biBitCount, 1);
125 if (info.bmiHeader.biBitCount != 1)
126 return false;
127
128 const size_t number_of_colors = 2;
129
130 const size_t header_and_palette =
131 sizeof(info.bmiHeader) + number_of_colors * sizeof(RGBQUAD);
132 // When getting pixel data palette is appended to memory pointed by
133 // BITMAPINFO passed so allocate additional memory to store additional data.
134 scoped_ptr<BITMAPINFO> header(
135 reinterpret_cast<BITMAPINFO*>(new char[header_and_palette]));
136 if (header == nullptr)
137 return false;
138 memcpy(header.get(), &(info.bmiHeader), sizeof(info.bmiHeader));
139
140 bitmap_data_ = scoped_ptr<uint32>(
141 new uint32[info.bmiHeader.biSizeImage / sizeof(uint32)]);
142 if (bitmap_data_ == nullptr)
143 return false;
144
145 int result = GetDIBits(hdc_,
146 handle,
147 0,
148 info.bmiHeader.biHeight,
149 bitmap_data_.get(),
150 header.get(),
151 DIB_RGB_COLORS);
152
153 return result != 0;
154 }
155
156 bool CursorVisibleHeightCalculator::IsRowTransparent(uint32 y) const {
157 // Set the padding bits to 1 to make mask matching easier.
158 *(bitmap_data_.get() + (y + 1)* row_size_ - 1) |= last_byte_mask_;
159 for (uint32 i = y * row_size_; i < (y + 1) * row_size_; ++i) {
160 if (*(bitmap_data_.get() + i) != transparent_mask)
161 return false;
162 }
163 return true;
164 }
165
166 } // namespace
167
168 namespace views {
169 namespace corewm {
170
171 int CursorHeightProvider::GetCursorHeight() {
172 CURSORINFO cursor = {0};
173 cursor.cbSize = sizeof(cursor);
174 GetCursorInfo(&cursor);
175
176 HeightStorage::const_iterator cached_height =
177 cached_heights_.find(cursor.hCursor);
178 if (cached_height != cached_heights_.end())
179 return cached_height->second;
180
181 CursorVisibleHeightCalculator cursor_data(cursor.hCursor);
182 cached_heights_[cursor.hCursor] = cursor_data.visible_height();
183
184 return cursor_data.visible_height();
185 }
186
187 } // namespace corewm
188 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698