| Index: ui/views/corewm/cursor_height_provider_win.cc
|
| diff --git a/ui/views/corewm/cursor_height_provider_win.cc b/ui/views/corewm/cursor_height_provider_win.cc
|
| index 0d28d3801aa8ce2d24f89339f054eaddb073de17..d3945034809d41f3bc015e018a87dfd8479fcfa5 100644
|
| --- a/ui/views/corewm/cursor_height_provider_win.cc
|
| +++ b/ui/views/corewm/cursor_height_provider_win.cc
|
| @@ -105,17 +105,48 @@ int CalculateCursorHeight(HCURSOR cursor_handle) {
|
| if (data == NULL)
|
| return kDefaultHeight;
|
|
|
| - const int cursor_height = GetSystemMetrics(SM_CYCURSOR);
|
| - // Crash data seems to indicate cursor_height may be bigger than the bitmap.
|
| - int i = std::max(0, static_cast<int>(bitmap_info.bmiHeader.biHeight) -
|
| - cursor_height);
|
| - for (; i < bitmap_info.bmiHeader.biHeight; ++i) {
|
| - if (!IsRowTransparent(data, row_size, last_byte_mask, i)) {
|
| - i--;
|
| + // There are 2 types of cursors: Ones that cover the area underneath
|
| + // completely (i.e. hand cursor) and ones that partially cover
|
| + // and partially blend with background (i. e. I-beam cursor).
|
| + // These will have either 1 square mask or 2 masks stacked on top
|
| + // of each other (xor mask and and mask).
|
| + const bool has_xor_mask =
|
| + bitmap_info.bmiHeader.biHeight == 2 * bitmap_info.bmiHeader.biWidth;
|
| + const int cursor_height =
|
| + has_xor_mask ? static_cast<int>(bitmap_info.bmiHeader.biHeight / 2)
|
| + : static_cast<int>(bitmap_info.bmiHeader.biHeight);
|
| + int xor_offset;
|
| + if (has_xor_mask) {
|
| + for (xor_offset = 0; xor_offset < cursor_height; ++xor_offset) {
|
| + const uint32_t row_start = row_size * xor_offset;
|
| + const uint32_t row_boundary = row_start + row_size;
|
| + for (uint32_t i = row_start; i < row_boundary; ++i)
|
| + data.get()[i] = ~(data.get()[i]);
|
| + if (!IsRowTransparent(data, row_size, last_byte_mask, xor_offset)) {
|
| + break;
|
| + }
|
| + }
|
| + } else {
|
| + xor_offset = cursor_height;
|
| + }
|
| +
|
| + int and_offset;
|
| +
|
| + for (and_offset = has_xor_mask ? cursor_height : 0;
|
| + and_offset < bitmap_info.bmiHeader.biHeight; ++and_offset) {
|
| + if (!IsRowTransparent(data, row_size, last_byte_mask, and_offset)) {
|
| break;
|
| }
|
| }
|
| - return bitmap_info.bmiHeader.biHeight - i - icon.yHotspot;
|
| + if (has_xor_mask) {
|
| + and_offset -= cursor_height;
|
| + }
|
| + const int offset = std::min(xor_offset, and_offset);
|
| +
|
| + DeleteObject(icon.hbmColor);
|
| + DeleteObject(icon.hbmMask);
|
| +
|
| + return cursor_height - offset - icon.yHotspot + 1;
|
| }
|
|
|
| } // namespace
|
|
|