OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/corewm/cursor_height_provider_win.h" | 5 #include "ui/views/corewm/cursor_height_provider_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <map> | 9 #include <map> |
10 | 10 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 last_byte_mask = (last_byte_mask << bits_to_shift); | 98 last_byte_mask = (last_byte_mask << bits_to_shift); |
99 else | 99 else |
100 last_byte_mask = 0; | 100 last_byte_mask = 0; |
101 | 101 |
102 const uint32_t row_size = | 102 const uint32_t row_size = |
103 (bitmap_info.bmiHeader.biWidth + kBitsPeruint32 - 1) / kBitsPeruint32; | 103 (bitmap_info.bmiHeader.biWidth + kBitsPeruint32 - 1) / kBitsPeruint32; |
104 PixelData data(GetBitmapData(icon.hbmMask, bitmap_info, hdc)); | 104 PixelData data(GetBitmapData(icon.hbmMask, bitmap_info, hdc)); |
105 if (data == NULL) | 105 if (data == NULL) |
106 return kDefaultHeight; | 106 return kDefaultHeight; |
107 | 107 |
108 const int cursor_height = GetSystemMetrics(SM_CYCURSOR); | 108 // There are 2 types of cursors: Ones that cover the area underneath |
109 // Crash data seems to indicate cursor_height may be bigger than the bitmap. | 109 // completely (i.e. hand cursor) and ones that partially cover |
110 int i = std::max(0, static_cast<int>(bitmap_info.bmiHeader.biHeight) - | 110 // and partially blend with background (i. e. I-beam cursor). |
111 cursor_height); | 111 // These will have either 1 square mask or 2 masks stacked on top |
112 for (; i < bitmap_info.bmiHeader.biHeight; ++i) { | 112 // of each other (xor mask and and mask). |
113 if (!IsRowTransparent(data, row_size, last_byte_mask, i)) { | 113 const bool has_xor_mask = |
114 i--; | 114 bitmap_info.bmiHeader.biHeight == 2 * bitmap_info.bmiHeader.biWidth; |
| 115 const int cursor_height = |
| 116 has_xor_mask ? static_cast<int>(bitmap_info.bmiHeader.biHeight / 2) |
| 117 : static_cast<int>(bitmap_info.bmiHeader.biHeight); |
| 118 int xor_offset; |
| 119 if (has_xor_mask) { |
| 120 for (xor_offset = 0; xor_offset < cursor_height; ++xor_offset) { |
| 121 const uint32_t row_start = row_size * xor_offset; |
| 122 const uint32_t row_boundary = row_start + row_size; |
| 123 for (uint32_t i = row_start; i < row_boundary; ++i) |
| 124 data.get()[i] = ~(data.get()[i]); |
| 125 if (!IsRowTransparent(data, row_size, last_byte_mask, xor_offset)) { |
| 126 break; |
| 127 } |
| 128 } |
| 129 } else { |
| 130 xor_offset = cursor_height; |
| 131 } |
| 132 |
| 133 int and_offset; |
| 134 |
| 135 for (and_offset = has_xor_mask ? cursor_height : 0; |
| 136 and_offset < bitmap_info.bmiHeader.biHeight; ++and_offset) { |
| 137 if (!IsRowTransparent(data, row_size, last_byte_mask, and_offset)) { |
115 break; | 138 break; |
116 } | 139 } |
117 } | 140 } |
118 return bitmap_info.bmiHeader.biHeight - i - icon.yHotspot; | 141 if (has_xor_mask) { |
| 142 and_offset -= cursor_height; |
| 143 } |
| 144 const int offset = std::min(xor_offset, and_offset); |
| 145 |
| 146 DeleteObject(icon.hbmColor); |
| 147 DeleteObject(icon.hbmMask); |
| 148 |
| 149 return cursor_height - offset - icon.yHotspot + 1; |
119 } | 150 } |
120 | 151 |
121 } // namespace | 152 } // namespace |
122 | 153 |
123 namespace views { | 154 namespace views { |
124 namespace corewm { | 155 namespace corewm { |
125 | 156 |
126 int GetCurrentCursorVisibleHeight() { | 157 int GetCurrentCursorVisibleHeight() { |
127 CURSORINFO cursor = {0}; | 158 CURSORINFO cursor = {0}; |
128 cursor.cbSize = sizeof(cursor); | 159 cursor.cbSize = sizeof(cursor); |
129 GetCursorInfo(&cursor); | 160 GetCursorInfo(&cursor); |
130 | 161 |
131 if (cached_heights == NULL) | 162 if (cached_heights == NULL) |
132 cached_heights = new HeightStorage; | 163 cached_heights = new HeightStorage; |
133 | 164 |
134 HeightStorage::const_iterator cached_height = | 165 HeightStorage::const_iterator cached_height = |
135 cached_heights->find(cursor.hCursor); | 166 cached_heights->find(cursor.hCursor); |
136 if (cached_height != cached_heights->end()) | 167 if (cached_height != cached_heights->end()) |
137 return cached_height->second; | 168 return cached_height->second; |
138 | 169 |
139 const int height = CalculateCursorHeight(cursor.hCursor); | 170 const int height = CalculateCursorHeight(cursor.hCursor); |
140 (*cached_heights)[cursor.hCursor] = height; | 171 (*cached_heights)[cursor.hCursor] = height; |
141 | 172 |
142 return height; | 173 return height; |
143 } | 174 } |
144 | 175 |
145 } // namespace corewm | 176 } // namespace corewm |
146 } // namespace views | 177 } // namespace views |
OLD | NEW |