Skip to content

Commit 0b8b740

Browse files
committed
PoC - Use Foreign Function & Memory API for GTK3 OS Support
1 parent 60dc886 commit 0b8b740

File tree

17 files changed

+622
-14
lines changed

17 files changed

+622
-14
lines changed

org.eclipse.wb.os.linux/.classpath

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<classpath>
3-
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21"/>
3+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-24">
4+
<attributes>
5+
<attribute name="module" value="true"/>
6+
</attributes>
7+
</classpathentry>
48
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
59
<classpathentry kind="src" path="src"/>
10+
<classpathentry kind="src" path="src_java25">
11+
<attributes>
12+
<attribute name="release" value="25"/>
13+
</attributes>
14+
</classpathentry>
615
<classpathentry kind="output" path="bin"/>
716
</classpath>

org.eclipse.wb.os.linux/.settings/org.eclipse.jdt.core.prefs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
eclipse.preferences.version=1
22
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3-
org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
3+
org.eclipse.jdt.core.compiler.codegen.targetPlatform=24
44
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5-
org.eclipse.jdt.core.compiler.compliance=21
5+
org.eclipse.jdt.core.compiler.compliance=24
66
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
77
org.eclipse.jdt.core.compiler.debug.localVariable=generate
88
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -65,7 +65,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa
6565
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
6666
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
6767
org.eclipse.jdt.core.compiler.release=enabled
68-
org.eclipse.jdt.core.compiler.source=21
68+
org.eclipse.jdt.core.compiler.source=24
6969
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
7070
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
7171
org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=true

org.eclipse.wb.os.linux/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.wb.os.linux;singleton:=true
55
Bundle-Version: 1.10.300.qualifier
66
Bundle-Vendor: %providerName
7-
Bundle-RequiredExecutionEnvironment: JavaSE-21
7+
Bundle-RequiredExecutionEnvironment: JavaSE-24
88
Eclipse-PlatformFilter: (& (osgi.ws=gtk) (osgi.os=linux))
99
Require-Bundle: org.eclipse.swt;bundle-version="[3.126.0,4.0.0)",
1010
org.eclipse.core.runtime;bundle-version="[3.31.100,4.0.0)",
@@ -18,6 +18,7 @@ Bundle-ActivationPolicy: lazy
1818
Bundle-Localization: plugin
1919
Import-Package: org.apache.commons.io;version="[2.16.1,3.0.0)",
2020
org.apache.commons.lang3;version="[3.14.0,4.0.0)",
21+
org.apache.commons.lang3.function;version="[3.14.0,4.0.0)",
2122
org.eclipse.wb.os
2223
Automatic-Module-Name: org.eclipse.wb.os.linux
2324
Provide-Capability: wbp;type=os

org.eclipse.wb.os.linux/src/org/eclipse/wb/internal/os/linux/OSSupportLinux.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.eclipse.swt.widgets.Menu;
3636
import org.eclipse.swt.widgets.MenuItem;
3737
import org.eclipse.swt.widgets.Shell;
38+
import org.eclipse.swt.widgets.TabItem;
3839
import org.eclipse.swt.widgets.Tree;
3940
import org.eclipse.swt.widgets.Widget;
4041

@@ -518,7 +519,7 @@ public final int getDefaultMenuBarHeight() {
518519
//
519520
////////////////////////////////////////////////////////////////////////////
520521
@Override
521-
public final Rectangle getTabItemBounds(Object tabItem) {
522+
public final Rectangle getTabItemBounds(TabItem tabItem) {
522523
return getWidgetBounds(tabItem);
523524
}
524525

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Patrick Ziegler and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* https://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Patrick Ziegler - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.wb.internal.os.linux;
14+
15+
import java.lang.foreign.Arena;
16+
import java.lang.foreign.MemoryLayout;
17+
import java.lang.foreign.MemorySegment;
18+
import java.lang.foreign.StructLayout;
19+
import java.lang.foreign.ValueLayout;
20+
21+
/**
22+
* A GdkRectangle data type for representing rectangles.
23+
*
24+
* GdkRectangle is identical to cairo_rectangle_t. Together with Cairo’s
25+
* cairo_region_t data type, these are the central types for representing sets
26+
* of pixels.
27+
*
28+
* The intersection of two rectangles can be computed with
29+
* gdk_rectangle_intersect(); to find the union of two rectangles use
30+
* gdk_rectangle_union().
31+
*
32+
* The cairo_region_t type provided by Cairo is usually used for managing
33+
* non-rectangular clipping of graphical operations.
34+
*
35+
* The Graphene library has a number of other data types for regions and volumes
36+
* in 2D and 3D.
37+
*/
38+
public sealed class GdkRectangle permits GtkAllocation {
39+
private static final StructLayout LAYOUT = MemoryLayout.structLayout( //
40+
ValueLayout.JAVA_INT.withName("x"), //
41+
ValueLayout.JAVA_INT.withName("y"), //
42+
ValueLayout.JAVA_INT.withName("width"), //
43+
ValueLayout.JAVA_INT.withName("height"));
44+
45+
private final MemorySegment segment;
46+
47+
public GdkRectangle(Arena arena) {
48+
segment = arena.allocate(LAYOUT);
49+
}
50+
51+
public final int x() {
52+
return segment.get(ValueLayout.JAVA_INT, 0);
53+
}
54+
55+
public final int y() {
56+
return segment.get(ValueLayout.JAVA_INT, 4);
57+
}
58+
59+
public final int width() {
60+
return segment.get(ValueLayout.JAVA_INT, 8);
61+
}
62+
63+
public final int height() {
64+
return segment.get(ValueLayout.JAVA_INT, 12);
65+
}
66+
67+
public final MemorySegment segment() {
68+
return segment;
69+
}
70+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Patrick Ziegler and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* https://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Patrick Ziegler - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.wb.internal.os.linux;
14+
15+
import java.lang.foreign.Arena;
16+
17+
/**
18+
* A GtkAllocation-struct of a widget represents region which has been allocated
19+
* to the widget by its parent. It is a subregion of its parents allocation.
20+
*/
21+
public final class GtkAllocation extends GdkRectangle {
22+
public GtkAllocation(Arena arena) {
23+
super(arena);
24+
}
25+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Patrick Ziegler and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* https://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Patrick Ziegler - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.wb.internal.os.linux;
14+
15+
import org.eclipse.wb.os.OSRuntimeException;
16+
17+
/**
18+
* Wrapper for all exceptions thrown while accessing native code.
19+
*/
20+
public class GtkRuntimeException extends OSRuntimeException {
21+
private static final long serialVersionUID = 1L;
22+
23+
public GtkRuntimeException(Throwable t) {
24+
super(t);
25+
}
26+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Patrick Ziegler and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* https://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Patrick Ziegler - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.wb.internal.os.linux;
14+
15+
import org.eclipse.wb.internal.os.linux.gtk3.GTK3;
16+
import org.eclipse.wb.internal.os.linux.gtk3.GtkWidget;
17+
import org.eclipse.wb.internal.swt.VisualDataMockupProvider;
18+
import org.eclipse.wb.os.OSSupport;
19+
20+
import org.eclipse.swt.graphics.Image;
21+
import org.eclipse.swt.graphics.Point;
22+
import org.eclipse.swt.graphics.Rectangle;
23+
import org.eclipse.swt.widgets.Control;
24+
import org.eclipse.swt.widgets.Menu;
25+
import org.eclipse.swt.widgets.MenuItem;
26+
import org.eclipse.swt.widgets.Shell;
27+
import org.eclipse.swt.widgets.TabItem;
28+
import org.eclipse.swt.widgets.Tree;
29+
import org.eclipse.swt.widgets.Widget;
30+
31+
import java.lang.foreign.Arena;
32+
import java.util.List;
33+
34+
public final class OSSupportLinux extends OSSupport {
35+
private final VisualDataMockupProvider mockupProvider = new VisualDataMockupProvider();
36+
37+
////////////////////////////////////////////////////////////////////////////
38+
//
39+
// Screen shot
40+
//
41+
////////////////////////////////////////////////////////////////////////////
42+
43+
@Override
44+
public void makeShots(Object control) throws Exception {
45+
// TODO Auto-generated method stub
46+
47+
}
48+
49+
@Override
50+
public Image makeShot(Control control) throws Exception {
51+
// TODO Auto-generated method stub
52+
return null;
53+
}
54+
55+
////////////////////////////////////////////////////////////////////////////
56+
//
57+
// Menu
58+
//
59+
////////////////////////////////////////////////////////////////////////////
60+
61+
@Override
62+
public Image getMenuPopupVisualData(Menu menu, int[] bounds) throws Exception {
63+
return mockupProvider.mockMenuPopupVisualData(menu, bounds);
64+
}
65+
66+
@Override
67+
public Image getMenuBarVisualData(Menu menu, List<Rectangle> bounds) {
68+
for (int i = 0; i < menu.getItemCount(); ++i) {
69+
MenuItem item = menu.getItem(i);
70+
bounds.add(getWidgetBounds(item));
71+
}
72+
return null;
73+
}
74+
75+
@Override
76+
public Rectangle getMenuBarBounds(Menu menu) {
77+
Rectangle bounds = getWidgetBounds(menu);
78+
Shell shell = menu.getShell();
79+
Point p = shell.toControl(shell.getLocation());
80+
p.x = -p.x;
81+
p.y = -p.y - bounds.height;
82+
return new Rectangle(p.x, p.y, bounds.width, bounds.height);
83+
}
84+
85+
@Override
86+
public int getDefaultMenuBarHeight() {
87+
// no way :(
88+
return 24;
89+
}
90+
91+
////////////////////////////////////////////////////////////////////////////
92+
//
93+
// TabItem
94+
//
95+
////////////////////////////////////////////////////////////////////////////
96+
97+
@Override
98+
public Rectangle getTabItemBounds(TabItem item) {
99+
return getWidgetBounds(item);
100+
}
101+
102+
////////////////////////////////////////////////////////////////////////////
103+
//
104+
// Alpha
105+
//
106+
////////////////////////////////////////////////////////////////////////////
107+
108+
@Override
109+
@SuppressWarnings("deprecation")
110+
public void setAlpha(Shell shell, int alpha) {
111+
GtkWidget widget = new GtkWidget(shell);
112+
if (GTK3.gtk_widget_is_composited(widget)) {
113+
GTK3.gtk_widget_set_opacity(widget, alpha / 255.0);
114+
}
115+
}
116+
117+
@Override
118+
@SuppressWarnings("deprecation")
119+
public int getAlpha(Shell shell) {
120+
GtkWidget widget = new GtkWidget(shell);
121+
if (GTK3.gtk_widget_is_composited(widget)) {
122+
return (int) (GTK3.gtk_widget_get_opacity(widget) * 255);
123+
}
124+
return 255;
125+
}
126+
127+
////////////////////////////////////////////////////////////////////////////
128+
//
129+
// Tree
130+
//
131+
////////////////////////////////////////////////////////////////////////////
132+
133+
@Override
134+
public boolean isPlusMinusTreeClick(Tree tree, int x, int y) {
135+
// TODO Auto-generated method stub
136+
return false;
137+
}
138+
139+
////////////////////////////////////////////////////////////////////////////
140+
//
141+
// Utils
142+
//
143+
////////////////////////////////////////////////////////////////////////////
144+
private Rectangle getWidgetBounds(Widget w) {
145+
GtkWidget widget = new GtkWidget(w);
146+
try (Arena arena = Arena.ofConfined()) {
147+
GtkAllocation allocation = new GtkAllocation(arena);
148+
GTK3.gtk_widget_get_allocation(widget, allocation);
149+
return new Rectangle(allocation.x(), allocation.y(), allocation.width(), allocation.height());
150+
}
151+
}
152+
}

0 commit comments

Comments
 (0)