diff options
author | Alexandr Miloslavskiy | 2020-08-12 21:46:46 +0000 |
---|---|---|
committer | Alexandr Miloslavskiy | 2020-08-13 19:12:09 +0000 |
commit | 879b971aa7b3be1b059b2dc17a1d90ffac034124 (patch) | |
tree | 4fa3043241546923541e282c2d64a0438c622f6c | |
parent | 26e6a88d6b17f2ea527ac9fd193f3a0cc9b98531 (diff) | |
download | eclipse.platform.swt-879b971aa7b3be1b059b2dc17a1d90ffac034124.tar.gz eclipse.platform.swt-879b971aa7b3be1b059b2dc17a1d90ffac034124.tar.xz eclipse.platform.swt-879b971aa7b3be1b059b2dc17a1d90ffac034124.zip |
Bug 565679 - [Win32] SWT requests WS_EX_CLIENTEDGE and then tries to make it look like WS_BORDER
This patch addresses problems in Tree:
* Border type is now `WS_BORDER` instead if incorrect `WS_EX_CLIENTEDGE`
`WS_BORDER` is a flat 1px border.
`WS_EX_CLIENTEDGE` is a 3D 2px border.
Workarounds forced Tree to appear as if it had `WS_BORDER`.
* When `hwndParent` is created, border is removed on Tree and added to
`hwndParent` instead. This is more reasonable and allows to remove
workaround in `Tree.setScrollWidth()` which moved unwanted borders
outside the visible area.
Side effects:
* Tree contents moved one pixel left/up, because border is now 1px
thinner. I think that this is fine.
* Border is now darker, matching original Windows appearance for
borders. I consider this to be a good change, because it brings SWT
in line with native applications.
Change-Id: I551cd86d746392b625dfd5cc70130fb89b1d0ca5
Signed-off-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com>
4 files changed, 80 insertions, 21 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java index eeefc7d03b..01a326753a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java @@ -1219,7 +1219,19 @@ int getBorderWidthInPixels () { if ((bits1 & OS.WS_EX_CLIENTEDGE) != 0) return OS.GetSystemMetrics (OS.SM_CXEDGE); if ((bits1 & OS.WS_EX_STATICEDGE) != 0) return OS.GetSystemMetrics (OS.SM_CXBORDER); int bits2 = OS.GetWindowLong (borderHandle, OS.GWL_STYLE); - if ((bits2 & OS.WS_BORDER) != 0) return OS.GetSystemMetrics (OS.SM_CXBORDER); + + if ((bits2 & OS.WS_BORDER) != 0) { + /* + * For compatibility reasons, isUseWsBorder() shall not change layout size + * compared to previously used WS_EX_CLIENTEDGE. Removing this workaround + * saves screen space, but could break some layouts. + */ + if (isUseWsBorder ()) + return OS.GetSystemMetrics (OS.SM_CXEDGE); + + return OS.GetSystemMetrics (OS.SM_CXBORDER); + } + return 0; } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index a219968fdd..57e86dd9ec 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -219,8 +219,6 @@ public class Display extends Device { boolean useWsBorderTable = false; static final String USE_WS_BORDER_TEXT_KEY = "org.eclipse.swt.internal.win32.Text.use_WS_BORDER"; //$NON-NLS-1$ boolean useWsBorderText = false; - static final String USE_WS_BORDER_TREE_KEY = "org.eclipse.swt.internal.win32.Tree.use_WS_BORDER"; //$NON-NLS-1$ - boolean useWsBorderTree = false; /** * Changes the color of Table header's column delimiters. * Only affects custom-drawn header, that is when background/foreground header color is set. @@ -4416,9 +4414,6 @@ public void setData (String key, Object value) { case USE_WS_BORDER_TEXT_KEY: useWsBorderText = !disableCustomThemeTweaks && _toBoolean(value); return; - case USE_WS_BORDER_TREE_KEY: - useWsBorderTree = !disableCustomThemeTweaks && _toBoolean(value); - return; case TABLE_HEADER_LINE_COLOR_KEY: tableHeaderLinePixel = disableCustomThemeTweaks ? -1 : _toColorPixel(value); return; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java index 12d1258c79..da9f96995f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java @@ -2208,15 +2208,36 @@ void createItemToolTips () { OS.SendMessage (itemToolTipHandle, OS.TTM_ADDTOOL, 0, lpti); } +/** + * On Windows, Tree does not support columns. The workaround is to emulate it + * by adding a Header control and custom-drawing Tree items. + * + * Creates Header (for columns) and wraps (Tree+Header) into an intermediate + * parent, so that (Tree+Header) behave as one whole. The wrapper is designed + * to mimic original Tree as much as possible. For that reason, all sorts of + * settings are copied over. + */ void createParent () { forceResize (); + + /* Copy Tree position to hwndParent */ RECT rect = new RECT (); OS.GetWindowRect (handle, rect); OS.MapWindowPoints (0, parent.handle, rect, 2); - int oldStyle = OS.GetWindowLong (handle, OS.GWL_STYLE); - int newStyle = super.widgetStyle () & ~OS.WS_VISIBLE; + + /* Copy Tree styles to hwndParent */ + final int oldStyle = OS.GetWindowLong (handle, OS.GWL_STYLE); + int newStyle = super.widgetStyle (); + newStyle &= ~OS.WS_VISIBLE; /* Show control once everything is configured */ if ((oldStyle & OS.WS_DISABLED) != 0) newStyle |= OS.WS_DISABLED; -// if ((oldStyle & OS.WS_VISIBLE) != 0) newStyle |= OS.WS_VISIBLE; + + /* Get rid of internal borders; hwndParent will have the borders now */ + if ((oldStyle & OS.WS_BORDER) != 0) { + int noBorderStyle = oldStyle & ~OS.WS_BORDER; + OS.SetWindowLong (handle, OS.GWL_STYLE, noBorderStyle); + } + + /* Create hwndParent */ hwndParent = OS.CreateWindowEx ( super.widgetExtStyle (), super.windowClass (), @@ -2231,8 +2252,14 @@ void createParent () { OS.GetModuleHandle (null), null); if (hwndParent == 0) error (SWT.ERROR_NO_HANDLES); + + /* Old code, not sure if needed */ OS.SetWindowLongPtr (hwndParent, OS.GWLP_ID, hwndParent); + + /* Copy dark scrollbar settings to hwndParent */ OS.SetWindowTheme (hwndParent, display.getExplorerTheme(), null); + + /* Create header */ int bits = OS.WS_EX_NOINHERITLAYOUT; if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL; hwndHeader = OS.CreateWindowEx ( @@ -2246,12 +2273,20 @@ void createParent () { OS.GetModuleHandle (null), null); if (hwndHeader == 0) error (SWT.ERROR_NO_HANDLES); + + /* Old code, not sure if needed */ OS.SetWindowLongPtr (hwndHeader, OS.GWLP_ID, hwndHeader); + + /* Copy Tree's font to header */ long hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); if (hFont != 0) OS.SendMessage (hwndHeader, OS.WM_SETFONT, hFont, 0); + + /* Copy Tree's tab-order to hwndParent */ long hwndInsertAfter = OS.GetWindow (handle, OS.GW_HWNDPREV); int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; OS.SetWindowPos (hwndParent, hwndInsertAfter, 0, 0, 0, 0, flags); + + /* Copy Tree's scrollbar settings to hwndParent */ SCROLLINFO info = new SCROLLINFO (); info.cbSize = SCROLLINFO.sizeof; info.fMask = OS.SIF_RANGE | OS.SIF_PAGE; @@ -2261,9 +2296,13 @@ void createParent () { OS.GetScrollInfo (hwndParent, OS.SB_VERT, info); info.nPage = info.nMax + 1; OS.SetScrollInfo (hwndParent, OS.SB_VERT, info, true); + + /* Columns are emulated by custom drawing items */ customDraw = true; + deregister (); if ((oldStyle & OS.WS_VISIBLE) != 0) { + /* All set, show the new hwndParent wrapper */ OS.ShowWindow (hwndParent, OS.SW_SHOW); } long hwndFocus = OS.GetFocus (); @@ -3793,7 +3832,7 @@ boolean isItemSelected (NMTVCUSTOMDRAW nmcd) { @Override boolean isUseWsBorder () { - return super.isUseWsBorder () || ((display != null) && display.useWsBorderTree); + return true; } void redrawSelection () { @@ -4851,13 +4890,11 @@ void setScrollWidth (int width) { if (playout.prc != 0) OS.HeapFree (hHeap, 0, playout.prc); if (playout.pwpos != 0) OS.HeapFree (hHeap, 0, playout.pwpos); OS.SetWindowPos (hwndHeader, OS.HWND_TOP, pos.x - left, pos.y, pos.cx + left, pos.cy, OS.SWP_NOACTIVATE); - int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); - int b = (bits & OS.WS_EX_CLIENTEDGE) != 0 ? OS.GetSystemMetrics (OS.SM_CXEDGE) : 0; int w = pos.cx + (columnCount == 0 && width == 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL)); int h = rect.bottom - rect.top - pos.cy; boolean oldIgnore = ignoreResize; ignoreResize = true; - OS.SetWindowPos (handle, 0, pos.x - left - b, pos.y + pos.cy - b, w + left + b * 2, h + b * 2, OS.SWP_NOACTIVATE | OS.SWP_NOZORDER); + OS.SetWindowPos (handle, 0, pos.x - left, pos.y + pos.cy, w + left, h, OS.SWP_NOACTIVATE | OS.SWP_NOZORDER); ignoreResize = oldIgnore; } diff --git a/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug565679_WS_BORDER.java b/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug565679_WS_BORDER.java index 224f0c91ea..cbe08040d1 100644 --- a/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug565679_WS_BORDER.java +++ b/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug565679_WS_BORDER.java @@ -52,10 +52,28 @@ public class Bug565679_WS_BORDER { new Spinner(compControls, 0); new Label(compControls, 0).setText("Tree (with header)"); - Tree tree = new Tree(compControls, SWT.BORDER); - tree.setHeaderVisible(true); - new TreeColumn(tree, 0).setText("Column"); - new TreeItem(tree, 0).setText("Item"); + { + Tree tree = new Tree(compControls, SWT.BORDER); + tree.setHeaderVisible(true); + TreeColumn column = new TreeColumn(tree, 0); + column.setText("Column"); + column.setWidth(100); + TreeItem treeItem1 = new TreeItem(tree, 0); + treeItem1.setText("Item"); + TreeItem treeItem2 = new TreeItem(treeItem1, 0); + treeItem2.setText("Item"); + treeItem1.setExpanded(true); + } + + new Label(compControls, 0).setText("Tree (no header)"); + { + Tree tree = new Tree(compControls, SWT.BORDER); + TreeItem treeItem1 = new TreeItem(tree, 0); + treeItem1.setText("Item"); + TreeItem treeItem2 = new TreeItem(treeItem1, 0); + treeItem2.setText("Item"); + treeItem1.setExpanded(true); + } } new Label(shell, 0).setText( @@ -91,9 +109,6 @@ public class Bug565679_WS_BORDER { new Label(compControls, 0).setText("ToolBar"); ToolBar toolbar = new ToolBar(compControls, SWT.BORDER); toolbar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - new Label(compControls, 0).setText("Tree (no header)"); - new Tree(compControls, SWT.BORDER); } new Label(shell, 0).setText( @@ -115,7 +130,7 @@ public class Bug565679_WS_BORDER { new TabItem(tabFolder, 0).setText("Item"); } - shell.setSize(400, 800); + shell.setSize(400, 900); shell.open(); while (!shell.isDisposed()) { |