From f0a56cad937b9461fedd10ad69961f05a383256b Mon Sep 17 00:00:00 2001 From: fxliang Date: Mon, 27 May 2024 16:03:18 +0800 Subject: [PATCH] fix: UI layout sizes are not DPI aware. --- WeaselUI/DirectWriteResources.cpp | 30 ++--- WeaselUI/FullScreenLayout.cpp | 11 +- WeaselUI/FullScreenLayout.h | 5 +- WeaselUI/HorizontalLayout.h | 5 +- WeaselUI/Layout.cpp | 35 ++++-- WeaselUI/Layout.h | 11 +- WeaselUI/StandardLayout.h | 5 +- WeaselUI/VHorizontalLayout.h | 5 +- WeaselUI/VerticalLayout.h | 5 +- WeaselUI/WeaselPanel.cpp | 198 +++++++++++++++++------------- WeaselUI/WeaselPanel.h | 7 ++ include/WeaselUI.h | 2 +- 12 files changed, 192 insertions(+), 127 deletions(-) diff --git a/WeaselUI/DirectWriteResources.cpp b/WeaselUI/DirectWriteResources.cpp index 1d51b6e77..9dde3d98a 100644 --- a/WeaselUI/DirectWriteResources.cpp +++ b/WeaselUI/DirectWriteResources.cpp @@ -32,8 +32,8 @@ std::vector wc_split(const wchar_t* in, const wchar_t* delim) { DirectWriteResources::DirectWriteResources(weasel::UIStyle& style, UINT dpi = 96) : _style(style), - dpiScaleX_(0), - dpiScaleY_(0), + dpiScaleFontPoint(0), + dpiScaleLayout(0), pD2d1Factory(NULL), pDWFactory(NULL), pRenderTarget(NULL), @@ -70,9 +70,9 @@ DirectWriteResources::DirectWriteResources(weasel::UIStyle& style, pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), pBrush.GetAddressOf()); // get the dpi information - dpiScaleX_ = dpiScaleY_ = (float)dpi; - dpiScaleX_ /= 72.0f; - dpiScaleY_ /= 72.0f; + dpiScaleFontPoint = dpiScaleLayout = (float)dpi; + dpiScaleFontPoint /= 72.0f; + dpiScaleLayout /= 96.0f; InitResources(style, dpi); } @@ -130,8 +130,8 @@ HRESULT DirectWriteResources::InitResources( DWRITE_FONT_WEIGHT fontWeight = DWRITE_FONT_WEIGHT_NORMAL; DWRITE_FONT_STYLE fontStyle = DWRITE_FONT_STYLE_NORMAL; // convert percentage to float - float linespacing = dpiScaleX_ * ((float)_style.linespacing / 100.0f); - float baseline = dpiScaleX_ * ((float)_style.baseline / 100.0f); + float linespacing = dpiScaleFontPoint * ((float)_style.linespacing / 100.0f); + float baseline = dpiScaleFontPoint * ((float)_style.baseline / 100.0f); if (_style.layout_type == UIStyle::LAYOUT_VERTICAL_TEXT) baseline = linespacing / 2; // setup font weight and font style by the first unit of font_face setting @@ -142,7 +142,7 @@ HRESULT DirectWriteResources::InitResources( std::wregex(STYLEORWEIGHT, std::wregex::icase), L""); hResult = pDWFactory->CreateTextFormat( _mainFontFace.c_str(), NULL, fontWeight, fontStyle, - DWRITE_FONT_STRETCH_NORMAL, font_point * dpiScaleX_, L"", + DWRITE_FONT_STRETCH_NORMAL, font_point * dpiScaleFontPoint, L"", reinterpret_cast(pTextFormat.GetAddressOf())); if (pTextFormat != NULL) { if (vertical_text) { @@ -169,7 +169,7 @@ HRESULT DirectWriteResources::InitResources( std::wregex(STYLEORWEIGHT, std::wregex::icase), L""); hResult = pDWFactory->CreateTextFormat( _mainFontFace.c_str(), NULL, fontWeight, fontStyle, - DWRITE_FONT_STRETCH_NORMAL, font_point * dpiScaleX_, L"", + DWRITE_FONT_STRETCH_NORMAL, font_point * dpiScaleFontPoint, L"", reinterpret_cast(pPreeditTextFormat.GetAddressOf())); if (pPreeditTextFormat != NULL) { if (vertical_text) { @@ -199,7 +199,7 @@ HRESULT DirectWriteResources::InitResources( std::wregex(STYLEORWEIGHT, std::wregex::icase), L""); hResult = pDWFactory->CreateTextFormat( _mainFontFace.c_str(), NULL, fontWeight, fontStyle, - DWRITE_FONT_STRETCH_NORMAL, label_font_point * dpiScaleX_, L"", + DWRITE_FONT_STRETCH_NORMAL, label_font_point * dpiScaleFontPoint, L"", reinterpret_cast(pLabelTextFormat.GetAddressOf())); if (pLabelTextFormat != NULL) { if (vertical_text) { @@ -228,7 +228,7 @@ HRESULT DirectWriteResources::InitResources( std::wregex(STYLEORWEIGHT, std::wregex::icase), L""); hResult = pDWFactory->CreateTextFormat( _mainFontFace.c_str(), NULL, fontWeight, fontStyle, - DWRITE_FONT_STRETCH_NORMAL, comment_font_point * dpiScaleX_, L"", + DWRITE_FONT_STRETCH_NORMAL, comment_font_point * dpiScaleFontPoint, L"", reinterpret_cast(pCommentTextFormat.GetAddressOf())); if (pCommentTextFormat != NULL) { if (vertical_text) { @@ -255,8 +255,8 @@ HRESULT DirectWriteResources::InitResources(const UIStyle& style, const UINT& dpi = 96) { _style = style; if (dpi) { - dpiScaleX_ = dpi / 72.0f; - dpiScaleY_ = dpi / 72.0f; + dpiScaleFontPoint = dpi / 72.0f; + dpiScaleLayout = dpi / 96.0f; } return InitResources(style.label_font_face, style.label_font_point, style.font_face, style.font_point, @@ -265,8 +265,8 @@ HRESULT DirectWriteResources::InitResources(const UIStyle& style, } void weasel::DirectWriteResources::SetDpi(const UINT& dpi) { - dpiScaleX_ = dpi / 72.0f; - dpiScaleY_ = dpi / 72.0f; + dpiScaleFontPoint = dpi / 72.0f; + dpiScaleLayout = dpi / 96.0f; pPreeditTextFormat.Reset(); pTextFormat.Reset(); diff --git a/WeaselUI/FullScreenLayout.cpp b/WeaselUI/FullScreenLayout.cpp index 9c86db40f..a5744dc22 100644 --- a/WeaselUI/FullScreenLayout.cpp +++ b/WeaselUI/FullScreenLayout.cpp @@ -92,17 +92,18 @@ bool FullScreenLayout::AdjustFontPoint(CDCHandle dc, int fontPointComment; if (pDWR->pLabelTextFormat != NULL) - fontPointLabel = - (int)(pDWR->pLabelTextFormat->GetFontSize() / pDWR->dpiScaleX_); + fontPointLabel = (int)(pDWR->pLabelTextFormat->GetFontSize() / + pDWR->dpiScaleFontPoint); else fontPointLabel = 0; if (pDWR->pTextFormat != NULL) - fontPoint = (int)(pDWR->pTextFormat->GetFontSize() / pDWR->dpiScaleX_); + fontPoint = + (int)(pDWR->pTextFormat->GetFontSize() / pDWR->dpiScaleFontPoint); else fontPoint = 0; if (pDWR->pCommentTextFormat != NULL) - fontPointComment = - (int)(pDWR->pCommentTextFormat->GetFontSize() / pDWR->dpiScaleX_); + fontPointComment = (int)(pDWR->pCommentTextFormat->GetFontSize() / + pDWR->dpiScaleFontPoint); else fontPointComment = 0; CSize sz = m_layout->GetContentSize(); diff --git a/WeaselUI/FullScreenLayout.h b/WeaselUI/FullScreenLayout.h index aee24f4d0..27c43d5c1 100644 --- a/WeaselUI/FullScreenLayout.h +++ b/WeaselUI/FullScreenLayout.h @@ -9,8 +9,9 @@ class FullScreenLayout : public StandardLayout { const Context& context, const Status& status, const CRect& inputPos, - Layout* layout) - : StandardLayout(style, context, status), + Layout* layout, + PDWR pDWR) + : StandardLayout(style, context, status, pDWR), mr_inputPos(inputPos), m_layout(layout) {} virtual ~FullScreenLayout() { delete m_layout; } diff --git a/WeaselUI/HorizontalLayout.h b/WeaselUI/HorizontalLayout.h index eb5110ec4..11eb31dc4 100644 --- a/WeaselUI/HorizontalLayout.h +++ b/WeaselUI/HorizontalLayout.h @@ -7,8 +7,9 @@ class HorizontalLayout : public StandardLayout { public: HorizontalLayout(const UIStyle& style, const Context& context, - const Status& status) - : StandardLayout(style, context, status) {} + const Status& status, + PDWR pDWR) + : StandardLayout(style, context, status, pDWR) {} virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); }; }; // namespace weasel diff --git a/WeaselUI/Layout.cpp b/WeaselUI/Layout.cpp index 559957607..60b60b4d7 100644 --- a/WeaselUI/Layout.cpp +++ b/WeaselUI/Layout.cpp @@ -4,7 +4,8 @@ using namespace weasel; Layout::Layout(const UIStyle& style, const Context& context, - const Status& status) + const Status& status, + PDWR pDWR) : _style(style), _context(context), _status(status), @@ -13,15 +14,35 @@ Layout::Layout(const UIStyle& style, labels(_context.cinfo.labels), id(_context.cinfo.highlighted), candidates_count((int)candidates.size()), - real_margin_x((abs(_style.margin_x) > _style.hilite_padding_x) - ? abs(_style.margin_x) - : _style.hilite_padding_x), - real_margin_y((abs(_style.margin_y) > _style.hilite_padding_y) - ? abs(_style.margin_y) - : _style.hilite_padding_y), labelFontValid(!!(_style.label_font_point > 0)), textFontValid(!!(_style.font_point > 0)), cmtFontValid(!!(_style.comment_font_point > 0)) { + if (pDWR) { + float scale = pDWR->dpiScaleLayout; + _style.min_width = (int)(_style.min_width * scale); + _style.min_height = (int)(_style.min_height * scale); + _style.max_width = (int)(_style.max_width * scale); + _style.max_height = (int)(_style.max_height * scale); + _style.border = (int)(_style.border * scale); + _style.margin_x = (int)(_style.margin_x * scale); + _style.margin_y = (int)(_style.margin_y * scale); + _style.spacing = (int)(_style.spacing * scale); + _style.candidate_spacing = (int)(_style.candidate_spacing * scale); + _style.hilite_spacing = (int)(_style.hilite_spacing * scale); + _style.hilite_padding_x = (int)(_style.hilite_padding_x * scale); + _style.hilite_padding_y = (int)(_style.hilite_padding_y * scale); + _style.round_corner = (int)(_style.round_corner * scale); + _style.round_corner_ex = (int)(_style.round_corner_ex * scale); + _style.shadow_radius = (int)(_style.shadow_radius * scale); + _style.shadow_offset_x = (int)(_style.shadow_offset_x * scale); + _style.shadow_offset_y = (int)(_style.shadow_offset_y * scale); + } + real_margin_x = ((abs(_style.margin_x) > _style.hilite_padding_x) + ? abs(_style.margin_x) + : _style.hilite_padding_x); + real_margin_y = ((abs(_style.margin_y) > _style.hilite_padding_y) + ? abs(_style.margin_y) + : _style.hilite_padding_y); offsetX = offsetY = 0; if (_style.shadow_radius != 0) { offsetX = abs(_style.shadow_offset_x) + _style.shadow_radius * 2; diff --git a/WeaselUI/Layout.h b/WeaselUI/Layout.h index f363e8ed5..0e19fd378 100644 --- a/WeaselUI/Layout.h +++ b/WeaselUI/Layout.h @@ -64,7 +64,10 @@ struct IsToRoundStruct { class Layout { public: - Layout(const UIStyle& style, const Context& context, const Status& status); + Layout(const UIStyle& style, + const Context& context, + const Status& status, + PDWR pDWR); virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL) = 0; /* All points in this class is based on the content area */ @@ -104,9 +107,11 @@ class Layout { int mark_width = 4; int mark_gap = 8; int mark_height = 0; + int real_margin_x; + int real_margin_y; + UIStyle _style; protected: - const UIStyle& _style; const Context& _context; const Status& _status; const std::vector& candidates; @@ -114,8 +119,6 @@ class Layout { const std::vector& labels; const int& id; const int candidates_count; - const int real_margin_x; - const int real_margin_y; const int labelFontValid; const int textFontValid; const int cmtFontValid; diff --git a/WeaselUI/StandardLayout.h b/WeaselUI/StandardLayout.h index 9fd504f56..b16cc05ae 100644 --- a/WeaselUI/StandardLayout.h +++ b/WeaselUI/StandardLayout.h @@ -14,8 +14,9 @@ class StandardLayout : public Layout { public: StandardLayout(const UIStyle& style, const Context& context, - const Status& status) - : Layout(style, context, status) {} + const Status& status, + PDWR pDWR) + : Layout(style, context, status, pDWR) {} /* Layout */ diff --git a/WeaselUI/VHorizontalLayout.h b/WeaselUI/VHorizontalLayout.h index 140a34a97..66937e8cc 100644 --- a/WeaselUI/VHorizontalLayout.h +++ b/WeaselUI/VHorizontalLayout.h @@ -7,8 +7,9 @@ class VHorizontalLayout : public StandardLayout { public: VHorizontalLayout(const UIStyle& style, const Context& context, - const Status& status) - : StandardLayout(style, context, status) {} + const Status& status, + PDWR pDWR) + : StandardLayout(style, context, status, pDWR) {} virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); private: diff --git a/WeaselUI/VerticalLayout.h b/WeaselUI/VerticalLayout.h index baed528e5..e4f85ee25 100644 --- a/WeaselUI/VerticalLayout.h +++ b/WeaselUI/VerticalLayout.h @@ -7,8 +7,9 @@ class VerticalLayout : public StandardLayout { public: VerticalLayout(const UIStyle& style, const Context& context, - const Status& status) - : StandardLayout(style, context, status) {} + const Status& status, + PDWR pDWR) + : StandardLayout(style, context, status, pDWR) {} virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); }; }; // namespace weasel diff --git a/WeaselUI/WeaselPanel.cpp b/WeaselUI/WeaselPanel.cpp index 8f67763ad..fbdca4563 100644 --- a/WeaselUI/WeaselPanel.cpp +++ b/WeaselUI/WeaselPanel.cpp @@ -80,8 +80,10 @@ WeaselPanel::WeaselPanel(weasel::UI& ui) HMONITOR hMonitor = MonitorFromRect(m_inputPos, MONITOR_DEFAULTTONEAREST); UINT dpiX = 96, dpiY = 96; - if (hMonitor) + if (hMonitor) { GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + m_hMonitor = hMonitor; + } dpi = dpiX; _InitFontRes(); m_ostyle = m_style; @@ -108,19 +110,19 @@ void WeaselPanel::_CreateLayout() { Layout* layout = NULL; if (m_style.layout_type == UIStyle::LAYOUT_VERTICAL_TEXT) { - layout = new VHorizontalLayout(m_style, m_ctx, m_status); + layout = new VHorizontalLayout(m_style, m_ctx, m_status, pDWR); } else { if (m_style.layout_type == UIStyle::LAYOUT_VERTICAL || m_style.layout_type == UIStyle::LAYOUT_VERTICAL_FULLSCREEN) { - layout = new VerticalLayout(m_style, m_ctx, m_status); + layout = new VerticalLayout(m_style, m_ctx, m_status, pDWR); } else if (m_style.layout_type == UIStyle::LAYOUT_HORIZONTAL || m_style.layout_type == UIStyle::LAYOUT_HORIZONTAL_FULLSCREEN) { - layout = new HorizontalLayout(m_style, m_ctx, m_status); + layout = new HorizontalLayout(m_style, m_ctx, m_status, pDWR); } if (IS_FULLSCREENLAYOUT(m_style)) { - layout = - new FullScreenLayout(m_style, m_ctx, m_status, m_inputPos, layout); + layout = new FullScreenLayout(m_style, m_ctx, m_status, m_inputPos, + layout, pDWR); } } m_layout = layout; @@ -139,7 +141,8 @@ void WeaselPanel::Refresh() { (m_ctx.empty() && should_show_icon); // show schema menu status: schema_id == L".default" bool show_schema_menu = m_status.schema_id == L".default"; - bool margin_negative = (m_style.margin_x < 0 || m_style.margin_y < 0); + bool margin_negative = + (DPI_SCALE(m_style.margin_x) < 0 || DPI_SCALE(m_style.margin_y) < 0); // when to hide_cadidates? // 1. margin_negative, and not in show tips mode( ascii switching / half-full // switching / simp-trad switching / error tips), and not in schema menu @@ -185,6 +188,7 @@ void WeaselPanel::_InitFontRes(bool forced) { } m_ostyle = m_style; dpi = dpiX; + dpiScaleLayout = (float)dpi / 96.0f; } static HBITMAP CopyDCToBitmap(HDC hDC, LPRECT lpRect) { @@ -272,7 +276,8 @@ LRESULT WeaselPanel::OnLeftClickedUp(UINT uMsg, CRect rect = m_layout->GetCandidateRect((int)m_ctx.cinfo.highlighted); if (m_istorepos) rect.OffsetRect(0, m_offsetys[m_ctx.cinfo.highlighted]); - rect.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rect.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); if (rect.PtInRect(point)) { size_t i = m_ctx.cinfo.highlighted; if (_UICallback) { @@ -306,32 +311,36 @@ LRESULT WeaselPanel::OnLeftClickedDown(UINT uMsg, CRect recth = m_layout->GetCandidateRect((int)m_ctx.cinfo.highlighted); if (m_istorepos) recth.OffsetRect(0, m_offsetys[m_ctx.cinfo.highlighted]); - recth.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + recth.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); // capture widow if (recth.PtInRect(point)) _CaptureRect(recth); else { // if shadow_color transparent, decrease the capture rectangle size if (COLORTRANSPARENT(m_style.shadow_color) && - m_style.shadow_radius != 0) { + DPI_SCALE(m_style.shadow_radius) != 0) { CRect crc(rcw); - int shadow_gap = - (m_style.shadow_offset_x == 0 && m_style.shadow_offset_y == 0) - ? 2 * m_style.shadow_radius - : m_style.shadow_radius + m_style.shadow_radius / 2; - int ofx = m_style.hilite_padding_x + abs(m_style.shadow_offset_x) + + int shadow_gap = (DPI_SCALE(m_style.shadow_offset_x) == 0 && + DPI_SCALE(m_style.shadow_offset_y) == 0) + ? 2 * DPI_SCALE(m_style.shadow_radius) + : DPI_SCALE(m_style.shadow_radius) + + DPI_SCALE(m_style.shadow_radius) / 2; + int ofx = DPI_SCALE(m_style.hilite_padding_x) + + abs(DPI_SCALE(m_style.shadow_offset_x)) + shadow_gap > - abs(m_style.margin_x) - ? m_style.hilite_padding_x + - abs(m_style.shadow_offset_x) + shadow_gap - - abs(m_style.margin_x) + abs(DPI_SCALE(m_style.margin_x)) + ? DPI_SCALE(m_style.hilite_padding_x) + + abs(DPI_SCALE(m_style.shadow_offset_x)) + + shadow_gap - abs(DPI_SCALE(m_style.margin_x)) : 0; - int ofy = m_style.hilite_padding_y + abs(m_style.shadow_offset_y) + + int ofy = DPI_SCALE(m_style.hilite_padding_y) + + abs(DPI_SCALE(m_style.shadow_offset_y)) + shadow_gap > - abs(m_style.margin_y) - ? m_style.hilite_padding_y + - abs(m_style.shadow_offset_y) + shadow_gap - - abs(m_style.margin_y) + abs(DPI_SCALE(m_style.margin_y)) + ? DPI_SCALE(m_style.hilite_padding_y) + + abs(DPI_SCALE(m_style.shadow_offset_y)) + + shadow_gap - abs(DPI_SCALE(m_style.margin_y)) : 0; crc.DeflateRect(m_layout->offsetX - ofx, m_layout->offsetY - ofy); _CaptureRect(crc); @@ -376,7 +385,8 @@ LRESULT WeaselPanel::OnLeftClickedDown(UINT uMsg, CRect rect = m_layout->GetCandidateRect((int)i); if (m_istorepos) rect.OffsetRect(0, m_offsetys[i]); - rect.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rect.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); if (rect.PtInRect(point)) { bar_scale_ = 0.8f; // modify highlighted @@ -435,7 +445,8 @@ LRESULT WeaselPanel::OnMouseMove(UINT uMsg, CRect rect = m_layout->GetCandidateRect((int)i); if (m_istorepos) rect.OffsetRect(0, m_offsetys[i]); - rect.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rect.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); if (rect.PtInRect(point)) { if (i != m_ctx.cinfo.highlighted) { if (m_style.hover_type == UIStyle::HoverType::HILITE) { @@ -486,7 +497,8 @@ void WeaselPanel::_HighlightText(CDCHandle& dc, NOT_FULLSCREENLAYOUT(m_style)) hiliteBackPath = new GraphicsRoundRectPath( rc, - m_style.round_corner_ex - (m_style.border % 2 ? m_style.border / 2 : 0), + DPI_SCALE(m_style.round_corner_ex) - + (DPI_SCALE(m_style.border) % 2 ? DPI_SCALE(m_style.border) / 2 : 0), rd.IsTopLeftNeedToRound, rd.IsTopRightNeedToRound, rd.IsBottomRightNeedToRound, rd.IsBottomLeftNeedToRound); else // background or current candidate background not out of window @@ -494,12 +506,12 @@ void WeaselPanel::_HighlightText(CDCHandle& dc, hiliteBackPath = new GraphicsRoundRectPath(rc, radius); // 必须shadow_color都是非完全透明色才做绘制, 全屏状态不绘制阴影保证响应速度 - if (m_style.shadow_radius && COLORNOTTRANSPARENT(shadowColor) && + if (DPI_SCALE(m_style.shadow_radius) && COLORNOTTRANSPARENT(shadowColor) && NOT_FULLSCREENLAYOUT(m_style)) { - CRect rect(blurMarginX + m_style.shadow_offset_x, - blurMarginY + m_style.shadow_offset_y, - rc.Width() + blurMarginX + m_style.shadow_offset_x, - rc.Height() + blurMarginY + m_style.shadow_offset_y); + CRect rect(blurMarginX + DPI_SCALE(m_style.shadow_offset_x), + blurMarginY + DPI_SCALE(m_style.shadow_offset_y), + rc.Width() + blurMarginX + DPI_SCALE(m_style.shadow_offset_x), + rc.Height() + blurMarginY + DPI_SCALE(m_style.shadow_offset_y)); BYTE r = GetRValue(shadowColor); BYTE g = GetGValue(shadowColor); BYTE b = GetBValue(shadowColor); @@ -513,16 +525,17 @@ void WeaselPanel::_HighlightText(CDCHandle& dc, Gdiplus::Graphics g_shadow(pBitmapDropShadow); g_shadow.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality); // dropshadow, draw a roundrectangle to blur - if (m_style.shadow_offset_x != 0 || m_style.shadow_offset_y != 0) { + if (DPI_SCALE(m_style.shadow_offset_x) != 0 || + DPI_SCALE(m_style.shadow_offset_y) != 0) { GraphicsRoundRectPath shadow_path(rect, radius); Gdiplus::SolidBrush shadow_brush(shadow_color); g_shadow.FillPath(&shadow_brush, &shadow_path); } // round shadow, draw multilines as base round line else { - int step = alpha / m_style.shadow_radius / 2; + int step = alpha / DPI_SCALE(m_style.shadow_radius) / 2; Gdiplus::Pen pen_shadow(shadow_color, (Gdiplus::REAL)1); - for (int i = 0; i < m_style.shadow_radius; i++) { + for (int i = 0; i < DPI_SCALE(m_style.shadow_radius); i++) { GraphicsRoundRectPath round_path(rect, radius + 1 + i); g_shadow.DrawPath(&pen_shadow, &round_path); shadow_color = Gdiplus::Color::MakeARGB(alpha - i * step, r, g, b); @@ -530,8 +543,8 @@ void WeaselPanel::_HighlightText(CDCHandle& dc, rect.InflateRect(1, 1); } } - DoGaussianBlur(pBitmapDropShadow, (float)m_style.shadow_radius, - (float)m_style.shadow_radius); + DoGaussianBlur(pBitmapDropShadow, (float)DPI_SCALE(m_style.shadow_radius), + (float)DPI_SCALE(m_style.shadow_radius)); g_back.DrawImage(pBitmapDropShadow, rc.left - blurMarginX, rc.top - blurMarginY); @@ -548,12 +561,13 @@ void WeaselPanel::_HighlightText(CDCHandle& dc, g_back.FillPath(&back_brush, hiliteBackPath); } // draw border, for bordercolor not transparent and border valid - if (COLORNOTTRANSPARENT(bordercolor) && m_style.border > 0) { + if (COLORNOTTRANSPARENT(bordercolor) && DPI_SCALE(m_style.border) > 0) { Gdiplus::Color border_color = GDPCOLOR_FROM_COLORREF(bordercolor); - Gdiplus::Pen gPenBorder(border_color, (Gdiplus::REAL)m_style.border); + Gdiplus::Pen gPenBorder(border_color, + (Gdiplus::REAL)DPI_SCALE(m_style.border)); // candidate window border if (type == BackType::BACKGROUND) { - GraphicsRoundRectPath bgPath(rc, m_style.round_corner_ex); + GraphicsRoundRectPath bgPath(rc, DPI_SCALE(m_style.round_corner_ex)); g_back.DrawPath(&gPenBorder, &bgPath); } else if (type != BackType::TEXT) // hilited_candidate_border / candidate_border @@ -597,9 +611,9 @@ bool WeaselPanel::_DrawPreedit(const Text& text, _TextOut(rc_before, str_before.c_str(), str_before.length(), m_style.text_color, txtFormat); if (m_style.layout_type == UIStyle::LAYOUT_VERTICAL_TEXT) - y += beforeSz.cy + m_style.hilite_spacing; + y += beforeSz.cy + DPI_SCALE(m_style.hilite_spacing); else - x += beforeSz.cx + m_style.hilite_spacing; + x += beforeSz.cx + DPI_SCALE(m_style.hilite_spacing); } { // zzz[yyy] @@ -614,9 +628,9 @@ bool WeaselPanel::_DrawPreedit(const Text& text, _TextOut(rc_hi, str_highlight.c_str(), str_highlight.length(), m_style.hilited_text_color, txtFormat); if (m_style.layout_type == UIStyle::LAYOUT_VERTICAL_TEXT) - y += rc_hi.Height() + m_style.hilite_spacing; + y += rc_hi.Height() + DPI_SCALE(m_style.hilite_spacing); else - x += rc_hi.Width() + m_style.hilite_spacing; + x += rc_hi.Width() + DPI_SCALE(m_style.hilite_spacing); } if (range.end < static_cast(t.length())) { // zzz[yyy]xxx @@ -680,9 +694,9 @@ bool WeaselPanel::_DrawPreeditBack(const Text& text, if (range.start > 0) { if (m_style.layout_type == UIStyle::LAYOUT_VERTICAL_TEXT) - y += beforeSz.cy + m_style.hilite_spacing; + y += beforeSz.cy + DPI_SCALE(m_style.hilite_spacing); else - x += beforeSz.cx + m_style.hilite_spacing; + x += beforeSz.cx + DPI_SCALE(m_style.hilite_spacing); } { CRect rc_hi; @@ -702,15 +716,16 @@ bool WeaselPanel::_DrawPreeditBack(const Text& text, rc_hi.InflateRect((STATUS_ICON_SIZE - hilitedSz.cx) / 2, 0); } - rc_hi.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rc_hi.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); IsToRoundStruct rd = m_layout->GetTextRoundInfo(); if (m_istorepos) { std::swap(rd.IsTopLeftNeedToRound, rd.IsBottomLeftNeedToRound); std::swap(rd.IsTopRightNeedToRound, rd.IsBottomRightNeedToRound); } _HighlightText(dc, rc_hi, m_style.hilited_back_color, - m_style.hilited_shadow_color, m_style.round_corner, - BackType::TEXT, rd); + m_style.hilited_shadow_color, + DPI_SCALE(m_style.round_corner), BackType::TEXT, rd); } } drawn = true; @@ -748,9 +763,10 @@ bool WeaselPanel::_DrawCandidates(CDCHandle& dc, bool back) { rect.OffsetRect(0, m_offsetys[i]); ReconfigRoundInfo(rd, i, m_candidateCount); } - rect.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rect.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); _HighlightText(dc, rect, 0x00000000, m_style.candidate_shadow_color, - m_style.round_corner, bkType, rd); + DPI_SCALE(m_style.round_corner), bkType, rd); drawn = true; } } @@ -766,9 +782,10 @@ bool WeaselPanel::_DrawCandidates(CDCHandle& dc, bool back) { rect.OffsetRect(0, m_offsetys[i]); ReconfigRoundInfo(rd, i, m_candidateCount); } - rect.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rect.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); _HighlightText(dc, rect, m_style.candidate_back_color, 0x00000000, - m_style.round_corner, bkType, rd, + DPI_SCALE(m_style.round_corner), bkType, rd, m_style.candidate_border_color); drawn = true; } @@ -781,11 +798,12 @@ bool WeaselPanel::_DrawCandidates(CDCHandle& dc, bool back) { rect.OffsetRect(0, m_offsetys[m_hoverIndex]); ReconfigRoundInfo(rd, m_hoverIndex, m_candidateCount); } - rect.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rect.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); _HighlightText(dc, rect, HALF_ALPHA_COLOR(m_style.hilited_candidate_back_color), HALF_ALPHA_COLOR(m_style.hilited_candidate_shadow_color), - m_style.round_corner, bkType, rd, + DPI_SCALE(m_style.round_corner), bkType, rd, HALF_ALPHA_COLOR(m_style.hilited_candidate_border_color)); } // draw highlighted background and shadow @@ -797,17 +815,19 @@ bool WeaselPanel::_DrawCandidates(CDCHandle& dc, bool back) { rect.OffsetRect(0, m_offsetys[m_ctx.cinfo.highlighted]); ReconfigRoundInfo(rd, m_ctx.cinfo.highlighted, m_candidateCount); } - rect.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rect.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); _HighlightText(dc, rect, m_style.hilited_candidate_back_color, markSt ? m_style.hilited_candidate_shadow_color : 0, - m_style.round_corner, bkType, rd, + DPI_SCALE(m_style.round_corner), bkType, rd, m_style.hilited_candidate_border_color); if (m_style.mark_text.empty() && COLORNOTTRANSPARENT(m_style.hilited_mark_color)) { - int height = min(rect.Height() - m_style.hilite_padding_y * 2, - rect.Height() - m_style.round_corner * 2); - int width = min(rect.Width() - m_style.hilite_padding_x * 2, - rect.Width() - m_style.round_corner * 2); + int height = + min(rect.Height() - DPI_SCALE(m_style.hilite_padding_y) * 2, + rect.Height() - DPI_SCALE(m_style.round_corner) * 2); + int width = min(rect.Width() - DPI_SCALE(m_style.hilite_padding_x) * 2, + rect.Width() - DPI_SCALE(m_style.round_corner) * 2); width = min(width, static_cast(rect.Width() * 0.618)); height = min(height, static_cast(rect.Height() * 0.618)); if (bar_scale_ != 1.0f) { @@ -887,7 +907,8 @@ bool WeaselPanel::_DrawCandidates(CDCHandle& dc, bool back) { CRect rc = m_layout->GetHighlightRect(); if (m_istorepos) rc.OffsetRect(0, m_offsetys[m_ctx.cinfo.highlighted]); - rc.InflateRect(m_style.hilite_padding_x, m_style.hilite_padding_y); + rc.InflateRect(DPI_SCALE(m_style.hilite_padding_x), + DPI_SCALE(m_style.hilite_padding_y)); int vgap = m_layout->mark_height ? (rc.Height() - m_layout->mark_height) / 2 : 0; @@ -895,15 +916,17 @@ bool WeaselPanel::_DrawCandidates(CDCHandle& dc, bool back) { m_layout->mark_width ? (rc.Width() - m_layout->mark_width) / 2 : 0; CRect hlRc; if (m_style.layout_type == UIStyle::LAYOUT_VERTICAL_TEXT) - hlRc = - CRect(rc.left + hgap, rc.top + m_style.hilite_padding_y, - rc.left + hgap + m_layout->mark_width, - rc.top + m_style.hilite_padding_y + m_layout->mark_height); + hlRc = CRect(rc.left + hgap, + rc.top + DPI_SCALE(m_style.hilite_padding_y), + rc.left + hgap + m_layout->mark_width, + rc.top + DPI_SCALE(m_style.hilite_padding_y) + + m_layout->mark_height); else - hlRc = - CRect(rc.left + m_style.hilite_padding_x, rc.top + vgap, - rc.left + m_style.hilite_padding_x + m_layout->mark_width, - rc.bottom - vgap); + hlRc = CRect(rc.left + DPI_SCALE(m_style.hilite_padding_x), + rc.top + vgap, + rc.left + DPI_SCALE(m_style.hilite_padding_x) + + m_layout->mark_width, + rc.bottom - vgap); _TextOut(hlRc, m_style.mark_text.c_str(), m_style.mark_text.length(), m_style.hilited_mark_color, pDWR->pTextFormat.Get()); } @@ -956,7 +979,7 @@ void WeaselPanel::DoPaint(CDCHandle dc) { btmys[m_candidateCount - i - 1] - base_gap - rects[i].bottom; else m_offsetys[i] = (rects[i - 1].top + m_offsetys[i - 1] - - m_style.candidate_spacing) - + DPI_SCALE(m_style.candidate_spacing)) - rects[i].bottom; } delete[] rects; @@ -966,9 +989,8 @@ void WeaselPanel::DoPaint(CDCHandle dc) { if ((!m_ctx.empty() && !m_style.inline_preedit) || (m_style.inline_preedit && (m_candidateCount || !m_ctx.aux.empty()))) { CRect backrc = m_layout->GetContentRect(); - // if (!m_style.border) backrc.InflateRect(1,1); _HighlightText(memDC, backrc, m_style.back_color, m_style.shadow_color, - m_style.round_corner_ex, BackType::BACKGROUND, + DPI_SCALE(m_style.round_corner_ex), BackType::BACKGROUND, IsToRoundStruct(), m_style.border_color); } if (!m_ctx.aux.str.empty()) { @@ -1089,6 +1111,7 @@ LRESULT WeaselPanel::OnDpiChanged(UINT uMsg, void WeaselPanel::MoveTo(RECT const& rc) { if (!m_layout) return; // avoid handling nullptr in _RepositionWindow + m_redraw_by_monitor_change = false; // if ascii_tip_follow_cursor set, move tip icon to mouse cursor if (m_style.ascii_tip_follow_cursor && m_ctx.empty() && (!m_status.composing) && m_layout->ShouldDisplayStatusIcon()) { @@ -1113,7 +1136,7 @@ void WeaselPanel::MoveTo(RECT const& rc) { // m_istorepos status changed by _RepositionWindow, or tips to show, // redrawing is required if (m_istorepos != m_istorepos_buf || !m_ctx.aux.empty() || - m_layout->ShouldDisplayStatusIcon()) + m_layout->ShouldDisplayStatusIcon() || m_redraw_by_monitor_change) RedrawWindow(); } } @@ -1128,6 +1151,10 @@ void WeaselPanel::_RepositionWindow(const bool& adj) { if (GetMonitorInfo(hMonitor, &info)) { rcWorkArea = info.rcWork; } + if (hMonitor != m_hMonitor) { + m_hMonitor = hMonitor; + m_redraw_by_monitor_change = true; + } } RECT rcWindow; GetWindowRect(&rcWindow); @@ -1138,13 +1165,13 @@ void WeaselPanel::_RepositionWindow(const bool& adj) { rcWorkArea.bottom -= height; int x = m_inputPos.left; int y = m_inputPos.bottom; - if (m_style.shadow_radius) { - x -= - (m_style.shadow_offset_x >= 0 || COLORTRANSPARENT(m_style.shadow_color)) - ? m_layout->offsetX - : (m_layout->offsetX / 2); + if (DPI_SCALE(m_style.shadow_radius)) { + x -= (DPI_SCALE(m_style.shadow_offset_x) >= 0 || + COLORTRANSPARENT(m_style.shadow_color)) + ? m_layout->offsetX + : (m_layout->offsetX / 2); if (adj) - y -= (m_style.shadow_offset_y > 0 || + y -= (DPI_SCALE(m_style.shadow_offset_y) > 0 || COLORTRANSPARENT(m_style.shadow_color)) ? m_layout->offsetY : (m_layout->offsetY / 2); @@ -1153,7 +1180,7 @@ void WeaselPanel::_RepositionWindow(const bool& adj) { if (m_style.layout_type == UIStyle::LAYOUT_VERTICAL_TEXT && !m_style.vertical_text_left_to_right) { x += m_layout->offsetX - width; - if (m_style.shadow_offset_x < 0) + if (DPI_SCALE(m_style.shadow_offset_x) < 0) x += m_layout->offsetX; } if (adj) @@ -1167,12 +1194,13 @@ void WeaselPanel::_RepositionWindow(const bool& adj) { if (!m_sticky) m_sticky = true; y = m_inputPos.top - height - 6; // over workarea bottom - if (m_style.shadow_radius && m_style.shadow_offset_y > 0) - y -= m_style.shadow_offset_y; + if (DPI_SCALE(m_style.shadow_radius) && + DPI_SCALE(m_style.shadow_offset_y) > 0) + y -= DPI_SCALE(m_style.shadow_offset_y); m_istorepos = (m_style.vertical_auto_reverse && m_style.layout_type == UIStyle::LAYOUT_VERTICAL); - if (m_style.shadow_radius > 0) - y += (m_style.shadow_offset_y < 0 || + if (DPI_SCALE(m_style.shadow_radius) > 0) + y += (DPI_SCALE(m_style.shadow_offset_y) < 0 || COLORTRANSPARENT(m_style.shadow_color)) ? m_layout->offsetY : (m_layout->offsetY / 2); diff --git a/WeaselUI/WeaselPanel.h b/WeaselUI/WeaselPanel.h index 4670d45b2..512d73255 100644 --- a/WeaselUI/WeaselPanel.h +++ b/WeaselUI/WeaselPanel.h @@ -73,6 +73,10 @@ class WeaselPanel static UINT_PTR ptimer; private: + template + int DPI_SCALE(T t) { + return (int)(t * dpiScaleLayout); + } void _InitFontRes(bool forced = false); void _CaptureRect(CRect& rect); bool m_mouse_entry = false; @@ -137,5 +141,8 @@ class WeaselPanel std::function& _UICallback; float bar_scale_ = 1.0; + float dpiScaleLayout = 1.0f; int m_hoverIndex = -1; + HMONITOR m_hMonitor = NULL; + bool m_redraw_by_monitor_change = false; }; diff --git a/include/WeaselUI.h b/include/WeaselUI.h index 6efd291a5..9a5382a69 100644 --- a/include/WeaselUI.h +++ b/include/WeaselUI.h @@ -150,7 +150,7 @@ class DirectWriteResources { void SetBrushColor(const D2D1_COLOR_F& color) { pBrush->SetColor(color); } void SetDpi(const UINT& dpi); - float dpiScaleX_, dpiScaleY_; + float dpiScaleFontPoint, dpiScaleLayout; ComPtr pD2d1Factory; ComPtr pDWFactory; ComPtr pRenderTarget;