diff options
123 files changed, 4027 insertions, 3351 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..69b47b5ade --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.bat text eol=crlf diff --git a/Jenkinsfile b/Jenkinsfile index 53cbd9aa8e..9c77094625 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -21,7 +21,7 @@ spec: memory: "512Mi" cpu: "500m" - name: container - image: akurtakov/swtbuild@sha256:2cd3dfdea1f250597c9e3797512953c03e2182344e86976c1b60117c5dd36a9e + image: akurtakov/swtbuild@sha256:fca953c5f0fa9fadb92b1875c1942f6042f4bd51327d1e1e8e40f39923103fe1 tty: true command: [ "uid_entrypoint", "cat" ] resources: @@ -87,7 +87,7 @@ spec: checkout scm } dir ('eclipse.platform.swt.binaries') { - checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CloneOption', timeout: 120]], submoduleCfg: [], userRemoteConfigs: [[url: 'https://git.eclipse.org/r/platform/eclipse.platform.swt.binaries.git']]]) + checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CloneOption', timeout: 120, depth: 1, shallow: true]], submoduleCfg: [], userRemoteConfigs: [[url: 'https://git.eclipse.org/r/platform/eclipse.platform.swt.binaries.git']]]) } } } @@ -129,7 +129,7 @@ spec: } steps { container('jnlp') { - sh "wget https://git.eclipse.org/c/platform/eclipse.platform.releng.aggregator.git/plain/scripts/verifyFreezePeriod.sh" + sh "wget https://download.eclipse.org/eclipse/relengScripts/scripts/verifyFreezePeriod.sh" sh "chmod +x verifyFreezePeriod.sh" withCredentials([string(credentialsId: 'google-api-key', variable: 'GOOGLE_API_KEY')]) { sh './verifyFreezePeriod.sh' diff --git a/bundles/org.eclipse.swt.tools.base/pom.xml b/bundles/org.eclipse.swt.tools.base/pom.xml index 4781c4b4e0..0b736e7934 100644 --- a/bundles/org.eclipse.swt.tools.base/pom.xml +++ b/bundles/org.eclipse.swt.tools.base/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF b/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF index 91bb72ee99..08b3d9e589 100644 --- a/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.swt.tools.spies;singleton:=true -Bundle-Version: 3.108.200.qualifier +Bundle-Version: 3.108.300.qualifier Bundle-ManifestVersion: 2 Export-Package: org.eclipse.swt.tools.internal, org.eclipse.swt.tools.views @@ -12,7 +12,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.4.0", org.eclipse.swt.tools.base;bundle-version="3.106.0", org.eclipse.e4.ui.model.workbench;bundle-version="2.1.400", - org.eclipse.swt;bundle-version="3.110.100", + org.eclipse.swt;bundle-version="3.119.0", org.eclipse.ui;bundle-version="3.113.0", org.eclipse.e4.ui.di;bundle-version="1.2.600" Automatic-Module-Name: org.eclipse.swt.tools.spies diff --git a/bundles/org.eclipse.swt.tools.spies/fragment.e4xmi b/bundles/org.eclipse.swt.tools.spies/fragment.e4xmi index e38c21a056..ac12910e99 100644 --- a/bundles/org.eclipse.swt.tools.spies/fragment.e4xmi +++ b/bundles/org.eclipse.swt.tools.spies/fragment.e4xmi @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="ASCII"?> <fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/descriptor/basic" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmi:id="_-LZIEN9kEemzyrbiRClN6A"> <fragments xsi:type="fragment:StringModelFragment" xmi:id="__HWaAN9kEemzyrbiRClN6A" featurename="descriptors" parentElementId="xpath:/"> - <elements xsi:type="basic:PartDescriptor" xmi:id="_GSP6cN9lEemzyrbiRClN6A" elementId="org.eclipse.swt.tools.spies.partdescriptor.sleak" label="Sleak" iconURI="platform:/plugin/org.eclipse.swt.tools.spies/icons/sleak.png" category="SWT Tools" contributionURI="bundleclass://org.eclipse.swt.tools.spies/org.eclipse.swt.tools.views.SleakView"> - <persistedState key="persistState" value="false"/> + <elements xsi:type="basic:PartDescriptor" xmi:id="_GSP6cN9lEemzyrbiRClN6A" elementId="org.eclipse.swt.tools.spies.partdescriptor.sleak" label="Sleak" iconURI="platform:/plugin/org.eclipse.swt.tools.spies/icons/sleak.png" category="SWT Tools" closeable="true" contributionURI="bundleclass://org.eclipse.swt.tools.spies/org.eclipse.swt.tools.views.SleakView"> + <persistedState key="persistState" value="true"/> <tags>View</tags> </elements> </fragments> diff --git a/bundles/org.eclipse.swt.tools.spies/pom.xml b/bundles/org.eclipse.swt.tools.spies/pom.xml index 5b6176c44e..70b8a6f430 100644 --- a/bundles/org.eclipse.swt.tools.spies/pom.xml +++ b/bundles/org.eclipse.swt.tools.spies/pom.xml @@ -14,11 +14,11 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> <artifactId>org.eclipse.swt.tools.spies</artifactId> - <version>3.108.200-SNAPSHOT</version> + <version>3.108.300-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java index 5358aabf22..8d9655d877 100644 --- a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java +++ b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java @@ -15,10 +15,13 @@ package org.eclipse.swt.tools.internal; import java.io.*; import java.util.*; +import java.util.function.*; import java.util.stream.*; import org.eclipse.swt.*; +import org.eclipse.swt.custom.*; import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.WidgetSpy.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.widgets.List; @@ -33,21 +36,22 @@ import org.eclipse.swt.widgets.List; public class Sleak { List list; Canvas canvas; - Button enableTracking, snapshot, diff, stackTrace, saveAs, save; + Button enableTracking, diff, stackTrace, saveAs, save; Combo diffType; Text text; - Label label; String filterPath = ""; String fileName = "sleakout"; - String selectedName = null; + String selectedName; boolean incrementFileNames = true; boolean saveImages = true; - int fileCount = 0; + int fileCount; java.util.List<ObjectWithError> oldObjects = new ArrayList<> (); java.util.List<ObjectWithError> objects = new ArrayList<> (); + NonDisposedWidgetTracker nonDisposedWidgetTracker = new NonDisposedWidgetTracker(); + public static void main (String [] args) { DeviceData data = new DeviceData(); data.tracking = true; @@ -90,71 +94,109 @@ public static void main (String [] args) { } public void create (Composite parent) { - enableTracking = new Button (parent, SWT.CHECK); - enableTracking.setText ("Enable"); - enableTracking.setToolTipText("Enable Device resource tracking. Only resources allocated once enabled will be tracked. To track devices created before view is created, turn on tracing options, see https://www.eclipse.org/swt/tools.php"); - enableTracking.addListener (SWT.Selection, e -> toggleEnableTracking ()); - enableTracking.setSelection(enableTracking.getDisplay().isTracking()); - canvas = new Canvas (parent, SWT.BORDER); + + SashForm sash = new SashForm(parent, SWT.SMOOTH); + sash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + sash.setOrientation(SWT.HORIZONTAL); + sash.setVisible(true); + + Composite left = new Composite(sash, 0); + left.setLayout(new GridLayout()); + left.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + Composite right = new Composite(sash, 0); + right.setLayout(new GridLayout()); + + sash.setWeights(new int[] {40,60}); + + // Right side + canvas = new Canvas (right, SWT.BORDER); canvas.addListener (SWT.Paint, event -> paintCanvas (event)); canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 10)); - text = new Text (parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + text = new Text (right, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 10)); setVisible(text, false); - snapshot = new Button (parent, SWT.PUSH); - snapshot.setText ("Snap"); - snapshot.addListener (SWT.Selection, event -> refreshAll ()); - snapshot.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false)); - diff = new Button (parent, SWT.PUSH); - diff.setText ("Diff"); + + // Left side + enableTracking = new Button (left, SWT.CHECK); + enableTracking.setText ("Enable resource tracking"); + enableTracking.setToolTipText("Enable Device resource tracking. Only resources allocated once enabled will be tracked. To track devices created before view is created, turn on tracing options, see https://www.eclipse.org/swt/tools.php"); + enableTracking.addListener (SWT.Selection, e -> toggleEnableTracking ()); + enableTracking.setSelection(enableTracking.getDisplay().isTracking()); + enableTracking.setLayoutData(new GridData(SWT.NONE, SWT.NONE, false, false)); + + Composite buttons = new Composite(left, 0); + buttons.setLayout(new GridLayout(4, false)); + buttons.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); + + diff = new Button (buttons, SWT.PUSH); + diff.setText ("Snap && Diff"); diff.addListener (SWT.Selection, event -> refreshDifference ()); - diff.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false)); - diffType = new Combo (parent, SWT.CHECK); + GridData diffData = new GridData(SWT.FILL, SWT.NONE, true, false); + diffData.horizontalSpan = 2; + diff.setLayoutData(diffData); + + save = new Button (buttons, SWT.PUSH); + save.setText ("Save"); + save.setToolTipText("Saves to the previously selected file."); + save.addListener (SWT.Selection, event -> saveToFile (false)); + save.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false)); + + saveAs = new Button (buttons, SWT.PUSH); + saveAs.setText ("Save As..."); + saveAs.setToolTipText("Saves the contents of the list to a file, optionally with the stack traces if selected."); + saveAs.addListener (SWT.Selection, event -> saveToFile (true)); + saveAs.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false)); + + Composite checkboxAndCombo = new Composite(left, 0); + checkboxAndCombo.setLayout(new GridLayout(2, false)); + checkboxAndCombo.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); + + diffType = new Combo (checkboxAndCombo, SWT.CHECK); diffType.add ("Object identity"); diffType.add ("Creator class and line"); diffType.add ("Creator class"); diffType.select(0); - diffType.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false)); - stackTrace = new Button (parent, SWT.CHECK); - stackTrace.setText ("Stack"); + diffType.setLayoutData(new GridData(SWT.NONE, SWT.NONE, false, false)); + + stackTrace = new Button (checkboxAndCombo, SWT.CHECK); + stackTrace.setText ("Show Stack"); stackTrace.addListener (SWT.Selection, e -> toggleStackTrace ()); - list = new List (parent, SWT.BORDER | SWT.V_SCROLL); + stackTrace.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE, true, false)); + + list = new List (left, SWT.BORDER | SWT.V_SCROLL); list.addListener (SWT.Selection, event -> refreshObject ()); - list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true)); - label = new Label (parent, SWT.NONE); - label.setText ("0 object(s)"); - saveAs = new Button (parent, SWT.PUSH); - saveAs.setText ("Save As..."); - saveAs.setToolTipText("Saves the contents of the list to a file, optionally with the stack traces if selected."); - saveAs.addListener (SWT.Selection, event -> saveToFile (true)); - saveAs.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false)); - save = new Button (parent, SWT.PUSH); - save.setText ("Save"); - save.setToolTipText("Saves to the previously selected file."); - save.addListener (SWT.Selection, event -> saveToFile (false)); - save.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false)); + list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + stackTrace.setSelection (false); + filterNonDisposedWidgetTypes(); } private void toggleEnableTracking() { Display display = enableTracking.getDisplay(); boolean tracking = display.isTracking(); display.setTracking(!tracking); + setWidgetTrackingEnabled(tracking); } -void refreshLabel () { - Map<String, Long> deleted = oldObjects.stream().collect( - Collectors.groupingBy(o -> o.object.getClass().getSimpleName(), Collectors.counting())); - Map<String, Long> created = objects.stream().collect( - Collectors.groupingBy(o -> o.object.getClass().getSimpleName(), Collectors.counting())); +void refreshLabel (java.util.List<ObjectWithError> createdObjects, java.util.List<ObjectWithError> deletedObjects) { + Function<? super ObjectWithError, ? extends String> classifier = o -> o.object.getClass().getSimpleName(); + + Map<String, Long> deleted = deletedObjects.stream().collect( + Collectors.groupingBy(classifier, Collectors.counting())); + + Map<String, Long> created = createdObjects.stream().collect( + Collectors.groupingBy(classifier, Collectors.counting())); + StringBuilder sb = new StringBuilder(); - Stream.concat(deleted.keySet().stream(), created.keySet().stream()).distinct().sorted(). - forEach(type -> addCounts(sb, type, deleted.get(type), created.get(type))); - label.setText (sb.length() > 0 ? sb.toString() : "0 object(s)"); - canvas.getParent().layout(); + Stream<String> deletedAndCreated = Stream.concat(deleted.keySet().stream(), created.keySet().stream()); + deletedAndCreated.distinct().sorted().forEach(type -> addCounts(sb, type, deleted.get(type), created.get(type))); + + String description = sb.length() > 0 ? sb.toString() : "0 object(s)"; + list.setToolTipText(description); } -void addCounts (StringBuilder string, String type, Long deleted, Long created) { +static void addCounts (StringBuilder string, String type, Long deleted, Long created) { if (deleted != null || created != null) { if (deleted != null) { string.append("-" + deleted); @@ -171,57 +213,104 @@ void addCounts (StringBuilder string, String type, Long deleted, Long created) { void refreshDifference () { Display display = canvas.getDisplay(); - DeviceData info = display.getDeviceData (); - if (!info.tracking) { - Shell shell = canvas.getShell(); - MessageBox dialog = new MessageBox (shell, SWT.ICON_WARNING | SWT.YES | SWT.NO); - dialog.setText (shell.getText ()); - dialog.setMessage ("Warning: Device is not tracking resource allocation\nWould you like to enable tracking now for future created resources?"); - if (SWT.YES == dialog.open ()) { - enableTracking.setSelection(true); - toggleEnableTracking(); + DeviceData info = getDeviceData(display); + + boolean hasOldData = !oldObjects.isEmpty(); + + java.util.List<ObjectWithError> old = new ArrayList<>(oldObjects); + java.util.List<ObjectWithError> disposed = new ArrayList<>(); + java.util.List<ObjectWithError> created = new ArrayList<>(); + java.util.List<ObjectWithError> same = collectNewObjects(info, old, disposed, created); + java.util.List<ObjectWithError> nonDisposedWidgets = getNonDisposedWidgets(); + created.addAll(nonDisposedWidgets); + resetNonDisposedWidgets(); + + if (diffType.getSelectionIndex() > 0) { + old.removeAll(same); + if (!old.isEmpty()) { + Iterator<ObjectWithError> createdIter = created.iterator (); + while (createdIter.hasNext ()) { + ObjectWithError createdObj = createdIter.next (); + StackTraceElement stack = createdObj.getCreator (); + Iterator<ObjectWithError> oldIter = old.iterator (); + while (oldIter.hasNext ()) { + ObjectWithError oldObj = oldIter.next(); + if (creatorEquals(stack, oldObj.getCreator ())) { + createdIter.remove (); + break; + } + } + } } } + + objects.clear(); + objects.addAll(created); + + oldObjects.clear(); + oldObjects.addAll(same); + oldObjects.addAll(created); + + + list.removeAll (); + text.setText (""); + canvas.redraw (); + if(hasOldData) { + for (ObjectWithError object : created) { + list.add (object.object.toString()); + } + } + if(hasOldData) { + refreshLabel (created, disposed); + } else { + refreshLabel (Collections.emptyList(), Collections.emptyList()); + } +} + +private static java.util.List<ObjectWithError> collectNewObjects(DeviceData info, + java.util.List<ObjectWithError> oldObjects, + java.util.List<ObjectWithError> disposedObjects, + java.util.List<ObjectWithError> createdObjects + ) { + disposedObjects.addAll(oldObjects); + ArrayList<ObjectWithError> sameObjects = new ArrayList<>(); - oldObjects = new ArrayList<> (objects); - objects.clear (); for (int i=0; i<info.objects.length; i++) { boolean found = false; Iterator<ObjectWithError> oldObject = oldObjects.iterator (); - if (!(info.objects [i] instanceof Color)) { + Object infoObject = info.objects [i]; + if (!(infoObject instanceof Color)) { // Bug 563018: Colors don't require disposal, so exclude them from the list of allocated objects. while (oldObject.hasNext () && !found) { - if (info.objects [i] == oldObject.next ().object) { - oldObject.remove (); + ObjectWithError next = oldObject.next (); + if (infoObject == next.object) { + sameObjects.add(next); found = true; } } if (!found) { - objects.add (new ObjectWithError (info.objects [i], info.errors[i])); + createdObjects.add(new ObjectWithError (infoObject, info.errors[i])); } } } - if (diffType.getSelectionIndex() > 0) { - Iterator<ObjectWithError> object = objects.iterator (); - while (object.hasNext ()) { - StackTraceElement stack = object.next ().getCreator (); - Iterator<ObjectWithError> old = oldObjects.iterator (); - while (old.hasNext ()) { - if (creatorEquals(stack, old.next().getCreator ())) { - old.remove (); - object.remove (); - break; - } - } + // objects that were not found in new system state are disposed + disposedObjects.removeAll(sameObjects); + return sameObjects; +} + +private DeviceData getDeviceData(Display display) { + DeviceData info = display.getDeviceData (); + if (!info.tracking) { + Shell shell = canvas.getShell(); + MessageBox dialog = new MessageBox (shell, SWT.ICON_WARNING | SWT.YES | SWT.NO); + dialog.setText (shell.getText ()); + dialog.setMessage ("Warning: Device is not tracking resource allocation\nWould you like to enable tracking now for future created resources?"); + if (SWT.YES == dialog.open ()) { + enableTracking.setSelection(true); + toggleEnableTracking(); } } - list.removeAll (); - text.setText (""); - canvas.redraw (); - for (ObjectWithError object : objects) { - list.add (object.object.toString()); - } - refreshLabel (); + return info; } boolean creatorEquals (StackTraceElement first, StackTraceElement second) { @@ -261,7 +350,7 @@ private void saveToFile(boolean prompt) { fileName = String.format("%s_%03d", fileName, fileCount++); } try (PrintWriter file = new PrintWriter(new FileOutputStream(fileName))) { - + int i = 0; for (ObjectWithError o : objects) { Object object = o.object; @@ -386,7 +475,7 @@ void refreshObject () { text.setText (objects.get(index).getStack()); setVisible(text, true); setVisible(canvas, false); - canvas.getParent().layout(); + text.getParent().layout(); } else { setVisible(canvas, true); setVisible(text, false); @@ -399,10 +488,26 @@ private void setVisible(Control control, boolean visible) { ((GridData)control.getLayoutData()).exclude = !visible; } -void refreshAll () { - objects.clear(); - refreshDifference (); - oldObjects = new ArrayList<>(objects); +private void filterNonDisposedWidgetTypes() { + java.util.List<Class<? extends Widget>> trackedTypes = Arrays.asList( +// Composite.class, +// Menu.class + ); + nonDisposedWidgetTracker.setTrackedTypes(trackedTypes); +} + +private void setWidgetTrackingEnabled(boolean tracking) { + nonDisposedWidgetTracker.setTrackingEnabled(tracking); +} + +private java.util.List<ObjectWithError> getNonDisposedWidgets() { + java.util.List<ObjectWithError> nonDisposedWidgets = new ArrayList<>(); + nonDisposedWidgetTracker.getNonDisposedWidgets().forEach((w, e) -> nonDisposedWidgets.add(new ObjectWithError(w, e))); + return nonDisposedWidgets; +} + +private void resetNonDisposedWidgets() { + nonDisposedWidgetTracker.startTracking(); } private static final class ObjectWithError { diff --git a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/views/SleakView.java b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/views/SleakView.java index 1f4203f700..e3985864e5 100644 --- a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/views/SleakView.java +++ b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/views/SleakView.java @@ -17,7 +17,6 @@ package org.eclipse.swt.tools.views; import javax.annotation.*; import org.eclipse.e4.ui.di.*; -import org.eclipse.swt.*; import org.eclipse.swt.tools.internal.*; import org.eclipse.swt.widgets.*; @@ -31,9 +30,9 @@ public class SleakView { @PostConstruct public void createPartControl(Composite parent) { - composite = new Composite(parent, SWT.NONE); Sleak sleak = new Sleak (); - sleak.create(composite); + sleak.create(parent); + composite = parent; } @Focus diff --git a/bundles/org.eclipse.swt.tools/pom.xml b/bundles/org.eclipse.swt.tools/pom.xml index e281b98ad9..93a15ed588 100644 --- a/bundles/org.eclipse.swt.tools/pom.xml +++ b/bundles/org.eclipse.swt.tools/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/JSON.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/JSON.java index 2730297b9f..2730297b9f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/JSON.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/JSON.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java index a3fed244b6..d0dce59089 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java @@ -8962,6 +8962,7 @@ void setCaretLocations(final Point[] locations, int direction) { carets[i] = new Caret(this, firstCaret.getStyle()); carets[i].setImage(firstCaret.getImage()); carets[i].setFont(firstCaret.getFont()); + carets[i].setSize(firstCaret.getSize()); } } else if (locations.length < carets.length) { for (int i = locations.length; i < carets.length; i++) { @@ -8969,7 +8970,7 @@ void setCaretLocations(final Point[] locations, int direction) { } carets = Arrays.copyOf(carets, locations.length); } - for (int i = 0; i < Math.min(caretOffsets.length, locations.length); i++) { + for (int i = Math.min(caretOffsets.length, locations.length)-1; i>=0; i--) { // reverse order, seee bug 579028#c7 final Caret caret = carets[i]; final int caretOffset = caretOffsets[i]; final Point location = locations[i]; @@ -9053,6 +9054,7 @@ void setCaretLocations(final Point[] locations, int direction) { } } updateCaretVisibility(); + super.redraw(); } columnX = locations[0].x; } @@ -9239,6 +9241,21 @@ public void setEnabled(boolean enabled) { this.insideSetEnableCall = false; } } + +@Override +public boolean setFocus() { + boolean focusGained = super.setFocus(); + if (focusGained && hasMultipleCarets()) { + // Multiple carets need to update their drawing. See bug 579179 + setCaretLocations(); + } + return focusGained; +} + +private boolean hasMultipleCarets() { + return carets != null && carets.length > 1; +} + /** * Sets a new font to render text with. * <p> @@ -11275,7 +11292,6 @@ void updateCaretVisibility() { c.setVisible(visible); }); } - redraw(); } } /** diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java index af900f9731..7dc98a6f7f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java @@ -13,10 +13,7 @@ *******************************************************************************/ package org.eclipse.swt.dnd; -import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; -import org.eclipse.swt.internal.cairo.*; -import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.widgets.*; /** @@ -83,73 +80,7 @@ public class TableDragSourceEffect extends DragSourceEffect { Image getDragSourceImage(DragSourceEvent event) { if (dragSourceImage != null) dragSourceImage.dispose(); - dragSourceImage = null; - - Table table = (Table) control; - //TEMPORARY CODE - if (table.isListening(SWT.EraseItem) || table.isListening (SWT.PaintItem)) return null; - - /* - * Bug in GTK. gtk_tree_selection_get_selected_rows() segmentation faults - * in versions smaller than 2.2.4 if the model is NULL. The fix is - * to give a valid pointer instead. - */ - long handle = table.handle; - long selection = GTK.gtk_tree_view_get_selection (handle); - long [] model = null; - long list = GTK.gtk_tree_selection_get_selected_rows (selection, model); - if (list == 0) return null; - int count = Math.min(10, OS.g_list_length (list)); - long originalList = list; - - Display display = table.getDisplay(); - if (count == 1) { - long path = OS.g_list_nth_data (list, 0); - long icon = GTK.gtk_tree_view_create_row_drag_icon (handle, path); - dragSourceImage = Image.gtk_new (display, SWT.ICON, icon, 0); - GTK.gtk_tree_path_free (path); - } else { - int width = 0, height = 0; - int[] w = new int[1], h = new int[1]; - int[] yy = new int[count], hh = new int[count]; - long [] icons = new long [count]; - GdkRectangle rect = new GdkRectangle (); - for (int i=0; i<count; i++) { - long path = OS.g_list_data (list); - GTK.gtk_tree_view_get_cell_area (handle, path, 0, rect); - icons[i] = GTK.gtk_tree_view_create_row_drag_icon(handle, path); - switch (Cairo.cairo_surface_get_type(icons[i])) { - case Cairo.CAIRO_SURFACE_TYPE_IMAGE: - w[0] = Cairo.cairo_image_surface_get_width(icons[i]); - h[0] = Cairo.cairo_image_surface_get_height(icons[i]); - break; - case Cairo.CAIRO_SURFACE_TYPE_XLIB: - w[0] = Cairo.cairo_xlib_surface_get_width(icons[i]); - h[0] = Cairo.cairo_xlib_surface_get_height(icons[i]); - break; - } - width = Math.max(width, w[0]); - height = rect.y + h[0] - yy[0]; - yy[i] = rect.y; - hh[i] = h[0]; - list = OS.g_list_next (list); - GTK.gtk_tree_path_free (path); - } - long surface = Cairo.cairo_image_surface_create(Cairo.CAIRO_FORMAT_ARGB32, width, height); - if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES); - long cairo = Cairo.cairo_create(surface); - if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES); - Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE); - for (int i=0; i<count; i++) { - Cairo.cairo_set_source_surface (cairo, icons[i], 2, yy[i] - yy[0] + 2); - Cairo.cairo_rectangle(cairo, 0, yy[i] - yy[0], width, hh[i]); - Cairo.cairo_fill(cairo); - Cairo.cairo_surface_destroy(icons[i]); - } - Cairo.cairo_destroy(cairo); - dragSourceImage = Image.gtk_new (display, SWT.ICON, surface, 0); - } - OS.g_list_free (originalList); + dragSourceImage = TreeTableCommon.getDragSourceImage(control); return dragSourceImage; } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java index d48a177f1c..f6eb7614c9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java @@ -13,10 +13,7 @@ *******************************************************************************/ package org.eclipse.swt.dnd; -import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; -import org.eclipse.swt.internal.cairo.*; -import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.widgets.*; /** @@ -82,73 +79,7 @@ public class TreeDragSourceEffect extends DragSourceEffect { Image getDragSourceImage(DragSourceEvent event) { if (dragSourceImage != null) dragSourceImage.dispose(); - dragSourceImage = null; - - Tree tree = (Tree) control; - //TEMPORARY CODE - if (tree.isListening(SWT.EraseItem) || tree.isListening (SWT.PaintItem)) return null; - - /* - * Bug in GTK. gtk_tree_selection_get_selected_rows() segmentation faults - * in versions smaller than 2.2.4 if the model is NULL. The fix is - * to give a valid pointer instead. - */ - long handle = tree.handle; - long selection = GTK.gtk_tree_view_get_selection (handle); - long [] model = null; - long list = GTK.gtk_tree_selection_get_selected_rows (selection, model); - if (list == 0) return null; - int count = Math.min(10, OS.g_list_length (list)); - long originalList = list; - - Display display = tree.getDisplay(); - if (count == 1) { - long path = OS.g_list_nth_data (list, 0); - long icon = GTK.gtk_tree_view_create_row_drag_icon (handle, path); - dragSourceImage = Image.gtk_new (display, SWT.ICON, icon, 0); - GTK.gtk_tree_path_free (path); - } else { - int width = 0, height = 0; - int[] w = new int[1], h = new int[1]; - int[] yy = new int[count], hh = new int[count]; - long [] icons = new long [count]; - GdkRectangle rect = new GdkRectangle (); - for (int i=0; i<count; i++) { - long path = OS.g_list_data (list); - GTK.gtk_tree_view_get_cell_area (handle, path, 0, rect); - icons[i] = GTK.gtk_tree_view_create_row_drag_icon(handle, path); - switch (Cairo.cairo_surface_get_type(icons[i])) { - case Cairo.CAIRO_SURFACE_TYPE_IMAGE: - w[0] = Cairo.cairo_image_surface_get_width(icons[i]); - h[0] = Cairo.cairo_image_surface_get_height(icons[i]); - break; - case Cairo.CAIRO_SURFACE_TYPE_XLIB: - w[0] = Cairo.cairo_xlib_surface_get_width(icons[i]); - h[0] = Cairo.cairo_xlib_surface_get_height(icons[i]); - break; - } - width = Math.max(width, w[0]); - height = rect.y + h[0] - yy[0]; - yy[i] = rect.y; - hh[i] = h[0]; - list = OS.g_list_next (list); - GTK.gtk_tree_path_free (path); - } - long surface = Cairo.cairo_image_surface_create(Cairo.CAIRO_FORMAT_ARGB32, width, height); - if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES); - long cairo = Cairo.cairo_create(surface); - if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES); - Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE); - for (int i=0; i<count; i++) { - Cairo.cairo_set_source_surface (cairo, icons[i], 2, yy[i] - yy[0] + 2); - Cairo.cairo_rectangle(cairo, 0, yy[i] - yy[0], width, hh[i]); - Cairo.cairo_fill(cairo); - Cairo.cairo_surface_destroy(icons[i]); - } - Cairo.cairo_destroy(cairo); - dragSourceImage = Image.gtk_new (display, SWT.ICON, surface, 0); - } - OS.g_list_free (originalList); + dragSourceImage = TreeTableCommon.getDragSourceImage(control); return dragSourceImage; } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeTableCommon.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeTableCommon.java new file mode 100644 index 0000000000..24560166d3 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeTableCommon.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2000, 2022 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.dnd; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.cairo.*; +import org.eclipse.swt.internal.gtk.*; +import org.eclipse.swt.widgets.*; + +class TreeTableCommon { + static Image getDragSourceImage(Control control) { + Image dragSourceImage; + + /* + * Bug in GTK. gtk_tree_selection_get_selected_rows() segmentation faults + * in versions smaller than 2.2.4 if the model is NULL. The fix is + * to give a valid pointer instead. + */ + long handle = control.handle; + long selection = GTK.gtk_tree_view_get_selection (handle); + long [] model = null; + long list = GTK.gtk_tree_selection_get_selected_rows (selection, model); + if (list == 0) return null; + int count = Math.min(10, OS.g_list_length (list)); + long originalList = list; + + Display display = control.getDisplay(); + if (count == 1) { + long path = OS.g_list_nth_data (list, 0); + long icon = GTK.gtk_tree_view_create_row_drag_icon (handle, path); + dragSourceImage = Image.gtk_new (display, SWT.ICON, icon, 0); + GTK.gtk_tree_path_free (path); + } else { + int width = 0, height = 0; + int[] w = new int[1], h = new int[1]; + int[] yy = new int[count], hh = new int[count]; + long [] icons = new long [count]; + GdkRectangle rect = new GdkRectangle (); + for (int i=0; i<count; i++) { + long path = OS.g_list_data (list); + GTK.gtk_tree_view_get_cell_area (handle, path, 0, rect); + icons[i] = GTK.gtk_tree_view_create_row_drag_icon(handle, path); + switch (Cairo.cairo_surface_get_type(icons[i])) { + case Cairo.CAIRO_SURFACE_TYPE_IMAGE: + w[0] = Cairo.cairo_image_surface_get_width(icons[i]); + h[0] = Cairo.cairo_image_surface_get_height(icons[i]); + break; + case Cairo.CAIRO_SURFACE_TYPE_XLIB: + w[0] = Cairo.cairo_xlib_surface_get_width(icons[i]); + h[0] = Cairo.cairo_xlib_surface_get_height(icons[i]); + break; + } + width = Math.max(width, w[0]); + height = rect.y + h[0] - yy[0]; + yy[i] = rect.y; + hh[i] = h[0]; + list = OS.g_list_next (list); + GTK.gtk_tree_path_free (path); + } + long surface = Cairo.cairo_image_surface_create(Cairo.CAIRO_FORMAT_ARGB32, width, height); + if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES); + long cairo = Cairo.cairo_create(surface); + if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES); + Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE); + for (int i=0; i<count; i++) { + Cairo.cairo_set_source_surface (cairo, icons[i], 2, yy[i] - yy[0] + 2); + Cairo.cairo_rectangle(cairo, 0, yy[i] - yy[0], width, hh[i]); + Cairo.cairo_fill(cairo); + Cairo.cairo_surface_destroy(icons[i]); + } + Cairo.cairo_destroy(cairo); + dragSourceImage = Image.gtk_new (display, SWT.ICON, surface, 0); + } + OS.g_list_free (originalList); + return dragSourceImage; + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java index 3ec3241774..d8bb1b5091 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2021 IBM Corporation and others. + * Copyright (c) 2007, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -21,6 +21,17 @@ public class OS extends C { Library.loadLibrary("swt-pi"); //$NON-NLS-1$ } + /* + * macOS version, encoded as ((major << 16) + (minor << 8) + bugfix). + * + * Note that for macOS >= 11, it has "wrong" values if executable's + * SDK is below 10.15 (or is it 11.0?), where 10.16.0 is reported + * regardless of actual macOS version. On the other hand, with good + * executable's SDK, real version is reported. + * + * This also means that executables with old SDK can't distinguish + * macOS 11 from macOS 12. + */ public static final int VERSION; public static int VERSION (int major, int minor, int bugfix) { @@ -167,6 +178,24 @@ public class OS extends C { * Custom message that will be sent when setTheme is called for example from Platform UI code. */ public static final long sel_appAppearanceChanged = OS.sel_registerName("appAppearanceChanged"); + + /** + * Experimental API for dark theme. + * <p> + * On Windows, there is no OS API for dark theme yet, and this method only + * configures various tweaks. Some of these tweaks have drawbacks. The tweaks + * are configured with defaults that fit Eclipse. Non-Eclipse applications are + * expected to configure individual tweaks instead of calling this method. + * Please see <code>Display#setData()</code> and documentation for string keys + * used there. + * </p> + * <p> + * On GTK, behavior may be different as the boolean flag doesn't force dark + * theme instead it specify that dark theme is preferred. + * </p> + * + * @param isDarkTheme <code>true</code> for dark theme + */ public static void setTheme(boolean isDarkTheme) { OS.objc_msgSend(NSApplication.sharedApplication().id, sel_appAppearanceChanged, isDarkTheme ? 1 : 0); } @@ -190,10 +219,7 @@ public class OS extends C { * @return true for macOS BigSur or later, returns false for macOS 10.15 and older */ public static boolean isBigSurOrLater () { - /* - * Currently Big Sur OS version matches with 10.16 and not 11.0. This may be temporary. - * Creating a method, so that it can be fixed in one place if/when this changes. - */ + // See comment for OS.VERSION for an explanation return OS.VERSION >= OS.VERSION(10, 16, 0); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/common/org/eclipse/swt/internal/Library.java b/bundles/org.eclipse.swt/Eclipse SWT PI/common/org/eclipse/swt/internal/Library.java index c630b9932d..5902733d19 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/common/org/eclipse/swt/internal/Library.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/common/org/eclipse/swt/internal/Library.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. + * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,10 +14,8 @@ package org.eclipse.swt.internal; import java.io.*; -import java.lang.reflect.*; import java.net.*; import java.nio.file.*; -import java.util.function.*; import java.util.jar.*; public class Library { @@ -32,12 +30,12 @@ public class Library { /** * SWT Minor version number (must be in the range 0..999) */ - static int MINOR_VERSION = 950; + static int MINOR_VERSION = 952; /** * SWT revision number (must be >= 0) */ - static int REVISION = 3; + static int REVISION = 6; /** * The JAVA and SWT versions @@ -382,105 +380,4 @@ public static String getVersionString () { return version; } -public static File findResource(String subDir, String resourceName, boolean mapResourceName){ - return findResource(subDir, resourceName, mapResourceName, true, true); -} -/** - * Locates a resource located either in java library path, swt library path, or attempts to extract it from inside swt.jar file. - * This function supports a single level subfolder, e.g SubFolder/resource. - * - * Dev note: (17/12/07) This has been developed and throughly tested on GTK. Designed to work on Cocoa/Win as well, but not tested. - * - * @param subDir 'null' or a folder name without slashes. E.g Correct: 'mysubdir', incorrect: '/subdir/'. - * Platform specific Slashes will be added automatically. - * @param resourceName e.g swt-webkitgtk - * @param mapResourceName true if you like platform specific mapping applied to resource name. e.g MyLib -> libMyLib-gtk-4826.so - */ -public static File findResource(String subDir, String resourceName, boolean mapResourceName, boolean replaceDylib, boolean searchInOsgi){ - - //We construct a 'maybe' subdirectory path. 'Maybe' because if no subDir given, then it's an empty string "". - // subdir e.g: subdir - String maybeSubDirPath = subDir != null ? subDir + SEPARATOR : ""; // e.g: subdir/ or "" - String maybeSubDirPathWithPrefix = subDir != null ? SEPARATOR + maybeSubDirPath : ""; // e.g: /subdir/ or "" - final String finalResourceName = mapResourceName ? - mapLibraryName(resourceName + "-" + Platform.PLATFORM + "-" + getVersionString (), replaceDylib) // e.g libMyLib-gtk-3826.so - : resourceName; - - // 1) Look for the resource in the java/swt library path(s) - // This code commonly finds the resource if the swt project is a required project and the swt binary (for your platform) - // project is open in your workplace (found in the JAVA_LIBRARY_PATH) or if you're explicitly specified SWT_LIBRARY_PATH. - { - Function<String, File> lookForFileInPath = searchPath -> { - String classpath = System.getProperty(searchPath); - if (classpath != null){ - String[] paths = classpath.split(File.pathSeparator); - for (String path : paths) { - File file = new File(path + SEPARATOR + maybeSubDirPath + finalResourceName); - if (file.exists()){ - return file; - } - } - } - return null; - }; - File result = null; - for (String path : new String[] {JAVA_LIB_PATH,SWT_LIB_PATH}) { - result = lookForFileInPath.apply(path); - if (result != null) - return result; - } - } - - // 2) If SWT is ran as OSGI bundle (e.g inside Eclipse), then local resources are extracted to - // eclipse/configuration/org.eclipse.osgi/NN/N/.cp/<resource> and we're given a pointer to the file. - if (searchInOsgi) { - // If this is an OSGI bundle look for the resource using getResource - URL url = Library.class.getClassLoader().getResource(maybeSubDirPathWithPrefix + finalResourceName); - URLConnection connection; - try { - connection = url.openConnection(); - Method getFileURLMethod = connection.getClass().getMethod("getFileURL"); - if (getFileURLMethod != null){ - // This method does the actual extraction of file to: ../eclipse/configuration/org.eclipse.osgi/NN/N/.cp/<SubDir>/resource.ext - URL result = (URL) getFileURLMethod.invoke(connection); - return new File(result.toURI()); - } - } catch (Exception e) { - // If any exceptions are thrown the resource cannot be located this way. - } - } - - // 3) Need to try to pull the resource out of the swt.jar. - // Look for the resource in the user's home directory, (if already extracted in the temp swt folder. (~/.swt/lib...) - // Extract from the swt.jar if not there already. - { - // Developer note: - // To test this piece of code, you need to compile SWT into a jar and use it in a test project. E.g - // cd ~/git/eclipse.platform.swt.binaries/bundles/org.eclipse.swt.gtk.linux.x86_64/ - // mvn clean verify -Pbuild-individual-bundles -Dnative=gtk.linux.x86_64 - // then ./target/ will contain org.eclipse.swt.gtk.linux.x86_64-3.106.100-SNAPSHOT.jar (and it's source), - // you can copy those into your test swt project and test that your resource is extracted into something like ~/.swt/... - // Lastly, if using subDir, you need to edit the build.properties and specify the folder you wish to have included in your jar in the includes. - File file = new File (USER_HOME + SEPARATOR + SWT_LIB_DIR + maybeSubDirPathWithPrefix, finalResourceName); - if (file.exists()){ - return file; - } else { // Try to extract file from jar if not found. - - // Create temp directory if it doesn't exist - File tempDir = new File (USER_HOME, SWT_LIB_DIR + maybeSubDirPathWithPrefix); - if ((!tempDir.exists () || tempDir.isDirectory ())) { - tempDir.mkdirs (); - } - - if (extract(file.getPath(), maybeSubDirPath + finalResourceName)) { - if (file.exists()) { - return file; - } - } - } - } - throw new UnsatisfiedLinkError("Could not find resource " + resourceName + (subDir != null ? " (in subdirectory: " + subDir + " )" : "")); -} - - } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/build.sh b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/build.sh index 3dea89eb97..d1694a9020 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/build.sh +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/build.sh @@ -144,11 +144,22 @@ case $SWT_OS.$SWT_ARCH in export PKG_CONFIG_PATH="/usr/lib64/pkgconfig/" fi ;; + "linux.loongarch64") + if [ "${CC}" = "" ]; then + export CC=gcc + fi + if [ "${JAVA_HOME}" = "" ]; then + export JAVA_HOME=`readlink -f /usr/bin/java | sed "s:jre/bin/java::"` + fi + if [ "${PKG_CONFIG_PATH}" = "" ]; then + export PKG_CONFIG_PATH="/usr/lib64/pkgconfig/" + fi + ;; esac # For 64-bit CPUs, we have a switch -if [ ${MODEL} = 'x86_64' -o ${MODEL} = 'ppc64le' -o ${MODEL} = 'aarch64' ]; then +if [ ${MODEL} = 'x86_64' -o ${MODEL} = 'ppc64le' -o ${MODEL} = 'aarch64' -o ${MODEL} = 'loongarch64' ]; then SWT_PTR_CFLAGS=-DJNI64 if [ -d /lib64 ]; then XLIB64=-L/usr/X11R6/lib64 @@ -174,7 +185,7 @@ fi if [ ${SWT_OS} = 'win32' ]; then AWT_LIB_EXPR="jawt.dll" else - AWT_LIB_EXPR="libjawt.*" + AWT_LIB_EXPR="libjawt.so" fi if [ -z "${AWT_LIB_PATH}" ]; then @@ -254,14 +265,6 @@ func_echo_plus "Building SWT/GTK+ for Architectures: $SWT_OS $SWT_ARCH" func_build_gtk4 () { export GTK_VERSION=4.0 - # Dictate Webkit2 Extension only if pkg-config flags exist - pkg-config --exists webkit2gtk-web-extension-4.0 - if [ $? = 0 ]; then - export BUILD_WEBKIT2EXTENSION="yes"; - else - func_echo_error "Warning: Cannot compile Webkit2 Extension because 'pkg-config --exists webkit2gtk-web-extension-4.0' check failed. Please install webkitgtk4-devel.ARCH on your system." - fi - func_echo_plus "Building GTK4 bindings:" ${MAKE_TYPE} -f $MAKEFILE all $MAKE_CAIRO $MAKE_AWT "${@}" RETURN_VALUE=$? #make can return 1 or 2 if it fails. Thus need to cache it in case it's used programmatically somewhere. @@ -276,14 +279,6 @@ func_build_gtk4 () { func_build_gtk3 () { export GTK_VERSION=3.0 - # Dictate Webkit2 Extension only if pkg-config flags exist - pkg-config --exists webkit2gtk-web-extension-4.0 - if [ $? = 0 ]; then - export BUILD_WEBKIT2EXTENSION="yes"; - else - func_echo_error "Warning: Cannot compile Webkit2 Extension because 'pkg-config --exists webkit2gtk-web-extension-4.0' check failed. Please install webkitgtk4-devel.ARCH on your system." - fi - func_echo_plus "Building GTK3 bindings:" ${MAKE_TYPE} -f $MAKEFILE all $MAKE_CAIRO $MAKE_AWT "${@}" RETURN_VALUE=$? #make can return 1 or 2 if it fails. Thus need to cache it in case it's used programmatically somewhere. @@ -313,4 +308,4 @@ elif [ "${GTK_VERSION}" = "4.0" ]; then elif [ "${GTK_VERSION}" = "3.0" -o "${GTK_VERSION}" = "" ]; then export GTK_VERSION="3.0" func_build_gtk3 "$@" -fi
\ No newline at end of file +fi diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c index 0c6ac3e76d..2e23672cf5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. + * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -465,6 +465,18 @@ JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1event_1controller_1get_1current_1event) } #endif +#ifndef NO_gtk_1event_1controller_1get_1current_1event_1state +JNIEXPORT jint JNICALL GTK4_NATIVE(gtk_1event_1controller_1get_1current_1event_1state) + (JNIEnv *env, jclass that, jlong arg0) +{ + jint rc = 0; + GTK4_NATIVE_ENTER(env, that, gtk_1event_1controller_1get_1current_1event_1state_FUNC); + rc = (jint)gtk_event_controller_get_current_event_state((GtkEventController *)arg0); + GTK4_NATIVE_EXIT(env, that, gtk_1event_1controller_1get_1current_1event_1state_FUNC); + return rc; +} +#endif + #ifndef NO_gtk_1event_1controller_1key_1new JNIEXPORT jlong JNICALL GTK4_NATIVE(gtk_1event_1controller_1key_1new) (JNIEnv *env, jclass that) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.c index d6e33bffc7..7047c84989 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. + * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -60,6 +60,7 @@ char * GTK4_nativeFunctionNames[] = { "gtk_1entry_1set_1buffer", "gtk_1event_1controller_1focus_1new", "gtk_1event_1controller_1get_1current_1event", + "gtk_1event_1controller_1get_1current_1event_1state", "gtk_1event_1controller_1key_1new", "gtk_1event_1controller_1motion_1new", "gtk_1event_1controller_1scroll_1new", diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h index dfed94f095..23bc1ce531 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk4_stats.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. + * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -70,6 +70,7 @@ typedef enum { gtk_1entry_1set_1buffer_FUNC, gtk_1event_1controller_1focus_1new_FUNC, gtk_1event_1controller_1get_1current_1event_FUNC, + gtk_1event_1controller_1get_1current_1event_1state_FUNC, gtk_1event_1controller_1key_1new_FUNC, gtk_1event_1controller_1motion_1new_FUNC, gtk_1event_1controller_1scroll_1new_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak index 749a6d0900..65c168f3fa 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak @@ -41,7 +41,6 @@ endif CAIRO_PREFIX = swt-cairo ATK_PREFIX = swt-atk WEBKIT_PREFIX = swt-webkit -WEBKIT_EXTENSION_PREFIX=swt-webkit2extension GLX_PREFIX = swt-glx SWT_LIB = lib$(SWT_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).so @@ -53,11 +52,6 @@ GLX_LIB = lib$(GLX_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).so WEBKIT_LIB = lib$(WEBKIT_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).so ALL_SWT_LIBS = $(SWT_LIB) $(AWT_LIB) $(SWTPI_LIB) $(CAIRO_LIB) $(ATK_LIB) $(GLX_LIB) $(WEBKIT_LIB) -# Webkit extension lib has to be put into a separate folder and is treated differently from the other libraries. -WEBKIT_EXTENSION_LIB = lib$(WEBKIT_EXTENSION_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).so -WEBEXTENSION_BASE_DIR = webkitextensions -WEBEXTENSION_DIR = $(WEBEXTENSION_BASE_DIR)$(maj_ver)$(min_ver)r$(rev) - CAIROCFLAGS = `pkg-config --cflags cairo` CAIROLIBS = `pkg-config --libs-only-L cairo` -lcairo @@ -85,9 +79,6 @@ GLXLIBS = -lGL -lGLU -lm WEBKITLIBS = `pkg-config --libs-only-l gio-2.0` WEBKITCFLAGS = `pkg-config --cflags gio-2.0` -WEBKIT_EXTENSION_CFLAGS=`pkg-config --cflags gtk+-3.0 webkit2gtk-web-extension-4.0` -WEBKIT_EXTENSION_LFLAGS=`pkg-config --libs gtk+-3.0 webkit2gtk-web-extension-4.0` - ifdef SWT_WEBKIT_DEBUG # don't use 'webkit2gtk-4.0' in production, as some systems might not have those libs and we get crashes. WEBKITLIBS += `pkg-config --libs-only-l webkit2gtk-4.0` @@ -215,11 +206,7 @@ atk_stats.o: atk_stats.c atk_structs.h atk_stats.h atk.h # # WebKit lib # -ifeq ($(BUILD_WEBKIT2EXTENSION),yes) -make_webkit: $(WEBKIT_LIB) make_webkit2extension -else make_webkit: $(WEBKIT_LIB) -endif $(WEBKIT_LIB): $(WEBKIT_OBJECTS) $(CC) $(LFLAGS) -o $(WEBKIT_LIB) $(WEBKIT_OBJECTS) $(WEBKITLIBS) @@ -236,16 +223,6 @@ webkitgtk_stats.o: webkitgtk_stats.c webkitgtk_stats.h webkitgtk_custom.o: webkitgtk_custom.c $(CC) $(CFLAGS) $(WEBKITCFLAGS) -c webkitgtk_custom.c - -# Webkit2 extension is a seperate .so lib. -make_webkit2extension: $(WEBKIT_EXTENSION_LIB) - -$(WEBKIT_EXTENSION_LIB) : webkitgtk_extension.o - $(CC) $(LFLAGS) -o $@ $^ $(WEBKIT_EXTENSION_LFLAGS) - -webkitgtk_extension.o : webkitgtk_extension.c - $(CC) $(CFLAGS) $(WEBKIT_EXTENSION_CFLAGS) ${SWT_PTR_CFLAGS} -fPIC -c $^ - # # GLX lib # @@ -275,16 +252,6 @@ glx_stats.o: glx_stats.c glx_stats.h # I hope there are no spaces in the path :-). install: all cp $(ALL_SWT_LIBS) $(OUTPUT_DIR) -ifeq ($(BUILD_WEBKIT2EXTENSION),yes) - @# Copy webextension into it's own folder, but create folder first. - @# CAREFULLY delete '.so' files inside webextension*. Then carefully remove the directories. 'rm -rf' seemed too risky of an approach. - @-[ "$$(ls -d $(OUTPUT_DIR)/$(WEBEXTENSION_BASE_DIR)*/*.so)" ] && rm -v `ls -d $(OUTPUT_DIR)/$(WEBEXTENSION_BASE_DIR)*/*.so` - @-[ "$$(ls -d $(OUTPUT_DIR)/$(WEBEXTENSION_BASE_DIR)*)" ] && rmdir -v `ls -d $(OUTPUT_DIR)/$(WEBEXTENSION_BASE_DIR)*` - - @# Copying webextension is not critical for build to succeed, thus we use '-'. SWT can still function without a webextension. - @-[ -d $(OUTPUT_DIR)/$(WEBEXTENSION_DIR) ] || mkdir -v $(OUTPUT_DIR)/$(WEBEXTENSION_DIR) # If folder does not exist, make it. - -cp $(WEBKIT_EXTENSION_LIB) $(OUTPUT_DIR)/$(WEBEXTENSION_DIR)/ -endif # # Clean diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c index 03523d86ef..cea7169846 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. All rights reserved. + * Copyright (c) 2000, 2022 IBM Corporation and others. All rights reserved. * The contents of this file are made available under the terms * of the GNU Lesser General Public License (LGPL) Version 2.1 that * accompanies this distribution (lgpl-v21.txt). The LGPL is also @@ -10851,6 +10851,18 @@ JNIEXPORT jlong JNICALL OS_NATIVE(X_1EVENT_1WINDOW) } #endif +#ifndef NO_addressof_1g_1free +JNIEXPORT jlong JNICALL OS_NATIVE(addressof_1g_1free) + (JNIEnv *env, jclass that) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, addressof_1g_1free_FUNC); + rc = (jlong)&g_free; + OS_NATIVE_EXIT(env, that, addressof_1g_1free_FUNC); + return rc; +} +#endif + #ifndef NO_call__JJJJJ JNIEXPORT jlong JNICALL OS_NATIVE(call__JJJJJ) (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4) @@ -11172,34 +11184,6 @@ fail: } #endif -#ifndef NO_g_1credentials_1is_1same_1user -JNIEXPORT jboolean JNICALL OS_NATIVE(g_1credentials_1is_1same_1user) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2) -{ - jlong *lparg2=NULL; - jboolean rc = 0; - OS_NATIVE_ENTER(env, that, g_1credentials_1is_1same_1user_FUNC); - if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; - rc = (jboolean)g_credentials_is_same_user((GCredentials *)arg0, (GCredentials *)arg1, (GError **)lparg2); -fail: - if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); - OS_NATIVE_EXIT(env, that, g_1credentials_1is_1same_1user_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1credentials_1new -JNIEXPORT jlong JNICALL OS_NATIVE(g_1credentials_1new) - (JNIEnv *env, jclass that) -{ - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1credentials_1new_FUNC); - rc = (jlong)g_credentials_new(); - OS_NATIVE_EXIT(env, that, g_1credentials_1new_FUNC); - return rc; -} -#endif - #ifndef NO_g_1date_1time_1get_1ymd JNIEXPORT void JNICALL OS_NATIVE(g_1date_1time_1get_1ymd) (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jintArray arg2, jintArray arg3) @@ -11242,143 +11226,6 @@ JNIEXPORT void JNICALL OS_NATIVE(g_1date_1time_1unref) } #endif -#ifndef NO_g_1dbus_1auth_1observer_1new -JNIEXPORT jlong JNICALL OS_NATIVE(g_1dbus_1auth_1observer_1new) - (JNIEnv *env, jclass that) -{ - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1auth_1observer_1new_FUNC); - rc = (jlong)g_dbus_auth_observer_new(); - OS_NATIVE_EXIT(env, that, g_1dbus_1auth_1observer_1new_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1dbus_1connection_1call -JNIEXPORT void JNICALL OS_NATIVE(g_1dbus_1connection_1call) - (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jbyteArray arg2, jbyteArray arg3, jbyteArray arg4, jlong arg5, jlong arg6, jint arg7, jint arg8, jlong arg9, jlong arg10, jlong arg11) -{ - jbyte *lparg1=NULL; - jbyte *lparg2=NULL; - jbyte *lparg3=NULL; - jbyte *lparg4=NULL; - OS_NATIVE_ENTER(env, that, g_1dbus_1connection_1call_FUNC); - if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; - if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail; - if (arg3) if ((lparg3 = (*env)->GetByteArrayElements(env, arg3, NULL)) == NULL) goto fail; - if (arg4) if ((lparg4 = (*env)->GetByteArrayElements(env, arg4, NULL)) == NULL) goto fail; - g_dbus_connection_call((GDBusConnection *)arg0, (const gchar *)lparg1, (const gchar *)lparg2, (const gchar *)lparg3, (const gchar *)lparg4, (GVariant *)arg5, (const GVariantType *)arg6, arg7, arg8, (GCancellable *)arg9, (GAsyncReadyCallback)arg10, (gpointer)arg11); -fail: - if (arg4 && lparg4) (*env)->ReleaseByteArrayElements(env, arg4, lparg4, 0); - if (arg3 && lparg3) (*env)->ReleaseByteArrayElements(env, arg3, lparg3, 0); - if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0); - if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); - OS_NATIVE_EXIT(env, that, g_1dbus_1connection_1call_FUNC); -} -#endif - -#ifndef NO_g_1dbus_1connection_1call_1finish -JNIEXPORT jlong JNICALL OS_NATIVE(g_1dbus_1connection_1call_1finish) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2) -{ - jlong *lparg2=NULL; - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1connection_1call_1finish_FUNC); - if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; - rc = (jlong)g_dbus_connection_call_finish((GDBusConnection *)arg0, (GAsyncResult *)arg1, (GError **)lparg2); -fail: - if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); - OS_NATIVE_EXIT(env, that, g_1dbus_1connection_1call_1finish_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1dbus_1connection_1call_1sync -JNIEXPORT jlong JNICALL OS_NATIVE(g_1dbus_1connection_1call_1sync) - (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jbyteArray arg2, jbyteArray arg3, jbyteArray arg4, jlong arg5, jlong arg6, jint arg7, jint arg8, jlong arg9, jlongArray arg10) -{ - jbyte *lparg1=NULL; - jbyte *lparg2=NULL; - jbyte *lparg3=NULL; - jbyte *lparg4=NULL; - jlong *lparg10=NULL; - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1connection_1call_1sync_FUNC); - if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; - if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail; - if (arg3) if ((lparg3 = (*env)->GetByteArrayElements(env, arg3, NULL)) == NULL) goto fail; - if (arg4) if ((lparg4 = (*env)->GetByteArrayElements(env, arg4, NULL)) == NULL) goto fail; - if (arg10) if ((lparg10 = (*env)->GetLongArrayElements(env, arg10, NULL)) == NULL) goto fail; - rc = (jlong)g_dbus_connection_call_sync((GDBusConnection *)arg0, (const gchar *)lparg1, (const gchar *)lparg2, (const gchar *)lparg3, (const gchar *)lparg4, (GVariant *)arg5, (const GVariantType *)arg6, arg7, arg8, (GCancellable *)arg9, (GError **)lparg10); -fail: - if (arg10 && lparg10) (*env)->ReleaseLongArrayElements(env, arg10, lparg10, 0); - if (arg4 && lparg4) (*env)->ReleaseByteArrayElements(env, arg4, lparg4, 0); - if (arg3 && lparg3) (*env)->ReleaseByteArrayElements(env, arg3, lparg3, 0); - if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0); - if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); - OS_NATIVE_EXIT(env, that, g_1dbus_1connection_1call_1sync_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1dbus_1connection_1close_1sync -JNIEXPORT jboolean JNICALL OS_NATIVE(g_1dbus_1connection_1close_1sync) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2) -{ - jlong *lparg2=NULL; - jboolean rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1connection_1close_1sync_FUNC); - if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; - rc = (jboolean)g_dbus_connection_close_sync((GDBusConnection *)arg0, (GCancellable *)arg1, (GError **)lparg2); -fail: - if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); - OS_NATIVE_EXIT(env, that, g_1dbus_1connection_1close_1sync_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1dbus_1connection_1is_1closed -JNIEXPORT jboolean JNICALL OS_NATIVE(g_1dbus_1connection_1is_1closed) - (JNIEnv *env, jclass that, jlong arg0) -{ - jboolean rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1connection_1is_1closed_FUNC); - rc = (jboolean)g_dbus_connection_is_closed((GDBusConnection *)arg0); - OS_NATIVE_EXIT(env, that, g_1dbus_1connection_1is_1closed_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1dbus_1connection_1new_1for_1address -JNIEXPORT void JNICALL OS_NATIVE(g_1dbus_1connection_1new_1for_1address) - (JNIEnv *env, jclass that, jbyteArray arg0, jint arg1, jlong arg2, jlong arg3, jlong arg4, jlong arg5) -{ - jbyte *lparg0=NULL; - OS_NATIVE_ENTER(env, that, g_1dbus_1connection_1new_1for_1address_FUNC); - if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail; - g_dbus_connection_new_for_address((const gchar *)lparg0, arg1, (GDBusAuthObserver *)arg2, (GCancellable *)arg3, (GAsyncReadyCallback)arg4, (gpointer)arg5); -fail: - if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0); - OS_NATIVE_EXIT(env, that, g_1dbus_1connection_1new_1for_1address_FUNC); -} -#endif - -#ifndef NO_g_1dbus_1connection_1new_1for_1address_1finish -JNIEXPORT jlong JNICALL OS_NATIVE(g_1dbus_1connection_1new_1for_1address_1finish) - (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1) -{ - jlong *lparg1=NULL; - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1connection_1new_1for_1address_1finish_FUNC); - if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail; - rc = (jlong)g_dbus_connection_new_for_address_finish((GAsyncResult *)arg0, (GError **)lparg1); -fail: - if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0); - OS_NATIVE_EXIT(env, that, g_1dbus_1connection_1new_1for_1address_1finish_FUNC); - return rc; -} -#endif - #ifndef NO_g_1dbus_1connection_1register_1object JNIEXPORT jint JNICALL OS_NATIVE(g_1dbus_1connection_1register_1object) (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jlong arg2, jlongArray arg3, jlong arg4, jlong arg5, jlongArray arg6) @@ -11401,18 +11248,6 @@ fail: } #endif -#ifndef NO_g_1dbus_1generate_1guid -JNIEXPORT jlong JNICALL OS_NATIVE(g_1dbus_1generate_1guid) - (JNIEnv *env, jclass that) -{ - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1generate_1guid_FUNC); - rc = (jlong)g_dbus_generate_guid(); - OS_NATIVE_EXIT(env, that, g_1dbus_1generate_1guid_FUNC); - return rc; -} -#endif - #ifndef NO_g_1dbus_1method_1invocation_1return_1value JNIEXPORT void JNICALL OS_NATIVE(g_1dbus_1method_1invocation_1return_1value) (JNIEnv *env, jclass that, jlong arg0, jlong arg1) @@ -11531,54 +11366,6 @@ fail: } #endif -#ifndef NO_g_1dbus_1server_1get_1client_1address -JNIEXPORT jlong JNICALL OS_NATIVE(g_1dbus_1server_1get_1client_1address) - (JNIEnv *env, jclass that, jlong arg0) -{ - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1server_1get_1client_1address_FUNC); - rc = (jlong)g_dbus_server_get_client_address((GDBusServer *)arg0); - OS_NATIVE_EXIT(env, that, g_1dbus_1server_1get_1client_1address_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1dbus_1server_1new_1sync -JNIEXPORT jlong JNICALL OS_NATIVE(g_1dbus_1server_1new_1sync) - (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3, jlong arg4, jlongArray arg5) -{ - jlong *lparg5=NULL; - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1dbus_1server_1new_1sync_FUNC); - if (arg5) if ((lparg5 = (*env)->GetLongArrayElements(env, arg5, NULL)) == NULL) goto fail; - rc = (jlong)g_dbus_server_new_sync((const gchar *)arg0, (GDBusServerFlags)arg1, (const gchar *)arg2, (GDBusAuthObserver *)arg3, (GCancellable *)arg4, (GError **)lparg5); -fail: - if (arg5 && lparg5) (*env)->ReleaseLongArrayElements(env, arg5, lparg5, 0); - OS_NATIVE_EXIT(env, that, g_1dbus_1server_1new_1sync_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1dbus_1server_1start -JNIEXPORT void JNICALL OS_NATIVE(g_1dbus_1server_1start) - (JNIEnv *env, jclass that, jlong arg0) -{ - OS_NATIVE_ENTER(env, that, g_1dbus_1server_1start_FUNC); - g_dbus_server_start((GDBusServer *)arg0); - OS_NATIVE_EXIT(env, that, g_1dbus_1server_1start_FUNC); -} -#endif - -#ifndef NO_g_1dbus_1server_1stop -JNIEXPORT void JNICALL OS_NATIVE(g_1dbus_1server_1stop) - (JNIEnv *env, jclass that, jlong arg0) -{ - OS_NATIVE_ENTER(env, that, g_1dbus_1server_1stop_FUNC); - g_dbus_server_stop((GDBusServer *)arg0); - OS_NATIVE_EXIT(env, that, g_1dbus_1server_1stop_FUNC); -} -#endif - #ifndef NO_g_1dir_1make_1tmp JNIEXPORT jlong JNICALL OS_NATIVE(g_1dir_1make_1tmp) (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1) @@ -11617,6 +11404,30 @@ JNIEXPORT jlong JNICALL OS_NATIVE(g_1error_1get_1message) } #endif +#ifndef NO_g_1error_1matches +JNIEXPORT jboolean JNICALL OS_NATIVE(g_1error_1matches) + (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2) +{ + jboolean rc = 0; + OS_NATIVE_ENTER(env, that, g_1error_1matches_FUNC); + rc = (jboolean)g_error_matches((const GError *)arg0, (GQuark)arg1, (gint)arg2); + OS_NATIVE_EXIT(env, that, g_1error_1matches_FUNC); + return rc; +} +#endif + +#ifndef NO_g_1file_1error_1quark +JNIEXPORT jint JNICALL OS_NATIVE(g_1file_1error_1quark) + (JNIEnv *env, jclass that) +{ + jint rc = 0; + OS_NATIVE_ENTER(env, that, g_1file_1error_1quark_FUNC); + rc = (jint)g_file_error_quark(); + OS_NATIVE_EXIT(env, that, g_1file_1error_1quark_FUNC); + return rc; +} +#endif + #ifndef NO_g_1file_1get_1path JNIEXPORT jlong JNICALL OS_NATIVE(g_1file_1get_1path) (JNIEnv *env, jclass that, jlong arg0) @@ -11846,18 +11657,6 @@ JNIEXPORT void JNICALL OS_NATIVE(g_1get_1current_1time) G_GNUC_END_IGNORE_DEPRECATIONS #endif -#ifndef NO_g_1get_1user_1name -JNIEXPORT jlong JNICALL OS_NATIVE(g_1get_1user_1name) - (JNIEnv *env, jclass that) -{ - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1get_1user_1name_FUNC); - rc = (jlong)g_get_user_name(); - OS_NATIVE_EXIT(env, that, g_1get_1user_1name_FUNC); - return rc; -} -#endif - #ifndef NO_g_1getenv JNIEXPORT jlong JNICALL OS_NATIVE(g_1getenv) (JNIEnv *env, jclass that, jbyteArray arg0) @@ -12199,6 +11998,18 @@ JNIEXPORT jlong JNICALL OS_NATIVE(g_1malloc) } #endif +#ifndef NO_g_1memory_1input_1stream_1new_1from_1data +JNIEXPORT jlong JNICALL OS_NATIVE(g_1memory_1input_1stream_1new_1from_1data) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, g_1memory_1input_1stream_1new_1from_1data_FUNC); + rc = (jlong)g_memory_input_stream_new_from_data((const void *)arg0, (gssize)arg1, (GDestroyNotify)arg2); + OS_NATIVE_EXIT(env, that, g_1memory_1input_1stream_1new_1from_1data_FUNC); + return rc; +} +#endif + #ifndef NO_g_1menu_1insert_1item JNIEXPORT void JNICALL OS_NATIVE(g_1menu_1insert_1item) (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2) @@ -12899,30 +12710,6 @@ JNIEXPORT jboolean JNICALL OS_NATIVE(g_1source_1remove) } #endif -#ifndef NO_g_1strconcat__JJJ -JNIEXPORT jlong JNICALL OS_NATIVE(g_1strconcat__JJJ) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) -{ - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1strconcat__JJJ_FUNC); - rc = (jlong)g_strconcat((const gchar *)arg0, (const gchar *)arg1, (const gchar *)NULL); - OS_NATIVE_EXIT(env, that, g_1strconcat__JJJ_FUNC); - return rc; -} -#endif - -#ifndef NO_g_1strconcat__JJJJ -JNIEXPORT jlong JNICALL OS_NATIVE(g_1strconcat__JJJJ) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3) -{ - jlong rc = 0; - OS_NATIVE_ENTER(env, that, g_1strconcat__JJJJ_FUNC); - rc = (jlong)g_strconcat((const gchar *)arg0, (const gchar *)arg1, (const gchar *)arg2, (const gchar *)NULL); - OS_NATIVE_EXIT(env, that, g_1strconcat__JJJJ_FUNC); - return rc; -} -#endif - #ifndef NO_g_1strdup JNIEXPORT jlong JNICALL OS_NATIVE(g_1strdup) (JNIEnv *env, jclass that, jlong arg0) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c index b289ad04d2..0ab5dc85d2 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. All rights reserved. + * Copyright (c) 2000, 2022 IBM Corporation and others. All rights reserved. * The contents of this file are made available under the terms * of the GNU Lesser General Public License (LGPL) Version 2.1 that * accompanies this distribution (lgpl-v21.txt). The LGPL is also @@ -936,6 +936,7 @@ char * OS_nativeFunctionNames[] = { "XSynchronize", "X_1EVENT_1TYPE", "X_1EVENT_1WINDOW", + "addressof_1g_1free", "call__JJJJJ", "call__JJJJJJJ", "call__JJJJJJJJ", @@ -961,21 +962,10 @@ char * OS_nativeFunctionNames[] = { "g_1closure_1unref", "g_1content_1type_1equals", "g_1content_1type_1is_1a", - "g_1credentials_1is_1same_1user", - "g_1credentials_1new", "g_1date_1time_1get_1ymd", "g_1date_1time_1new_1local", "g_1date_1time_1unref", - "g_1dbus_1auth_1observer_1new", - "g_1dbus_1connection_1call", - "g_1dbus_1connection_1call_1finish", - "g_1dbus_1connection_1call_1sync", - "g_1dbus_1connection_1close_1sync", - "g_1dbus_1connection_1is_1closed", - "g_1dbus_1connection_1new_1for_1address", - "g_1dbus_1connection_1new_1for_1address_1finish", "g_1dbus_1connection_1register_1object", - "g_1dbus_1generate_1guid", "g_1dbus_1method_1invocation_1return_1value", "g_1dbus_1node_1info_1lookup_1interface", "g_1dbus_1node_1info_1new_1for_1xml", @@ -983,13 +973,11 @@ char * OS_nativeFunctionNames[] = { "g_1dbus_1proxy_1call_1sync", "g_1dbus_1proxy_1get_1name_1owner", "g_1dbus_1proxy_1new_1for_1bus_1sync", - "g_1dbus_1server_1get_1client_1address", - "g_1dbus_1server_1new_1sync", - "g_1dbus_1server_1start", - "g_1dbus_1server_1stop", "g_1dir_1make_1tmp", "g_1error_1free", "g_1error_1get_1message", + "g_1error_1matches", + "g_1file_1error_1quark", "g_1file_1get_1path", "g_1file_1get_1uri", "g_1file_1info_1get_1content_1type", @@ -1005,7 +993,6 @@ char * OS_nativeFunctionNames[] = { "g_1filename_1to_1utf8", "g_1free", "g_1get_1current_1time", - "g_1get_1user_1name", "g_1getenv", "g_1icon_1new_1for_1string", "g_1icon_1to_1string", @@ -1033,6 +1020,7 @@ char * OS_nativeFunctionNames[] = { "g_1main_1context_1release", "g_1main_1context_1wakeup", "g_1malloc", + "g_1memory_1input_1stream_1new_1from_1data", "g_1menu_1insert_1item", "g_1menu_1item_1new", "g_1menu_1item_1new_1section", @@ -1085,8 +1073,6 @@ char * OS_nativeFunctionNames[] = { "g_1slist_1length", "g_1slist_1next", "g_1source_1remove", - "g_1strconcat__JJJ", - "g_1strconcat__JJJJ", "g_1strdup", "g_1strfreev", "g_1strtod", diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h index 4a96c27687..057048bff8 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. All rights reserved. + * Copyright (c) 2000, 2022 IBM Corporation and others. All rights reserved. * The contents of this file are made available under the terms * of the GNU Lesser General Public License (LGPL) Version 2.1 that * accompanies this distribution (lgpl-v21.txt). The LGPL is also @@ -910,6 +910,7 @@ typedef enum { XSynchronize_FUNC, X_1EVENT_1TYPE_FUNC, X_1EVENT_1WINDOW_FUNC, + addressof_1g_1free_FUNC, call__JJJJJ_FUNC, call__JJJJJJJ_FUNC, call__JJJJJJJJ_FUNC, @@ -935,21 +936,10 @@ typedef enum { g_1closure_1unref_FUNC, g_1content_1type_1equals_FUNC, g_1content_1type_1is_1a_FUNC, - g_1credentials_1is_1same_1user_FUNC, - g_1credentials_1new_FUNC, g_1date_1time_1get_1ymd_FUNC, g_1date_1time_1new_1local_FUNC, g_1date_1time_1unref_FUNC, - g_1dbus_1auth_1observer_1new_FUNC, - g_1dbus_1connection_1call_FUNC, - g_1dbus_1connection_1call_1finish_FUNC, - g_1dbus_1connection_1call_1sync_FUNC, - g_1dbus_1connection_1close_1sync_FUNC, - g_1dbus_1connection_1is_1closed_FUNC, - g_1dbus_1connection_1new_1for_1address_FUNC, - g_1dbus_1connection_1new_1for_1address_1finish_FUNC, g_1dbus_1connection_1register_1object_FUNC, - g_1dbus_1generate_1guid_FUNC, g_1dbus_1method_1invocation_1return_1value_FUNC, g_1dbus_1node_1info_1lookup_1interface_FUNC, g_1dbus_1node_1info_1new_1for_1xml_FUNC, @@ -957,13 +947,11 @@ typedef enum { g_1dbus_1proxy_1call_1sync_FUNC, g_1dbus_1proxy_1get_1name_1owner_FUNC, g_1dbus_1proxy_1new_1for_1bus_1sync_FUNC, - g_1dbus_1server_1get_1client_1address_FUNC, - g_1dbus_1server_1new_1sync_FUNC, - g_1dbus_1server_1start_FUNC, - g_1dbus_1server_1stop_FUNC, g_1dir_1make_1tmp_FUNC, g_1error_1free_FUNC, g_1error_1get_1message_FUNC, + g_1error_1matches_FUNC, + g_1file_1error_1quark_FUNC, g_1file_1get_1path_FUNC, g_1file_1get_1uri_FUNC, g_1file_1info_1get_1content_1type_FUNC, @@ -979,7 +967,6 @@ typedef enum { g_1filename_1to_1utf8_FUNC, g_1free_FUNC, g_1get_1current_1time_FUNC, - g_1get_1user_1name_FUNC, g_1getenv_FUNC, g_1icon_1new_1for_1string_FUNC, g_1icon_1to_1string_FUNC, @@ -1007,6 +994,7 @@ typedef enum { g_1main_1context_1release_FUNC, g_1main_1context_1wakeup_FUNC, g_1malloc_FUNC, + g_1memory_1input_1stream_1new_1from_1data_FUNC, g_1menu_1insert_1item_FUNC, g_1menu_1item_1new_FUNC, g_1menu_1item_1new_1section_FUNC, @@ -1059,8 +1047,6 @@ typedef enum { g_1slist_1length_FUNC, g_1slist_1next_FUNC, g_1source_1remove_FUNC, - g_1strconcat__JJJ_FUNC, - g_1strconcat__JJJJ_FUNC, g_1strdup_FUNC, g_1strfreev_FUNC, g_1strtod_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GdkRectangle.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GdkRectangle.java index 4e547d07e8..7623e32142 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GdkRectangle.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GdkRectangle.java @@ -14,6 +14,7 @@ *******************************************************************************/ package org.eclipse.swt.internal.gtk; +import org.eclipse.swt.graphics.Rectangle; public class GdkRectangle { /** @field cast=(gint) */ @@ -36,4 +37,8 @@ public class GdkRectangle { public String toString() { return "GdkRectangle {" + x + ", " + y + ", " + width + ", " + height + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ } + + public Rectangle toRectangle() { + return new Rectangle(x, y, width, height); + } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java index c1850b9764..64d9ac9fba 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. All rights reserved. + * Copyright (c) 2000, 2022 IBM Corporation and others. All rights reserved. * The contents of this file are made available under the terms * of the GNU Lesser General Public License (LGPL) Version 2.1 that * accompanies this distribution (lgpl-v21.txt). The LGPL is also @@ -145,6 +145,7 @@ public class OS extends C { } /** Constants */ + public static final int G_FILE_ERROR_IO = 21; public static final int G_FILE_TEST_IS_DIR = 1 << 2; public static final int G_FILE_TEST_IS_EXECUTABLE = 1 << 3; public static final int G_SIGNAL_MATCH_DATA = 1 << 4; @@ -210,11 +211,6 @@ public class OS extends C { public static final int G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START = 3; public static final int G_DBUS_CALL_FLAGS_NONE = 0; - public static final int G_DBUS_CALL_FLAGS_NO_AUTO_START = (1<<0); - - public static final int G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT = 1; - - public static final int G_DBUS_SERVER_FLAGS_NONE = 0; /** * DBus Data types as defined by: @@ -273,7 +269,6 @@ public class OS extends C { public static final byte[] accel_closures_changed = ascii("accel-closures-changed"); // Gtk3,4 public static final byte[] activate = ascii("activate"); // ? public static final byte[] angle_changed = ascii("angle_changed"); // Gtk3/4, Guesture related. - public static final byte[] authorize_authenticated_peer = ascii("authorize-authenticated-peer"); public static final byte[] backspace = ascii("backspace"); public static final byte[] begin = ascii("begin"); public static final byte[] button_press_event = ascii("button-press-event"); @@ -339,7 +334,6 @@ public class OS extends C { public static final byte[] motion = ascii("motion"); public static final byte[] move_cursor = ascii("move-cursor"); public static final byte[] move_focus = ascii("move-focus"); - public static final byte[] new_connection = ascii("new-connection"); public static final byte[] output = ascii("output"); public static final byte[] paste_clipboard = ascii("paste-clipboard"); public static final byte[] pressed = ascii("pressed"); @@ -376,6 +370,7 @@ public class OS extends C { public static final byte[] notify_default_height = ascii("notify::default-height"); public static final byte[] notify_default_width = ascii("notify::default-width"); public static final byte[] notify_maximized = ascii("notify::maximized"); + public static final byte[] notify_is_active = ascii("notify::is-active"); public static final byte[] notify_theme_change = ascii("notify::gtk-application-prefer-dark-theme"); public static final byte[] response = ascii("response"); public static final byte[] compute_size = ascii("compute-size"); @@ -899,6 +894,12 @@ public static final native boolean g_app_info_supports_uris(long appInfo); * @param error cast=(GError *) */ public static final native long g_error_get_message(long error); +/** + * @param error cast=(const GError *) + * @param domain cast=(GQuark) + * @param code cast=(gint) + */ +public static final native boolean g_error_matches(long error, int domain, int code); /** * @param gerror cast=(GError *) @@ -915,13 +916,7 @@ public static final native boolean g_content_type_equals(long type1, byte[] type * @param supertype cast=(gchar *) */ public static final native boolean g_content_type_is_a(long type, byte[] supertype); -public static final native long g_credentials_new(); -/** - * @param credentials cast=(GCredentials *) - * @param other_credentials cast=(GCredentials *) - * @param error cast=(GError **) - */ -public static final native boolean g_credentials_is_same_user(long credentials, long other_credentials, long [] error); +public static final native int g_file_error_quark(); /** * @param info cast=(GFileInfo *) */ @@ -1042,6 +1037,8 @@ public static final native long g_filename_from_utf8(long opsysstring, long len, public static final native long g_filename_from_uri(long uri, long [] hostname, long [] error); /** @param mem cast=(gpointer) */ public static final native void g_free(long mem); +/** @method accessor=g_free,flags=const address */ +public static final native long addressof_g_free(); /** * @param variable cast=(const gchar *),flags=no_out */ @@ -1051,7 +1048,6 @@ public static final native long g_getenv(byte [] variable); * @param result cast=(GTimeVal *) */ public static final native void g_get_current_time(long result); -public static final native long g_get_user_name(); /** * @method flags=ignore_deprecations * @param result cast=(GTimeVal *) @@ -1300,19 +1296,6 @@ public static final native void g_strfreev(long string_array); * @param endptr cast=(gchar **) */ public static final native double g_strtod(long str, long [] endptr); -/** - * @param str cast=(const gchar *) - * @param str2 cast=(const gchar *) - * @param str3 cast=(const gchar *) - * @param terminator cast=(const gchar *),flags=sentinel - */ -public static final native long g_strconcat(long str, long str2, long str3, long terminator); -/** - * @param str cast=(const gchar *) - * @param str2 cast=(const gchar *) - * @param terminator cast=(const gchar *),flags=sentinel - */ -public static final native long g_strconcat(long str, long str2, long terminator); /** @param str cast=(char *) */ public static final native long g_strdup (long str); /** @param g_class cast=(GType) */ @@ -1880,6 +1863,27 @@ public static final byte [] getThemeNameBytes() { } /** + * Experimental API for dark theme. + * <p> + * On Windows, there is no OS API for dark theme yet, and this method only + * configures various tweaks. Some of these tweaks have drawbacks. The tweaks + * are configured with defaults that fit Eclipse. Non-Eclipse applications are + * expected to configure individual tweaks instead of calling this method. + * Please see <code>Display#setData()</code> and documentation for string keys + * used there. + * </p> + * <p> + * On GTK, behavior may be different as the boolean flag doesn't force dark + * theme instead it specify that dark theme is preferred. + * </p> + * + * @param isDarkTheme <code>true</code> for dark theme + */ +public static final void setTheme(boolean isDarkTheme) { + setDarkThemePreferred (isDarkTheme); +} + +/** * @param tmpl cast=(const gchar *) * @param error cast=(GError **) */ @@ -1946,74 +1950,6 @@ public static final native int g_bus_own_name(int bus_type, byte[] name, int fla /** * @param connection cast=(GDBusConnection *) - * @param bus_name cast=(const gchar *) - * @param object_path cast=(const gchar *) - * @param interface_name cast=(const gchar *) - * @param method_name cast=(const gchar *) - * @param param cast=(GVariant *) - * @param reply_type cast=(const GVariantType *) - * @param cancellable cast=(GCancellable *) - * @param callback cast=(GAsyncReadyCallback) - * @param user_data cast=(gpointer) - * @category gdbus - */ -public static final native void g_dbus_connection_call(long connection, byte [] bus_name, byte [] object_path, byte [] interface_name, byte [] method_name, long param, long reply_type, int flag, int timeout, long cancellable, long callback, long user_data); - -/** - * @param proxy cast=(GDBusConnection *) - * @param res cast=(GAsyncResult *) - * @param error cast=(GError **) - * @category gdbus - */ -public static final native long g_dbus_connection_call_finish(long proxy, long res, long [] error); - -/** - * @param connection cast=(GDBusConnection *) - * @param bus_name cast=(const gchar *) - * @param object_path cast=(const gchar *) - * @param interface_name cast=(const gchar *) - * @param method_name cast=(const gchar *) - * @param param cast=(GVariant *) - * @param reply_type cast=(const GVariantType *) - * @param cancellable cast=(GCancellable *) - * @param error cast=(GError **) - * @category gdbus - */ -public static final native long g_dbus_connection_call_sync(long connection, byte [] bus_name, byte [] object_path, byte [] interface_name, byte [] method_name, long param, long reply_type, int flag, int timeout, long cancellable, long [] error); - -/** - * @param connection cast=(GDBusConnection *) - * @param cancellable cast=(GCancellable *) - * @param error cast=(GError **) - * @category gdbus - */ -public static final native boolean g_dbus_connection_close_sync(long connection, long cancellable, long [] error); - -/** - * @param connection cast=(GDBusConnection *) - * @category gdbus - */ -public static final native boolean g_dbus_connection_is_closed(long connection); - -/** - * @param address cast=(const gchar *) - * @param observer cast=(GDBusAuthObserver *) - * @param cancellable cast=(GCancellable *) - * @param callback cast=(GAsyncReadyCallback) - * @param user_data cast=(gpointer) - * @category gdbus - */ -public static final native void g_dbus_connection_new_for_address(byte[] address, int flags, long observer, long cancellable, long callback, long user_data); - -/** - * @param result cast=(GAsyncResult *) - * @param error cast=(GError **) - * @category gdbus - */ -public static final native long g_dbus_connection_new_for_address_finish(long result, long [] error); - -/** - * @param connection cast=(GDBusConnection *) * @param object_path cast=(const gchar *) * @param interface_info cast=(GDBusInterfaceInfo *) * @param vtable cast=(const GDBusInterfaceVTable *) @@ -2039,45 +1975,6 @@ public static final native long g_dbus_node_info_lookup_interface(long info, byt public static final native void g_dbus_method_invocation_return_value(long invocation, long parameters); /** - * @param address cast=(const gchar *) - * @param flags cast=(GDBusServerFlags) - * @param guid cast=(const gchar *) - * @param observer cast=(GDBusAuthObserver *) - * @param cancellable cast=(GCancellable *) - * @param error cast=(GError **) - * @category gdbus - */ -public static final native long g_dbus_server_new_sync(long address, int flags, long guid, long observer, long cancellable, long [] error); - -/** - * @param server cast=(GDBusServer *) - * @category gdbus - */ -public static final native void g_dbus_server_start(long server); - -/** - * @param server cast=(GDBusServer *) - * @category gdbus - */ -public static final native void g_dbus_server_stop(long server); - -/** - * @param server cast=(GDBusServer *) - * @category gdbus - */ -public static final native long g_dbus_server_get_client_address(long server); - -/** - * @category gdbus - */ -public static final native long g_dbus_auth_observer_new(); - -/** - * @category gdbus - */ -public static final native long g_dbus_generate_guid(); - -/** * @param type cast=(const GVariantType *) * @category gdbus */ @@ -2382,4 +2279,13 @@ public static final native int g_list_model_get_n_items(long list); * @param position cast=(guint) */ public static final native long g_list_model_get_item(long list, int position); + +/* GMemoryInputStream */ +/** + * @param data cast=(const void *) + * @param len cast=(gssize) + * @param destroy cast=(GDestroyNotify) + */ +public static final native long g_memory_input_stream_new_from_data(long data, long len, long destroy); + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java index cb925a9748..ecff340801 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk4/GTK4.java @@ -355,6 +355,8 @@ public class GTK4 { public static final native long gtk_event_controller_focus_new(); /** @param controller cast=(GtkEventController *) */ public static final native long gtk_event_controller_get_current_event(long controller); + /** @param controller cast=(GtkEventController *) */ + public static final native int gtk_event_controller_get_current_event_state(long controller); public static final native long gtk_event_controller_key_new(); public static final native long gtk_event_controller_motion_new(); /** @param flag cast=(GtkEventControllerScrollFlags) */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/build.bat b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/build.bat index c71d94bf4e..41e5f87770 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/build.bat +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/build.bat @@ -24,47 +24,58 @@ IF "x.%SWT_BUILDDIR%"=="x." set "SWT_BUILDDIR=W:" echo SWT build dir: %SWT_BUILDDIR% @rem Specify VisualStudio Edition: 'Community', 'Enterprise', 'Professional' etc. -IF "x.%MSVC_EDITION%"=="x." set "MSVC_EDITION=Community" +IF "x.%MSVC_EDITION%"=="x." set "MSVC_EDITION=auto" -@rem Specify VisualStudio Version: '2017' or newer '2019' -IF "x.%MSVC_VERSION%"=="x." set "MSVC_VERSION=2019" +@rem Specify VisualStudio Version: '2022', '2019', '2017' etc. +IF "x.%MSVC_VERSION%"=="x." set "MSVC_VERSION=auto" -IF "x.%MSVC_HOME%"=="x." set "MSVC_HOME=%SWT_BUILDDIR%\Microsoft\Visual Studio\%MSVC_VERSION%\" -IF NOT EXIST "%MSVC_HOME%" set "MSVC_HOME=%ProgramFiles(x86)%\Microsoft Visual Studio\%MSVC_VERSION%\BuildTools" -IF NOT EXIST "%MSVC_HOME%" set "MSVC_HOME=%ProgramFiles(x86)%\Microsoft Visual Studio\%MSVC_VERSION%\%MSVC_EDITION%" -IF EXIST "%MSVC_HOME%" ( - echo "Microsoft Visual Studio %MSVC_VERSION% dir: %MSVC_HOME%" +@rem Search for a usable Visual Studio +@rem --------------------------------- +IF "%MSVC_HOME%"=="" CALL :ECHO "'MSVC_HOME' was not provided, auto-searching for Visual Studio..." +@rem Bug 572308: Path used on older SWT build machines +IF "%MSVC_HOME%"=="" CALL :FindVisualStudio "%SWT_BUILDDIR%\Microsoft\Visual Studio\$MSVC_VERSION$" +@rem Bug 574007: Path used on Azure build machines +IF "%MSVC_HOME%"=="" CALL :FindVisualStudio "%ProgramFiles(x86)%\Microsoft Visual Studio\$MSVC_VERSION$\BuildTools" +@rem Bug 578519: Common installation paths; VisualStudio is installed in x64 ProgramFiles since VS2022 +IF "%MSVC_HOME%"=="" CALL :FindVisualStudio "%ProgramFiles%\Microsoft Visual Studio\$MSVC_VERSION$\$MSVC_EDITION$" +@rem Bug 578519: Common installation paths; VisualStudio is installed in x86 ProgramFiles before VS2022 +IF "%MSVC_HOME%"=="" CALL :FindVisualStudio "%ProgramFiles(x86)%\Microsoft Visual Studio\$MSVC_VERSION$\$MSVC_EDITION$" +@rem Report +IF NOT EXIST "%MSVC_HOME%" ( + CALL :ECHO "WARNING: Microsoft Visual Studio was not found (for edition=%MSVC_EDITION% version=%MSVC_VERSION%)" + CALL :ECHO " Refer steps for SWT Windows native setup: https://www.eclipse.org/swt/swt_win_native.php" ) ELSE ( - echo "WARNING: Microsoft Visual Studio %MSVC_VERSION% was not found." - echo " Refer steps for SWT Windows native setup: https://www.eclipse.org/swt/swt_win_native.php" + CALL :ECHO "MSVC_HOME: %MSVC_HOME%" ) -IF NOT "x.%1"=="x.x86_64" ( - ECHO 32-bit builds are no longer supported. - EXIT /B 1 -) - -set PROCESSOR_ARCHITECTURE=AMD64 -IF "x.%OUTPUT_DIR%"=="x." set OUTPUT_DIR=..\..\..\org.eclipse.swt.win32.win32.x86_64 - -:: Search for a usable JDK -:: ----------------------- -IF "%SWT_JAVA_HOME%"=="" ECHO 'SWT_JAVA_HOME' was not provided, auto-searching for JDK... -:: Bug 572733: JDK path used on Azure build machines +@rem Search for a usable JDK +@rem ----------------------- +IF "%SWT_JAVA_HOME%"=="" CALL :ECHO "'SWT_JAVA_HOME' was not provided, auto-searching for JDK..." +@rem Bug 572733: JDK path used on Azure build machines IF "%SWT_JAVA_HOME%"=="" CALL :TryToUseJdk "%ProgramFiles%\AdoptOpenJDK\jdk-8.0.292.10-hotspot" -:: Bug 526802: Probably some kind of legacy build machine path +@rem Bug 526802: Probably some kind of legacy build machine path IF "%SWT_JAVA_HOME%"=="" CALL :TryToUseJdk "%SWT_BUILDDIR%\Java\Oracle\jdk1.8.0-latest\x64" -:: Search for generic JDKs so that user can build with little configuration -:: Note that first found JDK wins, so sort them by order of preference. +@rem Search for generic JDKs so that user can build with little configuration +@rem Note that first found JDK wins, so sort them by order of preference. IF "%SWT_JAVA_HOME%"=="" CALL :TryToUseJdk "%ProgramFiles%\Java\jdk*" IF "%SWT_JAVA_HOME%"=="" CALL :TryToUseJdk "%ProgramFiles%\AdoptOpenJDK\jdk*" +@rem Report IF NOT EXIST "%SWT_JAVA_HOME%" ( - echo "WARNING: x64 Java JDK not found. Please set SWT_JAVA_HOME to your JDK directory." - echo " Refer steps for SWT Windows native setup: https://www.eclipse.org/swt/swt_win_native.php" + CALL :ECHO "WARNING: x64 Java JDK not found. Please set SWT_JAVA_HOME to your JDK directory." + CALL :ECHO " Refer steps for SWT Windows native setup: https://www.eclipse.org/swt/swt_win_native.php" ) ELSE ( - echo "SWT_JAVA_HOME x64: %SWT_JAVA_HOME%" + CALL :ECHO "SWT_JAVA_HOME x64: %SWT_JAVA_HOME%" +) + +@rem ----------------------- +IF NOT "x.%1"=="x.x86_64" ( + CALL :ECHO "ERROR: 32-bit builds are no longer supported." + EXIT /B 1 ) +set PROCESSOR_ARCHITECTURE=AMD64 +IF "x.%OUTPUT_DIR%"=="x." set OUTPUT_DIR=..\..\..\org.eclipse.swt.win32.win32.x86_64 + set CFLAGS=-DJNI64 call "%MSVC_HOME%\VC\Auxiliary\Build\vcvarsall.bat" x64 shift @@ -72,28 +83,103 @@ shift @rem if call to vcvarsall.bat (which sets up environment) silently fails, then provide advice to user. WHERE cl if %ERRORLEVEL% NEQ 0 ( - echo "WARNING: cl (Microsoft C compiler) not found on path. Please install Microsoft Visual Studio." - echo " If already installed, try launching eclipse from the 'Developer Command Prompt for VS' " - echo " Refer steps for SWT Windows native setup: https://www.eclipse.org/swt/swt_win_native.php" + CALL :ECHO "WARNING: cl (Microsoft C compiler) not found on path. Please install Microsoft Visual Studio." + CALL :ECHO " If already installed, try launching eclipse from the 'Developer Command Prompt for VS'" + CALL :ECHO " Refer steps for SWT Windows native setup: https://www.eclipse.org/swt/swt_win_native.php" ) nmake -f make_win32.mak %1 %2 %3 %4 %5 %6 %7 %8 %9 GOTO :EOF -:TryToUseJdk -SET TESTED_JDK_PATH_MASK=%~1 -:: Loop over all directories matching mask. -:: Note that directories are iterated in alphabetical order and *last* hit will -:: be selected in hopes to select the highest available JDK version. -FOR /D %%I IN ("%TESTED_JDK_PATH_MASK%") DO ( - IF NOT EXIST "%%~I" ( - ECHO -- JDK '%%~I' doesn't exist on disk - GOTO :EOF +@rem Find Visual Studio +@rem %1 = path template with '$MSVC_VERSION$' and '$MSVC_EDITION$' tokens +:FindVisualStudio + @rem Early return if already found + IF NOT "%MSVC_HOME%"=="" GOTO :EOF + + IF "%MSVC_VERSION%"=="auto" ( + CALL :FindVisualStudio2 "%~1" "2022" + CALL :FindVisualStudio2 "%~1" "2019" + CALL :FindVisualStudio2 "%~1" "2017" + ) ELSE ( + CALL :FindVisualStudio2 "%~1" "%MSVC_VERSION%" ) - IF NOT EXIST "%%~I\include\jni.h" ( - ECHO -- JDK '%%~I' is bad: no jni.h +GOTO :EOF + +@rem Find Visual Studio +@rem %1 = path template with '$MSVC_VERSION$' and '$MSVC_EDITION$' tokens +@rem %2 = value for '$MSVC_VERSION$' +:FindVisualStudio2 + @rem Early return if already found + IF NOT "%MSVC_HOME%"=="" GOTO :EOF + + IF "%MSVC_EDITION%"=="auto" ( + CALL :FindVisualStudio3 "%~1" "%~2" "Community" + CALL :FindVisualStudio3 "%~1" "%~2" "Enterprise" + CALL :FindVisualStudio3 "%~1" "%~2" "Professional" + ) ELSE ( + CALL :FindVisualStudio3 "%~1" "%~2" "%MSVC_EDITION%" + ) +GOTO :EOF + +@rem Find Visual Studio +@rem %1 = path template with '$MSVC_VERSION$' and '$MSVC_EDITION$' tokens +@rem %2 = value for '$MSVC_VERSION$' +@rem %3 = value for '$MSVC_EDITION$' +:FindVisualStudio3 + @rem Early return if already found + IF NOT "%MSVC_HOME%"=="" GOTO :EOF + + SET "TESTED_VS_PATH=%~1" + @rem Substitute '$MSVC_VERSION$' and '$MSVC_EDITION$' + CALL SET "TESTED_VS_PATH=%%TESTED_VS_PATH:$MSVC_VERSION$=%~2%%" + CALL SET "TESTED_VS_PATH=%%TESTED_VS_PATH:$MSVC_EDITION$=%~3%%" + + @rem If the folder isn't there, then skip it without printing errors + IF NOT EXIST "%TESTED_VS_PATH%" GOTO :EOF + + @rem Try this path + CALL :TryToUseVisualStudio "%TESTED_VS_PATH%" +GOTO :EOF + +@rem Test Visual Studio and set '%MSVC_HOME%' on success +@rem %1 = tested path +:TryToUseVisualStudio + SET "TESTED_VS_PATH=%~1" + IF NOT EXIST "%TESTED_VS_PATH%\VC\Auxiliary\Build\vcvarsall.bat" ( + CALL :ECHO "-- VisualStudio '%TESTED_VS_PATH%' is bad: 'vcvarsall.bat' not found" GOTO :EOF ) - ECHO -- JDK '%%~I' looks good, selecting it - SET SWT_JAVA_HOME=%%~I -) + CALL :ECHO "-- VisualStudio '%TESTED_VS_PATH%' looks good, selecting it" + SET "MSVC_HOME=%TESTED_VS_PATH%" +GOTO :EOF + +:TryToUseJdk + SET "TESTED_JDK_PATH_MASK=%~1" + @rem Loop over all directories matching mask. + @rem Note that directories are iterated in alphabetical order and *last* hit will + @rem be selected in hopes to select the highest available JDK version. + FOR /D %%I IN ("%TESTED_JDK_PATH_MASK%") DO ( + IF NOT EXIST "%%~I" ( + CALL :ECHO "-- JDK '%%~I' doesn't exist on disk" + GOTO :EOF + ) + IF NOT EXIST "%%~I\include\jni.h" ( + CALL :ECHO "-- JDK '%%~I' is bad: no jni.h" + GOTO :EOF + ) + CALL :ECHO "-- JDK '%%~I' looks good, selecting it" + SET "SWT_JAVA_HOME=%%~I" + ) +GOTO :EOF + +@rem Regular ECHO has trouble with special characters such as (). +@rem At the same time, if its argument is quoted, the quotes are printed literally. +@rem The workaround is to escape all special characters with ^ +:ECHO +SET "ECHO_STRING=%~1" +SET "ECHO_STRING=%ECHO_STRING:<=^<%" +SET "ECHO_STRING=%ECHO_STRING:>=^>%" +SET "ECHO_STRING=%ECHO_STRING:(=^(%" +SET "ECHO_STRING=%ECHO_STRING:)=^)%" +ECHO %ECHO_STRING% GOTO :EOF diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/make_win32.mak b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/make_win32.mak index 7e9cf972e6..e70c3dd343 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/make_win32.mak +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/make_win32.mak @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2000, 2018 IBM Corporation and others. +# Copyright (c) 2000, 2022 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java index d4af8f36be..372eb78785 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2020 IBM Corporation and others. + * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -2237,6 +2237,11 @@ public static final long SendMessage (long hWnd, int Msg, long wParam, TCHAR lPa * expected to configure individual tweaks instead of calling this method. * Please see <code>Display#setData()</code> and documentation for string keys * used there. + * </p> + * <p> + * On GTK, behavior may be different as the boolean flag doesn't force dark + * theme instead it specify that dark theme is preferred. + * </p> * * @param isDarkTheme <code>true</code> for dark theme */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c index 386a903097..b278236729 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2021 IBM Corporation and others. All rights reserved. + * Copyright (c) 2009, 2022 IBM Corporation and others. All rights reserved. * The contents of this file are made available under the terms * of the GNU Lesser General Public License (LGPL) Version 2.1 that * accompanies this distribution (lgpl-v21.txt). The LGPL is also @@ -84,33 +84,6 @@ fail: } #endif -#ifndef NO_JSObjectMakeArray -JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(JSObjectMakeArray) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2, jlongArray arg3) -{ - jlong *lparg2=NULL; - jlong *lparg3=NULL; - jlong rc = 0; - WebKitGTK_NATIVE_ENTER(env, that, JSObjectMakeArray_FUNC); - if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail; - if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail; -/* - rc = (jlong)JSObjectMakeArray(arg0, arg1, lparg2, lparg3); -*/ - { - WebKitGTK_LOAD_FUNCTION(fp, JSObjectMakeArray) - if (fp) { - rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong, jlong, jlong *, jlong *))fp)(arg0, arg1, lparg2, lparg3); - } - } -fail: - if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0); - if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0); - WebKitGTK_NATIVE_EXIT(env, that, JSObjectMakeArray_FUNC); - return rc; -} -#endif - #ifndef NO_JSStringCreateWithUTF8CString JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(JSStringCreateWithUTF8CString) (JNIEnv *env, jclass that, jbyteArray arg0) @@ -217,86 +190,6 @@ JNIEXPORT jint JNICALL WebKitGTK_NATIVE(JSValueGetType) } #endif -#ifndef NO_JSValueMakeBoolean -JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(JSValueMakeBoolean) - (JNIEnv *env, jclass that, jlong arg0, jint arg1) -{ - jlong rc = 0; - WebKitGTK_NATIVE_ENTER(env, that, JSValueMakeBoolean_FUNC); -/* - rc = (jlong)JSValueMakeBoolean(arg0, arg1); -*/ - { - WebKitGTK_LOAD_FUNCTION(fp, JSValueMakeBoolean) - if (fp) { - rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong, jint))fp)(arg0, arg1); - } - } - WebKitGTK_NATIVE_EXIT(env, that, JSValueMakeBoolean_FUNC); - return rc; -} -#endif - -#ifndef NO_JSValueMakeNumber -JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(JSValueMakeNumber) - (JNIEnv *env, jclass that, jlong arg0, jdouble arg1) -{ - jlong rc = 0; - WebKitGTK_NATIVE_ENTER(env, that, JSValueMakeNumber_FUNC); -/* - rc = (jlong)JSValueMakeNumber(arg0, arg1); -*/ - { - WebKitGTK_LOAD_FUNCTION(fp, JSValueMakeNumber) - if (fp) { - rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong, jdouble))fp)(arg0, arg1); - } - } - WebKitGTK_NATIVE_EXIT(env, that, JSValueMakeNumber_FUNC); - return rc; -} -#endif - -#ifndef NO_JSValueMakeString -JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(JSValueMakeString) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1) -{ - jlong rc = 0; - WebKitGTK_NATIVE_ENTER(env, that, JSValueMakeString_FUNC); -/* - rc = (jlong)JSValueMakeString(arg0, arg1); -*/ - { - WebKitGTK_LOAD_FUNCTION(fp, JSValueMakeString) - if (fp) { - rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong, jlong))fp)(arg0, arg1); - } - } - WebKitGTK_NATIVE_EXIT(env, that, JSValueMakeString_FUNC); - return rc; -} -#endif - -#ifndef NO_JSValueMakeUndefined -JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(JSValueMakeUndefined) - (JNIEnv *env, jclass that, jlong arg0) -{ - jlong rc = 0; - WebKitGTK_NATIVE_ENTER(env, that, JSValueMakeUndefined_FUNC); -/* - rc = (jlong)JSValueMakeUndefined(arg0); -*/ - { - WebKitGTK_LOAD_FUNCTION(fp, JSValueMakeUndefined) - if (fp) { - rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong))fp)(arg0); - } - } - WebKitGTK_NATIVE_EXIT(env, that, JSValueMakeUndefined_FUNC); - return rc; -} -#endif - #ifndef NO_JSValueToNumber JNIEXPORT jdouble JNICALL WebKitGTK_NATIVE(JSValueToNumber) (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2) @@ -1321,6 +1214,28 @@ JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1response_1policy_1decision_1get } #endif +#ifndef NO_webkit_1security_1manager_1register_1uri_1scheme_1as_1secure +JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1security_1manager_1register_1uri_1scheme_1as_1secure) + (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1) +{ + jbyte *lparg1=NULL; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1security_1manager_1register_1uri_1scheme_1as_1secure_FUNC); + if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; +/* + webkit_security_manager_register_uri_scheme_as_secure(arg0, lparg1); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_security_manager_register_uri_scheme_as_secure) + if (fp) { + ((void (CALLING_CONVENTION*)(jlong, jbyte *))fp)(arg0, lparg1); + } + } +fail: + if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); + WebKitGTK_NATIVE_EXIT(env, that, webkit_1security_1manager_1register_1uri_1scheme_1as_1secure_FUNC); +} +#endif + #ifndef NO_webkit_1uri_1request_1get_1http_1headers JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1uri_1request_1get_1http_1headers) (JNIEnv *env, jclass that, jlong arg0) @@ -1425,6 +1340,148 @@ JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1uri_1response_1get_1mime_1type) } #endif +#ifndef NO_webkit_1uri_1scheme_1request_1finish +JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1uri_1scheme_1request_1finish) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jbyteArray arg3) +{ + jbyte *lparg3=NULL; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1uri_1scheme_1request_1finish_FUNC); + if (arg3) if ((lparg3 = (*env)->GetByteArrayElements(env, arg3, NULL)) == NULL) goto fail; +/* + webkit_uri_scheme_request_finish(arg0, arg1, arg2, lparg3); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_uri_scheme_request_finish) + if (fp) { + ((void (CALLING_CONVENTION*)(jlong, jlong, jlong, jbyte *))fp)(arg0, arg1, arg2, lparg3); + } + } +fail: + if (arg3 && lparg3) (*env)->ReleaseByteArrayElements(env, arg3, lparg3, JNI_ABORT); + WebKitGTK_NATIVE_EXIT(env, that, webkit_1uri_1scheme_1request_1finish_FUNC); +} +#endif + +#ifndef NO_webkit_1uri_1scheme_1request_1get_1uri +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1uri_1scheme_1request_1get_1uri) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1uri_1scheme_1request_1get_1uri_FUNC); +/* + rc = (jlong)webkit_uri_scheme_request_get_uri(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_uri_scheme_request_get_uri) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, webkit_1uri_1scheme_1request_1get_1uri_FUNC); + return rc; +} +#endif + +#ifndef NO_webkit_1uri_1scheme_1request_1get_1web_1view +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1uri_1scheme_1request_1get_1web_1view) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1uri_1scheme_1request_1get_1web_1view_FUNC); +/* + rc = (jlong)webkit_uri_scheme_request_get_web_view(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_uri_scheme_request_get_web_view) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, webkit_1uri_1scheme_1request_1get_1web_1view_FUNC); + return rc; +} +#endif + +#ifndef NO_webkit_1user_1content_1manager_1add_1script +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1user_1content_1manager_1add_1script) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1) +{ + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1user_1content_1manager_1add_1script_FUNC); +/* + rc = (jlong)webkit_user_content_manager_add_script(arg0, arg1); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_user_content_manager_add_script) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong, jlong))fp)(arg0, arg1); + } + } + WebKitGTK_NATIVE_EXIT(env, that, webkit_1user_1content_1manager_1add_1script_FUNC); + return rc; +} +#endif + +#ifndef NO_webkit_1user_1content_1manager_1remove_1all_1scripts +JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1user_1content_1manager_1remove_1all_1scripts) + (JNIEnv *env, jclass that, jlong arg0) +{ + WebKitGTK_NATIVE_ENTER(env, that, webkit_1user_1content_1manager_1remove_1all_1scripts_FUNC); +/* + webkit_user_content_manager_remove_all_scripts(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_user_content_manager_remove_all_scripts) + if (fp) { + ((void (CALLING_CONVENTION*)(jlong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, webkit_1user_1content_1manager_1remove_1all_1scripts_FUNC); +} +#endif + +#ifndef NO_webkit_1user_1script_1new +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1user_1script_1new) + (JNIEnv *env, jclass that, jbyteArray arg0, jint arg1, jint arg2, jlong arg3, jlong arg4) +{ + jbyte *lparg0=NULL; + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1user_1script_1new_FUNC); + if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail; +/* + rc = (jlong)webkit_user_script_new(lparg0, arg1, arg2, arg3, arg4); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_user_script_new) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jbyte *, jint, jint, jlong, jlong))fp)(lparg0, arg1, arg2, arg3, arg4); + } + } +fail: + if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, JNI_ABORT); + WebKitGTK_NATIVE_EXIT(env, that, webkit_1user_1script_1new_FUNC); + return rc; +} +#endif + +#ifndef NO_webkit_1user_1script_1unref +JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1user_1script_1unref) + (JNIEnv *env, jclass that, jlong arg0) +{ + WebKitGTK_NATIVE_ENTER(env, that, webkit_1user_1script_1unref_FUNC); +/* + webkit_user_script_unref(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_user_script_unref) + if (fp) { + ((void (CALLING_CONVENTION*)(jlong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, webkit_1user_1script_1unref_FUNC); +} +#endif + #ifndef NO_webkit_1web_1context_1allow_1tls_1certificate_1for_1host JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1allow_1tls_1certificate_1for_1host) (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jbyteArray arg2) @@ -1489,6 +1546,26 @@ JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1get_1default) } #endif +#ifndef NO_webkit_1web_1context_1get_1security_1manager +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1get_1security_1manager) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1web_1context_1get_1security_1manager_FUNC); +/* + rc = (jlong)webkit_web_context_get_security_manager(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_web_context_get_security_manager) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, webkit_1web_1context_1get_1security_1manager_FUNC); + return rc; +} +#endif + #ifndef NO_webkit_1web_1context_1get_1type JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1get_1type) (JNIEnv *env, jclass that) @@ -1529,61 +1606,43 @@ JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1get_1website_1dat } #endif -#ifndef NO_webkit_1web_1context_1set_1tls_1errors_1policy -JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1set_1tls_1errors_1policy) - (JNIEnv *env, jclass that, jlong arg0, jint arg1) -{ - WebKitGTK_NATIVE_ENTER(env, that, webkit_1web_1context_1set_1tls_1errors_1policy_FUNC); -/* - webkit_web_context_set_tls_errors_policy(arg0, arg1); -*/ - { - WebKitGTK_LOAD_FUNCTION(fp, webkit_web_context_set_tls_errors_policy) - if (fp) { - ((void (CALLING_CONVENTION*)(jlong, jint))fp)(arg0, arg1); - } - } - WebKitGTK_NATIVE_EXIT(env, that, webkit_1web_1context_1set_1tls_1errors_1policy_FUNC); -} -#endif - -#ifndef NO_webkit_1web_1context_1set_1web_1extensions_1directory -JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1set_1web_1extensions_1directory) - (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1) +#ifndef NO_webkit_1web_1context_1register_1uri_1scheme +JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1register_1uri_1scheme) + (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jlong arg2, jlong arg3, jlong arg4) { jbyte *lparg1=NULL; - WebKitGTK_NATIVE_ENTER(env, that, webkit_1web_1context_1set_1web_1extensions_1directory_FUNC); + WebKitGTK_NATIVE_ENTER(env, that, webkit_1web_1context_1register_1uri_1scheme_FUNC); if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; /* - webkit_web_context_set_web_extensions_directory(arg0, lparg1); + webkit_web_context_register_uri_scheme(arg0, lparg1, arg2, arg3, arg4); */ { - WebKitGTK_LOAD_FUNCTION(fp, webkit_web_context_set_web_extensions_directory) + WebKitGTK_LOAD_FUNCTION(fp, webkit_web_context_register_uri_scheme) if (fp) { - ((void (CALLING_CONVENTION*)(jlong, jbyte *))fp)(arg0, lparg1); + ((void (CALLING_CONVENTION*)(jlong, jbyte *, jlong, jlong, jlong))fp)(arg0, lparg1, arg2, arg3, arg4); } } fail: if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); - WebKitGTK_NATIVE_EXIT(env, that, webkit_1web_1context_1set_1web_1extensions_1directory_FUNC); + WebKitGTK_NATIVE_EXIT(env, that, webkit_1web_1context_1register_1uri_1scheme_FUNC); } #endif -#ifndef NO_webkit_1web_1context_1set_1web_1extensions_1initialization_1user_1data -JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1set_1web_1extensions_1initialization_1user_1data) - (JNIEnv *env, jclass that, jlong arg0, jlong arg1) +#ifndef NO_webkit_1web_1context_1set_1tls_1errors_1policy +JNIEXPORT void JNICALL WebKitGTK_NATIVE(webkit_1web_1context_1set_1tls_1errors_1policy) + (JNIEnv *env, jclass that, jlong arg0, jint arg1) { - WebKitGTK_NATIVE_ENTER(env, that, webkit_1web_1context_1set_1web_1extensions_1initialization_1user_1data_FUNC); + WebKitGTK_NATIVE_ENTER(env, that, webkit_1web_1context_1set_1tls_1errors_1policy_FUNC); /* - webkit_web_context_set_web_extensions_initialization_user_data(arg0, arg1); + webkit_web_context_set_tls_errors_policy(arg0, arg1); */ { - WebKitGTK_LOAD_FUNCTION(fp, webkit_web_context_set_web_extensions_initialization_user_data) + WebKitGTK_LOAD_FUNCTION(fp, webkit_web_context_set_tls_errors_policy) if (fp) { - ((void (CALLING_CONVENTION*)(jlong, jlong))fp)(arg0, arg1); + ((void (CALLING_CONVENTION*)(jlong, jint))fp)(arg0, arg1); } } - WebKitGTK_NATIVE_EXIT(env, that, webkit_1web_1context_1set_1web_1extensions_1initialization_1user_1data_FUNC); + WebKitGTK_NATIVE_EXIT(env, that, webkit_1web_1context_1set_1tls_1errors_1policy_FUNC); } #endif @@ -1832,6 +1891,26 @@ JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1view_1get_1uri) } #endif +#ifndef NO_webkit_1web_1view_1get_1user_1content_1manager +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1view_1get_1user_1content_1manager) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, webkit_1web_1view_1get_1user_1content_1manager_FUNC); +/* + rc = (jlong)webkit_web_view_get_user_content_manager(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_web_view_get_user_content_manager) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jlong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, webkit_1web_1view_1get_1user_1content_1manager_FUNC); + return rc; +} +#endif + #ifndef NO_webkit_1web_1view_1get_1window_1properties JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(webkit_1web_1view_1get_1window_1properties) (JNIEnv *env, jclass that, jlong arg0) diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c deleted file mode 100644 index cd9a5e15fd..0000000000 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c +++ /dev/null @@ -1,616 +0,0 @@ -#include "webkitgtk_extension.h" - -/* - * To debug this extension: - * -ensure this is built with debug flags (look for '-g*' in make_linux, or 'SWT_LIB_DEBUG' macro) - * -connect to the WebKitWebProcess with the PID of this extension. It can be found as follows: - g_print("Extension PID: %d\n", getpid()); - */ - -// Client address of the main process GDBusServer -- the extension connects to this -const gchar *swt_main_proc_client_address = NULL; - -// Client address of the extension's GDBusServer -- SWT main process connects to this -const gchar *extension_server_address = NULL; - -// See: WebKitGTK.java's 'TYPE NOTES' -guchar SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY = 101; -guchar SWT_DBUS_MAGIC_NUMBER_NULL = 48; - -// This struct represents a BrowserFunction -typedef struct { - guint64 page_id; // page ID - gchar *function; // JS function - gchar *url; // URL the function belongs to -} BrowserFunction; - -// The list of BrowserFunctions registered to this extension -GSList *function_list = NULL; - -// GDBusConnection to the SWT main process -GDBusConnection *connection_to_main_proc = NULL; - -// This extension's GDBusServer and related resources -GDBusServer *server = NULL; -GDBusAuthObserver *auth_observer = NULL; -gchar *guid = NULL; - -// GDBusConnection from SWT main process -GDBusConnection *connection_from_main_proc = NULL; - -/** - * Caller should free the returned GVariant - */ -GVariant *call_main_proc_sync(char * method_name, GVariant *parameters) { - GError *error = NULL; // Some functions return errors through params - GVariant *result; // The value result from a call - - // Send a message - result = g_dbus_connection_call_sync(connection_to_main_proc, WEBKIT_MAIN_PROCESS_DBUS_NAME, - WEBKIT_MAIN_PROCESS_OBJECT_PATH, WEBKIT_MAIN_PROCESS_INTERFACE_NAME, method_name, parameters, - NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - // Error checking. - if (result == NULL) { - if (error != NULL) { - g_error("call_main_proc_sync failed because '%s.'\n", error->message); - } else { - g_error("call_main_proc_sync failed for an unknown reason.\n"); - } - return NULL; - } - - return result; -} - -// +--------------------------------------------------+ -// | JavaScriptCore to/from conversion GVariant logic | -// +--------------------------------------------------+ - -/** Return true if the given JSValueRef is one we can push over gdbus. False otherwise. - * We support basic types, nulls and arrays of basic types.*/ -gboolean is_js_valid(JSContextRef context, JSValueRef value) { - JSType type = JSValueGetType(context, value); - if (type == kJSTypeBoolean - || type == kJSTypeNumber - || type == kJSTypeString - || type == kJSTypeNull - || type == kJSTypeUndefined) { - return true; - } - if (type == kJSTypeObject && JSValueIsArray(context, value)) { - JSStringRef propertyName = JSStringCreateWithUTF8CString("length"); - JSObjectRef object = JSValueToObject(context, value, NULL); - JSValueRef valuePtr = JSObjectGetProperty(context, object, propertyName, NULL); - JSStringRelease(propertyName); - int length = (int) JSValueToNumber(context, valuePtr, NULL); - int i; - for (i = 0; i < length; i++) { - const JSValueRef child = JSObjectGetPropertyAtIndex(context, object, i, NULL); - if (!is_js_valid(context, child)) { - return false; - } - } - return true; - } - return false; -} - -/* - * Developer note: - * JavaScriptCore defines a "Number" to be a double in general. It doesn't seem to be using "Int". - */ -static GVariant * convert_js_to_gvariant (JSContextRef context, JSValueRef value){ - g_assert(context != NULL); - g_assert(value != NULL); - JSType type = JSValueGetType(context, value); - - if (type == kJSTypeBoolean) { - gboolean result = JSValueToNumber(context, value, NULL) != 0; - return g_variant_new_boolean(result); - } - - if (type == kJSTypeNumber) { - double result = JSValueToNumber(context, value, NULL); - return g_variant_new_double(result); - } - - if (type == kJSTypeString) { - JSStringRef stringRef = JSValueToStringCopy(context, value, NULL); - size_t length = JSStringGetMaximumUTF8CStringSize(stringRef); - char* string = (char*) malloc(length); - JSStringGetUTF8CString(stringRef, string, length); - GVariant *variant = g_variant_new_string(string); - free(string); - return variant; - } - - if (type == kJSTypeNull || type == kJSTypeUndefined) { - return g_variant_new_byte(SWT_DBUS_MAGIC_NUMBER_NULL); - } - - if (type == kJSTypeObject) { - JSStringRef propertyName = JSStringCreateWithUTF8CString("length"); - JSObjectRef object = JSValueToObject(context, value, NULL); - JSValueRef valuePtr = JSObjectGetProperty(context, object, propertyName, NULL); - JSStringRelease(propertyName); - - if (JSValueGetType(context, valuePtr) == kJSTypeNumber) { - int length = (int) JSValueToNumber(context, valuePtr, NULL); - - if (length == 0) { - return g_variant_new_byte(SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY); - } - GVariant **children = g_new(GVariant *, length); - int i = 0; - for (i = 0; i < length; i++) { - const JSValueRef child = JSObjectGetPropertyAtIndex(context, object, i, NULL); - children[i] = convert_js_to_gvariant(context, child); - } - GVariant* variant = g_variant_new_tuple(children, length); - g_free(children); - return variant; - } - } - - // Get type value string - JSStringRef valueIString = JSValueToStringCopy(context, value, NULL); - size_t valueUTF8Size = JSStringGetMaximumUTF8CStringSize(valueIString); - char* valueUTF8 = (char*) malloc(valueUTF8Size); - JSStringGetUTF8CString(valueIString, valueUTF8, valueUTF8Size); - - g_warning("Unhandled type %d value: %s \n", type, valueUTF8); - free(valueUTF8); - JSStringRelease(valueIString); - - return NULL; -} - - -static JSValueRef convert_gvariant_to_js (JSContextRef context, GVariant * value){ - g_assert(context != NULL); - g_assert(value != NULL); - - if (g_variant_is_of_type(value, G_VARIANT_TYPE_BYTE)) { // see: WebKitGTK.java 'TYPE NOTES' - guchar magic_number = g_variant_get_byte(value); - if (magic_number == SWT_DBUS_MAGIC_NUMBER_NULL) { - // 'JSValueMakeUndefined' is used as oppose to 'JSValueMakeNull' (from what I gather) for legacy reasons. - // I.e webkit1 used it, so we shall use it in webkit2 also. - return JSValueMakeUndefined(context); - } else if (magic_number == SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY) { - return JSObjectMakeArray(context, 0, NULL, NULL); // The empty array with no children. - } else { - g_error("Java sent an unknown magic number: '%d' , this should never happen. \n", magic_number); - } - } - - if (g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) { - return JSValueMakeBoolean(context, g_variant_get_boolean(value)); - } - - if (g_variant_is_of_type(value, G_VARIANT_TYPE_DOUBLE)) { - return JSValueMakeNumber(context, g_variant_get_double(value)); - } - - if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { - JSStringRef stringRef = JSStringCreateWithUTF8CString(g_variant_get_string(value, NULL)); - JSValueRef result = JSValueMakeString(context, stringRef); - JSStringRelease(stringRef); - return result; - } - - if (g_variant_is_of_type(value, G_VARIANT_TYPE_TUPLE)) { - gsize length = g_variant_n_children(value); - JSValueRef *children = g_new(JSValueRef, length); - - gsize i = 0; - for (i = 0; i < length; i++) { - children[i] = convert_gvariant_to_js(context, g_variant_get_child_value(value, i)); - } - JSValueRef result = JSObjectMakeArray(context, length, children, NULL); - g_free(children); - return result; - } - g_error("Unhandled type %s \n", g_variant_get_type_string(value)); - return NULL; -} - -// +--------------------+--------------------------------------------------------- -// | WebExtension Logic | -// +--------------------+ - -// Reached by calling "webkit2callJava();" in javascript console. -// Some basic c function to be exposed to the javascript environment -static JSValueRef webkit2callJava (JSContextRef context, - JSObjectRef function, - JSObjectRef thisObject, - size_t argumentCount, - const JSValueRef arguments[], // [String webview, double index, String Token, Object[] args] - JSValueRef *exception) { - g_assert (argumentCount == 4); - GVariant *g_var_params; // The parameters to a function call - - // Need to ensure user arguments won't break gdbus. - if (!is_js_valid(context, arguments[3])) { - g_warning("Arguments contain an invalid type (object). Only Number,Boolean,null,String and (mixed) arrays of basic types are supported"); - return 0; - } - - g_var_params = g_variant_new ("(@s@d@s@*)", // pointer to String, pointer to double, pointer to string, pointer to any type. - convert_js_to_gvariant(context, arguments[0]), // String webView - convert_js_to_gvariant(context, arguments[1]), // int index - convert_js_to_gvariant(context, arguments[2]), // String Token - convert_js_to_gvariant(context, arguments[3]) // js args - ); - - GVariant *g_var_result = call_main_proc_sync("webkit2callJava", g_var_params); - if (g_var_result == NULL) { - g_error("Java call returned NULL. This should never happpen\n"); - return 0; - } - - // gdbus dynamic call always returns an array(tuple) with return types. - // In our case, we return a single type or an array. - // E.g java:int -> gdbus:(i) (array containing one int) - // E.g java [int,str] -> gdbus:((is)) (array with array of (int+str). - // So we always extract the first child, convert and pass to js. - JSValueRef retVal = 0; - if (g_variant_is_of_type(g_var_result, G_VARIANT_TYPE_TUPLE)) { - if (g_variant_n_children(g_var_result) != 1) { - g_error("Should only receive a single item in the tuple, but length is: %ud\n", (unsigned int) g_variant_n_children(g_var_result)); - } - retVal = convert_gvariant_to_js(context, g_variant_get_child_value(g_var_result, 0)); - } else { - g_error("Unsupported return type. Should be an array, but received a single type.\n"); - } - - g_variant_unref(g_var_result); - return retVal; -} - -static void web_page_created_callback(WebKitWebExtension *extension, WebKitWebPage *web_page, gpointer user_data) { - // Observation. This seems to be called only once. -} - -/** - * Returns the main frame of the WebPage with the given ID - */ -static WebKitFrame *webkitgtk_extension_get_main_frame (const guint64 id) { - WebKitWebPage *web_page = webkit_web_extension_get_page (this_extension, id); - return webkit_web_page_get_main_frame (web_page); -} - -/* - * Execute the Javascript for the given page and URL. - */ -static gboolean webkitgtk_extension_execute_script (const guint64 page_id, gchar* script, gchar* url) { - WebKitFrame *main_frame = webkitgtk_extension_get_main_frame (page_id); - - JSStringRef url_string = JSStringCreateWithUTF8CString (url); - JSStringRef script_string = JSStringCreateWithUTF8CString (script); - - /* - * TODO Bug 570285: Replace with webkit_frame_get_js_context() - * when minimal WebKitGTK version is 2.22+ - */ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - JSGlobalContextRef context = webkit_frame_get_javascript_global_context (main_frame); - G_GNUC_END_IGNORE_DEPRECATIONS - - JSValueRef exception; - JSValueRef result = JSEvaluateScript(context, script_string, NULL, url_string, 0, &exception); - if (!result) { - JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL); - size_t exceptionUTF8Size = JSStringGetMaximumUTF8CStringSize(exceptionIString); - char* exceptionUTF8 = (char*)malloc(exceptionUTF8Size); - JSStringGetUTF8CString(exceptionIString, exceptionUTF8, exceptionUTF8Size); - g_error("Failed to execute script exception: %s\n", exceptionUTF8); - free(exceptionUTF8); - JSStringRelease(exceptionIString); - } - - JSStringRelease (url_string); - JSStringRelease (script_string); - - return result != NULL; -} - -void execute_browser_functions(gconstpointer item, gpointer page) { - BrowserFunction *function = (BrowserFunction *) item; - if (function != NULL && function->page_id == GPOINTER_TO_UINT(page)) { - webkitgtk_extension_execute_script(function->page_id, function->function, function->url); - } - return; -} - -gint find_browser_function (gconstpointer item, gconstpointer target) { - BrowserFunction *element = (BrowserFunction *) item; - BrowserFunction *remove = (BrowserFunction *) target; - if (element->page_id == remove->page_id && g_strcmp0(element->function, remove->function) == 0 && - g_strcmp0(element->url, remove->url) == 0) { - return 0; - } - return 1; -} - -void add_browser_function(guint64 page_id, const gchar *function, const gchar *url) { - BrowserFunction *func = g_slice_new0(BrowserFunction); - func->page_id = page_id; - func->function = g_strdup(function); - func->url = g_strdup(url); - function_list = g_slist_append(function_list, func); -} - -void remove_browser_function(guint64 page_id, const gchar *function, const gchar *url) { - BrowserFunction *func = g_slice_new0(BrowserFunction); - func->page_id = page_id; - func->function = g_strdup(function); - func->url = g_strdup(url); - GSList *to_remove = g_slist_find_custom(function_list, func, find_browser_function); - if (to_remove != NULL) { - BrowserFunction *delete_func = to_remove->data; - g_free(delete_func->function); - g_free(delete_func->url); - function_list = g_slist_delete_link(function_list, to_remove); - } - g_free(func->function); - g_free(func->url); - g_slice_free(BrowserFunction, func); -} - -void unpack_browser_function_array(GVariant *array) { - GVariantIter iter; - GVariant *child; - - g_variant_iter_init (&iter, array); - while ((child = g_variant_iter_next_value (&iter))) { - gsize length = (int)g_variant_n_children (child); - if (length > 3) { - // If the length is longer than three, something went wrong and this tuple should be skipped - g_warning("There was an error unpacking the GVariant tuple for a BrowserFunction in the web extension.\n"); - continue; - } - guint64 page = g_variant_get_uint64(g_variant_get_child_value(child, 0)); - if (page == -1UL) { - // Empty or malformed BrowserFunction, skip this one - continue; - } else { - const gchar *function = g_variant_get_string(g_variant_get_child_value(child, 1), NULL); - const gchar *url = g_variant_get_string(g_variant_get_child_value(child, 2), NULL); - if (function != NULL && url != NULL) { - add_browser_function(page, function, url); - } else { - g_warning("There was an error unpacking the function string or URL.\n"); - } - } - g_variant_unref (child); - } -} - -/* - * Every time a webpage is loaded, we should re-register the 'webkit2callJava' function. - * Additionally, we re-register all BrowserFunctions that are stored in the function_list - * GSList. - */ -static void window_object_cleared_callback (WebKitScriptWorld *world, WebKitWebPage *web_page, - WebKitFrame *frame, - gpointer user_data) { - // Observation: This is called every time a webpage is loaded. - JSGlobalContextRef jsContext; - JSObjectRef globalObject; - JSValueRef exception = 0; - - /* - * TODO Bug 570285: Replace with webkit_frame_get_js_context_for_script_world() - * when minimal WebKitGTK version is 2.22+ - */ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - jsContext = webkit_frame_get_javascript_context_for_script_world (frame, world); - G_GNUC_END_IGNORE_DEPRECATIONS - globalObject = JSContextGetGlobalObject (jsContext); - - JSStringRef function_name = JSStringCreateWithUTF8CString("webkit2callJava"); // Func reference by javascript - JSObjectRef jsFunction = JSObjectMakeFunctionWithCallback(jsContext, function_name, webkit2callJava); // C reference to func - JSObjectSetProperty(jsContext, globalObject, function_name, jsFunction, - kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, &exception); - - if (exception) { - g_print("OJSObjectSetProperty exception occurred"); - } - - /* - * Iterate over the list of BrowserFunctions and execute each one of them for the current page. - * This ensures that BrowserFunctions are not lost on page reloads. See bug 536141. - */ - if (function_list != NULL) { - guint64 page_id = webkit_web_page_get_id (web_page); - if (page_id != -1UL) { - g_slist_foreach(function_list, (GFunc)execute_browser_functions, GUINT_TO_POINTER(page_id)); - } else { - g_warning("There was an error fetching the page ID in the object_cleared callback.\n"); - } - } -} - -static void -webkitgtk_extension_handle_method_call (GDBusConnection *connection, const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) { - gboolean result = FALSE; - const gchar *script; - const gchar *url; - guint64 page_id; - // Check method names - if (g_strcmp0(method_name, "webkitgtk_extension_register_function") == 0) { - g_variant_get(parameters, "(t&s&s)", &page_id, &script, &url); - if (page_id != -1UL) { - result = TRUE; - // Return before processing the linked list, to prevent DBus from hanging - g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result)); - add_browser_function(page_id, script, url); - return; - } - g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result)); - return; - } - if (g_strcmp0(method_name, "webkitgtk_extension_deregister_function") == 0) { - g_variant_get(parameters, "(t&s&s)", &page_id, &script, &url); - if (page_id != -1UL) { - result = TRUE; - // Return before processing the linked list, to prevent DBus from hanging - g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result)); - remove_browser_function(page_id, script, url); - return; - } - g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result)); - return; - } - g_error ("Unknown method %s\n", method_name); -} - -static const GDBusInterfaceVTable interface_vtable = {.method_call = webkitgtk_extension_handle_method_call}; - -static void connection_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, - gpointer user_data) { - /* - * If this connection is closed we can shut the server down. NOTE: all connections are freed in the main - * SWT process, including connections created here in this extension. This is done for the sake of - * consistency to avoid double frees. - */ - if (connection == connection_from_main_proc) { - // Free server and its objects - g_dbus_server_stop(server); - g_object_unref(auth_observer); - g_object_unref(server); - g_free(guid); - } -} - -static gboolean new_connection_cb (GDBusServer *server, GDBusConnection *connection, gpointer user_data) { - // Create introspection XML - dbus_introspection_xml = g_new (gchar, strlen(dbus_introspection_xml_template) + - strlen(WEBKITGTK_EXTENSION_INTERFACE_NAME) + 1); - g_sprintf (dbus_introspection_xml, dbus_introspection_xml_template, WEBKITGTK_EXTENSION_INTERFACE_NAME); - - // Create DBus node - dbus_node = g_dbus_node_info_new_for_xml (dbus_introspection_xml, NULL); - g_assert (dbus_node != NULL); - - // Register node on the connection that was just created - dbus_interface = g_dbus_node_info_lookup_interface(dbus_node, WEBKITGTK_EXTENSION_INTERFACE_NAME); - guint registration_id = g_dbus_connection_register_object(connection, WEBKITGTK_EXTENSION_OBJECT_PATH, - dbus_interface, - &interface_vtable, NULL, /* user_data */ - NULL, /* user_data_free_func */ - NULL); /* GError** */ - g_assert(registration_id > 0); - - // This connection will be the one from the main SWT process - connection_from_main_proc = g_object_ref(connection); - - // Listen to the "close" signal on this connection so we can free resources in the extension when - // the time comes. - g_signal_connect(connection_from_main_proc, "closed", G_CALLBACK (connection_closed_cb), NULL); - - return 1; -} - -static gboolean extension_authorize_peer (GDBusAuthObserver *observer, GIOStream *stream, GCredentials *credentials, - gpointer user_data) { - g_autoptr (GError) error = NULL; - gboolean authorized = FALSE; - if (credentials != NULL) { - GCredentials *own_credentials; - own_credentials = g_credentials_new (); - if (g_credentials_is_same_user (credentials, own_credentials, &error)) { - authorized = TRUE; - } - g_object_unref (own_credentials); - } - if (error) { - g_warning ("Error authenticating client connection: %s", error->message); - } - return authorized; -} - -// Returns a valid GDBusServer address -- this will be the address used to connect to the extension's -// GDBusServer. On Linux, the address required is used for as an abstract path. If abstract path is not supported -// one must create & manage temporary directories. See Bug562443. -gchar *construct_server_address () { - gchar *tmp_address = g_strdup("unix:tmpdir=/tmp/SWT-WebExtensionGDBusServer"); - - return tmp_address; -} - -// Creates the GDBusServer for this web extension -static void create_server () { - g_autoptr (GError) error = NULL; - extension_server_address = construct_server_address(); - auth_observer = g_dbus_auth_observer_new(); - - guid = g_dbus_generate_guid(); - server = g_dbus_server_new_sync(extension_server_address, G_DBUS_SERVER_FLAGS_NONE, guid, - auth_observer, NULL, &error); - - if (error) { - g_error ("Failed to create server: %s", error->message); - } - - if (server) { - g_signal_connect(server, "new-connection", G_CALLBACK(new_connection_cb), NULL); - g_dbus_server_start(server); - g_signal_connect (auth_observer, "authorize-authenticated-peer", G_CALLBACK(extension_authorize_peer), NULL); - } -} - -// Identifies this web extension to the main SWT process by sending its -// server address over DBus. -static void identify_extension_to_main_proc () { - const gchar *client_address_for_extension_server = g_dbus_server_get_client_address(server); - GVariant *result = call_main_proc_sync("webkitWebExtensionIdentifier", g_variant_new ("(s)", - client_address_for_extension_server)); - - // Process and register any pending BrowserFunctions from the main SWT process - if (g_variant_is_of_type(result, G_VARIANT_TYPE_TUPLE)) { - unpack_browser_function_array(g_variant_get_child_value(result, 0)); - } else { - g_warning("webkitWebExtensionIdentifier return value from SWT was an unexpected type""(not a tuple).\n"); - } -} - -// Creates a GDBusConnection to the main SWT process -static void connect_to_main_proc (GVariant *user_data) { - swt_main_proc_client_address = g_variant_get_string(user_data, NULL); - - g_autoptr (GError) error = NULL; - connection_to_main_proc = g_dbus_connection_new_for_address_sync (swt_main_proc_client_address, - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, NULL, &error); - - if (error) { - g_error ("Failed to create connection: %s", error->message); - } - - if (connection_to_main_proc && g_dbus_connection_is_closed(connection_to_main_proc)) { - g_error ("Failed to created connection: connection is closed"); - } -} - -G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data(WebKitWebExtension *extension, GVariant *user_data) { - this_extension = extension; - - // Connect to the main SWT process - connect_to_main_proc(user_data); - - // Create this extension's GDBusServer - create_server(); - - // Identify this extension's server address to the main process - identify_extension_to_main_proc(); - - // WebKit callbacks - g_signal_connect(extension, "page-created", G_CALLBACK(web_page_created_callback), NULL); - g_signal_connect (webkit_script_world_get_default (), "window-object-cleared", G_CALLBACK (window_object_cleared_callback), NULL); -} diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h deleted file mode 100644 index 3edca55451..0000000000 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h +++ /dev/null @@ -1,74 +0,0 @@ - /******************************************************************************* - * Copyright (c) 2017 Red Hat and others. All rights reserved. - * The contents of this file are made available under the terms - * of the GNU Lesser General Public License (LGPL) Version 2.1 that - * accompanies this distribution (lgpl-v21.txt). The LGPL is also - * available at http://www.gnu.org/licenses/lgpl.html. If the version - * of the LGPL at http://www.gnu.org is different to the version of - * the LGPL accompanying this distribution and there is any conflict - * between the two license versions, the terms of the LGPL accompanying - * this distribution shall govern. - * - * Contributors: - * Red Hat - initial API and implementation - *******************************************************************************/ -#ifndef INC_webkit_extension_H -#define INC_webkit_extension_H - -#include <string.h> - -#include <glib.h> -#include <glib/gprintf.h> - -#include <gio/gio.h> -#include <stdlib.h> - -#include <unistd.h> -#include <stdio.h> - -// These 2 are only for getpid(); -#include <sys/types.h> -#include <unistd.h> - -#include <webkit2/webkit-web-extension.h> - -#include <JavaScriptCore/JavaScript.h> -#include <JavaScriptCore/JSContextRef.h> -#include <JavaScriptCore/JSObjectRef.h> -#include <JavaScriptCore/JSStringRef.h> - -#define WEBKITGTK_EXTENSION_DBUS_NAME "org.eclipse.swt.webkitgtk_extension" -#define WEBKITGTK_EXTENSION_OBJECT_PATH "/org/eclipse/swt/webkitgtk_extension/gdbus" -#define WEBKITGTK_EXTENSION_INTERFACE_NAME "org.eclipse.swt.webkitgtk_extension.gdbusInterface" - -#define WEBKIT_MAIN_PROCESS_DBUS_NAME "org.eclipse.swt" -#define WEBKIT_MAIN_PROCESS_OBJECT_PATH "/org/eclipse/swt/gdbus" -#define WEBKIT_MAIN_PROCESS_INTERFACE_NAME "org.eclipse.swt.gdbusInterface" - -static WebKitWebExtension *this_extension; - -static GDBusNodeInfo *dbus_node; -static GDBusInterfaceInfo *dbus_interface; -static gchar* dbus_introspection_xml; -static gchar* dbus_introspection_xml_template = -"<node>" - "<interface name='%s'>" - - "<method name='webkitgtk_extension_register_function'>" - "<arg type='t' name='page_id' direction='in'/>" - "<arg type='s' name='script' direction='in'/>" - "<arg type='s' name='url' direction='in'/>" - "<arg type='b' name='result' direction='out'/>" - "</method>" - - "<method name='webkitgtk_extension_deregister_function'>" - "<arg type='t' name='page_id' direction='in'/>" - "<arg type='s' name='script' direction='in'/>" - "<arg type='s' name='url' direction='in'/>" - "<arg type='b' name='result' direction='out'/>" - "</method>" - - "</interface>" -"</node>"; - -#endif /*INC_webkit_extension_H*/ diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c index 9a18355034..cc0c92c301 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2021 IBM Corporation and others. All rights reserved. + * Copyright (c) 2009, 2022 IBM Corporation and others. All rights reserved. * The contents of this file are made available under the terms * of the GNU Lesser General Public License (LGPL) Version 2.1 that * accompanies this distribution (lgpl-v21.txt). The LGPL is also @@ -25,16 +25,11 @@ char * WebKitGTK_nativeFunctionNames[] = { "GdkRectangle_1sizeof", "JSObjectGetProperty", "JSObjectGetPropertyAtIndex", - "JSObjectMakeArray", "JSStringCreateWithUTF8CString", "JSStringGetMaximumUTF8CStringSize", "JSStringGetUTF8CString", "JSStringRelease", "JSValueGetType", - "JSValueMakeBoolean", - "JSValueMakeNumber", - "JSValueMakeString", - "JSValueMakeUndefined", "JSValueToNumber", "JSValueToStringCopy", "soup_1cookie_1get_1name", @@ -85,19 +80,27 @@ char * WebKitGTK_nativeFunctionNames[] = { "webkit_1policy_1decision_1ignore", "webkit_1response_1policy_1decision_1get_1request", "webkit_1response_1policy_1decision_1get_1response", + "webkit_1security_1manager_1register_1uri_1scheme_1as_1secure", "webkit_1uri_1request_1get_1http_1headers", "webkit_1uri_1request_1get_1uri", "webkit_1uri_1request_1new", "webkit_1uri_1response_1get_1content_1length", "webkit_1uri_1response_1get_1mime_1type", + "webkit_1uri_1scheme_1request_1finish", + "webkit_1uri_1scheme_1request_1get_1uri", + "webkit_1uri_1scheme_1request_1get_1web_1view", + "webkit_1user_1content_1manager_1add_1script", + "webkit_1user_1content_1manager_1remove_1all_1scripts", + "webkit_1user_1script_1new", + "webkit_1user_1script_1unref", "webkit_1web_1context_1allow_1tls_1certificate_1for_1host", "webkit_1web_1context_1get_1cookie_1manager", "webkit_1web_1context_1get_1default", + "webkit_1web_1context_1get_1security_1manager", "webkit_1web_1context_1get_1type", "webkit_1web_1context_1get_1website_1data_1manager", + "webkit_1web_1context_1register_1uri_1scheme", "webkit_1web_1context_1set_1tls_1errors_1policy", - "webkit_1web_1context_1set_1web_1extensions_1directory", - "webkit_1web_1context_1set_1web_1extensions_1initialization_1user_1data", "webkit_1web_1resource_1get_1data", "webkit_1web_1resource_1get_1data_1finish", "webkit_1web_1view_1can_1go_1back", @@ -110,6 +113,7 @@ char * WebKitGTK_nativeFunctionNames[] = { "webkit_1web_1view_1get_1settings", "webkit_1web_1view_1get_1title", "webkit_1web_1view_1get_1uri", + "webkit_1web_1view_1get_1user_1content_1manager", "webkit_1web_1view_1get_1window_1properties", "webkit_1web_1view_1go_1back", "webkit_1web_1view_1go_1forward", diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h index a94d3e7565..c189b555b1 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2021 IBM Corporation and others. All rights reserved. + * Copyright (c) 2009, 2022 IBM Corporation and others. All rights reserved. * The contents of this file are made available under the terms * of the GNU Lesser General Public License (LGPL) Version 2.1 that * accompanies this distribution (lgpl-v21.txt). The LGPL is also @@ -35,16 +35,11 @@ typedef enum { GdkRectangle_1sizeof_FUNC, JSObjectGetProperty_FUNC, JSObjectGetPropertyAtIndex_FUNC, - JSObjectMakeArray_FUNC, JSStringCreateWithUTF8CString_FUNC, JSStringGetMaximumUTF8CStringSize_FUNC, JSStringGetUTF8CString_FUNC, JSStringRelease_FUNC, JSValueGetType_FUNC, - JSValueMakeBoolean_FUNC, - JSValueMakeNumber_FUNC, - JSValueMakeString_FUNC, - JSValueMakeUndefined_FUNC, JSValueToNumber_FUNC, JSValueToStringCopy_FUNC, soup_1cookie_1get_1name_FUNC, @@ -95,19 +90,27 @@ typedef enum { webkit_1policy_1decision_1ignore_FUNC, webkit_1response_1policy_1decision_1get_1request_FUNC, webkit_1response_1policy_1decision_1get_1response_FUNC, + webkit_1security_1manager_1register_1uri_1scheme_1as_1secure_FUNC, webkit_1uri_1request_1get_1http_1headers_FUNC, webkit_1uri_1request_1get_1uri_FUNC, webkit_1uri_1request_1new_FUNC, webkit_1uri_1response_1get_1content_1length_FUNC, webkit_1uri_1response_1get_1mime_1type_FUNC, + webkit_1uri_1scheme_1request_1finish_FUNC, + webkit_1uri_1scheme_1request_1get_1uri_FUNC, + webkit_1uri_1scheme_1request_1get_1web_1view_FUNC, + webkit_1user_1content_1manager_1add_1script_FUNC, + webkit_1user_1content_1manager_1remove_1all_1scripts_FUNC, + webkit_1user_1script_1new_FUNC, + webkit_1user_1script_1unref_FUNC, webkit_1web_1context_1allow_1tls_1certificate_1for_1host_FUNC, webkit_1web_1context_1get_1cookie_1manager_FUNC, webkit_1web_1context_1get_1default_FUNC, + webkit_1web_1context_1get_1security_1manager_FUNC, webkit_1web_1context_1get_1type_FUNC, webkit_1web_1context_1get_1website_1data_1manager_FUNC, + webkit_1web_1context_1register_1uri_1scheme_FUNC, webkit_1web_1context_1set_1tls_1errors_1policy_FUNC, - webkit_1web_1context_1set_1web_1extensions_1directory_FUNC, - webkit_1web_1context_1set_1web_1extensions_1initialization_1user_1data_FUNC, webkit_1web_1resource_1get_1data_FUNC, webkit_1web_1resource_1get_1data_1finish_FUNC, webkit_1web_1view_1can_1go_1back_FUNC, @@ -120,6 +123,7 @@ typedef enum { webkit_1web_1view_1get_1settings_FUNC, webkit_1web_1view_1get_1title_FUNC, webkit_1web_1view_1get_1uri_FUNC, + webkit_1web_1view_1get_1user_1content_1manager_FUNC, webkit_1web_1view_1get_1window_1properties_FUNC, webkit_1web_1view_1go_1back_FUNC, webkit_1web_1view_1go_1forward_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java index e249737812..e797734421 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java @@ -52,20 +52,7 @@ import org.eclipse.swt.widgets.*; * (the exception is the webextension, because it runs as a separate process and is only loaded dynamically). * - Try to keep all of your logic in Java and avoid writing custom C-code. (I went down this pit). Because if you * use native code, then you have to write dynamic native code (get function pointers, cast types etc.. big pain in the ass). - * (Webextension is again an exception). * - Don't try to add webkit2 include flags to pkg-config, as this will tie the swt-glue code to specific webkit versions. Thou shall not do this. - * (webextension is an exception). - * - * Webextension: - * - On Webkit2, a webextension is used to provide browserfunction/javascript callback functionality. (See the whole WebkitGDBus.java business). - * - I've initially implemented javascript execution by running javascript and then waiting in a display-loop until webkit makes a return call. - * I then added a whole bunch of logic to avoid deadlocks. - * In retrospec, the better approach would be to send things off via GDBus and let the webextension run the javascript synchronously. - * But this would take another 1-2 months of implementation time and wouldn't guarantee dead-lock free behaviour as callbacks could potentailly still - * cause deadlocks. It's an interesting thought however.. - * - Note, most GDBus tutorials talk about compiling GDBus bindings. But using them dynamically I found is much easier. See this guide: - * http://www.cs.grinnell.edu/~rebelsky/Courses/CSC195/2013S/Outlines/ - * * * EVENT_HANDLING_DOC: * - On webkit2, signals are implemented via regular gtk mechanism, hook events and pass them along as we receive them. @@ -109,6 +96,16 @@ class WebKit extends WebBrowser { String tlsErrorType; boolean firstLoad = true; + static boolean FirstCreate = true; + + /** + * Stores the browser which is opening a new browser window, + * during a WebKit {@code create} signal. This browser + * must be passed to a newly created browser as "related". + * + * See bug 579257. + */ + private static Browser parentBrowser; /** * Timeout used for javascript execution / deadlock detection. @@ -172,6 +169,9 @@ class WebKit extends WebBrowser { static final String DOMEVENT_MOUSEOVER = "mouseover"; //$NON-NLS-1$ static final String DOMEVENT_MOUSEWHEEL = "mousewheel"; //$NON-NLS-1$ + static final byte[] SWT_PROTOCOL = Converter.wcsToMbcs("swt", true); // $NON-NLS-1$ + static final byte[] JSON_MIME_TYPE = Converter.wcsToMbcs("application/json", true); // $NON-NLS-1$ + /* WebKit signal data */ static final int NOTIFY_PROGRESS = 1; static final int NOTIFY_TITLE = 2; @@ -195,10 +195,7 @@ class WebKit extends WebBrowser { static final String SWT_WEBKITGTK_VERSION = "org.eclipse.swt.internal.webkitgtk.version"; //$NON-NLS-1$ /* the following Callbacks are never freed */ - static Callback Proc2, Proc3, Proc4, Proc5; - - /** Process key/mouse events from javascript. */ - static Callback JSDOMEventProc; + static Callback Proc2, Proc3, Proc4, Proc5, JSDOMEventProc, RequestProc; /** Flag indicating whether TLS errors (like self-signed certificates) are to be ignored. */ static final boolean ignoreTls; @@ -210,9 +207,8 @@ class WebKit extends WebBrowser { Proc5 = new Callback (WebKit.class, "Proc", 5); //$NON-NLS-1$ new Webkit2AsyncToSync(); - WebKitExtension.init(); - JSDOMEventProc = new Callback (WebKit.class, "JSDOMEventProc", 3); //$NON-NLS-1$ + RequestProc = new Callback (WebKit.class, "RequestProc", 2); //$NON-NLS-1$ NativeClearSessions = () -> { if (!WebKitGTK.LibraryLoaded) return; @@ -255,49 +251,32 @@ class WebKit extends WebBrowser { @Override public void createFunction(BrowserFunction function) { - if (!WebkitGDBus.initialized) { - System.err.println("SWT webkit: WebkitGDBus and/or Webkit2Extension not loaded, BrowserFunction will not work." + - "Tried to create "+ function.name); - return; - } super.createFunction(function); - String url = this.getUrl().isEmpty() ? "nullURL" : this.getUrl(); - /* - * If the proxy to the extension has not yet been loaded, store the BrowserFunction page ID, - * function string, and URL in a HashMap. Once the proxy to the extension is loaded, these - * functions will be sent to and registered in the extension. - */ - if (!WebkitGDBus.connectionToExtensionCreated) { - WebkitGDBus.functionsPending = true; - ArrayList<ArrayList<String>> list = new ArrayList<>(); - ArrayList<String> functionAndUrl = new ArrayList<>(); - functionAndUrl.add(0, function.functionString); - functionAndUrl.add(1, url); - list.add(functionAndUrl); - ArrayList<ArrayList<String>> existing = WebkitGDBus.pendingBrowserFunctions.putIfAbsent(this.pageId, list); - if (existing != null) { - existing.add(functionAndUrl); - } - } else { - // If the proxy to the extension is already loaded, register the function in the extension via DBus - boolean successful = webkit_extension_modify_function(this.pageId, function.functionString, url, "register"); - if (!successful) { - System.err.println("SWT webkit: failure registering BrowserFunction " + function.name); - } - } + updateUserScript(); } @Override public void destroyFunction (BrowserFunction function) { - // Only deregister functions if the proxy to the extension has been loaded - if (WebkitGDBus.connectionToExtensionCreated) { - String url = this.getUrl().isEmpty() ? "nullURL" : this.getUrl(); - boolean successful = webkit_extension_modify_function(this.pageId, function.functionString, url, "deregister"); - if (!successful) { - System.err.println("SWT webkit: failure deregistering BrowserFunction from extension " + function.name); + super.destroyFunction(function); + updateUserScript(); + } + + void updateUserScript() { + // Maintain a script bundle of BrowserFunctions to be injected on page navigation or reload. + long manager = WebKitGTK.webkit_web_view_get_user_content_manager(webView); + WebKitGTK.webkit_user_content_manager_remove_all_scripts(manager); + if (!functions.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (BrowserFunction function : functions.values()) { + sb.append(function.functionString); } + sb.append('\0'); + byte[] scriptData = sb.toString().getBytes(StandardCharsets.UTF_8); + long script = WebKitGTK.webkit_user_script_new( + scriptData, WebKitGTK.WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START, WebKitGTK.WEBKIT_USER_CONTENT_INJECT_TOP_FRAME, 0, 0); + WebKitGTK.webkit_user_content_manager_add_script(manager, script); + WebKitGTK.webkit_user_script_unref(script); } - super.destroyFunction(function); } private static String getInternalErrorMsg () { @@ -321,170 +300,16 @@ class WebKit extends WebBrowser { return sw.toString(); } - /** - * This class deals with the WebKit extension. - * - * Extension is separately loaded and deals Javascript callbacks to Java. - * Extension is needed so that Javascript can receive a return value from Java - * (for which currently there is no api in WebkitGtk 2.18) - */ - static class WebKitExtension { - /** Note, if updating this, you need to change it also in webkitgtk_extension.c */ - private static final String javaScriptFunctionName = "webkit2callJava"; // $NON-NLS-1$ - private static final String webkitWebExtensionIdentifier = "webkitWebExtensionIdentifier"; // $NON-NLS-1$ - private static Callback initializeWebExtensions_callback; - - /** GDBusServer returned by WebkitGDBus */ - private static long dBusServer = 0; - - /** - * Don't continue initialization if something failed. This allows Browser to carryout some functionality - * even if the webextension failed to load. - */ - private static boolean loadFailed; - - static String getJavaScriptFunctionName() { - return javaScriptFunctionName; - } - static String getWebExtensionIdentifier() { - return webkitWebExtensionIdentifier; - } - static String getJavaScriptFunctionDeclaration(long webView) { - return "if (!window.callJava) {\n" - + " window.callJava = function callJava(index, token, args) {\n" - + " return " + javaScriptFunctionName + "('" + String.valueOf(webView) + "', index, token, args);\n" - + " }\n" - + "};\n"; - } - - static void init() { - /* - * Initialize GDBus before the extension, as the extension initialization callback at the C level - * sends data back to SWT via GDBus. Failure to load GDBus here will result in crashes. - * See bug 536141. - */ - dBusServer = gdbus_init(); - if (dBusServer == 0) { - System.err.println("SWT WebKit: error initializing DBus server, dBusServer == 0"); - } - initializeWebExtensions_callback = new Callback(WebKitExtension.class, "initializeWebExtensions_callback", void.class, new Type [] {long.class, long.class}); - if (WebKitGTK.webkit_get_minor_version() >= 4) { // Callback exists only since 2.04 - OS.g_signal_connect (WebKitGTK.webkit_web_context_get_default(), WebKitGTK.initialize_web_extensions, initializeWebExtensions_callback.getAddress(), 0); - } - } - - /** - * GDbus initialization can cause performance slow downs. So we int GDBus in lazy way. - * It can be initialized upon first use of BrowserFunction. - */ - static long gdbus_init() { - if (WebKitGTK.webkit_get_minor_version() < 4) { - System.err.println("SWT Webkit: Warning, You are using an old version of webkitgtk. (pre 2.4)" - + " BrowserFunction functionality will not be available"); - return 0; - } - - - if (!loadFailed) { - return WebkitGDBus.init(); - } else { - return 0; - } - } - - /** - * This callback is called to initialize webextension. - * It is the optimum place to set extension directory and set initialization user data. - * - * I've experimented with loading webextension later (to see if we can get performance gains), - * but found breakage. Webkitgtk doc says it should be loaded as early as possible and specifically best - * to do it in this calllback. - * - * See documenation: WebKitWebExtension (Description) - */ - @SuppressWarnings("unused") // Only called directly from C - private static void initializeWebExtensions_callback (long WebKitWebContext, long user_data) { - // 1) GDBus: - // Normally we'd first initialize gdbus channel. But gdbus makes Browser slower and isn't always needed. - // So WebkitGDBus is lazy-initialized, although it can be initialized here if gdbus is ever needed - // for more than BrowserFunction, like: - // WebkitGDBus.init(String.valueOf(uniqueID)); - // Also consider only loading gdbus if the extension initialized properly. - - // 2) Load Webkit Extension: - // Webkit extensions should be in their own directory. - String swtVersion = Library.getVersionString(); - File extension; - try { - extension = Library.findResource("webkitextensions" + swtVersion ,"swt-webkit2extension", true); - if (extension == null){ - throw new UnsatisfiedLinkError("SWT Webkit could not find it's webextension"); - } - } catch (UnsatisfiedLinkError e) { - System.err.println("SWT Webkit.java Error: Could not find webkit extension. BrowserFunction functionality will not be available. \n" - + "(swt version: " + swtVersion + ")" + WebKitGTK.swtWebkitGlueCodeVersion + WebKitGTK.swtWebkitGlueCodeVersionInfo); - int [] vers = internalGetWebkitVersion(); - System.err.println(String.format("WebKit2Gtk version %s.%s.%s", vers[0], vers[1], vers[2])); - System.err.println(getInternalErrorMsg()); - loadFailed = true; - return; - } - - String extensionsFolder = extension.getParent(); - /* Dev note: - * As per - * - WebkitSrc: WebKitExtensionManager.cpp, - * - IRC discussion with annulen - * you cannot load the webextension GModule directly, (webkitgtk 2.18). You can only specify directory and user data. - * So we need to treat this '.so' in a special way. - * (as a note, the webprocess would have to load the gmodule). - */ - WebKitGTK.webkit_web_context_set_web_extensions_directory(WebKitGTK.webkit_web_context_get_default(), Converter.wcsToMbcs (extensionsFolder, true)); - long clientAddress = OS.g_dbus_server_get_client_address(dBusServer); - String clientAddressJava = Converter.cCharPtrToJavaString(clientAddress, false); - long gvariantUserData = OS.g_variant_new_string(clientAddress); - WebKitGTK.webkit_web_context_set_web_extensions_initialization_user_data(WebKitGTK.webkit_web_context_get_default(), gvariantUserData); - } - - /** - * @param cb_args Raw callback arguments by function. - */ - static Object webkit2callJavaCallback(Object [] cb_args) { - assert cb_args.length == 4; - Object returnValue = null; - Long webViewLocal = (Double.valueOf((String) cb_args[0])).longValue(); - Browser browser = FindBrowser((long ) webViewLocal.longValue()); - Integer functionIndex = ((Double) cb_args[1]).intValue(); - String token = (String) cb_args[2]; - - BrowserFunction function = browser.webBrowser.functions.get(functionIndex); - if (function == null) { - System.err.println("SWT Webkit Error: Failed to find function with index: " + functionIndex); - return null; - } - if (!function.token.equals(token)) { - System.err.println("SWT Webkit Error: token mismatch for function with index: " + functionIndex); - return null; - } - try { - // Call user code. Exceptions can occur. - nonBlockingEvaluate++; - Object [] user_args = (Object []) cb_args[3]; - returnValue = function.function(user_args); - } catch (Exception e ) { - // - Something went wrong in user code. - System.err.println("SWT Webkit: Exception occured in user code of function: " + function.name); - returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ()); - } finally { - nonBlockingEvaluate--; - } - return returnValue; - } - } - @Override String getJavaCallDeclaration() { - return WebKitExtension.getJavaScriptFunctionDeclaration(webView); + // callJava does a synchronous XMLHttpRequest, which is handled by RequestProc. + return "if (!window.callJava) { window.callJava = function(index, token, args) {\n" + + "var xhr = new XMLHttpRequest();\n" + + "var uri = 'swt://browserfunction/' + index + '/' + token + '?' + encodeURIComponent(JSON.stringify(args));\n" + + "xhr.open('POST', uri, false);\n" + + "xhr.send(null);\n" + + "return JSON.parse(xhr.responseText);\n" + + "}}\n"; } /** @@ -601,6 +426,54 @@ static long JSDOMEventProc (long arg0, long event, long user_data) { return 0; } +static long RequestProc (long request, long user_data) { + // Custom protocol handler (swt://) for BrowserFunction callbacks. + // Note that a response must be sent regardless of any errors, otherwise the caller will hang. + String response = "null"; + + long webView = WebKitGTK.webkit_uri_scheme_request_get_web_view(request); + Browser browser = FindBrowser(webView); + if (browser != null) { + BrowserFunction function = null; + Object[] args = null; + + long uriPtr = WebKitGTK.webkit_uri_scheme_request_get_uri(request); + String uriStr = Converter.cCharPtrToJavaString(uriPtr, false); + try { + URI uri = new URI(uriStr); + String[] parts = uri.getPath().split("/"); + int index = Integer.parseInt(parts[1]); + String token = parts[2]; + + WebKit webkit = (WebKit)browser.webBrowser; + function = webkit.functions.get(index); + if (function != null && !function.token.equals(token)) { + function = null; + } + + args = (Object[]) JSON.parse(uri.getQuery()); + } catch (URISyntaxException | IllegalArgumentException | IndexOutOfBoundsException | ClassCastException e) { + } + + if (function != null) { + Object result; + try { + result = function.function(args); + } catch (Exception e) { + result = WebBrowser.CreateErrorString(e.getLocalizedMessage()); + } + response = JSON.stringify(result); + } + } + + long[] outBytes = new long[1]; + long dataPtr = OS.g_utf16_to_utf8(response.toCharArray(), response.length(), null, outBytes, null); + long stream = OS.g_memory_input_stream_new_from_data(dataPtr, outBytes[0], OS.addressof_g_free()); + WebKitGTK.webkit_uri_scheme_request_finish(request, stream, outBytes[0], JSON_MIME_TYPE); + OS.g_object_unref(stream); + return 0; +} + static long Proc (long handle, long user_data) { long webView = handle; @@ -767,10 +640,18 @@ public void create (Composite parent, int style) { */ Webkit2AsyncToSync.setCookieBrowser(browser); + if (FirstCreate) { + FirstCreate = false; + // Register the swt:// custom protocol for BrowserFunction calls via XMLHttpRequest + long context = WebKitGTK.webkit_web_context_get_default(); + WebKitGTK.webkit_web_context_register_uri_scheme(context, SWT_PROTOCOL, RequestProc.getAddress(), 0, 0); + long security = WebKitGTK.webkit_web_context_get_security_manager(context); + WebKitGTK.webkit_security_manager_register_uri_scheme_as_secure(security, SWT_PROTOCOL); + } Composite parentShell = parent.getParent(); - Browser parentBrowser = null; - if (parentShell != null) { + Browser parentBrowser = WebKit.parentBrowser; + if (parentBrowser == null && parentShell != null) { Control[] children = parentShell.getChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Browser) { @@ -996,46 +877,6 @@ void nonBlockingExecute(String script) { } } -/** - * Modifies a BrowserFunction in the web extension. This method can be used to register/deregister BrowserFunctions - * in the web extension, so that those BrowserFunctions are executed upon triggering of the object_cleared callback (in - * the extension, not in Java). - * - * This function will return true if: the operation succeeds synchronously, or if the synchronous call timed out and an - * asynchronous call was performed instead. All other cases will return false. - * - * Supported actions: "register" and "deregister" - * - * @param pageId the page ID of the WebKit instance/web page - * @param function the function string - * @param url the URL - * @param action the action being performed on the function, which will be used to form the DBus method name. - * @return true if the action succeeded (or was performed asynchronously), false if it failed - */ -private boolean webkit_extension_modify_function (long pageId, String function, String url, String action){ - long[] args = { OS.g_variant_new_uint64(pageId), - OS.g_variant_new_string (Converter.javaStringToCString(function)), - OS.g_variant_new_string (Converter.javaStringToCString(url))}; - final long argsTuple = OS.g_variant_new_tuple(args, args.length); - if (argsTuple == 0) return false; - String dbusMethodName = "webkitgtk_extension_" + action + "_function"; - Object returnVal = WebkitGDBus.callExtensionSync(argsTuple, dbusMethodName); - if (returnVal instanceof Boolean) { - return (Boolean) returnVal; - } else if (returnVal instanceof String) { - String returnString = (String) returnVal; - /* - * Call the extension asynchronously if a synchronous call times out. - * Note: this is a pretty rare case, and usually only happens when running test cases. - * See bug 536141. - */ - if ("timeout".equals(returnString)) { - return WebkitGDBus.callExtensionAsync(argsTuple, dbusMethodName); - } - } - return false; -} - @Override public boolean execute (String script) { if (!isJavascriptEnabled()) { @@ -1165,27 +1006,6 @@ private static class Webkit2AsyncToSync { * SWT implementation. * * If in doubt, you should use nonBlockingExecute() where possible :-). - * - * TODO_SOMEDAY: - * - Instead of async js execution and waiting for return value, it might be - * better to use gdbus, connect to webextension and execute JS synchronously. - * See: https://blogs.igalia.com/carlosgc/2013/09/10/webkit2gtk-web-process-extensions/ - * 'Extending JavaScript' - * Pros: - * - less likely deadlocks would occur due to developer error/not being careful. - * - js execution can work in synchronous callbacks from webkit. - * Cons: - * - High implementation cost/complexity. - * - Unexpected errors/behaviour due to GDBus timeouts. - * Proof of concept: - * https://git.eclipse.org/r/#/c/23416/16/bundles/org.eclipse.swt/Eclipse+SWT+WebKit/gtk/library/webkit_extension.c - * > 'webkit_extension_execute_script' - * Tennative structure: - * - Webextension should create gdbus server, make & communicate UniqueID (pid) to main proc - * - main proc should make a note of webextension's name+uniqueID - * - implement mechanism for packaging Java objects into gvariants, (see WebkitGDBus.java), - * - call webextension over gdbus, parse return value. - * */ static Object runjavascript(String script, Browser browser, long webView) { if (nonBlockingEvaluate > 0) { @@ -1364,7 +1184,7 @@ private static class Webkit2AsyncToSync { * triggers. */ Consumer<Integer> asyncFunc = (callbackID) -> WebKitGTK.webkit_cookie_manager_get_cookies(cookieManager, uri, 0, - getCookie_callback.getAddress(), WebkitGDBus.convertJavaToGVariant(new Object [] {cookieName, callbackID})); + getCookie_callback.getAddress(), GDBus.convertJavaToGVariant(new Object [] {cookieName, callbackID})); Webkit2AsyncReturnObj retObj = execAsyncAndWaitForReturn(cookieBrowser, asyncFunc, " getCookie() was called"); if (retObj.swtAsyncTimeout) { @@ -1376,7 +1196,7 @@ private static class Webkit2AsyncToSync { @SuppressWarnings("unused") // Callback only called only by C directly private static void getCookie_callback(long cookieManager, long result, long user_data) { - Object resultObject = WebkitGDBus.convertGVariantToJava(user_data); + Object resultObject = GDBus.convertGVariantToJava(user_data); // We are expecting a GVariant tuple, anything else means something went wrong if (resultObject instanceof Object []) { @@ -2325,10 +2145,12 @@ long webkit_create_web_view (long web_view, long frame) { }; try { nonBlockingEvaluate++; // running evaluate() inside openWindowListener and waiting for return leads to deadlock. Bug 512001 + parentBrowser = browser; fireOpenWindowListeners.run();// Permit evaluate()/execute() to execute scripts in listener, but do not provide return value. } catch (Exception e) { throw e; // rethrow execption if thrown, but decrement counter first. } finally { + parentBrowser = null; nonBlockingEvaluate--; } Browser browser = null; @@ -2803,38 +2625,6 @@ private void webkit_settings_set(byte [] property, int value) { OS.g_object_set(settings, property, value, 0); } -long convertToJS (long ctx, Object value) { - if (value == null) { - return WebKitGTK.JSValueMakeUndefined (ctx); - } - if (value instanceof String) { - byte[] bytes = ((String)value + '\0').getBytes (StandardCharsets.UTF_8); //$NON-NLS-1$ - long stringRef = WebKitGTK.JSStringCreateWithUTF8CString (bytes); - long result = WebKitGTK.JSValueMakeString (ctx, stringRef); - WebKitGTK.JSStringRelease (stringRef); - return result; - } - if (value instanceof Boolean) { - return WebKitGTK.JSValueMakeBoolean (ctx, ((Boolean)value).booleanValue () ? 1 : 0); - } - if (value instanceof Number) { - return WebKitGTK.JSValueMakeNumber (ctx, ((Number)value).doubleValue ()); - } - if (value instanceof Object[]) { - Object[] arrayValue = (Object[]) value; - int length = arrayValue.length; - long [] arguments = new long [length]; - for (int i = 0; i < length; i++) { - Object javaObject = arrayValue[i]; - long jsObject = convertToJS (ctx, javaObject); - arguments[i] = jsObject; - } - return WebKitGTK.JSObjectMakeArray (ctx, length, arguments, null); - } - SWT.error (SWT.ERROR_INVALID_RETURN_VALUE); - return 0; -} - static Object convertToJava (long ctx, long value) { int type = WebKitGTK.JSValueGetType (ctx, value); switch (type) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java deleted file mode 100644 index ef293be750..0000000000 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java +++ /dev/null @@ -1,666 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2017, 2022 Red Hat and others. All rights reserved. - * The contents of this file are made available under the terms - * of the GNU Lesser General Public License (LGPL) Version 2.1 that - * accompanies this distribution (lgpl-v21.txt). The LGPL is also - * available at http://www.gnu.org/licenses/lgpl.html. If the version - * of the LGPL at http://www.gnu.org is different to the version of - * the LGPL accompanying this distribution and there is any conflict - * between the two license versions, the terms of the LGPL accompanying - * this distribution shall govern. - * - * Contributors: - * Red Hat - initial API and implementation - *******************************************************************************/ - -package org.eclipse.swt.browser; - -import java.util.*; -import java.util.Map.*; - -import org.eclipse.swt.*; -import org.eclipse.swt.internal.*; -import org.eclipse.swt.internal.gtk.*; -import org.eclipse.swt.widgets.*; - -/** - * Logic for Webkit to interact with it's Webkit extension via GDBus. - * - * While this class supports quite a bit of GDBus and gvariant support, it is by no means a complete - * implementation and it's tailored to support Java to Javascript conversion. (E.g all Numbers are converted to Double). - * If this is ever to be used outside of Webkit, then care must be taken to deal with - * cases that are not currently implemented/used. See: WebKitGTK.java 'TYPE NOTES' - * - * For hygiene purposes, GVariant types should not be leaving this class. Convert on the way in/out. - * - * @category gdbus - */ -class WebkitGDBus { - /* - * If any of the GDBus names/paths/interfaces need to be changed, then they also need to be changed - * in the extension (webkitgtk_extension.c). - */ - - /* WEBKITGDBUS_DBUS_NAME isn't actually used but is here for informative purposes */ - @SuppressWarnings("unused") - private static final String WEBKITGDBUS_DBUS_NAME = "org.eclipse.swt"; - private static final byte [] WEBKITGDBUS_OBJECT_PATH = Converter.javaStringToCString("/org/eclipse/swt/gdbus"); - private static final String WEBKITGDBUS_INTERFACE_NAME_JAVA = "org.eclipse.swt.gdbusInterface"; - private static final byte [] WEBKITGDBUS_INTERFACE_NAME = Converter.javaStringToCString("org.eclipse.swt.gdbusInterface"); - - /* Extension connection details, in byte [] form */ - private static final byte [] EXTENSION_DBUS_NAME = Converter.javaStringToCString("org.eclipse.swt.webkitgtk_extension"); - private static final byte [] EXTENSION_OBJECT_PATH = Converter.javaStringToCString("/org/eclipse/swt/webkitgtk_extension/gdbus"); - private static final byte [] EXTENSION_INTERFACE_NAME = Converter.javaStringToCString("org.eclipse.swt.webkitgtk_extension.gdbusInterface"); - - /** Extension GDBusServer client address */ - private static String EXTENSION_DBUS_SERVER_CLIENT_ADDRESS; - - /* Accepted GDBus methods */ - private static final String webkit2callJava = WebKit.WebKitExtension.getJavaScriptFunctionName(); - private static final String webkitWebExtensionIdentifier = WebKit.WebKitExtension.getWebExtensionIdentifier(); - - /* Connections */ - /** GDBusConnection from the web extension */ - static long connectionFromExtension; - /** GDBusConnection to the web extension */ - static long connectionToExtension; - /** A field that is set to true if the proxy connection has been established, false otherwise. */ - static boolean connectionToExtensionCreated; - - /* Server related objects */ - /** GDBusServer for the main SWT process */ - private static long gDBusServer = 0; - /** GDBusAuthObserver for the server */ - private static long authObserver = 0; - /** GUID of the GDBusServer */ - private static long guid = 0; - - /** Display this GDBus class is "attached" to */ - static Display display; - - - // BrowserFunction logic - /** Set to true if there are <code>BrowserFunction</code> objects waiting to be registered with the web extension.*/ - static boolean functionsPending; - /** - * HashMap that stores any BrowserFunctions which have been created but not yet registered with the web extension. - * These functions will be registered with the web extension as soon as the proxy to the extension is set up. - * - * The format of the HashMap is (page ID, list of function string and URL). - */ - static HashMap<Long, ArrayList<ArrayList<String>>> pendingBrowserFunctions = new HashMap<>(); - - - /** - * Interface is read/parsed at run time. No compilation with gdbus-code-gen necessary. - * - * Note, - * - When calling a method via g_dbus_proxy_call_sync(..g_variant params..), - * the g_variant that describes parameters should only mirror incoming parameters. - * Each type is a separate argument. - * e.g: - * g_variant xml: - * "(si)", "string", 42 .. arg type='s' - * .. arg type='i' - * - * - Nested parameters need to have a 2nd bracket around them. - * e.g: - * g_variant xml: - * "((r)i)", *gvariant, 42 .. arg type='r' - * .. arg type='i' - * - * - '@' is a pointer to a gvariant. so '@r' is a pointer to nested type, i.e *gvariant - * - * To understand the mappings, it's good to understand DBus and GVariant's syntax: - * https://dbus.freedesktop.org/doc/dbus-specification.html#idm423 - * https://developer.gnome.org/glib/stable/glib-GVariantType.html - * - * Be mindful about only using supported DBUS_TYPE_* , as convert* methods might fail otherwise. - * Alternatively, modify convert* methods. - */ - private static final byte [] WEBKITGDBUS_INTROSPECTION_XML = Converter.javaStringToCString( - "<node>" - + " <interface name='" + WEBKITGDBUS_INTERFACE_NAME_JAVA + "'>" - + " <method name='" + webkit2callJava + "'>" - + " <arg type='"+ OS.DBUS_TYPE_STRING + "' name='webViewPtr' direction='in'/>" - + " <arg type='"+ OS.DBUS_TYPE_DOUBLE + "' name='index' direction='in'/>" - + " <arg type='"+ OS.DBUS_TYPE_STRING + "' name='token' direction='in'/>" - + " <arg type='" + OS.DBUS_TYPE_SINGLE_COMPLETE + "' name='arguments' direction='in'/>" - + " <arg type='" + OS.DBUS_TYPE_SINGLE_COMPLETE + "' name='result' direction='out'/>" - + " </method>" - + " <method name='" + webkitWebExtensionIdentifier + "'>" - + " <arg type='"+ OS.DBUS_TYPE_STRING + "' name='webExtensionServerAddress' direction='in'/>" - + " <arg type='"+ OS.DBUS_TYPE_STRUCT_ARRAY_BROWSER_FUNCS + "' name='result' direction='out'/>" - + " </method>" - + " </interface>" - + "</node>"); - - /** - * GDBus/DBus doesn't have a notion of Null. - * To get around this, we use magic numbers to represent special cases. - * Currently this is specific to Webkit to deal with Javascript data type conversions. - * @category gdbus */ - private static final byte SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY = 101; - /** @category gdbus */ - private static final byte SWT_DBUS_MAGIC_NUMBER_NULL = 48; - - - /** Callback for GDBus method handling */ - private static Callback handleMethodCB; - /** Callback for incoming connections to WebkitGDBus' server */ - private static Callback newConnectionCB; - /** Callback for creating a new connection to the web extension */ - private static Callback newConnectionToExtensionCB; - /** Callback for authenticating connections to WebkitGDBus' server */ - private static Callback authenticatePeerCB; - /** Callback for asynchronous proxy calls to the extension */ - private static Callback callExtensionAsyncCB; - - static { - handleMethodCB = new Callback (WebkitGDBus.class, "handleMethodCB", 8); //$NON-NLS-1$ - callExtensionAsyncCB = new Callback (WebkitGDBus.class, "callExtensionAsyncCB", 3); //$NON-NLS-1$ - newConnectionCB = new Callback (WebkitGDBus.class, "newConnectionCB", 3); //$NON-NLS-1$ - newConnectionToExtensionCB = new Callback (WebkitGDBus.class, "newConnectionToExtensionCB", 3); //$NON-NLS-1$ - authenticatePeerCB = new Callback (WebkitGDBus.class, "authenticatePeerCB", 4); //$NON-NLS-1$ - } - - /** True iff the GDBusServer has been initialized */ - static boolean initialized; - /** True iff this class has been attached to a Display */ - static boolean attachedToDisplay; - - /** This method is in an internal class and is not intended to be referenced by clients. */ - static long init () { - if (initialized) { - return gDBusServer; - } - initialized = true; - - // Generate address and GUID - long address = construct_server_address(); - authObserver = OS.g_dbus_auth_observer_new(); - guid = OS.g_dbus_generate_guid(); - - // Create server - long [] error = new long [1]; - gDBusServer = OS.g_dbus_server_new_sync(address, OS.G_DBUS_SERVER_FLAGS_NONE, guid, authObserver, 0, error); - - // Connect authentication and incoming connections signals to the newly created server, and start it - if (gDBusServer != 0) { - OS.g_signal_connect(gDBusServer, OS.new_connection, newConnectionCB.getAddress(), 0); - OS.g_signal_connect(authObserver, OS.authorize_authenticated_peer, authenticatePeerCB.getAddress(), 0); - OS.g_dbus_server_start(gDBusServer); - } else { - System.err.println("SWT WebKitGDBus: error creating DBus server " + Display.extractFreeGError(error[0])); - } - return gDBusServer; - } - - /** - * Sets the Display for this class. This allows WebkitGDBus to attach its servers and related objects - * to the provided Display. When the Display is disposed, it will will release the GDBus related - * resources. - * - * @param displayToSet the Display to set - */ - static void setDisplay (Display displayToSet) { - if (!attachedToDisplay) { - display = displayToSet; - - /* - * Add the GDBusServer, GDBusAuthObserver, and GUID to the Display. - * Note that we don't add the connections yet, because they likely - * don't exist. Those are added in callbacks as they come in. - */ - if (gDBusServer != 0) display.dBusServers.add(gDBusServer); - if (authObserver != 0) display.dBusAuthObservers.add(authObserver); - if (guid != 0) display.dBusGUIDS.add(guid); - attachedToDisplay = true; - } - } - - /** - * Constructs an address at which the GDBus server for the SWT main process - * can be reached. - * - * @return a pointer to the address - */ - private static long construct_server_address () { - // On Linux, the address required is used for as an abstract path. If abstract path is not supported - // one must create & manage temporary directories. See Bug562443. - byte [] address = Converter.wcsToMbcs("unix:tmpdir=/tmp/SWT-GDBusServer", true); - long addressPtr = OS.g_malloc(address.length); - C.memmove(addressPtr, address, address.length); - - return addressPtr; - } - - /** - * This is called when a client call one of the GDBus methods. - * - * Developer note: - * This method can be reached directly from GDBus cmd utility: - * gdbus call --session --dest org.eclipse.swt<UNIQUE_ID> --object-path /org/eclipse/swt/gdbus --method org.eclipse.swt.gdbusInterface.HelloWorld - * where as you tab complete, you append the UNIQUE_ID. - * - * @param connection GDBusConnection - * @param sender const gchar - * @param object_path const gchar - * @param interface_name const gchar - * @param method_name const gchar - * @param gvar_parameters GVariant - * @param invocation GDBusMethodInvocation - * @param user_data gpointer - * @return - */ - @SuppressWarnings("unused") // callback not directly called by SWT - private static long handleMethodCB ( - long connection, long sender, - long object_path, long interface_name, - long method_name, long gvar_parameters, - long invocation, long user_data) { - - String java_method_name = Converter.cCharPtrToJavaString(method_name, false); - Object result = null; - if (java_method_name != null) { - if (java_method_name.equals(webkit2callJava)) { - try { - Object [] java_parameters = (Object []) convertGVariantToJava(gvar_parameters); - result = WebKit.WebKitExtension.webkit2callJavaCallback(java_parameters); - } catch (Exception e) { - // gdbus should always return to prevent extension from hanging. - result = (String) WebBrowser.CreateErrorString (e.getLocalizedMessage ()); - System.err.println("SWT WebkitGDBus: Exception occured in Webkit2 callback logic."); - } - } else if (java_method_name.equals(webkitWebExtensionIdentifier)) { - Object [] serverAddress = (Object []) convertGVariantToJava(gvar_parameters); - if (serverAddress[0] instanceof String) { - EXTENSION_DBUS_SERVER_CLIENT_ADDRESS = (String) serverAddress[0]; - // Connect to the extension's server by creating a connection asynchronously - createConnectionToExtension(); - /* - * Return any pending BrowserFunctions that were created before WebkitGDBus - * was initialized. - */ - invokeReturnValueExtensionIdentifier(pendingBrowserFunctions, invocation); - } else { - System.err.println("SWT WebkitGDBus: error in web extension identification process." - + " BrowserFunction may not work."); - } - return 0; - } - } else { - result = (String) "SWT WebkitGDBus: GDBus called an unknown method?"; - System.err.println("SWT WebkitGDBus: Received a call from an unknown method: " + java_method_name); - } - invokeReturnValue(result, invocation); - return 0; - } - - @SuppressWarnings("unused") // callback not directly called by SWT - private static long callExtensionAsyncCB (long source_object, long result, long user_data) { - long [] error = new long [1]; - long gVariantResult = OS.g_dbus_connection_call_finish (connectionToExtension, result, error); - if (error[0] != 0) { - String msg = Display.extractFreeGError(error[0]); - System.err.println("SWT WebkitGDBus: there was an error executing something asynchronously with the extension (Java callback)."); - System.err.println("SWT WebkitGDBus: the error message provided is " + msg); - } - OS.g_variant_unref(gVariantResult); - return 0; - } - - @SuppressWarnings("unused") // callback not directly called by SWT - private static long authenticatePeerCB (long observer, long stream, long credentials, long user_data) { - boolean authorized = false; - if (credentials != 0) { - long[] error = new long [1]; - long ownCredentials = OS.g_credentials_new(); - authorized = OS.g_credentials_is_same_user(credentials, ownCredentials, error); - if (error[0] != 0) { - String msg = Display.extractFreeGError(error[0]); - System.err.println("SWT WebkitGDBus: error authenticating client connection to server " + msg); - } - OS.g_object_unref(ownCredentials); - } - return authorized ? 1 : 0; - } - - @SuppressWarnings("unused") // callback not directly called by SWT - private static long newConnectionCB (long server, long connection, long user_data) { - long gdBusNodeInfo; - long [] error = new long [1]; - gdBusNodeInfo = OS.g_dbus_node_info_new_for_xml(WEBKITGDBUS_INTROSPECTION_XML, error); - if (gdBusNodeInfo == 0 || error[0] != 0) { - System.err.println("SWT WebkitGDBus: failed to get introspection data"); - } - assert gdBusNodeInfo != 0 : "SWT WebKitGDBus: introspection data should not be 0"; - - long interface_info = OS.g_dbus_node_info_lookup_interface(gdBusNodeInfo, WEBKITGDBUS_INTERFACE_NAME); - long[] vtable = { handleMethodCB.getAddress(), 0, 0 }; - - OS.g_dbus_connection_register_object( - connection, - WEBKITGDBUS_OBJECT_PATH, - interface_info, - vtable, - 0, // user_data - 0, // user_data_free_func - error); - - if (error[0] != 0) { - System.err.println("SWT WebKitGDBus: failed to register object: " + WEBKITGDBUS_OBJECT_PATH); - return 0; - } - - // Ref the connection and add it to the Display's list of connections - connectionFromExtension = OS.g_object_ref(connection); - if (attachedToDisplay && display != null) { - if (!display.dBusConnections.contains(connection)) display.dBusConnections.add(connectionFromExtension); - } - return 1; - } - - @SuppressWarnings("unused") // callback not directly called by SWT - private static long newConnectionToExtensionCB (long sourceObject, long result, long user_data) { - long [] error = new long [1]; - connectionToExtension = OS.g_dbus_connection_new_for_address_finish(result, error); - if (error[0] != 0) { - System.err.println("SWT WebKitGDBus: error finishing connection: " + Display.extractFreeGError(error[0])); - return 0; - } else { - connectionToExtensionCreated = true; - } - - // Add the connections to the Display's list of connections - if (attachedToDisplay && display != null) { - if (!display.dBusConnections.contains(connectionToExtension)) display.dBusConnections.add(connectionToExtension); - } - return 0; - } - - /** - * Returns a GVariant to the DBus invocation of the extension identifier method. When the extension - * is initialized it sends a DBus message to the SWT webkit instance. As a return value, the SWT webkit - * instance sends any BrowserFunctions that have been registered. If no functions have been registered, - * an "empty" function with a page ID of -1 is sent. - * - * @param map the HashMap of BrowserFunctions waiting to be registered in the extension, or null - * if you'd like to explicitly send an empty function signature - * @param invocation the GDBus invocation to return the value on - */ - private static void invokeReturnValueExtensionIdentifier (HashMap<Long, ArrayList<ArrayList<String>>> map, - long invocation) { - long resultGVariant; - long builder; - long type = OS.g_variant_type_new(OS.G_VARIANT_TYPE_ARRAY_BROWSER_FUNCS); - builder = OS.g_variant_builder_new(type); - if (builder == 0) return; - Object [] tupleArray = new Object[3]; - boolean sendEmptyFunction; - if (map == null) { - sendEmptyFunction = true; - } else { - sendEmptyFunction = map.isEmpty() && !functionsPending; - } - /* - * No functions to register, send a page ID of -1 and empty strings. - */ - if (sendEmptyFunction) { - tupleArray[0] = (long)-1; - tupleArray[1] = ""; - tupleArray[2] = ""; - long tupleGVariant = convertJavaToGVariant(tupleArray); - if (tupleGVariant != 0) { - OS.g_variant_builder_add_value(builder, tupleGVariant); - } else { - System.err.println("SWT WebKitGDBus: error creating empty BrowserFunction GVariant tuple, skipping."); - } - } else { - for (Entry<Long, ArrayList<ArrayList<String>>> entry : map.entrySet()) { - ArrayList<ArrayList<String>> list = entry.getValue(); - if (list != null) { - for (ArrayList<String> stringList : list) { - Object [] stringArray = stringList.toArray(); - if (stringArray.length > 2) { - System.err.println("SWT WebKitGDBus: String array with BrowserFunction and URL should never have" - + "more than 2 Strings"); - } - tupleArray[0] = entry.getKey(); - System.arraycopy(stringArray, 0, tupleArray, 1, 2); - long tupleGVariant = convertJavaToGVariant(tupleArray); - if (tupleGVariant != 0) { - OS.g_variant_builder_add_value(builder, tupleGVariant); - } else { - System.err.println("SWT WebKitGDBus: error creating BrowserFunction GVariant tuple, skipping."); - } - } - } - } - } - resultGVariant = OS.g_variant_builder_end(builder); - String typeString = Converter.cCharPtrToJavaString(OS.g_variant_get_type_string(resultGVariant), false); - if (!OS.DBUS_TYPE_STRUCT_ARRAY_BROWSER_FUNCS.equals(typeString)) { - System.err.println("SWT WebKitGDBus: an error packaging the GVariant occurred: type mismatch."); - } - long [] variants = {resultGVariant}; - long finalGVariant = OS.g_variant_new_tuple(variants, 1); - OS.g_dbus_method_invocation_return_value(invocation, finalGVariant); - OS.g_variant_builder_unref(builder); - OS.g_variant_type_free(type); - } - - private static void invokeReturnValue (Object result, long invocation) { - long resultGVariant = 0; - try { - resultGVariant = convertJavaToGVariant(new Object [] {result}); // Result has to be a tuple. - } catch (SWTException e) { - // gdbus should always return to prevent extension from hanging. - String errMsg = (String) WebBrowser.CreateErrorString (e.getLocalizedMessage ()); - resultGVariant = convertJavaToGVariant(new Object [] {errMsg}); - } - OS.g_dbus_method_invocation_return_value(invocation, resultGVariant); - } - - /** - * Asynchronously initializes a GDBusConnection to the web extension. Connection process - * will be confirmed when the newConnectionToExtension callback is called. - */ - private static void createConnectionToExtension() { - byte [] address = Converter.javaStringToCString(EXTENSION_DBUS_SERVER_CLIENT_ADDRESS); - long [] error = new long [1]; - // Create connection asynchronously to avoid deadlock issues - OS.g_dbus_connection_new_for_address (address, OS.G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, - 0, 0, newConnectionToExtensionCB.getAddress(), 0); - - if (error[0] != 0) { - System.err.println("SWT WebkitGDBus: error creating connection to the extension " - + Display.extractFreeGError(error[0])); - } - } - - /** - * Calls the web extension synchronously. Returns true if the operation succeeded, and false - * otherwise (or if the operation times out). - * - * @param params a pointer to the GVariant containing the parameters - * @param methodName a String representing the DBus method name in the extension - * @return an Object representing the return value from DBus in boolean form - */ - static Object callExtensionSync (long params, String methodName) { - long [] error = new long [1]; // GError ** - long gVariant = OS.g_dbus_connection_call_sync(connectionToExtension, EXTENSION_DBUS_NAME, EXTENSION_OBJECT_PATH, - EXTENSION_INTERFACE_NAME, Converter.javaStringToCString(methodName), params, - 0, OS.G_DBUS_CALL_FLAGS_NO_AUTO_START, 1000, 0, error); - if (error[0] != 0) { - String msg = Display.extractFreeGError(error[0]); - /* - * Don't print console warnings for timeout errors, as we can handle these ourselves. - * Note, most timeout errors happen only when running test cases, not during "normal" use. - */ - if (msg != null && (!msg.contains("Timeout") && !msg.contains("timeout"))) { - System.err.println("SWT WebKitGDBus: there was an error executing something synchronously with the extension."); - System.err.println("SWT WebKitGDBus: the error message is: " + msg); - return (Object) false; - } - return (Object) "timeout"; - } - Object resultObject = gVariant != 0 ? convertGVariantToJava(gVariant) : (Object) false; - // Sometimes we get back tuples from GDBus, which get converted into Object arrays. In this case - // we only care about the first value, since the extension never returns anything more than that. - if (resultObject instanceof Object[]) { - return ((Object []) resultObject)[0]; - } - return resultObject; - } - - /** - * Calls the web extension asynchronously. Note, this method returning true does not - * guarantee the operation's success, it only means no errors occurred. - * - * @param params a pointer to the GVariant containing the parameters - * @param methodName a String representing the DBus method name in the extension - * @return true if the extension was called without errors, false otherwise - */ - static boolean callExtensionAsync (long params, String methodName) { - long [] error = new long [1]; // GError ** - OS.g_dbus_connection_call(connectionToExtension, EXTENSION_DBUS_NAME, EXTENSION_OBJECT_PATH, - EXTENSION_INTERFACE_NAME, Converter.javaStringToCString(methodName), params, - 0, OS.G_DBUS_CALL_FLAGS_NO_AUTO_START, 1000, 0, callExtensionAsyncCB.getAddress(), 0); - if (error[0] != 0) { - String msg = Display.extractFreeGError(error[0]); - System.err.println("SWT WebKitGDBus: there was an error executing something asynchronously " - + "with the extension."); - System.err.println("SWT WebKitGDBus: the error message is: " + msg); - return false; - } - return true; - } - - /* TYPE NOTES - * - * GDBus doesn't support all the types that we need. I used encoded 'byte' to translate some types. - * - * - 'null' is not supported. I thought to potentially use 'maybe' types, but they imply a possible NULL of a certain type, but not null itself. - * so I use 'byte=48' (meaning '0' in ASCII) to denote null. - * - * - Empty arrays/structs are not supported by gdbus. - * "Container types ... Empty structures are not allowed; there must be at least one type code between the parentheses" - * src: https://dbus.freedesktop.org/doc/dbus-specification.html - * I used byte=101 (meaning 'e' in ASCII) to denote empty array. - * - * In Javascript all Number types seem to be 'double', (int/float/double/short -> Double). So we convert everything into double accordingly. - * - * DBus Type info: https://dbus.freedesktop.org/doc/dbus-specification.html#idm423 - * GDBus Type info: https://developer.gnome.org/glib/stable/glib-GVariantType.html - */ - - /** - * Converts the given GVariant to a Java object. - * (Only subset of types is currently supported). - * - * We assume that the given gvariant does not contain errors. (checked by webextension first). - * - * @param gVariant a pointer to the native GVariant - */ - static Object convertGVariantToJava(long gVariant){ - - if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_BOOLEAN)){ - return OS.g_variant_get_boolean(gVariant); - } - - // see: WebKitGTK.java 'TYPE NOTES' - if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_BYTE)) { - byte byteVal = OS.g_variant_get_byte(gVariant); - - switch (byteVal) { - case WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_NULL: - return null; - case WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY: - return new Object [0]; - default: - System.err.println("SWT WebKitGDBus: received an unsupported byte type via GDBus: " + byteVal); - break; - } - } - - if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_DOUBLE)){ - return OS.g_variant_get_double(gVariant); - } - - if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_UINT64)){ - return OS.g_variant_get_uint64(gVariant); - } - - if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_STRING)){ - return Converter.cCharPtrToJavaString(OS.g_variant_get_string(gVariant, null), false); - } - - if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_TUPLE)){ - int length = (int)OS.g_variant_n_children (gVariant); - Object[] result = new Object[length]; - for (int i = 0; i < length; i++) { - result[i] = convertGVariantToJava (OS.g_variant_get_child_value(gVariant, i)); - } - return result; - } - - String typeString = Converter.cCharPtrToJavaString(OS.g_variant_get_type_string(gVariant), false); - SWT.error (SWT.ERROR_INVALID_ARGUMENT, new Throwable("Unhandled variant type " + typeString )); - return null; - } - - /** - * Converts the given Java Object to a GVariant * representation. - * (Only subset of types is currently supported). - * - * We assume that input Object may contain invalid types. - * - * @return pointer GVariant * - */ - static long convertJavaToGVariant(Object javaObject) throws SWTException { - - if (javaObject == null) { - return OS.g_variant_new_byte(WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_NULL); // see: WebKitGTK.java 'TYPE NOTES' - } - - if (javaObject instanceof Long) { - return OS.g_variant_new_uint64((Long) javaObject); - } - - if (javaObject instanceof String) { - return OS.g_variant_new_string (Converter.javaStringToCString((String) javaObject)); - } - - if (javaObject instanceof Boolean) { - return OS.g_variant_new_boolean((Boolean) javaObject); - } - - // We treat Integer, Long, Double, Short as a 'double' because in Javascript these are all 'double'. - // Note, they all extend 'Number' java type, so they are an instance of it. - if (javaObject instanceof Number) { // see: WebKitGTK.java 'TYPE NOTES' - return OS.g_variant_new_double (((Number) javaObject).doubleValue()); - } - - if (javaObject instanceof Object[]) { - Object[] arrayValue = (Object[]) javaObject; - int length = arrayValue.length; - - if (length == 0) { - return OS.g_variant_new_byte(WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY); // see: WebKitGTK.java 'TYPE NOTES' - } - - long variants[] = new long [length]; - - for (int i = 0; i < length; i++) { - variants[i] = convertJavaToGVariant(arrayValue[i]); - } - - return OS.g_variant_new_tuple(variants, length); - } - System.err.println("SWT WebKitGDBus: invalid object being returned to JavaScript: " + javaObject.toString() + "\n" - + "Only the following are supported: null, String, Boolean, Number(Long,Integer,Double...), Object[] of basic types"); - throw new SWTException(SWT.ERROR_INVALID_ARGUMENT, "Given object is not valid: " + javaObject.toString()); - } -} diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java index d02d7f967e..a49a689a05 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java @@ -87,6 +87,8 @@ public class WebKitGTK extends C { public static final int WEBKIT_WEBSITE_DATA_COOKIES = 1 << 8; + public static final int WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START = 0; + public static final int WEBKIT_USER_CONTENT_INJECT_TOP_FRAME = 1; /** Signals */ @@ -114,9 +116,6 @@ public class WebKitGTK extends C { public static final byte[] failed = ascii ("failed"); // $NON-NLS-1$ public static final byte[] finished = ascii ("finished"); // $NON-NLS-1$ - // Webkit2 extension - public static final byte[] initialize_web_extensions = ascii ("initialize-web-extensions"); - // Status text signals public static final byte[] mouse_target_changed = ascii ("mouse-target-changed"); // $NON-NLS-1$ @@ -180,9 +179,6 @@ public static final native long JSObjectGetProperty(long ctx, long object, long public static final native long JSObjectGetPropertyAtIndex(long ctx, long object, int propertyIndex, long [] exception); /** @method flags=dynamic */ -public static final native long JSObjectMakeArray(long ctx, long argumentCount, long [] arguments, long [] exception); - -/** @method flags=dynamic */ public static final native long JSStringCreateWithUTF8CString(byte[] string); /** @method flags=dynamic */ @@ -203,18 +199,6 @@ public static final native void webkit_javascript_result_unref(long js_result); public static final native int JSValueGetType(long ctx, long value); /** @method flags=dynamic */ -public static final native long JSValueMakeBoolean(long ctx, int bool); - -/** @method flags=dynamic */ -public static final native long JSValueMakeNumber(long ctx, double number); - -/** @method flags=dynamic */ -public static final native long JSValueMakeString(long ctx, long string); - -/** @method flags=dynamic */ -public static final native long JSValueMakeUndefined(long ctx); - -/** @method flags=dynamic */ public static final native double JSValueToNumber(long ctx, long value, long [] exception); /** @method flags=dynamic */ @@ -377,9 +361,15 @@ public static final native long webkit_web_context_get_cookie_manager(long conte public static final native long webkit_web_context_get_website_data_manager(long context); /** @method flags=dynamic */ +public static final native long webkit_web_context_get_security_manager(long context); + +/** @method flags=dynamic */ public static final native void webkit_web_context_set_tls_errors_policy(long context, int policy); /** @method flags=dynamic */ +public static final native void webkit_web_context_register_uri_scheme(long context, byte[] scheme, long callback, long user_data, long user_data_destroy_func); + +/** @method flags=dynamic */ public static final native int webkit_web_view_can_go_back(long web_view); /** @method flags=dynamic */ @@ -404,6 +394,9 @@ public static final native long webkit_web_view_get_page_id(long web_view); public static final native long webkit_web_view_get_settings(long web_view); /** @method flags=dynamic */ +public static final native long webkit_web_view_get_user_content_manager(long web_view); + +/** @method flags=dynamic */ public static final native long webkit_web_view_get_title(long web_view); /** @method flags=dynamic */ @@ -444,14 +437,6 @@ public static final native long webkit_web_view_new(); /** @method flags=dynamic */ public static final native long webkit_web_view_new_with_related_view(long web_view); - -/** @method flags=dynamic */ // @param context cast=(WebKitWebContext*) @param directory cast=(const gchar *) -public static final native void webkit_web_context_set_web_extensions_directory(long context, byte[] directory); - -/** @method flags=dynamic */ -public static final native void webkit_web_context_set_web_extensions_initialization_user_data(long /* int */ context, long /* int */ user_data); - - /** * @method flags=dynamic * @param js_result cast=(gpointer) @@ -512,6 +497,36 @@ public static final native long webkit_uri_request_get_uri(long request); /** @method flags=dynamic */ public static final native long webkit_uri_response_get_mime_type(long responce); +/** + * @method flags=dynamic + * @param content_type flags=no_out + */ +public static final native void webkit_uri_scheme_request_finish(long request, long stream, long stream_length, byte[] content_type); + +/** @method flags=dynamic */ +public static final native long webkit_uri_scheme_request_get_uri (long request); + +/** @method flags=dynamic */ +public static final native long webkit_uri_scheme_request_get_web_view(long request); + +/** @method flags=dynamic */ +public static final native long webkit_user_content_manager_add_script(long manager, long script); + +/** @method flags=dynamic */ +public static final native void webkit_user_content_manager_remove_all_scripts(long manager); + +/** @method flags=dynamic */ +public static final native void webkit_security_manager_register_uri_scheme_as_secure(long security_manager, byte[] scheme); + +/** + * @method flags=dynamic + * @param source flags=no_out + */ +public static final native long webkit_user_script_new (byte[] source, int injected_frames, int injection_time, long allow_list, long block_list); + +/** @method flags=dynamic */ +public static final native void webkit_user_script_unref (long user_script); + /* --------------------- start SWT natives --------------------- */ public static final native int GdkRectangle_sizeof(); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java index 2d004432bc..23c3df501b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/TextLayout.java @@ -248,7 +248,7 @@ void computeRuns() { if (style.strikeout) { attrStr.addAttribute(OS.NSStrikethroughStyleAttributeName, NSNumber.numberWithInt(OS.NSUnderlineStyleSingle), range); Color strikeColor = style.strikeoutColor; - if (strikeColor != null) { + if (strikeColor != null && !strikeColor.isDisposed()) { NSColor color = NSColor.colorWithDeviceRed(strikeColor.handle[0], strikeColor.handle[1], strikeColor.handle[2], 1); attrStr.addAttribute(OS.NSStrikethroughColorAttributeName, color, range); } @@ -277,7 +277,7 @@ void computeRuns() { if (underlineStyle != 0) { attrStr.addAttribute(OS.NSUnderlineStyleAttributeName, NSNumber.numberWithInt(underlineStyle), range); Color underlineColor = style.underlineColor; - if (underlineColor != null) { + if (underlineColor != null && !underlineColor.isDisposed()) { NSColor color = NSColor.colorWithDeviceRed(underlineColor.handle[0], underlineColor.handle[1], underlineColor.handle[2], 1); attrStr.addAttribute(OS.NSUnderlineColorAttributeName, color, range); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Button.java index 02cc5bdf67..370c88d76c 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Button.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Button.java @@ -173,7 +173,8 @@ NSSize cellSizeForBounds (long id, long sel, NSRect cellFrame) { NSAttributedString attribStr = createString(text, null, foreground, style, true, true, true); NSRect rect = attribStr.boundingRectWithSize(wrapSize, OS.NSStringDrawingUsesLineFragmentOrigin); attribStr.release(); - double trimHeight = size.height - titleRect.height; + // Avoid trim height to be set to a negative value + double trimHeight = Math.max(size.height - titleRect.height, 0); size.height = rect.height; if (image != null && ((style & (SWT.CHECK|SWT.RADIO)) !=0)) { NSSize imageSize = image.handle.size(); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java index 7f2b241843..d2ef22338b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java @@ -860,8 +860,9 @@ static private void configureSystemOptions () { * macOS 11 always enables it regardless of sdk. The option is force * enabled here in case SWT runs with java/launcher linked with older sdk. */ - if (!OS.isBigSurOrLater ()) + if (!OS.isBigSurOrLater ()) { configureSystemOption ("NSViewAllowsRootLayerBacking", true); + } /* * Starting with macOS 11, layer backing is always enabled. That's fine. @@ -874,8 +875,36 @@ static private void configureSystemOptions () { * things a lot slower. The workaround is to disable the "automatic" image * format. */ - if (OS.isBigSurOrLater ()) + if (OS.isBigSurOrLater ()) { configureSystemOption ("NSViewUsesAutomaticLayerBackingStores", false); + } + + /* + * Bug 578171: There is new code in macOS 12 that remembers which + * Shell was active before menu popup was shown and tries to + * re-activate after menu popup is closed. Unfortunately there is a + * bug in this code: if window list changes, it activates a wrong + * Shell. + * + * This is a bug on its own, but worse yet, this causes a JVM crash + * because activating a new Shell causes menu bar to reset its + * internal data, which is unexpected to the macOS's menu tracking + * loop. + * + * Both bugs are bugs of macOS itself. The workaround is to disable + * the new macOS 12 behavior. + * + * The condition should be for (macOS >= 12), but it's not possible + * to reliably distinguish 11 from 12, see comment for OS.VERSION. + * That's fine: older macOS don't know this setting and will not + * check for it anyway. + */ + if (OS.isBigSurOrLater ()) { + // The name of the option is misleading. What it really means + // is whether '-[NSMenuWindowManagerWindow _setVisible:]' shall + // save/restore current key window or not. + configureSystemOption ("NSMenuWindowManagerWindowShouldSetVisible", true); + } } /** @@ -1028,13 +1057,13 @@ void createMainMenu () { appleMenu.initWithTitle(emptyStr); OS.objc_msgSend(application.id, OS.sel_registerName("setAppleMenu:"), appleMenu.id); - title = NSString.stringWith(SWT.getMessage("About") + " " + appName); + title = NSString.stringWith(SWT.getMessage("SWT_About") + " " + appName); menuItem = appleMenu.addItemWithTitle(title, OS.sel_orderFrontStandardAboutPanel_, emptyStr); menuItem.setTarget(applicationDelegate); appleMenu.addItem(NSMenuItem.separatorItem()); - title = NSString.stringWith(SWT.getMessage("Preferences...")); + title = NSString.stringWith(SWT.getMessage("SWT_Preferences")); menuItem = appleMenu.addItemWithTitle(title, 0, NSString.stringWith(",")); /* @@ -1045,7 +1074,7 @@ void createMainMenu () { appleMenu.addItem(NSMenuItem.separatorItem()); - title = NSString.stringWith(SWT.getMessage("Services")); + title = NSString.stringWith(SWT.getMessage("SWT_Services")); menuItem = appleMenu.addItemWithTitle(title, 0, emptyStr); NSMenu servicesMenu = (NSMenu)new NSMenu().alloc(); servicesMenu.initWithTitle(emptyStr); @@ -1055,22 +1084,22 @@ void createMainMenu () { appleMenu.addItem(NSMenuItem.separatorItem()); - title = NSString.stringWith(SWT.getMessage("Hide") + " " + appName); + title = NSString.stringWith(SWT.getMessage("SWT_Hide") + " " + appName); menuItem = appleMenu.addItemWithTitle(title, OS.sel_hide_, NSString.stringWith("h")); menuItem.setTarget(applicationDelegate); - title = NSString.stringWith(SWT.getMessage("Hide Others")); + title = NSString.stringWith(SWT.getMessage("SWT_HideOthers")); menuItem = appleMenu.addItemWithTitle(title, OS.sel_hideOtherApplications_, NSString.stringWith("h")); menuItem.setKeyEquivalentModifierMask(OS.NSCommandKeyMask | OS.NSAlternateKeyMask); menuItem.setTarget(applicationDelegate); - title = NSString.stringWith(SWT.getMessage("Show All")); + title = NSString.stringWith(SWT.getMessage("SWT_ShowAll")); menuItem = appleMenu.addItemWithTitle(title, OS.sel_unhideAllApplications_, emptyStr); menuItem.setTarget(applicationDelegate); appleMenu.addItem(NSMenuItem.separatorItem()); - title = NSString.stringWith(SWT.getMessage("Quit") + " " + appName); + title = NSString.stringWith(SWT.getMessage("SWT_Quit") + " " + appName); menuItem = appleMenu.addItemWithTitle(title, OS.sel_applicationShouldTerminate_, NSString.stringWith("q")); menuItem.setTarget(applicationDelegate); @@ -5654,28 +5683,24 @@ void applicationWillFinishLaunching (long id, long sel, long notification) { /* To find the nib look for each of these paths, in order, until one is found: * /System/Library/..../Resources/<display name>.lproj/DefaultApp.nib * /System/Library/..../Resources/<language>.lproj/DefaultApp.nib - * /System/Library/..../Resources/<user's default language>.lproj/DefaultApp.nib - * /System/Library/..../Resources/English.lproj/DefaultApp.nib. - * /System/Library/..../Resources/en.lproj/DefaultApp.nib. + * /System/Library/..../Resources/Base.lproj/DefaultApp.nib + * + * If nib file is not found, use the fallback method createMainMenu() to create menu with localized strings. */ NSString path; NSDictionary dict = NSDictionary.dictionaryWithObject(applicationDelegate, NSString.stringWith("NSOwner")); - NSBundle bundle = NSBundle.bundleWithIdentifier(NSString.stringWith("com.apple.JavaVM")); + NSBundle bundle = NSBundle.bundleWithPath(NSString.stringWith("/System/Library/Frameworks/JavaVM.framework/")); if (bundle != null) { path = bundle.pathForResource(NSString.stringWith("DefaultApp"), NSString.stringWith("nib"), null, languageDisplayName); if (path == null) path = bundle.pathForResource(NSString.stringWith("DefaultApp"), NSString.stringWith("nib"), null, NSString.stringWith(languageISOValue)); - if (path == null) path = bundle.pathForResource(NSString.stringWith("DefaultApp"), NSString.stringWith("nib")); - if (!loaded) loaded = path != null && NSBundle.loadNibFile(path, dict, 0); - if (!loaded) { - path = bundle.pathForResource(NSString.stringWith("DefaultApp"), NSString.stringWith("nib"), null, NSString.stringWith("English")); - if (path == null) path = bundle.pathForResource(NSString.stringWith("DefaultApp"), NSString.stringWith("nib"), null, NSString.stringWith("en")); - loaded = path != null && NSBundle.loadNibFile(path, dict, 0); + if (path == null && languageISOValue.equals("en")) { + path = bundle.pathForResource(NSString.stringWith("DefaultApp"), NSString.stringWith("nib")); } + if (!loaded) loaded = path != null && NSBundle.loadNibFile(path, dict, 0); } - if (!loaded) { - path = NSString.stringWith(System.getProperty("java.home") + "/../Resources/English.lproj/DefaultApp.nib"); - loaded = path != null && NSBundle.loadNibFile(path, dict, 0); - } + /* + * Create the main menu ourselves if Default.nib was not loaded or was not found for the specific language + */ if (!loaded) { createMainMenu(); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java index 965fb9d96e..c49f1354fe 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Table.java @@ -3636,39 +3636,66 @@ boolean tableView_writeRowsWithIndexes_toPasteboard(long id, long sel, long arg0 return sendMouseEvent(NSApplication.sharedApplication().currentEvent(), SWT.DragDetect, true); } +void handleClickSelected() { + /* + * When there are multiple selected items and one of them is clicked + * without modifiers, macOS supports two cases: + * 1) For single click, all other items are deselected + * 2) For double-click, selection stays as is, allowing to create + * double-click event with multiple items. + * In order to distinguish between the two, macOS delays (1) by + * [NSEvent doubleClickInterval] in order to see if it's case (2). + * This causes SWT.Selection to occur after SWT.MouseUp. + * + * Bug 289483: For consistent cross-platform behavior, we want + * SWT.Selection to occur before SWT.MouseUp. The workaround is to + * implement (1) in SWT code and ignore the delayed selection event. + */ + + int clickedRow = selectedRowIndex; + selectedRowIndex = -1; + + if (clickedRow == -1) return; + if (dragDetected) return; + + // Deselect all items except the clicked one + NSTableView widget = (NSTableView)view; + NSIndexSet selectedRows = widget.selectedRowIndexes (); + int count = (int)selectedRows.count(); + long [] indexBuffer = new long [count]; + selectedRows.getIndexes(indexBuffer, count, 0); + for (int i = 0; i < count; i++) { + if (indexBuffer[i] == clickedRow) continue; + ignoreSelect = true; + widget.deselectRow (indexBuffer[i]); + ignoreSelect = false; + } + + // Bug 456602: It's possible that item is removed between mouse + // down (where 'selectedRowIndex' was cached) and mouse up (current + // code). In such case, all other items are still deselected, because + // 1) without workaround, selection should have happened in mouse down, + // where item still existed + // 2) clicking empty space deselects all items on macOS + // If item is deleted, then pending selection is canceled by macOS, so + // there's no need to ignore the next selection event. + if (clickedRow >= itemCount) return; + + // Emulate SWT.Selection + Event event = new Event (); + event.item = _getItem(clickedRow); + sendSelectionEvent (SWT.Selection, event, false); + + // Ignore real SWT.Selection that will arrive later + ignoreSelect = true; +} + @Override boolean sendMouseEvent(NSEvent nsEvent, int type, boolean send) { if (type == SWT.DragDetect) { dragDetected = true; } else if (type == SWT.MouseUp) { - /* - * This code path handles the case of an unmodified click on an already-selected row. - * To keep the order of events correct, deselect the other selected items and send the - * selection event before MouseUp is sent. Ignore the next selection event. - */ - if (selectedRowIndex != -1) { - if (dragDetected) { - selectedRowIndex = -1; - } else { - NSTableView widget = (NSTableView)view; - NSIndexSet selectedRows = widget.selectedRowIndexes (); - int count = (int)selectedRows.count(); - long [] indexBuffer = new long [count]; - selectedRows.getIndexes(indexBuffer, count, 0); - for (int i = 0; i < count; i++) { - if (indexBuffer[i] == selectedRowIndex) continue; - ignoreSelect = true; - widget.deselectRow (indexBuffer[i]); - ignoreSelect = false; - } - - Event event = new Event (); - event.item = _getItem ((int)selectedRowIndex); - selectedRowIndex = -1; - sendSelectionEvent (SWT.Selection, event, false); - ignoreSelect = true; - } - } + handleClickSelected(); dragDetected = false; } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java index da9954aa6a..1c2de57fa6 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Tree.java @@ -2805,11 +2805,7 @@ boolean sendMouseEvent(NSEvent nsEvent, int type, boolean send) { if (type == SWT.DragDetect) { dragDetected = true; } else if (type == SWT.MouseUp) { - /* - * This code path handles the case of an unmodified click on an already-selected row. - * To keep the order of events correct, deselect the other selected items and send the - * selection event before MouseUp is sent. Ignore the next selection event. - */ + // See code comment in Table.handleClickSelected() if (selectedRowIndex != -1) { if (dragDetected) { selectedRowIndex = -1; @@ -2828,6 +2824,8 @@ boolean sendMouseEvent(NSEvent nsEvent, int type, boolean send) { Event event = new Event (); id itemID = widget.itemAtRow (selectedRowIndex); + // (itemID = null) means that item was removed after + // 'selectedRowIndex' was cached if (itemID != null) { Widget item = display.getWidget (itemID.id); if (item != null && item instanceof TreeItem) { @@ -3074,7 +3072,7 @@ public void setHeaderVisible (boolean show) { /** * Sets the number of root-level items contained in the receiver. * <p> - * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(org.eclipse.swt.widgets.Tree,int,int)} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} * and {@link TreeItem#setItemCount} * * @param count the number of items diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/TreeItem.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/TreeItem.java index 1fdf19e060..529082d051 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/TreeItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/TreeItem.java @@ -67,8 +67,8 @@ public class TreeItem extends Item { * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>. * Item is inserted as last direct child of the tree. * <p> - * The fastest way to insert many items is documented in {@link org.eclipse.swt.widgets.TreeItem#TreeItem(Tree,int,int)} - * and {@link org.eclipse.swt.widgets.TreeItem#setItemCount} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} + * and {@link TreeItem#setItemCount} * * @param parent a tree control which will be the parent of the new instance (cannot be null) * @param style no styles are currently supported, pass SWT.NONE @@ -126,8 +126,8 @@ public TreeItem (Tree parent, int style, int index) { * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>. * Item is inserted as last direct child of the specified <code>TreeItem</code>. * <p> - * The fastest way to insert many items is documented in {@link org.eclipse.swt.widgets.TreeItem#TreeItem(Tree,int,int)} - * and {@link org.eclipse.swt.widgets.TreeItem#setItemCount} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} + * and {@link TreeItem#setItemCount} * * @param parentItem a tree control which will be the parent of the new instance (cannot be null) * @param style no styles are currently supported, pass SWT.NONE @@ -152,8 +152,8 @@ public TreeItem (TreeItem parentItem, int style) { * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>. * Item is inserted as <code>index</code> direct child of the specified <code>TreeItem</code>. * <p> - * The fastest way to insert many items is documented in {@link org.eclipse.swt.widgets.TreeItem#TreeItem(Tree,int,int)} - * and {@link org.eclipse.swt.widgets.TreeItem#setItemCount} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} + * and {@link TreeItem#setItemCount} * * @param parentItem a tree control which will be the parent of the new instance (cannot be null) * @param style no styles are currently supported, pass SWT.NONE diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java index d9f38fd976..d20f9ca7c4 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Widget.java @@ -105,7 +105,7 @@ public abstract class Widget { static final int DEFAULT_HEIGHT = 64; Widget () { - /* Do nothing */ + notifyCreationTracker(); } /** @@ -143,6 +143,7 @@ public Widget (Widget parent, int style) { this.style = style; display = parent.display; reskinWidget (); + notifyCreationTracker(); } long accessibleHandle() { @@ -1376,6 +1377,7 @@ void release (boolean destroy) { } } } + notifyDisposalTracker(); } void releaseChildren (boolean destroy) { @@ -2190,4 +2192,16 @@ boolean writeSelectionToPasteboard(long id, long sel, long pasteboard, long type return false; } +void notifyCreationTracker() { + if (WidgetSpy.isEnabled) { + WidgetSpy.getInstance().widgetCreated(this); + } +} + +void notifyDisposalTracker() { + if (WidgetSpy.isEnabled) { + WidgetSpy.getInstance().widgetDisposed(this); + } +} + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak b/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak index a2a919082b..429f0e5b6b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2000, 2021 IBM Corporation and others. +# Copyright (c) 2000, 2022 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -13,7 +13,7 @@ #******************************************************************************* maj_ver=4 -min_ver=950 -rev=3 -comma_ver=4,950,3,0 +min_ver=952 +rev=6 +comma_ver=4,952,6,0 cef_ver=3071
\ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java index 5dadc75cac..97837153a1 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java @@ -2275,6 +2275,7 @@ public class SWT { * <p><b>Used By:</b></p> * <ul> * <li><code>FormAttachment</code> in a <code>FormLayout</code></li> + * <li><code>BoderData</code> in a <code>BoderLayout</code></li> * </ul> */ public static final int TOP = UP; @@ -2299,6 +2300,7 @@ public class SWT { * <ul> * <li><code>FormAttachment</code> in a <code>FormLayout</code></li> * <li><code>TabFolder</code></li> + * <li><code>BoderData</code> in a <code>BoderLayout</code></li> * </ul> */ public static final int BOTTOM = DOWN; @@ -2329,6 +2331,10 @@ public class SWT { * This constant can also be used to representing the left keyboard * location during a key event. * </p> + * <p><b>Used By:</b></p> + * <ul> + * <li><code>BoderData</code> in a <code>BoderLayout</code></li> + * </ul> */ public static final int LEFT = LEAD; @@ -2358,6 +2364,10 @@ public class SWT { * This constant can also be used to representing the right keyboard * location during a key event. * </p> + * <p><b>Used By:</b></p> + * <ul> + * <li><code>BoderData</code> in a <code>BoderLayout</code></li> + * </ul> */ public static final int RIGHT = TRAIL; @@ -2369,6 +2379,7 @@ public class SWT { * <li><code>Label</code></li> * <li><code>TableColumn</code></li> * <li><code>FormAttachment</code> in a <code>FormLayout</code></li> + * <li><code>BoderData</code> in a <code>BoderLayout</code></li> * </ul> */ public static final int CENTER = 1 << 24; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/SWTMessages.properties b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/SWTMessages.properties index da86f4f1e8..1c9a2c67aa 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/SWTMessages.properties +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/SWTMessages.properties @@ -126,3 +126,10 @@ SWT_ValidTo=Valid To SWT_ValidFromTo=Valid from: {0} to: {1} SWT_Subject=Subject SWT_SerialNumber=Serial Number +SWT_About=About +SWT_Preferences=Preferences... +SWT_Services=Services +SWT_Hide=Hide +SWT_HideOthers=Hide Others +SWT_ShowAll=Show All +SWT_Quit=Quit diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/WidgetSpy.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/WidgetSpy.java new file mode 100644 index 0000000000..0acb6c3479 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/WidgetSpy.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2022 Simeon Andreev and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Simeon Andreev - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.internal; + +import java.util.*; +import java.util.List; + +import org.eclipse.swt.widgets.*; + +/** + * Helper class to allow widget creation and disposal monitoring + */ +public class WidgetSpy { + + /** + * Flag to prevent {@link Widget} from entering this class during debugging, + * if tracking of creation and disposal is not enabled. + */ + public static boolean isEnabled; + + private static final WidgetSpy instance = new WidgetSpy(); + + private WidgetTracker widgetTracker; + + private WidgetSpy() { + // singleton + } + + public static WidgetSpy getInstance() { + return instance; + } + + /** + * Enables tracking of {@link Widget} object creation and disposal. + * + * WARNING: the tracker will be called from the UI thread. Do not block + * it and do not throw any exceptions. + * + * @param tracker notified when a widget is created or disposed. Use + * {@code null} to disable tracking. The tracker will be + * notified of widgets created and disposed after setting the tracker. + */ + public void setWidgetTracker(WidgetTracker tracker) { + isEnabled = tracker != null; + widgetTracker = tracker; + } + + public void widgetCreated(Widget widget) { + if (widgetTracker != null) { + widgetTracker.widgetCreated(widget); + } + } + + public void widgetDisposed(Widget widget) { + if (widgetTracker != null) { + widgetTracker.widgetDisposed(widget); + } + } + + /** + * Custom callback to register widget creation / disposal + */ + public static interface WidgetTracker { + default void widgetCreated(Widget widget) {} + + default void widgetDisposed(Widget widget) {} + } + + /** + * Default implementation simply collects all created and not disposed widgets + */ + public static class NonDisposedWidgetTracker implements WidgetTracker { + + private final Map<Widget, Error> nonDisposedWidgets = new LinkedHashMap<>(); + private final Set<Class<? extends Widget> > trackedTypes = new HashSet<>(); + + @Override + public void widgetCreated(Widget widget) { + boolean isTracked = isTracked(widget); + if (isTracked) { + Error creationException = new Error("Created widget of type: " + widget.getClass().getSimpleName()); + nonDisposedWidgets.put(widget, creationException); + } + } + + @Override + public void widgetDisposed(Widget widget) { + boolean isTracked = isTracked(widget); + if (isTracked) { + nonDisposedWidgets.remove(widget); + } + } + + public Map<Widget, Error> getNonDisposedWidgets() { + return Collections.unmodifiableMap(nonDisposedWidgets); + } + + public void startTracking() { + clearNonDisposedWidgets(); + WidgetSpy.getInstance().setWidgetTracker(this); + } + + private void clearNonDisposedWidgets() { + nonDisposedWidgets.clear(); + } + + public void stopTracking() { + WidgetSpy.getInstance().setWidgetTracker(null); + } + + public void setTrackingEnabled(boolean enabled) { + if (enabled) { + startTracking(); + } else { + stopTracking(); + } + } + + public void setTrackedTypes(List<Class<? extends Widget>> types) { + trackedTypes.clear(); + trackedTypes.addAll(types); + } + + private boolean isTracked(Widget widget) { + boolean isTrackingAllTypes = trackedTypes.isEmpty(); + if (isTrackingAllTypes) { + return true; + } + if (widget != null) { + Class<? extends Widget> widgetType = widget.getClass(); + if (trackedTypes.contains(widgetType)) { + return true; + } + for (Class<? extends Widget> filteredType : trackedTypes) { + if (filteredType.isAssignableFrom(widgetType)) { + return true; + } + } + } + return false; + } + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/BorderData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/BorderData.java new file mode 100644 index 0000000000..bd4dfcb663 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/BorderData.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2022 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.layout; + +import static org.eclipse.swt.SWT.*; + +import java.util.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Controls the several aspects of a {@link BorderLayout}. + * + * @since 3.119 + */ +public final class BorderData { + + private final Map<Control, Point> cachedSize = new IdentityHashMap<>(1); + + public int hHint = SWT.DEFAULT; + public int wHint = SWT.DEFAULT; + public int region = SWT.CENTER; + + /** + * creates a {@link BorderData} with default options + */ + public BorderData() { + } + + /** + * creates a {@link BorderData} initialized with the given region, valid values + * are {@link SWT#TOP}, {@link SWT#CENTER}, {@link SWT#LEFT}, {@link SWT#RIGHT}, + * {@link SWT#BOTTOM} + * + * @param region the region valid values are {@link SWT#TOP}, + * {@link SWT#CENTER}, {@link SWT#LEFT}, {@link SWT#RIGHT}, + * {@link SWT#BOTTOM} + */ + public BorderData(int region) { + this.region = region; + } + + /** + * creates a {@link BorderData} initialized with the given region and width and + * height hints + * + * @param region the region valid values are {@link SWT#TOP}, + * {@link SWT#CENTER}, {@link SWT#LEFT}, {@link SWT#RIGHT}, + * {@link SWT#BOTTOM} + * @param widthHint the default hint for the width + * @param heightHint he default hint for the height + */ + public BorderData(int region, int widthHint, int heightHint) { + this.region = region; + this.wHint = widthHint; + this.hHint = heightHint; + } + + Point getSize(Control control) { + return cachedSize.computeIfAbsent(control, c -> c.computeSize(wHint, hHint, true)); + } + + void flushCache(Control control) { + cachedSize.remove(control); + } + + @Override + public String toString() { + return "BorderData [region=" + getRegionString(region) + ", hHint=" + hHint + ", wHint=" + wHint + "]"; + } + + static String getRegionString(int region) { + switch (region) { + case SWT.TOP: + return "SWT.TOP"; + case SWT.RIGHT: + return "SWT.RIGHT"; + case SWT.BOTTOM: + return "SWT.BOTTOM"; + case SWT.LEFT: + return "SWT.LEFT"; + case SWT.CENTER: + return "SWT.CENTER"; + default: + return "SWT.NONE"; + } + } + + /** + * + * @return the region of this BorderData or {@link SWT#NONE} if it is out of + * range + */ + int getRegion() { + switch (region) { + case TOP: + case BOTTOM: + case CENTER: + case RIGHT: + case LEFT: + return region; + case SWT.NONE: + default: + return SWT.NONE; + } + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/BorderLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/BorderLayout.java new file mode 100644 index 0000000000..4f6b176971 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/BorderLayout.java @@ -0,0 +1,420 @@ +/******************************************************************************* + * Copyright (c) 2022 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.layout; + +import static org.eclipse.swt.SWT.*; + +import java.util.*; +import java.util.AbstractMap.*; +import java.util.List; +import java.util.Map.*; +import java.util.function.*; +import java.util.stream.*; +import java.util.stream.IntStream.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * {@link BorderLayout} places controls in five regions + * + * <pre> + * +--------------------------------+ + * | NORTH / TOP | + * +---+------------------------+---+ + * | | | | + * | W | | E | + * | E | | A | + * | S | | S | + * | T | | T | + * | / | | / | + * | L | CENTER | R | + * | E | | I | + * | F | | G | + * | T | | H | + * | | | T | + * | | | | + * +---+------------------------+---+ + * | SOUTH / BOTTOM | + * +--------------------------------+ + * </pre> + * + * The controls at the NORTH/SOUTH borders get their preferred heights, the + * controls at the EAST/WEST get their preferred widths and the center region + * grow/shrink according to the remaining space. If more than one control is + * placed inside a region the controls are equally distributed across their axis + * where the grow (CENTER controlled by the {@link BorderLayout#type} value) + * + * @since 3.119 + */ +public class BorderLayout extends Layout { + + private static final ToIntFunction<Point> WIDTH = p -> p.x; + private static final ToIntFunction<Point> HEIGHT = p -> p.y; + + /** + * type specifies how controls will be positioned within the center region. + * + * The default value is {@link SWT#HORIZONTAL}. + * + * Possible values are: + * <ul> + * <li>{@link SWT#HORIZONTAL}: Position the controls horizontally from left to + * right</li> + * <li>{@link SWT#VERTICAL}: Position the controls vertically from top to + * bottom</li> + * </ul> + */ + public int type = SWT.HORIZONTAL; + /** + * marginWidth specifies the number of points of horizontal margin that will be + * placed along the left and right edges of the layout. + * + * The default value is 0. + * + */ + public int marginWidth = 0; + /** + * marginHeight specifies the number of points of vertical margin that will be + * placed along the top and bottom edges of the layout. + * + * The default value is 0. + * + */ + public int marginHeight = 0; + /** + * spacing specifies the number of points between the edge of one region and its + * neighboring regions. + * + * The default value is 0. + * + */ + public int spacing = 0; + /** + * controlSpacing specifies the number of points between the edge of one control + * and its neighboring control inside a region. + * + * The default value is 0. + * + */ + public int controlSpacing = 0; + /** + * If the width of the {@link SWT#LEFT} and {@link SWT#RIGHT} region exceeds the + * available space this factor is used to distribute the size to the controls, + * valid values range between [0 ... 1] + * + * The default value is 0.5 (equal distribution of available space) + */ + public double widthDistributionFactor = 0.5; + /** + * If the height of the {@link SWT#TOP} and {@link SWT#BOTTOM} region exceeds the + * available space this factor is used to distribute the size to the controls, + * valid values range between [0 ... 1] + * + * The default value is 0.5 (equal distribution of available space) + * + */ + public double heightDistributionFactor = 0.5; + + @Override + protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { + if (hHint > SWT.DEFAULT && wHint > SWT.DEFAULT) { + return new Point(wHint, hHint); + } + Stream<Entry<Control, BorderData>> children = Arrays.stream(composite.getChildren())// + .map(control-> borderDataControl(control, flushCache)); + Map<Integer, List<Entry<Control, BorderData>>> regionMap = children + .collect(Collectors.groupingBy(BorderLayout::region)); + int width; + if (wHint <= SWT.DEFAULT) { + Builder widthBuilder = IntStream.builder(); + int northWidth = getTotal(WIDTH, TOP, regionMap); + int southWidth = getTotal(WIDTH, BOTTOM, regionMap); + int centerWidth; + if (type == SWT.HORIZONTAL) { + centerWidth = getTotal(WIDTH, CENTER, regionMap); + } else { + centerWidth = getMax(WIDTH, CENTER, regionMap); + } + int westWidth = getMax(WIDTH, LEFT, regionMap); + int eastWidth = getMax(WIDTH, RIGHT, regionMap); + int middleWidth = westWidth + centerWidth + eastWidth; + if (centerWidth > 0) { + if (westWidth > 0) { + middleWidth += spacing; + } + if (eastWidth > 0) { + middleWidth += spacing; + } + } else if (westWidth > 0 && eastWidth > 0) { + middleWidth += spacing; + } + widthBuilder.add(middleWidth); + widthBuilder.add(northWidth); + widthBuilder.add(southWidth); + width = widthBuilder.build().max().orElse(0) + 2 * marginWidth; + } else { + width = wHint; + } + int height; + if (hHint <= SWT.DEFAULT) { + Builder heightBuilder = IntStream.builder(); + int northHeight = getMax(HEIGHT, TOP, regionMap); + int southHeight = getMax(HEIGHT, BOTTOM, regionMap); + int westHeight = getTotal(HEIGHT, LEFT, regionMap); + int eastHeight = getTotal(HEIGHT, RIGHT, regionMap); + int centerHeight; + if (type == SWT.HORIZONTAL) { + centerHeight = getMax(HEIGHT, CENTER, regionMap); + } else { + centerHeight = getTotal(HEIGHT, CENTER, regionMap); + } + if (centerHeight > 0) { + if (northHeight > 0) { + centerHeight += spacing; + } + if (southHeight > 0) { + centerHeight += spacing; + } + } + if (westHeight > 0) { + if (northHeight > 0) { + westHeight += spacing; + } + if (southHeight > 0) { + westHeight += spacing; + } + } + if (eastHeight > 0) { + if (northHeight > 0) { + eastHeight += spacing; + } + if (southHeight > 0) { + eastHeight += spacing; + } + } + int sum = northHeight + southHeight; + heightBuilder.add(westHeight + sum); + heightBuilder.add(centerHeight + sum); + heightBuilder.add(eastHeight + sum); + height = heightBuilder.build().max().orElse(0) + 2 * marginHeight; + } else { + height = hHint; + } + return new Point(width, height); + } + + /** + * Calculates the total W/H according to the extractor + * + * @param extractor either {@link #WIDTH} or {@link #HEIGHT} + * @param region the region to compute + * @param regionMap the map of regions + * @return the total W/H including the {@link #controlSpacing} + */ + private int getTotal(ToIntFunction<Point> extractor, int region, + Map<Integer, List<Entry<Control, BorderData>>> regionMap) { + List<Entry<Control, BorderData>> list = regionMap.getOrDefault(region, Collections.emptyList()); + if (list.isEmpty()) { + return 0; + } + return list.stream().mapToInt(entry -> extractor.applyAsInt(entry.getValue().getSize(entry.getKey()))).sum() + + ((list.size() - 1) * controlSpacing); + } + + private static int getMax(ToIntFunction<Point> extractor, int region, + Map<Integer, List<Entry<Control, BorderData>>> regionMap) { + List<Entry<Control, BorderData>> list = regionMap.getOrDefault(region, Collections.emptyList()); + return getMax(extractor, list); + } + + private static int getMax(ToIntFunction<Point> extractor, List<Entry<Control, BorderData>> list) { + return list.stream().mapToInt(entry -> extractor.applyAsInt(entry.getValue().getSize(entry.getKey()))).max() + .orElse(0); + } + + @Override + protected void layout(Composite composite, boolean flushCache) { + Rectangle clientArea = composite.getClientArea(); + int clientX = clientArea.x + marginWidth; + int clientY = clientArea.y + marginHeight; + int clientWidth = clientArea.width - 2 * marginWidth; + int clientHeight = clientArea.height - 2 * marginHeight; + Stream<Entry<Control, BorderData>> children = Arrays.stream(composite.getChildren())// + .map(control-> borderDataControl(control, flushCache)); + Map<Integer, List<Entry<Control, BorderData>>> regionMap = children + .collect(Collectors.groupingBy(BorderLayout::region)); + regionMap.getOrDefault(SWT.NONE, Collections.emptyList()) + .forEach(entry -> entry.getKey().setBounds(clientX, clientY, 0, 0)); + List<Entry<Control, BorderData>> northList = regionMap.getOrDefault(TOP, Collections.emptyList()); + List<Entry<Control, BorderData>> southList = regionMap.getOrDefault(BOTTOM, Collections.emptyList()); + List<Entry<Control, BorderData>> westList = regionMap.getOrDefault(LEFT, Collections.emptyList()); + List<Entry<Control, BorderData>> eastList = regionMap.getOrDefault(RIGHT, Collections.emptyList()); + List<Entry<Control, BorderData>> centerList = regionMap.getOrDefault(CENTER, Collections.emptyList()); + int northControlCount = northList.size(); + int northControlHeight = getMax(HEIGHT, northList); + int southControlCount = southList.size(); + int southControlHeight = getMax(HEIGHT, southList); + if (northControlHeight + southControlHeight > clientHeight) { + int distributionSize = (int) (clientHeight * heightDistributionFactor); + if (northControlHeight > distributionSize) { + northControlHeight = distributionSize; + } + southControlHeight = clientHeight - northControlHeight; + } + int centerControlHeight = clientHeight - northControlHeight - southControlHeight; + int westControlCount = westList.size(); + int westControlWidth = getMax(WIDTH, westList); + int eastControlCount = eastList.size(); + int eastControlWidth = getMax(WIDTH, eastList); + if (westControlWidth + eastControlWidth > clientWidth) { + int distributionSize = (int) (clientWidth * widthDistributionFactor); + if (westControlWidth > distributionSize) { + westControlWidth = distributionSize; + } + eastControlWidth = clientWidth - westControlWidth; + } + int centerControlWidth = clientWidth - westControlWidth - eastControlWidth; + int centerControlCount = centerList.size(); + // Full width and preferred height for NORTH and SOUTH if possible + if (northControlCount > 0) { + int controlWidth = (clientWidth - (northControlCount - 1) * controlSpacing) / northControlCount; + int x = clientX; + int y = clientY; + for (Entry<Control, BorderData> entry : northList) { + entry.getKey().setBounds(x, y, controlWidth, northControlHeight); + x += controlWidth + controlSpacing; + } + } + if (southControlCount > 0) { + int controlWidth = (clientWidth - (southControlCount - 1) * controlSpacing) / southControlCount; + int x = clientX; + int y = clientY + centerControlHeight + northControlHeight; + for (Entry<Control, BorderData> entry : southList) { + entry.getKey().setBounds(x, y, controlWidth, southControlHeight); + x += controlWidth + controlSpacing; + } + } + // remaining height for WEST and EAST, preferred width for WEST and EAST if + // possible ... + if (westControlCount > 0) { + int x = clientX; + int y = clientY + northControlHeight; + int h = clientHeight - northControlHeight - southControlHeight; + if (northControlCount > 0) { + y += spacing; + h -= spacing; + } + if (southControlCount > 0) { + h -= spacing; + } + int controlHeight = (h - (westControlCount - 1) * controlSpacing) / westControlCount; + for (Entry<Control, BorderData> entry : westList) { + entry.getKey().setBounds(x, y, westControlWidth, controlHeight); + y += controlHeight + controlSpacing; + } + } + if (eastControlCount > 0) { + int x = clientX + centerControlWidth + westControlWidth; + int y = clientY + northControlHeight; + int h = clientHeight - northControlHeight - southControlHeight; + if (northControlCount > 0) { + y += spacing; + h -= spacing; + } + if (southControlCount > 0) { + h -= spacing; + } + int controlHeight = (h - (eastControlCount - 1) * controlSpacing) / eastControlCount; + for (Entry<Control, BorderData> entry : eastList) { + entry.getKey().setBounds(x, y, eastControlWidth, controlHeight); + y += controlHeight + controlSpacing; + } + } + // remaining height and width for CENTER + if (centerControlCount > 0) { + int x = clientX + westControlWidth; + int y = clientY + northControlHeight; + int h = centerControlHeight; + int w = centerControlWidth; + if (westControlCount > 0) { + x += spacing; + w -= spacing; + } + if (eastControlCount > 0) { + w -= spacing; + } + if (northControlCount > 0) { + y += spacing; + h -= spacing; + } + if (southControlCount > 0) { + h -= spacing; + } + int controlHeight; + int controlWidth; + if (type == SWT.HORIZONTAL) { + controlHeight = h; + controlWidth = (w - (centerControlCount - 1) * controlSpacing) / centerControlCount; + } else { + controlWidth = w; + controlHeight = (h - (centerControlCount - 1) * controlSpacing) / centerControlCount; + } + for (Entry<Control, BorderData> entry : centerList) { + entry.getKey().setBounds(x, y, controlWidth, controlHeight); + if (type == SWT.HORIZONTAL) { + x += controlWidth + controlSpacing; + } else { + y += controlHeight + controlSpacing; + } + } + } + } + + private static <C extends Control> Entry<C, BorderData> borderDataControl(C control, boolean flushCache) { + Object layoutData = control.getLayoutData(); + if (layoutData instanceof BorderData) { + BorderData borderData = (BorderData) layoutData; + if (flushCache) { + borderData.flushCache(control); + } + return new SimpleEntry<>(control, borderData); + } else { + return new SimpleEntry<>(control, null); + } + } + + private static int region(Entry<Control, BorderData> entry) { + BorderData borderData = entry.getValue(); + if (borderData == null) { + //we assume all controls without explicit data to be placed in the center area + return SWT.CENTER; + } + return borderData.getRegion(); + } + + @Override + public String toString() { + return "BorderLayout [" // + + "type=" + ((type == SWT.HORIZONTAL) ? "SWT.HORIZONTAL" : "SWT.VERTICAL") // + + ", marginWidth=" + marginWidth // + + ", marginHeight=" + marginHeight // + + ", spacing=" + spacing // + + ", controlSpacing=" + controlSpacing // + + ", widthDistributionFactor=" + widthDistributionFactor// + + ", heightDistributionFactor=" + heightDistributionFactor // + + "]"; + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt b/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt index f423d893b9..ccc5290de9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt @@ -1 +1 @@ -version 4.950
\ No newline at end of file +version 4.952
\ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java index ec5d50b551..7a0f7aee60 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java @@ -17,11 +17,13 @@ package org.eclipse.swt.graphics; import java.io.*; import java.util.*; +import java.util.List; import org.eclipse.swt.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.internal.image.*; +import org.eclipse.swt.widgets.*; /** * Instances of this class are used to load images from, @@ -176,16 +178,12 @@ boolean isInterlacedPNG(byte [] imageAsByteArray) { } ImageData [] getImageDataArrayFromStream(InputStream stream) { - byte[] buffer = new byte[2048]; long loader = GDK.gdk_pixbuf_loader_new(); - int length; List<ImageData> imgDataList = new ArrayList<>(); try { // 1) Load InputStream into byte array ByteArrayOutputStream baos = new ByteArrayOutputStream(); - while ((length = stream.read(buffer)) > -1) { - baos.write(buffer, 0, length); - } + stream.transferTo(baos); baos.flush(); byte[] data_buffer = baos.toByteArray(); if (data_buffer.length == 0) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT); // empty stream @@ -193,7 +191,20 @@ ImageData [] getImageDataArrayFromStream(InputStream stream) { // 2) Copy byte array to C memory, write to GdkPixbufLoader long buffer_ptr = OS.g_malloc(data_buffer.length); C.memmove(buffer_ptr, data_buffer, data_buffer.length); - GDK.gdk_pixbuf_loader_write(loader, buffer_ptr, data_buffer.length, null); + long [] error = new long [1]; + GDK.gdk_pixbuf_loader_write(loader, buffer_ptr, data_buffer.length, error); + if(error[0] != 0) { + /* Bug 576484 + * It is safe just to assume if this fails it is most likely an IO error + * since unsupported format is checked before, and invalid image right after. + * Still, check if it belongs to the G_FILE_ERROR domain and IO error code + */ + if(OS.g_error_matches(error[0], OS.g_file_error_quark(), OS.G_FILE_ERROR_IO)){ + SWT.error(SWT.ERROR_IO, null, Display.extractFreeGError(error[0])); + } else { + OS.g_error_free(error[0]); + } + } GDK.gdk_pixbuf_loader_close(loader, null); // 3) Get GdkPixbufAnimation from loader diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/GDBus.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/GDBus.java index 8bda62b217..78def99d4a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/GDBus.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/GDBus.java @@ -335,7 +335,7 @@ public class GDBus { * * @param gVariant a pointer to the native GVariant */ - private static Object[] convertGVariantToJava(long gVariant) { + public static Object[] convertGVariantToJava(long gVariant) { Object retVal = convertGVariantToJavaHelper(gVariant); if (retVal instanceof Object[]) { return (Object[]) retVal; @@ -405,7 +405,7 @@ public class GDBus { * * @return pointer GVariant * */ - private static long convertJavaToGVariant(Object javaObject) throws SWTException { + public static long convertJavaToGVariant(Object javaObject) throws SWTException { if (javaObject == null) { return 0; } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java index 07609de651..10a2f92441 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2020 IBM Corporation and others. + * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -304,7 +304,7 @@ void createHandle (int index) { switch (style & bits) { case SWT.ARROW: - byte arrowType [] = GTK.GTK_NAMED_ICON_GO_UP; + byte[] arrowType = GTK.GTK_NAMED_ICON_GO_UP; if ((style & SWT.UP) != 0) arrowType = GTK.GTK_NAMED_ICON_GO_UP; if ((style & SWT.DOWN) != 0) arrowType = GTK.GTK_NAMED_ICON_GO_DOWN; if ((style & SWT.LEFT) != 0) arrowType = GTK.GTK_NAMED_ICON_GO_PREVIOUS; @@ -844,7 +844,7 @@ void _setAlignment (int alignment) { style &= ~(SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT); style |= alignment & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT); boolean isRTL = (style & SWT.RIGHT_TO_LEFT) != 0; - byte arrowType [] = GTK.GTK_NAMED_ICON_GO_UP; + byte[] arrowType = GTK.GTK_NAMED_ICON_GO_UP; switch (alignment) { case SWT.UP: arrowType = GTK.GTK_NAMED_ICON_GO_UP; break; case SWT.DOWN: arrowType = GTK.GTK_NAMED_ICON_GO_DOWN; break; @@ -1187,7 +1187,7 @@ void setOrientation (boolean create) { if (labelHandle != 0) GTK.gtk_widget_set_direction (labelHandle, dir); if (imageHandle != 0) GTK.gtk_widget_set_direction (imageHandle, dir); if (arrowHandle != 0) { - byte arrowType [] = (style & SWT.RIGHT_TO_LEFT) != 0 ? GTK.GTK_NAMED_ICON_GO_NEXT : GTK.GTK_NAMED_ICON_GO_PREVIOUS; + byte[] arrowType = (style & SWT.RIGHT_TO_LEFT) != 0 ? GTK.GTK_NAMED_ICON_GO_NEXT : GTK.GTK_NAMED_ICON_GO_PREVIOUS; switch (style & (SWT.LEFT | SWT.RIGHT)) { case SWT.LEFT: GTK3.gtk_image_set_from_icon_name (arrowHandle, arrowType, GTK.GTK_ICON_SIZE_MENU); break; case SWT.RIGHT: GTK3.gtk_image_set_from_icon_name (arrowHandle, arrowType, GTK.GTK_ICON_SIZE_MENU); break; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java index ffdbf489ac..d3bb60ab59 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java @@ -57,6 +57,8 @@ public abstract class Control extends Widget implements Drawable { static final boolean DISABLE_EMOJI = Boolean.getBoolean("SWT_GTK_INPUT_HINT_NO_EMOJI"); long fixedHandle; + long firstFixedHandle = 0; + long keyController; long redrawWindow, enableWindow, provider; int drawCount, backgroundAlpha = 255; long dragGesture, zoomGesture, rotateGesture, panGesture; @@ -432,7 +434,7 @@ void hookEvents () { private void hookKeyboardAndFocusSignals(long focusHandle) { if (GTK.GTK4) { - long keyController = GTK4.gtk_event_controller_key_new(); + keyController = GTK4.gtk_event_controller_key_new(); GTK4.gtk_widget_add_controller(focusHandle, keyController); GTK.gtk_event_controller_set_propagation_phase(keyController, GTK.GTK_PHASE_CAPTURE); OS.g_signal_connect(keyController, OS.key_pressed, display.keyPressReleaseProc, KEY_PRESSED); @@ -3926,6 +3928,25 @@ void gtk4_focus_enter_event(long controller, long event) { } @Override +void gtk4_focus_window_event(long handle, long event) { + super.gtk4_focus_window_event(handle, event); + + if(firstFixedHandle == 0) { + long child = handle; + //3rd child of shell will be SWTFixed + for(int i = 0; i<3; i++) { + child = GTK4.gtk_widget_get_first_child(child); + } + firstFixedHandle = child != 0 ? child:0; + } + + if(firstFixedHandle !=0 && GTK.gtk_widget_has_focus(firstFixedHandle)) { + if(event == SWT.FocusIn)sendFocusEvent(SWT.FocusIn); + else sendFocusEvent(SWT.FocusOut); + } +} + +@Override long gtk_focus_out_event (long widget, long event) { // widget could be disposed at this point if (handle != 0) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java index 4dfc47fb1f..4eaa9e6cff 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java @@ -132,13 +132,13 @@ public class Display extends Device { Callback eventCallback; long eventProc, windowProc2, windowProc3, windowProc4, windowProc5, windowProc6; long changeValueProc; - long snapshotDrawProc, keyPressReleaseProc, focusProc, enterMotionProc, leaveProc, + long snapshotDrawProc, keyPressReleaseProc, focusProc, windowActiveProc, enterMotionProc, leaveProc, scrollProc, resizeProc, activateProc, gesturePressReleaseProc; long notifyProc; long computeSizeProc; Callback windowCallback2, windowCallback3, windowCallback4, windowCallback5, windowCallback6; Callback changeValue; - Callback snapshotDraw, keyPressReleaseCallback, focusCallback, enterMotionCallback, computeSizeCallback, + Callback snapshotDraw, keyPressReleaseCallback, focusCallback, windowActiveCallback, enterMotionCallback, computeSizeCallback, scrollCallback, leaveCallback, resizeCallback, activateCallback, gesturePressReleaseCallback; Callback notifyCallback; EventTable eventTable, filterTable; @@ -222,19 +222,6 @@ public class Display extends Device { SessionManagerListener sessionManagerListener; Runnable [] disposeList; - /* - * DBus objects to be freed upong Display release. Only public for use in - * other areas of SWT (i.e. WebKit). See bug 540060. - */ - /** @noreference */ - public java.util.List<Long> dBusServers = new ArrayList<>(); - /** @noreference */ - public java.util.List<Long> dBusAuthObservers = new ArrayList<>(); - /** @noreference */ - public java.util.List<Long> dBusGUIDS = new ArrayList<>(); - /** @noreference */ - public java.util.List<Long> dBusConnections = new ArrayList<>(); - /* Deferred Layout list */ Composite[] layoutDeferred; int layoutDeferredCount; @@ -3573,6 +3560,9 @@ void initializeCallbacks () { focusCallback = new Callback(this, "focusProc", void.class, new Type[] {long.class, long.class}); //$NON-NLS-1$ focusProc = focusCallback.getAddress(); + windowActiveCallback = new Callback(this, "windowActiveProc", void.class, new Type[] {long.class, long.class}); //$NON-NLS-1$ + windowActiveProc = windowActiveCallback.getAddress(); + enterMotionCallback = new Callback(this, "enterMotionProc", void.class, new Type[] { long.class, double.class, double.class, long.class}); //$NON-NLS-1$ enterMotionProc = enterMotionCallback.getAddress (); @@ -3850,44 +3840,6 @@ void initializeSessionManager() { } /** - * Some parts of SWT (like WebKit) use GDBus for IPC. Some of these objects - * cannot be disposed of in their own classes due to design challenges. - * In these instances we release them along with this Display. This ensures - * no Browser will be using them at disposal time. - */ -void releaseDBusServices() { - releaseSessionManager(); - for (long connection : dBusConnections) { - if (OS.g_dbus_connection_is_closed(connection)) continue; - long [] error = new long [1]; - boolean closed = OS.g_dbus_connection_close_sync(connection, 0, error); - if (error[0] != 0) { - String msg = extractFreeGError(error[0]); - System.err.println("SWT Display: error closing connection: " + msg); - } - if (closed) { - // Free this as we added a reference to it - OS.g_object_unref(connection); - } - } - for (long server : dBusServers) { - OS.g_dbus_server_stop(server); - OS.g_object_unref(server); - } - for (long authObserver : dBusAuthObservers) { - OS.g_object_unref(authObserver); - } - for (long guid : dBusGUIDS) { - OS.g_free(guid); - } - dBusConnections.clear(); - dBusServers.clear(); - dBusAuthObservers.clear(); - dBusGUIDS.clear(); - dBusServers = dBusAuthObservers = dBusGUIDS = dBusConnections = null; -} - -/** * Helper method to extract GError messages. Only call if the pointer is valid (i.e. non-zero). * * @param errorPtr pointer to the GError @@ -4670,7 +4622,6 @@ protected void release () { synchronizer.releaseSynchronizer (); synchronizer = null; - releaseDBusServices (); releaseSessionManager (); releaseDisplay (); super.release (); @@ -4701,6 +4652,10 @@ void releaseDisplay () { focusCallback = null; focusProc = 0; + windowActiveCallback.dispose(); + windowActiveCallback = null; + windowActiveProc = 0; + enterMotionCallback.dispose(); enterMotionCallback = null; enterMotionProc = 0; @@ -6130,13 +6085,18 @@ boolean scrollProc(long controller, double dx, double dy, long user_data) { return false; } -void focusProc(long controller, long user_data) { +void focusProc(long controller, long user_data) {; long handle = GTK.gtk_event_controller_get_widget(controller); Widget widget = getWidget(handle); if (widget != null) widget.focusProc(controller, user_data); } +void windowActiveProc(long handle, long user_data) {; + Widget widget = getWidget(handle); + if (widget != null) widget.windowActiveProc(handle, user_data); +} + boolean keyPressReleaseProc(long controller, int keyval, int keycode, int state, long user_data) { long handle = GTK.gtk_event_controller_get_widget(controller); Widget widget = getWidget(handle); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java index 23db4e2023..224734ad0e 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java @@ -947,6 +947,7 @@ void hookEvents () { } if (GTK.GTK4) { OS.g_signal_connect_closure (shellHandle, OS.close_request, display.getClosure (CLOSE_REQUEST), false); + OS.g_signal_connect(shellHandle, OS.notify_is_active, display.windowActiveProc, FOCUS_IN); long keyController = GTK4.gtk_event_controller_key_new(); GTK4.gtk_widget_add_controller(shellHandle, keyController); GTK.gtk_event_controller_set_propagation_phase(keyController, GTK.GTK_PHASE_TARGET); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java index 1e0ec9eca1..cc67a0eef6 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java @@ -2961,6 +2961,32 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr } } } + + GdkRectangle rendererRect = new GdkRectangle (); + GdkRectangle columnRect = new GdkRectangle (); + int y_offset; + { + /* + * SWT creates multiple renderers (kind of sub-columns) per column. + * For example: one for checkbox, one for image, one for text. + * 'background_area' argument in this function is area of currently + * painted renderer. However, for SWT.EraseItem and SWT.PaintItem, + * SWT wants entire column's area along with the event. There's api + * 'gtk_tree_view_get_background_area()' but it calculates item's + * rect in control, which will have wrong Y if item is rendered + * separately (for example, for drag image). + * The workaround is to take X range from api and Y range from argument. + */ + OS.memmove (rendererRect, background_area, GdkRectangle.sizeof); + + long path = GTK.gtk_tree_model_get_path (modelHandle, iter); + GTK.gtk_tree_view_get_background_area (handle, path, columnHandle, columnRect); + GTK.gtk_tree_path_free (path); + + y_offset = columnRect.y - rendererRect.y; + columnRect.y -= y_offset; + } + if (item != null) { if (GTK.GTK_IS_CELL_RENDERER_TOGGLE (cell) || (columnIndex != 0 || (style & SWT.CHECK) == 0)) { drawFlags = (int)flags; @@ -2980,10 +3006,7 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr if ((flags & GTK.GTK_CELL_RENDERER_FOCUSED) != 0) drawState |= SWT.FOCUSED; } - GdkRectangle rect = new GdkRectangle (); - long path = GTK.gtk_tree_model_get_path (modelHandle, iter); - GTK.gtk_tree_view_get_background_area (handle, path, columnHandle, rect); - GTK.gtk_tree_path_free (path); + Rectangle rect = columnRect.toRectangle (); if ((drawState & SWT.SELECTED) == 0) { if ((state & PARENT_BACKGROUND) != 0 || backgroundImage != null) { Control control = findBackgroundControl (); @@ -3029,23 +3052,36 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr if (cr != 0) { GdkRectangle r = new GdkRectangle(); GDK.gdk_cairo_get_clip_rectangle(cr, r); - Rectangle rect2 = DPIUtil.autoScaleDown(new Rectangle(rect.x, r.y, r.width, r.height)); + Rectangle rect2 = DPIUtil.autoScaleDown(rect); // Caveat: rect2 is necessary because GC#setClipping(Rectangle) got broken by bug 446075 gc.setClipping(rect2.x, rect2.y, rect2.width, rect2.height); } else { - Rectangle rect2 = DPIUtil.autoScaleDown(new Rectangle(rect.x, rect.y, rect.width, rect.height)); + Rectangle rect2 = DPIUtil.autoScaleDown(rect); // Caveat: rect2 is necessary because GC#setClipping(Rectangle) got broken by bug 446075 gc.setClipping(rect2.x, rect2.y, rect2.width, rect2.height); } + + // SWT.PaintItem/SWT.EraseItem often expect that event.y matches + // what 'event.item.getBounds()' returns. The workaround is to + // adjust coordinate system temporarily. Event event = new Event (); - event.item = item; - event.index = columnIndex; - event.gc = gc; - event.detail = drawState; - Rectangle eventRect = new Rectangle (rect.x, rect.y, rect.width, rect.height); - event.setBounds (DPIUtil.autoScaleDown (eventRect)); - sendEvent (SWT.EraseItem, event); + try { + Rectangle eventRect = new Rectangle (rect.x, rect.y, rect.width, rect.height); + + eventRect.y += y_offset; + Cairo.cairo_translate (cr, 0, -y_offset); + + event.item = item; + event.index = columnIndex; + event.gc = gc; + event.detail = drawState; + event.setBounds (DPIUtil.autoScaleDown (eventRect)); + sendEvent (SWT.EraseItem, event); + } finally { + Cairo.cairo_translate (cr, 0, y_offset); + } + drawForegroundRGBA = null; drawState = event.doit ? event.detail : 0; drawFlags &= ~(GTK.GTK_CELL_RENDERER_FOCUSED | GTK.GTK_CELL_RENDERER_SELECTED); @@ -3074,9 +3110,7 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr if ((drawState & SWT.BACKGROUND) != 0 && (drawState & SWT.SELECTED) == 0) { GC gc = getGC(cr); gc.setBackground (item.getBackground (columnIndex)); - GdkRectangle rect = new GdkRectangle (); - OS.memmove (rect, background_area, GdkRectangle.sizeof); - gc.fillRectangle(DPIUtil.autoScaleDown(new Rectangle(rect.x, rect.y, rect.width, rect.height))); + gc.fillRectangle (DPIUtil.autoScaleDown (rendererRect.toRectangle ())); gc.dispose (); } if ((drawState & SWT.FOREGROUND) != 0 || GTK.GTK_IS_CELL_RENDERER_TOGGLE (cell)) { @@ -3102,10 +3136,7 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr if (GTK.GTK_IS_CELL_RENDERER_TEXT (cell)) { if (hooks (SWT.PaintItem)) { if (wasSelected) drawState |= SWT.SELECTED; - GdkRectangle rect = new GdkRectangle (); - long path = GTK.gtk_tree_model_get_path (modelHandle, iter); - GTK.gtk_tree_view_get_background_area (handle, path, columnHandle, rect); - GTK.gtk_tree_path_free (path); + Rectangle rect = columnRect.toRectangle (); ignoreSize = true; int [] contentX = new int [1], contentWidth = new int [1]; gtk_cell_renderer_get_preferred_size (cell, handle, contentWidth, null); @@ -3149,18 +3180,30 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr gc.setFont (item.getFont (columnIndex)); if ((style & SWT.MIRRORED) != 0) rect.x = getClientWidth () - rect.width - rect.x; - Rectangle rect2 = DPIUtil.autoScaleDown(new Rectangle(rect.x, rect.y, rect.width, rect.height)); + Rectangle rect2 = DPIUtil.autoScaleDown(rect); // Caveat: rect2 is necessary because GC#setClipping(Rectangle) got broken by bug 446075 gc.setClipping(rect2.x, rect2.y, rect2.width, rect2.height); + // SWT.PaintItem/SWT.EraseItem often expect that event.y matches + // what 'event.item.getBounds()' returns. The workaround is to + // adjust coordinate system temporarily. Event event = new Event (); - event.item = item; - event.index = columnIndex; - event.gc = gc; - Rectangle eventRect = new Rectangle (rect.x + contentX [0], rect.y, contentWidth [0], rect.height); - event.setBounds (DPIUtil.autoScaleDown (eventRect)); - event.detail = drawState; - sendEvent (SWT.PaintItem, event); + try { + Rectangle eventRect = new Rectangle (rect.x + contentX [0], rect.y, contentWidth [0], rect.height); + + eventRect.y += y_offset; + Cairo.cairo_translate (cr, 0, -y_offset); + + event.item = item; + event.index = columnIndex; + event.gc = gc; + event.detail = drawState; + event.setBounds (DPIUtil.autoScaleDown (eventRect)); + sendEvent (SWT.PaintItem, event); + } finally { + Cairo.cairo_translate (cr, 0, y_offset); + } + gc.dispose(); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java index 723b591b09..bdf0b5fa2a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java @@ -59,6 +59,15 @@ public class ToolItem extends Item { boolean mapHooked; boolean enabled = true; + /** + * The image that is currently used by the tool item. + * Either the image set by client code via {@link #setImage(Image)} + * or {@link #setDisabledImage(Image)}, depending on button state. + * Or if the button is disabled but no disabled image is specified, + * a grayed out version of the "normal" image. + */ + Image currentImage; + /** * Constructs a new instance of this class given its parent * (which must be a <code>ToolBar</code>) and a style value @@ -657,6 +666,7 @@ long gtk_create_menu_proxy (long widget) { return 1; } + Image image = currentImage; if (image != null) { ImageList imageList = parent.imageList; if (imageList != null) { @@ -1261,6 +1271,7 @@ private void disposeDefault() { void _setImage (Image image) { if ((style & SWT.SEPARATOR) != 0) return; + currentImage = image; if (image != null) { ImageList imageList = parent.imageList; if (imageList == null) imageList = parent.imageList = new ImageList (); @@ -1293,15 +1304,7 @@ void _setImage (Image image) { * required to reset the proxy menu. Otherwise, the * old menuItem appears in the overflow menu. */ - if ((style & SWT.DROP_DOWN) != 0) { - if (GTK.GTK4) { - /* TODO: GTK4 have to implement our own overflow menu */ - } else { - proxyMenuItem = 0; - proxyMenuItem = GTK3.gtk_tool_item_retrieve_proxy_menu_item (handle); - OS.g_signal_connect(proxyMenuItem, OS.activate, ToolBar.menuItemSelectedFunc.getAddress(), handle); - } - } + recreateMenuProxy(); parent.relayout (); } @@ -1411,15 +1414,7 @@ public void setText (String string) { * required to reset the proxy menu. Otherwise, the * old menuItem appears in the overflow menu. */ - if ((style & SWT.DROP_DOWN) != 0) { - if (GTK.GTK4) { - /* TODO: GTK4 have to implement our own overflow menu */ - } else { - proxyMenuItem = 0; - proxyMenuItem = GTK3.gtk_tool_item_retrieve_proxy_menu_item (handle); - OS.g_signal_connect(proxyMenuItem, OS.activate, ToolBar.menuItemSelectedFunc.getAddress(), handle); - } - } + recreateMenuProxy(); parent.relayout (); } @@ -1474,15 +1469,7 @@ public void setToolTipText(String string) { * Otherwise, the old menuItem appears in the overflow * menu as a blank item. */ - if ((style & SWT.DROP_DOWN) != 0) { - if (GTK.GTK4) { - /* TODO: GTK4 have to implement our own overflow menu */ - } else { - proxyMenuItem = 0; - proxyMenuItem = GTK3.gtk_tool_item_retrieve_proxy_menu_item (handle); - OS.g_signal_connect(proxyMenuItem, OS.activate, ToolBar.menuItemSelectedFunc.getAddress(), handle); - } - } + recreateMenuProxy(); } /** @@ -1570,4 +1557,15 @@ long dpiChanged(long object, long arg0) { return 0; } + +private void recreateMenuProxy() { + if ((style & SWT.DROP_DOWN) != 0 || proxyMenuItem != 0) { + if (GTK.GTK4) { + /* TODO: GTK4 have to implement our own overflow menu */ + } else { + proxyMenuItem = 0; + proxyMenuItem = GTK3.gtk_tool_item_retrieve_proxy_menu_item (handle); + } + } +} }
\ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java index 77e6bdfd26..cab5bf8567 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java @@ -3168,6 +3168,32 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr } } } + + GdkRectangle rendererRect = new GdkRectangle (); + GdkRectangle columnRect = new GdkRectangle (); + int y_offset; + { + /* + * SWT creates multiple renderers (kind of sub-columns) per column. + * For example: one for checkbox, one for image, one for text. + * 'background_area' argument in this function is area of currently + * painted renderer. However, for SWT.EraseItem and SWT.PaintItem, + * SWT wants entire column's area along with the event. There's api + * 'gtk_tree_view_get_background_area()' but it calculates item's + * rect in control, which will have wrong Y if item is rendered + * separately (for example, for drag image). + * The workaround is to take X range from api and Y range from argument. + */ + OS.memmove (rendererRect, background_area, GdkRectangle.sizeof); + + long path = GTK.gtk_tree_model_get_path (modelHandle, iter); + GTK.gtk_tree_view_get_background_area (handle, path, columnHandle, columnRect); + GTK.gtk_tree_path_free (path); + + y_offset = columnRect.y - rendererRect.y; + columnRect.y -= y_offset; + } + if (item != null) { if (GTK.GTK_IS_CELL_RENDERER_TOGGLE (cell) || ( columnIndex != 0 || (style & SWT.CHECK) == 0)) { drawFlags = (int)flags; @@ -3187,10 +3213,7 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr if ((flags & GTK.GTK_CELL_RENDERER_FOCUSED) != 0) drawState |= SWT.FOCUSED; } - GdkRectangle rect = new GdkRectangle (); - long path = GTK.gtk_tree_model_get_path (modelHandle, iter); - GTK.gtk_tree_view_get_background_area (handle, path, columnHandle, rect); - GTK.gtk_tree_path_free (path); + Rectangle rect = columnRect.toRectangle (); // Use the x and width information from the Cairo context. See bug 535124. if (cr != 0) { GdkRectangle r2 = new GdkRectangle (); @@ -3243,21 +3266,34 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr if (cr != 0) { // Use the original rectangle, not the Cairo clipping for the y, width, and height values. // See bug 535124. - Rectangle rect2 = DPIUtil.autoScaleDown(new Rectangle(rect.x, rect.y, rect.width, rect.height)); + Rectangle rect2 = DPIUtil.autoScaleDown(rect); gc.setClipping(rect2.x, rect2.y, rect2.width, rect2.height); } else { - Rectangle rect2 = DPIUtil.autoScaleDown(new Rectangle(rect.x, rect.y, rect.width, rect.height)); + Rectangle rect2 = DPIUtil.autoScaleDown(rect); // Caveat: rect2 is necessary because GC#setClipping(Rectangle) got broken by bug 446075 gc.setClipping(rect2.x, rect2.y, rect2.width, rect2.height); } + + // SWT.PaintItem/SWT.EraseItem often expect that event.y matches + // what 'event.item.getBounds()' returns. The workaround is to + // adjust coordinate system temporarily. Event event = new Event (); - event.item = item; - event.index = columnIndex; - event.gc = gc; - Rectangle eventRect = new Rectangle (rect.x, rect.y, rect.width, rect.height); - event.setBounds (DPIUtil.autoScaleDown (eventRect)); - event.detail = drawState; - sendEvent (SWT.EraseItem, event); + try { + Rectangle eventRect = new Rectangle (rect.x, rect.y, rect.width, rect.height); + + eventRect.y += y_offset; + Cairo.cairo_translate (cr, 0, -y_offset); + + event.item = item; + event.index = columnIndex; + event.gc = gc; + event.detail = drawState; + event.setBounds (DPIUtil.autoScaleDown (eventRect)); + sendEvent (SWT.EraseItem, event); + } finally { + Cairo.cairo_translate (cr, 0, y_offset); + } + drawForegroundRGBA = null; drawState = event.doit ? event.detail : 0; drawFlags &= ~(GTK.GTK_CELL_RENDERER_FOCUSED | GTK.GTK_CELL_RENDERER_SELECTED); @@ -3275,12 +3311,9 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr } } if ((drawState & SWT.BACKGROUND) != 0 && (drawState & SWT.SELECTED) == 0) { - GC gc = getGC(cr); gc.setBackground (item.getBackground (columnIndex)); - GdkRectangle rect = new GdkRectangle (); - OS.memmove (rect, background_area, GdkRectangle.sizeof); - gc.fillRectangle(DPIUtil.autoScaleDown(new Rectangle(rect.x, rect.y, rect.width, rect.height))); + gc.fillRectangle (DPIUtil.autoScaleDown (rendererRect.toRectangle ())); gc.dispose (); } if ((drawState & SWT.FOREGROUND) != 0 || GTK.GTK_IS_CELL_RENDERER_TOGGLE (cell)) { @@ -3306,10 +3339,7 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr if (GTK.GTK_IS_CELL_RENDERER_TEXT (cell)) { if (hooks (SWT.PaintItem)) { if (wasSelected) drawState |= SWT.SELECTED; - GdkRectangle rect = new GdkRectangle (); - long path = GTK.gtk_tree_model_get_path (modelHandle, iter); - GTK.gtk_tree_view_get_background_area (handle, path, columnHandle, rect); - GTK.gtk_tree_path_free (path); + Rectangle rect = columnRect.toRectangle (); ignoreSize = true; int [] contentX = new int [1], contentWidth = new int [1]; gtk_cell_renderer_get_preferred_size (cell, handle, contentWidth, null); @@ -3339,7 +3369,7 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr /* indent */ GdkRectangle rect3 = new GdkRectangle (); GTK.gtk_widget_realize (handle); - path = GTK.gtk_tree_model_get_path (modelHandle, iter); + long path = GTK.gtk_tree_model_get_path (modelHandle, iter); GTK.gtk_tree_view_get_cell_area (handle, path, columnHandle, rect3); GTK.gtk_tree_path_free (path); contentX[0] += rect3.x; @@ -3362,18 +3392,30 @@ void rendererRender (long cell, long cr, long snapshot, long widget, long backgr rect.x = getClientWidth () - rect.width - rect.x; } - Rectangle rect2 = DPIUtil.autoScaleDown(new Rectangle(rect.x, rect.y, rect.width, rect.height)); + Rectangle rect2 = DPIUtil.autoScaleDown(rect); // Caveat: rect2 is necessary because GC#setClipping(Rectangle) got broken by bug 446075 gc.setClipping(rect2.x, rect2.y, rect2.width, rect2.height); + // SWT.PaintItem/SWT.EraseItem often expect that event.y matches + // what 'event.item.getBounds()' returns. The workaround is to + // adjust coordinate system temporarily. Event event = new Event (); - event.item = item; - event.index = columnIndex; - event.gc = gc; - Rectangle eventRect = new Rectangle (rect.x + contentX [0], rect.y, contentWidth [0], rect.height); - event.setBounds (DPIUtil.autoScaleDown (eventRect)); - event.detail = drawState; - sendEvent(SWT.PaintItem, event); + try { + Rectangle eventRect = new Rectangle (rect.x + contentX [0], rect.y, contentWidth [0], rect.height); + + eventRect.y += y_offset; + Cairo.cairo_translate (cr, 0, -y_offset); + + event.item = item; + event.index = columnIndex; + event.gc = gc; + event.detail = drawState; + event.setBounds (DPIUtil.autoScaleDown (eventRect)); + sendEvent (SWT.PaintItem, event); + } finally { + Cairo.cairo_translate (cr, 0, y_offset); + } + gc.dispose(); } } @@ -3500,7 +3542,7 @@ void setItemCount (long parentIter, int count) { /** * Sets the number of root-level items contained in the receiver. * <p> - * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(org.eclipse.swt.widgets.Tree,int,int)} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} * and {@link TreeItem#setItemCount} * * @param count the number of items diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java index c7545f6658..d4f94ac010 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java @@ -51,8 +51,8 @@ public class TreeItem extends Item { * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>. * Item is inserted as last direct child of the tree. * <p> - * The fastest way to insert many items is documented in {@link org.eclipse.swt.widgets.TreeItem#TreeItem(Tree,int,int)} - * and {@link org.eclipse.swt.widgets.TreeItem#setItemCount} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} + * and {@link TreeItem#setItemCount} * * @param parent a tree control which will be the parent of the new instance (cannot be null) * @param style no styles are currently supported, pass SWT.NONE @@ -110,8 +110,8 @@ public TreeItem (Tree parent, int style, int index) { * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>. * Item is inserted as last direct child of the specified <code>TreeItem</code>. * <p> - * The fastest way to insert many items is documented in {@link org.eclipse.swt.widgets.TreeItem#TreeItem(Tree,int,int)} - * and {@link org.eclipse.swt.widgets.TreeItem#setItemCount} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} + * and {@link TreeItem#setItemCount} * * @param parentItem a tree control which will be the parent of the new instance (cannot be null) * @param style no styles are currently supported, pass SWT.NONE @@ -136,8 +136,8 @@ public TreeItem (TreeItem parentItem, int style) { * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>. * Item is inserted as <code>index</code> direct child of the specified <code>TreeItem</code>. * <p> - * The fastest way to insert many items is documented in {@link org.eclipse.swt.widgets.TreeItem#TreeItem(Tree,int,int)} - * and {@link org.eclipse.swt.widgets.TreeItem#setItemCount} + * The fastest way to insert many items is documented in {@link TreeItem#TreeItem(Tree,int,int)} + * and {@link TreeItem#setItemCount} * * @param parentItem a tree control which will be the parent of the new instance (cannot be null) * @param style no styles are currently supported, pass SWT.NONE diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java index 0c301d5b1e..3aa2083ff4 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java @@ -255,7 +255,9 @@ public abstract class Widget { /** * Prevents uninitialized instances from being created outside the package. */ -Widget () {} +Widget () { + notifyCreationTracker(); +} /** * Constructs a new instance of this class given its parent @@ -292,6 +294,7 @@ public Widget (Widget parent, int style) { this.style = style; display = parent.display; reskinWidget (); + notifyCreationTracker(); } void _addListener (int eventType, Listener listener) { @@ -793,6 +796,14 @@ void gtk4_key_release_event(long controller, int keyval, int keycode, int state, void gtk4_focus_enter_event(long controller, long event) {} /** + * @param handle the handle of the window that caused the event + * @param event the type of event, should be FocusIn or FocusOut + */ +void gtk4_focus_window_event(long handle, long event) { + gtk_focus_in_event (handle, event); +} + +/** * @param controller the corresponding controller responsible for capturing the event * @param event the GdkEvent captured */ @@ -1345,6 +1356,7 @@ void release (boolean destroy) { releaseHandle (); } } + notifyDisposalTracker(); } } @@ -1583,7 +1595,8 @@ char [] sendIMKeyEvent (int type, long event, char [] chars) { int index = 0, count = 0, state = 0; long ptr = 0; if (event == 0) { - ptr = GTK3.gtk_get_current_event (); + long controller = Control.getControl(this.handle).keyController; + ptr = GTK.GTK4 ? GTK4.gtk_event_controller_get_current_event(controller):GTK3.gtk_get_current_event (); if (ptr != 0) { int eventType = GDK.gdk_event_get_event_type(ptr); eventType = Control.fixGdkEventTypeValues(eventType); @@ -1603,9 +1616,13 @@ char [] sendIMKeyEvent (int type, long event, char [] chars) { break; } } else { - int [] buffer = new int [1]; - GTK3.gtk_get_current_event_state (buffer); - state = buffer [0]; + if(GTK.GTK4) { + state = GTK4.gtk_event_controller_get_current_event_state(controller); + } else { + int [] buffer = new int [1]; + GTK3.gtk_get_current_event_state (buffer); + state = buffer [0]; + } } } else { ptr = event; @@ -1627,13 +1644,13 @@ char [] sendIMKeyEvent (int type, long event, char [] chars) { * the key by returning null. */ if (isDisposed ()) { - if (ptr != 0 && ptr != event) gdk_event_free (ptr); + if (ptr != 0 && ptr != event && !GTK.GTK4) gdk_event_free (ptr); return null; } if (javaEvent.doit) chars [count++] = chars [index]; index++; } - if (ptr != 0 && ptr != event) gdk_event_free (ptr); + if (ptr != 0 && ptr != event && !GTK.GTK4) gdk_event_free (ptr); if (count == 0) return null; if (index != count) { char [] result = new char [count]; @@ -2295,6 +2312,12 @@ void focusProc(long controller, long user_data) { } } +void windowActiveProc(long handle, long user_data) { + long eventType = GTK.gtk_window_is_active(handle) ? SWT.FocusIn:SWT.FocusOut; + + gtk4_focus_window_event(handle, eventType); +} + boolean keyPressReleaseProc(long controller, int keyval, int keycode, int state, long user_data) { long event = GTK4.gtk_event_controller_get_current_event(controller); @@ -2520,4 +2543,17 @@ void gtk_widget_size_allocate (long widget, GtkAllocation allocation, int baseli GTK3.gtk_widget_size_allocate(widget, allocation); } } + +void notifyCreationTracker() { + if (WidgetSpy.isEnabled) { + WidgetSpy.getInstance().widgetCreated(this); + } +} + +void notifyDisposalTracker() { + if (WidgetSpy.isEnabled) { + WidgetSpy.getInstance().widgetDisposed(this); + } +} + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java index a89ddf86f9..b79fe461f5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java @@ -1220,12 +1220,14 @@ void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, data.hNullBitmap = 0; } } - if (srcImage.alpha != -1 || srcImage.alphaData != null) { - drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); + boolean isDib = bm.bmBits != 0; + int depth = bm.bmPlanes * bm.bmBitsPixel; + if (isDib && depth == 32) { + drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); } else if (srcImage.transparentPixel != -1) { drawBitmapTransparent(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); } else { - drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); + drawBitmapColor(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); } if (mustRestore) { long hOldBitmap = OS.SelectObject(memGC.handle, srcImage.handle); @@ -1233,35 +1235,15 @@ void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, } } -void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) { - /* Simple cases */ - if (srcImage.alpha == 0) return; - if (srcImage.alpha == 255) { - drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight); - return; - } - +void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { boolean alphaBlendSupport = true; boolean isPrinter = OS.GetDeviceCaps(handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER; + int sourceAlpha = -1; if (isPrinter) { int caps = OS.GetDeviceCaps(handle, OS.SHADEBLENDCAPS); if (caps != 0) { - if (srcImage.alpha != -1) { - alphaBlendSupport = (caps & OS.SB_CONST_ALPHA) != 0; - } else { - alphaBlendSupport = (caps & OS.SB_PIXEL_ALPHA) != 0; - } - } - } - if (alphaBlendSupport) { - BLENDFUNCTION blend = new BLENDFUNCTION(); - blend.BlendOp = OS.AC_SRC_OVER; - long srcHdc = OS.CreateCompatibleDC(handle); - long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle); - if (srcImage.alpha != -1) { - blend.SourceConstantAlpha = (byte)srcImage.alpha; - OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, blend); - } else { + long srcHdc = OS.CreateCompatibleDC(handle); + long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle); long memDib = Image.createDIB(srcWidth, srcHeight, 32); if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES); long memHdc = OS.CreateCompatibleDC(handle); @@ -1271,34 +1253,41 @@ void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY); byte[] srcData = new byte[dibBM.bmWidthBytes * dibBM.bmHeight]; OS.MoveMemory(srcData, dibBM.bmBits, srcData.length); - final int apinc = imgWidth - srcWidth; - int ap = srcY * imgWidth + srcX, sp = 0; - byte[] alphaData = srcImage.alphaData; - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int alpha = alphaData[ap++] & 0xff; - int r = ((srcData[sp + 0] & 0xFF) * alpha) + 128; - r = (r + (r >> 8)) >> 8; - int g = ((srcData[sp + 1] & 0xFF) * alpha) + 128; - g = (g + (g >> 8)) >> 8; - int b = ((srcData[sp + 2] & 0xFF) * alpha) + 128; - b = (b + (b >> 8)) >> 8; - srcData[sp+0] = (byte)r; - srcData[sp+1] = (byte)g; - srcData[sp+2] = (byte)b; - srcData[sp+3] = (byte)alpha; - sp += 4; + int size = srcData.length; + sourceAlpha = srcData[3] & 0xFF; + for (int sp = 7; sp < size; sp += 4) { + int currentAlpha = srcData[sp] & 0xFF; + if (sourceAlpha != currentAlpha) { + sourceAlpha = -1; + break; } - ap += apinc; } - OS.MoveMemory(dibBM.bmBits, srcData, srcData.length); - blend.SourceConstantAlpha = (byte)0xff; - blend.AlphaFormat = OS.AC_SRC_ALPHA; - OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, blend); OS.SelectObject(memHdc, oldMemBitmap); OS.DeleteDC(memHdc); OS.DeleteObject(memDib); + OS.SelectObject(srcHdc, oldSrcBitmap); + OS.DeleteDC(srcHdc); + if (sourceAlpha != -1) { + if (sourceAlpha == 0) return; + if (sourceAlpha == 255) { + drawBitmapColor(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple); + return; + } + alphaBlendSupport = (caps & OS.SB_CONST_ALPHA) != 0; + } + else { + alphaBlendSupport = (caps & OS.SB_PIXEL_ALPHA) != 0; + } } + } + if (alphaBlendSupport) { + BLENDFUNCTION blend = new BLENDFUNCTION(); + blend.BlendOp = OS.AC_SRC_OVER; + long srcHdc = OS.CreateCompatibleDC(handle); + long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle); + blend.SourceConstantAlpha = (byte)sourceAlpha; + blend.AlphaFormat = OS.AC_SRC_ALPHA; + OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, srcHdc, 0, 0, srcWidth, srcHeight, blend); OS.SelectObject(srcHdc, oldSrcBitmap); OS.DeleteDC(srcHdc); return; @@ -1348,26 +1337,6 @@ void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe byte[] srcData = new byte[sizeInBytes]; OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes); - /* Merge the alpha channel in place */ - int alpha = srcImage.alpha; - final boolean hasAlphaChannel = (srcImage.alpha == -1); - if (hasAlphaChannel) { - final int apinc = imgWidth - srcWidth; - final int spinc = dibBM.bmWidthBytes - srcWidth * 4; - int ap = srcY * imgWidth + srcX, sp = 3; - byte[] alphaData = srcImage.alphaData; - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - srcData[sp] = alphaData[ap++]; - sp += 4; - } - ap += apinc; - sp += spinc; - } - } - - /* Scale the foreground pixels with alpha */ - OS.MoveMemory(dibBM.bmBits, srcData, sizeInBytes); /* * When drawing to a printer, StretchBlt does not correctly stretch if * the source and destination HDCs are the same. The workaround is to @@ -1403,10 +1372,10 @@ void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe int dp = 0; for (int y = 0; y < destHeight; ++y) { for (int x = 0; x < destWidth; ++x) { - if (hasAlphaChannel) alpha = srcData[dp + 3] & 0xff; - destData[dp] += ((srcData[dp] & 0xff) - (destData[dp] & 0xff)) * alpha / 255; - destData[dp + 1] += ((srcData[dp + 1] & 0xff) - (destData[dp + 1] & 0xff)) * alpha / 255; - destData[dp + 2] += ((srcData[dp + 2] & 0xff) - (destData[dp + 2] & 0xff)) * alpha / 255; + int alpha = srcData[dp + 3] & 0xFF; + destData[dp ] += (srcData[dp ] & 0xFF) - (destData[dp ] & 0xFF) * alpha / 255; + destData[dp + 1] += (srcData[dp + 1] & 0xFF) - (destData[dp + 1] & 0xFF) * alpha / 255; + destData[dp + 2] += (srcData[dp + 2] & 0xFF) - (destData[dp + 2] & 0xFF) * alpha / 255; dp += 4; } dp += dpinc; @@ -1642,7 +1611,7 @@ void drawBitmapTransparent(Image srcImage, int srcX, int srcY, int srcWidth, int OS.DeleteDC(srcHdc); } -void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) { +void drawBitmapColor(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { long srcHdc = OS.CreateCompatibleDC(handle); long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle); int dwRop = OS.GetROP2(handle) == OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index c0766ccab7..1b38c70d27 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -112,16 +112,6 @@ public final class Image extends Resource implements Drawable { GC memGC; /** - * the alpha data for the image - */ - byte[] alphaData; - - /** - * the global alpha value to be used for every pixel - */ - int alpha = -1; - - /** * ImageFileNameProvider to provide file names at various Zoom levels */ private ImageFileNameProvider imageFileNameProvider; @@ -283,11 +273,6 @@ public Image(Device device, Image srcImage, int flag) { device.internal_dispose_GC(hDC, null); transparentPixel = srcImage.transparentPixel; - alpha = srcImage.alpha; - if (srcImage.alphaData != null) { - alphaData = new byte[srcImage.alphaData.length]; - System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length); - } break; case SWT.ICON: handle = OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0); @@ -977,9 +962,12 @@ void initNative(String filename) { long [] createGdipImage() { switch (type) { case SWT.BITMAP: { - if (alpha != -1 || alphaData != null || transparentPixel != -1) { - BITMAP bm = new BITMAP(); - OS.GetObject(handle, BITMAP.sizeof, bm); + BITMAP bm = new BITMAP(); + OS.GetObject(handle, BITMAP.sizeof, bm); + int depth = bm.bmPlanes * bm.bmBitsPixel; + boolean isDib = bm.bmBits != 0; + boolean hasAlpha = isDib && depth == 32; + if (hasAlpha || transparentPixel != -1) { int imgWidth = bm.bmWidth; int imgHeight = bm.bmHeight; long hDC = device.internal_new_GC(null); @@ -993,8 +981,14 @@ long [] createGdipImage() { OS.GetObject(memDib, BITMAP.sizeof, dibBM); int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight; OS.BitBlt(memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY); + long hHeap = OS.GetProcessHeap(); + long pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, sizeInBytes); + if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES); byte red = 0, green = 0, blue = 0; - if (transparentPixel != -1) { + if (hasAlpha) { + OS.MoveMemory(pixels, bm.bmBits, sizeInBytes); + } + else { if (bm.bmBitsPixel <= 8) { byte[] color = new byte[4]; OS.GetDIBColorTable(srcHdc, transparentPixel, 1, color); @@ -1029,30 +1023,8 @@ long [] createGdipImage() { break; } } - } - OS.SelectObject(srcHdc, oldSrcBitmap); - OS.SelectObject(memHdc, oldMemBitmap); - OS.DeleteObject(srcHdc); - OS.DeleteObject(memHdc); - byte[] srcData = new byte[sizeInBytes]; - OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes); - OS.DeleteObject(memDib); - device.internal_dispose_GC(hDC, null); - if (alpha != -1) { - for (int y = 0, dp = 0; y < imgHeight; ++y) { - for (int x = 0; x < imgWidth; ++x) { - srcData[dp + 3] = (byte)alpha; - dp += 4; - } - } - } else if (alphaData != null) { - for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) { - for (int x = 0; x < imgWidth; ++x) { - srcData[dp + 3] = alphaData[ap++]; - dp += 4; - } - } - } else if (transparentPixel != -1) { + byte[] srcData = new byte[sizeInBytes]; + OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes); for (int y = 0, dp = 0; y < imgHeight; ++y) { for (int x = 0; x < imgWidth; ++x) { if (srcData[dp] == blue && srcData[dp + 1] == green && srcData[dp + 2] == red) { @@ -1063,12 +1035,15 @@ long [] createGdipImage() { dp += 4; } } + OS.MoveMemory(pixels, srcData, sizeInBytes); } - long hHeap = OS.GetProcessHeap(); - long pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length); - if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES); - OS.MoveMemory(pixels, srcData, sizeInBytes); - return new long []{Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels), pixels}; + OS.SelectObject(srcHdc, oldSrcBitmap); + OS.SelectObject(memHdc, oldMemBitmap); + OS.DeleteObject(srcHdc); + OS.DeleteObject(memHdc); + OS.DeleteObject(memDib); + int pixelFormat = hasAlpha ? Gdip.PixelFormat32bppPARGB : Gdip.PixelFormat32bppARGB; + return new long []{Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, pixelFormat, pixels), pixels}; } return new long []{Gdip.Bitmap_new(handle, 0), 0}; } @@ -1633,10 +1608,32 @@ public ImageData getImageDataAtCurrentZoom() { /* Construct and return the ImageData */ ImageData imageData = new ImageData(width, height, depth, palette, 4, data); imageData.transparentPixel = this.transparentPixel; - imageData.alpha = alpha; - if (alpha == -1 && alphaData != null) { - imageData.alphaData = new byte[alphaData.length]; - System.arraycopy(alphaData, 0, imageData.alphaData, 0, alphaData.length); + if (isDib && depth == 32) { + byte straightData[] = new byte[imageSize]; + byte alphaData[] = new byte[width * height]; + boolean validAlpha = true; + for (int ap = 0, dp = 0; validAlpha && ap < alphaData.length; ap++, dp += 4) { + int b = data[dp ] & 0xFF; + int g = data[dp + 1] & 0xFF; + int r = data[dp + 2] & 0xFF; + int a = data[dp + 3] & 0xFF; + alphaData[ap] = (byte) a; + validAlpha = validAlpha && b <= a && g <= a && r <= a; + if (a != 0) { + straightData[dp ] = (byte) (((b * 0xFF) + a / 2) / a); + straightData[dp + 1] = (byte) (((g * 0xFF) + a / 2) / a); + straightData[dp + 2] = (byte) (((r * 0xFF) + a / 2) / a); + } + } + if (validAlpha) { + imageData.data = straightData; + imageData.alphaData = alphaData; + } + else { + for (int dp = 3; dp < imageSize; dp += 4) { + data[dp] = (byte) 0xFF; + } + } } return imageData; } @@ -1684,6 +1681,7 @@ void init(int width, int height) { int planes = OS.GetDeviceCaps(hDC, OS.PLANES); int depth = bits * planes; if (depth < 16) depth = 16; + if (depth > 24) depth = 24; handle = createDIB(width, height, depth); } if (handle != 0) { @@ -1729,6 +1727,9 @@ static long [] init(Device device, Image image, ImageData i) { img.alphaData = i.alphaData; i = img; } + + boolean hasAlpha = i.alpha != -1 || i.alphaData != null; + /* * Windows supports 16-bit mask of (0x7C00, 0x3E0, 0x1F), * 24-bit mask of (0xFF0000, 0xFF00, 0xFF) and 32-bit mask @@ -1745,51 +1746,56 @@ static long [] init(Device device, Image image, ImageData i) { int newOrder = ImageData.MSB_FIRST; PaletteData newPalette = null; - switch (i.depth) { - case 8: - /* - * Bug 566545. Usually each color mask selects a different part of the pixel - * value to encode the according color. In this common case it is rather trivial - * to convert an 8-bit direct color image to the Windows supported 16-bit image. - * However there is no enforcement for the color masks to be disjunct. For - * example an 8-bit image where all color masks select the same 8-bit of pixel - * value (mask = 0xFF and shift = 0 for all colors) results in a very efficient - * 8-bit gray-scale image without the need of defining a color table. - * - * That's why we need to calculate the actual required depth if all colors are - * stored non-overlapping which might require 24-bit instead of the usual - * expected 16-bit. - */ - int minDepth = ImageData.getChannelWidth(redMask, palette.redShift) - + ImageData.getChannelWidth(greenMask, palette.greenShift) - + ImageData.getChannelWidth(blueMask, palette.blueShift); - if (minDepth <= 16) { - newDepth = 16; + if (hasAlpha) { + newDepth = 32; + newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); + } + else { + switch (i.depth) { + case 8: + /* + * Bug 566545. Usually each color mask selects a different part of the pixel + * value to encode the according color. In this common case it is rather trivial + * to convert an 8-bit direct color image to the Windows supported 16-bit image. + * However there is no enforcement for the color masks to be disjunct. For + * example an 8-bit image where all color masks select the same 8-bit of pixel + * value (mask = 0xFF and shift = 0 for all colors) results in a very efficient + * 8-bit gray-scale image without the need of defining a color table. + * + * That's why we need to calculate the actual required depth if all colors are + * stored non-overlapping which might require 24-bit instead of the usual + * expected 16-bit. + */ + int minDepth = ImageData.getChannelWidth(redMask, palette.redShift) + + ImageData.getChannelWidth(greenMask, palette.greenShift) + + ImageData.getChannelWidth(blueMask, palette.blueShift); + if (minDepth <= 16) { + newDepth = 16; + newOrder = ImageData.LSB_FIRST; + newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F); + } else { + newDepth = 24; + newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000); + } + break; + case 16: newOrder = ImageData.LSB_FIRST; - newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F); - } else { + if (!(redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) { + newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F); + } + break; + case 24: + if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) { + newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000); + } + break; + case 32: newDepth = 24; newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000); - } - break; - case 16: - newOrder = ImageData.LSB_FIRST; - if (!(redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) { - newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F); - } - break; - case 24: - if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) { - newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000); - } - break; - case 32: - if (!(redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) { - newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); - } - break; - default: - SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); + break; + default: + SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); + } } if (newPalette != null) { ImageData img = new ImageData(i.width, i.height, newDepth, newPalette); @@ -1808,6 +1814,73 @@ static long [] init(Device device, Image image, ImageData i) { i = img; } } + else if (hasAlpha) { + int newDepth = 32; + PaletteData newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); + int newOrder = ImageData.MSB_FIRST; + RGB[] rgbs = i.palette.getRGBs(); + int length = rgbs.length; + byte[] srcReds = new byte[length]; + byte[] srcGreens = new byte[length]; + byte[] srcBlues = new byte[length]; + for (int j = 0; j < rgbs.length; j++) { + RGB rgb = rgbs[j]; + if (rgb == null) continue; + srcReds[j] = (byte)rgb.red; + srcGreens[j] = (byte)rgb.green; + srcBlues[j] = (byte)rgb.blue; + } + ImageData img = new ImageData(i.width, i.height, newDepth, newPalette); + ImageData.blit(ImageData.BLIT_SRC, + i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, srcReds, srcGreens, srcBlues, + ImageData.ALPHA_OPAQUE, null, 0, 0, 0, + img.data, img.depth, img.bytesPerLine, newOrder, 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask, + false, false); + + if (i.transparentPixel != -1) { + img.transparentPixel = newPalette.getPixel(i.palette.getRGB(i.transparentPixel)); + } + img.maskPad = i.maskPad; + img.maskData = i.maskData; + img.alpha = i.alpha; + img.alphaData = i.alphaData; + i = img; + } + if (i.alpha != -1) { + int alpha = i.alpha & 0xFF; + byte[] data = i.data; + for (int dp = 0; dp < i.data.length; dp += 4) { + /* pre-multiplied alpha */ + int r = ((data[dp ] & 0xFF) * alpha) + 128; + r = (r + (r >> 8)) >> 8; + int g = ((data[dp + 1] & 0xFF) * alpha) + 128; + g = (g + (g >> 8)) >> 8; + int b = ((data[dp + 2] & 0xFF) * alpha) + 128; + b = (b + (b >> 8)) >> 8; + data[dp ] = (byte) b; + data[dp + 1] = (byte) g; + data[dp + 2] = (byte) r; + data[dp + 3] = (byte) alpha; + } + } + else if (i.alphaData != null) { + byte[] data = i.data; + for (int ap = 0, dp = 0; dp < i.data.length; ap++, dp += 4) { + /* pre-multiplied alpha */ + int a = i.alphaData[ap] & 0xFF; + int r = ((data[dp ] & 0xFF) * a) + 128; + r = (r + (r >> 8)) >> 8; + int g = ((data[dp + 1] & 0xFF) * a) + 128; + g = (g + (g >> 8)) >> 8; + int b = ((data[dp + 2] & 0xFF) * a) + 128; + b = (b + (b >> 8)) >> 8; + data[dp ] = (byte) r; + data[dp + 1] = (byte) g; + data[dp + 2] = (byte) b; + data[dp + 3] = (byte) a; + } + } + /* Construct bitmap info header by hand */ RGB[] rgbs = i.palette.getRGBs(); BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); @@ -1894,14 +1967,6 @@ static long [] init(Device device, Image image, ImageData i) { image.handle = hDib; image.type = SWT.BITMAP; image.transparentPixel = i.transparentPixel; - if (image.transparentPixel == -1) { - image.alpha = i.alpha; - if (i.alpha == -1 && i.alphaData != null) { - int length = i.alphaData.length; - image.alphaData = new byte[length]; - System.arraycopy(i.alphaData, 0, image.alphaData, 0, length); - } - } } } return result; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java index 4f8ae61709..1c71538df3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java @@ -2871,10 +2871,12 @@ StyleItem[] merge (long items, int itemCount) { } } + boolean mayNeedSplit = true; int styleLimit = translateOffset(styles[styleIndex + 1].start); if (styleLimit <= itemLimit) { int runLen = styleLimit - start; if (runLen < MAX_RUN_LENGTH) { + mayNeedSplit = false; styleIndex++; start = styleLimit; if (start < itemLimit && 0 < start && start < end) { @@ -2888,7 +2890,7 @@ StyleItem[] merge (long items, int itemCount) { } } int runLen = itemLimit - start; - if (runLen > MAX_RUN_LENGTH) { + if (mayNeedSplit && runLen > MAX_RUN_LENGTH) { start += splitLongRun(item); } else if (itemLimit <= styleLimit) { itemIndex = nextItemIndex; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java index ff2a39ff6c..34ccb923d2 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java @@ -151,10 +151,16 @@ long copyWithAlpha (long hBitmap, int background, byte[] alphaData, int destWidt /* Merge the alpha channel in place */ if (alphaData != null) { int spinc = dibBM.bmWidthBytes - srcWidth * 4; - int ap = 0, sp = 3; + int ap = 0, sp = 0; for (int y = 0; y < srcHeight; ++y) { for (int x = 0; x < srcWidth; ++x) { - srcData [sp] = alphaData [ap++]; + int a = alphaData [ap++] & 0xFF; + if (a != 0) { + srcData [sp ] = (byte)((((srcData [sp ] & 0xFF) * 0xFF) + a / 2) / a); + srcData [sp + 1] = (byte)((((srcData [sp + 1] & 0xFF) * 0xFF) + a / 2) / a); + srcData [sp + 2] = (byte)((((srcData [sp + 2] & 0xFF) * 0xFF) + a / 2) / a); + } + srcData [sp + 3] = (byte)a; sp += 4; } sp += spinc; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java index 82516a201f..592eaedc40 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java @@ -1433,6 +1433,71 @@ LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) { return super.wmNotifyChild (hdr, wParam, lParam); } +static int getThemeStateId(int style, boolean pressed, boolean enabled) { + int direction = style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT); + + /* + * Feature in Windows. DrawThemeBackground() does not mirror the drawing. + * The fix is switch left to right and right to left. + */ + if ((style & SWT.MIRRORED) != 0) { + if (direction == SWT.LEFT) { + direction = SWT.RIGHT; + } else if (direction == SWT.RIGHT) { + direction = SWT.LEFT; + } + } + + /* + * On Win11, scrollbars no longer show arrows by default. + * Arrows only show up when hot/disabled/pushed. + * The workaround is to use hot image in place of default. + */ + boolean hot = false; + if (OS.WIN32_BUILD >= OS.WIN32_BUILD_WIN11_21H2) { + if (!pressed && enabled) { + hot = true; + } + } + + if (hot) { + switch (direction) { + case SWT.UP: return OS.ABS_UPHOT; + case SWT.DOWN: return OS.ABS_DOWNHOT; + case SWT.LEFT: return OS.ABS_LEFTHOT; + case SWT.RIGHT: return OS.ABS_RIGHTHOT; + } + } + + if (pressed) { + switch (direction) { + case SWT.UP: return OS.ABS_UPPRESSED; + case SWT.DOWN: return OS.ABS_DOWNPRESSED; + case SWT.LEFT: return OS.ABS_LEFTPRESSED; + case SWT.RIGHT: return OS.ABS_RIGHTPRESSED; + } + } + + if (!enabled) { + switch (direction) { + case SWT.UP: return OS.ABS_UPDISABLED; + case SWT.DOWN: return OS.ABS_DOWNDISABLED; + case SWT.LEFT: return OS.ABS_LEFTDISABLED; + case SWT.RIGHT: return OS.ABS_RIGHTDISABLED; + } + } + + switch (direction) { + case SWT.UP: return OS.ABS_UPNORMAL; + case SWT.DOWN: return OS.ABS_DOWNNORMAL; + case SWT.LEFT: return OS.ABS_LEFTNORMAL; + case SWT.RIGHT: return OS.ABS_RIGHTNORMAL; + } + + // Have some sane value if all else fails + return OS.ABS_LEFTNORMAL; +} + @Override LRESULT wmDrawChild (long wParam, long lParam) { if ((style & SWT.ARROW) == 0) return super.wmDrawChild (wParam, lParam); @@ -1441,29 +1506,9 @@ LRESULT wmDrawChild (long wParam, long lParam) { RECT rect = new RECT (); OS.SetRect (rect, struct.left, struct.top, struct.right, struct.bottom); if (OS.IsAppThemed ()) { - int iStateId = OS.ABS_LEFTNORMAL; - switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) { - case SWT.UP: iStateId = OS.ABS_UPNORMAL; break; - case SWT.DOWN: iStateId = OS.ABS_DOWNNORMAL; break; - case SWT.LEFT: iStateId = OS.ABS_LEFTNORMAL; break; - case SWT.RIGHT: iStateId = OS.ABS_RIGHTNORMAL; break; - } - /* - * Feature in Windows. DrawThemeBackground() does not mirror the drawing. - * The fix is switch left to right and right to left. - */ - if ((style & SWT.MIRRORED) != 0) { - if ((style & (SWT.LEFT | SWT.RIGHT)) != 0) { - iStateId = iStateId == OS.ABS_RIGHTNORMAL ? OS.ABS_LEFTNORMAL : OS.ABS_RIGHTNORMAL; - } - } - /* - * NOTE: The normal, hot, pressed and disabled state is - * computed relying on the fact that the increment between - * the direction states is invariant (always separated by 4). - */ - if (!getEnabled ()) iStateId += OS.ABS_UPDISABLED - OS.ABS_UPNORMAL; - if ((struct.itemState & OS.ODS_SELECTED) != 0) iStateId += OS.ABS_UPPRESSED - OS.ABS_UPNORMAL; + boolean pressed = ((struct.itemState & OS.ODS_SELECTED) != 0); + boolean enabled = getEnabled (); + int iStateId = getThemeStateId(style, pressed, enabled); OS.DrawThemeBackground (display.hScrollBarTheme (), struct.hDC, OS.SBP_ARROWBTN, iStateId, rect, null); } else { int uState = OS.DFCS_SCROLLLEFT; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java index bc0f470331..5b5342b940 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java @@ -38,6 +38,9 @@ import org.eclipse.swt.internal.win32.*; * @noextend This class is not intended to be subclassed by clients. */ public class Caret extends Widget { + /** The Caret last updated on the OS-level */ + private static Caret currentCaret; + Canvas parent; int x, y, width, height; boolean moved, resized; @@ -285,6 +288,7 @@ void killFocus () { void move () { moved = false; + setCurrentCaret(this); if (!OS.SetCaretPos (x, y)) return; resizeIME (); } @@ -332,6 +336,9 @@ void releaseParent () { @Override void releaseWidget () { super.releaseWidget (); + if (isCurrentCaret()) { + setCurrentCaret(null); + } parent = null; image = null; font = null; @@ -390,7 +397,7 @@ public void setBounds (int x, int y, int width, int height) { void setBoundsInPixels (int x, int y, int width, int height) { boolean samePosition = this.x == x && this.y == y; boolean sameExtent = this.width == width && this.height == height; - if (samePosition && sameExtent) return; + if (samePosition && sameExtent && isCurrentCaret()) return; this.x = x; this.y = y; this.width = width; @@ -530,12 +537,20 @@ public void setLocation (int x, int y) { } void setLocationInPixels (int x, int y) { - if (this.x == x && this.y == y) return; + if (this.x == x && this.y == y && isCurrentCaret()) return; this.x = x; this.y = y; moved = true; if (isVisible && hasFocus ()) move (); } +private boolean isCurrentCaret() { + return Caret.currentCaret == this; +} + +private void setCurrentCaret(Caret caret) { + Caret.currentCaret = caret; +} + /** * Sets the receiver's location to the point specified by * the argument which is relative to the receiver's @@ -572,7 +587,7 @@ public void setSize (int width, int height) { } void setSizeInPixels (int width, int height) { - if (this.width == width && this.height == height) return; + if (this.width == width && this.height == height && isCurrentCaret()) return; this.width = width; this.height = height; resized = true; if (isVisible && hasFocus ()) resize (); 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 151be728f1..2e71ec17df 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 @@ -991,39 +991,6 @@ static long create32bitDIB (Image image) { dp += 4; } } - } else if (alpha != -1) { - for (int y = 0, dp = 0; y < imgHeight; ++y) { - for (int x = 0; x < imgWidth; ++x) { - int r = ((srcData[dp + 0] & 0xFF) * alpha) + 128; - r = (r + (r >> 8)) >> 8; - int g = ((srcData[dp + 1] & 0xFF) * alpha) + 128; - g = (g + (g >> 8)) >> 8; - int b = ((srcData[dp + 2] & 0xFF) * alpha) + 128; - b = (b + (b >> 8)) >> 8; - srcData[dp+0] = (byte)r; - srcData[dp+1] = (byte)g; - srcData[dp+2] = (byte)b; - srcData[dp+3] = (byte)alpha; - dp += 4; - } - } - } else if (alphaData != null) { - for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) { - for (int x = 0; x < imgWidth; ++x) { - int a = alphaData[ap++] & 0xFF; - int r = ((srcData[dp + 0] & 0xFF) * a) + 128; - r = (r + (r >> 8)) >> 8; - int g = ((srcData[dp + 1] & 0xFF) * a) + 128; - g = (g + (g >> 8)) >> 8; - int b = ((srcData[dp + 2] & 0xFF) * a) + 128; - b = (b + (b >> 8)) >> 8; - srcData[dp+0] = (byte)r; - srcData[dp+1] = (byte)g; - srcData[dp+2] = (byte)b; - srcData[dp+3] = (byte)a; - dp += 4; - } - } } else if (transparentPixel != -1) { for (int y = 0, dp = 0; y < imgHeight; ++y) { for (int x = 0; x < imgWidth; ++x) { @@ -1035,7 +1002,7 @@ static long create32bitDIB (Image image) { dp += 4; } } - } else { + } else if (alpha == -1 && alphaData == null) { for (int y = 0, dp = 0; y < imgHeight; ++y) { for (int x = 0; x < imgWidth; ++x) { srcData [dp + 3] = (byte)0xFF; @@ -1117,6 +1084,11 @@ static long create32bitDIB (long hBitmap, int alpha, byte [] alphaData, int tran if (alpha != -1) { for (int y = 0, dp = 0; y < imgHeight; ++y) { for (int x = 0; x < imgWidth; ++x) { + if (alpha != 0) { + srcData [dp ] = (byte)((((srcData[dp ] & 0xFF) * 0xFF) + alpha / 2) / alpha); + srcData [dp + 1] = (byte)((((srcData[dp + 1] & 0xFF) * 0xFF) + alpha / 2) / alpha); + srcData [dp + 2] = (byte)((((srcData[dp + 2] & 0xFF) * 0xFF) + alpha / 2) / alpha); + } srcData [dp + 3] = (byte)alpha; dp += 4; } @@ -1124,7 +1096,13 @@ static long create32bitDIB (long hBitmap, int alpha, byte [] alphaData, int tran } else if (alphaData != null) { for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) { for (int x = 0; x < imgWidth; ++x) { - srcData [dp + 3] = alphaData [ap++]; + int a = alphaData [ap++] & 0xFF; + if (a != 0) { + srcData [dp ] = (byte)((((srcData[dp ] & 0xFF) * 0xFF) + a / 2) / a); + srcData [dp + 1] = (byte)((((srcData[dp + 1] & 0xFF) * 0xFF) + a / 2) / a); + srcData [dp + 2] = (byte)((((srcData[dp + 2] & 0xFF) * 0xFF) + a / 2) / a); + } + srcData [dp + 3] = (byte)a; dp += 4; } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java index 823a620c74..097ab46efa 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java @@ -324,6 +324,75 @@ int getWidthInPixels () { } /** + * WINAPI doesn't provide any means to request column's optimal size. + * There is only an API to resize to optimal size. The workaround is to + * 1) disable redraw + * 2) resize to optimal + * 3) query new column size + * 4) set old column size + * 5) enable redraw + * This preserves old column size. As a consequence, no painting is + * needed after enabling redraw. + */ +private int calcAutoWidth(int index, boolean withHeader) { + long hwnd = parent.handle; + + // WM_SETREDRAW has a side effect of forcing Control to be visible. + // On the other hand, if control is invisible, 'WM_SETREDRAW' is not needed. + int style = OS.GetWindowLong (hwnd, OS.GWL_STYLE); + boolean isTableVisible = ((style & OS.WS_VISIBLE) != 0); + boolean isTableDrawing = parent.getDrawing (); + boolean needsDisableRedraw = isTableVisible && isTableDrawing; + + try { + if (needsDisableRedraw) { + // WM_SETREDRAW is used directly, because 'Control.setRedraw()' + // also repaints, which is to be avoided in this function. + OS.SendMessage (hwnd, OS.WM_SETREDRAW, 0, 0); + } + + int oldWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); + + /* + * Feature in Windows. When LVSCW_AUTOSIZE_USEHEADER is used + * with LVM_SETCOLUMNWIDTH to resize the last column, the last + * column is expanded to fill the client area. The fix is to + * resize the table to be small, set the column width and then + * restore the table to its original size. + * + * Note: temporarily setting LVS_EX_COLUMNSNAPPOINTS may be a + * less intrusive workaround. + */ + RECT rect = null; + boolean fixWidth = index == parent.getColumnCount () - 1; + if (fixWidth) { + rect = new RECT (); + OS.GetWindowRect (hwnd, rect); + OS.UpdateWindow (hwnd); + int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER; + OS.SetWindowPos (hwnd, 0, 0, 0, 0, rect.bottom - rect.top, flags); + } + + int resizeType = withHeader ? OS.LVSCW_AUTOSIZE_USEHEADER : OS.LVSCW_AUTOSIZE; + OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, resizeType); + + if (fixWidth) { + int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOZORDER; + OS.SetWindowPos (hwnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags); + } + + int newWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); + OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, oldWidth); + + return newWidth; + } finally { + if (needsDisableRedraw) { + OS.SendMessage (hwnd, OS.WM_SETREDRAW, 1, 0); + } + } +} + +/** * Causes the receiver to be resized to its preferred size. * For a composite, this involves computing the preferred size * from its layout, if there is one. @@ -381,10 +450,8 @@ public void pack () { } if (newFont != 0) OS.SelectObject (hDC, oldFont); OS.ReleaseDC (hwnd, hDC); - OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth); } else { - OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE); - columnWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); + columnWidth = calcAutoWidth (index, false); if (index == 0) { /* * Bug in Windows. When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE @@ -412,38 +479,19 @@ public void pack () { } if (headerWidth > columnWidth) { if (!hasHeaderImage) { - /* - * Feature in Windows. When LVSCW_AUTOSIZE_USEHEADER is used - * with LVM_SETCOLUMNWIDTH to resize the last column, the last - * column is expanded to fill the client area. The fix is to - * resize the table to be small, set the column width and then - * restore the table to its original size. - */ - RECT rect = null; - boolean fixWidth = index == parent.getColumnCount () - 1; - if (fixWidth) { - rect = new RECT (); - OS.GetWindowRect (hwnd, rect); - OS.UpdateWindow (hwnd); - int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER; - OS.SetWindowPos (hwnd, 0, 0, 0, 0, rect.bottom - rect.top, flags); - } - OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE_USEHEADER); - if (fixWidth) { - int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOZORDER; - OS.SetWindowPos (hwnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags); - } + // The code has been there for years and it's no longer clear why + // not just use 'headerWidth' here. Maybe because SWT's size + // calculation is imperfect and WINAPI will do it better? + columnWidth = calcAutoWidth (index, true); } else { - OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, headerWidth); - } - } else { - if (index == 0) { - OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth); + columnWidth = headerWidth; } } + + OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth); + parent.ignoreColumnResize = false; - int newWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); - if (oldWidth != newWidth) { + if (oldWidth != columnWidth) { updateToolTip (index); sendEvent (SWT.Resize); if (isDisposed ()) return; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java index 3cb9a97aaf..488cf58683 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java @@ -125,6 +125,7 @@ public abstract class Widget { * Prevents uninitialized instances from being created outside the package. */ Widget () { + notifyCreationTracker(); } /** @@ -162,6 +163,7 @@ public Widget (Widget parent, int style) { this.style = style; display = parent.display; reskinWidget (); + notifyCreationTracker(); } void _addListener (int eventType, Listener listener) { @@ -829,6 +831,7 @@ void release (boolean destroy) { releaseHandle (); } } + notifyDisposalTracker(); } } @@ -2487,4 +2490,17 @@ LRESULT wmXButtonUp (long hwnd, long wParam, long lParam) { } return result; } + +void notifyCreationTracker() { + if (WidgetSpy.isEnabled) { + WidgetSpy.getInstance().widgetCreated(this); + } +} + +void notifyDisposalTracker() { + if (WidgetSpy.isEnabled) { + WidgetSpy.getInstance().widgetDisposed(this); + } +} + } diff --git a/bundles/org.eclipse.swt/META-INF/MANIFEST.MF b/bundles/org.eclipse.swt/META-INF/MANIFEST.MF index 6a625d3e24..e17013ede2 100644 --- a/bundles/org.eclipse.swt/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.swt/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.swt; singleton:=true -Bundle-Version: 3.118.100.qualifier +Bundle-Version: 3.119.100.qualifier Bundle-ManifestVersion: 2 Bundle-Localization: plugin DynamicImport-Package: org.eclipse.swt.accessibility2 @@ -15,13 +15,13 @@ Export-Package: org.eclipse.swt.dnd, org.eclipse.swt.events, org.eclipse.swt.graphics, + org.eclipse.swt.internal;x-friends:="org.eclipse.ui,org.eclipse.swt.tools.spies", + org.eclipse.swt.internal.image;x-internal:=true, org.eclipse.swt.layout, org.eclipse.swt.opengl, org.eclipse.swt.printing, org.eclipse.swt.program, - org.eclipse.swt.widgets, - org.eclipse.swt.internal; x-friends:="org.eclipse.ui", - org.eclipse.swt.internal.image; x-internal:=true + org.eclipse.swt.widgets Eclipse-ExtensibleAPI: true Bundle-RequiredExecutionEnvironment: JavaSE-11 Automatic-Module-Name: org.eclipse.swt diff --git a/bundles/org.eclipse.swt/Readme.Win32.md b/bundles/org.eclipse.swt/Readme.Win32.md index daa9a946ab..a0764e3d31 100644 --- a/bundles/org.eclipse.swt/Readme.Win32.md +++ b/bundles/org.eclipse.swt/Readme.Win32.md @@ -21,7 +21,7 @@ libraries in the binary repository. * Download & install Java *JDK* (Last tested on JDK9) http://www.oracle.com/technetwork/java/javase/downloads/index.html * Download and install Eclipse. Either the "Eclipse IDE for Eclipse Committers" or a recent integration build: - http://download.eclipse.org/eclipse/downloads/ + https://download.eclipse.org/eclipse/downloads/ * (Optionally) install CDT from marketplace if you want to work on C/Native parts of SWT. * (if not already installed) installed EGit integration. * Open the git perspective. Add the following two repositories, which can be found on: (use git protocol) diff --git a/bundles/org.eclipse.swt/buildFragment.xml b/bundles/org.eclipse.swt/buildFragment.xml index 549a4c0bef..5a12f3e94e 100644 --- a/bundles/org.eclipse.swt/buildFragment.xml +++ b/bundles/org.eclipse.swt/buildFragment.xml @@ -258,9 +258,9 @@ <fileset dir="${build.result.folder}/@dot" includes="**" /> </copy> <copy todir="${destination.temp.folder}/${full.name}"> - <fileset dir="${fragmentdir}" includes="fragment.properties,about.html,about_files/,swt*.dll,libswt*.so,libswt*.sl,libswt*.a,libswt*.jnilib,libXm.so.2,webkitextensions*/libswt*.so,META-INF/,WebView2Loader.dll" /> + <fileset dir="${fragmentdir}" includes="fragment.properties,about.html,about_files/,swt*.dll,libswt*.so,libswt*.sl,libswt*.a,libswt*.jnilib,libXm.so.2,META-INF/,WebView2Loader.dll" /> </copy> - <chmod perm="755" dir="${destination.temp.folder}/${full.name}" includes="swt*.dll,libswt*.so,libswt*.sl,libswt*.a,libswt*.jnilib,libXm.so.2,webkitextensions*/libswt*.so,WebView2Loader.dll" /> + <chmod perm="755" dir="${destination.temp.folder}/${full.name}" includes="swt*.dll,libswt*.so,libswt*.sl,libswt*.a,libswt*.jnilib,libXm.so.2,WebView2Loader.dll" /> <eclipse.versionReplacer path="${destination.temp.folder}/${full.name}" version="${version.suffix}" /> </target> @@ -271,7 +271,7 @@ <property name="includetranslationfiles" value="true" /> <property name="swtbasename" value="swt" /> <antcall target="build.jars" /> - <jar jarfile="${build.result.folder}/${swtbasename}.jar" basedir="${fragmentdir}" update="true" includes="swt*.dll,libswt*.so,libswt*.sl,libswt*.a,libswt*.jnilib,libXm.so.2,webkitextensions*/libswt*.so,WebView2Loader.dll" /> + <jar jarfile="${build.result.folder}/${swtbasename}.jar" basedir="${fragmentdir}" update="true" includes="swt*.dll,libswt*.so,libswt*.sl,libswt*.a,libswt*.jnilib,libXm.so.2,WebView2Loader.dll" /> <move file="${build.result.folder}/${swtbasename}.jar" todir="${temp.folder}/swtdownload" /> <delete dir="${build.result.folder}/@dot" /> <antcall target="build.sources" /> diff --git a/bundles/org.eclipse.swt/buildSWT.xml b/bundles/org.eclipse.swt/buildSWT.xml index 70d0831f3c..07a871d77b 100644 --- a/bundles/org.eclipse.swt/buildSWT.xml +++ b/bundles/org.eclipse.swt/buildSWT.xml @@ -66,15 +66,15 @@ <param name="fragment" value="org.eclipse.swt.cocoa.macosx.x86_64"/> </antcall> <antcall target="check_fragment_libraries"> - <param name="library_count" value="8"/> + <param name="library_count" value="7"/> <param name="fragment" value="org.eclipse.swt.gtk.linux.aarch64"/> </antcall> <antcall target="check_fragment_libraries"> - <param name="library_count" value="8"/> + <param name="library_count" value="7"/> <param name="fragment" value="org.eclipse.swt.gtk.linux.ppc64le"/> </antcall> <antcall target="check_fragment_libraries"> - <param name="library_count" value="8"/> + <param name="library_count" value="7"/> <param name="fragment" value="org.eclipse.swt.gtk.linux.x86_64"/> </antcall> <antcall target="check_fragment_libraries"> @@ -86,7 +86,7 @@ <target name="check_fragment_libraries" depends="get_version"> <echo>Checking ${fragment}</echo> <property name="checkdir" value="~/build/check_libraries"/> - <property name="library_count" value="34"/> + <property name="library_count" value="31"/> <property name="fragment" value=""/> <fileset id="match" dir="${repo.bin}/bundles/${fragment}" includes="**/org.eclipse.swt.gtk.linux.aarch64/**, **/org.eclipse.swt.gtk.linux.ppc64le/**, **/org.eclipse.swt.gtk.linux.x86_64/**, **/org.eclipse.swt.win32.win32.x86_64/**, **/org.eclipse.swt.cocoa.macosx.aarch64/**, **/org.eclipse.swt.cocoa.macosx.x86_64/**"> <filename regex="[0-9][0-9][0-9][0-9]"/> @@ -615,7 +615,6 @@ <!-- Get list of files to commit --> <fileset id="addid" dir="${repo.bin}"> <include name="bundles/*/*${swt_version}*"/> - <include name="bundles/*/webkitextensions${swt_version}/*${swt_version}*"/> <include name="bundles/*/build.sha1"/> <exclude name="**/.git/**"/> <exclude name="**/tmpdir/**"/> @@ -788,12 +787,6 @@ port="${port}" keyfile="${keyfile}" trust="true"/> - <scp file="swtbuild@${build_machine}:${lib_output}/webkitextensions${swt_version}/*" - todir="${output_dir}/webkitextensions${swt_version}/" - port="${port}" - keyfile="${keyfile}" - trust="true" - failonerror="false"/> <sshexec host="${build_machine}" username="swtbuild" port="${port}" @@ -804,10 +797,6 @@ <target name="build_local"> <property name="gtk_version" value="3.0" /> - <exec executable="mkdir"> - <arg value="-p"/> - <arg value="${output_dir}/webkitextensions${swt_version}/"/> - </exec> <exec dir="${build_dir}" executable="sh" failonerror="true"> <arg line="build.sh"/> <env key="GTK_VERSION" value="${gtk_version}"/> diff --git a/bundles/org.eclipse.swt/pom.xml b/bundles/org.eclipse.swt/pom.xml index d708f394f1..51cbee8974 100644 --- a/bundles/org.eclipse.swt/pom.xml +++ b/bundles/org.eclipse.swt/pom.xml @@ -16,12 +16,12 @@ <parent> <artifactId>eclipse.platform.swt</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../</relativePath> </parent> <groupId>org.eclipse.swt</groupId> <artifactId>org.eclipse.swt</artifactId> - <version>3.118.100-SNAPSHOT</version> + <version>3.119.100-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <properties> @@ -29,7 +29,7 @@ forceContextQualifier gets updated during build input process using ant script <SWT source repo>/bundles/org.eclipse.swt/buildInternal.xml --> - <forceContextQualifier>v20220119-1826</forceContextQualifier> + <forceContextQualifier>v20220326-2203</forceContextQualifier> <sonar.sources>Eclipse SWT Accessibility/cocoa,Eclipse SWT Accessibility/common,Eclipse SWT Accessibility/gtk,Eclipse SWT Accessibility/win32,Eclipse SWT AWT/cocoa,Eclipse SWT AWT/common,Eclipse SWT AWT/gtk,Eclipse SWT AWT/win32,Eclipse SWT Browser/cocoa,Eclipse SWT Browser/common,Eclipse SWT Browser/gtk,Eclipse SWT Browser/win32,Eclipse SWT Custom Widgets/common,Eclipse SWT Drag and Drop/cocoa,Eclipse SWT Drag and Drop/common,Eclipse SWT Drag and Drop/gtk,Eclipse SWT Drag and Drop/win32,Eclipse SWT OLE Win32/win32,Eclipse SWT OpenGL/cocoa,Eclipse SWT OpenGL/common,Eclipse SWT OpenGL/glx,Eclipse SWT OpenGL/gtk,Eclipse SWT OpenGL/win32,Eclipse SWT PI/cairo,Eclipse SWT PI/cocoa,Eclipse SWT PI/common,Eclipse SWT PI/gtk,Eclipse SWT PI/win32,Eclipse SWT Printing/cocoa,Eclipse SWT Printing/common,Eclipse SWT Printing/gtk,Eclipse SWT Printing/win32,Eclipse SWT Program/cocoa,Eclipse SWT Program/common,Eclipse SWT Program/gtk,Eclipse SWT Program/win32,Eclipse SWT WebKit/cocoa,Eclipse SWT WebKit/gtk,Eclipse SWT/cairo,Eclipse SWT/cocoa,Eclipse SWT/common,Eclipse SWT/emulated/bidi,Eclipse SWT/emulated/coolbar,Eclipse SWT/emulated/expand,Eclipse SWT/emulated/taskbar,Eclipse SWT/emulated/tooltip,Eclipse SWT/gtk,Eclipse SWT/win32</sonar.sources> </properties> diff --git a/container/Dockerfile b/container/Dockerfile index fa7be5dbd8..cd1a4f5649 100644 --- a/container/Dockerfile +++ b/container/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipsecbi/fedora-gtk3-mutter:29-gtk3.24 +FROM eclipsecbi/fedora-gtk3-mutter:30-gtk3.24 # Back to root for install USER 0 diff --git a/examples/org.eclipse.swt.examples.browser.demos/pom.xml b/examples/org.eclipse.swt.examples.browser.demos/pom.xml index 1bd4f24028..739538de2a 100644 --- a/examples/org.eclipse.swt.examples.browser.demos/pom.xml +++ b/examples/org.eclipse.swt.examples.browser.demos/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/examples/org.eclipse.swt.examples.launcher/pom.xml b/examples/org.eclipse.swt.examples.launcher/pom.xml index 32477aa6f1..f066a82431 100644 --- a/examples/org.eclipse.swt.examples.launcher/pom.xml +++ b/examples/org.eclipse.swt.examples.launcher/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/examples/org.eclipse.swt.examples.ole.win32/pom.xml b/examples/org.eclipse.swt.examples.ole.win32/pom.xml index 6b424468ee..5e50471043 100644 --- a/examples/org.eclipse.swt.examples.ole.win32/pom.xml +++ b/examples/org.eclipse.swt.examples.ole.win32/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/examples/org.eclipse.swt.examples.views/pom.xml b/examples/org.eclipse.swt.examples.views/pom.xml index 04d7fb8d74..b0af44b7b2 100644 --- a/examples/org.eclipse.swt.examples.views/pom.xml +++ b/examples/org.eclipse.swt.examples.views/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/examples/org.eclipse.swt.examples/META-INF/MANIFEST.MF b/examples/org.eclipse.swt.examples/META-INF/MANIFEST.MF index 9bbf5adabe..a278ed410e 100644 --- a/examples/org.eclipse.swt.examples/META-INF/MANIFEST.MF +++ b/examples/org.eclipse.swt.examples/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin.SWTStandaloneExampleSet.name Bundle-SymbolicName: org.eclipse.swt.examples; singleton:=true -Bundle-Version: 3.107.100.qualifier +Bundle-Version: 3.107.200.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-11 diff --git a/examples/org.eclipse.swt.examples/pom.xml b/examples/org.eclipse.swt.examples/pom.xml index 89677ad88b..82f064df74 100644 --- a/examples/org.eclipse.swt.examples/pom.xml +++ b/examples/org.eclipse.swt.examples/pom.xml @@ -14,11 +14,11 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> <artifactId>org.eclipse.swt.examples</artifactId> - <version>3.107.100-SNAPSHOT</version> + <version>3.107.200-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/controlexample/browser-content.html b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/controlexample/browser-content.html index bcb8288efc..3fb059c6b3 100644 --- a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/controlexample/browser-content.html +++ b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/controlexample/browser-content.html @@ -22,7 +22,7 @@ and more, check out <a href="http://www.eclipse.org/swt/">http://www.eclipse.org <h3>Eclipse Downloads Page</h3> <p>To download the latest Integration Build of eclipse, go to: -<a href="http://download.eclipse.org/eclipse/downloads/">http://download.eclipse.org/eclipse/downloads</a>.</p> +<a href="https://download.eclipse.org/eclipse/downloads/">https://download.eclipse.org/eclipse/downloads</a>.</p> <h3>Bug Reports and Feature Requests</h3> <p>To report an SWT bug or request an SWT feature, go to: diff --git a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/imageanalyzer/ImageAnalyzer.java b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/imageanalyzer/ImageAnalyzer.java index 1638aa6d44..326e3d0668 100644 --- a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/imageanalyzer/ImageAnalyzer.java +++ b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/imageanalyzer/ImageAnalyzer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -205,7 +205,7 @@ public class ImageAnalyzer { shell.setText(bundle.getString("Image_analyzer")); // Hook resize and dispose listeners. - shell.addControlListener(ControlListener.controlResizedAdapter(e-> resizeShell(e))); + shell.addControlListener(ControlListener.controlResizedAdapter(this::resizeShell)); shell.addShellListener(ShellListener.shellClosedAdapter(e -> { animate = false; // stop any animation in progress if (animateThread != null) { @@ -833,7 +833,7 @@ public class ImageAnalyzer { loader = new ImageLoader(); if (incremental) { // Prepare to handle incremental events. - loader.addImageLoaderListener(event -> incrementalDataLoaded(event)); + loader.addImageLoaderListener(this::incrementalDataLoaded); incrementalThreadStart(); } // Read the new image(s) from the chosen file. @@ -884,7 +884,7 @@ public class ImageAnalyzer { loader = new ImageLoader(); if (incremental) { // Prepare to handle incremental events. - loader.addImageLoaderListener(event -> incrementalDataLoaded(event)); + loader.addImageLoaderListener(this::incrementalDataLoaded); incrementalThreadStart(); } // Read the new image(s) from the chosen URL. @@ -929,7 +929,7 @@ public class ImageAnalyzer { // Synchronize so we don't try to remove when the vector is null. synchronized (ImageAnalyzer.this) { if (incrementalEvents != null) { - if (incrementalEvents.size() > 0) { + if (!incrementalEvents.isEmpty()) { ImageLoaderEvent event = incrementalEvents.remove(0); if (image != null) image.dispose(); image = new Image(display, event.imageData); @@ -1655,22 +1655,19 @@ public class ImageAnalyzer { shell.setText(string); if (imageDataArray.length > 1) { - string = createMsg(bundle.getString("Type_index"), - new Object[] {fileTypeString(imageData.type), - Integer.valueOf(imageDataIndex + 1), - Integer.valueOf(imageDataArray.length)}); + string = createMsg(bundle.getString("Type_index"), fileTypeString(imageData.type), + Integer.valueOf(imageDataIndex + 1), Integer.valueOf(imageDataArray.length)); } else { string = createMsg(bundle.getString("Type_string"), fileTypeString(imageData.type)); } typeLabel.setText(string); string = createMsg(bundle.getString("Size_value"), - new Object[] {Integer.valueOf(imageData.width), - Integer.valueOf(imageData.height)}); + Integer.valueOf(imageData.width), Integer.valueOf(imageData.height)); sizeLabel.setText(string); string = createMsg(bundle.getString("Depth_value"), - new Object[] {Integer.valueOf(imageData.depth), Integer.valueOf(display.getDepth())}); + Integer.valueOf(imageData.depth), Integer.valueOf(display.getDepth())); depthLabel.setText(string); string = createMsg(bundle.getString("Transparent_pixel_value"), pixelInfo(imageData.transparentPixel)); @@ -1680,27 +1677,25 @@ public class ImageAnalyzer { timeToLoadLabel.setText(string); string = createMsg(bundle.getString("Animation_size_value"), - new Object[] {Integer.valueOf(loader.logicalScreenWidth), - Integer.valueOf(loader.logicalScreenHeight)}); + Integer.valueOf(loader.logicalScreenWidth), Integer.valueOf(loader.logicalScreenHeight)); screenSizeLabel.setText(string); string = createMsg(bundle.getString("Background_pixel_value"), pixelInfo(loader.backgroundPixel)); backgroundPixelLabel.setText(string); string = createMsg(bundle.getString("Image_location_value"), - new Object[] {Integer.valueOf(imageData.x), Integer.valueOf(imageData.y)}); + Integer.valueOf(imageData.x), Integer.valueOf(imageData.y)); locationLabel.setText(string); string = createMsg(bundle.getString("Disposal_value"), - new Object[] {Integer.valueOf(imageData.disposalMethod), - disposalString(imageData.disposalMethod)}); + Integer.valueOf(imageData.disposalMethod), disposalString(imageData.disposalMethod)); disposalMethodLabel.setText(string); int delay = imageData.delayTime * 10; int delayUsed = visibleDelay(delay); if (delay != delayUsed) { string = createMsg(bundle.getString("Delay_value"), - new Object[] {Integer.valueOf(delay), Integer.valueOf(delayUsed)}); + Integer.valueOf(delay), Integer.valueOf(delayUsed)); } else { string = createMsg(bundle.getString("Delay_used"), Integer.valueOf(delay)); } @@ -1722,17 +1717,17 @@ public class ImageAnalyzer { string = createMsg( bundle.getString("Pixel_data_value"), - new Object[] { Integer.valueOf(imageData.bytesPerLine), Integer.valueOf(imageData.scanlinePad), depthInfo(imageData.depth), (imageData.alphaData != null && imageData.alphaData.length > 0) ? - bundle.getString("Scroll_for_alpha") : "" }); + bundle.getString("Scroll_for_alpha") : ""); dataLabel.setText(string); String data = dataHexDump(dataText.getLineDelimiter()); dataText.setText(data); + ArrayList<StyleRange> ranges = new ArrayList<>(); // bold the first column all the way down int index = 0; while((index = data.indexOf(':', index+1)) != -1) { @@ -1742,8 +1737,9 @@ public class ImageAnalyzer { start = index - ALPHA_CHARS; length = ALPHA_CHARS; } - dataText.setStyleRange(new StyleRange(start, length, dataText.getForeground(), dataText.getBackground(), SWT.BOLD)); + ranges.add(new StyleRange(start, length, dataText.getForeground(), dataText.getBackground(), SWT.BOLD)); } + if(!ranges.isEmpty()) dataText.setStyleRanges(ranges.toArray(new StyleRange[0])); statusLabel.setText(""); @@ -2083,7 +2079,7 @@ public class ImageAnalyzer { */ void showErrorDialog(String operation, String filename, Throwable e) { MessageBox box = new MessageBox(shell, SWT.ICON_ERROR); - String message = createMsg(bundle.getString("Error"), new String[] {operation, filename}); + String message = createMsg(bundle.getString("Error"), operation, filename); String errorMessage = ""; if (e != null) { if (e instanceof SWTException) { @@ -2168,16 +2164,13 @@ public class ImageAnalyzer { Object[] args = {Integer.valueOf(depth), ""}; switch (depth) { case 1: - args[1] = createMsg(bundle.getString("Multi_pixels"), - new Object[] {Integer.valueOf(8), " [01234567]"}); + args[1] = createMsg(bundle.getString("Multi_pixels"), Integer.valueOf(8), " [01234567]"); break; case 2: - args[1] = createMsg(bundle.getString("Multi_pixels"), - new Object[] {Integer.valueOf(4), "[00112233]"}); + args[1] = createMsg(bundle.getString("Multi_pixels"), Integer.valueOf(4), "[00112233]"); break; case 4: - args[1] = createMsg(bundle.getString("Multi_pixels"), - new Object[] {Integer.valueOf(2), "[00001111]"}); + args[1] = createMsg(bundle.getString("Multi_pixels"), Integer.valueOf(2), "[00001111]"); break; case 8: args[1] = bundle.getString("One_byte"); @@ -2353,13 +2346,9 @@ public class ImageAnalyzer { compressionRatioLabel.setEnabled(false); } - static String createMsg(String msg, Object[] args) { + static String createMsg(String msg, Object... args) { MessageFormat formatter = new MessageFormat(msg); return formatter.format(args); } - static String createMsg(String msg, Object arg) { - MessageFormat formatter = new MessageFormat(msg); - return formatter.format(new Object[]{arg}); - } } diff --git a/examples/org.eclipse.swt.snippets/previews/Snippet379.png b/examples/org.eclipse.swt.snippets/previews/Snippet379.png Binary files differnew file mode 100644 index 0000000000..ee1cc11fbb --- /dev/null +++ b/examples/org.eclipse.swt.snippets/previews/Snippet379.png diff --git a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet154.java b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet154.java index 3b53f20a1b..cc37286975 100644 --- a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet154.java +++ b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet154.java @@ -54,7 +54,7 @@ public class Snippet154 { /* Create and setting up frame */ Frame frame = SWT_AWT.new_Frame(composite); - Panel panel = new Panel(new BorderLayout()) { + Panel panel = new Panel(new java.awt.BorderLayout()) { @Override public void update(java.awt.Graphics g) { /* Do not erase the background */ @@ -84,7 +84,7 @@ public class Snippet154 { table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.createDefaultColumnsFromModel(); JScrollPane scrollPane = new JScrollPane(table); - contentPane.setLayout(new BorderLayout()); + contentPane.setLayout(new java.awt.BorderLayout()); contentPane.add(scrollPane); shell.open(); diff --git a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet246.java b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet246.java index a8eb74443c..331228deac 100644 --- a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet246.java +++ b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet246.java @@ -21,32 +21,51 @@ package org.eclipse.swt.snippets; */ import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; public class Snippet246 { + static Display display; public static void main(String[] args) { - Display display = new Display(); - Font font = new Font(display, "Comic Sans MS", 24, SWT.BOLD); - Image image = new Image(display, 87, 48); + display = new Display(); + Shell shell = new Shell(display); + shell.setText("Snippet 246"); + GridLayout layout = new GridLayout(2, false); + shell.setLayout(layout); + createImage(); + + String executionPath = System.getProperty("user.dir"); + Label label = new Label(shell, SWT.WRAP); + label.setText("File created as: " + executionPath.replace("\\", "/")+"/swt.png"); + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } + + private static void createImage() { + Font font = new Font(display, "Comic Sans MS", 48, SWT.BOLD); + Image image = new Image(display, 174, 96); GC gc = new GC(image); gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); gc.fillRectangle(image.getBounds()); gc.setFont(font); gc.setForeground(display.getSystemColor(SWT.COLOR_RED)); - gc.drawString("S", 3, 0); + gc.drawString("S", 3, 10); gc.setForeground(display.getSystemColor(SWT.COLOR_GREEN)); - gc.drawString("W", 25, 0); + gc.drawString("W", 50, 10); gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE)); - gc.drawString("T", 62, 0); + gc.drawString("T", 124, 10); gc.dispose(); ImageLoader loader = new ImageLoader(); - loader.data = new ImageData[] {image.getImageData()}; + loader.data = new ImageData[] { image.getImageData() }; loader.save("swt.png", SWT.IMAGE_PNG); - image.dispose(); font.dispose(); - display.dispose(); } } diff --git a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet337.java b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet337.java index 669bef4745..357afaff54 100644 --- a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet337.java +++ b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet337.java @@ -64,7 +64,7 @@ public static void main(String args[]) { mainPanel.add(new JTextField("a JTextField")); mainPanel.add(launchBrowserButton); - mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER); + mainFrame.getContentPane().add(mainPanel, java.awt.BorderLayout.CENTER); mainFrame.pack(); mainFrame.setVisible(true); }); diff --git a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet379.java b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet379.java new file mode 100644 index 0000000000..1a865ce39b --- /dev/null +++ b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet379.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2021 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.snippets; + +import org.eclipse.swt.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +/** + * This snippet demonstrates the usage of {@link BorderLayout} + */ +public class Snippet379 { + + public static void main(String[] args) { + + Display display = new Display(); + Shell shell = new Shell(display); + shell.setText("Border Layout Snippet"); + BorderLayout layout = new BorderLayout(); + layout.marginHeight = 16; + layout.marginWidth = 8; + layout.spacing = 4; + layout.controlSpacing = 2; + layout.type = SWT.VERTICAL; + shell.setBackground(display.getSystemColor(SWT.COLOR_CYAN)); + shell.setLayout(layout); + shell.setSize(800, 600); + region(new Button(shell, SWT.PUSH), SWT.TOP).setText("North 1"); + region(new Button(shell, SWT.PUSH), SWT.TOP).setText("North 2"); + region(new Button(shell, SWT.PUSH), SWT.BOTTOM).setText("South 1"); + region(new Button(shell, SWT.PUSH), SWT.BOTTOM).setText("South 2"); + region(new Button(shell, SWT.PUSH), SWT.LEFT).setText("West 1"); + region(new Button(shell, SWT.PUSH), SWT.LEFT).setText("West 2"); + region(new Button(shell, SWT.PUSH), SWT.RIGHT).setText("East 1"); + region(new Button(shell, SWT.PUSH), SWT.RIGHT).setText("East 2"); + new Text(shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL).setText("Center 1"); + new Text(shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL).setText("Center 2"); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + display.dispose(); + } + + private static <C extends Control> C region(C control, int region) { + control.setLayoutData(new BorderData(region)); + return control; + } + +} diff --git a/features/org.eclipse.swt.tools.feature/feature.xml b/features/org.eclipse.swt.tools.feature/feature.xml index 682f874a75..662c6510c9 100644 --- a/features/org.eclipse.swt.tools.feature/feature.xml +++ b/features/org.eclipse.swt.tools.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.swt.tools.feature" label="%featureName" - version="3.108.300.qualifier" + version="3.108.400.qualifier" provider-name="%providerName" license-feature="org.eclipse.license" license-feature-version="0.0.0"> diff --git a/features/org.eclipse.swt.tools.feature/pom.xml b/features/org.eclipse.swt.tools.feature/pom.xml index a86a3d3bd3..babc7c8373 100644 --- a/features/org.eclipse.swt.tools.feature/pom.xml +++ b/features/org.eclipse.swt.tools.feature/pom.xml @@ -15,12 +15,12 @@ <parent> <artifactId>eclipse.platform.swt</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../</relativePath> </parent> <groupId>org.eclipse.swt.tools.feature</groupId> <artifactId>org.eclipse.swt.tools.feature</artifactId> - <version>3.108.300-SNAPSHOT</version> + <version>3.108.400-SNAPSHOT</version> <packaging>eclipse-feature</packaging> <build> <plugins> diff --git a/local-build/local-build-parent/pom.xml b/local-build/local-build-parent/pom.xml index 45e0db0d78..424afe267b 100644 --- a/local-build/local-build-parent/pom.xml +++ b/local-build/local-build-parent/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../</relativePath> </parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> diff --git a/local-build/org.eclipse.swt.fragments.localbuild/pom.xml b/local-build/org.eclipse.swt.fragments.localbuild/pom.xml index 7fb02bf540..4014fe2bba 100644 --- a/local-build/org.eclipse.swt.fragments.localbuild/pom.xml +++ b/local-build/org.eclipse.swt.fragments.localbuild/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../</relativePath> </parent> <groupId>org.eclipse.swt</groupId> @@ -16,7 +16,7 @@ <parent> <groupId>org.eclipse</groupId> <artifactId>eclipse-platform-parent</artifactId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../eclipse-platform-parent</relativePath> </parent> diff --git a/tests/org.eclipse.swt.tests.cocoa/ManualTests/org/eclipse/swt/tests/cocoa/snippets/Bug569088_macOS_RadioButtonNotRendered.java b/tests/org.eclipse.swt.tests.cocoa/ManualTests/org/eclipse/swt/tests/cocoa/snippets/Bug569088_macOS_RadioButtonNotRendered.java new file mode 100644 index 0000000000..b7194458e4 --- /dev/null +++ b/tests/org.eclipse.swt.tests.cocoa/ManualTests/org/eclipse/swt/tests/cocoa/snippets/Bug569088_macOS_RadioButtonNotRendered.java @@ -0,0 +1,42 @@ +package org.eclipse.swt.tests.cocoa.snippets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +public class Bug569088_macOS_RadioButtonNotRendered { + + public static void main(String[] args) { + final Display display = new Display(); + + final Shell shell = new Shell(display); + shell.setSize(300, 300); + shell.setLayout(new GridLayout(2, true)); + + final Button button1 = new Button(shell, SWT.RADIO | SWT.WRAP); + button1.setText("Button text 1 is loooooooong"); + button1.setForeground(display.getSystemColor(SWT.COLOR_RED)); + button1.setBackground(display.getSystemColor(SWT.COLOR_BLUE)); + button1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + final Button button2 = new Button(shell, SWT.CHECK | SWT.WRAP); + button2.setText("Button text 2 is loooooooong"); + button2.setForeground(display.getSystemColor(SWT.COLOR_RED)); + button2.setBackground(display.getSystemColor(SWT.COLOR_BLUE)); + button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + shell.open(); + System.err.println(button1.getBounds()); // Rectangle {5, 5, 142, 0} + System.err.println(button2.getBounds()); // Rectangle {152, 10, 142, 0} + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + display.dispose(); + } + +} diff --git a/tests/org.eclipse.swt.tests.cocoa/pom.xml b/tests/org.eclipse.swt.tests.cocoa/pom.xml index b6cdd784e0..3a629b7c51 100644 --- a/tests/org.eclipse.swt.tests.cocoa/pom.xml +++ b/tests/org.eclipse.swt.tests.cocoa/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/tests/org.eclipse.swt.tests.gtk/META-INF/MANIFEST.MF b/tests/org.eclipse.swt.tests.gtk/META-INF/MANIFEST.MF index f5d046b2e7..e492847919 100644 --- a/tests/org.eclipse.swt.tests.gtk/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.swt.tests.gtk/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.swt.tests.gtk -Bundle-Version: 3.108.0.qualifier +Bundle-Version: 3.108.100.qualifier Bundle-Vendor: %providerName Require-Bundle: org.junit;bundle-version="4.12.0", org.eclipse.swt diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug525946_DownloadFunction.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug525946_DownloadFunction.java index 9079cf9e5b..0a99bae100 100644 --- a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug525946_DownloadFunction.java +++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug525946_DownloadFunction.java @@ -34,8 +34,8 @@ public class Bug525946_DownloadFunction { shell.setBounds(10, 10, 400, 400); shell.setLayout(new FillLayout()); final Browser browser = new Browser(shell, SWT.NONE); -// browser.setUrl("http://download.eclipse.org/eclipse/downloads/drops4/I20180416-2000/download.php?dropFile=eclipse-test-framework-I20180416-2000.zip"); // 2.3 mb - browser.setUrl("http://download.eclipse.org/tools/orbit/downloads/drops/R20170516192513/orbit-buildrepo-R20170516192513.zip"); // 400mb +// browser.setUrl("https://download.eclipse.org/eclipse/downloads/drops4/I20180416-2000/download.php?dropFile=eclipse-test-framework-I20180416-2000.zip"); // 2.3 mb + browser.setUrl("https://download.eclipse.org/tools/orbit/downloads/drops/R20170516192513/orbit-buildrepo-R20170516192513.zip"); // 400mb shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug579257_new_webkit_window.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug579257_new_webkit_window.java new file mode 100644 index 0000000000..993cfe4ade --- /dev/null +++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug579257_new_webkit_window.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2022 Simeon Andreev and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Simeon Andreev - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.tests.gtk.snippets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.browser.VisibilityWindowAdapter; +import org.eclipse.swt.browser.WindowEvent; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +public class Bug579257_new_webkit_window { + + public static void main(String[] args) { + String webPageHtml = "<html><head></head><body>" + + "<a href=\"https://www.eclipse.org\" target=\"new\">link with target property set to \"new\"</a>" + + "</body></html>"; + Display display = new Display(); + Shell shell = new Shell(display); + shell.setSize(600, 400); + shell.setLayout(new FillLayout()); + shell.setText("Bug579257_new_webkit_window"); + + Composite composite = new Composite(shell, SWT.NONE); + composite.setLayout(new FillLayout()); + + Browser b = new Browser(composite, SWT.NONE); + b.setText(webPageHtml); + b.addOpenWindowListener(event -> { + Shell newWindowShell = new Shell(shell, SWT.SHELL_TRIM); + newWindowShell.setLayout(new FillLayout()); + Browser newWindowBrowser = new Browser(newWindowShell, SWT.NONE); + newWindowBrowser.addVisibilityWindowListener(new VisibilityWindowAdapter() { + @Override + public void show(WindowEvent e) { + newWindowShell.setSize(400, 200); + newWindowShell.open(); + } + }); + event.browser = newWindowBrowser; + }); + + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } +}
\ No newline at end of file diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug579283_TestToolbarOverflow_itemEnablement.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug579283_TestToolbarOverflow_itemEnablement.java new file mode 100644 index 0000000000..3826a9bafc --- /dev/null +++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug579283_TestToolbarOverflow_itemEnablement.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2022 Simeon Andreev and others. All rights reserved. + * The contents of this file are made available under the terms + * of the GNU Lesser General Public License (LGPL) Version 2.1 that + * accompanies this distribution (lgpl-v21.txt). The LGPL is also + * available at http://www.gnu.org/licenses/lgpl.html. If the version + * of the LGPL at http://www.gnu.org is different to the version of + * the LGPL accompanying this distribution and there is any conflict + * between the two license versions, the terms of the LGPL accompanying + * this distribution shall govern. + * + * Contributors: + * Simeon Andreev - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.tests.gtk.snippets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +/** + * Description: Toolbar items in a toolbar overflow submenu (enabled with style flag {@link SWT.WRAP}) + * do not show correct image enablement. + * <p> + * Steps to reproduce: + * <ol> + * <li>Run the snippet.</li> + * <li>Resize the {@link Shell}, so that only some of the icons are visible.</li> + * <li>Mouse-over the first toolbar button, which is enabled.</li> + * <li>The overflow button (downward arrow) should be visible to the right now.</li> + * <li>Click it, observe that the disabled buttons don't have disabled images.</li> + * <li>Click one of the overflow submenu items.</li> + * <li>Show the overflow menu again, observe that the image of the clicked item is not changed.</li> + * </ol> + * </p> + * Expected results: Images of disabled buttons should appear grayed out. + * Images should change on overflow submenu item click. + * Text and tooltip of an overflow submenu item should also change on click. + * Clicking on overflow submenu items should result in only 1 widget selected notification (see console output). + * Actual results: Images of disabled buttons in the overflow submenu are not grayed out. + * Images are not updated on overflow submenu item click. + */ +public class Bug579283_TestToolbarOverflow_itemEnablement { + + public static void main(String[] args) { + Display display = new Display(); + Shell shell = new Shell(display); + shell.setText("Bug 579283 test enablement of overflowing toolbar items"); + shell.setLayout(new FillLayout()); + Composite c1 = new Composite(shell, SWT.BORDER); + c1.setLayout(new FillLayout()); + + ToolBar toolBar = new ToolBar(c1, SWT.WRAP); + toolBar.setLayout(new RowLayout()); + + Image[] icons = { + display.getSystemImage(SWT.ICON_INFORMATION), + display.getSystemImage(SWT.ICON_WARNING), + display.getSystemImage(SWT.ICON_ERROR), + }; + + for (int i = 0; i < 8; ++i) { + final int index = i; + ToolItem item = new ToolItem(toolBar, SWT.CHECK); + item.setImage(icons[0]); + item.setText(String.valueOf(i)); + item.setToolTipText(String.valueOf(i)); + if (i % 2 == 0) { + item.setEnabled(false); + } + item.addSelectionListener(new SelectionAdapter() { + int iconIndex = 0; + @Override + public void widgetSelected(SelectionEvent e) { + System.out.println("Toolbar button " + index + " clicked!"); + ++iconIndex; + item.setImage(icons[iconIndex % icons.length]); + item.setText(String.valueOf(index) + "[" + iconIndex + "]"); + item.setToolTipText(String.valueOf(index) + "[" + iconIndex + "]"); + } + }); + } + + shell.setSize(500, 100); + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + + display.dispose(); + } + +}
\ No newline at end of file diff --git a/tests/org.eclipse.swt.tests.gtk/pom.xml b/tests/org.eclipse.swt.tests.gtk/pom.xml index 8e4d84a5d9..dfd787edcb 100644 --- a/tests/org.eclipse.swt.tests.gtk/pom.xml +++ b/tests/org.eclipse.swt.tests.gtk/pom.xml @@ -14,12 +14,12 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> <artifactId>org.eclipse.swt.tests.gtk</artifactId> - <version>3.108.0-SNAPSHOT</version> + <version>3.108.100-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> <code.ignoredWarnings>${tests.ignoredWarnings}</code.ignoredWarnings> diff --git a/tests/org.eclipse.swt.tests.win32/pom.xml b/tests/org.eclipse.swt.tests.win32/pom.xml index 49a3c0627a..37bcbbc7cc 100644 --- a/tests/org.eclipse.swt.tests.win32/pom.xml +++ b/tests/org.eclipse.swt.tests.win32/pom.xml @@ -14,7 +14,7 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java index 3bbc19a203..4daf9d8692 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java @@ -2162,6 +2162,47 @@ public void test_BrowserFunction_callback_afterPageReload() { assertTrue(message, passed); } +@Test +public void test_BrowserFunction_multiprocess() { + // Test that BrowserFunctions work in multiple Browser instances simultaneously. + Browser browser1 = new Browser(shell, SWT.NONE); + Browser browser2 = new Browser(shell, SWT.NONE); + + class JavaFunc extends BrowserFunction { + JavaFunc(Browser browser) { + super(browser, "javaFunc"); + } + + @Override + public Object function(Object[] arguments) { + return arguments[0]; + } + } + new JavaFunc(browser1); + new JavaFunc(browser2); + assertEquals("value1", browser1.evaluate("return javaFunc('value1')")); + assertEquals("value2", browser2.evaluate("return javaFunc('value2')")); + + // Ensure that navigation to a different page preserves BrowserFunctions. + int[] completed = new int[1]; + ProgressListener listener = new ProgressAdapter() { + @Override + public void completed(ProgressEvent event) { + completed[0]++; + } + }; + browser1.addProgressListener(listener); + browser2.addProgressListener(listener); + browser1.setText("<body>new_page1"); + browser2.setText("<body>new_page2"); + waitForPassCondition(() -> completed[0] == 2); + assertEquals("value1", browser1.evaluate("return javaFunc('value1')")); + assertEquals("value2", browser2.evaluate("return javaFunc('value2')")); + + browser1.dispose(); + browser2.dispose(); +} + /* custom */ /** diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_TextLayout.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_TextLayout.java index 174a988728..e91b80a6ba 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_TextLayout.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_TextLayout.java @@ -23,6 +23,7 @@ import static org.junit.Assert.fail; import java.util.Arrays; import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; @@ -1180,4 +1181,66 @@ public void test_bug23406_longLines() { check(bestProgramInThai, 1000); } +@Test +public void test_Bug579335_win32_StyledText_LongLine() { + if (!SwtTestUtil.isWindows) { + // TODO This test was written for the platform specific parts of TextLayout and + // on Linux (and possibly mac) + // the size of images needed to run the tests causes failures. + if (SwtTestUtil.verbose) { + System.out.println( + "Excluded test_Bug579335_win32_StyledText_LongLine(org.eclipse.swt.tests.junit.Test_org_eclipse_swt_graphics_TextLayout)."); + } + return; + } + + Font font = null; + Image image = null; + TextLayout layout = null; + + try { + font = new Font(display, SwtTestUtil.testFontName, 16, SWT.NORMAL); + + layout = new TextLayout(display); + layout.setFont(font); + layout.setText("a".repeat(33000)); + Color red = display.getSystemColor(SWT.COLOR_RED); + Color white = display.getSystemColor(SWT.COLOR_WHITE); + Color green = display.getSystemColor(SWT.COLOR_GREEN); + TextStyle redStyle = new TextStyle(font, red, white); + TextStyle greenStyle = new TextStyle(font, green, white); + + image = draw(layout, SWT.DEFAULT); + + layout.setStyle(redStyle, 7, 7); + layout.setStyle(greenStyle, 8, 8 + 32909 - 1); + + image = draw(layout, SWT.DEFAULT); + + // reset for next test + image.dispose(); + layout.setStyle(null, 0, 33000 - 1); + + layout.setStyle(greenStyle, 2, 2 + 16000 - 1); + image = draw(layout, SWT.DEFAULT); + + // reset for next test + image.dispose(); + layout.setStyle(null, 0, 33000 - 1); + + layout.setStyle(redStyle, 0, 0 + 1 - 1); + layout.setStyle(greenStyle, 1, 1 + 32916 - 1); + image = draw(layout, SWT.DEFAULT); + +// SwtTestUtil.debugDisplayImage(image); + } finally { + + if (layout != null) + layout.dispose(); + if (image != null) + image.dispose(); + if (font != null) + font.dispose(); + } +} } diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_layout_BorderLayout.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_layout_BorderLayout.java new file mode 100644 index 0000000000..e241a44bef --- /dev/null +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_layout_BorderLayout.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2021 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.tests.junit; + +import static org.junit.Assert.assertEquals; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.BorderData; +import org.eclipse.swt.layout.BorderLayout; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.Before; +import org.junit.Test; + +/** + * Automated Test Suite for class {@link BorderLayout} + * + */ +public class Test_org_eclipse_swt_layout_BorderLayout { + + Display display; + + @Before + public void setUp() { + display = Display.getDefault(); + } + + public void tearDown() { + SwtTestUtil.processEvents(); + display.dispose(); + } + + @Test + public void testControlExcluded() { + Shell shell = new Shell(display); + shell.setLayout(new BorderLayout()); + shell.setSize(800, 600); + MockControl control = new MockControl(shell); + control.setLayoutData(new BorderData(SWT.NONE)); + control.setBounds(0, 0, 100, 100); + shell.open(); + SwtTestUtil.processEvents(); + // the expectation is that the control is set to zero width/height + // even we have set a different size before... + Rectangle bounds = control.getBounds(); + assertEquals(0, bounds.width); + assertEquals(0, bounds.height); + shell.dispose(); + } + + @Test + public void testHints() { + Shell shell = new Shell(display); + shell.setLayout(new BorderLayout()); + shell.setSize(800, 600); + MockControl control = new MockControl(shell); + control.setLayoutData(new BorderData(SWT.TOP, 40, 50)); + shell.open(); + SwtTestUtil.processEvents(); + // the expectation is that the hints are passed to the control + assertEquals(40, control.wHint); + assertEquals(50, control.hHint); + shell.dispose(); + } + + @Test + public void testControlLayout() { + Shell shell = new Shell(display); + shell.setLayout(new BorderLayout()); + shell.setSize(800, 600); + MockControl topControl = new MockControl(shell); + topControl.reportedHeight = 10; + topControl.reportedWidth = 1000000; + MockControl bottomControl = new MockControl(shell); + bottomControl.reportedHeight = 20; + bottomControl.reportedWidth = 123; + MockControl leftControl = new MockControl(shell); + leftControl.reportedHeight = 5; + leftControl.reportedWidth = 50; + MockControl rightControl = new MockControl(shell); + rightControl.reportedHeight = 5; + rightControl.reportedWidth = 40; + MockControl centerControl = new MockControl(shell); + topControl.setLayoutData(new BorderData(SWT.TOP)); + bottomControl.setLayoutData(new BorderData(SWT.BOTTOM)); + leftControl.setLayoutData(new BorderData(SWT.LEFT)); + rightControl.setLayoutData(new BorderData(SWT.RIGHT)); + shell.open(); + shell.layout(); + SwtTestUtil.processEvents(); + // the expectation is that the control at the north is at the top and has the + // size returned by computeSize but a width that is the width of the shell + Rectangle clientArea = shell.getClientArea(); + Rectangle topBounds = topControl.getBounds(); + assertEquals(0, topBounds.x); + assertEquals(0, topBounds.y); + assertEquals(clientArea.width, topBounds.width); + assertEquals(topControl.reportedHeight, topBounds.height); + // the expectation is that the control at the south is at the bottom and has + // the size returned by computeSize but a width that is the width of the shell + Rectangle bottomBounds = bottomControl.getBounds(); + assertEquals(0, bottomBounds.x); + assertEquals(clientArea.height - bottomControl.reportedHeight, bottomBounds.y); + assertEquals(clientArea.width, bottomBounds.width); + assertEquals(bottomControl.reportedHeight, bottomBounds.height); + // the expectation is that the control at the west is placed left and has + // the size returned by computeSize but the height is that of the shell + // subtracting the height of the north/south controls + Rectangle leftBounds = leftControl.getBounds(); + assertEquals(0, leftBounds.x); + assertEquals(topControl.reportedHeight, leftBounds.y); + assertEquals(leftControl.reportedWidth, leftBounds.width); + assertEquals(clientArea.height - topControl.reportedHeight - bottomControl.reportedHeight, leftBounds.height); + // the expectation is that the control at the east is placed right and has + // the size returned by computeSize but the height is that of the shell + // subtracting the height of the north/south controls + Rectangle rightBounds = rightControl.getBounds(); + assertEquals(clientArea.width - rightControl.reportedWidth, rightBounds.x); + assertEquals(topControl.reportedHeight, rightBounds.y); + assertEquals(rightControl.reportedWidth, rightBounds.width); + assertEquals(clientArea.height - topControl.reportedHeight - bottomControl.reportedHeight, rightBounds.height); + // the center control should take the remaining size... + Rectangle centerBounds = centerControl.getBounds(); + assertEquals(leftControl.reportedWidth, centerBounds.x); + assertEquals(topControl.reportedHeight, centerBounds.y); + assertEquals(clientArea.width - leftControl.reportedWidth - rightControl.reportedWidth, centerBounds.width); + assertEquals(clientArea.height - topControl.reportedHeight - bottomControl.reportedHeight, centerBounds.height); + shell.dispose(); + } + + private static final class MockControl extends Canvas { + + private int wHint; + private int hHint; + + private int reportedHeight = -1; + private int reportedWidth = -1; + + public MockControl(Composite parent) { + super(parent, SWT.NONE); + setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLUE)); + } + + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + System.out.println( + "Test_org_eclipse_swt_layout_BorderLayout.MockControl.computeSize(" + wHint + "," + hHint + ")"); + this.wHint = wHint; + this.hHint = hHint; + if (reportedHeight > 0 && reportedWidth > 0) { + return new Point(reportedWidth, reportedHeight); + } + return super.computeSize(wHint, hHint, changed); + } + + } + +} diff --git a/tests/org.eclipse.swt.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.swt.tests/META-INF/MANIFEST.MF index 4b7dae65a7..78d2b616fd 100644 --- a/tests/org.eclipse.swt.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.swt.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.swt.tests -Bundle-Version: 3.106.1600.qualifier +Bundle-Version: 3.106.1700.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.swt.tests.junit, diff --git a/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug456602_macOS_AIOOBE_Table_selectedRowIndex.java b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug456602_macOS_AIOOBE_Table_selectedRowIndex.java new file mode 100644 index 0000000000..c161b26a22 --- /dev/null +++ b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug456602_macOS_AIOOBE_Table_selectedRowIndex.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2022 Syntevo and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Syntevo - initial API and implementation + *******************************************************************************/ + +package org.eclipse.swt.tests.manual; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.*; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; + +import java.util.Arrays; + +public final class Bug456602_macOS_AIOOBE_Table_selectedRowIndex { + public static void main(String[] args) { + final Display display = new Display(); + + final Shell shell = new Shell(display); + shell.setLayout(new GridLayout(1, true)); + + Label hint = new Label(shell, 0); + hint.setText( + "Bug 456602\n" + + "----------\n" + + "1) Use macOS\n" + + "2) Click 'Delete items' button\n" + + "3) Press left mouse button on last table item and HOLD the button\n" + + "4) When item is deleted, release the button\n" + + "5) Bug 456602: SWT will have an internal AIOOBE\n" + + "6) Bug 456602: More exceptions are reported if you set focus to\n" + + " Text beforehand and move the mouse after\n" + + "7) In real world, user would clicks faster, but crashes will\n" + + " still happen sometimes\n" + + "\n" + + "Bug 355200 and Bug 289483\n" + + "-------------------------\n" + + "Just to ensure that old workarounds are still working fine:\n" + + "1) Click any Table item when multiple items are selected\n" + + "2) SWT.Selection shall report clicked item\n" + + "3) The order shall be: SWT.MouseDown, SWT.Selection, SWT.MouseUp" + ); + + Table table = new Table(shell, SWT.BORDER | SWT.MULTI); + table.addListener(SWT.MouseDown, e -> { + System.out.println(System.currentTimeMillis() + " SWT.MouseDown: " + Arrays.toString(table.getSelectionIndices())); + }); + table.addListener(SWT.MouseUp, e -> { + System.out.println(System.currentTimeMillis() + " SWT.MouseUp: " + Arrays.toString(table.getSelectionIndices())); + }); + table.addListener(SWT.Selection, e -> { + System.out.println(System.currentTimeMillis() + " SWT.Selection: " + Arrays.toString(table.getSelectionIndices())); + }); + + for (int iItem = 0; iItem < 10; iItem++) { + new TableItem(table, 0).setText("Item #" + iItem); + } + table.selectAll(); + + Button button = new Button(shell, SWT.PUSH); + button.setText("Delete items after 2000ms"); + button.addListener(SWT.Selection, e -> { + display.timerExec(2000, () -> { + table.setItemCount(table.getItemCount() / 2); + }); + }); + + new Text(shell, 0).setText("I'm a text field"); + + shell.pack(); + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + + display.dispose(); + } +} diff --git a/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug546935_TableFlickeringResizingColumns.java b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug546935_TableFlickeringResizingColumns.java new file mode 100644 index 0000000000..fd759c4bfa --- /dev/null +++ b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug546935_TableFlickeringResizingColumns.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2021 Syntevo and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Syntevo - initial API and implementation + *******************************************************************************/ + +package org.eclipse.swt.tests.manual; + +import org.eclipse.swt.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +public class Bug546935_TableFlickeringResizingColumns { + public static void main(String[] args) { + final Display display = new Display(); + final Shell shell = new Shell(display); + shell.setLayout(new GridLayout(1, true)); + + final Label hint = new Label(shell, 0); + hint.setText( + "1) Run on Windows\n" + + "2) Choose a column where header is wider than items\n" + + "3) Double-click the header separator to auto-adjust column size\n" + + "4) Bug 546935: there is flickering even though column size doesn't change" + ); + + final Table table = new Table(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + table.setHeaderVisible(true); + + String[] columns = { + "column", + "header is longer" + }; + + String[] items = { + "item is longer", + "item" + }; + + for (int iColumn = 0; iColumn < columns.length * 3; iColumn++) { + final TableColumn tableColumn = new TableColumn(table, 0); + tableColumn.setText(columns[iColumn % columns.length]); + tableColumn.setWidth(100); + } + + for (int iItem = 0; iItem < 100; iItem++) { + TableItem item = new TableItem(table, 0); + for (int iColumn = 0; iColumn < table.getColumnCount(); iColumn++) { + item.setText(iColumn, items[iColumn % columns.length]); + } + } + + // 'MeasureItem' is required to reproduce. + table.addListener(SWT.MeasureItem, event -> { + event.width = 35; + }); + + // Debugging code, not needed to reproduce + { + final int[] itemsMeasured = new int[1]; + final int[] itemsPainted = new int[1]; + table.addListener(SWT.MeasureItem, event -> { + itemsMeasured[0]++; + }); + table.addListener(SWT.PaintItem, event -> { + itemsPainted[0]++; + }); + table.addListener(SWT.Paint, event -> { + System.out.format("Measured=%d Painted=%d%n", itemsMeasured[0], itemsPainted[0]); + itemsMeasured[0] = 0; + itemsPainted[0] = 0; + }); + } + + Button btnPackColumn = new Button(shell, SWT.PUSH); + btnPackColumn.setText("Pack columns"); + btnPackColumn.addListener(SWT.Selection, e -> { + for (int iColumn = 0; iColumn < table.getColumnCount(); iColumn++) { + table.getColumn(iColumn).pack(); + } + }); + + shell.setSize(800, 340); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + display.dispose(); + } +} diff --git a/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug577129_Win11_NoButtonArrows.java b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug577129_Win11_NoButtonArrows.java new file mode 100644 index 0000000000..1958c3eee0 --- /dev/null +++ b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug577129_Win11_NoButtonArrows.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2022 Syntevo and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Syntevo - initial API and implementation + *******************************************************************************/ + +package org.eclipse.swt.tests.manual; + +import org.eclipse.swt.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +public final class Bug577129_Win11_NoButtonArrows { + public static void main(String[] args) { + final Display display = new Display(); + final Shell shell = new Shell(display); + shell.setLayout (new GridLayout (1, true)); + + Label hint = new Label (shell, 0); + hint.setText ( + "1) Run on Win11 (Win10 is not enough)\n" + + "2) Bug 577129: Enabled buttons don't show arrows" + ); + + Composite composite = new Composite(shell, 0); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + composite.setLayout(new GridLayout (5, true)); + + Button button; + + new Label(composite, 0).setText(""); + new Label(composite, 0).setText("UP"); + new Label(composite, 0).setText("DOWN"); + new Label(composite, 0).setText("LEFT"); + new Label(composite, 0).setText("RIGHT"); + + for (int isEnabled = 0; isEnabled < 2; isEnabled++) { + if (isEnabled != 0) { + new Label(composite, 0).setText("Enabled"); + } else { + new Label(composite, 0).setText("Disabled"); + } + + button = new Button(composite, SWT.ARROW | SWT.UP); + if (isEnabled == 0) { + button.setEnabled(false); + } + + button = new Button(composite, SWT.ARROW | SWT.DOWN); + if (isEnabled == 0) { + button.setEnabled(false); + } + + button = new Button(composite, SWT.ARROW | SWT.LEFT); + if (isEnabled == 0) { + button.setEnabled(false); + } + + button = new Button(composite, SWT.ARROW | SWT.RIGHT); + if (isEnabled == 0) { + button.setEnabled(false); + } + } + + shell.pack(); + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + + display.dispose(); + } +} diff --git a/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug577878_GTK_TreeTable_NoDragImageWithPaintItem.java b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug577878_GTK_TreeTable_NoDragImageWithPaintItem.java new file mode 100644 index 0000000000..028e5c5cb6 --- /dev/null +++ b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug577878_GTK_TreeTable_NoDragImageWithPaintItem.java @@ -0,0 +1,216 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 Syntevo and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Syntevo - initial API and implementation + *******************************************************************************/ + +package org.eclipse.swt.tests.manual; + +import org.eclipse.swt.*; +import org.eclipse.swt.dnd.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +public final class Bug577878_GTK_TreeTable_NoDragImageWithPaintItem { + static final int NUM_ROWS = 100; + static final int NUM_COLS = 2; + static final int IMG_CX = 22; + static final int IMG_CY = 16; + + static String makeItemText(int iRow, int iCol) { + return "Item#" + iRow + ":" + iCol; + } + + static Image makeItemImage(Device device, int iRow) { + Image image = new Image(device, IMG_CX, IMG_CY); + GC gc = new GC(image); + gc.setBackground(new Color(100,255,100)); + gc.fillRectangle(0, 0, IMG_CX-1, IMG_CY-1); + gc.drawRectangle(0, 0, IMG_CX-1, IMG_CY-1); + + String text = Integer.toString(iRow); + Point textSize = gc.stringExtent(text); + gc.drawText(text, (IMG_CX - textSize.x) / 2, (IMG_CY - textSize.y) / 2); + + gc.dispose(); + return image; + } + + static void paintItem(Event event, Image image, int iRow) { + if (image != null) { + event.x += 2; + int y = event.y + (event.height - image.getBounds().height) / 2; + event.gc.drawImage(image, event.x, y); + event.x += image.getBounds().width; + } + + event.x += 2; + String text = makeItemText(iRow, event.index); + Point textSize = event.gc.stringExtent(text); + int y = event.y + (event.height - textSize.y) / 2; + event.gc.drawString (text, event.x, y, true); + } + + static void createTable(Composite parent, boolean isCustomPaint, boolean isImages) { + Table control = new Table (parent, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI); + control.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true)); + + control.setHeaderVisible (true); + for (int iColumn = 0; iColumn < NUM_COLS; iColumn++) { + TableColumn column = new TableColumn (control, 0); + column.setText ("Col#" + iColumn); + column.setWidth (120); + } + + control.setItemCount (NUM_ROWS); + + if (isImages) { + for (int iItem = 0; iItem < NUM_ROWS; iItem++) { + control.getItem(iItem).setImage(makeItemImage(parent.getDisplay(), iItem)); + } + } + + if (isCustomPaint) { + control.addListener (SWT.MeasureItem, e -> { + e.width = 120; + e.height = 20; + }); + + control.addListener (SWT.EraseItem, e -> { + e.detail &= ~SWT.FOREGROUND; + }); + + control.addListener (SWT.PaintItem, e -> { + TableItem item = (TableItem) e.item; + int iRow = item.getParent ().indexOf (item); + paintItem(e, item.getImage(), iRow); + }); + } else { + for (int iRow = 0; iRow < NUM_ROWS; iRow++) { + for (int iCol = 0; iCol < NUM_COLS; iCol++) { + control.getItem (iRow).setText (iCol, makeItemText(iRow, iCol)); + } + } + } + + DragSource dragSource = new DragSource (control, DND.DROP_MOVE | DND.DROP_COPY); + dragSource.setTransfer (TextTransfer.getInstance ()); + dragSource.addDragListener (new DragSourceAdapter ()); + } + + static void createTree(Composite parent, boolean isCustomPaint, boolean isImages) { + Tree control = new Tree (parent, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI); + control.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true)); + + control.setHeaderVisible (true); + for (int iColumn = 0; iColumn < NUM_COLS; iColumn++) { + TreeColumn column = new TreeColumn (control, 0); + column.setText ("Col#" + iColumn); + column.setWidth (120); + } + + control.setItemCount (NUM_ROWS); + + if (isImages) { + for (int iItem = 0; iItem < NUM_ROWS; iItem++) { + control.getItem(iItem).setImage(makeItemImage(parent.getDisplay(), iItem)); + } + } + + if (isCustomPaint) { + control.addListener (SWT.MeasureItem, e -> { + e.width = 120; + e.height = 20; + }); + + control.addListener (SWT.EraseItem, e -> { + e.detail &= ~SWT.FOREGROUND; + }); + + control.addListener (SWT.PaintItem, e -> { + TreeItem item = (TreeItem) e.item; + TreeItem parentItem = item.getParentItem (); + int iRow = (parentItem != null) ? parentItem.indexOf (item) : item.getParent ().indexOf (item); + paintItem(e, item.getImage(), iRow); + }); + } else { + for (int iRow = 0; iRow < NUM_ROWS; iRow++) { + for (int iCol = 0; iCol < NUM_COLS; iCol++) { + control.getItem (iRow).setText (iCol, makeItemText(iRow, iCol)); + } + } + } + + TreeItem child = new TreeItem (control.getItem(1), 0); + if (!isCustomPaint) { + for (int iCol = 0; iCol < NUM_COLS; iCol++) { + child.setText (iCol, makeItemText(0, iCol)); + } + } + + DragSource dragSource = new DragSource (control, DND.DROP_MOVE | DND.DROP_COPY); + dragSource.setTransfer (TextTransfer.getInstance ()); + dragSource.addDragListener (new DragSourceAdapter ()); + } + + public static void main(String[] args) { + final Display display = new Display(); + final Shell shell = new Shell(display); + shell.setLayout (new GridLayout (1, true)); + + Label hint = new Label(shell, 0); + hint.setText ( + "1) Run on GTK\n" + + "2) Drag rows from regular Table/Tree - there will be a drag image\n" + + "3) Bug 577878: Table/Tree with SWT.PaintItem do not have drag image\n" + + "\n" + + "Patch v2:\n" + + "4) Bug 577878 v2: Tree/Table with image should not have empty space\n" + + " to the left of the item\n" + + "5) Bug 579395: Tree with images and PaintItem overpaints expanders\n" + + " Old bug, not fixed in this patch." + ); + + Composite composite = new Composite (shell, 0); + composite.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true)); + composite.setLayout (new GridLayout (4, true)); + + new Label(composite, 0).setText ("Table"); + new Label(composite, 0).setText ("Table+Images"); + new Label(composite, 0).setText ("Table+PaintItem"); + new Label(composite, 0).setText ("Table+PaintItem+Images"); + createTable(composite, false, false); + createTable(composite, false, true); + createTable(composite, true, false); + createTable(composite, true, true); + + new Label(composite, 0).setText ("Tree"); + new Label(composite, 0).setText ("Tree+Images"); + new Label(composite, 0).setText ("Tree+PaintItem"); + new Label(composite, 0).setText ("Tree+PaintItem+Images"); + createTree(composite, false, false); + createTree(composite, false, true); + createTree(composite, true, false); + createTree(composite, true, true); + + shell.setSize (900, 600); + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + + display.dispose(); + } +} diff --git a/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug578171_macOS_JvmCrash_ShowMenuWindow.java b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug578171_macOS_JvmCrash_ShowMenuWindow.java new file mode 100644 index 0000000000..2fd8c97bae --- /dev/null +++ b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/Bug578171_macOS_JvmCrash_ShowMenuWindow.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2022 Syntevo and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Syntevo - initial API and implementation + *******************************************************************************/ + +package org.eclipse.swt.tests.manual; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +public class Bug578171_macOS_JvmCrash_ShowMenuWindow { + public static void main(String[] args) { + final Display display = new Display(); + final Shell shell = new Shell(display); + shell.setLayout(new GridLayout(1, true)); + + new Label(shell, 0).setText( + "1) Use macOS 12 (macOS < 12 are not affected)\n" + + "2) Press the button\n" + + "3) Click menu bar and move mouse left-right to switch between submenus\n" + + "4) Bug 578171: Popup Shell will be activated; that's a bug already\n" + + "5) Bug 578171: JVM will crash" + ); + + Menu rootMenu = new Menu(shell, SWT.BAR); + shell.setMenuBar(rootMenu); + for (int iMenu = 0; iMenu < 3; iMenu++) { + MenuItem rootItem = new MenuItem(rootMenu, SWT.CASCADE); + rootItem.setText("Menu:" + iMenu); + + Menu menu = new Menu(shell, SWT.DROP_DOWN); + rootItem.setMenu(menu); + + for (int iItem = 0; iItem < 10; iItem++) { + MenuItem item = new MenuItem(menu, SWT.CASCADE); + item.setText("MenuItem:" + iMenu + ":" + iItem); + } + } + + Button button = new Button(shell, SWT.PUSH); + button.setText("Show popup after 2000ms"); + button.addListener(SWT.Selection, e -> { + display.timerExec(2000, () -> { + Shell popup = new Shell(shell, SWT.DIALOG_TRIM); + popup.addListener(SWT.Activate, e2 -> { + System.out.println("Popup Shell SWT.Activate: It's a bug when it happens without clicking the popup"); + }); + + popup.setSize(100, 100); + popup.setVisible(true); + }); + }); + + new Label(shell, 0).setText("A text field so that you can check if Shell is still active:"); + new Text(shell, 0).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + shell.pack(); + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + + display.dispose(); + } +}
\ No newline at end of file diff --git a/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/SnippetDrawAlpha.java b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/SnippetDrawAlpha.java new file mode 100644 index 0000000000..2570ba506e --- /dev/null +++ b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/SnippetDrawAlpha.java @@ -0,0 +1,98 @@ +package org.eclipse.swt.tests.manual; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageLoader; +import org.eclipse.swt.graphics.PaletteData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +public class SnippetDrawAlpha { + public static void main(String[] args) { + Display display = new Display(); + Shell shell = new Shell(display); + shell.setLayout(new GridLayout(4, false)); + + createImageLabels(display, shell, "/eclipse16.png"); + createImageLabels(display, shell, "/eclipse32.png"); + createImageLabels(display, shell, "/pause.gif"); + createImageLabels(display, shell, "/run.gif"); + createImageLabels(display, shell, "/warning.gif"); + createImageLabels(display, shell, "/transparent.png"); + + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } + + private static void createImageLabels(Display display, Shell shell, String fileName) { + createImageLabel(display, shell, fileName, -1); + createImageLabel(display, shell, fileName, 1); + createImageLabel(display, shell, fileName, 1.5f); + createImageLabel(display, shell, fileName, 2); + } + + private static void createImageLabel(Display display, Shell shell, String fileName, float scaleFactor) { + ImageLoader loader = new ImageLoader(); + loader.load(SnippetDrawAlpha.class.getResourceAsStream(fileName)); + ImageData data = loader.data[0]; + if (scaleFactor != -1) { + data = autoScaleImageData(display, data, scaleFactor); + } + Image image = new Image(display, data); + Label label = new Label(shell, SWT.NONE); + label.setImage(image); + } + + private static ImageData autoScaleImageData(Device device, final ImageData imageData, float scaleFactor) { + int width = imageData.width; + int height = imageData.height; + int scaledWidth = Math.round(width * scaleFactor); + int scaledHeight = Math.round(height * scaleFactor); + + Image original = new Image(device, imageData); + + /* Create a 24 bit image data with alpha channel */ + final ImageData resultData = new ImageData(scaledWidth, scaledHeight, 24, + new PaletteData(0xFF, 0xFF00, 0xFF0000)); + resultData.alphaData = new byte[scaledWidth * scaledHeight]; + + /* + * FIXME: something is wrong in SWT on win32. alphaData is apparently + * not used in GC#drawImage(..) below, and images end up fully + * transparent. + */ +// if ("win32".equals(SWT.getPlatform())) { +// // This hack makes the images at least visible, but loses all transparency: +// Arrays.fill (resultData.alphaData, (byte) 0xFF); +// // Makes the wrong non-transparent background white instead of black: +// Arrays.fill(resultData.data, (byte) 0xFF); +// } + + Image resultImage = new Image(device, resultData); + GC gc = new GC(resultImage); + gc.setAntialias(SWT.ON); + gc.drawImage(original, 0, 0, width, height, + /* + * E.g. destWidth here is effectively DPIUtil.autoScaleDown + * (scaledWidth), but avoiding rounding errors. Nevertheless, we + * still have some rounding errors due to the point-based API + * GC#drawImage(..). + */ + 0, 0, scaledWidth, scaledHeight); + gc.dispose(); + original.dispose(); + ImageData result = resultImage.getImageData(); + resultImage.dispose(); + return result; + } +}
\ No newline at end of file diff --git a/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/SnippetDrawAlphaTwoPass.java b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/SnippetDrawAlphaTwoPass.java new file mode 100644 index 0000000000..9e21d134d4 --- /dev/null +++ b/tests/org.eclipse.swt.tests/ManualTests/org/eclipse/swt/tests/manual/SnippetDrawAlphaTwoPass.java @@ -0,0 +1,159 @@ +package org.eclipse.swt.tests.manual; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageLoader; +import org.eclipse.swt.graphics.PaletteData; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +public class SnippetDrawAlphaTwoPass { + + // Alpha and BW palette definitions from org.eclipse.ui.internal.decorators.DecorationImageBuilder + private static final PaletteData ALPHA_PALETTE, BW_PALETTE; + + static { + RGB[] rgbs = new RGB[256]; + for (int i = 0; i < rgbs.length; i++) { + rgbs[i] = new RGB(i, i, i); + } + + ALPHA_PALETTE = new PaletteData(rgbs); + BW_PALETTE = new PaletteData(new RGB[] { new RGB(0, 0, 0), new RGB(255, 255, 255) }); + } + + public static void main(String[] args) { + Display display = new Display(); + Shell shell = new Shell(display); + shell.setLayout(new GridLayout(4, false)); + + createImageLabels(display, shell, "/eclipse16.png"); + createImageLabels(display, shell, "/eclipse32.png"); + createImageLabels(display, shell, "/pause.gif"); + createImageLabels(display, shell, "/run.gif"); + createImageLabels(display, shell, "/warning.gif"); + createImageLabels(display, shell, "/transparent.png"); + + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } + + private static void createImageLabels(Display display, Shell shell, String fileName) { + createImageLabel(display, shell, fileName, -1); + createImageLabel(display, shell, fileName, 1); + createImageLabel(display, shell, fileName, 1.5f); + createImageLabel(display, shell, fileName, 2); + } + + private static void createImageLabel(Display display, Shell shell, String fileName, float scaleFactor) { + ImageLoader loader = new ImageLoader(); + loader.load(SnippetDrawAlpha.class.getResourceAsStream(fileName)); + ImageData data = loader.data[0]; + if (scaleFactor != -1) { + data = autoScaleImageData(display, data, scaleFactor); + } + Image image = new Image(display, data); + Label label = new Label(shell, SWT.NONE); + label.setImage(image); + } + + private static ImageData autoScaleImageData(Device device, final ImageData imageData, float scaleFactor) { + int width = imageData.width; + int height = imageData.height; + int scaledWidth = Math.round(width * scaleFactor); + int scaledHeight = Math.round(height * scaleFactor); + + ImageData imageMaskData = null; + + if (imageData.getTransparencyType() == SWT.TRANSPARENCY_ALPHA) { + imageMaskData = new ImageData(width, height, 8, ALPHA_PALETTE, 1, imageData.alphaData); + } else if (imageData.getTransparencyType() == SWT.TRANSPARENCY_PIXEL || imageData.getTransparencyType() == SWT.TRANSPARENCY_MASK) { + ImageData transparencyMaskData = imageData.getTransparencyMask(); + imageMaskData = new ImageData(width, height, 1, BW_PALETTE, transparencyMaskData.scanlinePad, transparencyMaskData.data); + } + + Image original = new Image(device, imageData); + Image originalMask = null; + + if (imageMaskData != null) { + originalMask = new Image(device, imageMaskData); + } + + /* Create a 24 bit image data with alpha channel */ + ImageData resultData = new ImageData(scaledWidth, scaledHeight, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000)); + ImageData resultMaskData = null; + + if (imageMaskData != null) { + resultMaskData = new ImageData(scaledWidth, scaledHeight, imageMaskData.depth, imageMaskData.palette); + } + + Image result = new Image(device, resultData); + Image resultMask = null; + + GC gc = new GC(result); + gc.setAntialias(SWT.ON); + gc.drawImage(original, 0, 0, width, height, 0, 0, scaledWidth, scaledHeight); + gc.dispose(); + + if (resultMaskData != null) { + resultMask = new Image(device, resultMaskData); + gc = new GC(resultMask); + gc.setAntialias(SWT.ON); + gc.drawImage(originalMask, 0, 0, width, height, 0, 0, scaledWidth, scaledHeight); + gc.dispose(); + } + + original.dispose(); + originalMask.dispose(); + + ImageData scaledResult = result.getImageData(); + + if (resultMask != null) { + ImageData scaledResultMaskData = resultMask.getImageData(); + + // Convert 1-bit mask + if (scaledResultMaskData.depth == 1) { + scaledResult.maskPad = scaledResultMaskData.scanlinePad; + scaledResult.maskData = scaledResultMaskData.data; + } else { + byte[] alphaData = scaledResultMaskData.data; + if (scaledResultMaskData.scanlinePad != 1) { + alphaData = convertPad(scaledResultMaskData.data, scaledResultMaskData.width, scaledResultMaskData.height, + scaledResultMaskData.depth, scaledResultMaskData.scanlinePad, 1); + } + scaledResult.alphaData = alphaData; + } + } + + result.dispose(); + resultMask.dispose(); + return scaledResult; + } + + // copied from ImageData.convertPad as it is not accessible outside the org.eclipse.swt package + private static byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) { + if (pad == newPad) return data; + int stride = (width * depth + 7) / 8; + int bpl = (stride + (pad - 1)) / pad * pad; + int newBpl = (stride + (newPad - 1)) / newPad * newPad; + byte[] newData = new byte[height * newBpl]; + int srcIndex = 0, destIndex = 0; + for (int y = 0; y < height; y++) { + System.arraycopy(data, srcIndex, newData, destIndex, stride); + srcIndex += bpl; + destIndex += newBpl; + } + return newData; + } +}
\ No newline at end of file diff --git a/tests/org.eclipse.swt.tests/data/eclipse.png b/tests/org.eclipse.swt.tests/data/eclipse.png Binary files differnew file mode 100644 index 0000000000..73975241eb --- /dev/null +++ b/tests/org.eclipse.swt.tests/data/eclipse.png diff --git a/tests/org.eclipse.swt.tests/data/eclipse16.png b/tests/org.eclipse.swt.tests/data/eclipse16.png Binary files differnew file mode 100644 index 0000000000..7fc69518a8 --- /dev/null +++ b/tests/org.eclipse.swt.tests/data/eclipse16.png diff --git a/tests/org.eclipse.swt.tests/data/eclipse24.png b/tests/org.eclipse.swt.tests/data/eclipse24.png Binary files differnew file mode 100644 index 0000000000..fbddd3cd78 --- /dev/null +++ b/tests/org.eclipse.swt.tests/data/eclipse24.png diff --git a/tests/org.eclipse.swt.tests/data/eclipse32.png b/tests/org.eclipse.swt.tests/data/eclipse32.png Binary files differnew file mode 100644 index 0000000000..bf85680075 --- /dev/null +++ b/tests/org.eclipse.swt.tests/data/eclipse32.png diff --git a/tests/org.eclipse.swt.tests/data/pause.gif b/tests/org.eclipse.swt.tests/data/pause.gif Binary files differnew file mode 100644 index 0000000000..161e3f594f --- /dev/null +++ b/tests/org.eclipse.swt.tests/data/pause.gif diff --git a/tests/org.eclipse.swt.tests/data/run.gif b/tests/org.eclipse.swt.tests/data/run.gif Binary files differnew file mode 100644 index 0000000000..944a230aad --- /dev/null +++ b/tests/org.eclipse.swt.tests/data/run.gif diff --git a/tests/org.eclipse.swt.tests/data/warning.gif b/tests/org.eclipse.swt.tests/data/warning.gif Binary files differnew file mode 100644 index 0000000000..cf4fdf93c7 --- /dev/null +++ b/tests/org.eclipse.swt.tests/data/warning.gif diff --git a/tests/org.eclipse.swt.tests/pom.xml b/tests/org.eclipse.swt.tests/pom.xml index 264d236f70..997f93499a 100644 --- a/tests/org.eclipse.swt.tests/pom.xml +++ b/tests/org.eclipse.swt.tests/pom.xml @@ -14,12 +14,12 @@ <parent> <artifactId>eclipse.platform.swt.localbuild</artifactId> <groupId>eclipse.platform.swt</groupId> - <version>4.23.0-SNAPSHOT</version> + <version>4.24.0-SNAPSHOT</version> <relativePath>../../local-build/local-build-parent/</relativePath> </parent> <groupId>org.eclipse.swt</groupId> <artifactId>org.eclipse.swt.tests</artifactId> - <version>3.106.1600-SNAPSHOT</version> + <version>3.106.1700-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> <code.ignoredWarnings>${tests.ignoredWarnings}</code.ignoredWarnings> |