Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandr Miloslavskiy2020-08-12 21:46:46 +0000
committerAlexandr Miloslavskiy2020-08-13 19:12:09 +0000
commit879b971aa7b3be1b059b2dc17a1d90ffac034124 (patch)
tree4fa3043241546923541e282c2d64a0438c622f6c
parent26e6a88d6b17f2ea527ac9fd193f3a0cc9b98531 (diff)
downloadeclipse.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>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java14
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java5
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java51
-rw-r--r--tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug565679_WS_BORDER.java31
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()) {

Back to the top