Starting with Win10, height of multiline edit controls no longer seems to be hardwired to a multiple of the font height (when larger than font height).
- Adapt the tests accordingly (detecting how to compute the expected height of a control). - Extend the ranges of the tested heights.
Note: - there may be another way to detect the model for height computation. - the range of heights tested stem from internal testing and is larger than existing testing. It could be reduced as a range, or picking values from a fixed set of values (if needed).
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=52152
Signed-off-by: Eric Pouech eric.pouech@gmail.com
From: Eric Pouech eric.pouech@gmail.com
Starting with Win10, height of multiline edit controls no longer seems to be hardwired to a multiple of the font height (when larger than font height).
- Adapt the tests accordingly (detecting how to compute the expected height of a control). - Extend the ranges of the tested heights.
Note: - there may be another way to detect the model for height computation. - the range of heights tested stem from internal testing and is larger than existing testing. It could be reduced as a range, or picking values from a fixed set of values (if needed).
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=52152
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/comctl32/tests/edit.c | 134 ++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 48 deletions(-)
diff --git a/dlls/comctl32/tests/edit.c b/dlls/comctl32/tests/edit.c index 91d16e044a0..dc301deab39 100644 --- a/dlls/comctl32/tests/edit.c +++ b/dlls/comctl32/tests/edit.c @@ -2073,30 +2073,75 @@ do { \ edit_pos_ok(test_left, format_rect.left - left_margin, left); \ } while(0)
-static void test_text_position_style(DWORD style) +/* Starting with Win10, multiline edit controls can have any value for height. + * Before, they always have a height which is a multiple of the font height. + * So detect which model we're running the tests on, and adjust the expected + * height accordingly. + */ + +static BOOL old_height_model; + +static DWORD compute_height(HWND hwedit, BOOL single_line, unsigned tmHeight, unsigned incr, unsigned limit) { - HWND hwEdit; - HFONT font, oldFont; - HDC dc; - TEXTMETRICA metrics; - INT b, bm, b2, b3; - BOOL xb, single_line = !(style & ES_MULTILINE); + if (single_line) return tmHeight; + if (incr >= limit) incr -= limit; + return old_height_model ? (tmHeight + incr) - ((tmHeight + incr) % tmHeight) : tmHeight + incr; +}
- b = GetSystemMetrics(SM_CYBORDER) + 1; - b2 = 2 * b; - b3 = 3 * b; - bm = b2 - 1; +static void get_font_bits(HFONT *font, TEXTMETRICA *metrics) +{ + HDC dc; + HFONT oldFont; + BOOL xb;
/* Get a stock font for which we can determine the metrics */ - font = GetStockObject(SYSTEM_FONT); - ok (font != NULL, "GetStockObject SYSTEM_FONT failed\n"); + *font = GetStockObject(SYSTEM_FONT); + ok (*font != NULL, "GetStockObject SYSTEM_FONT failed\n"); dc = GetDC(NULL); ok (dc != NULL, "GetDC() failed\n"); oldFont = SelectObject(dc, font); - xb = GetTextMetricsA(dc, &metrics); + xb = GetTextMetricsA(dc, metrics); ok (xb, "GetTextMetrics failed\n"); SelectObject(dc, oldFont); ReleaseDC(NULL, dc); +} + +static BOOL determine_height_model(void) +{ + HANDLE hwEdit; + HFONT font; + TEXTMETRICA metrics; + RECT format_rect; + BOOL ret = TRUE; + + get_font_bits(&font, &metrics); + hwEdit = create_child_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_VISIBLE, 0); + SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); + + set_client_height(hwEdit, metrics.tmHeight + 1); + SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); + + old_height_model = TRUE; + if (format_rect.bottom - format_rect.top == metrics.tmHeight + 1) + old_height_model = FALSE; + else + ret = format_rect.bottom - format_rect.top == metrics.tmHeight; + + destroy_child_editcontrol(hwEdit); + return ret; +} + +static void test_text_position_style(DWORD style) +{ + HWND hwEdit; + HFONT font; + TEXTMETRICA metrics; + INT b, b2, incr; + BOOL single_line = !(style & ES_MULTILINE); + + get_font_bits(&font, &metrics); + b = GetSystemMetrics(SM_CYBORDER) + 1; + b2 = 2 * b;
/* Windows' edit control has some bugs in multi-line mode: * - Sometimes the format rectangle doesn't get updated @@ -2112,41 +2157,36 @@ static void test_text_position_style(DWORD style) SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0); - check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0); - check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, 0), 0); destroy_child_editcontrol(hwEdit);
hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0); SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, incr >= b2 ? b : 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, b2), b); destroy_child_editcontrol(hwEdit);
hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE); SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, incr >= 2 ? 1 : 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, 2), 1); destroy_child_editcontrol(hwEdit);
hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE); SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, incr >= 2 ? 1 : 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, 2), 1); destroy_child_editcontrol(hwEdit);
@@ -2156,46 +2196,44 @@ static void test_text_position_style(DWORD style) SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0); - check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0); - check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, 0), 0); DestroyWindow(hwEdit);
hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0); SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b); - check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, incr >= b2 ? b : 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, b2), b); DestroyWindow(hwEdit);
hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE); SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, incr >= 2 ? 1 : 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, 2), 1); DestroyWindow(hwEdit);
hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE); SendMessageA(hwEdit, WM_SETFONT, (WPARAM) font, FALSE); if (single_line) check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1); - check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1); - check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1); + for (incr = 0; incr < 4 * metrics.tmHeight; incr++) + check_pos(hwEdit, metrics.tmHeight + incr, incr >= 2 ? 1 : 0, + compute_height(hwEdit, single_line, metrics.tmHeight, incr, 2), 1); DestroyWindow(hwEdit); }
static void test_text_position(void) { + ok (determine_height_model(), "Unable to guess the height model, forcing old one\n"); + trace("EDIT: Using %s model for height computation\n", old_height_model ? "old" : "new"); + trace("EDIT: Text position (Single line)\n"); test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL); trace("EDIT: Text position (Multi line)\n");
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/edit.c:
edit_pos_ok(test_left, format_rect.left - left_margin, left); \
} while(0)
-static void test_text_position_style(DWORD style) +/* Starting with Win10, multiline edit controls can have any value for height.
- Before, they always have a height which is a multiple of the font height.
- So detect which model we're running the tests on, and adjust the expected
- height accordingly.
- */
+static BOOL old_height_model;
+static DWORD compute_height(HWND hwedit, BOOL single_line, unsigned tmHeight, unsigned incr, unsigned limit)
The style is a bit inconsistent. Let's not use camel cases.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/edit.c:
- ok (font != NULL, "GetStockObject SYSTEM_FONT failed\n");
- *font = GetStockObject(SYSTEM_FONT);
- ok (*font != NULL, "GetStockObject SYSTEM_FONT failed\n"); dc = GetDC(NULL); ok (dc != NULL, "GetDC() failed\n"); oldFont = SelectObject(dc, font);
- xb = GetTextMetricsA(dc, &metrics);
- xb = GetTextMetricsA(dc, metrics); ok (xb, "GetTextMetrics failed\n"); SelectObject(dc, oldFont); ReleaseDC(NULL, dc);
+}
+static BOOL determine_height_model(void) +{
- HANDLE hwEdit;
Let's use HWND instead. And not camel cases here as well.
On Fri Dec 23 02:46:43 2022 +0000, Zhiyi Zhang wrote:
The style is a bit inconsistent. Let's not use camel cases.
I'll do, but for the record, the file is already fully inconsistent (eg. hwEdit, single_line to name of few). It's kinda hard to guess the right intention from the surrounding code.