From 95700f9f14d5f4820a1b7627d09c80f9d2ab9bb0 Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Fri, 20 Sep 2024 17:08:40 +0200 Subject: [PATCH 01/11] Enabled Browser JavaScript execution during constructor In SWT you can execute JavaScript code in the Browser constructor, in RWT you could not, because the Iframe did not yet exist. Now it flickers into existence and you can execute JavaScript in it. Also-by: Ralf Schlesinger --- .../js/rwt/widgets/Browser.js | 24 +++++++++------ .../src/org/eclipse/swt/browser/Browser.java | 30 ++++++++++++++++++- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js b/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js index ff60807174..b25d6ca36e 100644 --- a/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js +++ b/bundles/org.eclipse.rap.rwt/js/rwt/widgets/Browser.js @@ -146,6 +146,7 @@ rwt.qx.Class.define( "rwt.widgets.Browser", { try { result = this._parseEvalResult( this._eval( script ) ); } catch( ex ) { + console.log(ex); success = false; } var connection = rwt.remote.Connection.getInstance(); @@ -198,7 +199,7 @@ rwt.qx.Class.define( "rwt.widgets.Browser", { // not accessible when it appears it should be // => user navigated to external site. this._throwSecurityException( true ); - } + } } }, @@ -215,21 +216,26 @@ rwt.qx.Class.define( "rwt.widgets.Browser", { }, _eval : function( script ) { - var win = this.getContentWindow(); - if( !win[ "eval" ] && win[ "execScript" ] ) { - // Workaround for IE bug, see: http://www.thismuchiknow.co.uk/?p=25 - win.execScript( "null;", "JScript" ); - } - return win[ "eval" ]( script ); + var win = this.getContentWindow(); + + if (win !== null) { + if( !win[ "eval" ] && win[ "execScript" ] ) { + // Workaround for IE bug, see: http://www.thismuchiknow.co.uk/?p=25 + win.execScript( "null;", "JScript" ); + } + return win[ "eval" ]( script ); + } else { + console.error("Window is null, can not execute scipts:\n" + script); + } }, _parseEvalResult : function( value ) { var result = null; var win = this.getContentWindow(); // NOTE: This mimics the behavior of the evaluate method in SWT: - if( value instanceof win.Function || value instanceof Function ) { + if( (win !== null && value instanceof win.Function) || value instanceof Function ) { result = this.toJSON( [ [] ] ); - } else if( value instanceof win.Array || value instanceof Array ) { + } else if( (win !== null && value instanceof win.Array) || value instanceof Array ) { result = this.toJSON( [ value ] ); } else if( typeof value !== "object" && typeof value !== "function" ) { // above: some browser say regular expressions of the type "function" diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java index d0e4148d4e..0719789bca 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java @@ -36,6 +36,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TypedListener; @@ -80,6 +81,7 @@ public class Browser extends Composite { private BrowserCallback browserCallback; private transient IBrowserAdapter browserAdapter; private final List functions; + private boolean clientInited = false; /** * Constructs a new instance of this class given its parent @@ -258,6 +260,33 @@ public boolean execute( String script ) { if( executeScript != null ) { throw new IllegalStateException( "Another script is already pending" ); } + + boolean showedShell = false; + Shell shell = getShell(); + + try { + // Show the shell, so that the browser is created in the browser + if (!clientInited && shell != null && !shell.getVisible()) { + showedShell = true; + //shell.setMinimized(true); + shell.setVisible(true); + internalExecute( "" ); + } + + internalExecute( script ); + } finally { + // if we showed it, we have to hide it again + if (showedShell) { + //shell.setMinimized(false); + shell.setVisible(false); + internalExecute( "" ); + } + clientInited = true; + } + return executeResult.booleanValue(); + } + + protected void internalExecute( String script ) { executeScript = script; executeResult = null; while( executeResult == null ) { @@ -268,7 +297,6 @@ public boolean execute( String script ) { } executeScript = null; executePending = false; - return executeResult.booleanValue(); } /** From 26c0a6a4b2be0ed86d8bd1b9779079fe25c3ebfe Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Fri, 20 Sep 2024 17:08:40 +0200 Subject: [PATCH 02/11] Enabled Browser JavaScript execution during constructor Adapted test so Browser throws WidgetDisposed, when widget is disposed. Also-by: Ralf Schlesinger --- .../src/org/eclipse/swt/browser/Browser_Test.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java index 5e80f3670f..b3f8099d7b 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/browser/Browser_Test.java @@ -34,6 +34,7 @@ import org.eclipse.rap.rwt.testfixture.TestContext; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; +import org.eclipse.swt.SWTException; import org.eclipse.swt.internal.browser.browserkit.BrowserLCA; import org.eclipse.swt.internal.events.EventTypes; import org.eclipse.swt.internal.widgets.IBrowserAdapter; @@ -356,9 +357,12 @@ public void run() { } } ); - boolean result = browser.execute( "var x = 2;" ); - - assertFalse( result ); + try { + boolean result = browser.execute( "var x = 2;" ); + fail(); + } catch( SWTException expected ) { + assertEquals( "Widget is disposed", expected.getMessage() ); + } } @Test From 68c1443daa25737329d034df27b2e442508cbd9b Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Mon, 23 Sep 2024 15:56:50 +0200 Subject: [PATCH 03/11] added constructor with additional parameter like swt Also-by: Ralf Schlesinger --- .../org/eclipse/ui/dialogs/FilteredTree.java | 120 +++++++++++------- 1 file changed, 77 insertions(+), 43 deletions(-) diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/FilteredTree.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/FilteredTree.java index 87e48ff8bd..d47d694d8c 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/FilteredTree.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/FilteredTree.java @@ -34,8 +34,6 @@ import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; //import org.eclipse.swt.events.KeyAdapter; //import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.ModifyEvent; @@ -43,7 +41,8 @@ import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseMoveListener; -import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; //import org.eclipse.swt.events.SelectionAdapter; //import org.eclipse.swt.events.SelectionEvent; //import org.eclipse.swt.events.TraverseEvent; @@ -59,7 +58,6 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IWorkbenchPreferenceConstants; import org.eclipse.ui.PlatformUI; @@ -208,7 +206,7 @@ public class FilteredTree extends Composite { * {@link #FilteredTree(Composite, int, PatternFilter, boolean)} where using the new * look is encouraged */ - public FilteredTree(Composite parent, int treeStyle, PatternFilter filter) { + public FilteredTree(Composite parent, int treeStyle, PatternFilter filter) { super(parent, SWT.NONE); this.parent = parent; // RAP [rh] initialize image descriptors in session scope @@ -238,6 +236,41 @@ public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, boole init(treeStyle, filter); } + /** + * Create a new instance of the receiver. + * + *

+ * + * WARNING: Passing false as parameter for useFastHashLookup results in a + * slow performing tree and should not be used if the underlying data model uses + * a stable and correct hashCode and equals implementation. + * + *

+ * + * @param parent the parent Composite + * @param treeStyle the style bits for the Tree + * @param filter the filter to be used + * @param useNewLook true if the new 3.5 look should be used + * @param useFastHashLookup true, if tree should use fast hash lookup, false, if + * the tree should be slow but working for data with + * mutable or broken hashcode implementation. Only used + * if treeViewer is already initialized + * @since 3.116 + */ + public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, boolean useNewLook, + boolean useFastHashLookup) + { + super(parent, SWT.NONE); + this.parent = parent; + this.useNewLook = useNewLook; + // RAP [rh] initialize image descriptors in session scope + initializeImageDescriptors(); + init(treeStyle, filter); + if (treeViewer != null) { + treeViewer.setUseHashlookup(useFastHashLookup); + } + } + /** * Create a new instance of the receiver. Subclasses that wish to override * the default creation behavior may use this constructor, but must ensure @@ -250,7 +283,7 @@ public FilteredTree(Composite parent, int treeStyle, PatternFilter filter, boole * @deprecated As of 3.5, replaced by {@link #FilteredTree(Composite, boolean)} where using the * look is encouraged */ - protected FilteredTree(Composite parent) { + protected FilteredTree(Composite parent) { super(parent, SWT.NONE); this.parent = parent; // RAP [rh] initialize image descriptors in session scope @@ -387,10 +420,11 @@ private static boolean useNativeSearchField(Composite composite) { */ protected Composite createFilterControls(Composite parent) { createFilterText(parent); - if (useNewLook) - createClearTextNew(parent); - else - createClearTextOld(parent); + if (useNewLook) { + createClearTextNew(parent); + } else { + createClearTextOld(parent); + } if (clearButtonControl != null) { // initially there is no text to clear clearButtonControl.setVisible(false); @@ -425,7 +459,7 @@ protected Control createTreeControl(Composite parent, int style) { * * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) */ - public void widgetDisposed(DisposeEvent e) { + public void widgetDisposed(DisposeEvent e) { refreshJob.cancel(); } }); @@ -484,7 +518,7 @@ private void createRefreshJob() { */ protected WorkbenchJob doCreateRefreshJob() { return new WorkbenchJob("Refresh Filter") {//$NON-NLS-1$ - public IStatus runInUIThread(IProgressMonitor monitor) { + public IStatus runInUIThread(IProgressMonitor monitor) { if (treeViewer.getControl().isDisposed()) { return Status.CANCEL_STATUS; } @@ -692,7 +726,7 @@ protected void createFilterText(Composite parent) { * * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent) */ - public void focusGained(FocusEvent e) { + public void focusGained(FocusEvent e) { if (!useNewLook) { /* * Running in an asyncExec because the selectAll() does not appear to work when @@ -700,7 +734,7 @@ public void focusGained(FocusEvent e) { */ Display display= filterText.getDisplay(); display.asyncExec(new Runnable() { - public void run() { + public void run() { if (!filterText.isDisposed()) { if (getInitialText().equals( filterText.getText().trim())) { @@ -719,7 +753,7 @@ public void run() { * @see org.eclipse.swt.events.FocusAdapter#focusLost(org.eclipse.swt.events.FocusEvent) */ - public void focusLost(FocusEvent e) { + public void focusLost(FocusEvent e) { if (!useNewLook) { return; } @@ -740,7 +774,7 @@ public void focusLost(FocusEvent e) { * @see * org.eclipse.swt.events.MouseAdapter#mouseDown(org.eclipse.swt.events.MouseEvent) */ - public void mouseDown(MouseEvent e) { + public void mouseDown(MouseEvent e) { if (filterText.getText().equals(initialText)) { // XXX: We cannot call clearText() due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=260664 setFilterText(""); //$NON-NLS-1$ @@ -804,7 +838,7 @@ public void mouseDown(MouseEvent e) { * * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ - public void modifyText(ModifyEvent e) { + public void modifyText(ModifyEvent e) { textChanged(); } }); @@ -819,10 +853,10 @@ public void modifyText(ModifyEvent e) { * * @see org.eclipse.swt.events.SelectionAdapter#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) */ - public void widgetDefaultSelected(SelectionEvent e) { + public void widgetDefaultSelected(SelectionEvent e) { if (e.detail == SWT.ICON_CANCEL) - clearText(); - } + clearText(); + } }); } @@ -830,7 +864,7 @@ public void widgetDefaultSelected(SelectionEvent e) { // if the text widget supported cancel then it will have it's own // integrated button. We can take all of the space. if ((filterText.getStyle() & SWT.ICON_CANCEL) != 0) - gridData.horizontalSpan = 2; + gridData.horizontalSpan = 2; filterText.setLayoutData(gridData); } @@ -886,7 +920,7 @@ protected long getRefreshJobDelay() { * @param background * background Color to set */ - public void setBackground(Color background) { + public void setBackground(Color background) { super.setBackground(background); if (filterComposite != null && (!useNewLook || useNativeSearchField(filterComposite))) { filterComposite.setBackground(background); @@ -915,7 +949,7 @@ private void createClearTextOld(Composite parent) { * * @see org.eclipse.jface.action.Action#run() */ - public void run() { + public void run() { clearText(); } }; @@ -954,12 +988,12 @@ private void createClearTextNew(Composite parent) { clearButton.addMouseListener(new MouseAdapter() { private MouseMoveListener fMoveListener; - public void mouseDown(MouseEvent e) { + public void mouseDown(MouseEvent e) { clearButton.setImage(pressedImage); fMoveListener= new MouseMoveListener() { private boolean fMouseInButton= true; - public void mouseMove(MouseEvent e) { + public void mouseMove(MouseEvent e) { boolean mouseInButton= isMouseInButton(e); if (mouseInButton != fMouseInButton) { fMouseInButton= mouseInButton; @@ -971,7 +1005,7 @@ public void mouseMove(MouseEvent e) { // clearButton.addMouseMoveListener(fMoveListener); } - public void mouseUp(MouseEvent e) { + public void mouseUp(MouseEvent e) { if (fMoveListener != null) { // RAP [bm] mouse move listener // clearButton.removeMouseMoveListener(fMoveListener); @@ -1004,7 +1038,7 @@ private boolean isMouseInButton(MouseEvent e) { // } // }); clearButton.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { + public void widgetDisposed(DisposeEvent e) { inactiveImage.dispose(); activeImage.dispose(); pressedImage.dispose(); @@ -1102,7 +1136,7 @@ public void setInitialText(String text) { textChanged(); } else { getDisplay().asyncExec(new Runnable() { - public void run() { + public void run() { if (!filterText.isDisposed() && filterText.isFocusControl()) { setFilterText(initialText); textChanged(); @@ -1192,79 +1226,79 @@ public NotifyingTreeViewer(Composite parent, int style) { super(parent, style); } - public void add(Object parentElementOrTreePath, Object childElement) { + public void add(Object parentElementOrTreePath, Object childElement) { getPatternFilter().clearCaches(); super.add(parentElementOrTreePath, childElement); } - public void add(Object parentElementOrTreePath, Object[] childElements) { + public void add(Object parentElementOrTreePath, Object[] childElements) { getPatternFilter().clearCaches(); super.add(parentElementOrTreePath, childElements); } - protected void inputChanged(Object input, Object oldInput) { + protected void inputChanged(Object input, Object oldInput) { getPatternFilter().clearCaches(); super.inputChanged(input, oldInput); } - public void insert(Object parentElementOrTreePath, Object element, + public void insert(Object parentElementOrTreePath, Object element, int position) { getPatternFilter().clearCaches(); super.insert(parentElementOrTreePath, element, position); } - public void refresh() { + public void refresh() { getPatternFilter().clearCaches(); super.refresh(); } - public void refresh(boolean updateLabels) { + public void refresh(boolean updateLabels) { getPatternFilter().clearCaches(); super.refresh(updateLabels); } - public void refresh(Object element) { + public void refresh(Object element) { getPatternFilter().clearCaches(); super.refresh(element); } - public void refresh(Object element, boolean updateLabels) { + public void refresh(Object element, boolean updateLabels) { getPatternFilter().clearCaches(); super.refresh(element, updateLabels); } - public void remove(Object elementsOrTreePaths) { + public void remove(Object elementsOrTreePaths) { getPatternFilter().clearCaches(); super.remove(elementsOrTreePaths); } - public void remove(Object parent, Object[] elements) { + public void remove(Object parent, Object[] elements) { getPatternFilter().clearCaches(); super.remove(parent, elements); } - public void remove(Object[] elementsOrTreePaths) { + public void remove(Object[] elementsOrTreePaths) { getPatternFilter().clearCaches(); super.remove(elementsOrTreePaths); } - public void replace(Object parentElementOrTreePath, int index, + public void replace(Object parentElementOrTreePath, int index, Object element) { getPatternFilter().clearCaches(); super.replace(parentElementOrTreePath, index, element); } - public void setChildCount(Object elementOrTreePath, int count) { + public void setChildCount(Object elementOrTreePath, int count) { getPatternFilter().clearCaches(); super.setChildCount(elementOrTreePath, count); } - public void setContentProvider(IContentProvider provider) { + public void setContentProvider(IContentProvider provider) { getPatternFilter().clearCaches(); super.setContentProvider(provider); } - public void setHasChildren(Object elementOrTreePath, boolean hasChildren) { + public void setHasChildren(Object elementOrTreePath, boolean hasChildren) { getPatternFilter().clearCaches(); super.setHasChildren(elementOrTreePath, hasChildren); } From 0d9cd13bbc7aed3085e992267319b3b3ef67460f Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Mon, 23 Sep 2024 15:58:10 +0200 Subject: [PATCH 04/11] added RowLayoutFactory.center() from original SWT API Also-by: Ralf Schlesinger --- .../eclipse/jface/layout/RowLayoutFactory.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/layout/RowLayoutFactory.java b/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/layout/RowLayoutFactory.java index a0cc0c2b44..4048ef9f2e 100644 --- a/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/layout/RowLayoutFactory.java +++ b/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/layout/RowLayoutFactory.java @@ -12,7 +12,6 @@ package org.eclipse.jface.layout; import java.io.Serializable; - import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.RowLayout; @@ -215,6 +214,20 @@ public RowLayoutFactory fill(boolean fill) { return this; } + /** + * Center specifies whether the controls in a row should be centered vertically + * in each cell for horizontal layouts, or centered horizontally in each cell + * for vertical layouts. + * + * @param center the center status + * @return this + * @since 3.20 + */ + public RowLayoutFactory center(boolean center) { + layout.center = center; + return this; + } + /** * Justify specifies whether the controls in a row should be fully * justified, with any extra space placed between the controls. From 2a7e15b25cf328b17dc222aa12a5fd7e3aee8c5d Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Mon, 23 Sep 2024 15:59:37 +0200 Subject: [PATCH 05/11] changed toString in MouseEvent like SWT Also-by: Ralf Schlesinger --- .../src/org/eclipse/swt/events/MouseEvent.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/events/MouseEvent.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/events/MouseEvent.java index 0951ad3031..7ee836d13b 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/events/MouseEvent.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/events/MouseEvent.java @@ -100,8 +100,7 @@ public String toString() { return string.substring( 0, string.length() - 1 ) // remove trailing '}' + " button=" + button - + " stateMask=" - + stateMask + + " stateMask=0x" + Integer.toHexString( stateMask ) + " x=" + x + " y=" From 8b80f79f30467ad6bfdc06b6913455a43a5f3fe5 Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Mon, 23 Sep 2024 16:03:31 +0200 Subject: [PATCH 06/11] Dispose Events should be send even if notifyListeners is overridden It was possible to prevent the delivery of dispose event, by overridding notifyListeners, this is not possible in swt. Also-by: Ralf Schlesinger --- .../src/org/eclipse/swt/widgets/Widget.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java index 66fa302508..20da24d9af 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java @@ -583,6 +583,17 @@ public void removeListener( int eventType, Listener listener ) { * @since 1.2 */ public void notifyListeners( int eventType, Event event ) { + notifyListenersInternal( eventType, event ); + } + + /** + * Private notifyListeners because childs override the normal notifyListeners, but dispose in + * normal swt calls around it. + * + * @param eventType + * @param event + */ + protected final void notifyListenersInternal( int eventType, Event event ) { checkWidget(); Event newEvent = event == null ? new Event() : event; newEvent.widget = this; @@ -838,7 +849,7 @@ public void dispose() { } if( !hasState( DISPOSE_SENT ) ) { addState( DISPOSE_SENT ); - notifyListeners( SWT.Dispose, new Event() ); + notifyListenersInternal( SWT.Dispose, new Event() ); } if( !hasState( DISPOSED ) ) { releaseChildren(); From 5ec6a7e30cdfbb7c5d0e086cd762c466d1582174 Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Mon, 23 Sep 2024 16:04:29 +0200 Subject: [PATCH 07/11] Fix for Browser that was showing nothing Also-by: Ralf Schlesinger Also-by: Rico Scholz --- .../org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java index 0719789bca..68cff971fa 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/browser/Browser.java @@ -756,6 +756,7 @@ public void handleEvent( Event event ) { case EventTypes.LOCALTION_CHANGING: { LocationListener locationListener = ( LocationListener )getEventListener(); LocationEvent locationEvent = new LocationEvent( event ); + locationEvent.doit = event.doit; locationListener.changing( locationEvent ); event.doit = locationEvent.doit; break; From 6b46de89ece43315785b64bca92fe4edaf527c89 Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Mon, 23 Sep 2024 16:19:54 +0200 Subject: [PATCH 08/11] modified painting to change order like swt adapted tests to new behavior Also-by: Ralf Schlesinger --- .../jface/viewers/CellToolTipProvider.java | 19 ++++++++------- .../org/eclipse/swt/graphics/ControlGC.java | 3 ++- .../src/org/eclipse/swt/widgets/Canvas.java | 23 ++++++++++++++++++- .../src/org/eclipse/swt/widgets/Display.java | 2 +- .../src/org/eclipse/swt/widgets/Widget.java | 16 ++++++++----- .../resources/ClientResources_Test.java | 8 ++++++- .../widgets/canvaskit/CanvasLCA_Test.java | 3 +++ .../org/eclipse/swt/widgets/Canvas_Test.java | 22 +++++++++++++----- .../org/eclipse/swt/widgets/Control_Test.java | 2 ++ 9 files changed, 74 insertions(+), 24 deletions(-) diff --git a/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/viewers/CellToolTipProvider.java b/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/viewers/CellToolTipProvider.java index 1b214d9563..1fcae81293 100644 --- a/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/viewers/CellToolTipProvider.java +++ b/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/viewers/CellToolTipProvider.java @@ -11,7 +11,6 @@ package org.eclipse.jface.viewers; import java.io.Serializable; - import org.eclipse.jface.util.SafeRunnable; import org.eclipse.swt.internal.widgets.ICellToolTipAdapter; import org.eclipse.swt.internal.widgets.ICellToolTipProvider; @@ -30,17 +29,21 @@ final class CellToolTipProvider implements ICellToolTipProvider, Serializable { static void attach( ColumnViewer viewer, CellLabelProvider labelProvider ) { ICellToolTipAdapter adapter = getAdapter( viewer ); - if( labelProvider != null ) { - CellToolTipProvider provider = new CellToolTipProvider( viewer ); - adapter.setCellToolTipProvider( provider ); - } else { - adapter.setCellToolTipProvider( null ); + if (adapter != null) { + if (labelProvider != null) { + CellToolTipProvider provider = new CellToolTipProvider(viewer); + adapter.setCellToolTipProvider(provider); + } else { + adapter.setCellToolTipProvider(null); + } } } - public void getToolTipText( final Item item, final int columnIndex ) { + @Override +public void getToolTipText( final Item item, final int columnIndex ) { SafeRunnable.run( new SafeRunnable() { - public void run() { + @Override + public void run() { Object element = item.getData(); ViewerColumn column = viewer.getViewerColumn( columnIndex ); CellLabelProvider labelProvider = column.getLabelProvider(); diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java index 7877cbbe11..fe38af851c 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java @@ -207,7 +207,8 @@ void setClipping( Path path ) { @Override Rectangle getClipping() { if( clippingRect == null ) { - return control.getBounds(); + Rectangle bounds = control.getBounds(); + return new Rectangle( 0, 0, bounds.width, bounds.height ); } return new Rectangle( clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height ); } diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Canvas.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Canvas.java index 75336c9863..4efd6bd049 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Canvas.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Canvas.java @@ -11,6 +11,8 @@ ******************************************************************************/ package org.eclipse.swt.widgets; +import java.io.Serializable; + import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCA; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; @@ -182,6 +184,10 @@ void internalSetRedraw( boolean redraw, int x, int y, int width, int height ) { } private void repaint( Rectangle paintRect ) { + getDisplay().asyncExec( new RepaintRunnable(paintRect)); + } + + private void repaintSync( Rectangle paintRect ) { if( gcAdapter != null ) { gcAdapter.clearGCOperations(); gcAdapter.setForceRedraw( true ); @@ -190,11 +196,26 @@ private void repaint( Rectangle paintRect ) { Event paintEvent = new Event(); paintEvent.gc = gc; paintEvent.setBounds( paintRect ); - notifyListeners( SWT.Paint, paintEvent ); + notifyListenersInternal( SWT.Paint, paintEvent, true ); gc.dispose(); if( gcAdapter != null ) { gcAdapter.setPaintRect( paintRect ); } } + private class RepaintRunnable implements Runnable, Serializable { + private static final long serialVersionUID = 687991492884005033L; + private Rectangle paintRect; + + RepaintRunnable(Rectangle paintRect) { + this.paintRect = paintRect; + } + + @Override + public void run() { + if( !isDisposed() ) { + repaintSync( paintRect ); + } + } + } } diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Display.java index aaf9df5878..61ce1e6dcb 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Display.java @@ -1213,7 +1213,7 @@ private static boolean executeNextEvent() { Event event = events[ 0 ]; EventList.getInstance().remove( event ); if( EventUtil.allowProcessing( event ) ) { - event.widget.notifyListeners( event.type, event ); + event.widget.notifyListenersInternal( event.type, event, true ); result = true; } else { events = EventList.getInstance().getAll(); diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java index 20da24d9af..645a7430c8 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Widget.java @@ -583,7 +583,7 @@ public void removeListener( int eventType, Listener listener ) { * @since 1.2 */ public void notifyListeners( int eventType, Event event ) { - notifyListenersInternal( eventType, event ); + notifyListenersInternal( eventType, event, false ); } /** @@ -592,8 +592,12 @@ public void notifyListeners( int eventType, Event event ) { * * @param eventType * @param event + * @param onlyDirectCall no add to eventlist allowed */ - protected final void notifyListenersInternal( int eventType, Event event ) { + protected final void notifyListenersInternal( int eventType, + Event event, + boolean onlyDirectCall ) + { checkWidget(); Event newEvent = event == null ? new Event() : event; newEvent.widget = this; @@ -602,7 +606,7 @@ protected final void notifyListenersInternal( int eventType, Event event ) { if( newEvent.time == 0 ) { newEvent.time = EventUtil.getLastEventTime(); } - sendEvent( newEvent ); + sendEvent( newEvent, onlyDirectCall ); } /** @@ -691,8 +695,8 @@ protected void removeListener( int eventType, SWTEventListener listener ) { } } - private void sendEvent( Event event ) { - if( isEventProcessingPhase() ) { + private void sendEvent( Event event, boolean onlyDirectCall ) { + if( isEventProcessingPhase() && ( event.type != SWT.Paint || onlyDirectCall ) ) { event.display.filterEvent( event ); if( eventTable != null ) { eventTable.sendEvent( event ); @@ -849,7 +853,7 @@ public void dispose() { } if( !hasState( DISPOSE_SENT ) ) { addState( DISPOSE_SENT ); - notifyListenersInternal( SWT.Dispose, new Event() ); + notifyListenersInternal( SWT.Dispose, new Event(), false ); } if( !hasState( DISPOSED ) ) { releaseChildren(); diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/resources/ClientResources_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/resources/ClientResources_Test.java index c9ef6ad703..3a527345dc 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/resources/ClientResources_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/resources/ClientResources_Test.java @@ -16,6 +16,8 @@ import java.io.IOException; import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.internal.RWTProperties; @@ -81,7 +83,11 @@ public void testIncludesDebugSettings() throws IOException { String content = getRegisteredContent( RAP_CLIENT_JS_PATH ); - assertTrue( content.contains( "qxvariants = {\n \"qx.debug\" : \"on\"\n};" ) ); + // Pattern: .*qxvariants\W*=\W*\{\W*\"qx.debug\"\W*:\W*\"on\"\W*\};.* + String patternString = ".*qxvariants\\W*=\\W*\\{\\W*\\\"qx.debug\\\"\\W*:\\W*\\\"on\\\"\\W*\\};.*"; + Pattern pattern = Pattern.compile(patternString, Pattern.MULTILINE); + Matcher matcher = pattern.matcher(content); + assertTrue( matcher.find()); } @Test diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/CanvasLCA_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/CanvasLCA_Test.java index f1d3ce3f97..072cc65bad 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/CanvasLCA_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/CanvasLCA_Test.java @@ -283,6 +283,7 @@ public void paintControl( PaintEvent event ) { Fixture.fakeResponseWriter(); canvas.setSize( 150, 150 ); + while (display.readAndDispatch()) {} lca.renderChanges( canvas ); CallOperation init = getGCOperation( canvas, "init" ); @@ -310,6 +311,7 @@ public void paintControl( PaintEvent event ) { Fixture.fakeResponseWriter(); canvas.redraw(); + while (display.readAndDispatch()) {} lca.renderChanges( canvas ); CallOperation draw = getGCOperation( canvas, "draw" ); @@ -333,6 +335,7 @@ public void paintControl( PaintEvent event ) { Fixture.fakeResponseWriter(); canvas.redraw(); + while (display.readAndDispatch()) {} lca.renderChanges( canvas ); assertNotNull( getGCOperation( canvas, "init" ) ); diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Canvas_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Canvas_Test.java index 51e9aeed1b..4185efba0d 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Canvas_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Canvas_Test.java @@ -61,9 +61,11 @@ public void paintControl( PaintEvent event ) { } ); canvas.redraw(); + while (display.readAndDispatch()) {} - assertEquals( 1, paintEventLog.size() ); - PaintEvent event = paintEventLog.get( 0 ); + // 2 = 1 orignal drawing + 1 redraws + assertEquals( 2, paintEventLog.size() ); + PaintEvent event = paintEventLog.get( 1 ); assertSame( canvas, event.widget ); assertTrue( event.gc.isDisposed() ); assertEquals( event.x, 0 ); @@ -82,9 +84,11 @@ public void paintControl( PaintEvent event ) { } ); canvas.redraw( 1, 2, 3, 4, true ); + while (display.readAndDispatch()) {} - assertEquals( 1, paintEventLog.size() ); - PaintEvent event = paintEventLog.get( 0 ); + // 2 = 1 orignal drawing + 1 redraws + assertEquals( 2, paintEventLog.size() ); + PaintEvent event = paintEventLog.get( 1 ); assertSame( canvas, event.widget ); assertTrue( event.gc.isDisposed() ); assertEquals( event.x, 1 ); @@ -102,7 +106,10 @@ public void paintControl( PaintEvent event ) { } } ); canvas.setSize( 100, 100 ); - assertEquals( 1, paintEventLog.size() ); + while (display.readAndDispatch()) {} + + // 2 = 1 orignal drawing + 1 redraws after resize + assertEquals( 2, paintEventLog.size() ); } @Test @@ -116,7 +123,10 @@ public void paintControl( PaintEvent event ) { } ); canvas.redraw(); canvas.redraw(); - assertEquals( 2, paintEventLog.size() ); + while (display.readAndDispatch()) {} + + // 3 = 1 orignal drawing + 2 redraws + assertEquals( 3, paintEventLog.size() ); GCAdapter adapter = canvas.getAdapter( GCAdapter.class ); assertEquals( 1, adapter.getGCOperations().length ); } diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Control_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Control_Test.java index f9c659cd55..da29b55ff6 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Control_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/widgets/Control_Test.java @@ -1158,6 +1158,8 @@ public void testRedrawTriggersLCAInOrder() { control1.redraw(); display.readAndDispatch(); display.readAndDispatch(); + display.readAndDispatch(); + display.readAndDispatch(); assertEquals( 2, log.size() ); assertEquals( control0, log.get( 0 ) ); assertEquals( control1, log.get( 1 ) ); From 95af3b1938edaa41b9380eb99caa6bcfc57a210a Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Tue, 24 Sep 2024 10:56:15 +0200 Subject: [PATCH 09/11] handle mouse events statemask like in swt In SWT the buttons are not in the statemask except in MouseUp. Also-by: Ralf Schlesinger --- .../protocol/ControlOperationHandler.java | 19 ++++- .../ControlOperationHandler_Test.java | 40 +++++++++- .../eclipse/swt/events/MouseEvent_Test.java | 64 +++++++++++++++- .../combokit/ComboOperationHandler_Test.java | 73 ++++++++++++++++++- .../treekit/TreeOperationHandler_Test.java | 72 +++++++++++++++++- 5 files changed, 261 insertions(+), 7 deletions(-) diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler.java index b2962285cb..85336861d9 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler.java @@ -29,12 +29,15 @@ import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_PARAM_Y; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_TRAVERSE; import static org.eclipse.rap.rwt.internal.protocol.ProtocolUtil.wasEventSent; +import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext; import static org.eclipse.swt.internal.events.EventLCAUtil.translateButton; import static org.eclipse.swt.internal.widgets.ControlUtil.getControlAdapter; import org.eclipse.rap.json.JsonArray; import org.eclipse.rap.json.JsonObject; import org.eclipse.rap.json.JsonValue; +import org.eclipse.rap.rwt.RWT; +import org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; @@ -333,7 +336,18 @@ static Event createMouseEvent( int eventType, Control control, JsonObject proper event.x = point.x; event.y = point.y; event.time = properties.get( EVENT_PARAM_TIME ).asInt(); - event.stateMask = readStateMask( properties ) | translateButton( event.button ); + + if (isSwtMode()) { + event.stateMask = readStateMask( properties ); + // [pw] The button mask confuses NatTable MouseEventMatcher since + // the button mask is not there in SWT except in MouseUp event, + // see Widget.class line 1351 (in swt) + if ( SWT.MouseUp == eventType ) { + event.stateMask |= translateButton( event.button ); + } + } else { + event.stateMask = readStateMask( properties ) | translateButton( event.button ); + } // TODO: send count by the client event.count = determineCount( eventType, control ); return event; @@ -540,4 +554,7 @@ private static int translateCursor( String cursor ) { return result; } + private static boolean isSwtMode() { + return getApplicationContext().getLifeCycleFactory().getLifeCycle() instanceof RWTLifeCycle; + } } diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler_Test.java index 91235829a5..b7466d905b 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/protocol/ControlOperationHandler_Test.java @@ -10,12 +10,14 @@ ******************************************************************************/ package org.eclipse.rap.rwt.internal.protocol; +import static org.eclipse.rap.rwt.application.Application.OperationMode.SWT_COMPATIBILITY; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_KEY_DOWN; import static org.eclipse.rap.rwt.internal.protocol.ControlOperationHandler.createKeyEvent; import static org.eclipse.rap.rwt.internal.protocol.ControlOperationHandler.createMenuDetectEvent; import static org.eclipse.rap.rwt.internal.protocol.ControlOperationHandler.createMouseEvent; import static org.eclipse.rap.rwt.internal.protocol.ControlOperationHandler.getTraverseKey; import static org.eclipse.rap.rwt.internal.protocol.ControlOperationHandler.translateKeyCode; +import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -27,6 +29,9 @@ import org.eclipse.rap.json.JsonArray; import org.eclipse.rap.json.JsonObject; +import org.eclipse.rap.rwt.application.Application.OperationMode; +import org.eclipse.rap.rwt.internal.lifecycle.LifeCycleFactory; +import org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle; import org.eclipse.rap.rwt.testfixture.internal.Fixture; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; @@ -71,7 +76,9 @@ public void tearDown() { } @Test - public void testCreateMouseEvent() { + public void testCreateMouseEventeJeeMode() { + ensureOperationMode(OperationMode.JEE_COMPATIBILITY); + JsonObject properties = new JsonObject() .add( "button", 1 ) .add( "x", 15 ) @@ -90,6 +97,29 @@ public void testCreateMouseEvent() { assertEquals( 1, event.count ); } + @Test + public void testCreateMouseEventeSwtMode() { + ensureOperationMode(OperationMode.SWT_COMPATIBILITY); + + JsonObject properties = new JsonObject() + .add( "button", 1 ) + .add( "x", 15 ) + .add( "y", 20 ) + .add( "time", 4 ); + + Event event = createMouseEvent( SWT.MouseDown, control, properties ); + + assertEquals( SWT.MouseDown, event.type ); + assertEquals( control, event.widget ); + assertEquals( 0, event.stateMask ); + assertEquals( 1, event.button ); + assertEquals( 4, event.x ); + assertEquals( 9, event.y ); + assertEquals( 4, event.time ); + assertEquals( 1, event.count ); + } + + @Test public void testCreateMouseEvent_withKeyModifiers() { JsonObject properties = new JsonObject() @@ -496,4 +526,12 @@ public void testHandleSetCursor_invalidCursor() { handler.handleSet( mockedControl, properties ); } + private static void ensureOperationMode( OperationMode operationMode ) { + LifeCycleFactory lifeCycleFactory = getApplicationContext().getLifeCycleFactory(); + lifeCycleFactory.deactivate(); + if( SWT_COMPATIBILITY.equals( operationMode ) ) { + lifeCycleFactory.configure( RWTLifeCycle.class ); + } + lifeCycleFactory.activate(); + } } diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/events/MouseEvent_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/events/MouseEvent_Test.java index 757eb3196d..16cccae3d1 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/events/MouseEvent_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/events/MouseEvent_Test.java @@ -12,6 +12,8 @@ package org.eclipse.swt.events; import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.getRemoteObject; +import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext; +import static org.eclipse.rap.rwt.application.Application.OperationMode.SWT_COMPATIBILITY; import static org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil.getId; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; @@ -26,7 +28,10 @@ import java.util.List; import org.eclipse.rap.json.JsonObject; +import org.eclipse.rap.rwt.application.Application.OperationMode; +import org.eclipse.rap.rwt.internal.lifecycle.LifeCycleFactory; import org.eclipse.rap.rwt.internal.lifecycle.PhaseId; +import org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle; import org.eclipse.rap.rwt.internal.protocol.ClientMessageConst; import org.eclipse.rap.rwt.testfixture.internal.Fixture; import org.eclipse.swt.SWT; @@ -178,7 +183,8 @@ public void testTypedMouseEventOrderWithClick() { } @Test - public void testTypedMouseEventOrderWithDoubleClick() { + public void testTypedMouseEventOrderWithDoubleClickJeeMode() { + ensureOperationMode( OperationMode.JEE_COMPATIBILITY ); MouseListener mouseListener = mock( MouseListener.class ); shell.setLocation( 100, 100 ); shell.open(); @@ -221,6 +227,53 @@ public void testTypedMouseEventOrderWithDoubleClick() { assertTrue( ( mouseUp.stateMask & SWT.BUTTON1 ) != 0 ); assertEquals( 2, mouseUp.count ); } + + @Test + public void testTypedMouseEventOrderWithDoubleClickSwtMode() { + ensureOperationMode( OperationMode.SWT_COMPATIBILITY ); + MouseListener mouseListener = mock( MouseListener.class ); + shell.setLocation( 100, 100 ); + shell.open(); + shell.addMouseListener( mouseListener ); + int eventX = shell.getLocation().x + shell.getClientArea().x + 1; + int eventY = shell.getLocation().y + shell.getClientArea().y + 1; + + // Simulate request that sends a mouseDown + mouseUp + dblClick sequence + Fixture.fakeNewRequest(); + fakeMouseDownRequest( shell, eventX, eventY ); + fakeMouseUpRequest( shell, eventX, eventY ); + fakeMouseDoubleClickRequest( shell, eventX, eventY ); + Fixture.readDataAndProcessAction( display ); + + InOrder inOrder = inOrder( mouseListener ); + ArgumentCaptor downCaptor = ArgumentCaptor.forClass( MouseEvent.class ); + inOrder.verify( mouseListener ).mouseDown( downCaptor.capture() ); + MouseEvent mouseDown = downCaptor.getValue(); + assertSame( shell, mouseDown.widget ); + assertEquals( 1, mouseDown.button ); + assertEquals( 15, mouseDown.x ); + assertEquals( 53, mouseDown.y ); + assertEquals( 2, mouseDown.count ); + ArgumentCaptor doubleClickCaptor = ArgumentCaptor.forClass( MouseEvent.class ); + inOrder.verify( mouseListener ).mouseDoubleClick( doubleClickCaptor.capture() ); + MouseEvent mouseDoubleClick = doubleClickCaptor.getValue(); + assertSame( shell, mouseDoubleClick.widget ); + assertEquals( 1, mouseDoubleClick.button ); + assertEquals( 15, mouseDoubleClick.x ); + assertEquals( 53, mouseDoubleClick.y ); + assertEquals( 0, mouseDoubleClick.stateMask ); + assertEquals( 2, mouseDoubleClick.count ); + ArgumentCaptor upCaptor = ArgumentCaptor.forClass( MouseEvent.class ); + inOrder.verify( mouseListener ).mouseUp( upCaptor.capture() ); + MouseEvent mouseUp = upCaptor.getValue(); + assertSame( shell, mouseUp.widget ); + assertEquals( 1, mouseUp.button ); + assertEquals( 15, mouseUp.x ); + assertEquals( 53, mouseUp.y ); + assertTrue( ( mouseUp.stateMask & SWT.BUTTON1 ) != 0 ); + assertEquals( 2, mouseUp.count ); + } + @Test public void testUntypedMouseEventOrderWithClick() { @@ -385,6 +438,15 @@ private static void fakeMouseDownRequest( Widget widget, int x, int y ) { .add( ClientMessageConst.EVENT_PARAM_TIME, 0 ); Fixture.fakeNotifyOperation( getId( widget ), ClientMessageConst.EVENT_MOUSE_DOWN, parameters ); } + + private static void ensureOperationMode( OperationMode operationMode ) { + LifeCycleFactory lifeCycleFactory = getApplicationContext().getLifeCycleFactory(); + lifeCycleFactory.deactivate(); + if( SWT_COMPATIBILITY.equals( operationMode ) ) { + lifeCycleFactory.configure( RWTLifeCycle.class ); + } + lifeCycleFactory.activate(); + } private static class LoggingListener implements Listener { private final List events; diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/combokit/ComboOperationHandler_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/combokit/ComboOperationHandler_Test.java index 1b234b8360..e099ff1af8 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/combokit/ComboOperationHandler_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/combokit/ComboOperationHandler_Test.java @@ -10,6 +10,7 @@ ******************************************************************************/ package org.eclipse.swt.internal.widgets.combokit; +import static org.eclipse.rap.rwt.application.Application.OperationMode.SWT_COMPATIBILITY; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_DEFAULT_SELECTION; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_FOCUS_IN; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_FOCUS_OUT; @@ -21,6 +22,7 @@ import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_MOUSE_UP; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_SELECTION; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_TRAVERSE; +import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -34,8 +36,11 @@ import org.eclipse.rap.json.JsonArray; import org.eclipse.rap.json.JsonObject; +import org.eclipse.rap.rwt.application.Application.OperationMode; +import org.eclipse.rap.rwt.internal.lifecycle.LifeCycleFactory; import org.eclipse.rap.rwt.internal.lifecycle.PhaseId; import org.eclipse.rap.rwt.internal.lifecycle.ProcessActionRunner; +import org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle; import org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil; import org.eclipse.rap.rwt.internal.protocol.ClientMessageConst; import org.eclipse.rap.rwt.testfixture.internal.Fixture; @@ -314,7 +319,8 @@ public void testHandleNotifyFocusOut() { } @Test - public void testHandleNotifyMouseDown() { + public void testHandleNotifyMouseDownJeeMode() { + ensureOperationMode( OperationMode.JEE_COMPATIBILITY ); Combo spyCombo = spy( combo ); handler = new ComboOperationHandler( spyCombo ); JsonObject properties = new JsonObject() @@ -337,9 +343,37 @@ public void testHandleNotifyMouseDown() { assertEquals( 4, event.time ); assertEquals( 1, event.count ); } + + @Test + public void testHandleNotifyMouseDownSwtMode() { + ensureOperationMode( OperationMode.SWT_COMPATIBILITY ); + Combo spyCombo = spy( combo ); + handler = new ComboOperationHandler( spyCombo ); + JsonObject properties = new JsonObject() + .add( "altKey", true ) + .add( "shiftKey", true ) + .add( "button", 1 ) + .add( "x", 2 ) + .add( "y", 3 ) + .add( "time", 4 ); + + handler.handleNotify( EVENT_MOUSE_DOWN, properties ); + + ArgumentCaptor captor = ArgumentCaptor.forClass( Event.class ); + verify( spyCombo ).notifyListeners( eq( SWT.MouseDown ), captor.capture() ); + Event event = captor.getValue(); + assertEquals( SWT.ALT | SWT.SHIFT, event.stateMask ); + assertEquals( 1, event.button ); + assertEquals( 1, event.x ); + assertEquals( 2, event.y ); + assertEquals( 4, event.time ); + assertEquals( 1, event.count ); + } + @Test - public void testHandleNotifyMouseDoubleClick() { + public void testHandleNotifyMouseDoubleClickJeeMode() { + ensureOperationMode( OperationMode.JEE_COMPATIBILITY ); Combo spyCombo = spy( combo ); handler = new ComboOperationHandler( spyCombo ); JsonObject properties = new JsonObject() @@ -362,6 +396,33 @@ public void testHandleNotifyMouseDoubleClick() { assertEquals( 4, event.time ); assertEquals( 2, event.count ); } + + @Test + public void testHandleNotifyMouseDoubleClickSwtMode() { + ensureOperationMode( OperationMode.SWT_COMPATIBILITY ); + Combo spyCombo = spy( combo ); + handler = new ComboOperationHandler( spyCombo ); + JsonObject properties = new JsonObject() + .add( "altKey", true ) + .add( "shiftKey", true ) + .add( "button", 1 ) + .add( "x", 2 ) + .add( "y", 3 ) + .add( "time", 4 ); + + handler.handleNotify( EVENT_MOUSE_DOUBLE_CLICK, properties ); + + ArgumentCaptor captor = ArgumentCaptor.forClass( Event.class ); + verify( spyCombo ).notifyListeners( eq( SWT.MouseDoubleClick ), captor.capture() ); + Event event = captor.getValue(); + assertEquals( SWT.ALT | SWT.SHIFT, event.stateMask ); + assertEquals( 1, event.button ); + assertEquals( 1, event.x ); + assertEquals( 2, event.y ); + assertEquals( 4, event.time ); + assertEquals( 2, event.count ); + } + @Test public void testHandleNotifyMouseUp() { @@ -481,4 +542,12 @@ private static Point getPreservedSelection( Combo combo ) { return ( Point )adapter.getPreserved( "selection" ); } + private static void ensureOperationMode( OperationMode operationMode ) { + LifeCycleFactory lifeCycleFactory = getApplicationContext().getLifeCycleFactory(); + lifeCycleFactory.deactivate(); + if( SWT_COMPATIBILITY.equals( operationMode ) ) { + lifeCycleFactory.configure( RWTLifeCycle.class ); + } + lifeCycleFactory.activate(); + } } diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/treekit/TreeOperationHandler_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/treekit/TreeOperationHandler_Test.java index cb6a770591..e1c75b3926 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/treekit/TreeOperationHandler_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/treekit/TreeOperationHandler_Test.java @@ -10,6 +10,7 @@ ******************************************************************************/ package org.eclipse.swt.internal.widgets.treekit; +import static org.eclipse.rap.rwt.application.Application.OperationMode.SWT_COMPATIBILITY; import static org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil.getId; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_COLLAPSE; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_DEFAULT_SELECTION; @@ -25,6 +26,7 @@ import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_SELECTION; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_SET_DATA; import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_TRAVERSE; +import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; @@ -38,6 +40,9 @@ import org.eclipse.rap.json.JsonArray; import org.eclipse.rap.json.JsonObject; import org.eclipse.rap.rwt.RWT; +import org.eclipse.rap.rwt.application.Application.OperationMode; +import org.eclipse.rap.rwt.internal.lifecycle.LifeCycleFactory; +import org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle; import org.eclipse.rap.rwt.testfixture.internal.Fixture; import org.eclipse.swt.SWT; import org.eclipse.swt.internal.widgets.CellToolTipUtil; @@ -240,7 +245,8 @@ public void testHandleNotifyFocusOut() { } @Test - public void testHandleNotifyMouseDown() { + public void testHandleNotifyMouseDownJeeMode() { + ensureOperationMode( OperationMode.JEE_COMPATIBILITY ); Tree spyTree = spy( tree ); handler = new TreeOperationHandler( spyTree ); @@ -263,6 +269,32 @@ public void testHandleNotifyMouseDown() { assertEquals( 4, event.time ); assertEquals( 1, event.count ); } + + @Test + public void testHandleNotifyMouseDownSwtMode() { + ensureOperationMode( OperationMode.SWT_COMPATIBILITY ); + Tree spyTree = spy( tree ); + handler = new TreeOperationHandler( spyTree ); + + JsonObject properties = new JsonObject() + .add( "altKey", true ) + .add( "shiftKey", true ) + .add( "button", 1 ) + .add( "x", 2 ) + .add( "y", 3 ) + .add( "time", 4 ); + handler.handleNotify( EVENT_MOUSE_DOWN, properties ); + + ArgumentCaptor captor = ArgumentCaptor.forClass( Event.class ); + verify( spyTree ).notifyListeners( eq( SWT.MouseDown ), captor.capture() ); + Event event = captor.getValue(); + assertEquals( SWT.ALT | SWT.SHIFT, event.stateMask ); + assertEquals( 1, event.button ); + assertEquals( 2, event.x ); + assertEquals( 3, event.y ); + assertEquals( 4, event.time ); + assertEquals( 1, event.count ); + } @Test public void testHandleNotifyMouseDown_skippedOnHeader() { @@ -283,7 +315,8 @@ public void testHandleNotifyMouseDown_skippedOnHeader() { } @Test - public void testHandleNotifyMouseDoubleClick() { + public void testHandleNotifyMouseDoubleClickJeeMode() { + ensureOperationMode( OperationMode.JEE_COMPATIBILITY ); Tree spyTree = spy( tree ); handler = new TreeOperationHandler( spyTree ); @@ -306,6 +339,33 @@ public void testHandleNotifyMouseDoubleClick() { assertEquals( 4, event.time ); assertEquals( 2, event.count ); } + + @Test + public void testHandleNotifyMouseDoubleClickSwtMode() { + ensureOperationMode( OperationMode.SWT_COMPATIBILITY ); + Tree spyTree = spy( tree ); + handler = new TreeOperationHandler( spyTree ); + + JsonObject properties = new JsonObject() + .add( "altKey", true ) + .add( "shiftKey", true ) + .add( "button", 1 ) + .add( "x", 2 ) + .add( "y", 3 ) + .add( "time", 4 ); + handler.handleNotify( EVENT_MOUSE_DOUBLE_CLICK, properties ); + + ArgumentCaptor captor = ArgumentCaptor.forClass( Event.class ); + verify( spyTree ).notifyListeners( eq( SWT.MouseDoubleClick ), captor.capture() ); + Event event = captor.getValue(); + assertEquals( SWT.ALT | SWT.SHIFT, event.stateMask ); + assertEquals( 1, event.button ); + assertEquals( 2, event.x ); + assertEquals( 3, event.y ); + assertEquals( 4, event.time ); + assertEquals( 2, event.count ); + } + @Test public void testHandleNotifyMouseUp() { @@ -509,4 +569,12 @@ private static ITreeAdapter getTreeAdapter( Tree tree ) { return tree.getAdapter( ITreeAdapter.class ); } + private static void ensureOperationMode( OperationMode operationMode ) { + LifeCycleFactory lifeCycleFactory = getApplicationContext().getLifeCycleFactory(); + lifeCycleFactory.deactivate(); + if( SWT_COMPATIBILITY.equals( operationMode ) ) { + lifeCycleFactory.configure( RWTLifeCycle.class ); + } + lifeCycleFactory.activate(); + } } From 0ce2ed8320306afc66b57bdeb0b1a3121f05ba8c Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Tue, 24 Sep 2024 11:10:00 +0200 Subject: [PATCH 10/11] Preventing NPE because of backcalls from super constructor SWT does not call getBackground/getForeground/getFont during construction, so RWT should not too. Also-by: Ralf Schlesinger --- .../org/eclipse/swt/graphics/ControlGC.java | 8 +-- .../src/org/eclipse/swt/widgets/Control.java | 49 ++++++++++++++++++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java index fe38af851c..b6181de998 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/ControlGC.java @@ -48,16 +48,16 @@ class ControlGC extends GCDelegate { ControlGC( Control control ) { this.control = control; - background = control.getBackground(); - foreground = control.getForeground(); - font = control.getFont(); + font = control.getFontInternal(); + background = control.getBackgroundInternal(); + foreground = control.getForegroundInternal(); alpha = 255; lineWidth = 0; lineCap = SWT.CAP_FLAT; lineJoin = SWT.JOIN_MITER; lineStyle = SWT.LINE_SOLID; } - + @Override void setBackground( Color color ) { if( !background.equals( color ) ) { diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Control.java index d8367ef0bb..6e4379ef78 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Control.java @@ -519,7 +519,7 @@ public void setBackground( Color color ) { background = color; updateBackground(); } - + /** * Returns the receiver's background color. * @@ -531,6 +531,21 @@ public void setBackground( Color color ) { * */ public Color getBackground() { + return getBackgroundInternal(); + } + + /** + * Returns the receiver's background color. + * SWT often uses the raw property, this method gets the raw value and not an overriden one. + * + * @return the background color + * + * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
+ */ + public final Color getBackgroundInternal() { checkWidget(); Control control = findBackgroundControl(); if( control == null ) { @@ -543,7 +558,7 @@ public Color getBackground() { Shell shell = control.getShell(); control = control.parent; while( result == null && control != null ) { - result = control.getBackground(); + result = control.getBackgroundInternal(); control = control == shell ? null : control.parent; } if( result == null ) { @@ -643,6 +658,21 @@ public void setForeground( Color color ) { * */ public Color getForeground() { + return getForegroundInternal(); + } + + /** + * Returns the foreground color that the receiver will use to draw. + * SWT often uses the raw property, this method gets the raw value and not an overriden one. + * + * @return the receiver's foreground color + * + * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
+ */ + public final Color getForegroundInternal() { checkWidget(); Color result = foreground; if( result == null ) { @@ -762,6 +792,21 @@ public void setFont( Font font ) { * */ public Font getFont() { + return getFontInternal(); + } + + /** + * Returns the font that the receiver will use to paint textual information. + * SWT often uses the raw property, this method gets the raw value and not an overriden one. + * + * @return the receiver's font + * + * @exception SWTException
    + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
+ */ + public final Font getFontInternal() { checkWidget(); Font result = font; if( result == null ) { From 42d4d24e4ab76dda526a86ea6e8fb0c5a6172cb2 Mon Sep 17 00:00:00 2001 From: Pascal Weyprecht Date: Tue, 24 Sep 2024 12:08:09 +0200 Subject: [PATCH 11/11] Added vertical offset for swt compatible drawing RAP is drawing text on coordinate 0,0 everytime at the top. RCP is stepping down and introduces something like a margin. We set the margins to get in most cases good looking texts. Could be wrong sometimes and off by 1. Also-by: Ralf Schlesinger Also-by: Rico Scholz --- .../src/org/eclipse/swt/graphics/GC.java | 7 ++-- .../swt/internal/graphics/FontUtil.java | 36 +++++++++++++++++-- .../eclipse/swt/graphics/ControlGC_Test.java | 6 ++-- .../canvaskit/GCOperationWriter_Test.java | 15 +++++--- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/GC.java index 7b7d78dbd0..a36e97d953 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/graphics/GC.java @@ -17,6 +17,7 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.SWTException; +import org.eclipse.swt.internal.graphics.FontUtil; import org.eclipse.swt.widgets.Control; @@ -1726,9 +1727,9 @@ public void drawText( String string, int x, int y, int flags ) { checkDisposed(); if( string == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); - } - if( string.length() != 0 ) { - delegate.drawText( string, x, y, flags ); + } else if( string.length() != 0 ) { + int normalizedHeight = (int) Math.round(getFont().getFontData()[0].getHeight() / FontUtil.LINE_HEIGHT_FACTOR); + delegate.drawText(string, x, y + FontUtil.getVerticalOffset(normalizedHeight), flags); } } diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/internal/graphics/FontUtil.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/internal/graphics/FontUtil.java index d5eac87bda..27f197a0a3 100644 --- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/internal/graphics/FontUtil.java +++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/internal/graphics/FontUtil.java @@ -10,16 +10,48 @@ ******************************************************************************/ package org.eclipse.swt.internal.graphics; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.rap.rwt.internal.service.ServletLog; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; public class FontUtil { - + + public static final double LINE_HEIGHT_FACTOR = 1.4; + private static final Map VERTICAL_OFFSET_MAP = new HashMap<>(); + static { + VERTICAL_OFFSET_MAP.put( Integer.valueOf(7), Integer.valueOf(2) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(8), Integer.valueOf(2) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(9), Integer.valueOf(2) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(10), Integer.valueOf(4) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(11), Integer.valueOf(4) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(12), Integer.valueOf(6) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(13), Integer.valueOf(6) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(14), Integer.valueOf(6) ); + VERTICAL_OFFSET_MAP.put( Integer.valueOf(15), Integer.valueOf(9) ); + } + public static FontData getData( Font font ) { return font.getFontData()[ 0 ]; } - + + /** + * + * returns the vertical offset needed for a given character height to simulate Windows + * behavior in + * RAP + * + * @param charHeight + * @return vertical offset in px (default 0 when + * charHeight not in between 7 and 15) + + */ + public static int getVerticalOffset( int charHeight ) { + Integer charHeightInteger = Integer.valueOf( charHeight ); + if( VERTICAL_OFFSET_MAP.containsKey( charHeightInteger ) ) { + return VERTICAL_OFFSET_MAP.get( charHeightInteger ).intValue(); + } + ServletLog.log( "charHeight must be between 7 and 15 for vertival offset estimation", null ); + return 0; + } + private FontUtil() { // prevent instance creation } diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/graphics/ControlGC_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/graphics/ControlGC_Test.java index 085b32a484..a975ba73f8 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/graphics/ControlGC_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/graphics/ControlGC_Test.java @@ -654,7 +654,8 @@ public void testDrawText() { DrawText operation = ( DrawText )gcOperations[ 0 ]; assertEquals( "text", operation.text ); assertEquals( 10, operation.x ); - assertEquals( 10, operation.y ); + // vertical offset for swt compatibility + assertEquals( 14, operation.y ); assertEquals( SWT.DRAW_TRANSPARENT, operation.flags ); } @@ -672,7 +673,8 @@ public void testDrawString() { DrawText operation = ( DrawText )gcOperations[ 0 ]; assertEquals( "text", operation.text ); assertEquals( 10, operation.x ); - assertEquals( 10, operation.y ); + // vertical offset for swt compatibility + assertEquals( 14, operation.y ); assertEquals( SWT.DRAW_TRANSPARENT, operation.flags ); } diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/GCOperationWriter_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/GCOperationWriter_Test.java index 0278444c4b..73ceb44265 100644 --- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/GCOperationWriter_Test.java +++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/swt/internal/widgets/canvaskit/GCOperationWriter_Test.java @@ -573,7 +573,8 @@ public void testDrawText() { gc.drawText( "foo", 30, 34, true ); JsonArray ops = getGCOperations( canvas ); - assertEquals( "[\"strokeText\",\"foo\",false,true,true,30,34]", getOperation( 0, ops ) ); + // vertical offset for swt compatibility + assertEquals( "[\"strokeText\",\"foo\",false,true,true,30,38]", getOperation( 0, ops ) ); } @Test @@ -581,7 +582,8 @@ public void testDrawTextWithMenmonic() { gc.drawText( "foo", 30, 34, SWT.DRAW_MNEMONIC ); JsonArray ops = getGCOperations( canvas ); - assertEquals( "[\"fillText\",\"foo\",true,false,false,30,34]", getOperation( 0, ops ) ); + // vertical offset for swt compatibility + assertEquals( "[\"fillText\",\"foo\",true,false,false,30,38]", getOperation( 0, ops ) ); } @Test @@ -589,7 +591,8 @@ public void testDrawTextWithDelimiter() { gc.drawText( "foo", 30, 34, SWT.DRAW_DELIMITER ); JsonArray ops = getGCOperations( canvas ); - assertEquals( "[\"fillText\",\"foo\",false,true,false,30,34]", getOperation( 0, ops ) ); + // vertical offset for swt compatibility + assertEquals( "[\"fillText\",\"foo\",false,true,false,30,38]", getOperation( 0, ops ) ); } @Test @@ -597,7 +600,8 @@ public void testDrawTextWithTab() { gc.drawText( "foo", 30, 34, SWT.DRAW_TAB ); JsonArray ops = getGCOperations( canvas ); - assertEquals( "[\"fillText\",\"foo\",false,false,true,30,34]", getOperation( 0, ops ) ); + // vertical offset for swt compatibility + assertEquals( "[\"fillText\",\"foo\",false,false,true,30,38]", getOperation( 0, ops ) ); } @Test @@ -605,7 +609,8 @@ public void testFillText() { gc.drawText( "foo", 30, 34 ); JsonArray ops = getGCOperations( canvas ); - assertEquals( "[\"fillText\",\"foo\",false,true,true,30,34]", getOperation( 0, ops ) ); + // vertical offset for swt compatibility + assertEquals( "[\"fillText\",\"foo\",false,true,true,30,38]", getOperation( 0, ops ) ); } // bug 351216: [GC] Throws unexpected "Graphic is diposed" exception