From 77bf6d9a5fba0f56ae8950c5bd8f30d380ba4967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Wed, 16 Aug 2023 14:53:07 -0300 Subject: [PATCH] Fix creation of cursor mask (fix aseprite/aseprite#3989) --- os/win/system.cpp | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/os/win/system.cpp b/os/win/system.cpp index c68ce3fb1..698128c7b 100644 --- a/os/win/system.cpp +++ b/os/win/system.cpp @@ -117,8 +117,20 @@ class WinCursorCache { // Create an empty mask bitmap. HBITMAP hmonobmp() { - if (!m_hmonobmp) - m_hmonobmp.reset(CreateBitmap(m_size.w, m_size.h, 1, 1, nullptr)); + if (!m_hmonobmp) { + // We must fill the mask bitmap with ones to avoid issues when a cursor is fully + // transparent. Before this change we were returning a "no cursor" from makeCursor + // when the cursor was fully transparent to avoid showing a black bitmap as the + // cursor. But then the following issue was found: + // https://github.com/aseprite/aseprite/issues/3989 (which is about the mouse + // cursor leaving a trail of cursors after it was switched to a fully transparent + // cursor bitmap. + // By filling the mask with ones we fix both, the issue and the black cursor. + int maskSize = (((m_size.w + 15) >> 4) << 1) * m_size.h; + auto maskBits = std::make_unique(maskSize); + std::memset(maskBits.get(), 0xFF, maskSize); + m_hmonobmp.reset(CreateBitmap(m_size.w, m_size.h, 1, 1, maskBits.get())); + } return m_hmonobmp.get(); } @@ -195,16 +207,12 @@ CursorRef SystemWin::makeCursor(const os::Surface* surface, return nullptr; uint32_t* bits = g_cursor_cache.bits(); - bool completelyTransparent = true; for (int y=0; ygetData(0, (sz.h-1-y)/scale); for (int x=0, u=0; x> format.alphaShift); - if (a) - completelyTransparent = false; - *bits = (a << 24) | (((c & format.redMask ) >> format.redShift ) << 16) | (((c & format.greenMask) >> format.greenShift) << 8) | @@ -216,16 +224,6 @@ CursorRef SystemWin::makeCursor(const os::Surface* surface, } } - // It looks like if we set a cursor that is completely transparent - // (all pixels with alpha=0), Windows will create a black opaque - // rectangle cursor. Which is not what we are looking for. So in - // this specific case we put a "no cursor" which has the expected - // result. - if (completelyTransparent) { - // Return a valid Cursor instance but with a nullptr handle. - return make_ref(nullptr); - } - ICONINFO ii; ii.fIcon = FALSE; ii.xHotspot = scale*focus.x + scale/2;