Skip to content

Commit

Permalink
Eliminate playlist tabs and tab stack flickering
Browse files Browse the repository at this point in the history
This eliminates flickering when resizing the playlist tabs and tab stack panels by using double-buffered painting.

This applies to both light and dark modes.
  • Loading branch information
reupen committed Feb 18, 2022
1 parent 43941d1 commit f0415da
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 60 deletions.
16 changes: 9 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,30 @@
[#437](https://github.com/reupen/columns_ui/pull/437), [#438](https://github.com/reupen/columns_ui/pull/438),
[#439](https://github.com/reupen/columns_ui/pull/439), [#440](https://github.com/reupen/columns_ui/pull/440),
[#442](https://github.com/reupen/columns_ui/pull/442), [#444](https://github.com/reupen/columns_ui/pull/444),
[#445](https://github.com/reupen/columns_ui/pull/445)]
[#445](https://github.com/reupen/columns_ui/pull/445), [#451](https://github.com/reupen/columns_ui/pull/451)]

* The Filter search toolbar is now integrated with the Colours and fonts preferences page, and its font, foreground colour and background colour are now configurable. [[#424](https://github.com/reupen/columns_ui/pull/424)]

(Note that selection colours are not supported.)
* The status bar can now show the number of selected tracks. [[#450](https://github.com/reupen/columns_ui/pull/450)]

* Improvements were made to the status bar layout logic (including better DPI scaling). [[#432](https://github.com/reupen/columns_ui/pull/432)]

* The status bar playlist lock icon was replaced with the 🔒 character. [[#432](https://github.com/reupen/columns_ui/pull/432)]

* The default playback button icons were tweaked. This includes the removal of subtle glow effects. [[#435](https://github.com/reupen/columns_ui/pull/435)]

* The Filter search toolbar is now integrated with the Colours and fonts preferences page, and its font, foreground colour and background colour are now configurable. [[#424](https://github.com/reupen/columns_ui/pull/424)]

(Note that selection colours are not supported.)

* The filter search button icons were updated. [[#438](https://github.com/reupen/columns_ui/pull/438)]

* The default no-cover artwork image was updated. [[#437](https://github.com/reupen/columns_ui/pull/437)]

* The status bar playlist lock icon was replaced with the 🔒 character. [[#432](https://github.com/reupen/columns_ui/pull/432)]
* Flickering when resizing the Playlist tabs and Tab stack panels was eliminated. [[#451](https://github.com/reupen/columns_ui/pull/451)]

* The 'View/Show toolbars' menu item is now only shown if the shift key is held down when opening the View menu. [[#410](https://github.com/reupen/columns_ui/pull/410)]

* A warning was added under the 'Show toolbars' option in preferences. [[#410](https://github.com/reupen/columns_ui/pull/410)]

* The status bar can now show the number of selected tracks. [[#450](https://github.com/reupen/columns_ui/pull/450)]

### Bug fixes

* A problem where the playlist tabs panel had an incorrect maximum width or height was fixed. [[#449](https://github.com/reupen/columns_ui/pull/449)]
Expand Down
30 changes: 14 additions & 16 deletions foo_ui_columns/dark_mode_tabs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,16 @@ void handle_tab_control_paint(HWND wnd)
const auto active_item_brush = get_colour_brush_lazy(ColourID::TabControlActiveItemBackground, is_dark);

PAINTSTRUCT ps{};
const auto dc = wil::BeginPaint(wnd, &ps);
const auto _select_font = wil::SelectObject(dc.get(), GetWindowFont(wnd));
const auto _select_pen = wil::SelectObject(dc.get(), border_pen.get());
const auto paint_dc = wil::BeginPaint(wnd, &ps);
const auto buffered_dc = uih::BufferedDC(paint_dc.get(), ps.rcPaint);
const auto _select_font = wil::SelectObject(buffered_dc.get(), GetWindowFont(wnd));
const auto _select_pen = wil::SelectObject(buffered_dc.get(), border_pen.get());

SetTextColor(dc.get(), get_colour(ColourID::TabControlItemText, is_dark));
SetBkMode(dc.get(), TRANSPARENT);

RECT client_rect{};
GetClientRect(wnd, &client_rect);
SetTextColor(buffered_dc.get(), get_colour(ColourID::TabControlItemText, is_dark));
SetBkMode(buffered_dc.get(), TRANSPARENT);

if (ps.fErase)
FillRect(dc.get(), &client_rect, *get_colour_brush_lazy(ColourID::TabControlBackground, is_dark));
FillRect(buffered_dc.get(), &ps.rcPaint, *get_colour_brush_lazy(ColourID::TabControlBackground, is_dark));

for (auto&& [index, item] : ranges::views::enumerate(items)) {
const auto is_new_line = index == 0 || items[index - 1].rc.top != item.rc.top;
Expand Down Expand Up @@ -110,23 +108,23 @@ void handle_tab_control_paint(HWND wnd)

return *default_item_brush;
}();
FillRect(dc.get(), &item_rect, item_back_brush);
FillRect(buffered_dc.get(), &item_rect, item_back_brush);

MoveToEx(dc.get(), item_rect.right, item_rect.bottom, nullptr);
LineTo(dc.get(), item_rect.right, item_rect.top);
LineTo(dc.get(), item_rect.left, item_rect.top);
MoveToEx(buffered_dc.get(), item_rect.right, item_rect.bottom, nullptr);
LineTo(buffered_dc.get(), item_rect.right, item_rect.top);
LineTo(buffered_dc.get(), item_rect.left, item_rect.top);
if (is_new_line || item.is_active) {
LineTo(dc.get(), item_rect.left, item_rect.bottom);
LineTo(buffered_dc.get(), item_rect.left, item_rect.bottom);
}

SIZE sz{};
GetTextExtentPoint32(dc.get(), item.text.data(), gsl::narrow<int>(item.text.length()), &sz);
GetTextExtentPoint32(buffered_dc.get(), item.text.data(), gsl::narrow<int>(item.text.length()), &sz);

// Position using original rect, but shift up 1px if it's the active tab
const auto x = item.rc.left + (RECT_CX(item.rc) - sz.cx) / 2;
const auto y = item.rc.top + (RECT_CY(item.rc) - sz.cy) / 2 - (item.is_active ? 1_spx : 0);

ExtTextOut(dc.get(), x, y, ETO_CLIPPED, &item_rect, item.text.data(), item.text.length(), nullptr);
ExtTextOut(buffered_dc.get(), x, y, ETO_CLIPPED, &item_rect, item.text.data(), item.text.length(), nullptr);
}
}

Expand Down
14 changes: 5 additions & 9 deletions foo_ui_columns/playlist_tabs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,17 +259,13 @@ LRESULT WINAPI PlaylistTabs::hook(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_ERASEBKGND:
if (!colours::is_dark_mode_active())
break;

return FALSE;
case WM_PAINT: {
if (!colours::is_dark_mode_active())
break;

dark::handle_tab_control_paint(wnd);
case WM_PAINT:
if (colours::is_dark_mode_active())
dark::handle_tab_control_paint(wnd);
else
uih::paint_subclassed_window_with_buffering(wnd, tabproc);
return 0;
}
case WM_GETDLGCODE:
return DLGC_WANTALLKEYS;
case WM_KEYDOWN: {
Expand Down
14 changes: 5 additions & 9 deletions foo_ui_columns/splitter_tabs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -915,17 +915,13 @@ LRESULT WINAPI TabStackPanel::on_hooked_message(HWND wnd, UINT msg, WPARAM wp, L
{
switch (msg) {
case WM_ERASEBKGND:
if (!colours::is_dark_mode_active())
break;

return FALSE;
case WM_PAINT: {
if (!colours::is_dark_mode_active())
break;

dark::handle_tab_control_paint(wnd);
case WM_PAINT:
if (colours::is_dark_mode_active())
dark::handle_tab_control_paint(wnd);
else
uih::paint_subclassed_window_with_buffering(wnd, m_tab_proc);
return 0;
}
case WM_GETDLGCODE:
return DLGC_WANTALLKEYS;
case WM_KEYDOWN: {
Expand Down
36 changes: 18 additions & 18 deletions foo_ui_columns/status_pane_msgproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
}
} break;
case WM_PAINT: {
uih::PaintScope ps(wnd);
uih::MemoryDC dc(ps);
PAINTSTRUCT ps{};
const auto paint_dc = wil::BeginPaint(wnd, &ps);
uih::BufferedDC dc(paint_dc.get(), ps.rcPaint);

const auto font_height = uGetFontHeight(m_font.get());
const auto line_height = font_height + uih::scale_dpi_value(3);
Expand All @@ -97,7 +98,7 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
RECT rc_volume{};
GetRelativeRect(m_volume_control.get_wnd(), wnd, &rc_volume);

render_background(dc, rc_client);
render_background(dc.get(), rc_client);

RECT rc_text{rc_client};
rc_text.right = rc_volume.left - uih::scale_dpi_value(20);
Expand All @@ -110,11 +111,12 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
rc_line_2.top = rc_line_1.bottom;
rc_line_2.bottom = rc_line_2.top + line_height;

HFONT fnt_old = SelectFont(dc, m_font.get());
const auto _ = wil::SelectObject(dc.get(), m_font.get());

const char* placeholder = "999999999 items selected";
const auto default_text_colour = dark::get_system_colour(COLOR_BTNTEXT, colours::is_dark_mode_active());
int placeholder_len = get_text_width(dc, placeholder, strlen(placeholder)) + uih::scale_dpi_value(20);
int placeholder_len
= uih::get_text_width(dc.get(), placeholder, strlen(placeholder)) + uih::scale_dpi_value(20);

pfc::string8 items_text;
items_text << m_item_count << " item";
Expand All @@ -123,47 +125,45 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
if (m_selection)
items_text << " selected";

text_out_colours_tab(dc, items_text, -1, uih::scale_dpi_value(1), uih::scale_dpi_value(3), &rc_line_1, false,
default_text_colour, false, false, uih::ALIGN_LEFT);
text_out_colours_tab(dc.get(), items_text, -1, uih::scale_dpi_value(1), uih::scale_dpi_value(3), &rc_line_1,
false, default_text_colour, false, false, uih::ALIGN_LEFT);
if (m_item_count) {
pfc::string_formatter formatter;
text_out_colours_tab(dc, formatter << "Length: " << m_length_text, -1, uih::scale_dpi_value(1),
text_out_colours_tab(dc.get(), formatter << "Length: " << m_length_text, -1, uih::scale_dpi_value(1),
uih::scale_dpi_value(3), &rc_line_2, false, default_text_colour, false, false, uih::ALIGN_LEFT);
}

if (m_menu_active) {
{
RECT rc_item = rc_line_1;
text_out_colours_tab(dc, m_menu_text, -1, uih::scale_dpi_value(1) + placeholder_len,
text_out_colours_tab(dc.get(), m_menu_text, -1, uih::scale_dpi_value(1) + placeholder_len,
uih::scale_dpi_value(3), &rc_item, false, default_text_colour, false, false, uih::ALIGN_LEFT,
nullptr, true, true, nullptr);
}
} else {
placeholder = "Playing: ";
t_size placeholder2_len = get_text_width(dc, placeholder, strlen(placeholder));
t_size placeholder2_len = uih::get_text_width(dc.get(), placeholder, strlen(placeholder));

t_size now_playing_x_end = uih::scale_dpi_value(4) + placeholder_len + placeholder2_len;
{
RECT rc_item = rc_line_1;
// rc_item.right = 4 + placeholder_len + placeholder2_len;
text_out_colours_tab(dc, m_track_label, -1, uih::scale_dpi_value(4) + placeholder_len, 0, &rc_item,
false, default_text_colour, false, false, uih::ALIGN_LEFT, nullptr, true, true, nullptr);
text_out_colours_tab(dc.get(), m_track_label, -1, uih::scale_dpi_value(4) + placeholder_len, 0,
&rc_item, false, default_text_colour, false, false, uih::ALIGN_LEFT, nullptr, true, true, nullptr);
}
if (playing1.get_length()) {
pfc::string_list_impl playingstrings;
g_split_string_by_crlf(playing1.get_ptr(), playingstrings);
t_size lines = playingstrings.get_count();
if (lines)
text_out_colours_tab(dc, playingstrings[0], pfc_infinite, now_playing_x_end, 0, &rc_line_1, false,
default_text_colour, true, false, uih::ALIGN_LEFT);
text_out_colours_tab(dc.get(), playingstrings[0], pfc_infinite, now_playing_x_end, 0, &rc_line_1,
false, default_text_colour, true, false, uih::ALIGN_LEFT);
if (lines > 1)
text_out_colours_tab(dc, playingstrings[1], pfc_infinite, now_playing_x_end, 0, &rc_line_2, false,
default_text_colour, true, false, uih::ALIGN_LEFT);
text_out_colours_tab(dc.get(), playingstrings[1], pfc_infinite, now_playing_x_end, 0, &rc_line_2,
false, default_text_colour, true, false, uih::ALIGN_LEFT);
}
}

SelectFont(dc, fnt_old);

return 0;
}
}
Expand Down
2 changes: 1 addition & 1 deletion ui_helpers
Submodule ui_helpers updated 2 files
+10 −0 gdi.cpp
+17 −36 gdi.h

0 comments on commit f0415da

Please sign in to comment.