aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/app
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/app')
-rw-r--r--vendor/gioui.org/app/Gio.java (renamed from vendor/gioui.org/app/internal/window/Gio.java)0
-rw-r--r--vendor/gioui.org/app/GioActivity.java (renamed from vendor/gioui.org/app/internal/window/GioActivity.java)15
-rw-r--r--vendor/gioui.org/app/GioView.java480
-rw-r--r--vendor/gioui.org/app/app.go4
-rw-r--r--vendor/gioui.org/app/app_android.go48
-rw-r--r--vendor/gioui.org/app/d3d11_windows.go135
-rw-r--r--vendor/gioui.org/app/datadir.go1
-rw-r--r--vendor/gioui.org/app/datadir_android.go41
-rw-r--r--vendor/gioui.org/app/egl_android.go66
-rw-r--r--vendor/gioui.org/app/egl_wayland.go (renamed from vendor/gioui.org/app/internal/window/egl_wayland.go)43
-rw-r--r--vendor/gioui.org/app/egl_windows.go (renamed from vendor/gioui.org/app/internal/window/egl_windows.go)27
-rw-r--r--vendor/gioui.org/app/egl_x11.go59
-rw-r--r--vendor/gioui.org/app/framework_ios.h (renamed from vendor/gioui.org/app/internal/window/framework_ios.h)0
-rw-r--r--vendor/gioui.org/app/gl_ios.go (renamed from vendor/gioui.org/app/internal/window/gl_ios.go)93
-rw-r--r--vendor/gioui.org/app/gl_ios.m (renamed from vendor/gioui.org/app/internal/window/gl_ios.m)6
-rw-r--r--vendor/gioui.org/app/gl_js.go69
-rw-r--r--vendor/gioui.org/app/gl_macos.go121
-rw-r--r--vendor/gioui.org/app/gl_macos.m74
-rw-r--r--vendor/gioui.org/app/internal/cocoainit/cocoa_darwin.go20
-rw-r--r--vendor/gioui.org/app/internal/d3d11/backend_windows.go856
-rw-r--r--vendor/gioui.org/app/internal/d3d11/d3d11_windows.go1344
-rw-r--r--vendor/gioui.org/app/internal/egl/egl.go279
-rw-r--r--vendor/gioui.org/app/internal/egl/egl_unix.go104
-rw-r--r--vendor/gioui.org/app/internal/egl/egl_windows.go164
-rw-r--r--vendor/gioui.org/app/internal/glimpl/gl.go541
-rw-r--r--vendor/gioui.org/app/internal/glimpl/gl_js.go339
-rw-r--r--vendor/gioui.org/app/internal/glimpl/gl_windows.go406
-rw-r--r--vendor/gioui.org/app/internal/log/log_android.go24
-rw-r--r--vendor/gioui.org/app/internal/log/log_ios.go9
-rw-r--r--vendor/gioui.org/app/internal/log/log_ios.m11
-rw-r--r--vendor/gioui.org/app/internal/srgb/srgb.go195
-rw-r--r--vendor/gioui.org/app/internal/window/GioView.java255
-rw-r--r--vendor/gioui.org/app/internal/window/d3d11_windows.go102
-rw-r--r--vendor/gioui.org/app/internal/window/egl_android.go54
-rw-r--r--vendor/gioui.org/app/internal/window/egl_x11.go50
-rw-r--r--vendor/gioui.org/app/internal/window/gl_js.go98
-rw-r--r--vendor/gioui.org/app/internal/window/gl_macos.go90
-rw-r--r--vendor/gioui.org/app/internal/window/gl_macos.m143
-rw-r--r--vendor/gioui.org/app/internal/window/os_android.c96
-rw-r--r--vendor/gioui.org/app/internal/window/os_android.go684
-rw-r--r--vendor/gioui.org/app/internal/window/os_darwin.m22
-rw-r--r--vendor/gioui.org/app/internal/window/os_macos.go460
-rw-r--r--vendor/gioui.org/app/internal/window/os_unix.go39
-rw-r--r--vendor/gioui.org/app/internal/window/window.go102
-rw-r--r--vendor/gioui.org/app/internal/windows/windows.go157
-rw-r--r--vendor/gioui.org/app/internal/xkb/xkb_unix.go15
-rw-r--r--vendor/gioui.org/app/loop.go157
-rw-r--r--vendor/gioui.org/app/metal_darwin.go172
-rw-r--r--vendor/gioui.org/app/metal_ios.go48
-rw-r--r--vendor/gioui.org/app/metal_macos.go49
-rw-r--r--vendor/gioui.org/app/os.go220
-rw-r--r--vendor/gioui.org/app/os_android.go1283
-rw-r--r--vendor/gioui.org/app/os_darwin.go (renamed from vendor/gioui.org/app/internal/window/os_darwin.go)76
-rw-r--r--vendor/gioui.org/app/os_darwin.m12
-rw-r--r--vendor/gioui.org/app/os_ios.go (renamed from vendor/gioui.org/app/internal/window/os_ios.go)162
-rw-r--r--vendor/gioui.org/app/os_ios.m (renamed from vendor/gioui.org/app/internal/window/os_ios.m)90
-rw-r--r--vendor/gioui.org/app/os_js.go (renamed from vendor/gioui.org/app/internal/window/os_js.go)342
-rw-r--r--vendor/gioui.org/app/os_macos.go663
-rw-r--r--vendor/gioui.org/app/os_macos.m (renamed from vendor/gioui.org/app/internal/window/os_macos.m)191
-rw-r--r--vendor/gioui.org/app/os_unix.go50
-rw-r--r--vendor/gioui.org/app/os_wayland.c (renamed from vendor/gioui.org/app/internal/window/os_wayland.c)4
-rw-r--r--vendor/gioui.org/app/os_wayland.go (renamed from vendor/gioui.org/app/internal/window/os_wayland.go)328
-rw-r--r--vendor/gioui.org/app/os_windows.go (renamed from vendor/gioui.org/app/internal/window/os_windows.go)486
-rw-r--r--vendor/gioui.org/app/os_x11.go (renamed from vendor/gioui.org/app/internal/window/os_x11.go)420
-rw-r--r--vendor/gioui.org/app/runmain.go (renamed from vendor/gioui.org/app/internal/window/runmain.go)3
-rw-r--r--vendor/gioui.org/app/sigpipe_darwin.go18
-rw-r--r--vendor/gioui.org/app/vulkan.go210
-rw-r--r--vendor/gioui.org/app/vulkan_android.go90
-rw-r--r--vendor/gioui.org/app/vulkan_wayland.go81
-rw-r--r--vendor/gioui.org/app/vulkan_x11.go81
-rw-r--r--vendor/gioui.org/app/wayland_text_input.c (renamed from vendor/gioui.org/app/internal/window/wayland_text_input.c)40
-rw-r--r--vendor/gioui.org/app/wayland_text_input.h (renamed from vendor/gioui.org/app/internal/window/wayland_text_input.h)21
-rw-r--r--vendor/gioui.org/app/wayland_xdg_decoration.c (renamed from vendor/gioui.org/app/internal/window/wayland_xdg_decoration.c)20
-rw-r--r--vendor/gioui.org/app/wayland_xdg_decoration.h (renamed from vendor/gioui.org/app/internal/window/wayland_xdg_decoration.h)12
-rw-r--r--vendor/gioui.org/app/wayland_xdg_shell.c (renamed from vendor/gioui.org/app/internal/window/wayland_xdg_shell.c)107
-rw-r--r--vendor/gioui.org/app/wayland_xdg_shell.h (renamed from vendor/gioui.org/app/internal/window/wayland_xdg_shell.h)191
-rw-r--r--vendor/gioui.org/app/window.go734
77 files changed, 6549 insertions, 7753 deletions
diff --git a/vendor/gioui.org/app/internal/window/Gio.java b/vendor/gioui.org/app/Gio.java
index 33e1a68..33e1a68 100644
--- a/vendor/gioui.org/app/internal/window/Gio.java
+++ b/vendor/gioui.org/app/Gio.java
diff --git a/vendor/gioui.org/app/internal/window/GioActivity.java b/vendor/gioui.org/app/GioActivity.java
index 260d4b6..4565e38 100644
--- a/vendor/gioui.org/app/internal/window/GioActivity.java
+++ b/vendor/gioui.org/app/GioActivity.java
@@ -3,12 +3,8 @@
package org.gioui;
import android.app.Activity;
-import android.content.res.Configuration;
-import android.os.Build;
import android.os.Bundle;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
+import android.content.res.Configuration;
public final class GioActivity extends Activity {
private GioView view;
@@ -16,13 +12,8 @@ public final class GioActivity extends Activity {
@Override public void onCreate(Bundle state) {
super.onCreate(state);
- Window w = getWindow();
-
this.view = new GioView(this);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- this.view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- }
- this.view.setLayoutParams(new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT));
+
setContentView(view);
}
@@ -48,7 +39,7 @@ public final class GioActivity extends Activity {
@Override public void onLowMemory() {
super.onLowMemory();
- view.lowMemory();
+ GioView.onLowMemory();
}
@Override public void onBackPressed() {
diff --git a/vendor/gioui.org/app/GioView.java b/vendor/gioui.org/app/GioView.java
new file mode 100644
index 0000000..14639b0
--- /dev/null
+++ b/vendor/gioui.org/app/GioView.java
@@ -0,0 +1,480 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package org.gioui;
+
+import java.lang.Class;
+import java.lang.IllegalAccessException;
+import java.lang.InstantiationException;
+import java.lang.ExceptionInInitializerError;
+import java.lang.SecurityException;
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.Editable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.WindowInsets;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.view.Window;
+import android.view.WindowInsetsController;
+import android.view.WindowManager;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.EditorInfo;
+import android.text.InputType;
+import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import java.io.UnsupportedEncodingException;
+
+public final class GioView extends SurfaceView {
+ private static boolean jniLoaded;
+
+ private final SurfaceHolder.Callback surfCallbacks;
+ private final View.OnFocusChangeListener focusCallback;
+ private final InputMethodManager imm;
+ private final float scrollXScale;
+ private final float scrollYScale;
+ private int keyboardHint;
+ private AccessibilityManager accessManager;
+
+ private long nhandle;
+
+ public GioView(Context context) {
+ this(context, null);
+ }
+
+ public GioView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ }
+ setLayoutParams(new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT));
+
+ // Late initialization of the Go runtime to wait for a valid context.
+ Gio.init(context.getApplicationContext());
+
+ // Set background color to transparent to avoid a flickering
+ // issue on ChromeOS.
+ setBackgroundColor(Color.argb(0, 0, 0, 0));
+
+ ViewConfiguration conf = ViewConfiguration.get(context);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ scrollXScale = conf.getScaledHorizontalScrollFactor();
+ scrollYScale = conf.getScaledVerticalScrollFactor();
+
+ // The platform focus highlight is not aware of Gio's widgets.
+ setDefaultFocusHighlightEnabled(false);
+ } else {
+ float listItemHeight = 48; // dp
+ float px = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ listItemHeight,
+ getResources().getDisplayMetrics()
+ );
+ scrollXScale = px;
+ scrollYScale = px;
+ }
+
+ accessManager = (AccessibilityManager)context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ nhandle = onCreateView(this);
+ imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ focusCallback = new View.OnFocusChangeListener() {
+ @Override public void onFocusChange(View v, boolean focus) {
+ GioView.this.onFocusChange(nhandle, focus);
+ }
+ };
+ setOnFocusChangeListener(focusCallback);
+ surfCallbacks = new SurfaceHolder.Callback() {
+ @Override public void surfaceCreated(SurfaceHolder holder) {
+ // Ignore; surfaceChanged is guaranteed to be called immediately after this.
+ }
+ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ onSurfaceChanged(nhandle, getHolder().getSurface());
+ }
+ @Override public void surfaceDestroyed(SurfaceHolder holder) {
+ onSurfaceDestroyed(nhandle);
+ }
+ };
+ getHolder().addCallback(surfCallbacks);
+ }
+
+ @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (nhandle != 0) {
+ onKeyEvent(nhandle, keyCode, event.getUnicodeChar(), event.getEventTime());
+ }
+ return false;
+ }
+
+ @Override public boolean onGenericMotionEvent(MotionEvent event) {
+ dispatchMotionEvent(event);
+ return true;
+ }
+
+ @Override public boolean onTouchEvent(MotionEvent event) {
+ // Ask for unbuffered events. Flutter and Chrome do it
+ // so assume it's good for us as well.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ requestUnbufferedDispatch(event);
+ }
+
+ dispatchMotionEvent(event);
+ return true;
+ }
+
+ private void setCursor(int id) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ return;
+ }
+ PointerIcon pointerIcon = PointerIcon.getSystemIcon(getContext(), id);
+ setPointerIcon(pointerIcon);
+ }
+
+ private void setOrientation(int id, int fallback) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ id = fallback;
+ }
+ ((Activity) this.getContext()).setRequestedOrientation(id);
+ }
+
+ private void setFullscreen(boolean enabled) {
+ int flags = this.getSystemUiVisibility();
+ if (enabled) {
+ flags |= SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ flags |= SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ flags |= SYSTEM_UI_FLAG_FULLSCREEN;
+ flags |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ } else {
+ flags &= ~SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ flags &= ~SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ flags &= ~SYSTEM_UI_FLAG_FULLSCREEN;
+ flags &= ~SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ }
+ this.setSystemUiVisibility(flags);
+ }
+
+ private enum Bar {
+ NAVIGATION,
+ STATUS,
+ }
+
+ private void setBarColor(Bar t, int color, int luminance) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ return;
+ }
+
+ Window window = ((Activity) this.getContext()).getWindow();
+
+ int insetsMask;
+ int viewMask;
+
+ switch (t) {
+ case STATUS:
+ insetsMask = WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+ viewMask = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ window.setStatusBarColor(color);
+ break;
+ case NAVIGATION:
+ insetsMask = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+ viewMask = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ window.setNavigationBarColor(color);
+ break;
+ default:
+ throw new RuntimeException("invalid bar type");
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ return;
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ int flags = this.getSystemUiVisibility();
+ if (luminance > 128) {
+ flags |= viewMask;
+ } else {
+ flags &= ~viewMask;
+ }
+ this.setSystemUiVisibility(flags);
+ return;
+ }
+
+ WindowInsetsController insetsController = window.getInsetsController();
+ if (insetsController == null) {
+ return;
+ }
+ if (luminance > 128) {
+ insetsController.setSystemBarsAppearance(insetsMask, insetsMask);
+ } else {
+ insetsController.setSystemBarsAppearance(0, insetsMask);
+ }
+ }
+
+ private void setStatusColor(int color, int luminance) {
+ this.setBarColor(Bar.STATUS, color, luminance);
+ }
+
+ private void setNavigationColor(int color, int luminance) {
+ this.setBarColor(Bar.NAVIGATION, color, luminance);
+ }
+
+ @Override protected boolean dispatchHoverEvent(MotionEvent event) {
+ if (!accessManager.isTouchExplorationEnabled()) {
+ return super.dispatchHoverEvent(event);
+ }
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ // Fall through.
+ case MotionEvent.ACTION_HOVER_MOVE:
+ onTouchExploration(nhandle, event.getX(), event.getY());
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ onExitTouchExploration(nhandle);
+ break;
+ }
+ return true;
+ }
+
+ void sendA11yEvent(int eventType, int viewId) {
+ if (!accessManager.isEnabled()) {
+ return;
+ }
+ AccessibilityEvent event = obtainA11yEvent(eventType, viewId);
+ getParent().requestSendAccessibilityEvent(this, event);
+ }
+
+ AccessibilityEvent obtainA11yEvent(int eventType, int viewId) {
+ AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+ event.setPackageName(getContext().getPackageName());
+ event.setSource(this, viewId);
+ return event;
+ }
+
+ boolean isA11yActive() {
+ return accessManager.isEnabled();
+ }
+
+ void sendA11yChange(int viewId) {
+ if (!accessManager.isEnabled()) {
+ return;
+ }
+ AccessibilityEvent event = obtainA11yEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED, viewId);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+ }
+ getParent().requestSendAccessibilityEvent(this, event);
+ }
+
+ private void dispatchMotionEvent(MotionEvent event) {
+ if (nhandle == 0) {
+ return;
+ }
+ for (int j = 0; j < event.getHistorySize(); j++) {
+ long time = event.getHistoricalEventTime(j);
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ onTouchEvent(
+ nhandle,
+ event.ACTION_MOVE,
+ event.getPointerId(i),
+ event.getToolType(i),
+ event.getHistoricalX(i, j),
+ event.getHistoricalY(i, j),
+ scrollXScale*event.getHistoricalAxisValue(MotionEvent.AXIS_HSCROLL, i, j),
+ scrollYScale*event.getHistoricalAxisValue(MotionEvent.AXIS_VSCROLL, i, j),
+ event.getButtonState(),
+ time);
+ }
+ }
+ int act = event.getActionMasked();
+ int idx = event.getActionIndex();
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ int pact = event.ACTION_MOVE;
+ if (i == idx) {
+ pact = act;
+ }
+ onTouchEvent(
+ nhandle,
+ pact,
+ event.getPointerId(i),
+ event.getToolType(i),
+ event.getX(i), event.getY(i),
+ scrollXScale*event.getAxisValue(MotionEvent.AXIS_HSCROLL, i),
+ scrollYScale*event.getAxisValue(MotionEvent.AXIS_VSCROLL, i),
+ event.getButtonState(),
+ event.getEventTime());
+ }
+ }
+
+ @Override public InputConnection onCreateInputConnection(EditorInfo editor) {
+ editor.inputType = this.keyboardHint;
+ editor.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_NO_EXTRACT_UI;
+ return new InputConnection(this);
+ }
+
+ void setInputHint(int hint) {
+ if (hint == this.keyboardHint) {
+ return;
+ }
+ this.keyboardHint = hint;
+ imm.restartInput(this);
+ }
+
+ void showTextInput() {
+ GioView.this.requestFocus();
+ imm.showSoftInput(GioView.this, 0);
+ }
+
+ void hideTextInput() {
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ }
+
+ @Override protected boolean fitSystemWindows(Rect insets) {
+ if (nhandle != 0) {
+ onWindowInsets(nhandle, insets.top, insets.right, insets.bottom, insets.left);
+ }
+ return true;
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ if (nhandle != 0) {
+ onFrameCallback(nhandle);
+ }
+ }
+
+ int getDensity() {
+ return getResources().getDisplayMetrics().densityDpi;
+ }
+
+ float getFontScale() {
+ return getResources().getConfiguration().fontScale;
+ }
+
+ public void start() {
+ if (nhandle != 0) {
+ onStartView(nhandle);
+ }
+ }
+
+ public void stop() {
+ if (nhandle != 0) {
+ onStopView(nhandle);
+ }
+ }
+
+ public void destroy() {
+ if (nhandle != 0) {
+ onDestroyView(nhandle);
+ }
+ }
+
+ protected void unregister() {
+ setOnFocusChangeListener(null);
+ getHolder().removeCallback(surfCallbacks);
+ nhandle = 0;
+ }
+
+ public void configurationChanged() {
+ if (nhandle != 0) {
+ onConfigurationChanged(nhandle);
+ }
+ }
+
+ public boolean backPressed() {
+ if (nhandle == 0) {
+ return false;
+ }
+ return onBack(nhandle);
+ }
+
+ static private native long onCreateView(GioView view);
+ static private native void onDestroyView(long handle);
+ static private native void onStartView(long handle);
+ static private native void onStopView(long handle);
+ static private native void onSurfaceDestroyed(long handle);
+ static private native void onSurfaceChanged(long handle, Surface surface);
+ static private native void onConfigurationChanged(long handle);
+ static private native void onWindowInsets(long handle, int top, int right, int bottom, int left);
+ static public native void onLowMemory();
+ static private native void onTouchEvent(long handle, int action, int pointerID, int tool, float x, float y, float scrollX, float scrollY, int buttons, long time);
+ static private native void onKeyEvent(long handle, int code, int character, long time);
+ static private native void onFrameCallback(long handle);
+ static private native boolean onBack(long handle);
+ static private native void onFocusChange(long handle, boolean focus);
+ static private native AccessibilityNodeInfo initializeAccessibilityNodeInfo(long handle, int viewId, int screenX, int screenY, AccessibilityNodeInfo info);
+ static private native void onTouchExploration(long handle, float x, float y);
+ static private native void onExitTouchExploration(long handle);
+ static private native void onA11yFocus(long handle, int viewId);
+ static private native void onClearA11yFocus(long handle, int viewId);
+
+ private static class InputConnection extends BaseInputConnection {
+ private final Editable editable;
+
+ InputConnection(View view) {
+ // Passing false enables "dummy mode", where the BaseInputConnection
+ // attempts to convert IME operations to key events.
+ super(view, false);
+ editable = Editable.Factory.getInstance().newEditable("");
+ }
+
+ @Override public Editable getEditable() {
+ return editable;
+ }
+ }
+
+ @Override public AccessibilityNodeProvider getAccessibilityNodeProvider() {
+ return new AccessibilityNodeProvider() {
+ private final int[] screenOff = new int[2];
+
+ @Override public AccessibilityNodeInfo createAccessibilityNodeInfo(int viewId) {
+ AccessibilityNodeInfo info = null;
+ if (viewId == View.NO_ID) {
+ info = AccessibilityNodeInfo.obtain(GioView.this);
+ GioView.this.onInitializeAccessibilityNodeInfo(info);
+ } else {
+ info = AccessibilityNodeInfo.obtain(GioView.this, viewId);
+ info.setPackageName(getContext().getPackageName());
+ info.setVisibleToUser(true);
+ }
+ GioView.this.getLocationOnScreen(screenOff);
+ info = GioView.this.initializeAccessibilityNodeInfo(nhandle, viewId, screenOff[0], screenOff[1], info);
+ return info;
+ }
+
+ @Override public boolean performAction(int viewId, int action, Bundle arguments) {
+ if (viewId == View.NO_ID) {
+ return GioView.this.performAccessibilityAction(action, arguments);
+ }
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
+ GioView.this.onA11yFocus(nhandle, viewId);
+ GioView.this.sendA11yEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, viewId);
+ return true;
+ case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
+ GioView.this.onClearA11yFocus(nhandle, viewId);
+ GioView.this.sendA11yEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED, viewId);
+ return true;
+ }
+ return false;
+ }
+ };
+ }
+}
diff --git a/vendor/gioui.org/app/app.go b/vendor/gioui.org/app/app.go
index d21224e..e00298a 100644
--- a/vendor/gioui.org/app/app.go
+++ b/vendor/gioui.org/app/app.go
@@ -5,8 +5,6 @@ package app
import (
"os"
"strings"
-
- "gioui.org/app/internal/window"
)
// extraArgs contains extra arguments to append to
@@ -44,5 +42,5 @@ func DataDir() (string, error) {
// require control of the main thread of the program for
// running windows.
func Main() {
- window.Main()
+ osMain()
}
diff --git a/vendor/gioui.org/app/app_android.go b/vendor/gioui.org/app/app_android.go
deleted file mode 100644
index 58e40d0..0000000
--- a/vendor/gioui.org/app/app_android.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package app
-
-import (
- "gioui.org/app/internal/window"
-)
-
-// JavaVM returns the global JNI JavaVM.
-func JavaVM() uintptr {
- return window.JavaVM()
-}
-
-// AppContext returns the global Application context as a JNI
-// jobject.
-func AppContext() uintptr {
- return window.AppContext()
-}
-
-// Do invokes the function with a JNI jobject handle to the underlying
-// Android View. The function is invoked on the main thread, and the
-// handle is invalidated after the function returns.
-//
-// Note: Do may deadlock if called from the same goroutine that receives from
-// Events.
-func (w *Window) Do(f func(view uintptr)) {
- type androidDriver interface {
- Do(f func(view uintptr)) bool
- }
- success := make(chan bool)
- for {
- driver := make(chan androidDriver, 1)
- // two-stage process: first wait for a valid driver...
- w.driverDo(func() {
- driver <- w.driver.(androidDriver)
- })
- // .. then run the function on the main thread using the
- // driver. The driver Do method returns false if the
- // view was invalidated while switching to the main thread.
- window.RunOnMain(func() {
- d := <-driver
- success <- d.Do(f)
- })
- if <-success {
- break
- }
- }
-}
diff --git a/vendor/gioui.org/app/d3d11_windows.go b/vendor/gioui.org/app/d3d11_windows.go
new file mode 100644
index 0000000..ab04ee4
--- /dev/null
+++ b/vendor/gioui.org/app/d3d11_windows.go
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package app
+
+import (
+ "fmt"
+ "unsafe"
+
+ "gioui.org/gpu"
+ "gioui.org/internal/d3d11"
+)
+
+type d3d11Context struct {
+ win *window
+ dev *d3d11.Device
+ ctx *d3d11.DeviceContext
+
+ swchain *d3d11.IDXGISwapChain
+ renderTarget *d3d11.RenderTargetView
+ width, height int
+}
+
+const debug = false
+
+func init() {
+ drivers = append(drivers, gpuAPI{
+ priority: 1,
+ initializer: func(w *window) (context, error) {
+ hwnd, _, _ := w.HWND()
+ var flags uint32
+ if debug {
+ flags |= d3d11.CREATE_DEVICE_DEBUG
+ }
+ dev, ctx, _, err := d3d11.CreateDevice(
+ d3d11.DRIVER_TYPE_HARDWARE,
+ flags,
+ )
+ if err != nil {
+ return nil, fmt.Errorf("NewContext: %v", err)
+ }
+ swchain, err := d3d11.CreateSwapChain(dev, hwnd)
+ if err != nil {
+ d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release)
+ d3d11.IUnknownRelease(unsafe.Pointer(dev), dev.Vtbl.Release)
+ return nil, err
+ }
+ return &d3d11Context{win: w, dev: dev, ctx: ctx, swchain: swchain}, nil
+ },
+ })
+}
+
+func (c *d3d11Context) API() gpu.API {
+ return gpu.Direct3D11{Device: unsafe.Pointer(c.dev)}
+}
+
+func (c *d3d11Context) RenderTarget() (gpu.RenderTarget, error) {
+ return gpu.Direct3D11RenderTarget{
+ RenderTarget: unsafe.Pointer(c.renderTarget),
+ }, nil
+}
+
+func (c *d3d11Context) Present() error {
+ err := c.swchain.Present(1, 0)
+ if err == nil {
+ return nil
+ }
+ if err, ok := err.(d3d11.ErrorCode); ok {
+ switch err.Code {
+ case d3d11.DXGI_STATUS_OCCLUDED:
+ // Ignore
+ return nil
+ case d3d11.DXGI_ERROR_DEVICE_RESET, d3d11.DXGI_ERROR_DEVICE_REMOVED, d3d11.D3DDDIERR_DEVICEREMOVED:
+ return gpu.ErrDeviceLost
+ }
+ }
+ return err
+}
+
+func (c *d3d11Context) Refresh() error {
+ var width, height int
+ _, width, height = c.win.HWND()
+ if c.renderTarget != nil && width == c.width && height == c.height {
+ return nil
+ }
+ c.releaseFBO()
+ if err := c.swchain.ResizeBuffers(0, 0, 0, d3d11.DXGI_FORMAT_UNKNOWN, 0); err != nil {
+ return err
+ }
+ c.width = width
+ c.height = height
+
+ backBuffer, err := c.swchain.GetBuffer(0, &d3d11.IID_Texture2D)
+ if err != nil {
+ return err
+ }
+ texture := (*d3d11.Resource)(unsafe.Pointer(backBuffer))
+ renderTarget, err := c.dev.CreateRenderTargetView(texture)
+ d3d11.IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.Vtbl.Release)
+ if err != nil {
+ return err
+ }
+ c.renderTarget = renderTarget
+ return nil
+}
+
+func (c *d3d11Context) Lock() error {
+ c.ctx.OMSetRenderTargets(c.renderTarget, nil)
+ return nil
+}
+
+func (c *d3d11Context) Unlock() {}
+
+func (c *d3d11Context) Release() {
+ c.releaseFBO()
+ if c.swchain != nil {
+ d3d11.IUnknownRelease(unsafe.Pointer(c.swchain), c.swchain.Vtbl.Release)
+ }
+ if c.ctx != nil {
+ d3d11.IUnknownRelease(unsafe.Pointer(c.ctx), c.ctx.Vtbl.Release)
+ }
+ if c.dev != nil {
+ d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release)
+ }
+ *c = d3d11Context{}
+ if debug {
+ d3d11.ReportLiveObjects()
+ }
+}
+
+func (c *d3d11Context) releaseFBO() {
+ if c.renderTarget != nil {
+ d3d11.IUnknownRelease(unsafe.Pointer(c.renderTarget), c.renderTarget.Vtbl.Release)
+ c.renderTarget = nil
+ }
+}
diff --git a/vendor/gioui.org/app/datadir.go b/vendor/gioui.org/app/datadir.go
index 31e5453..500a59a 100644
--- a/vendor/gioui.org/app/datadir.go
+++ b/vendor/gioui.org/app/datadir.go
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: Unlicense OR MIT
+//go:build !android
// +build !android
package app
diff --git a/vendor/gioui.org/app/datadir_android.go b/vendor/gioui.org/app/datadir_android.go
deleted file mode 100644
index 450e6cf..0000000
--- a/vendor/gioui.org/app/datadir_android.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build android
-
-package app
-
-import "C"
-
-import (
- "os"
- "path/filepath"
- "sync"
-
- "gioui.org/app/internal/window"
-)
-
-var (
- dataDirOnce sync.Once
- dataPath string
-)
-
-func dataDir() (string, error) {
- dataDirOnce.Do(func() {
- dataPath = window.GetDataDir()
- // Set XDG_CACHE_HOME to make os.UserCacheDir work.
- if _, exists := os.LookupEnv("XDG_CACHE_HOME"); !exists {
- cachePath := filepath.Join(dataPath, "cache")
- os.Setenv("XDG_CACHE_HOME", cachePath)
- }
- // Set XDG_CONFIG_HOME to make os.UserConfigDir work.
- if _, exists := os.LookupEnv("XDG_CONFIG_HOME"); !exists {
- cfgPath := filepath.Join(dataPath, "config")
- os.Setenv("XDG_CONFIG_HOME", cfgPath)
- }
- // Set HOME to make os.UserHomeDir work.
- if _, exists := os.LookupEnv("HOME"); !exists {
- os.Setenv("HOME", dataPath)
- }
- })
- return dataPath, nil
-}
diff --git a/vendor/gioui.org/app/egl_android.go b/vendor/gioui.org/app/egl_android.go
new file mode 100644
index 0000000..2c31130
--- /dev/null
+++ b/vendor/gioui.org/app/egl_android.go
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package app
+
+/*
+#include <android/native_window_jni.h>
+#include <EGL/egl.h>
+*/
+import "C"
+
+import (
+ "unsafe"
+
+ "gioui.org/internal/egl"
+)
+
+type androidContext struct {
+ win *window
+ eglSurf egl.NativeWindowType
+ width, height int
+ *egl.Context
+}
+
+func init() {
+ newAndroidGLESContext = func(w *window) (context, error) {
+ ctx, err := egl.NewContext(nil)
+ if err != nil {
+ return nil, err
+ }
+ return &androidContext{win: w, Context: ctx}, nil
+ }
+}
+
+func (c *androidContext) Release() {
+ if c.Context != nil {
+ c.Context.Release()
+ c.Context = nil
+ }
+}
+
+func (c *androidContext) Refresh() error {
+ c.Context.ReleaseSurface()
+ if err := c.win.setVisual(c.Context.VisualID()); err != nil {
+ return err
+ }
+ win, width, height := c.win.nativeWindow()
+ c.eglSurf = egl.NativeWindowType(unsafe.Pointer(win))
+ c.width, c.height = width, height
+ return nil
+}
+
+func (c *androidContext) Lock() error {
+ // The Android emulator creates a broken surface if it is not
+ // created on the same thread as the context is made current.
+ if c.eglSurf != nil {
+ if err := c.Context.CreateSurface(c.eglSurf, c.width, c.height); err != nil {
+ return err
+ }
+ c.eglSurf = nil
+ }
+ return c.Context.MakeCurrent()
+}
+
+func (c *androidContext) Unlock() {
+ c.Context.ReleaseCurrent()
+}
diff --git a/vendor/gioui.org/app/internal/window/egl_wayland.go b/vendor/gioui.org/app/egl_wayland.go
index b4878b4..c2406a0 100644
--- a/vendor/gioui.org/app/internal/window/egl_wayland.go
+++ b/vendor/gioui.org/app/egl_wayland.go
@@ -1,20 +1,22 @@
// SPDX-License-Identifier: Unlicense OR MIT
-// +build linux,!android,!nowayland freebsd
+//go:build ((linux && !android) || freebsd) && !nowayland
+// +build linux,!android freebsd
+// +build !nowayland
-package window
+package app
import (
"errors"
"unsafe"
- "gioui.org/app/internal/egl"
+ "gioui.org/internal/egl"
)
/*
#cgo linux pkg-config: egl wayland-egl
#cgo freebsd openbsd LDFLAGS: -lwayland-egl
-#cgo CFLAGS: -DMESA_EGL_NO_X11_HEADERS
+#cgo CFLAGS: -DEGL_NO_X11
#include <EGL/egl.h>
#include <wayland-client.h>
@@ -22,22 +24,24 @@ import (
*/
import "C"
-type context struct {
+type wlContext struct {
win *window
*egl.Context
eglWin *C.struct_wl_egl_window
}
-func (w *window) NewContext() (Context, error) {
- disp := egl.NativeDisplayType(unsafe.Pointer(w.display()))
- ctx, err := egl.NewContext(disp)
- if err != nil {
- return nil, err
+func init() {
+ newWaylandEGLContext = func(w *window) (context, error) {
+ disp := egl.NativeDisplayType(unsafe.Pointer(w.display()))
+ ctx, err := egl.NewContext(disp)
+ if err != nil {
+ return nil, err
+ }
+ return &wlContext{Context: ctx, win: w}, nil
}
- return &context{Context: ctx, win: w}, nil
}
-func (c *context) Release() {
+func (c *wlContext) Release() {
if c.Context != nil {
c.Context.Release()
c.Context = nil
@@ -48,7 +52,7 @@ func (c *context) Release() {
}
}
-func (c *context) MakeCurrent() error {
+func (c *wlContext) Refresh() error {
c.Context.ReleaseSurface()
if c.eglWin != nil {
C.wl_egl_window_destroy(c.eglWin)
@@ -64,12 +68,13 @@ func (c *context) MakeCurrent() error {
}
c.eglWin = eglWin
eglSurf := egl.NativeWindowType(uintptr(unsafe.Pointer(eglWin)))
- if err := c.Context.CreateSurface(eglSurf, width, height); err != nil {
- return err
- }
- return c.Context.MakeCurrent()
+ return c.Context.CreateSurface(eglSurf, width, height)
}
-func (c *context) Lock() {}
+func (c *wlContext) Lock() error {
+ return c.Context.MakeCurrent()
+}
-func (c *context) Unlock() {}
+func (c *wlContext) Unlock() {
+ c.Context.ReleaseCurrent()
+}
diff --git a/vendor/gioui.org/app/internal/window/egl_windows.go b/vendor/gioui.org/app/egl_windows.go
index 654d279..3a95450 100644
--- a/vendor/gioui.org/app/internal/window/egl_windows.go
+++ b/vendor/gioui.org/app/egl_windows.go
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: Unlicense OR MIT
-package window
+package app
import (
- "gioui.org/app/internal/egl"
+ "golang.org/x/sys/windows"
+
+ "gioui.org/internal/egl"
)
type glContext struct {
@@ -12,9 +14,9 @@ type glContext struct {
}
func init() {
- backends = append(backends, gpuAPI{
+ drivers = append(drivers, gpuAPI{
priority: 2,
- initializer: func(w *window) (Context, error) {
+ initializer: func(w *window) (context, error) {
disp := egl.NativeDisplayType(w.HDC())
ctx, err := egl.NewContext(disp)
if err != nil {
@@ -32,9 +34,13 @@ func (c *glContext) Release() {
}
}
-func (c *glContext) MakeCurrent() error {
+func (c *glContext) Refresh() error {
c.Context.ReleaseSurface()
- win, width, height := c.win.HWND()
+ var (
+ win windows.Handle
+ width, height int
+ )
+ win, width, height = c.win.HWND()
eglSurf := egl.NativeWindowType(win)
if err := c.Context.CreateSurface(eglSurf, width, height); err != nil {
return err
@@ -43,9 +49,14 @@ func (c *glContext) MakeCurrent() error {
return err
}
c.Context.EnableVSync(true)
+ c.Context.ReleaseCurrent()
return nil
}
-func (c *glContext) Lock() {}
+func (c *glContext) Lock() error {
+ return c.Context.MakeCurrent()
+}
-func (c *glContext) Unlock() {}
+func (c *glContext) Unlock() {
+ c.Context.ReleaseCurrent()
+}
diff --git a/vendor/gioui.org/app/egl_x11.go b/vendor/gioui.org/app/egl_x11.go
new file mode 100644
index 0000000..7234808
--- /dev/null
+++ b/vendor/gioui.org/app/egl_x11.go
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build ((linux && !android) || freebsd || openbsd) && !nox11
+// +build linux,!android freebsd openbsd
+// +build !nox11
+
+package app
+
+import (
+ "unsafe"
+
+ "gioui.org/internal/egl"
+)
+
+type x11Context struct {
+ win *x11Window
+ *egl.Context
+}
+
+func init() {
+ newX11EGLContext = func(w *x11Window) (context, error) {
+ disp := egl.NativeDisplayType(unsafe.Pointer(w.display()))
+ ctx, err := egl.NewContext(disp)
+ if err != nil {
+ return nil, err
+ }
+ return &x11Context{win: w, Context: ctx}, nil
+ }
+}
+
+func (c *x11Context) Release() {
+ if c.Context != nil {
+ c.Context.Release()
+ c.Context = nil
+ }
+}
+
+func (c *x11Context) Refresh() error {
+ c.Context.ReleaseSurface()
+ win, width, height := c.win.window()
+ eglSurf := egl.NativeWindowType(uintptr(win))
+ if err := c.Context.CreateSurface(eglSurf, width, height); err != nil {
+ return err
+ }
+ if err := c.Context.MakeCurrent(); err != nil {
+ return err
+ }
+ c.Context.EnableVSync(true)
+ c.Context.ReleaseCurrent()
+ return nil
+}
+
+func (c *x11Context) Lock() error {
+ return c.Context.MakeCurrent()
+}
+
+func (c *x11Context) Unlock() {
+ c.Context.ReleaseCurrent()
+}
diff --git a/vendor/gioui.org/app/internal/window/framework_ios.h b/vendor/gioui.org/app/framework_ios.h
index 18e5a02..18e5a02 100644
--- a/vendor/gioui.org/app/internal/window/framework_ios.h
+++ b/vendor/gioui.org/app/framework_ios.h
diff --git a/vendor/gioui.org/app/internal/window/gl_ios.go b/vendor/gioui.org/app/gl_ios.go
index 0099189..2dc2dbf 100644
--- a/vendor/gioui.org/app/internal/window/gl_ios.go
+++ b/vendor/gioui.org/app/gl_ios.go
@@ -1,10 +1,13 @@
// SPDX-License-Identifier: Unlicense OR MIT
-// +build darwin,ios
+//go:build darwin && ios && nometal
+// +build darwin,ios,nometal
-package window
+package app
/*
+@import UIKit;
+
#include <CoreFoundation/CoreFoundation.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
@@ -14,32 +17,34 @@ __attribute__ ((visibility ("hidden"))) int gio_presentRenderbuffer(CFTypeRef ct
__attribute__ ((visibility ("hidden"))) int gio_makeCurrent(CFTypeRef ctx);
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createContext(void);
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLLayer(void);
+
+static CFTypeRef getViewLayer(CFTypeRef viewRef) {
+ @autoreleasepool {
+ UIView *view = (__bridge UIView *)viewRef;
+ return CFBridgingRetain(view.layer);
+ }
+}
+
*/
import "C"
import (
"errors"
"fmt"
+ "runtime"
- "gioui.org/app/internal/glimpl"
- "gioui.org/gpu/backend"
- "gioui.org/gpu/gl"
+ "gioui.org/gpu"
+ "gioui.org/internal/gl"
)
type context struct {
- owner *window
- c *glimpl.Functions
- ctx C.CFTypeRef
- layer C.CFTypeRef
- init bool
- frameBuffer gl.Framebuffer
- colorBuffer, depthBuffer gl.Renderbuffer
-}
-
-func init() {
- layerFactory = func() uintptr {
- return uintptr(C.gio_createGLLayer())
- }
+ owner *window
+ c *gl.Functions
+ ctx C.CFTypeRef
+ layer C.CFTypeRef
+ init bool
+ frameBuffer gl.Framebuffer
+ colorBuffer gl.Renderbuffer
}
func newContext(w *window) (*context, error) {
@@ -47,17 +52,30 @@ func newContext(w *window) (*context, error) {
if ctx == 0 {
return nil, fmt.Errorf("failed to create EAGLContext")
}
+ api := contextAPI()
+ f, err := gl.NewFunctions(api.Context, api.ES)
+ if err != nil {
+ return nil, err
+ }
c := &context{
ctx: ctx,
owner: w,
- layer: C.CFTypeRef(w.contextLayer()),
- c: new(glimpl.Functions),
+ layer: C.getViewLayer(w.contextView()),
+ c: f,
}
return c, nil
}
-func (c *context) Backend() (backend.Device, error) {
- return gl.NewBackend(c.c)
+func contextAPI() gpu.OpenGL {
+ return gpu.OpenGL{}
+}
+
+func (c *context) RenderTarget() gpu.RenderTarget {
+ return gpu.OpenGLRenderTarget(c.frameBuffer)
+}
+
+func (c *context) API() gpu.API {
+ return contextAPI()
}
func (c *context) Release() {
@@ -67,7 +85,6 @@ func (c *context) Release() {
C.gio_renderbufferStorage(c.ctx, 0, C.GLenum(gl.RENDERBUFFER))
c.c.DeleteFramebuffer(c.frameBuffer)
c.c.DeleteRenderbuffer(c.colorBuffer)
- c.c.DeleteRenderbuffer(c.depthBuffer)
C.gio_makeCurrent(0)
C.CFRelease(c.ctx)
c.ctx = 0
@@ -77,10 +94,6 @@ func (c *context) Present() error {
if c.layer == 0 {
panic("context is not active")
}
- // Discard depth buffer as recommended in
- // https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html
- c.c.BindFramebuffer(gl.FRAMEBUFFER, c.frameBuffer)
- c.c.InvalidateFramebuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT)
c.c.BindRenderbuffer(gl.RENDERBUFFER, c.colorBuffer)
if C.gio_presentRenderbuffer(c.ctx, C.GLenum(gl.RENDERBUFFER)) == 0 {
return errors.New("presentRenderBuffer failed")
@@ -88,23 +101,30 @@ func (c *context) Present() error {
return nil
}
-func (c *context) Lock() {}
+func (c *context) Lock() error {
+ // OpenGL contexts are implicit and thread-local. Lock the OS thread.
+ runtime.LockOSThread()
-func (c *context) Unlock() {}
+ if C.gio_makeCurrent(c.ctx) == 0 {
+ return errors.New("[EAGLContext setCurrentContext] failed")
+ }
+ return nil
+}
+
+func (c *context) Unlock() {
+ C.gio_makeCurrent(0)
+}
-func (c *context) MakeCurrent() error {
+func (c *context) Refresh() error {
if C.gio_makeCurrent(c.ctx) == 0 {
- C.CFRelease(c.ctx)
- c.ctx = 0
return errors.New("[EAGLContext setCurrentContext] failed")
}
if !c.init {
c.init = true
c.frameBuffer = c.c.CreateFramebuffer()
c.colorBuffer = c.c.CreateRenderbuffer()
- c.depthBuffer = c.c.CreateRenderbuffer()
}
- if !c.owner.isVisible() {
+ if !c.owner.visible {
// Make sure any in-flight GL commands are complete.
c.c.Finish()
return nil
@@ -114,14 +134,9 @@ func (c *context) MakeCurrent() error {
if C.gio_renderbufferStorage(c.ctx, c.layer, C.GLenum(gl.RENDERBUFFER)) == 0 {
return errors.New("renderbufferStorage failed")
}
- w := c.c.GetRenderbufferParameteri(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)
- h := c.c.GetRenderbufferParameteri(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)
- c.c.BindRenderbuffer(gl.RENDERBUFFER, c.depthBuffer)
- c.c.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h)
c.c.BindRenderbuffer(gl.RENDERBUFFER, currentRB)
c.c.BindFramebuffer(gl.FRAMEBUFFER, c.frameBuffer)
c.c.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, c.colorBuffer)
- c.c.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, c.depthBuffer)
if st := c.c.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE {
return fmt.Errorf("framebuffer incomplete, status: %#x\n", st)
}
diff --git a/vendor/gioui.org/app/internal/window/gl_ios.m b/vendor/gioui.org/app/gl_ios.m
index 065ea97..8e50753 100644
--- a/vendor/gioui.org/app/internal/window/gl_ios.m
+++ b/vendor/gioui.org/app/gl_ios.m
@@ -1,12 +1,16 @@
// SPDX-License-Identifier: Unlicense OR MIT
-// +build darwin,ios
+// +build darwin,ios,nometal
@import UIKit;
@import OpenGLES;
#include "_cgo_export.h"
+Class gio_layerClass(void) {
+ return [CAEAGLLayer class];
+}
+
int gio_renderbufferStorage(CFTypeRef ctxRef, CFTypeRef layerRef, GLenum buffer) {
EAGLContext *ctx = (__bridge EAGLContext *)ctxRef;
CAEAGLLayer *layer = (__bridge CAEAGLLayer *)layerRef;
diff --git a/vendor/gioui.org/app/gl_js.go b/vendor/gioui.org/app/gl_js.go
new file mode 100644
index 0000000..e3aee8d
--- /dev/null
+++ b/vendor/gioui.org/app/gl_js.go
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package app
+
+import (
+ "errors"
+ "syscall/js"
+
+ "gioui.org/gpu"
+ "gioui.org/internal/gl"
+)
+
+type glContext struct {
+ ctx js.Value
+ cnv js.Value
+}
+
+func newContext(w *window) (*glContext, error) {
+ args := map[string]interface{}{
+ // Enable low latency rendering.
+ // See https://developers.google.com/web/updates/2019/05/desynchronized.
+ "desynchronized": true,
+ "preserveDrawingBuffer": true,
+ }
+ ctx := w.cnv.Call("getContext", "webgl2", args)
+ if ctx.IsNull() {
+ ctx = w.cnv.Call("getContext", "webgl", args)
+ }
+ if ctx.IsNull() {
+ return nil, errors.New("app: webgl is not supported")
+ }
+ c := &glContext{
+ ctx: ctx,
+ cnv: w.cnv,
+ }
+ return c, nil
+}
+
+func (c *glContext) RenderTarget() (gpu.RenderTarget, error) {
+ return gpu.OpenGLRenderTarget{}, nil
+}
+
+func (c *glContext) API() gpu.API {
+ return gpu.OpenGL{Context: gl.Context(c.ctx)}
+}
+
+func (c *glContext) Release() {
+}
+
+func (c *glContext) Present() error {
+ if c.ctx.Call("isContextLost").Bool() {
+ return errors.New("context lost")
+ }
+ return nil
+}
+
+func (c *glContext) Lock() error {
+ return nil
+}
+
+func (c *glContext) Unlock() {}
+
+func (c *glContext) Refresh() error {
+ return nil
+}
+
+func (w *window) NewContext() (context, error) {
+ return newContext(w)
+}
diff --git a/vendor/gioui.org/app/gl_macos.go b/vendor/gioui.org/app/gl_macos.go
new file mode 100644
index 0000000..7511bbd
--- /dev/null
+++ b/vendor/gioui.org/app/gl_macos.go
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build darwin && !ios && nometal
+// +build darwin,!ios,nometal
+
+package app
+
+import (
+ "errors"
+ "runtime"
+
+ "unsafe"
+
+ "gioui.org/gpu"
+ "gioui.org/internal/gl"
+)
+
+/*
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <AppKit/AppKit.h>
+#include <dlfcn.h>
+
+__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLContext(void);
+__attribute__ ((visibility ("hidden"))) void gio_setContextView(CFTypeRef ctx, CFTypeRef view);
+__attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx);
+__attribute__ ((visibility ("hidden"))) void gio_updateContext(CFTypeRef ctx);
+__attribute__ ((visibility ("hidden"))) void gio_flushContextBuffer(CFTypeRef ctx);
+__attribute__ ((visibility ("hidden"))) void gio_clearCurrentContext(void);
+__attribute__ ((visibility ("hidden"))) void gio_lockContext(CFTypeRef ctxRef);
+__attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef);
+
+typedef void (*PFN_glFlush)(void);
+
+static void glFlush(PFN_glFlush f) {
+ f();
+}
+*/
+import "C"
+
+type glContext struct {
+ c *gl.Functions
+ ctx C.CFTypeRef
+ view C.CFTypeRef
+
+ glFlush C.PFN_glFlush
+}
+
+func newContext(w *window) (*glContext, error) {
+ clib := C.CString("/System/Library/Frameworks/OpenGL.framework/OpenGL")
+ defer C.free(unsafe.Pointer(clib))
+ lib, err := C.dlopen(clib, C.RTLD_NOW|C.RTLD_LOCAL)
+ if err != nil {
+ return nil, err
+ }
+ csym := C.CString("glFlush")
+ defer C.free(unsafe.Pointer(csym))
+ glFlush := C.PFN_glFlush(C.dlsym(lib, csym))
+ if glFlush == nil {
+ return nil, errors.New("gl: missing symbol glFlush in the OpenGL framework")
+ }
+ view := w.contextView()
+ ctx := C.gio_createGLContext()
+ if ctx == 0 {
+ return nil, errors.New("gl: failed to create NSOpenGLContext")
+ }
+ C.gio_setContextView(ctx, view)
+ c := &glContext{
+ ctx: ctx,
+ view: view,
+ glFlush: glFlush,
+ }
+ return c, nil
+}
+
+func (c *glContext) RenderTarget() (gpu.RenderTarget, error) {
+ return gpu.OpenGLRenderTarget{}, nil
+}
+
+func (c *glContext) API() gpu.API {
+ return gpu.OpenGL{}
+}
+
+func (c *glContext) Release() {
+ if c.ctx != 0 {
+ C.gio_clearCurrentContext()
+ C.CFRelease(c.ctx)
+ c.ctx = 0
+ }
+}
+
+func (c *glContext) Present() error {
+ // Assume the caller already locked the context.
+ C.glFlush(c.glFlush)
+ return nil
+}
+
+func (c *glContext) Lock() error {
+ // OpenGL contexts are implicit and thread-local. Lock the OS thread.
+ runtime.LockOSThread()
+
+ C.gio_lockContext(c.ctx)
+ C.gio_makeCurrentContext(c.ctx)
+ return nil
+}
+
+func (c *glContext) Unlock() {
+ C.gio_clearCurrentContext()
+ C.gio_unlockContext(c.ctx)
+}
+
+func (c *glContext) Refresh() error {
+ c.Lock()
+ defer c.Unlock()
+ C.gio_updateContext(c.ctx)
+ return nil
+}
+
+func (w *window) NewContext() (context, error) {
+ return newContext(w)
+}
diff --git a/vendor/gioui.org/app/gl_macos.m b/vendor/gioui.org/app/gl_macos.m
new file mode 100644
index 0000000..fe83743
--- /dev/null
+++ b/vendor/gioui.org/app/gl_macos.m
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+// +build darwin,!ios,nometal
+
+@import AppKit;
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <OpenGL/OpenGL.h>
+#include "_cgo_export.h"
+
+CALayer *gio_layerFactory(void) {
+ @autoreleasepool {
+ return [CALayer layer];
+ }
+}
+
+CFTypeRef gio_createGLContext(void) {
+ @autoreleasepool {
+ NSOpenGLPixelFormatAttribute attr[] = {
+ NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
+ NSOpenGLPFAColorSize, 24,
+ NSOpenGLPFAAccelerated,
+ // Opt-in to automatic GPU switching. CGL-only property.
+ kCGLPFASupportsAutomaticGraphicsSwitching,
+ NSOpenGLPFAAllowOfflineRenderers,
+ 0
+ };
+ NSOpenGLPixelFormat *pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
+
+ NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:pixFormat shareContext: nil];
+ return CFBridgingRetain(ctx);
+ }
+}
+
+void gio_setContextView(CFTypeRef ctxRef, CFTypeRef viewRef) {
+ NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
+ NSView *view = (__bridge NSView *)viewRef;
+ [view setWantsBestResolutionOpenGLSurface:YES];
+ [ctx setView:view];
+}
+
+void gio_clearCurrentContext(void) {
+ @autoreleasepool {
+ [NSOpenGLContext clearCurrentContext];
+ }
+}
+
+void gio_updateContext(CFTypeRef ctxRef) {
+ @autoreleasepool {
+ NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
+ [ctx update];
+ }
+}
+
+void gio_makeCurrentContext(CFTypeRef ctxRef) {
+ @autoreleasepool {
+ NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
+ [ctx makeCurrentContext];
+ }
+}
+
+void gio_lockContext(CFTypeRef ctxRef) {
+ @autoreleasepool {
+ NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
+ CGLLockContext([ctx CGLContextObj]);
+ }
+}
+
+void gio_unlockContext(CFTypeRef ctxRef) {
+ @autoreleasepool {
+ NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
+ CGLUnlockContext([ctx CGLContextObj]);
+ }
+}
diff --git a/vendor/gioui.org/app/internal/cocoainit/cocoa_darwin.go b/vendor/gioui.org/app/internal/cocoainit/cocoa_darwin.go
deleted file mode 100644
index 2a34e57..0000000
--- a/vendor/gioui.org/app/internal/cocoainit/cocoa_darwin.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// Package cocoainit initializes support for multithreaded
-// programs in Cocoa.
-package cocoainit
-
-/*
-#cgo CFLAGS: -xobjective-c -fmodules -fobjc-arc
-#import <Foundation/Foundation.h>
-
-static inline void activate_cocoa_multithreading() {
- [[NSThread new] start];
-}
-#pragma GCC visibility push(hidden)
-*/
-import "C"
-
-func init() {
- C.activate_cocoa_multithreading()
-}
diff --git a/vendor/gioui.org/app/internal/d3d11/backend_windows.go b/vendor/gioui.org/app/internal/d3d11/backend_windows.go
deleted file mode 100644
index 48ff175..0000000
--- a/vendor/gioui.org/app/internal/d3d11/backend_windows.go
+++ /dev/null
@@ -1,856 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package d3d11
-
-import (
- "errors"
- "fmt"
- "image"
- "math"
- "unsafe"
-
- "gioui.org/gpu/backend"
- gunsafe "gioui.org/internal/unsafe"
- "golang.org/x/sys/windows"
-)
-
-const debug = false
-
-type Device struct {
- dev *_ID3D11Device
- ctx *_ID3D11DeviceContext
- featLvl uint32
- floatFormat uint32
- depthStates map[depthState]*_ID3D11DepthStencilState
- blendStates map[blendState]*_ID3D11BlendState
-}
-
-type Backend struct {
- // Temporary storage to avoid garbage.
- clearColor [4]float32
- viewport _D3D11_VIEWPORT
- depthState depthState
- blendState blendState
- prog *Program
-
- dev *Device
- caps backend.Caps
-
- // fbo is the currently bound fbo.
- fbo *Framebuffer
-}
-
-type blendState struct {
- enable bool
- sfactor backend.BlendFactor
- dfactor backend.BlendFactor
-}
-
-type depthState struct {
- enable bool
- mask bool
- fn backend.DepthFunc
-}
-
-type Texture struct {
- backend *Backend
- format uint32
- bindings backend.BufferBinding
- tex *_ID3D11Texture2D
- sampler *_ID3D11SamplerState
- resView *_ID3D11ShaderResourceView
- width int
- height int
-}
-
-type Program struct {
- backend *Backend
-
- vert struct {
- shader *_ID3D11VertexShader
- uniforms *Buffer
- }
- frag struct {
- shader *_ID3D11PixelShader
- uniforms *Buffer
- }
-}
-
-type Framebuffer struct {
- dev *Device
- format uint32
- resource *_ID3D11Resource
- renderTarget *_ID3D11RenderTargetView
- depthView *_ID3D11DepthStencilView
- foreign bool
-}
-
-type Buffer struct {
- backend *Backend
- bind uint32
- buf *_ID3D11Buffer
- immutable bool
-}
-
-type InputLayout struct {
- dev *Device
- layout *_ID3D11InputLayout
-}
-
-type SwapChain struct {
- swchain *_IDXGISwapChain
- fbo *Framebuffer
-}
-
-func NewDevice() (*Device, error) {
- var flags uint32
- if debug {
- flags |= _D3D11_CREATE_DEVICE_DEBUG
- }
- d3ddev, d3dctx, featLvl, err := _D3D11CreateDevice(
- _D3D_DRIVER_TYPE_HARDWARE,
- flags,
- )
- if err != nil {
- return nil, fmt.Errorf("NewContext: %v", err)
- }
- dev := &Device{dev: d3ddev, ctx: d3dctx, featLvl: featLvl}
- if featLvl < _D3D_FEATURE_LEVEL_9_1 {
- _IUnknownRelease(unsafe.Pointer(d3ddev), d3ddev.vtbl.Release)
- _IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release)
- return nil, fmt.Errorf("d3d11: feature level too low: %d", featLvl)
- }
- floatFormat, ok := detectFloatFormat(d3ddev)
- if !ok {
- _IUnknownRelease(unsafe.Pointer(d3ddev), d3ddev.vtbl.Release)
- _IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release)
- return nil, fmt.Errorf("d3d11: no available floating point formats")
- }
- dev.floatFormat = floatFormat
- dev.depthStates = make(map[depthState]*_ID3D11DepthStencilState)
- dev.blendStates = make(map[blendState]*_ID3D11BlendState)
- return dev, nil
-}
-
-func detectFloatFormat(dev *_ID3D11Device) (uint32, bool) {
- formats := []uint32{
- _DXGI_FORMAT_R16_FLOAT,
- _DXGI_FORMAT_R32_FLOAT,
- _DXGI_FORMAT_R16G16_FLOAT,
- _DXGI_FORMAT_R32G32_FLOAT,
- // These last two are really wasteful, but c'est la vie.
- _DXGI_FORMAT_R16G16B16A16_FLOAT,
- _DXGI_FORMAT_R32G32B32A32_FLOAT,
- }
- for _, format := range formats {
- need := uint32(_D3D11_FORMAT_SUPPORT_TEXTURE2D | _D3D11_FORMAT_SUPPORT_RENDER_TARGET)
- if support, _ := dev.CheckFormatSupport(format); support&need == need {
- return format, true
- }
- }
- return 0, false
-}
-
-func (d *Device) CreateSwapChain(hwnd windows.Handle) (*SwapChain, error) {
- dxgiDev, err := _IUnknownQueryInterface(unsafe.Pointer(d.dev), d.dev.vtbl.QueryInterface, &_IID_IDXGIDevice)
- if err != nil {
- return nil, fmt.Errorf("NewContext: %v", err)
- }
- adapter, err := (*_IDXGIDevice)(unsafe.Pointer(dxgiDev)).GetAdapter()
- _IUnknownRelease(unsafe.Pointer(dxgiDev), dxgiDev.vtbl.Release)
- if err != nil {
- return nil, fmt.Errorf("NewContext: %v", err)
- }
- dxgiFactory, err := (*_IDXGIObject)(unsafe.Pointer(adapter)).GetParent(&_IID_IDXGIFactory)
- _IUnknownRelease(unsafe.Pointer(adapter), adapter.vtbl.Release)
- if err != nil {
- return nil, fmt.Errorf("NewContext: %v", err)
- }
- d3dswchain, err := (*_IDXGIFactory)(unsafe.Pointer(dxgiFactory)).CreateSwapChain(
- (*_IUnknown)(unsafe.Pointer(d.dev)),
- &_DXGI_SWAP_CHAIN_DESC{
- BufferDesc: _DXGI_MODE_DESC{
- Format: _DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- },
- SampleDesc: _DXGI_SAMPLE_DESC{
- Count: 1,
- },
- BufferUsage: _DXGI_USAGE_RENDER_TARGET_OUTPUT,
- BufferCount: 1,
- OutputWindow: hwnd,
- Windowed: 1,
- SwapEffect: _DXGI_SWAP_EFFECT_DISCARD,
- },
- )
- _IUnknownRelease(unsafe.Pointer(dxgiFactory), dxgiFactory.vtbl.Release)
- if err != nil {
- return nil, fmt.Errorf("NewContext: %v", err)
- }
- return &SwapChain{swchain: d3dswchain, fbo: &Framebuffer{}}, nil
-}
-
-func (s *SwapChain) Framebuffer(d *Device) (*Framebuffer, error) {
- if s.fbo.renderTarget != nil {
- return s.fbo, nil
- }
- desc, err := s.swchain.GetDesc()
- if err != nil {
- return nil, err
- }
- backBuffer, err := s.swchain.GetBuffer(0, &_IID_ID3D11Texture2D)
- if err != nil {
- return nil, err
- }
- texture := (*_ID3D11Resource)(unsafe.Pointer(backBuffer))
- renderTarget, err := d.dev.CreateRenderTargetView(texture)
- _IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.vtbl.Release)
- if err != nil {
- return nil, err
- }
- depthView, err := createDepthView(d.dev, int(desc.BufferDesc.Width), int(desc.BufferDesc.Height), 24)
- if err != nil {
- _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release)
- return nil, err
- }
- s.fbo.renderTarget = renderTarget
- s.fbo.depthView = depthView
- s.fbo.dev = d
- return s.fbo, nil
-}
-
-func (d *Device) Release() {
- _IUnknownRelease(unsafe.Pointer(d.ctx), d.ctx.vtbl.Release)
- _IUnknownRelease(unsafe.Pointer(d.dev), d.dev.vtbl.Release)
- d.ctx = nil
- d.dev = nil
- for _, state := range d.depthStates {
- _IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release)
- }
- d.depthStates = nil
- for _, state := range d.blendStates {
- _IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release)
- }
- d.blendStates = nil
-}
-
-func (s *SwapChain) Resize() error {
- if s.fbo.renderTarget != nil {
- s.fbo.Release()
- }
- return s.swchain.ResizeBuffers(0, 0, 0, _DXGI_FORMAT_UNKNOWN, 0)
-}
-
-func (s *SwapChain) Release() {
- _IUnknownRelease(unsafe.Pointer(s.swchain), s.swchain.vtbl.Release)
-}
-
-func (s *SwapChain) Present() error {
- return s.swchain.Present(1, 0)
-}
-
-func NewBackend(d *Device) (*Backend, error) {
- caps := backend.Caps{
- MaxTextureSize: 2048, // 9.1 maximum
- }
- switch {
- case d.featLvl >= _D3D_FEATURE_LEVEL_11_0:
- caps.MaxTextureSize = 16384
- case d.featLvl >= _D3D_FEATURE_LEVEL_9_3:
- caps.MaxTextureSize = 4096
- }
- b := &Backend{dev: d, caps: caps}
- // Disable backface culling to match OpenGL.
- state, err := b.dev.dev.CreateRasterizerState(&_D3D11_RASTERIZER_DESC{
- CullMode: _D3D11_CULL_NONE,
- FillMode: _D3D11_FILL_SOLID,
- DepthClipEnable: 1,
- })
- // Enable depth mask to match OpenGL.
- b.depthState.mask = true
- if err != nil {
- return nil, err
- }
- b.dev.ctx.RSSetState(state)
- _IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release)
- return b, nil
-}
-
-func (b *Backend) BeginFrame() {
-}
-
-func (b *Backend) EndFrame() {
-}
-
-func (b *Backend) Caps() backend.Caps {
- return b.caps
-}
-
-func (b *Backend) NewTimer() backend.Timer {
- panic("timers not supported")
-}
-
-func (b *Backend) IsTimeContinuous() bool {
- panic("timers not supported")
-}
-
-func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, minFilter, magFilter backend.TextureFilter, bindings backend.BufferBinding) (backend.Texture, error) {
- var d3dfmt uint32
- switch format {
- case backend.TextureFormatFloat:
- d3dfmt = b.dev.floatFormat
- case backend.TextureFormatSRGB:
- d3dfmt = _DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
- default:
- return nil, fmt.Errorf("unsupported texture format %d", format)
- }
- tex, err := b.dev.dev.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
- Width: uint32(width),
- Height: uint32(height),
- MipLevels: 1,
- ArraySize: 1,
- Format: d3dfmt,
- SampleDesc: _DXGI_SAMPLE_DESC{
- Count: 1,
- Quality: 0,
- },
- BindFlags: convBufferBinding(bindings),
- })
- if err != nil {
- return nil, err
- }
- var (
- sampler *_ID3D11SamplerState
- resView *_ID3D11ShaderResourceView
- )
- if bindings&backend.BufferBindingTexture != 0 {
- var filter uint32
- switch {
- case minFilter == backend.FilterNearest && magFilter == backend.FilterNearest:
- filter = _D3D11_FILTER_MIN_MAG_MIP_POINT
- case minFilter == backend.FilterLinear && magFilter == backend.FilterLinear:
- filter = _D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT
- default:
- _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release)
- return nil, fmt.Errorf("unsupported texture filter combination %d, %d", minFilter, magFilter)
- }
- var err error
- sampler, err = b.dev.dev.CreateSamplerState(&_D3D11_SAMPLER_DESC{
- Filter: filter,
- AddressU: _D3D11_TEXTURE_ADDRESS_CLAMP,
- AddressV: _D3D11_TEXTURE_ADDRESS_CLAMP,
- AddressW: _D3D11_TEXTURE_ADDRESS_CLAMP,
- MaxAnisotropy: 1,
- MinLOD: -math.MaxFloat32,
- MaxLOD: math.MaxFloat32,
- })
- if err != nil {
- _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release)
- return nil, err
- }
- resView, err = b.dev.dev.CreateShaderResourceViewTEX2D(
- (*_ID3D11Resource)(unsafe.Pointer(tex)),
- &_D3D11_SHADER_RESOURCE_VIEW_DESC_TEX2D{
- _D3D11_SHADER_RESOURCE_VIEW_DESC: _D3D11_SHADER_RESOURCE_VIEW_DESC{
- Format: d3dfmt,
- ViewDimension: _D3D11_SRV_DIMENSION_TEXTURE2D,
- },
- Texture2D: _D3D11_TEX2D_SRV{
- MostDetailedMip: 0,
- MipLevels: ^uint32(0),
- },
- },
- )
- if err != nil {
- _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release)
- _IUnknownRelease(unsafe.Pointer(sampler), sampler.vtbl.Release)
- return nil, err
- }
- }
- return &Texture{backend: b, format: d3dfmt, tex: tex, sampler: sampler, resView: resView, bindings: bindings, width: width, height: height}, nil
-}
-
-func (b *Backend) CurrentFramebuffer() backend.Framebuffer {
- renderTarget := b.dev.ctx.OMGetRenderTargets()
- if renderTarget != nil {
- // Assume someone else is holding on to it.
- _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release)
- }
- if renderTarget == b.fbo.renderTarget {
- return b.fbo
- }
- return &Framebuffer{dev: b.dev, renderTarget: renderTarget, foreign: true}
-}
-
-func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Framebuffer, error) {
- d3dtex := tex.(*Texture)
- if d3dtex.bindings&backend.BufferBindingFramebuffer == 0 {
- return nil, errors.New("the texture was created without BufferBindingFramebuffer binding")
- }
- resource := (*_ID3D11Resource)(unsafe.Pointer(d3dtex.tex))
- renderTarget, err := b.dev.dev.CreateRenderTargetView(resource)
- if err != nil {
- return nil, err
- }
- fbo := &Framebuffer{dev: b.dev, format: d3dtex.format, resource: resource, renderTarget: renderTarget}
- if depthBits > 0 {
- depthView, err := createDepthView(b.dev.dev, d3dtex.width, d3dtex.height, depthBits)
- if err != nil {
- _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release)
- return nil, err
- }
- fbo.depthView = depthView
- }
- return fbo, nil
-}
-
-func createDepthView(d *_ID3D11Device, width, height, depthBits int) (*_ID3D11DepthStencilView, error) {
- depthTex, err := d.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
- Width: uint32(width),
- Height: uint32(height),
- MipLevels: 1,
- ArraySize: 1,
- Format: _DXGI_FORMAT_D24_UNORM_S8_UINT,
- SampleDesc: _DXGI_SAMPLE_DESC{
- Count: 1,
- Quality: 0,
- },
- BindFlags: _D3D11_BIND_DEPTH_STENCIL,
- })
- if err != nil {
- return nil, err
- }
- depthView, err := d.CreateDepthStencilViewTEX2D(
- (*_ID3D11Resource)(unsafe.Pointer(depthTex)),
- &_D3D11_DEPTH_STENCIL_VIEW_DESC_TEX2D{
- Format: _DXGI_FORMAT_D24_UNORM_S8_UINT,
- ViewDimension: _D3D11_DSV_DIMENSION_TEXTURE2D,
- },
- )
- _IUnknownRelease(unsafe.Pointer(depthTex), depthTex.vtbl.Release)
- return depthView, err
-}
-
-func (b *Backend) NewInputLayout(vertexShader backend.ShaderSources, layout []backend.InputDesc) (backend.InputLayout, error) {
- if len(vertexShader.Inputs) != len(layout) {
- return nil, fmt.Errorf("NewInputLayout: got %d inputs, expected %d", len(layout), len(vertexShader.Inputs))
- }
- descs := make([]_D3D11_INPUT_ELEMENT_DESC, len(layout))
- for i, l := range layout {
- inp := vertexShader.Inputs[i]
- cname, err := windows.BytePtrFromString(inp.Semantic)
- if err != nil {
- return nil, err
- }
- var format uint32
- switch l.Type {
- case backend.DataTypeFloat:
- switch l.Size {
- case 1:
- format = _DXGI_FORMAT_R32_FLOAT
- case 2:
- format = _DXGI_FORMAT_R32G32_FLOAT
- case 3:
- format = _DXGI_FORMAT_R32G32B32_FLOAT
- case 4:
- format = _DXGI_FORMAT_R32G32B32A32_FLOAT
- default:
- panic("unsupported float data size")
- }
- case backend.DataTypeShort:
- switch l.Size {
- case 1:
- format = _DXGI_FORMAT_R16_SINT
- case 2:
- format = _DXGI_FORMAT_R16G16_SINT
- default:
- panic("unsupported float data size")
- }
- default:
- panic("unsupported data type")
- }
- descs[i] = _D3D11_INPUT_ELEMENT_DESC{
- SemanticName: cname,
- SemanticIndex: uint32(inp.SemanticIndex),
- Format: format,
- AlignedByteOffset: uint32(l.Offset),
- }
- }
- l, err := b.dev.dev.CreateInputLayout(descs, vertexShader.HLSL)
- if err != nil {
- return nil, err
- }
- return &InputLayout{dev: b.dev, layout: l}, nil
-}
-
-func (b *Backend) NewBuffer(typ backend.BufferBinding, size int) (backend.Buffer, error) {
- if typ&backend.BufferBindingUniforms != 0 {
- if typ != backend.BufferBindingUniforms {
- return nil, errors.New("uniform buffers cannot have other bindings")
- }
- if size%16 != 0 {
- return nil, fmt.Errorf("constant buffer size is %d, expected a multiple of 16", size)
- }
- }
- bind := convBufferBinding(typ)
- buf, err := b.dev.dev.CreateBuffer(&_D3D11_BUFFER_DESC{
- ByteWidth: uint32(size),
- BindFlags: bind,
- }, nil)
- if err != nil {
- return nil, err
- }
- return &Buffer{backend: b, buf: buf, bind: bind}, nil
-}
-
-func (b *Backend) NewImmutableBuffer(typ backend.BufferBinding, data []byte) (backend.Buffer, error) {
- if typ&backend.BufferBindingUniforms != 0 {
- if typ != backend.BufferBindingUniforms {
- return nil, errors.New("uniform buffers cannot have other bindings")
- }
- if len(data)%16 != 0 {
- return nil, fmt.Errorf("constant buffer size is %d, expected a multiple of 16", len(data))
- }
- }
- bind := convBufferBinding(typ)
- buf, err := b.dev.dev.CreateBuffer(&_D3D11_BUFFER_DESC{
- ByteWidth: uint32(len(data)),
- Usage: _D3D11_USAGE_IMMUTABLE,
- BindFlags: bind,
- }, data)
- if err != nil {
- return nil, err
- }
- return &Buffer{backend: b, buf: buf, bind: bind, immutable: true}, nil
-}
-
-func (b *Backend) NewProgram(vertexShader, fragmentShader backend.ShaderSources) (backend.Program, error) {
- vs, err := b.dev.dev.CreateVertexShader(vertexShader.HLSL)
- if err != nil {
- return nil, err
- }
- ps, err := b.dev.dev.CreatePixelShader(fragmentShader.HLSL)
- if err != nil {
- return nil, err
- }
- p := &Program{backend: b}
- p.vert.shader = vs
- p.frag.shader = ps
- return p, nil
-}
-
-func (b *Backend) Clear(colr, colg, colb, cola float32) {
- b.clearColor = [4]float32{colr, colg, colb, cola}
- b.dev.ctx.ClearRenderTargetView(b.fbo.renderTarget, &b.clearColor)
-}
-
-func (b *Backend) ClearDepth(depth float32) {
- if b.fbo.depthView != nil {
- b.dev.ctx.ClearDepthStencilView(b.fbo.depthView, _D3D11_CLEAR_DEPTH|_D3D11_CLEAR_STENCIL, depth, 0)
- }
-}
-
-func (b *Backend) Viewport(x, y, width, height int) {
- b.viewport = _D3D11_VIEWPORT{
- TopLeftX: float32(x),
- TopLeftY: float32(y),
- Width: float32(width),
- Height: float32(height),
- MinDepth: 0.0,
- MaxDepth: 1.0,
- }
- b.dev.ctx.RSSetViewports(&b.viewport)
-}
-
-func (b *Backend) DrawArrays(mode backend.DrawMode, off, count int) {
- b.prepareDraw(mode)
- b.dev.ctx.Draw(uint32(count), uint32(off))
-}
-
-func (b *Backend) DrawElements(mode backend.DrawMode, off, count int) {
- b.prepareDraw(mode)
- b.dev.ctx.DrawIndexed(uint32(count), uint32(off), 0)
-}
-
-func (b *Backend) prepareDraw(mode backend.DrawMode) {
- if p := b.prog; p != nil {
- b.dev.ctx.VSSetShader(p.vert.shader)
- b.dev.ctx.PSSetShader(p.frag.shader)
- if buf := p.vert.uniforms; buf != nil {
- b.dev.ctx.VSSetConstantBuffers(buf.buf)
- }
- if buf := p.frag.uniforms; buf != nil {
- b.dev.ctx.PSSetConstantBuffers(buf.buf)
- }
- }
- var topology uint32
- switch mode {
- case backend.DrawModeTriangles:
- topology = _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
- case backend.DrawModeTriangleStrip:
- topology = _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
- default:
- panic("unsupported draw mode")
- }
- b.dev.ctx.IASetPrimitiveTopology(topology)
-
- depthState, ok := b.dev.depthStates[b.depthState]
- if !ok {
- var desc _D3D11_DEPTH_STENCIL_DESC
- if b.depthState.enable {
- desc.DepthEnable = 1
- }
- if b.depthState.mask {
- desc.DepthWriteMask = _D3D11_DEPTH_WRITE_MASK_ALL
- }
- switch b.depthState.fn {
- case backend.DepthFuncGreater:
- desc.DepthFunc = _D3D11_COMPARISON_GREATER
- case backend.DepthFuncGreaterEqual:
- desc.DepthFunc = _D3D11_COMPARISON_GREATER_EQUAL
- default:
- panic("unsupported depth func")
- }
- var err error
- depthState, err = b.dev.dev.CreateDepthStencilState(&desc)
- if err != nil {
- panic(err)
- }
- b.dev.depthStates[b.depthState] = depthState
- }
- b.dev.ctx.OMSetDepthStencilState(depthState, 0)
-
- blendState, ok := b.dev.blendStates[b.blendState]
- if !ok {
- var desc _D3D11_BLEND_DESC
- t0 := &desc.RenderTarget[0]
- t0.RenderTargetWriteMask = _D3D11_COLOR_WRITE_ENABLE_ALL
- t0.BlendOp = _D3D11_BLEND_OP_ADD
- t0.BlendOpAlpha = _D3D11_BLEND_OP_ADD
- if b.blendState.enable {
- t0.BlendEnable = 1
- }
- scol, salpha := toBlendFactor(b.blendState.sfactor)
- dcol, dalpha := toBlendFactor(b.blendState.dfactor)
- t0.SrcBlend = scol
- t0.SrcBlendAlpha = salpha
- t0.DestBlend = dcol
- t0.DestBlendAlpha = dalpha
- var err error
- blendState, err = b.dev.dev.CreateBlendState(&desc)
- if err != nil {
- panic(err)
- }
- b.dev.blendStates[b.blendState] = blendState
- }
- b.dev.ctx.OMSetBlendState(blendState, nil, 0xffffffff)
-}
-
-func (b *Backend) DepthFunc(f backend.DepthFunc) {
- b.depthState.fn = f
-}
-
-func (b *Backend) SetBlend(enable bool) {
- b.blendState.enable = enable
-}
-
-func (b *Backend) SetDepthTest(enable bool) {
- b.depthState.enable = enable
-}
-
-func (b *Backend) DepthMask(mask bool) {
- b.depthState.mask = mask
-}
-
-func (b *Backend) BlendFunc(sfactor, dfactor backend.BlendFactor) {
- b.blendState.sfactor = sfactor
- b.blendState.dfactor = dfactor
-}
-
-func (t *Texture) Upload(img *image.RGBA) {
- b := img.Bounds()
- w := b.Dx()
- if img.Stride != w*4 {
- panic("unsupported stride")
- }
- start := (b.Min.X + b.Min.Y*w) * 4
- end := (b.Max.X + (b.Max.Y-1)*w) * 4
- pixels := img.Pix[start:end]
- res := (*_ID3D11Resource)(unsafe.Pointer(t.tex))
- t.backend.dev.ctx.UpdateSubresource(res, uint32(img.Stride), uint32(len(pixels)), pixels)
-}
-
-func (t *Texture) Release() {
- _IUnknownRelease(unsafe.Pointer(t.tex), t.tex.vtbl.Release)
- t.tex = nil
- if t.sampler != nil {
- _IUnknownRelease(unsafe.Pointer(t.sampler), t.sampler.vtbl.Release)
- t.sampler = nil
- }
- if t.resView != nil {
- _IUnknownRelease(unsafe.Pointer(t.resView), t.resView.vtbl.Release)
- t.resView = nil
- }
-}
-
-func (b *Backend) BindTexture(unit int, tex backend.Texture) {
- t := tex.(*Texture)
- b.dev.ctx.PSSetSamplers(uint32(unit), t.sampler)
- b.dev.ctx.PSSetShaderResources(uint32(unit), t.resView)
-}
-
-func (b *Backend) BindProgram(prog backend.Program) {
- b.prog = prog.(*Program)
-}
-
-func (p *Program) Release() {
- _IUnknownRelease(unsafe.Pointer(p.vert.shader), p.vert.shader.vtbl.Release)
- _IUnknownRelease(unsafe.Pointer(p.frag.shader), p.frag.shader.vtbl.Release)
- p.vert.shader = nil
- p.frag.shader = nil
-}
-
-func (p *Program) SetVertexUniforms(buf backend.Buffer) {
- p.vert.uniforms = buf.(*Buffer)
-}
-
-func (p *Program) SetFragmentUniforms(buf backend.Buffer) {
- p.frag.uniforms = buf.(*Buffer)
-}
-
-func (b *Backend) BindVertexBuffer(buf backend.Buffer, stride, offset int) {
- b.dev.ctx.IASetVertexBuffers(buf.(*Buffer).buf, uint32(stride), uint32(offset))
-}
-
-func (b *Backend) BindIndexBuffer(buf backend.Buffer) {
- b.dev.ctx.IASetIndexBuffer(buf.(*Buffer).buf, _DXGI_FORMAT_R16_UINT, 0)
-}
-
-func (b *Buffer) Upload(data []byte) {
- b.backend.dev.ctx.UpdateSubresource((*_ID3D11Resource)(unsafe.Pointer(b.buf)), 0, 0, data)
-}
-
-func (b *Buffer) Release() {
- _IUnknownRelease(unsafe.Pointer(b.buf), b.buf.vtbl.Release)
- b.buf = nil
-}
-
-func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte) error {
- if f.resource == nil {
- return errors.New("framebuffer does not support ReadPixels")
- }
- w, h := src.Dx(), src.Dy()
- tex, err := f.dev.dev.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
- Width: uint32(w),
- Height: uint32(h),
- MipLevels: 1,
- ArraySize: 1,
- Format: f.format,
- SampleDesc: _DXGI_SAMPLE_DESC{
- Count: 1,
- Quality: 0,
- },
- Usage: _D3D11_USAGE_STAGING,
- CPUAccessFlags: _D3D11_CPU_ACCESS_READ,
- })
- if err != nil {
- return fmt.Errorf("ReadPixels: %v", err)
- }
- defer _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release)
- res := (*_ID3D11Resource)(unsafe.Pointer(tex))
- f.dev.ctx.CopySubresourceRegion(
- res,
- 0, // Destination subresource.
- 0, 0, 0, // Destination coordinates (x, y, z).
- f.resource,
- 0, // Source subresource.
- &_D3D11_BOX{
- left: uint32(src.Min.X),
- top: uint32(src.Min.Y),
- right: uint32(src.Max.X),
- bottom: uint32(src.Max.Y),
- front: 0,
- back: 1,
- },
- )
- resMap, err := f.dev.ctx.Map(res, 0, _D3D11_MAP_READ, 0)
- if err != nil {
- return fmt.Errorf("ReadPixels: %v", err)
- }
- defer f.dev.ctx.Unmap(res, 0)
- srcPitch := w * 4
- dstPitch := int(resMap.RowPitch)
- mapSize := dstPitch * h
- data := gunsafe.SliceOf(resMap.pData)[:mapSize:mapSize]
- width := w * 4
- for r := 0; r < h; r++ {
- pixels := pixels[r*srcPitch:]
- copy(pixels[:width], data[r*dstPitch:])
- }
- return nil
-}
-
-func (b *Backend) BindFramebuffer(fbo backend.Framebuffer) {
- b.fbo = fbo.(*Framebuffer)
- b.dev.ctx.OMSetRenderTargets(b.fbo.renderTarget, b.fbo.depthView)
-}
-
-func (f *Framebuffer) Invalidate() {
-}
-
-func (f *Framebuffer) Release() {
- if f.foreign {
- panic("cannot release Framebuffer from CurrentFramebuffer")
- }
- if f.renderTarget != nil {
- _IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.vtbl.Release)
- f.renderTarget = nil
- }
- if f.depthView != nil {
- _IUnknownRelease(unsafe.Pointer(f.depthView), f.depthView.vtbl.Release)
- f.depthView = nil
- }
-}
-
-func (b *Backend) BindInputLayout(layout backend.InputLayout) {
- b.dev.ctx.IASetInputLayout(layout.(*InputLayout).layout)
-}
-
-func (l *InputLayout) Release() {
- _IUnknownRelease(unsafe.Pointer(l.layout), l.layout.vtbl.Release)
- l.layout = nil
-}
-
-func convBufferBinding(typ backend.BufferBinding) uint32 {
- var bindings uint32
- if typ&backend.BufferBindingVertices != 0 {
- bindings |= _D3D11_BIND_VERTEX_BUFFER
- }
- if typ&backend.BufferBindingIndices != 0 {
- bindings |= _D3D11_BIND_INDEX_BUFFER
- }
- if typ&backend.BufferBindingUniforms != 0 {
- bindings |= _D3D11_BIND_CONSTANT_BUFFER
- }
- if typ&backend.BufferBindingTexture != 0 {
- bindings |= _D3D11_BIND_SHADER_RESOURCE
- }
- if typ&backend.BufferBindingFramebuffer != 0 {
- bindings |= _D3D11_BIND_RENDER_TARGET
- }
- return bindings
-}
-
-func toBlendFactor(f backend.BlendFactor) (uint32, uint32) {
- switch f {
- case backend.BlendFactorOne:
- return _D3D11_BLEND_ONE, _D3D11_BLEND_ONE
- case backend.BlendFactorOneMinusSrcAlpha:
- return _D3D11_BLEND_INV_SRC_ALPHA, _D3D11_BLEND_INV_SRC_ALPHA
- case backend.BlendFactorZero:
- return _D3D11_BLEND_ZERO, _D3D11_BLEND_ZERO
- case backend.BlendFactorDstColor:
- return _D3D11_BLEND_DEST_COLOR, _D3D11_BLEND_DEST_ALPHA
- default:
- panic("unsupported blend source factor")
- }
-}
diff --git a/vendor/gioui.org/app/internal/d3d11/d3d11_windows.go b/vendor/gioui.org/app/internal/d3d11/d3d11_windows.go
deleted file mode 100644
index 3dd2138..0000000
--- a/vendor/gioui.org/app/internal/d3d11/d3d11_windows.go
+++ /dev/null
@@ -1,1344 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package d3d11
-
-import (
- "fmt"
- "math"
- "syscall"
- "unsafe"
-
- "gioui.org/internal/f32color"
-
- "golang.org/x/sys/windows"
-)
-
-type _DXGI_SWAP_CHAIN_DESC struct {
- BufferDesc _DXGI_MODE_DESC
- SampleDesc _DXGI_SAMPLE_DESC
- BufferUsage uint32
- BufferCount uint32
- OutputWindow windows.Handle
- Windowed uint32
- SwapEffect uint32
- Flags uint32
-}
-
-type _DXGI_SAMPLE_DESC struct {
- Count uint32
- Quality uint32
-}
-
-type _DXGI_MODE_DESC struct {
- Width uint32
- Height uint32
- RefreshRate _DXGI_RATIONAL
- Format uint32
- ScanlineOrdering uint32
- Scaling uint32
-}
-
-type _DXGI_RATIONAL struct {
- Numerator uint32
- Denominator uint32
-}
-
-type _D3D11_TEXTURE2D_DESC struct {
- Width uint32
- Height uint32
- MipLevels uint32
- ArraySize uint32
- Format uint32
- SampleDesc _DXGI_SAMPLE_DESC
- Usage uint32
- BindFlags uint32
- CPUAccessFlags uint32
- MiscFlags uint32
-}
-
-type _D3D11_SAMPLER_DESC struct {
- Filter uint32
- AddressU uint32
- AddressV uint32
- AddressW uint32
- MipLODBias float32
- MaxAnisotropy uint32
- ComparisonFunc uint32
- BorderColor [4]float32
- MinLOD float32
- MaxLOD float32
-}
-
-type _D3D11_SHADER_RESOURCE_VIEW_DESC_TEX2D struct {
- _D3D11_SHADER_RESOURCE_VIEW_DESC
- Texture2D _D3D11_TEX2D_SRV
-}
-
-type _D3D11_SHADER_RESOURCE_VIEW_DESC struct {
- Format uint32
- ViewDimension uint32
-}
-
-type _D3D11_TEX2D_SRV struct {
- MostDetailedMip uint32
- MipLevels uint32
-}
-
-type _D3D11_INPUT_ELEMENT_DESC struct {
- SemanticName *byte
- SemanticIndex uint32
- Format uint32
- InputSlot uint32
- AlignedByteOffset uint32
- InputSlotClass uint32
- InstanceDataStepRate uint32
-}
-
-type _IDXGISwapChain struct {
- vtbl *struct {
- _IUnknownVTbl
- SetPrivateData uintptr
- SetPrivateDataInterface uintptr
- GetPrivateData uintptr
- GetParent uintptr
- GetDevice uintptr
- Present uintptr
- GetBuffer uintptr
- SetFullscreenState uintptr
- GetFullscreenState uintptr
- GetDesc uintptr
- ResizeBuffers uintptr
- ResizeTarget uintptr
- GetContainingOutput uintptr
- GetFrameStatistics uintptr
- GetLastPresentCount uintptr
- }
-}
-
-type _ID3D11Device struct {
- vtbl *struct {
- _IUnknownVTbl
- CreateBuffer uintptr
- CreateTexture1D uintptr
- CreateTexture2D uintptr
- CreateTexture3D uintptr
- CreateShaderResourceView uintptr
- CreateUnorderedAccessView uintptr
- CreateRenderTargetView uintptr
- CreateDepthStencilView uintptr
- CreateInputLayout uintptr
- CreateVertexShader uintptr
- CreateGeometryShader uintptr
- CreateGeometryShaderWithStreamOutput uintptr
- CreatePixelShader uintptr
- CreateHullShader uintptr
- CreateDomainShader uintptr
- CreateComputeShader uintptr
- CreateClassLinkage uintptr
- CreateBlendState uintptr
- CreateDepthStencilState uintptr
- CreateRasterizerState uintptr
- CreateSamplerState uintptr
- CreateQuery uintptr
- CreatePredicate uintptr
- CreateCounter uintptr
- CreateDeferredContext uintptr
- OpenSharedResource uintptr
- CheckFormatSupport uintptr
- CheckMultisampleQualityLevels uintptr
- CheckCounterInfo uintptr
- CheckCounter uintptr
- CheckFeatureSupport uintptr
- GetPrivateData uintptr
- SetPrivateData uintptr
- SetPrivateDataInterface uintptr
- GetFeatureLevel uintptr
- GetCreationFlags uintptr
- GetDeviceRemovedReason uintptr
- GetImmediateContext uintptr
- SetExceptionMode uintptr
- GetExceptionMode uintptr
- }
-}
-
-type _ID3D11DeviceContext struct {
- vtbl *struct {
- _IUnknownVTbl
- GetDevice uintptr
- GetPrivateData uintptr
- SetPrivateData uintptr
- SetPrivateDataInterface uintptr
- VSSetConstantBuffers uintptr
- PSSetShaderResources uintptr
- PSSetShader uintptr
- PSSetSamplers uintptr
- VSSetShader uintptr
- DrawIndexed uintptr
- Draw uintptr
- Map uintptr
- Unmap uintptr
- PSSetConstantBuffers uintptr
- IASetInputLayout uintptr
- IASetVertexBuffers uintptr
- IASetIndexBuffer uintptr
- DrawIndexedInstanced uintptr
- DrawInstanced uintptr
- GSSetConstantBuffers uintptr
- GSSetShader uintptr
- IASetPrimitiveTopology uintptr
- VSSetShaderResources uintptr
- VSSetSamplers uintptr
- Begin uintptr
- End uintptr
- GetData uintptr
- SetPredication uintptr
- GSSetShaderResources uintptr
- GSSetSamplers uintptr
- OMSetRenderTargets uintptr
- OMSetRenderTargetsAndUnorderedAccessViews uintptr
- OMSetBlendState uintptr
- OMSetDepthStencilState uintptr
- SOSetTargets uintptr
- DrawAuto uintptr
- DrawIndexedInstancedIndirect uintptr
- DrawInstancedIndirect uintptr
- Dispatch uintptr
- DispatchIndirect uintptr
- RSSetState uintptr
- RSSetViewports uintptr
- RSSetScissorRects uintptr
- CopySubresourceRegion uintptr
- CopyResource uintptr
- UpdateSubresource uintptr
- CopyStructureCount uintptr
- ClearRenderTargetView uintptr
- ClearUnorderedAccessViewUint uintptr
- ClearUnorderedAccessViewFloat uintptr
- ClearDepthStencilView uintptr
- GenerateMips uintptr
- SetResourceMinLOD uintptr
- GetResourceMinLOD uintptr
- ResolveSubresource uintptr
- ExecuteCommandList uintptr
- HSSetShaderResources uintptr
- HSSetShader uintptr
- HSSetSamplers uintptr
- HSSetConstantBuffers uintptr
- DSSetShaderResources uintptr
- DSSetShader uintptr
- DSSetSamplers uintptr
- DSSetConstantBuffers uintptr
- CSSetShaderResources uintptr
- CSSetUnorderedAccessViews uintptr
- CSSetShader uintptr
- CSSetSamplers uintptr
- CSSetConstantBuffers uintptr
- VSGetConstantBuffers uintptr
- PSGetShaderResources uintptr
- PSGetShader uintptr
- PSGetSamplers uintptr
- VSGetShader uintptr
- PSGetConstantBuffers uintptr
- IAGetInputLayout uintptr
- IAGetVertexBuffers uintptr
- IAGetIndexBuffer uintptr
- GSGetConstantBuffers uintptr
- GSGetShader uintptr
- IAGetPrimitiveTopology uintptr
- VSGetShaderResources uintptr
- VSGetSamplers uintptr
- GetPredication uintptr
- GSGetShaderResources uintptr
- GSGetSamplers uintptr
- OMGetRenderTargets uintptr
- OMGetRenderTargetsAndUnorderedAccessViews uintptr
- OMGetBlendState uintptr
- OMGetDepthStencilState uintptr
- SOGetTargets uintptr
- RSGetState uintptr
- RSGetViewports uintptr
- RSGetScissorRects uintptr
- HSGetShaderResources uintptr
- HSGetShader uintptr
- HSGetSamplers uintptr
- HSGetConstantBuffers uintptr
- DSGetShaderResources uintptr
- DSGetShader uintptr
- DSGetSamplers uintptr
- DSGetConstantBuffers uintptr
- CSGetShaderResources uintptr
- CSGetUnorderedAccessViews uintptr
- CSGetShader uintptr
- CSGetSamplers uintptr
- CSGetConstantBuffers uintptr
- ClearState uintptr
- Flush uintptr
- GetType uintptr
- GetContextFlags uintptr
- FinishCommandList uintptr
- }
-}
-
-type _ID3D11RenderTargetView struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11Resource struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11Texture2D struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11Buffer struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11SamplerState struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11PixelShader struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11ShaderResourceView struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11DepthStencilView struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11BlendState struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11DepthStencilState struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11VertexShader struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11RasterizerState struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _ID3D11InputLayout struct {
- vtbl *struct {
- _IUnknownVTbl
- GetBufferPointer uintptr
- GetBufferSize uintptr
- }
-}
-
-type _D3D11_DEPTH_STENCIL_DESC struct {
- DepthEnable uint32
- DepthWriteMask uint32
- DepthFunc uint32
- StencilEnable uint32
- StencilReadMask uint8
- StencilWriteMask uint8
- FrontFace _D3D11_DEPTH_STENCILOP_DESC
- BackFace _D3D11_DEPTH_STENCILOP_DESC
-}
-
-type _D3D11_DEPTH_STENCILOP_DESC struct {
- StencilFailOp uint32
- StencilDepthFailOp uint32
- StencilPassOp uint32
- StencilFunc uint32
-}
-
-type _D3D11_DEPTH_STENCIL_VIEW_DESC_TEX2D struct {
- Format uint32
- ViewDimension uint32
- Flags uint32
- Texture2D _D3D11_TEX2D_DSV
-}
-
-type _D3D11_TEX2D_DSV struct {
- MipSlice uint32
-}
-
-type _D3D11_BLEND_DESC struct {
- AlphaToCoverageEnable uint32
- IndependentBlendEnable uint32
- RenderTarget [8]_D3D11_RENDER_TARGET_BLEND_DESC
-}
-
-type _D3D11_RENDER_TARGET_BLEND_DESC struct {
- BlendEnable uint32
- SrcBlend uint32
- DestBlend uint32
- BlendOp uint32
- SrcBlendAlpha uint32
- DestBlendAlpha uint32
- BlendOpAlpha uint32
- RenderTargetWriteMask uint8
-}
-
-type _IDXGIObject struct {
- vtbl *struct {
- _IUnknownVTbl
- SetPrivateData uintptr
- SetPrivateDataInterface uintptr
- GetPrivateData uintptr
- GetParent uintptr
- }
-}
-
-type _IDXGIAdapter struct {
- vtbl *struct {
- _IUnknownVTbl
- SetPrivateData uintptr
- SetPrivateDataInterface uintptr
- GetPrivateData uintptr
- GetParent uintptr
- EnumOutputs uintptr
- GetDesc uintptr
- CheckInterfaceSupport uintptr
- GetDesc1 uintptr
- }
-}
-
-type _IDXGIFactory struct {
- vtbl *struct {
- _IUnknownVTbl
- SetPrivateData uintptr
- SetPrivateDataInterface uintptr
- GetPrivateData uintptr
- GetParent uintptr
- EnumAdapters uintptr
- MakeWindowAssociation uintptr
- GetWindowAssociation uintptr
- CreateSwapChain uintptr
- CreateSoftwareAdapter uintptr
- }
-}
-
-type _IDXGIDevice struct {
- vtbl *struct {
- _IUnknownVTbl
- SetPrivateData uintptr
- SetPrivateDataInterface uintptr
- GetPrivateData uintptr
- GetParent uintptr
- GetAdapter uintptr
- CreateSurface uintptr
- QueryResourceResidency uintptr
- SetGPUThreadPriority uintptr
- GetGPUThreadPriority uintptr
- }
-}
-
-type _IUnknown struct {
- vtbl *struct {
- _IUnknownVTbl
- }
-}
-
-type _IUnknownVTbl struct {
- QueryInterface uintptr
- AddRef uintptr
- Release uintptr
-}
-
-type _D3D11_BUFFER_DESC struct {
- ByteWidth uint32
- Usage uint32
- BindFlags uint32
- CPUAccessFlags uint32
- MiscFlags uint32
- StructureByteStride uint32
-}
-
-type _GUID struct {
- Data1 uint32
- Data2 uint16
- Data3 uint16
- Data4_0 uint8
- Data4_1 uint8
- Data4_2 uint8
- Data4_3 uint8
- Data4_4 uint8
- Data4_5 uint8
- Data4_6 uint8
- Data4_7 uint8
-}
-
-type _D3D11_VIEWPORT struct {
- TopLeftX float32
- TopLeftY float32
- Width float32
- Height float32
- MinDepth float32
- MaxDepth float32
-}
-
-type _D3D11_SUBRESOURCE_DATA struct {
- pSysMem *byte
-}
-
-type _D3D11_BOX struct {
- left uint32
- top uint32
- front uint32
- right uint32
- bottom uint32
- back uint32
-}
-
-type _D3D11_MAPPED_SUBRESOURCE struct {
- pData uintptr
- RowPitch uint32
- DepthPitch uint32
-}
-
-type ErrorCode struct {
- Name string
- Code uint32
-}
-
-type _D3D11_RASTERIZER_DESC struct {
- FillMode uint32
- CullMode uint32
- FrontCounterClockwise uint32
- DepthBias int32
- DepthBiasClamp float32
- SlopeScaledDepthBias float32
- DepthClipEnable uint32
- ScissorEnable uint32
- MultisampleEnable uint32
- AntialiasedLineEnable uint32
-}
-
-var (
- _IID_ID3D11Texture2D = _GUID{0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c}
- _IID_IDXGIDevice = _GUID{0x54ec77fa, 0x1377, 0x44e6, 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c}
- _IID_IDXGIFactory = _GUID{0x7b7166ec, 0x21c7, 0x44ae, 0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3, 0x69}
-)
-
-var (
- d3d11 = windows.NewLazySystemDLL("d3d11.dll")
-
- __D3D11CreateDevice = d3d11.NewProc("D3D11CreateDevice")
- __D3D11CreateDeviceAndSwapChain = d3d11.NewProc("D3D11CreateDeviceAndSwapChain")
-)
-
-const (
- _D3D11_SDK_VERSION = 7
- _D3D_DRIVER_TYPE_HARDWARE = 1
-
- _DXGI_FORMAT_UNKNOWN = 0
- _DXGI_FORMAT_R16_FLOAT = 54
- _DXGI_FORMAT_R32_FLOAT = 41
- _DXGI_FORMAT_R32G32_FLOAT = 16
- _DXGI_FORMAT_R32G32B32_FLOAT = 6
- _DXGI_FORMAT_R32G32B32A32_FLOAT = 2
- _DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29
- _DXGI_FORMAT_R16_SINT = 59
- _DXGI_FORMAT_R16G16_SINT = 38
- _DXGI_FORMAT_R16_UINT = 57
- _DXGI_FORMAT_D24_UNORM_S8_UINT = 45
- _DXGI_FORMAT_R16G16_FLOAT = 34
- _DXGI_FORMAT_R16G16B16A16_FLOAT = 10
-
- _D3D11_FORMAT_SUPPORT_TEXTURE2D = 0x20
- _D3D11_FORMAT_SUPPORT_RENDER_TARGET = 0x4000
-
- _DXGI_USAGE_RENDER_TARGET_OUTPUT = 1 << (1 + 4)
-
- _D3D11_CPU_ACCESS_READ = 0x20000
-
- _D3D11_MAP_READ = 1
-
- _DXGI_SWAP_EFFECT_DISCARD = 0
-
- _D3D_FEATURE_LEVEL_9_1 = 0x9100
- _D3D_FEATURE_LEVEL_9_3 = 0x9300
- _D3D_FEATURE_LEVEL_11_0 = 0xb000
-
- _D3D11_USAGE_IMMUTABLE = 1
- _D3D11_USAGE_STAGING = 3
-
- _D3D11_BIND_VERTEX_BUFFER = 0x1
- _D3D11_BIND_INDEX_BUFFER = 0x2
- _D3D11_BIND_CONSTANT_BUFFER = 0x4
- _D3D11_BIND_SHADER_RESOURCE = 0x8
- _D3D11_BIND_RENDER_TARGET = 0x20
- _D3D11_BIND_DEPTH_STENCIL = 0x40
-
- _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4
- _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5
-
- _D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14
- _D3D11_FILTER_MIN_MAG_MIP_POINT = 0
-
- _D3D11_TEXTURE_ADDRESS_MIRROR = 2
- _D3D11_TEXTURE_ADDRESS_CLAMP = 3
- _D3D11_TEXTURE_ADDRESS_WRAP = 1
-
- _D3D11_SRV_DIMENSION_TEXTURE2D = 4
-
- _D3D11_CREATE_DEVICE_DEBUG = 0x2
-
- _D3D11_FILL_SOLID = 3
-
- _D3D11_CULL_NONE = 1
-
- _D3D11_CLEAR_DEPTH = 0x1
- _D3D11_CLEAR_STENCIL = 0x2
-
- _D3D11_DSV_DIMENSION_TEXTURE2D = 3
-
- _D3D11_DEPTH_WRITE_MASK_ALL = 1
-
- _D3D11_COMPARISON_GREATER = 5
- _D3D11_COMPARISON_GREATER_EQUAL = 7
-
- _D3D11_BLEND_OP_ADD = 1
- _D3D11_BLEND_ONE = 2
- _D3D11_BLEND_INV_SRC_ALPHA = 6
- _D3D11_BLEND_ZERO = 1
- _D3D11_BLEND_DEST_COLOR = 9
- _D3D11_BLEND_DEST_ALPHA = 7
-
- _D3D11_COLOR_WRITE_ENABLE_ALL = 1 | 2 | 4 | 8
-
- DXGI_STATUS_OCCLUDED = 0x087A0001
- DXGI_ERROR_DEVICE_RESET = 0x887A0007
- DXGI_ERROR_DEVICE_REMOVED = 0x887A0005
- D3DDDIERR_DEVICEREMOVED = 1<<31 | 0x876<<16 | 2160
-)
-
-func _D3D11CreateDevice(driverType uint32, flags uint32) (*_ID3D11Device, *_ID3D11DeviceContext, uint32, error) {
- var (
- dev *_ID3D11Device
- ctx *_ID3D11DeviceContext
- featLvl uint32
- )
- r, _, _ := __D3D11CreateDevice.Call(
- 0, // pAdapter
- uintptr(driverType), // driverType
- 0, // Software
- uintptr(flags), // Flags
- 0, // pFeatureLevels
- 0, // FeatureLevels
- _D3D11_SDK_VERSION, // SDKVersion
- uintptr(unsafe.Pointer(&dev)), // ppDevice
- uintptr(unsafe.Pointer(&featLvl)), // pFeatureLevel
- uintptr(unsafe.Pointer(&ctx)), // ppImmediateContext
- )
- if r != 0 {
- return nil, nil, 0, ErrorCode{Name: "D3D11CreateDevice", Code: uint32(r)}
- }
- return dev, ctx, featLvl, nil
-}
-
-func _D3D11CreateDeviceAndSwapChain(driverType uint32, flags uint32, swapDesc *_DXGI_SWAP_CHAIN_DESC) (*_ID3D11Device, *_ID3D11DeviceContext, *_IDXGISwapChain, uint32, error) {
- var (
- dev *_ID3D11Device
- ctx *_ID3D11DeviceContext
- swchain *_IDXGISwapChain
- featLvl uint32
- )
- r, _, _ := __D3D11CreateDeviceAndSwapChain.Call(
- 0, // pAdapter
- uintptr(driverType), // driverType
- 0, // Software
- uintptr(flags), // Flags
- 0, // pFeatureLevels
- 0, // FeatureLevels
- _D3D11_SDK_VERSION, // SDKVersion
- uintptr(unsafe.Pointer(swapDesc)), // pSwapChainDesc
- uintptr(unsafe.Pointer(&swchain)), // ppSwapChain
- uintptr(unsafe.Pointer(&dev)), // ppDevice
- uintptr(unsafe.Pointer(&featLvl)), // pFeatureLevel
- uintptr(unsafe.Pointer(&ctx)), // ppImmediateContext
- )
- if r != 0 {
- return nil, nil, nil, 0, ErrorCode{Name: "D3D11CreateDeviceAndSwapChain", Code: uint32(r)}
- }
- return dev, ctx, swchain, featLvl, nil
-}
-
-func (d *_ID3D11Device) CheckFormatSupport(format uint32) (uint32, error) {
- var support uint32
- r, _, _ := syscall.Syscall(
- d.vtbl.CheckFormatSupport,
- 3,
- uintptr(unsafe.Pointer(d)),
- uintptr(format),
- uintptr(unsafe.Pointer(&support)),
- )
- if r != 0 {
- return 0, ErrorCode{Name: "ID3D11DeviceCheckFormatSupport", Code: uint32(r)}
- }
- return support, nil
-}
-
-func (d *_ID3D11Device) CreateBuffer(desc *_D3D11_BUFFER_DESC, data []byte) (*_ID3D11Buffer, error) {
- var dataDesc *_D3D11_SUBRESOURCE_DATA
- if len(data) > 0 {
- dataDesc = &_D3D11_SUBRESOURCE_DATA{
- pSysMem: &data[0],
- }
- }
- var buf *_ID3D11Buffer
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateBuffer,
- 4,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(dataDesc)),
- uintptr(unsafe.Pointer(&buf)),
- 0, 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateBuffer", Code: uint32(r)}
- }
- return buf, nil
-}
-
-func (d *_ID3D11Device) CreateDepthStencilViewTEX2D(res *_ID3D11Resource, desc *_D3D11_DEPTH_STENCIL_VIEW_DESC_TEX2D) (*_ID3D11DepthStencilView, error) {
- var view *_ID3D11DepthStencilView
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateDepthStencilView,
- 4,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(res)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(&view)),
- 0, 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateDepthStencilView", Code: uint32(r)}
- }
- return view, nil
-}
-
-func (d *_ID3D11Device) CreatePixelShader(bytecode []byte) (*_ID3D11PixelShader, error) {
- var shader *_ID3D11PixelShader
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreatePixelShader,
- 5,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(&bytecode[0])),
- uintptr(len(bytecode)),
- 0, // pClassLinkage
- uintptr(unsafe.Pointer(&shader)),
- 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreatePixelShader", Code: uint32(r)}
- }
- return shader, nil
-}
-
-func (d *_ID3D11Device) CreateVertexShader(bytecode []byte) (*_ID3D11VertexShader, error) {
- var shader *_ID3D11VertexShader
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateVertexShader,
- 5,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(&bytecode[0])),
- uintptr(len(bytecode)),
- 0, // pClassLinkage
- uintptr(unsafe.Pointer(&shader)),
- 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateVertexShader", Code: uint32(r)}
- }
- return shader, nil
-}
-
-func (d *_ID3D11Device) CreateShaderResourceViewTEX2D(res *_ID3D11Resource, desc *_D3D11_SHADER_RESOURCE_VIEW_DESC_TEX2D) (*_ID3D11ShaderResourceView, error) {
- var resView *_ID3D11ShaderResourceView
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateShaderResourceView,
- 4,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(res)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(&resView)),
- 0, 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateShaderResourceView", Code: uint32(r)}
- }
- return resView, nil
-}
-
-func (d *_ID3D11Device) CreateRasterizerState(desc *_D3D11_RASTERIZER_DESC) (*_ID3D11RasterizerState, error) {
- var state *_ID3D11RasterizerState
- r, _, _ := syscall.Syscall(
- d.vtbl.CreateRasterizerState,
- 3,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(&state)),
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateRasterizerState", Code: uint32(r)}
- }
- return state, nil
-}
-
-func (d *_ID3D11Device) CreateInputLayout(descs []_D3D11_INPUT_ELEMENT_DESC, bytecode []byte) (*_ID3D11InputLayout, error) {
- var pdesc *_D3D11_INPUT_ELEMENT_DESC
- if len(descs) > 0 {
- pdesc = &descs[0]
- }
- var layout *_ID3D11InputLayout
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateInputLayout,
- 6,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(pdesc)),
- uintptr(len(descs)),
- uintptr(unsafe.Pointer(&bytecode[0])),
- uintptr(len(bytecode)),
- uintptr(unsafe.Pointer(&layout)),
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateInputLayout", Code: uint32(r)}
- }
- return layout, nil
-}
-
-func (d *_ID3D11Device) CreateSamplerState(desc *_D3D11_SAMPLER_DESC) (*_ID3D11SamplerState, error) {
- var sampler *_ID3D11SamplerState
- r, _, _ := syscall.Syscall(
- d.vtbl.CreateSamplerState,
- 3,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(&sampler)),
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateSamplerState", Code: uint32(r)}
- }
- return sampler, nil
-}
-
-func (d *_ID3D11Device) CreateTexture2D(desc *_D3D11_TEXTURE2D_DESC) (*_ID3D11Texture2D, error) {
- var tex *_ID3D11Texture2D
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateTexture2D,
- 4,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(desc)),
- 0, // pInitialData
- uintptr(unsafe.Pointer(&tex)),
- 0, 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11CreateTexture2D", Code: uint32(r)}
- }
- return tex, nil
-}
-
-func (d *_ID3D11Device) CreateRenderTargetView(res *_ID3D11Resource) (*_ID3D11RenderTargetView, error) {
- var target *_ID3D11RenderTargetView
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateRenderTargetView,
- 4,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(res)),
- 0, // pDesc
- uintptr(unsafe.Pointer(&target)),
- 0, 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateRenderTargetView", Code: uint32(r)}
- }
- return target, nil
-}
-
-func (d *_ID3D11Device) CreateBlendState(desc *_D3D11_BLEND_DESC) (*_ID3D11BlendState, error) {
- var state *_ID3D11BlendState
- r, _, _ := syscall.Syscall(
- d.vtbl.CreateBlendState,
- 3,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(&state)),
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateBlendState", Code: uint32(r)}
- }
- return state, nil
-}
-
-func (d *_ID3D11Device) CreateDepthStencilState(desc *_D3D11_DEPTH_STENCIL_DESC) (*_ID3D11DepthStencilState, error) {
- var state *_ID3D11DepthStencilState
- r, _, _ := syscall.Syscall(
- d.vtbl.CreateDepthStencilState,
- 3,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(&state)),
- )
- if r != 0 {
- return nil, ErrorCode{Name: "ID3D11DeviceCreateDepthStencilState", Code: uint32(r)}
- }
- return state, nil
-}
-
-func (s *_IDXGISwapChain) GetDesc() (_DXGI_SWAP_CHAIN_DESC, error) {
- var desc _DXGI_SWAP_CHAIN_DESC
- r, _, _ := syscall.Syscall(
- s.vtbl.GetDesc,
- 2,
- uintptr(unsafe.Pointer(s)),
- uintptr(unsafe.Pointer(&desc)),
- 0,
- )
- if r != 0 {
- return _DXGI_SWAP_CHAIN_DESC{}, ErrorCode{Name: "IDXGISwapChainGetDesc", Code: uint32(r)}
- }
- return desc, nil
-}
-
-func (s *_IDXGISwapChain) ResizeBuffers(buffers, width, height, newFormat, flags uint32) error {
- r, _, _ := syscall.Syscall6(
- s.vtbl.ResizeBuffers,
- 6,
- uintptr(unsafe.Pointer(s)),
- uintptr(buffers),
- uintptr(width),
- uintptr(height),
- uintptr(newFormat),
- uintptr(flags),
- )
- if r != 0 {
- return ErrorCode{Name: "IDXGISwapChainResizeBuffers", Code: uint32(r)}
- }
- return nil
-}
-
-func (s *_IDXGISwapChain) Present(SyncInterval int, Flags uint32) error {
- r, _, _ := syscall.Syscall(
- s.vtbl.Present,
- 3,
- uintptr(unsafe.Pointer(s)),
- uintptr(SyncInterval),
- uintptr(Flags),
- )
- if r != 0 {
- return ErrorCode{Name: "IDXGISwapChainPresent", Code: uint32(r)}
- }
- return nil
-}
-
-func (s *_IDXGISwapChain) GetBuffer(index int, riid *_GUID) (*_IUnknown, error) {
- var buf *_IUnknown
- r, _, _ := syscall.Syscall6(
- s.vtbl.GetBuffer,
- 4,
- uintptr(unsafe.Pointer(s)),
- uintptr(index),
- uintptr(unsafe.Pointer(riid)),
- uintptr(unsafe.Pointer(&buf)),
- 0,
- 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "IDXGISwapChainGetBuffer", Code: uint32(r)}
- }
- return buf, nil
-}
-
-func (c *_ID3D11DeviceContext) Unmap(resource *_ID3D11Resource, subResource uint32) {
- syscall.Syscall(
- c.vtbl.Unmap,
- 3,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(resource)),
- uintptr(subResource),
- )
-}
-
-func (c *_ID3D11DeviceContext) Map(resource *_ID3D11Resource, subResource, mapType, mapFlags uint32) (_D3D11_MAPPED_SUBRESOURCE, error) {
- var resMap _D3D11_MAPPED_SUBRESOURCE
- r, _, _ := syscall.Syscall6(
- c.vtbl.Map,
- 6,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(resource)),
- uintptr(subResource),
- uintptr(mapType),
- uintptr(mapFlags),
- uintptr(unsafe.Pointer(&resMap)),
- )
- if r != 0 {
- return resMap, ErrorCode{Name: "ID3D11DeviceContextMap", Code: uint32(r)}
- }
- return resMap, nil
-}
-
-func (c *_ID3D11DeviceContext) CopySubresourceRegion(dst *_ID3D11Resource, dstSubresource, dstX, dstY, dstZ uint32, src *_ID3D11Resource, srcSubresource uint32, srcBox *_D3D11_BOX) {
- syscall.Syscall9(
- c.vtbl.CopySubresourceRegion,
- 9,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(dst)),
- uintptr(dstSubresource),
- uintptr(dstX),
- uintptr(dstY),
- uintptr(dstZ),
- uintptr(unsafe.Pointer(src)),
- uintptr(srcSubresource),
- uintptr(unsafe.Pointer(srcBox)),
- )
-}
-
-func (c *_ID3D11DeviceContext) ClearDepthStencilView(target *_ID3D11DepthStencilView, flags uint32, depth float32, stencil uint8) {
- syscall.Syscall6(
- c.vtbl.ClearDepthStencilView,
- 5,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(target)),
- uintptr(flags),
- uintptr(math.Float32bits(depth)),
- uintptr(stencil),
- 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) ClearRenderTargetView(target *_ID3D11RenderTargetView, color *[4]float32) {
- syscall.Syscall(
- c.vtbl.ClearRenderTargetView,
- 3,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(target)),
- uintptr(unsafe.Pointer(color)),
- )
-}
-
-func (c *_ID3D11DeviceContext) RSSetViewports(viewport *_D3D11_VIEWPORT) {
- syscall.Syscall(
- c.vtbl.RSSetViewports,
- 3,
- uintptr(unsafe.Pointer(c)),
- 1, // NumViewports
- uintptr(unsafe.Pointer(viewport)),
- )
-}
-
-func (c *_ID3D11DeviceContext) VSSetShader(s *_ID3D11VertexShader) {
- syscall.Syscall6(
- c.vtbl.VSSetShader,
- 4,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(s)),
- 0, // ppClassInstances
- 0, // NumClassInstances
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) VSSetConstantBuffers(b *_ID3D11Buffer) {
- syscall.Syscall6(
- c.vtbl.VSSetConstantBuffers,
- 4,
- uintptr(unsafe.Pointer(c)),
- 0, // StartSlot
- 1, // NumBuffers
- uintptr(unsafe.Pointer(&b)),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) PSSetConstantBuffers(b *_ID3D11Buffer) {
- syscall.Syscall6(
- c.vtbl.PSSetConstantBuffers,
- 4,
- uintptr(unsafe.Pointer(c)),
- 0, // StartSlot
- 1, // NumBuffers
- uintptr(unsafe.Pointer(&b)),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) PSSetShaderResources(startSlot uint32, s *_ID3D11ShaderResourceView) {
- syscall.Syscall6(
- c.vtbl.PSSetShaderResources,
- 4,
- uintptr(unsafe.Pointer(c)),
- uintptr(startSlot),
- 1, // NumViews
- uintptr(unsafe.Pointer(&s)),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) PSSetSamplers(startSlot uint32, s *_ID3D11SamplerState) {
- syscall.Syscall6(
- c.vtbl.PSSetSamplers,
- 4,
- uintptr(unsafe.Pointer(c)),
- uintptr(startSlot),
- 1, // NumSamplers
- uintptr(unsafe.Pointer(&s)),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) PSSetShader(s *_ID3D11PixelShader) {
- syscall.Syscall6(
- c.vtbl.PSSetShader,
- 4,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(s)),
- 0, // ppClassInstances
- 0, // NumClassInstances
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) UpdateSubresource(res *_ID3D11Resource, rowPitch, depthPitch uint32, data []byte) {
- syscall.Syscall9(
- c.vtbl.UpdateSubresource,
- 7,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(res)),
- 0, // DstSubresource
- 0, // pDstBox
- uintptr(unsafe.Pointer(&data[0])),
- uintptr(rowPitch),
- uintptr(depthPitch),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) RSSetState(state *_ID3D11RasterizerState) {
- syscall.Syscall(
- c.vtbl.RSSetState,
- 2,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(state)),
- 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) IASetInputLayout(layout *_ID3D11InputLayout) {
- syscall.Syscall(
- c.vtbl.IASetInputLayout,
- 2,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(layout)),
- 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) IASetIndexBuffer(buf *_ID3D11Buffer, format, offset uint32) {
- syscall.Syscall6(
- c.vtbl.IASetIndexBuffer,
- 4,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(buf)),
- uintptr(format),
- uintptr(offset),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) IASetVertexBuffers(buf *_ID3D11Buffer, stride, offset uint32) {
- syscall.Syscall6(
- c.vtbl.IASetVertexBuffers,
- 6,
- uintptr(unsafe.Pointer(c)),
- 0, // StartSlot
- 1, // NumBuffers,
- uintptr(unsafe.Pointer(&buf)),
- uintptr(unsafe.Pointer(&stride)),
- uintptr(unsafe.Pointer(&offset)),
- )
-}
-
-func (c *_ID3D11DeviceContext) IASetPrimitiveTopology(mode uint32) {
- syscall.Syscall(
- c.vtbl.IASetPrimitiveTopology,
- 2,
- uintptr(unsafe.Pointer(c)),
- uintptr(mode),
- 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) OMGetRenderTargets() *_ID3D11RenderTargetView {
- var target *_ID3D11RenderTargetView
- syscall.Syscall6(
- c.vtbl.OMGetRenderTargets,
- 4,
- uintptr(unsafe.Pointer(c)),
- 1, // NumViews
- uintptr(unsafe.Pointer(&target)),
- 0, // pDepthStencilView
- 0, 0,
- )
- return target
-}
-
-func (c *_ID3D11DeviceContext) OMSetRenderTargets(target *_ID3D11RenderTargetView, depthStencil *_ID3D11DepthStencilView) {
- syscall.Syscall6(
- c.vtbl.OMSetRenderTargets,
- 4,
- uintptr(unsafe.Pointer(c)),
- 1, // NumViews
- uintptr(unsafe.Pointer(&target)),
- uintptr(unsafe.Pointer(depthStencil)),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) Draw(count, start uint32) {
- syscall.Syscall(
- c.vtbl.Draw,
- 3,
- uintptr(unsafe.Pointer(c)),
- uintptr(count),
- uintptr(start),
- )
-}
-
-func (c *_ID3D11DeviceContext) DrawIndexed(count, start uint32, base int32) {
- syscall.Syscall6(
- c.vtbl.DrawIndexed,
- 4,
- uintptr(unsafe.Pointer(c)),
- uintptr(count),
- uintptr(start),
- uintptr(base),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) OMSetBlendState(state *_ID3D11BlendState, factor *f32color.RGBA, sampleMask uint32) {
- syscall.Syscall6(
- c.vtbl.OMSetBlendState,
- 4,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(state)),
- uintptr(unsafe.Pointer(factor)),
- uintptr(sampleMask),
- 0, 0,
- )
-}
-
-func (c *_ID3D11DeviceContext) OMSetDepthStencilState(state *_ID3D11DepthStencilState, stencilRef uint32) {
- syscall.Syscall(
- c.vtbl.OMSetDepthStencilState,
- 3,
- uintptr(unsafe.Pointer(c)),
- uintptr(unsafe.Pointer(state)),
- uintptr(stencilRef),
- )
-}
-
-func (d *_IDXGIObject) GetParent(guid *_GUID) (*_IDXGIObject, error) {
- var parent *_IDXGIObject
- r, _, _ := syscall.Syscall(
- d.vtbl.GetParent,
- 3,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(guid)),
- uintptr(unsafe.Pointer(&parent)),
- )
- if r != 0 {
- return nil, ErrorCode{Name: "IDXGIObjectGetParent", Code: uint32(r)}
- }
- return parent, nil
-}
-
-func (d *_IDXGIFactory) CreateSwapChain(device *_IUnknown, desc *_DXGI_SWAP_CHAIN_DESC) (*_IDXGISwapChain, error) {
- var swchain *_IDXGISwapChain
- r, _, _ := syscall.Syscall6(
- d.vtbl.CreateSwapChain,
- 4,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(device)),
- uintptr(unsafe.Pointer(desc)),
- uintptr(unsafe.Pointer(&swchain)),
- 0, 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "IDXGIFactory", Code: uint32(r)}
- }
- return swchain, nil
-}
-
-func (d *_IDXGIDevice) GetAdapter() (*_IDXGIAdapter, error) {
- var adapter *_IDXGIAdapter
- r, _, _ := syscall.Syscall(
- d.vtbl.GetAdapter,
- 2,
- uintptr(unsafe.Pointer(d)),
- uintptr(unsafe.Pointer(&adapter)),
- 0,
- )
- if r != 0 {
- return nil, ErrorCode{Name: "IDXGIDeviceGetAdapter", Code: uint32(r)}
- }
- return adapter, nil
-}
-
-func _IUnknownQueryInterface(obj unsafe.Pointer, queryInterfaceMethod uintptr, guid *_GUID) (*_IUnknown, error) {
- var ref *_IUnknown
- r, _, _ := syscall.Syscall(
- queryInterfaceMethod,
- 3,
- uintptr(obj),
- uintptr(unsafe.Pointer(guid)),
- uintptr(unsafe.Pointer(&ref)),
- )
- if r != 0 {
- return nil, ErrorCode{Name: "IUnknownQueryInterface", Code: uint32(r)}
- }
- return ref, nil
-}
-
-func _IUnknownRelease(obj unsafe.Pointer, releaseMethod uintptr) {
- syscall.Syscall(
- releaseMethod,
- 1,
- uintptr(obj),
- 0,
- 0,
- )
-}
-
-func (e ErrorCode) Error() string {
- return fmt.Sprintf("%s: %#x", e.Name, e.Code)
-}
diff --git a/vendor/gioui.org/app/internal/egl/egl.go b/vendor/gioui.org/app/internal/egl/egl.go
deleted file mode 100644
index f1d2595..0000000
--- a/vendor/gioui.org/app/internal/egl/egl.go
+++ /dev/null
@@ -1,279 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build linux windows freebsd openbsd
-
-package egl
-
-import (
- "errors"
- "fmt"
- "runtime"
- "strings"
-
- "gioui.org/app/internal/glimpl"
- "gioui.org/app/internal/srgb"
- "gioui.org/gpu/backend"
- "gioui.org/gpu/gl"
-)
-
-type Context struct {
- c *glimpl.Functions
- disp _EGLDisplay
- eglCtx *eglContext
- eglSurf _EGLSurface
- width, height int
- refreshFBO bool
- // For sRGB emulation.
- srgbFBO *srgb.FBO
-}
-
-type eglContext struct {
- config _EGLConfig
- ctx _EGLContext
- visualID int
- srgb bool
- surfaceless bool
-}
-
-var (
- nilEGLDisplay _EGLDisplay
- nilEGLSurface _EGLSurface
- nilEGLContext _EGLContext
- nilEGLConfig _EGLConfig
- EGL_DEFAULT_DISPLAY NativeDisplayType
-)
-
-const (
- _EGL_ALPHA_SIZE = 0x3021
- _EGL_BLUE_SIZE = 0x3022
- _EGL_CONFIG_CAVEAT = 0x3027
- _EGL_CONTEXT_CLIENT_VERSION = 0x3098
- _EGL_DEPTH_SIZE = 0x3025
- _EGL_GL_COLORSPACE_KHR = 0x309d
- _EGL_GL_COLORSPACE_SRGB_KHR = 0x3089
- _EGL_GREEN_SIZE = 0x3023
- _EGL_EXTENSIONS = 0x3055
- _EGL_NATIVE_VISUAL_ID = 0x302e
- _EGL_NONE = 0x3038
- _EGL_OPENGL_ES2_BIT = 0x4
- _EGL_RED_SIZE = 0x3024
- _EGL_RENDERABLE_TYPE = 0x3040
- _EGL_SURFACE_TYPE = 0x3033
- _EGL_WINDOW_BIT = 0x4
-)
-
-func (c *Context) Release() {
- if c.srgbFBO != nil {
- c.srgbFBO.Release()
- c.srgbFBO = nil
- }
- c.ReleaseSurface()
- if c.eglCtx != nil {
- eglDestroyContext(c.disp, c.eglCtx.ctx)
- eglTerminate(c.disp)
- eglReleaseThread()
- c.eglCtx = nil
- }
- c.disp = nilEGLDisplay
-}
-
-func (c *Context) Present() error {
- if c.srgbFBO != nil {
- c.srgbFBO.Blit()
- }
- if !eglSwapBuffers(c.disp, c.eglSurf) {
- return fmt.Errorf("eglSwapBuffers failed (%x)", eglGetError())
- }
- if c.srgbFBO != nil {
- c.srgbFBO.AfterPresent()
- }
- return nil
-}
-
-func NewContext(disp NativeDisplayType) (*Context, error) {
- if err := loadEGL(); err != nil {
- return nil, err
- }
- eglDisp := eglGetDisplay(disp)
- // eglGetDisplay can return EGL_NO_DISPLAY yet no error
- // (EGL_SUCCESS), in which case a default EGL display might be
- // available.
- if eglDisp == nilEGLDisplay {
- eglDisp = eglGetDisplay(EGL_DEFAULT_DISPLAY)
- }
- if eglDisp == nilEGLDisplay {
- return nil, fmt.Errorf("eglGetDisplay failed: 0x%x", eglGetError())
- }
- eglCtx, err := createContext(eglDisp)
- if err != nil {
- return nil, err
- }
- c := &Context{
- disp: eglDisp,
- eglCtx: eglCtx,
- c: new(glimpl.Functions),
- }
- return c, nil
-}
-
-func (c *Context) Functions() *glimpl.Functions {
- return c.c
-}
-
-func (c *Context) Backend() (backend.Device, error) {
- return gl.NewBackend(c.c)
-}
-
-func (c *Context) ReleaseSurface() {
- if c.eglSurf == nilEGLSurface {
- return
- }
- // Make sure any in-flight GL commands are complete.
- c.c.Finish()
- c.ReleaseCurrent()
- eglDestroySurface(c.disp, c.eglSurf)
- c.eglSurf = nilEGLSurface
-}
-
-func (c *Context) VisualID() int {
- return c.eglCtx.visualID
-}
-
-func (c *Context) CreateSurface(win NativeWindowType, width, height int) error {
- eglSurf, err := createSurface(c.disp, c.eglCtx, win)
- c.eglSurf = eglSurf
- c.width = width
- c.height = height
- c.refreshFBO = true
- return err
-}
-
-func (c *Context) ReleaseCurrent() {
- if c.disp != nilEGLDisplay {
- eglMakeCurrent(c.disp, nilEGLSurface, nilEGLSurface, nilEGLContext)
- }
-}
-
-func (c *Context) MakeCurrent() error {
- if c.eglSurf == nilEGLSurface && !c.eglCtx.surfaceless {
- return errors.New("no surface created yet EGL_KHR_surfaceless_context is not supported")
- }
- if !eglMakeCurrent(c.disp, c.eglSurf, c.eglSurf, c.eglCtx.ctx) {
- return fmt.Errorf("eglMakeCurrent error 0x%x", eglGetError())
- }
- if c.eglCtx.srgb || c.eglSurf == nilEGLSurface {
- return nil
- }
- if c.srgbFBO == nil {
- var err error
- c.srgbFBO, err = srgb.New(c.c)
- if err != nil {
- return err
- }
- }
- if c.refreshFBO {
- c.refreshFBO = false
- return c.srgbFBO.Refresh(c.width, c.height)
- }
- return nil
-}
-
-func (c *Context) EnableVSync(enable bool) {
- if enable {
- eglSwapInterval(c.disp, 1)
- } else {
- eglSwapInterval(c.disp, 0)
- }
-}
-
-func hasExtension(exts []string, ext string) bool {
- for _, e := range exts {
- if ext == e {
- return true
- }
- }
- return false
-}
-
-func createContext(disp _EGLDisplay) (*eglContext, error) {
- major, minor, ret := eglInitialize(disp)
- if !ret {
- return nil, fmt.Errorf("eglInitialize failed: 0x%x", eglGetError())
- }
- // sRGB framebuffer support on EGL 1.5 or if EGL_KHR_gl_colorspace is supported.
- exts := strings.Split(eglQueryString(disp, _EGL_EXTENSIONS), " ")
- srgb := major > 1 || minor >= 5 || hasExtension(exts, "EGL_KHR_gl_colorspace")
- attribs := []_EGLint{
- _EGL_RENDERABLE_TYPE, _EGL_OPENGL_ES2_BIT,
- _EGL_SURFACE_TYPE, _EGL_WINDOW_BIT,
- _EGL_BLUE_SIZE, 8,
- _EGL_GREEN_SIZE, 8,
- _EGL_RED_SIZE, 8,
- _EGL_CONFIG_CAVEAT, _EGL_NONE,
- }
- if srgb {
- if runtime.GOOS == "linux" || runtime.GOOS == "android" {
- // Some Mesa drivers crash if an sRGB framebuffer is requested without alpha.
- // https://bugs.freedesktop.org/show_bug.cgi?id=107782.
- //
- // Also, some Android devices (Samsung S9) needs alpha for sRGB to work.
- attribs = append(attribs, _EGL_ALPHA_SIZE, 1)
- }
- // Only request a depth buffer if we're going to render directly to the framebuffer.
- attribs = append(attribs, _EGL_DEPTH_SIZE, 16)
- }
- attribs = append(attribs, _EGL_NONE)
- eglCfg, ret := eglChooseConfig(disp, attribs)
- if !ret {
- return nil, fmt.Errorf("eglChooseConfig failed: 0x%x", eglGetError())
- }
- if eglCfg == nilEGLConfig {
- return nil, errors.New("eglChooseConfig returned 0 configs")
- }
- visID, ret := eglGetConfigAttrib(disp, eglCfg, _EGL_NATIVE_VISUAL_ID)
- if !ret {
- return nil, errors.New("newContext: eglGetConfigAttrib for _EGL_NATIVE_VISUAL_ID failed")
- }
- ctxAttribs := []_EGLint{
- _EGL_CONTEXT_CLIENT_VERSION, 3,
- _EGL_NONE,
- }
- eglCtx := eglCreateContext(disp, eglCfg, nilEGLContext, ctxAttribs)
- if eglCtx == nilEGLContext {
- // Fall back to OpenGL ES 2 and rely on extensions.
- ctxAttribs := []_EGLint{
- _EGL_CONTEXT_CLIENT_VERSION, 2,
- _EGL_NONE,
- }
- eglCtx = eglCreateContext(disp, eglCfg, nilEGLContext, ctxAttribs)
- if eglCtx == nilEGLContext {
- return nil, fmt.Errorf("eglCreateContext failed: 0x%x", eglGetError())
- }
- }
- return &eglContext{
- config: _EGLConfig(eglCfg),
- ctx: _EGLContext(eglCtx),
- visualID: int(visID),
- srgb: srgb,
- surfaceless: hasExtension(exts, "EGL_KHR_surfaceless_context"),
- }, nil
-}
-
-func createSurface(disp _EGLDisplay, eglCtx *eglContext, win NativeWindowType) (_EGLSurface, error) {
- var surfAttribs []_EGLint
- if eglCtx.srgb {
- surfAttribs = append(surfAttribs, _EGL_GL_COLORSPACE_KHR, _EGL_GL_COLORSPACE_SRGB_KHR)
- }
- surfAttribs = append(surfAttribs, _EGL_NONE)
- eglSurf := eglCreateWindowSurface(disp, eglCtx.config, win, surfAttribs)
- if eglSurf == nilEGLSurface && eglCtx.srgb {
- // Try again without sRGB
- eglCtx.srgb = false
- surfAttribs = []_EGLint{_EGL_NONE}
- eglSurf = eglCreateWindowSurface(disp, eglCtx.config, win, surfAttribs)
- }
- if eglSurf == nilEGLSurface {
- return nilEGLSurface, fmt.Errorf("newContext: eglCreateWindowSurface failed 0x%x (sRGB=%v)", eglGetError(), eglCtx.srgb)
- }
- return eglSurf, nil
-}
diff --git a/vendor/gioui.org/app/internal/egl/egl_unix.go b/vendor/gioui.org/app/internal/egl/egl_unix.go
deleted file mode 100644
index 0c6734f..0000000
--- a/vendor/gioui.org/app/internal/egl/egl_unix.go
+++ /dev/null
@@ -1,104 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build linux freebsd openbsd
-
-package egl
-
-/*
-#cgo linux,!android pkg-config: egl
-#cgo freebsd openbsd android LDFLAGS: -lEGL
-#cgo freebsd CFLAGS: -I/usr/local/include
-#cgo freebsd LDFLAGS: -L/usr/local/lib
-#cgo openbsd CFLAGS: -I/usr/X11R6/include
-#cgo openbsd LDFLAGS: -L/usr/X11R6/lib
-#cgo CFLAGS: -DMESA_EGL_NO_X11_HEADERS
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-*/
-import "C"
-
-type (
- _EGLint = C.EGLint
- _EGLDisplay = C.EGLDisplay
- _EGLConfig = C.EGLConfig
- _EGLContext = C.EGLContext
- _EGLSurface = C.EGLSurface
- NativeDisplayType = C.EGLNativeDisplayType
- NativeWindowType = C.EGLNativeWindowType
-)
-
-func loadEGL() error {
- return nil
-}
-
-func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
- var cfg C.EGLConfig
- var ncfg C.EGLint
- if C.eglChooseConfig(disp, &attribs[0], &cfg, 1, &ncfg) != C.EGL_TRUE {
- return nilEGLConfig, false
- }
- return _EGLConfig(cfg), true
-}
-
-func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
- ctx := C.eglCreateContext(disp, cfg, shareCtx, &attribs[0])
- return _EGLContext(ctx)
-}
-
-func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
- return C.eglDestroySurface(disp, surf) == C.EGL_TRUE
-}
-
-func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
- return C.eglDestroyContext(disp, ctx) == C.EGL_TRUE
-}
-
-func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
- var val _EGLint
- ret := C.eglGetConfigAttrib(disp, cfg, attr, &val)
- return val, ret == C.EGL_TRUE
-}
-
-func eglGetError() _EGLint {
- return C.eglGetError()
-}
-
-func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
- var maj, min _EGLint
- ret := C.eglInitialize(disp, &maj, &min)
- return maj, min, ret == C.EGL_TRUE
-}
-
-func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
- return C.eglMakeCurrent(disp, draw, read, ctx) == C.EGL_TRUE
-}
-
-func eglReleaseThread() bool {
- return C.eglReleaseThread() == C.EGL_TRUE
-}
-
-func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
- return C.eglSwapBuffers(disp, surf) == C.EGL_TRUE
-}
-
-func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
- return C.eglSwapInterval(disp, interval) == C.EGL_TRUE
-}
-
-func eglTerminate(disp _EGLDisplay) bool {
- return C.eglTerminate(disp) == C.EGL_TRUE
-}
-
-func eglQueryString(disp _EGLDisplay, name _EGLint) string {
- return C.GoString(C.eglQueryString(disp, name))
-}
-
-func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
- return C.eglGetDisplay(disp)
-}
-
-func eglCreateWindowSurface(disp _EGLDisplay, conf _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
- eglSurf := C.eglCreateWindowSurface(disp, conf, win, &attribs[0])
- return eglSurf
-}
diff --git a/vendor/gioui.org/app/internal/egl/egl_windows.go b/vendor/gioui.org/app/internal/egl/egl_windows.go
deleted file mode 100644
index 5d9a4fe..0000000
--- a/vendor/gioui.org/app/internal/egl/egl_windows.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package egl
-
-import (
- "fmt"
- "runtime"
- "sync"
- "unsafe"
-
- syscall "golang.org/x/sys/windows"
-
- "gioui.org/app/internal/glimpl"
- gunsafe "gioui.org/internal/unsafe"
-)
-
-type (
- _EGLint int32
- _EGLDisplay uintptr
- _EGLConfig uintptr
- _EGLContext uintptr
- _EGLSurface uintptr
- NativeDisplayType uintptr
- NativeWindowType uintptr
-)
-
-var (
- libEGL = syscall.NewLazyDLL("libEGL.dll")
- _eglChooseConfig = libEGL.NewProc("eglChooseConfig")
- _eglCreateContext = libEGL.NewProc("eglCreateContext")
- _eglCreateWindowSurface = libEGL.NewProc("eglCreateWindowSurface")
- _eglDestroyContext = libEGL.NewProc("eglDestroyContext")
- _eglDestroySurface = libEGL.NewProc("eglDestroySurface")
- _eglGetConfigAttrib = libEGL.NewProc("eglGetConfigAttrib")
- _eglGetDisplay = libEGL.NewProc("eglGetDisplay")
- _eglGetError = libEGL.NewProc("eglGetError")
- _eglInitialize = libEGL.NewProc("eglInitialize")
- _eglMakeCurrent = libEGL.NewProc("eglMakeCurrent")
- _eglReleaseThread = libEGL.NewProc("eglReleaseThread")
- _eglSwapInterval = libEGL.NewProc("eglSwapInterval")
- _eglSwapBuffers = libEGL.NewProc("eglSwapBuffers")
- _eglTerminate = libEGL.NewProc("eglTerminate")
- _eglQueryString = libEGL.NewProc("eglQueryString")
-)
-
-var loadOnce sync.Once
-
-func loadEGL() error {
- var err error
- loadOnce.Do(func() {
- err = loadDLLs()
- })
- return err
-}
-
-func loadDLLs() error {
- if err := loadDLL(libEGL, "libEGL.dll"); err != nil {
- return err
- }
- if err := loadDLL(glimpl.LibGLESv2, "libGLESv2.dll"); err != nil {
- return err
- }
- // d3dcompiler_47.dll is needed internally for shader compilation to function.
- return loadDLL(syscall.NewLazyDLL("d3dcompiler_47.dll"), "d3dcompiler_47.dll")
-}
-
-func loadDLL(dll *syscall.LazyDLL, name string) error {
- err := dll.Load()
- if err != nil {
- return fmt.Errorf("egl: failed to load %s: %v", name, err)
- }
- return nil
-}
-
-func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
- var cfg _EGLConfig
- var ncfg _EGLint
- a := &attribs[0]
- r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(a)), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg)))
- issue34474KeepAlive(a)
- return cfg, r != 0
-}
-
-func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
- a := &attribs[0]
- c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(a)))
- issue34474KeepAlive(a)
- return _EGLContext(c)
-}
-
-func eglCreateWindowSurface(disp _EGLDisplay, cfg _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
- a := &attribs[0]
- s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(a)))
- issue34474KeepAlive(a)
- return _EGLSurface(s)
-}
-
-func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
- r, _, _ := _eglDestroySurface.Call(uintptr(disp), uintptr(surf))
- return r != 0
-}
-
-func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
- r, _, _ := _eglDestroyContext.Call(uintptr(disp), uintptr(ctx))
- return r != 0
-}
-
-func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
- var val uintptr
- r, _, _ := _eglGetConfigAttrib.Call(uintptr(disp), uintptr(cfg), uintptr(attr), uintptr(unsafe.Pointer(&val)))
- return _EGLint(val), r != 0
-}
-
-func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
- d, _, _ := _eglGetDisplay.Call(uintptr(disp))
- return _EGLDisplay(d)
-}
-
-func eglGetError() _EGLint {
- e, _, _ := _eglGetError.Call()
- return _EGLint(e)
-}
-
-func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
- var maj, min uintptr
- r, _, _ := _eglInitialize.Call(uintptr(disp), uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)))
- return _EGLint(maj), _EGLint(min), r != 0
-}
-
-func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
- r, _, _ := _eglMakeCurrent.Call(uintptr(disp), uintptr(draw), uintptr(read), uintptr(ctx))
- return r != 0
-}
-
-func eglReleaseThread() bool {
- r, _, _ := _eglReleaseThread.Call()
- return r != 0
-}
-
-func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
- r, _, _ := _eglSwapInterval.Call(uintptr(disp), uintptr(interval))
- return r != 0
-}
-
-func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
- r, _, _ := _eglSwapBuffers.Call(uintptr(disp), uintptr(surf))
- return r != 0
-}
-
-func eglTerminate(disp _EGLDisplay) bool {
- r, _, _ := _eglTerminate.Call(uintptr(disp))
- return r != 0
-}
-
-func eglQueryString(disp _EGLDisplay, name _EGLint) string {
- r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name))
- return gunsafe.GoString(gunsafe.SliceOf(r))
-}
-
-// issue34474KeepAlive calls runtime.KeepAlive as a
-// workaround for golang.org/issue/34474.
-func issue34474KeepAlive(v interface{}) {
- runtime.KeepAlive(v)
-}
diff --git a/vendor/gioui.org/app/internal/glimpl/gl.go b/vendor/gioui.org/app/internal/glimpl/gl.go
deleted file mode 100644
index 5b23e4e..0000000
--- a/vendor/gioui.org/app/internal/glimpl/gl.go
+++ /dev/null
@@ -1,541 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build darwin linux freebsd openbsd
-
-package glimpl
-
-import (
- "runtime"
- "strings"
- "unsafe"
-
- "gioui.org/gpu/gl"
-)
-
-/*
-#cgo CFLAGS: -Werror
-#cgo linux,!android pkg-config: glesv2
-#cgo linux freebsd LDFLAGS: -ldl
-#cgo freebsd openbsd android LDFLAGS: -lGLESv2
-#cgo freebsd CFLAGS: -I/usr/local/include
-#cgo freebsd LDFLAGS: -L/usr/local/lib
-#cgo openbsd CFLAGS: -I/usr/X11R6/include
-#cgo openbsd LDFLAGS: -L/usr/X11R6/lib
-#cgo darwin,!ios CFLAGS: -DGL_SILENCE_DEPRECATION
-#cgo darwin,!ios LDFLAGS: -framework OpenGL
-#cgo darwin,ios CFLAGS: -DGLES_SILENCE_DEPRECATION
-#cgo darwin,ios LDFLAGS: -framework OpenGLES
-
-#include <stdlib.h>
-
-#ifdef __APPLE__
- #include "TargetConditionals.h"
- #if TARGET_OS_IPHONE
- #include <OpenGLES/ES3/gl.h>
- #else
- #include <OpenGL/gl3.h>
- #endif
-#else
-#define __USE_GNU
-#include <dlfcn.h>
-#include <GLES2/gl2.h>
-#include <GLES3/gl3.h>
-#endif
-
-static void (*_glBindBufferBase)(GLenum target, GLuint index, GLuint buffer);
-static GLuint (*_glGetUniformBlockIndex)(GLuint program, const GLchar *uniformBlockName);
-static void (*_glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
-static void (*_glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum *attachments);
-
-static void (*_glBeginQuery)(GLenum target, GLuint id);
-static void (*_glDeleteQueries)(GLsizei n, const GLuint *ids);
-static void (*_glEndQuery)(GLenum target);
-static void (*_glGenQueries)(GLsizei n, GLuint *ids);
-static void (*_glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params);
-static const GLubyte* (*_glGetStringi)(GLenum name, GLuint index);
-
-// The pointer-free version of glVertexAttribPointer, to avoid the Cgo pointer checks.
-__attribute__ ((visibility ("hidden"))) void gio_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, uintptr_t offset) {
- glVertexAttribPointer(index, size, type, normalized, stride, (const GLvoid *)offset);
-}
-
-// The pointer-free version of glDrawElements, to avoid the Cgo pointer checks.
-__attribute__ ((visibility ("hidden"))) void gio_glDrawElements(GLenum mode, GLsizei count, GLenum type, const uintptr_t offset) {
- glDrawElements(mode, count, type, (const GLvoid *)offset);
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glBindBufferBase(GLenum target, GLuint index, GLuint buffer) {
- _glBindBufferBase(target, index, buffer);
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) {
- _glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
-}
-
-__attribute__ ((visibility ("hidden"))) GLuint gio_glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName) {
- return _glGetUniformBlockIndex(program, uniformBlockName);
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glInvalidateFramebuffer(GLenum target, GLenum attachment) {
- // gl.Framebuffer invalidation is just a hint and can safely be ignored.
- if (_glInvalidateFramebuffer != NULL) {
- _glInvalidateFramebuffer(target, 1, &attachment);
- }
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glBeginQuery(GLenum target, GLenum attachment) {
- _glBeginQuery(target, attachment);
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glDeleteQueries(GLsizei n, const GLuint *ids) {
- _glDeleteQueries(n, ids);
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glEndQuery(GLenum target) {
- _glEndQuery(target);
-}
-
-__attribute__ ((visibility ("hidden"))) const GLubyte* gio_glGetStringi(GLenum name, GLuint index) {
- if (_glGetStringi == NULL) {
- return NULL;
- }
- return _glGetStringi(name, index);
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glGenQueries(GLsizei n, GLuint *ids) {
- _glGenQueries(n, ids);
-}
-
-__attribute__ ((visibility ("hidden"))) void gio_glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) {
- _glGetQueryObjectuiv(id, pname, params);
-}
-
-__attribute__((constructor)) static void gio_loadGLFunctions() {
-#ifdef __APPLE__
- #if TARGET_OS_IPHONE
- _glInvalidateFramebuffer = glInvalidateFramebuffer;
- _glBeginQuery = glBeginQuery;
- _glDeleteQueries = glDeleteQueries;
- _glEndQuery = glEndQuery;
- _glGenQueries = glGenQueries;
- _glGetQueryObjectuiv = glGetQueryObjectuiv;
- #endif
- _glBindBufferBase = glBindBufferBase;
- _glGetUniformBlockIndex = glGetUniformBlockIndex;
- _glUniformBlockBinding = glUniformBlockBinding;
- _glGetStringi = glGetStringi;
-#else
- // Load libGLESv3 if available.
- dlopen("libGLESv3.so", RTLD_NOW | RTLD_GLOBAL);
- _glBindBufferBase = dlsym(RTLD_DEFAULT, "glBindBufferBase");
- _glGetUniformBlockIndex = dlsym(RTLD_DEFAULT, "glGetUniformBlockIndex");
- _glUniformBlockBinding = dlsym(RTLD_DEFAULT, "glUniformBlockBinding");
- _glInvalidateFramebuffer = dlsym(RTLD_DEFAULT, "glInvalidateFramebuffer");
- _glGetStringi = dlsym(RTLD_DEFAULT, "glGetStringi");
- // Fall back to EXT_invalidate_framebuffer if available.
- if (_glInvalidateFramebuffer == NULL) {
- _glInvalidateFramebuffer = dlsym(RTLD_DEFAULT, "glDiscardFramebufferEXT");
- }
-
- _glBeginQuery = dlsym(RTLD_DEFAULT, "glBeginQuery");
- if (_glBeginQuery == NULL)
- _glBeginQuery = dlsym(RTLD_DEFAULT, "glBeginQueryEXT");
- _glDeleteQueries = dlsym(RTLD_DEFAULT, "glDeleteQueries");
- if (_glDeleteQueries == NULL)
- _glDeleteQueries = dlsym(RTLD_DEFAULT, "glDeleteQueriesEXT");
- _glEndQuery = dlsym(RTLD_DEFAULT, "glEndQuery");
- if (_glEndQuery == NULL)
- _glEndQuery = dlsym(RTLD_DEFAULT, "glEndQueryEXT");
- _glGenQueries = dlsym(RTLD_DEFAULT, "glGenQueries");
- if (_glGenQueries == NULL)
- _glGenQueries = dlsym(RTLD_DEFAULT, "glGenQueriesEXT");
- _glGetQueryObjectuiv = dlsym(RTLD_DEFAULT, "glGetQueryObjectuiv");
- if (_glGetQueryObjectuiv == NULL)
- _glGetQueryObjectuiv = dlsym(RTLD_DEFAULT, "glGetQueryObjectuivEXT");
-#endif
-}
-*/
-import "C"
-
-type Functions struct {
- // gl.Query caches.
- uints [100]C.GLuint
- ints [100]C.GLint
-}
-
-func (f *Functions) ActiveTexture(texture gl.Enum) {
- C.glActiveTexture(C.GLenum(texture))
-}
-
-func (f *Functions) AttachShader(p gl.Program, s gl.Shader) {
- C.glAttachShader(C.GLuint(p.V), C.GLuint(s.V))
-}
-
-func (f *Functions) BeginQuery(target gl.Enum, query gl.Query) {
- C.gio_glBeginQuery(C.GLenum(target), C.GLenum(query.V))
-}
-
-func (f *Functions) BindAttribLocation(p gl.Program, a gl.Attrib, name string) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
- C.glBindAttribLocation(C.GLuint(p.V), C.GLuint(a), cname)
-}
-
-func (f *Functions) BindBufferBase(target gl.Enum, index int, b gl.Buffer) {
- C.gio_glBindBufferBase(C.GLenum(target), C.GLuint(index), C.GLuint(b.V))
-}
-
-func (f *Functions) BindBuffer(target gl.Enum, b gl.Buffer) {
- C.glBindBuffer(C.GLenum(target), C.GLuint(b.V))
-}
-
-func (f *Functions) BindFramebuffer(target gl.Enum, fb gl.Framebuffer) {
- C.glBindFramebuffer(C.GLenum(target), C.GLuint(fb.V))
-}
-
-func (f *Functions) BindRenderbuffer(target gl.Enum, fb gl.Renderbuffer) {
- C.glBindRenderbuffer(C.GLenum(target), C.GLuint(fb.V))
-}
-
-func (f *Functions) BindTexture(target gl.Enum, t gl.Texture) {
- C.glBindTexture(C.GLenum(target), C.GLuint(t.V))
-}
-
-func (f *Functions) BlendEquation(mode gl.Enum) {
- C.glBlendEquation(C.GLenum(mode))
-}
-
-func (f *Functions) BlendFunc(sfactor, dfactor gl.Enum) {
- C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
-}
-
-func (f *Functions) BufferData(target gl.Enum, src []byte, usage gl.Enum) {
- var p unsafe.Pointer
- if len(src) > 0 {
- p = unsafe.Pointer(&src[0])
- }
- C.glBufferData(C.GLenum(target), C.GLsizeiptr(len(src)), p, C.GLenum(usage))
-}
-
-func (f *Functions) CheckFramebufferStatus(target gl.Enum) gl.Enum {
- return gl.Enum(C.glCheckFramebufferStatus(C.GLenum(target)))
-}
-
-func (f *Functions) Clear(mask gl.Enum) {
- C.glClear(C.GLbitfield(mask))
-}
-
-func (f *Functions) ClearColor(red float32, green float32, blue float32, alpha float32) {
- C.glClearColor(C.GLfloat(red), C.GLfloat(green), C.GLfloat(blue), C.GLfloat(alpha))
-}
-
-func (f *Functions) ClearDepthf(d float32) {
- C.glClearDepthf(C.GLfloat(d))
-}
-
-func (f *Functions) CompileShader(s gl.Shader) {
- C.glCompileShader(C.GLuint(s.V))
-}
-
-func (f *Functions) CreateBuffer() gl.Buffer {
- C.glGenBuffers(1, &f.uints[0])
- return gl.Buffer{uint(f.uints[0])}
-}
-
-func (f *Functions) CreateFramebuffer() gl.Framebuffer {
- C.glGenFramebuffers(1, &f.uints[0])
- return gl.Framebuffer{uint(f.uints[0])}
-}
-
-func (f *Functions) CreateProgram() gl.Program {
- return gl.Program{uint(C.glCreateProgram())}
-}
-
-func (f *Functions) CreateQuery() gl.Query {
- C.gio_glGenQueries(1, &f.uints[0])
- return gl.Query{uint(f.uints[0])}
-}
-
-func (f *Functions) CreateRenderbuffer() gl.Renderbuffer {
- C.glGenRenderbuffers(1, &f.uints[0])
- return gl.Renderbuffer{uint(f.uints[0])}
-}
-
-func (f *Functions) CreateShader(ty gl.Enum) gl.Shader {
- return gl.Shader{uint(C.glCreateShader(C.GLenum(ty)))}
-}
-
-func (f *Functions) CreateTexture() gl.Texture {
- C.glGenTextures(1, &f.uints[0])
- return gl.Texture{uint(f.uints[0])}
-}
-
-func (f *Functions) DeleteBuffer(v gl.Buffer) {
- f.uints[0] = C.GLuint(v.V)
- C.glDeleteBuffers(1, &f.uints[0])
-}
-
-func (f *Functions) DeleteFramebuffer(v gl.Framebuffer) {
- f.uints[0] = C.GLuint(v.V)
- C.glDeleteFramebuffers(1, &f.uints[0])
-}
-
-func (f *Functions) DeleteProgram(p gl.Program) {
- C.glDeleteProgram(C.GLuint(p.V))
-}
-
-func (f *Functions) DeleteQuery(query gl.Query) {
- f.uints[0] = C.GLuint(query.V)
- C.gio_glDeleteQueries(1, &f.uints[0])
-}
-
-func (f *Functions) DeleteRenderbuffer(v gl.Renderbuffer) {
- f.uints[0] = C.GLuint(v.V)
- C.glDeleteRenderbuffers(1, &f.uints[0])
-}
-
-func (f *Functions) DeleteShader(s gl.Shader) {
- C.glDeleteShader(C.GLuint(s.V))
-}
-
-func (f *Functions) DeleteTexture(v gl.Texture) {
- f.uints[0] = C.GLuint(v.V)
- C.glDeleteTextures(1, &f.uints[0])
-}
-
-func (f *Functions) DepthFunc(v gl.Enum) {
- C.glDepthFunc(C.GLenum(v))
-}
-
-func (f *Functions) DepthMask(mask bool) {
- m := C.GLboolean(C.GL_FALSE)
- if mask {
- m = C.GLboolean(C.GL_TRUE)
- }
- C.glDepthMask(m)
-}
-
-func (f *Functions) DisableVertexAttribArray(a gl.Attrib) {
- C.glDisableVertexAttribArray(C.GLuint(a))
-}
-
-func (f *Functions) Disable(cap gl.Enum) {
- C.glDisable(C.GLenum(cap))
-}
-
-func (f *Functions) DrawArrays(mode gl.Enum, first int, count int) {
- C.glDrawArrays(C.GLenum(mode), C.GLint(first), C.GLsizei(count))
-}
-
-func (f *Functions) DrawElements(mode gl.Enum, count int, ty gl.Enum, offset int) {
- C.gio_glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(ty), C.uintptr_t(offset))
-}
-
-func (f *Functions) Enable(cap gl.Enum) {
- C.glEnable(C.GLenum(cap))
-}
-
-func (f *Functions) EndQuery(target gl.Enum) {
- C.gio_glEndQuery(C.GLenum(target))
-}
-
-func (f *Functions) EnableVertexAttribArray(a gl.Attrib) {
- C.glEnableVertexAttribArray(C.GLuint(a))
-}
-
-func (f *Functions) Finish() {
- C.glFinish()
-}
-
-func (f *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget gl.Enum, renderbuffer gl.Renderbuffer) {
- C.glFramebufferRenderbuffer(C.GLenum(target), C.GLenum(attachment), C.GLenum(renderbuffertarget), C.GLuint(renderbuffer.V))
-}
-
-func (f *Functions) FramebufferTexture2D(target, attachment, texTarget gl.Enum, t gl.Texture, level int) {
- C.glFramebufferTexture2D(C.GLenum(target), C.GLenum(attachment), C.GLenum(texTarget), C.GLuint(t.V), C.GLint(level))
-}
-
-func (c *Functions) GetBinding(pname gl.Enum) gl.Object {
- return gl.Object{uint(c.GetInteger(pname))}
-}
-
-func (f *Functions) GetError() gl.Enum {
- return gl.Enum(C.glGetError())
-}
-
-func (f *Functions) GetRenderbufferParameteri(target, pname gl.Enum) int {
- C.glGetRenderbufferParameteriv(C.GLenum(target), C.GLenum(pname), &f.ints[0])
- return int(f.ints[0])
-}
-
-func (f *Functions) GetFramebufferAttachmentParameteri(target, attachment, pname gl.Enum) int {
- C.glGetFramebufferAttachmentParameteriv(C.GLenum(target), C.GLenum(attachment), C.GLenum(pname), &f.ints[0])
- return int(f.ints[0])
-}
-
-func (f *Functions) GetInteger(pname gl.Enum) int {
- C.glGetIntegerv(C.GLenum(pname), &f.ints[0])
- return int(f.ints[0])
-}
-
-func (f *Functions) GetProgrami(p gl.Program, pname gl.Enum) int {
- C.glGetProgramiv(C.GLuint(p.V), C.GLenum(pname), &f.ints[0])
- return int(f.ints[0])
-}
-
-func (f *Functions) GetProgramInfoLog(p gl.Program) string {
- n := f.GetProgrami(p, gl.INFO_LOG_LENGTH)
- buf := make([]byte, n)
- C.glGetProgramInfoLog(C.GLuint(p.V), C.GLsizei(len(buf)), nil, (*C.GLchar)(unsafe.Pointer(&buf[0])))
- return string(buf)
-}
-
-func (f *Functions) GetQueryObjectuiv(query gl.Query, pname gl.Enum) uint {
- C.gio_glGetQueryObjectuiv(C.GLuint(query.V), C.GLenum(pname), &f.uints[0])
- return uint(f.uints[0])
-}
-
-func (f *Functions) GetShaderi(s gl.Shader, pname gl.Enum) int {
- C.glGetShaderiv(C.GLuint(s.V), C.GLenum(pname), &f.ints[0])
- return int(f.ints[0])
-}
-
-func (f *Functions) GetShaderInfoLog(s gl.Shader) string {
- n := f.GetShaderi(s, gl.INFO_LOG_LENGTH)
- buf := make([]byte, n)
- C.glGetShaderInfoLog(C.GLuint(s.V), C.GLsizei(len(buf)), nil, (*C.GLchar)(unsafe.Pointer(&buf[0])))
- return string(buf)
-}
-
-func (f *Functions) GetStringi(pname gl.Enum, index int) string {
- str := C.gio_glGetStringi(C.GLenum(pname), C.GLuint(index))
- if str == nil {
- return ""
- }
- return C.GoString((*C.char)(unsafe.Pointer(str)))
-}
-
-func (f *Functions) GetString(pname gl.Enum) string {
- switch {
- case runtime.GOOS == "darwin" && pname == gl.EXTENSIONS:
- // macOS OpenGL 3 core profile doesn't support glGetString(GL_EXTENSIONS).
- // Use glGetStringi(GL_EXTENSIONS, <index>).
- var exts []string
- nexts := f.GetInteger(gl.NUM_EXTENSIONS)
- for i := 0; i < nexts; i++ {
- ext := f.GetStringi(gl.EXTENSIONS, i)
- exts = append(exts, ext)
- }
- return strings.Join(exts, " ")
- default:
- str := C.glGetString(C.GLenum(pname))
- return C.GoString((*C.char)(unsafe.Pointer(str)))
- }
-}
-
-func (f *Functions) GetUniformBlockIndex(p gl.Program, name string) uint {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
- return uint(C.gio_glGetUniformBlockIndex(C.GLuint(p.V), cname))
-}
-
-func (f *Functions) GetUniformLocation(p gl.Program, name string) gl.Uniform {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
- return gl.Uniform{int(C.glGetUniformLocation(C.GLuint(p.V), cname))}
-}
-
-func (f *Functions) InvalidateFramebuffer(target, attachment gl.Enum) {
- C.gio_glInvalidateFramebuffer(C.GLenum(target), C.GLenum(attachment))
-}
-
-func (f *Functions) LinkProgram(p gl.Program) {
- C.glLinkProgram(C.GLuint(p.V))
-}
-
-func (f *Functions) PixelStorei(pname gl.Enum, param int32) {
- C.glPixelStorei(C.GLenum(pname), C.GLint(param))
-}
-
-func (f *Functions) Scissor(x, y, width, height int32) {
- C.glScissor(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
-}
-
-func (f *Functions) ReadPixels(x, y, width, height int, format, ty gl.Enum, data []byte) {
- var p unsafe.Pointer
- if len(data) > 0 {
- p = unsafe.Pointer(&data[0])
- }
- C.glReadPixels(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(ty), p)
-}
-
-func (f *Functions) RenderbufferStorage(target, internalformat gl.Enum, width, height int) {
- C.glRenderbufferStorage(C.GLenum(target), C.GLenum(internalformat), C.GLsizei(width), C.GLsizei(height))
-}
-
-func (f *Functions) ShaderSource(s gl.Shader, src string) {
- csrc := C.CString(src)
- defer C.free(unsafe.Pointer(csrc))
- strlen := C.GLint(len(src))
- C.glShaderSource(C.GLuint(s.V), 1, &csrc, &strlen)
-}
-
-func (f *Functions) TexImage2D(target gl.Enum, level int, internalFormat int, width int, height int, format gl.Enum, ty gl.Enum, data []byte) {
- var p unsafe.Pointer
- if len(data) > 0 {
- p = unsafe.Pointer(&data[0])
- }
- C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GLint(internalFormat), C.GLsizei(width), C.GLsizei(height), 0, C.GLenum(format), C.GLenum(ty), p)
-}
-
-func (f *Functions) TexSubImage2D(target gl.Enum, level int, x int, y int, width int, height int, format gl.Enum, ty gl.Enum, data []byte) {
- var p unsafe.Pointer
- if len(data) > 0 {
- p = unsafe.Pointer(&data[0])
- }
- C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(ty), p)
-}
-
-func (f *Functions) TexParameteri(target, pname gl.Enum, param int) {
- C.glTexParameteri(C.GLenum(target), C.GLenum(pname), C.GLint(param))
-}
-
-func (f *Functions) UniformBlockBinding(p gl.Program, uniformBlockIndex uint, uniformBlockBinding uint) {
- C.gio_glUniformBlockBinding(C.GLuint(p.V), C.GLuint(uniformBlockIndex), C.GLuint(uniformBlockBinding))
-}
-
-func (f *Functions) Uniform1f(dst gl.Uniform, v float32) {
- C.glUniform1f(C.GLint(dst.V), C.GLfloat(v))
-}
-
-func (f *Functions) Uniform1i(dst gl.Uniform, v int) {
- C.glUniform1i(C.GLint(dst.V), C.GLint(v))
-}
-
-func (f *Functions) Uniform2f(dst gl.Uniform, v0 float32, v1 float32) {
- C.glUniform2f(C.GLint(dst.V), C.GLfloat(v0), C.GLfloat(v1))
-}
-
-func (f *Functions) Uniform3f(dst gl.Uniform, v0 float32, v1 float32, v2 float32) {
- C.glUniform3f(C.GLint(dst.V), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2))
-}
-
-func (f *Functions) Uniform4f(dst gl.Uniform, v0 float32, v1 float32, v2 float32, v3 float32) {
- C.glUniform4f(C.GLint(dst.V), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2), C.GLfloat(v3))
-}
-
-func (f *Functions) UseProgram(p gl.Program) {
- C.glUseProgram(C.GLuint(p.V))
-}
-
-func (f *Functions) VertexAttribPointer(dst gl.Attrib, size int, ty gl.Enum, normalized bool, stride int, offset int) {
- var n C.GLboolean = C.GL_FALSE
- if normalized {
- n = C.GL_TRUE
- }
- C.gio_glVertexAttribPointer(C.GLuint(dst), C.GLint(size), C.GLenum(ty), n, C.GLsizei(stride), C.uintptr_t(offset))
-}
-
-func (f *Functions) Viewport(x int, y int, width int, height int) {
- C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
-}
diff --git a/vendor/gioui.org/app/internal/glimpl/gl_js.go b/vendor/gioui.org/app/internal/glimpl/gl_js.go
deleted file mode 100644
index e4291d0..0000000
--- a/vendor/gioui.org/app/internal/glimpl/gl_js.go
+++ /dev/null
@@ -1,339 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package glimpl
-
-import (
- "errors"
- "strings"
- "syscall/js"
-
- "gioui.org/gpu/gl"
-)
-
-type Functions struct {
- Ctx js.Value
- EXT_disjoint_timer_query js.Value
- EXT_disjoint_timer_query_webgl2 js.Value
-
- // Cached JS arrays.
- byteBuf js.Value
- int32Buf js.Value
-}
-
-func (f *Functions) Init(version int) error {
- if version < 2 {
- f.EXT_disjoint_timer_query = f.getExtension("EXT_disjoint_timer_query")
- if f.getExtension("OES_texture_half_float").IsNull() && f.getExtension("OES_texture_float").IsNull() {
- return errors.New("gl: no support for neither OES_texture_half_float nor OES_texture_float")
- }
- if f.getExtension("EXT_sRGB").IsNull() {
- return errors.New("gl: EXT_sRGB not supported")
- }
- } else {
- // WebGL2 extensions.
- f.EXT_disjoint_timer_query_webgl2 = f.getExtension("EXT_disjoint_timer_query_webgl2")
- if f.getExtension("EXT_color_buffer_half_float").IsNull() && f.getExtension("EXT_color_buffer_float").IsNull() {
- return errors.New("gl: no support for neither EXT_color_buffer_half_float nor EXT_color_buffer_float")
- }
- }
- return nil
-}
-
-func (f *Functions) getExtension(name string) js.Value {
- return f.Ctx.Call("getExtension", name)
-}
-
-func (f *Functions) ActiveTexture(t gl.Enum) {
- f.Ctx.Call("activeTexture", int(t))
-}
-func (f *Functions) AttachShader(p gl.Program, s gl.Shader) {
- f.Ctx.Call("attachShader", js.Value(p), js.Value(s))
-}
-func (f *Functions) BeginQuery(target gl.Enum, query gl.Query) {
- if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
- f.Ctx.Call("beginQuery", int(target), js.Value(query))
- } else {
- f.EXT_disjoint_timer_query.Call("beginQueryEXT", int(target), js.Value(query))
- }
-}
-func (f *Functions) BindAttribLocation(p gl.Program, a gl.Attrib, name string) {
- f.Ctx.Call("bindAttribLocation", js.Value(p), int(a), name)
-}
-func (f *Functions) BindBuffer(target gl.Enum, b gl.Buffer) {
- f.Ctx.Call("bindBuffer", int(target), js.Value(b))
-}
-func (f *Functions) BindBufferBase(target gl.Enum, index int, b gl.Buffer) {
- f.Ctx.Call("bindBufferBase", int(target), index, js.Value(b))
-}
-func (f *Functions) BindFramebuffer(target gl.Enum, fb gl.Framebuffer) {
- f.Ctx.Call("bindFramebuffer", int(target), js.Value(fb))
-}
-func (f *Functions) BindRenderbuffer(target gl.Enum, rb gl.Renderbuffer) {
- f.Ctx.Call("bindRenderbuffer", int(target), js.Value(rb))
-}
-func (f *Functions) BindTexture(target gl.Enum, t gl.Texture) {
- f.Ctx.Call("bindTexture", int(target), js.Value(t))
-}
-func (f *Functions) BlendEquation(mode gl.Enum) {
- f.Ctx.Call("blendEquation", int(mode))
-}
-func (f *Functions) BlendFunc(sfactor, dfactor gl.Enum) {
- f.Ctx.Call("blendFunc", int(sfactor), int(dfactor))
-}
-func (f *Functions) BufferData(target gl.Enum, src []byte, usage gl.Enum) {
- f.Ctx.Call("bufferData", int(target), f.byteArrayOf(src), int(usage))
-}
-func (f *Functions) CheckFramebufferStatus(target gl.Enum) gl.Enum {
- return gl.Enum(f.Ctx.Call("checkFramebufferStatus", int(target)).Int())
-}
-func (f *Functions) Clear(mask gl.Enum) {
- f.Ctx.Call("clear", int(mask))
-}
-func (f *Functions) ClearColor(red, green, blue, alpha float32) {
- f.Ctx.Call("clearColor", red, green, blue, alpha)
-}
-func (f *Functions) ClearDepthf(d float32) {
- f.Ctx.Call("clearDepth", d)
-}
-func (f *Functions) CompileShader(s gl.Shader) {
- f.Ctx.Call("compileShader", js.Value(s))
-}
-func (f *Functions) CreateBuffer() gl.Buffer {
- return gl.Buffer(f.Ctx.Call("createBuffer"))
-}
-func (f *Functions) CreateFramebuffer() gl.Framebuffer {
- return gl.Framebuffer(f.Ctx.Call("createFramebuffer"))
-}
-func (f *Functions) CreateProgram() gl.Program {
- return gl.Program(f.Ctx.Call("createProgram"))
-}
-func (f *Functions) CreateQuery() gl.Query {
- return gl.Query(f.Ctx.Call("createQuery"))
-}
-func (f *Functions) CreateRenderbuffer() gl.Renderbuffer {
- return gl.Renderbuffer(f.Ctx.Call("createRenderbuffer"))
-}
-func (f *Functions) CreateShader(ty gl.Enum) gl.Shader {
- return gl.Shader(f.Ctx.Call("createShader", int(ty)))
-}
-func (f *Functions) CreateTexture() gl.Texture {
- return gl.Texture(f.Ctx.Call("createTexture"))
-}
-func (f *Functions) DeleteBuffer(v gl.Buffer) {
- f.Ctx.Call("deleteBuffer", js.Value(v))
-}
-func (f *Functions) DeleteFramebuffer(v gl.Framebuffer) {
- f.Ctx.Call("deleteFramebuffer", js.Value(v))
-}
-func (f *Functions) DeleteProgram(p gl.Program) {
- f.Ctx.Call("deleteProgram", js.Value(p))
-}
-func (f *Functions) DeleteQuery(query gl.Query) {
- if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
- f.Ctx.Call("deleteQuery", js.Value(query))
- } else {
- f.EXT_disjoint_timer_query.Call("deleteQueryEXT", js.Value(query))
- }
-}
-func (f *Functions) DeleteShader(s gl.Shader) {
- f.Ctx.Call("deleteShader", js.Value(s))
-}
-func (f *Functions) DeleteRenderbuffer(v gl.Renderbuffer) {
- f.Ctx.Call("deleteRenderbuffer", js.Value(v))
-}
-func (f *Functions) DeleteTexture(v gl.Texture) {
- f.Ctx.Call("deleteTexture", js.Value(v))
-}
-func (f *Functions) DepthFunc(fn gl.Enum) {
- f.Ctx.Call("depthFunc", int(fn))
-}
-func (f *Functions) DepthMask(mask bool) {
- f.Ctx.Call("depthMask", mask)
-}
-func (f *Functions) DisableVertexAttribArray(a gl.Attrib) {
- f.Ctx.Call("disableVertexAttribArray", int(a))
-}
-func (f *Functions) Disable(cap gl.Enum) {
- f.Ctx.Call("disable", int(cap))
-}
-func (f *Functions) DrawArrays(mode gl.Enum, first, count int) {
- f.Ctx.Call("drawArrays", int(mode), first, count)
-}
-func (f *Functions) DrawElements(mode gl.Enum, count int, ty gl.Enum, offset int) {
- f.Ctx.Call("drawElements", int(mode), count, int(ty), offset)
-}
-func (f *Functions) Enable(cap gl.Enum) {
- f.Ctx.Call("enable", int(cap))
-}
-func (f *Functions) EnableVertexAttribArray(a gl.Attrib) {
- f.Ctx.Call("enableVertexAttribArray", int(a))
-}
-func (f *Functions) EndQuery(target gl.Enum) {
- if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
- f.Ctx.Call("endQuery", int(target))
- } else {
- f.EXT_disjoint_timer_query.Call("endQueryEXT", int(target))
- }
-}
-func (f *Functions) Finish() {
- f.Ctx.Call("finish")
-}
-func (f *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget gl.Enum, renderbuffer gl.Renderbuffer) {
- f.Ctx.Call("framebufferRenderbuffer", int(target), int(attachment), int(renderbuffertarget), js.Value(renderbuffer))
-}
-func (f *Functions) FramebufferTexture2D(target, attachment, texTarget gl.Enum, t gl.Texture, level int) {
- f.Ctx.Call("framebufferTexture2D", int(target), int(attachment), int(texTarget), js.Value(t), level)
-}
-func (f *Functions) GetError() gl.Enum {
- return gl.Enum(f.Ctx.Call("getError").Int())
-}
-func (f *Functions) GetRenderbufferParameteri(target, pname gl.Enum) int {
- return paramVal(f.Ctx.Call("getRenderbufferParameteri", int(pname)))
-}
-func (f *Functions) GetFramebufferAttachmentParameteri(target, attachment, pname gl.Enum) int {
- return paramVal(f.Ctx.Call("getFramebufferAttachmentParameter", int(target), int(attachment), int(pname)))
-}
-func (f *Functions) GetBinding(pname gl.Enum) gl.Object {
- return gl.Object(f.Ctx.Call("getParameter", int(pname)))
-}
-func (f *Functions) GetInteger(pname gl.Enum) int {
- return paramVal(f.Ctx.Call("getParameter", int(pname)))
-}
-func (f *Functions) GetProgrami(p gl.Program, pname gl.Enum) int {
- return paramVal(f.Ctx.Call("getProgramParameter", js.Value(p), int(pname)))
-}
-func (f *Functions) GetProgramInfoLog(p gl.Program) string {
- return f.Ctx.Call("getProgramInfoLog", js.Value(p)).String()
-}
-func (f *Functions) GetQueryObjectuiv(query gl.Query, pname gl.Enum) uint {
- if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
- return uint(paramVal(f.Ctx.Call("getQueryParameter", js.Value(query), int(pname))))
- } else {
- return uint(paramVal(f.EXT_disjoint_timer_query.Call("getQueryObjectEXT", js.Value(query), int(pname))))
- }
-}
-func (f *Functions) GetShaderi(s gl.Shader, pname gl.Enum) int {
- return paramVal(f.Ctx.Call("getShaderParameter", js.Value(s), int(pname)))
-}
-func (f *Functions) GetShaderInfoLog(s gl.Shader) string {
- return f.Ctx.Call("getShaderInfoLog", js.Value(s)).String()
-}
-func (f *Functions) GetString(pname gl.Enum) string {
- switch pname {
- case gl.EXTENSIONS:
- extsjs := f.Ctx.Call("getSupportedExtensions")
- var exts []string
- for i := 0; i < extsjs.Length(); i++ {
- exts = append(exts, "GL_"+extsjs.Index(i).String())
- }
- return strings.Join(exts, " ")
- default:
- return f.Ctx.Call("getParameter", int(pname)).String()
- }
-}
-func (f *Functions) GetUniformBlockIndex(p gl.Program, name string) uint {
- return uint(paramVal(f.Ctx.Call("getUniformBlockIndex", js.Value(p), name)))
-}
-func (f *Functions) GetUniformLocation(p gl.Program, name string) gl.Uniform {
- return gl.Uniform(f.Ctx.Call("getUniformLocation", js.Value(p), name))
-}
-func (f *Functions) InvalidateFramebuffer(target, attachment gl.Enum) {
- fn := f.Ctx.Get("invalidateFramebuffer")
- if !fn.IsUndefined() {
- if f.int32Buf.IsUndefined() {
- f.int32Buf = js.Global().Get("Int32Array").New(1)
- }
- f.int32Buf.SetIndex(0, int32(attachment))
- f.Ctx.Call("invalidateFramebuffer", int(target), f.int32Buf)
- }
-}
-func (f *Functions) LinkProgram(p gl.Program) {
- f.Ctx.Call("linkProgram", js.Value(p))
-}
-func (f *Functions) PixelStorei(pname gl.Enum, param int32) {
- f.Ctx.Call("pixelStorei", int(pname), param)
-}
-func (f *Functions) RenderbufferStorage(target, internalformat gl.Enum, width, height int) {
- f.Ctx.Call("renderbufferStorage", int(target), int(internalformat), width, height)
-}
-func (f *Functions) ReadPixels(x, y, width, height int, format, ty gl.Enum, data []byte) {
- f.resizeByteBuffer(len(data))
- f.Ctx.Call("readPixels", x, y, width, height, int(format), int(ty), f.byteBuf)
- js.CopyBytesToGo(data, f.byteBuf)
-}
-func (f *Functions) Scissor(x, y, width, height int32) {
- f.Ctx.Call("scissor", x, y, width, height)
-}
-func (f *Functions) ShaderSource(s gl.Shader, src string) {
- f.Ctx.Call("shaderSource", js.Value(s), src)
-}
-func (f *Functions) TexImage2D(target gl.Enum, level int, internalFormat int, width, height int, format, ty gl.Enum, data []byte) {
- f.Ctx.Call("texImage2D", int(target), int(level), int(internalFormat), int(width), int(height), 0, int(format), int(ty), f.byteArrayOf(data))
-}
-func (f *Functions) TexSubImage2D(target gl.Enum, level int, x, y, width, height int, format, ty gl.Enum, data []byte) {
- f.Ctx.Call("texSubImage2D", int(target), level, x, y, width, height, int(format), int(ty), f.byteArrayOf(data))
-}
-func (f *Functions) TexParameteri(target, pname gl.Enum, param int) {
- f.Ctx.Call("texParameteri", int(target), int(pname), int(param))
-}
-func (f *Functions) UniformBlockBinding(p gl.Program, uniformBlockIndex uint, uniformBlockBinding uint) {
- f.Ctx.Call("uniformBlockBinding", js.Value(p), int(uniformBlockIndex), int(uniformBlockBinding))
-}
-func (f *Functions) Uniform1f(dst gl.Uniform, v float32) {
- f.Ctx.Call("uniform1f", js.Value(dst), v)
-}
-func (f *Functions) Uniform1i(dst gl.Uniform, v int) {
- f.Ctx.Call("uniform1i", js.Value(dst), v)
-}
-func (f *Functions) Uniform2f(dst gl.Uniform, v0, v1 float32) {
- f.Ctx.Call("uniform2f", js.Value(dst), v0, v1)
-}
-func (f *Functions) Uniform3f(dst gl.Uniform, v0, v1, v2 float32) {
- f.Ctx.Call("uniform3f", js.Value(dst), v0, v1, v2)
-}
-func (f *Functions) Uniform4f(dst gl.Uniform, v0, v1, v2, v3 float32) {
- f.Ctx.Call("uniform4f", js.Value(dst), v0, v1, v2, v3)
-}
-func (f *Functions) UseProgram(p gl.Program) {
- f.Ctx.Call("useProgram", js.Value(p))
-}
-func (f *Functions) VertexAttribPointer(dst gl.Attrib, size int, ty gl.Enum, normalized bool, stride, offset int) {
- f.Ctx.Call("vertexAttribPointer", int(dst), size, int(ty), normalized, stride, offset)
-}
-func (f *Functions) Viewport(x, y, width, height int) {
- f.Ctx.Call("viewport", x, y, width, height)
-}
-
-func (f *Functions) byteArrayOf(data []byte) js.Value {
- if len(data) == 0 {
- return js.Null()
- }
- f.resizeByteBuffer(len(data))
- js.CopyBytesToJS(f.byteBuf, data)
- return f.byteBuf
-}
-
-func (f *Functions) resizeByteBuffer(n int) {
- if n == 0 {
- return
- }
- if !f.byteBuf.IsUndefined() && f.byteBuf.Length() >= n {
- return
- }
- f.byteBuf = js.Global().Get("Uint8Array").New(n)
-}
-
-func paramVal(v js.Value) int {
- switch v.Type() {
- case js.TypeBoolean:
- if b := v.Bool(); b {
- return 1
- } else {
- return 0
- }
- case js.TypeNumber:
- return v.Int()
- default:
- panic("unknown parameter type")
- }
-}
diff --git a/vendor/gioui.org/app/internal/glimpl/gl_windows.go b/vendor/gioui.org/app/internal/glimpl/gl_windows.go
deleted file mode 100644
index 4fe1d91..0000000
--- a/vendor/gioui.org/app/internal/glimpl/gl_windows.go
+++ /dev/null
@@ -1,406 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package glimpl
-
-import (
- "math"
- "runtime"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-
- "gioui.org/gpu/gl"
- gunsafe "gioui.org/internal/unsafe"
-)
-
-var (
- LibGLESv2 = windows.NewLazyDLL("libGLESv2.dll")
- _glActiveTexture = LibGLESv2.NewProc("glActiveTexture")
- _glAttachShader = LibGLESv2.NewProc("glAttachShader")
- _glBeginQuery = LibGLESv2.NewProc("glBeginQuery")
- _glBindAttribLocation = LibGLESv2.NewProc("glBindAttribLocation")
- _glBindBuffer = LibGLESv2.NewProc("glBindBuffer")
- _glBindBufferBase = LibGLESv2.NewProc("glBindBufferBase")
- _glBindFramebuffer = LibGLESv2.NewProc("glBindFramebuffer")
- _glBindRenderbuffer = LibGLESv2.NewProc("glBindRenderbuffer")
- _glBindTexture = LibGLESv2.NewProc("glBindTexture")
- _glBlendEquation = LibGLESv2.NewProc("glBlendEquation")
- _glBlendFunc = LibGLESv2.NewProc("glBlendFunc")
- _glBufferData = LibGLESv2.NewProc("glBufferData")
- _glCheckFramebufferStatus = LibGLESv2.NewProc("glCheckFramebufferStatus")
- _glClear = LibGLESv2.NewProc("glClear")
- _glClearColor = LibGLESv2.NewProc("glClearColor")
- _glClearDepthf = LibGLESv2.NewProc("glClearDepthf")
- _glDeleteQueries = LibGLESv2.NewProc("glDeleteQueries")
- _glCompileShader = LibGLESv2.NewProc("glCompileShader")
- _glGenBuffers = LibGLESv2.NewProc("glGenBuffers")
- _glGenFramebuffers = LibGLESv2.NewProc("glGenFramebuffers")
- _glGetUniformBlockIndex = LibGLESv2.NewProc("glGetUniformBlockIndex")
- _glCreateProgram = LibGLESv2.NewProc("glCreateProgram")
- _glGenRenderbuffers = LibGLESv2.NewProc("glGenRenderbuffers")
- _glCreateShader = LibGLESv2.NewProc("glCreateShader")
- _glGenTextures = LibGLESv2.NewProc("glGenTextures")
- _glDeleteBuffers = LibGLESv2.NewProc("glDeleteBuffers")
- _glDeleteFramebuffers = LibGLESv2.NewProc("glDeleteFramebuffers")
- _glDeleteProgram = LibGLESv2.NewProc("glDeleteProgram")
- _glDeleteShader = LibGLESv2.NewProc("glDeleteShader")
- _glDeleteRenderbuffers = LibGLESv2.NewProc("glDeleteRenderbuffers")
- _glDeleteTextures = LibGLESv2.NewProc("glDeleteTextures")
- _glDepthFunc = LibGLESv2.NewProc("glDepthFunc")
- _glDepthMask = LibGLESv2.NewProc("glDepthMask")
- _glDisableVertexAttribArray = LibGLESv2.NewProc("glDisableVertexAttribArray")
- _glDisable = LibGLESv2.NewProc("glDisable")
- _glDrawArrays = LibGLESv2.NewProc("glDrawArrays")
- _glDrawElements = LibGLESv2.NewProc("glDrawElements")
- _glEnable = LibGLESv2.NewProc("glEnable")
- _glEnableVertexAttribArray = LibGLESv2.NewProc("glEnableVertexAttribArray")
- _glEndQuery = LibGLESv2.NewProc("glEndQuery")
- _glFinish = LibGLESv2.NewProc("glFinish")
- _glFramebufferRenderbuffer = LibGLESv2.NewProc("glFramebufferRenderbuffer")
- _glFramebufferTexture2D = LibGLESv2.NewProc("glFramebufferTexture2D")
- _glGenQueries = LibGLESv2.NewProc("glGenQueries")
- _glGetError = LibGLESv2.NewProc("glGetError")
- _glGetRenderbufferParameteri = LibGLESv2.NewProc("glGetRenderbufferParameteri")
- _glGetFramebufferAttachmentParameteri = LibGLESv2.NewProc("glGetFramebufferAttachmentParameteri")
- _glGetIntegerv = LibGLESv2.NewProc("glGetIntegerv")
- _glGetProgramiv = LibGLESv2.NewProc("glGetProgramiv")
- _glGetProgramInfoLog = LibGLESv2.NewProc("glGetProgramInfoLog")
- _glGetQueryObjectuiv = LibGLESv2.NewProc("glGetQueryObjectuiv")
- _glGetShaderiv = LibGLESv2.NewProc("glGetShaderiv")
- _glGetShaderInfoLog = LibGLESv2.NewProc("glGetShaderInfoLog")
- _glGetString = LibGLESv2.NewProc("glGetString")
- _glGetUniformLocation = LibGLESv2.NewProc("glGetUniformLocation")
- _glInvalidateFramebuffer = LibGLESv2.NewProc("glInvalidateFramebuffer")
- _glLinkProgram = LibGLESv2.NewProc("glLinkProgram")
- _glPixelStorei = LibGLESv2.NewProc("glPixelStorei")
- _glReadPixels = LibGLESv2.NewProc("glReadPixels")
- _glRenderbufferStorage = LibGLESv2.NewProc("glRenderbufferStorage")
- _glScissor = LibGLESv2.NewProc("glScissor")
- _glShaderSource = LibGLESv2.NewProc("glShaderSource")
- _glTexImage2D = LibGLESv2.NewProc("glTexImage2D")
- _glTexSubImage2D = LibGLESv2.NewProc("glTexSubImage2D")
- _glTexParameteri = LibGLESv2.NewProc("glTexParameteri")
- _glUniformBlockBinding = LibGLESv2.NewProc("glUniformBlockBinding")
- _glUniform1f = LibGLESv2.NewProc("glUniform1f")
- _glUniform1i = LibGLESv2.NewProc("glUniform1i")
- _glUniform2f = LibGLESv2.NewProc("glUniform2f")
- _glUniform3f = LibGLESv2.NewProc("glUniform3f")
- _glUniform4f = LibGLESv2.NewProc("glUniform4f")
- _glUseProgram = LibGLESv2.NewProc("glUseProgram")
- _glVertexAttribPointer = LibGLESv2.NewProc("glVertexAttribPointer")
- _glViewport = LibGLESv2.NewProc("glViewport")
-)
-
-type Functions struct {
- // gl.Query caches.
- int32s [100]int32
-}
-
-func (c *Functions) ActiveTexture(t gl.Enum) {
- syscall.Syscall(_glActiveTexture.Addr(), 1, uintptr(t), 0, 0)
-}
-func (c *Functions) AttachShader(p gl.Program, s gl.Shader) {
- syscall.Syscall(_glAttachShader.Addr(), 2, uintptr(p.V), uintptr(s.V), 0)
-}
-func (f *Functions) BeginQuery(target gl.Enum, query gl.Query) {
- syscall.Syscall(_glBeginQuery.Addr(), 2, uintptr(target), uintptr(query.V), 0)
-}
-func (c *Functions) BindAttribLocation(p gl.Program, a gl.Attrib, name string) {
- cname := cString(name)
- c0 := &cname[0]
- syscall.Syscall(_glBindAttribLocation.Addr(), 3, uintptr(p.V), uintptr(a), uintptr(unsafe.Pointer(c0)))
- issue34474KeepAlive(c)
-}
-func (c *Functions) BindBuffer(target gl.Enum, b gl.Buffer) {
- syscall.Syscall(_glBindBuffer.Addr(), 2, uintptr(target), uintptr(b.V), 0)
-}
-func (c *Functions) BindBufferBase(target gl.Enum, index int, b gl.Buffer) {
- syscall.Syscall(_glBindBufferBase.Addr(), 3, uintptr(target), uintptr(index), uintptr(b.V))
-}
-func (c *Functions) BindFramebuffer(target gl.Enum, fb gl.Framebuffer) {
- syscall.Syscall(_glBindFramebuffer.Addr(), 2, uintptr(target), uintptr(fb.V), 0)
-}
-func (c *Functions) BindRenderbuffer(target gl.Enum, rb gl.Renderbuffer) {
- syscall.Syscall(_glBindRenderbuffer.Addr(), 2, uintptr(target), uintptr(rb.V), 0)
-}
-func (c *Functions) BindTexture(target gl.Enum, t gl.Texture) {
- syscall.Syscall(_glBindTexture.Addr(), 2, uintptr(target), uintptr(t.V), 0)
-}
-func (c *Functions) BlendEquation(mode gl.Enum) {
- syscall.Syscall(_glBlendEquation.Addr(), 1, uintptr(mode), 0, 0)
-}
-func (c *Functions) BlendFunc(sfactor, dfactor gl.Enum) {
- syscall.Syscall(_glBlendFunc.Addr(), 2, uintptr(sfactor), uintptr(dfactor), 0)
-}
-func (c *Functions) BufferData(target gl.Enum, src []byte, usage gl.Enum) {
- if n := len(src); n == 0 {
- syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), 0, 0, uintptr(usage), 0, 0)
- } else {
- s0 := &src[0]
- syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), uintptr(n), uintptr(unsafe.Pointer(s0)), uintptr(usage), 0, 0)
- issue34474KeepAlive(s0)
- }
-}
-func (c *Functions) CheckFramebufferStatus(target gl.Enum) gl.Enum {
- s, _, _ := syscall.Syscall(_glCheckFramebufferStatus.Addr(), 1, uintptr(target), 0, 0)
- return gl.Enum(s)
-}
-func (c *Functions) Clear(mask gl.Enum) {
- syscall.Syscall(_glClear.Addr(), 1, uintptr(mask), 0, 0)
-}
-func (c *Functions) ClearColor(red, green, blue, alpha float32) {
- syscall.Syscall6(_glClearColor.Addr(), 4, uintptr(math.Float32bits(red)), uintptr(math.Float32bits(green)), uintptr(math.Float32bits(blue)), uintptr(math.Float32bits(alpha)), 0, 0)
-}
-func (c *Functions) ClearDepthf(d float32) {
- syscall.Syscall(_glClearDepthf.Addr(), 1, uintptr(math.Float32bits(d)), 0, 0)
-}
-func (c *Functions) CompileShader(s gl.Shader) {
- syscall.Syscall(_glCompileShader.Addr(), 1, uintptr(s.V), 0, 0)
-}
-func (c *Functions) CreateBuffer() gl.Buffer {
- var buf uintptr
- syscall.Syscall(_glGenBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&buf)), 0)
- return gl.Buffer{uint(buf)}
-}
-func (c *Functions) CreateFramebuffer() gl.Framebuffer {
- var fb uintptr
- syscall.Syscall(_glGenFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&fb)), 0)
- return gl.Framebuffer{uint(fb)}
-}
-func (c *Functions) CreateProgram() gl.Program {
- p, _, _ := syscall.Syscall(_glCreateProgram.Addr(), 0, 0, 0, 0)
- return gl.Program{uint(p)}
-}
-func (f *Functions) CreateQuery() gl.Query {
- var q uintptr
- syscall.Syscall(_glGenQueries.Addr(), 2, 1, uintptr(unsafe.Pointer(&q)), 0)
- return gl.Query{uint(q)}
-}
-func (c *Functions) CreateRenderbuffer() gl.Renderbuffer {
- var rb uintptr
- syscall.Syscall(_glGenRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&rb)), 0)
- return gl.Renderbuffer{uint(rb)}
-}
-func (c *Functions) CreateShader(ty gl.Enum) gl.Shader {
- s, _, _ := syscall.Syscall(_glCreateShader.Addr(), 1, uintptr(ty), 0, 0)
- return gl.Shader{uint(s)}
-}
-func (c *Functions) CreateTexture() gl.Texture {
- var t uintptr
- syscall.Syscall(_glGenTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&t)), 0)
- return gl.Texture{uint(t)}
-}
-func (c *Functions) DeleteBuffer(v gl.Buffer) {
- syscall.Syscall(_glDeleteBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&v)), 0)
-}
-func (c *Functions) DeleteFramebuffer(v gl.Framebuffer) {
- syscall.Syscall(_glDeleteFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&v.V)), 0)
-}
-func (c *Functions) DeleteProgram(p gl.Program) {
- syscall.Syscall(_glDeleteProgram.Addr(), 1, uintptr(p.V), 0, 0)
-}
-func (f *Functions) DeleteQuery(query gl.Query) {
- syscall.Syscall(_glDeleteQueries.Addr(), 2, 1, uintptr(unsafe.Pointer(&query.V)), 0)
-}
-func (c *Functions) DeleteShader(s gl.Shader) {
- syscall.Syscall(_glDeleteShader.Addr(), 1, uintptr(s.V), 0, 0)
-}
-func (c *Functions) DeleteRenderbuffer(v gl.Renderbuffer) {
- syscall.Syscall(_glDeleteRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&v.V)), 0)
-}
-func (c *Functions) DeleteTexture(v gl.Texture) {
- syscall.Syscall(_glDeleteTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&v.V)), 0)
-}
-func (c *Functions) DepthFunc(f gl.Enum) {
- syscall.Syscall(_glDepthFunc.Addr(), 1, uintptr(f), 0, 0)
-}
-func (c *Functions) DepthMask(mask bool) {
- var m uintptr
- if mask {
- m = 1
- }
- syscall.Syscall(_glDepthMask.Addr(), 1, m, 0, 0)
-}
-func (c *Functions) DisableVertexAttribArray(a gl.Attrib) {
- syscall.Syscall(_glDisableVertexAttribArray.Addr(), 1, uintptr(a), 0, 0)
-}
-func (c *Functions) Disable(cap gl.Enum) {
- syscall.Syscall(_glDisable.Addr(), 1, uintptr(cap), 0, 0)
-}
-func (c *Functions) DrawArrays(mode gl.Enum, first, count int) {
- syscall.Syscall(_glDrawArrays.Addr(), 3, uintptr(mode), uintptr(first), uintptr(count))
-}
-func (c *Functions) DrawElements(mode gl.Enum, count int, ty gl.Enum, offset int) {
- syscall.Syscall6(_glDrawElements.Addr(), 4, uintptr(mode), uintptr(count), uintptr(ty), uintptr(offset), 0, 0)
-}
-func (c *Functions) Enable(cap gl.Enum) {
- syscall.Syscall(_glEnable.Addr(), 1, uintptr(cap), 0, 0)
-}
-func (c *Functions) EnableVertexAttribArray(a gl.Attrib) {
- syscall.Syscall(_glEnableVertexAttribArray.Addr(), 1, uintptr(a), 0, 0)
-}
-func (f *Functions) EndQuery(target gl.Enum) {
- syscall.Syscall(_glEndQuery.Addr(), 1, uintptr(target), 0, 0)
-}
-func (c *Functions) Finish() {
- syscall.Syscall(_glFinish.Addr(), 0, 0, 0, 0)
-}
-func (c *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget gl.Enum, renderbuffer gl.Renderbuffer) {
- syscall.Syscall6(_glFramebufferRenderbuffer.Addr(), 4, uintptr(target), uintptr(attachment), uintptr(renderbuffertarget), uintptr(renderbuffer.V), 0, 0)
-}
-func (c *Functions) FramebufferTexture2D(target, attachment, texTarget gl.Enum, t gl.Texture, level int) {
- syscall.Syscall6(_glFramebufferTexture2D.Addr(), 5, uintptr(target), uintptr(attachment), uintptr(texTarget), uintptr(t.V), uintptr(level), 0)
-}
-func (f *Functions) GetUniformBlockIndex(p gl.Program, name string) uint {
- cname := cString(name)
- c0 := &cname[0]
- u, _, _ := syscall.Syscall(_glGetUniformBlockIndex.Addr(), 2, uintptr(p.V), uintptr(unsafe.Pointer(c0)), 0)
- issue34474KeepAlive(c0)
- return uint(u)
-}
-func (c *Functions) GetBinding(pname gl.Enum) gl.Object {
- return gl.Object{uint(c.GetInteger(pname))}
-}
-func (c *Functions) GetError() gl.Enum {
- e, _, _ := syscall.Syscall(_glGetError.Addr(), 0, 0, 0, 0)
- return gl.Enum(e)
-}
-func (c *Functions) GetRenderbufferParameteri(target, pname gl.Enum) int {
- p, _, _ := syscall.Syscall(_glGetRenderbufferParameteri.Addr(), 2, uintptr(target), uintptr(pname), 0)
- return int(p)
-}
-func (c *Functions) GetFramebufferAttachmentParameteri(target, attachment, pname gl.Enum) int {
- p, _, _ := syscall.Syscall(_glGetFramebufferAttachmentParameteri.Addr(), 3, uintptr(target), uintptr(attachment), uintptr(pname))
- return int(p)
-}
-func (c *Functions) GetInteger(pname gl.Enum) int {
- syscall.Syscall(_glGetIntegerv.Addr(), 2, uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])), 0)
- return int(c.int32s[0])
-}
-func (c *Functions) GetProgrami(p gl.Program, pname gl.Enum) int {
- syscall.Syscall(_glGetProgramiv.Addr(), 3, uintptr(p.V), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
- return int(c.int32s[0])
-}
-func (c *Functions) GetProgramInfoLog(p gl.Program) string {
- n := c.GetProgrami(p, gl.INFO_LOG_LENGTH)
- buf := make([]byte, n)
- syscall.Syscall6(_glGetProgramInfoLog.Addr(), 4, uintptr(p.V), uintptr(len(buf)), 0, uintptr(unsafe.Pointer(&buf[0])), 0, 0)
- return string(buf)
-}
-func (c *Functions) GetQueryObjectuiv(query gl.Query, pname gl.Enum) uint {
- syscall.Syscall(_glGetQueryObjectuiv.Addr(), 3, uintptr(query.V), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
- return uint(c.int32s[0])
-}
-func (c *Functions) GetShaderi(s gl.Shader, pname gl.Enum) int {
- syscall.Syscall(_glGetShaderiv.Addr(), 3, uintptr(s.V), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
- return int(c.int32s[0])
-}
-func (c *Functions) GetShaderInfoLog(s gl.Shader) string {
- n := c.GetShaderi(s, gl.INFO_LOG_LENGTH)
- buf := make([]byte, n)
- syscall.Syscall6(_glGetShaderInfoLog.Addr(), 4, uintptr(s.V), uintptr(len(buf)), 0, uintptr(unsafe.Pointer(&buf[0])), 0, 0)
- return string(buf)
-}
-func (c *Functions) GetString(pname gl.Enum) string {
- s, _, _ := syscall.Syscall(_glGetString.Addr(), 1, uintptr(pname), 0, 0)
- return gunsafe.GoString(gunsafe.SliceOf(s))
-}
-func (c *Functions) GetUniformLocation(p gl.Program, name string) gl.Uniform {
- cname := cString(name)
- c0 := &cname[0]
- u, _, _ := syscall.Syscall(_glGetUniformLocation.Addr(), 2, uintptr(p.V), uintptr(unsafe.Pointer(c0)), 0)
- issue34474KeepAlive(c0)
- return gl.Uniform{int(u)}
-}
-func (c *Functions) InvalidateFramebuffer(target, attachment gl.Enum) {
- addr := _glInvalidateFramebuffer.Addr()
- if addr == 0 {
- // InvalidateFramebuffer is just a hint. Skip it if not supported.
- return
- }
- syscall.Syscall(addr, 3, uintptr(target), 1, uintptr(unsafe.Pointer(&attachment)))
-}
-func (c *Functions) LinkProgram(p gl.Program) {
- syscall.Syscall(_glLinkProgram.Addr(), 1, uintptr(p.V), 0, 0)
-}
-func (c *Functions) PixelStorei(pname gl.Enum, param int32) {
- syscall.Syscall(_glPixelStorei.Addr(), 2, uintptr(pname), uintptr(param), 0)
-}
-func (f *Functions) ReadPixels(x, y, width, height int, format, ty gl.Enum, data []byte) {
- d0 := &data[0]
- syscall.Syscall9(_glReadPixels.Addr(), 7, uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0)), 0, 0)
- issue34474KeepAlive(d0)
-}
-func (c *Functions) RenderbufferStorage(target, internalformat gl.Enum, width, height int) {
- syscall.Syscall6(_glRenderbufferStorage.Addr(), 4, uintptr(target), uintptr(internalformat), uintptr(width), uintptr(height), 0, 0)
-}
-func (c *Functions) Scissor(x, y, width, height int32) {
- syscall.Syscall6(_glScissor.Addr(), 4, uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0, 0)
-}
-func (c *Functions) ShaderSource(s gl.Shader, src string) {
- var n uintptr = uintptr(len(src))
- psrc := &src
- syscall.Syscall6(_glShaderSource.Addr(), 4, uintptr(s.V), 1, uintptr(unsafe.Pointer(psrc)), uintptr(unsafe.Pointer(&n)), 0, 0)
- issue34474KeepAlive(psrc)
-}
-func (c *Functions) TexImage2D(target gl.Enum, level int, internalFormat int, width, height int, format, ty gl.Enum, data []byte) {
- if len(data) == 0 {
- syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), 0)
- } else {
- d0 := &data[0]
- syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0)))
- issue34474KeepAlive(d0)
- }
-}
-func (c *Functions) TexSubImage2D(target gl.Enum, level int, x, y, width, height int, format, ty gl.Enum, data []byte) {
- d0 := &data[0]
- syscall.Syscall9(_glTexSubImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0)))
- issue34474KeepAlive(d0)
-}
-func (c *Functions) TexParameteri(target, pname gl.Enum, param int) {
- syscall.Syscall(_glTexParameteri.Addr(), 3, uintptr(target), uintptr(pname), uintptr(param))
-}
-func (f *Functions) UniformBlockBinding(p gl.Program, uniformBlockIndex uint, uniformBlockBinding uint) {
- syscall.Syscall(_glUniformBlockBinding.Addr(), 3, uintptr(p.V), uintptr(uniformBlockIndex), uintptr(uniformBlockBinding))
-}
-func (c *Functions) Uniform1f(dst gl.Uniform, v float32) {
- syscall.Syscall(_glUniform1f.Addr(), 2, uintptr(dst.V), uintptr(math.Float32bits(v)), 0)
-}
-func (c *Functions) Uniform1i(dst gl.Uniform, v int) {
- syscall.Syscall(_glUniform1i.Addr(), 2, uintptr(dst.V), uintptr(v), 0)
-}
-func (c *Functions) Uniform2f(dst gl.Uniform, v0, v1 float32) {
- syscall.Syscall(_glUniform2f.Addr(), 3, uintptr(dst.V), uintptr(math.Float32bits(v0)), uintptr(math.Float32bits(v1)))
-}
-func (c *Functions) Uniform3f(dst gl.Uniform, v0, v1, v2 float32) {
- syscall.Syscall6(_glUniform3f.Addr(), 4, uintptr(dst.V), uintptr(math.Float32bits(v0)), uintptr(math.Float32bits(v1)), uintptr(math.Float32bits(v2)), 0, 0)
-}
-func (c *Functions) Uniform4f(dst gl.Uniform, v0, v1, v2, v3 float32) {
- syscall.Syscall6(_glUniform4f.Addr(), 5, uintptr(dst.V), uintptr(math.Float32bits(v0)), uintptr(math.Float32bits(v1)), uintptr(math.Float32bits(v2)), uintptr(math.Float32bits(v3)), 0)
-}
-func (c *Functions) UseProgram(p gl.Program) {
- syscall.Syscall(_glUseProgram.Addr(), 1, uintptr(p.V), 0, 0)
-}
-func (c *Functions) VertexAttribPointer(dst gl.Attrib, size int, ty gl.Enum, normalized bool, stride, offset int) {
- var norm uintptr
- if normalized {
- norm = 1
- }
- syscall.Syscall6(_glVertexAttribPointer.Addr(), 6, uintptr(dst), uintptr(size), uintptr(ty), norm, uintptr(stride), uintptr(offset))
-}
-func (c *Functions) Viewport(x, y, width, height int) {
- syscall.Syscall6(_glViewport.Addr(), 4, uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0, 0)
-}
-
-func cString(s string) []byte {
- b := make([]byte, len(s)+1)
- copy(b, s)
- return b
-}
-
-// issue34474KeepAlive calls runtime.KeepAlive as a
-// workaround for golang.org/issue/34474.
-func issue34474KeepAlive(v interface{}) {
- runtime.KeepAlive(v)
-}
diff --git a/vendor/gioui.org/app/internal/log/log_android.go b/vendor/gioui.org/app/internal/log/log_android.go
index 7936911..1245598 100644
--- a/vendor/gioui.org/app/internal/log/log_android.go
+++ b/vendor/gioui.org/app/internal/log/log_android.go
@@ -40,16 +40,22 @@ type androidLogWriter struct {
}
func (w *androidLogWriter) Write(data []byte) (int, error) {
- // Truncate the buffer, leaving space for the '\0'.
- if max := len(w.buf) - 1; len(data) > max {
- data = data[:max]
+ n := 0
+ for len(data) > 0 {
+ msg := data
+ // Truncate the buffer, leaving space for the '\0'.
+ if max := len(w.buf) - 1; len(msg) > max {
+ msg = msg[:max]
+ }
+ buf := w.buf[:len(msg)+1]
+ copy(buf, msg)
+ // Terminating '\0'.
+ buf[len(msg)] = 0
+ C.__android_log_write(C.ANDROID_LOG_INFO, logTag, (*C.char)(unsafe.Pointer(&buf[0])))
+ n += len(msg)
+ data = data[len(msg):]
}
- buf := w.buf[:len(data)+1]
- copy(buf, data)
- // Terminating '\0'.
- buf[len(data)] = 0
- C.__android_log_write(C.ANDROID_LOG_INFO, logTag, (*C.char)(unsafe.Pointer(&buf[0])))
- return len(data), nil
+ return n, nil
}
func logFd(fd uintptr) {
diff --git a/vendor/gioui.org/app/internal/log/log_ios.go b/vendor/gioui.org/app/internal/log/log_ios.go
index e49f425..cad4e19 100644
--- a/vendor/gioui.org/app/internal/log/log_ios.go
+++ b/vendor/gioui.org/app/internal/log/log_ios.go
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: Unlicense OR MIT
+//go:build darwin && ios
// +build darwin,ios
package log
@@ -7,7 +8,11 @@ package log
/*
#cgo CFLAGS: -Werror -fmodules -fobjc-arc -x objective-c
-__attribute__ ((visibility ("hidden"))) void nslog(char *str);
+@import Foundation;
+
+static void nslog(char *str) {
+ NSLog(@"%@", @(str));
+}
*/
import "C"
@@ -17,7 +22,7 @@ import (
"log"
"unsafe"
- _ "gioui.org/app/internal/cocoainit"
+ _ "gioui.org/internal/cocoainit"
)
func init() {
diff --git a/vendor/gioui.org/app/internal/log/log_ios.m b/vendor/gioui.org/app/internal/log/log_ios.m
deleted file mode 100644
index 201bc36..0000000
--- a/vendor/gioui.org/app/internal/log/log_ios.m
+++ /dev/null
@@ -1,11 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build darwin,ios
-
-@import Foundation;
-
-#include "_cgo_export.h"
-
-void nslog(char *str) {
- NSLog(@"%@", @(str));
-}
diff --git a/vendor/gioui.org/app/internal/srgb/srgb.go b/vendor/gioui.org/app/internal/srgb/srgb.go
deleted file mode 100644
index c148b04..0000000
--- a/vendor/gioui.org/app/internal/srgb/srgb.go
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package srgb
-
-import (
- "fmt"
- "runtime"
- "strings"
-
- "gioui.org/app/internal/glimpl"
- "gioui.org/gpu/gl"
- "gioui.org/internal/unsafe"
-)
-
-// FBO implements an intermediate sRGB FBO
-// for gamma-correct rendering on platforms without
-// sRGB enabled native framebuffers.
-type FBO struct {
- c *glimpl.Functions
- width, height int
- frameBuffer gl.Framebuffer
- depthBuffer gl.Renderbuffer
- colorTex gl.Texture
- blitted bool
- quad gl.Buffer
- prog gl.Program
- gl3 bool
-}
-
-func New(f *glimpl.Functions) (*FBO, error) {
- var gl3 bool
- glVer := f.GetString(gl.VERSION)
- ver, _, err := gl.ParseGLVersion(glVer)
- if err != nil {
- return nil, err
- }
- if ver[0] >= 3 {
- gl3 = true
- } else {
- exts := f.GetString(gl.EXTENSIONS)
- if !strings.Contains(exts, "EXT_sRGB") {
- return nil, fmt.Errorf("no support for OpenGL ES 3 nor EXT_sRGB")
- }
- }
- s := &FBO{
- c: f,
- gl3: gl3,
- frameBuffer: f.CreateFramebuffer(),
- colorTex: f.CreateTexture(),
- depthBuffer: f.CreateRenderbuffer(),
- }
- f.BindTexture(gl.TEXTURE_2D, s.colorTex)
- f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
- f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
- f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
- f.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
- return s, nil
-}
-
-func (s *FBO) Blit() {
- if !s.blitted {
- prog, err := gl.CreateProgram(s.c, blitVSrc, blitFSrc, []string{"pos", "uv"})
- if err != nil {
- panic(err)
- }
- s.prog = prog
- s.c.UseProgram(prog)
- s.c.Uniform1i(gl.GetUniformLocation(s.c, prog, "tex"), 0)
- s.quad = s.c.CreateBuffer()
- s.c.BindBuffer(gl.ARRAY_BUFFER, s.quad)
- s.c.BufferData(gl.ARRAY_BUFFER,
- unsafe.BytesView([]float32{
- -1, +1, 0, 1,
- +1, +1, 1, 1,
- -1, -1, 0, 0,
- +1, -1, 1, 0,
- }),
- gl.STATIC_DRAW)
- s.blitted = true
- }
- s.c.BindFramebuffer(gl.FRAMEBUFFER, gl.Framebuffer{})
- s.c.UseProgram(s.prog)
- s.c.BindTexture(gl.TEXTURE_2D, s.colorTex)
- s.c.BindBuffer(gl.ARRAY_BUFFER, s.quad)
- s.c.VertexAttribPointer(0 /* pos */, 2, gl.FLOAT, false, 4*4, 0)
- s.c.VertexAttribPointer(1 /* uv */, 2, gl.FLOAT, false, 4*4, 4*2)
- s.c.EnableVertexAttribArray(0)
- s.c.EnableVertexAttribArray(1)
- s.c.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
- s.c.BindTexture(gl.TEXTURE_2D, gl.Texture{})
- s.c.DisableVertexAttribArray(0)
- s.c.DisableVertexAttribArray(1)
- s.c.BindFramebuffer(gl.FRAMEBUFFER, s.frameBuffer)
- s.c.InvalidateFramebuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0)
- s.c.InvalidateFramebuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT)
- // The Android emulator requires framebuffer 0 bound at eglSwapBuffer time.
- // Bind the sRGB framebuffer again in afterPresent.
- s.c.BindFramebuffer(gl.FRAMEBUFFER, gl.Framebuffer{})
-}
-
-func (s *FBO) AfterPresent() {
- s.c.BindFramebuffer(gl.FRAMEBUFFER, s.frameBuffer)
-}
-
-func (s *FBO) Refresh(w, h int) error {
- s.width, s.height = w, h
- if w == 0 || h == 0 {
- return nil
- }
- s.c.BindTexture(gl.TEXTURE_2D, s.colorTex)
- if s.gl3 {
- s.c.TexImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, w, h, gl.RGBA, gl.UNSIGNED_BYTE, nil)
- } else /* EXT_sRGB */ {
- s.c.TexImage2D(gl.TEXTURE_2D, 0, gl.SRGB_ALPHA_EXT, w, h, gl.SRGB_ALPHA_EXT, gl.UNSIGNED_BYTE, nil)
- }
- currentRB := gl.Renderbuffer(s.c.GetBinding(gl.RENDERBUFFER_BINDING))
- s.c.BindRenderbuffer(gl.RENDERBUFFER, s.depthBuffer)
- s.c.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h)
- s.c.BindRenderbuffer(gl.RENDERBUFFER, currentRB)
- s.c.BindFramebuffer(gl.FRAMEBUFFER, s.frameBuffer)
- s.c.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, s.colorTex, 0)
- s.c.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, s.depthBuffer)
- if st := s.c.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE {
- return fmt.Errorf("sRGB framebuffer incomplete (%dx%d), status: %#x error: %x", s.width, s.height, st, s.c.GetError())
- }
-
- if runtime.GOOS == "js" {
- // With macOS Safari, rendering to and then reading from a SRGB8_ALPHA8
- // texture result in twice gamma corrected colors. Using a plain RGBA
- // texture seems to work.
- s.c.ClearColor(.5, .5, .5, 1.0)
- s.c.Clear(gl.COLOR_BUFFER_BIT)
- var pixel [4]byte
- s.c.ReadPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel[:])
- if pixel[0] == 128 { // Correct sRGB color value is ~188
- s.c.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, gl.RGBA, gl.UNSIGNED_BYTE, nil)
- if st := s.c.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE {
- return fmt.Errorf("fallback RGBA framebuffer incomplete (%dx%d), status: %#x error: %x", s.width, s.height, st, s.c.GetError())
- }
- }
- }
-
- return nil
-}
-
-func (s *FBO) Release() {
- s.c.DeleteFramebuffer(s.frameBuffer)
- s.c.DeleteTexture(s.colorTex)
- s.c.DeleteRenderbuffer(s.depthBuffer)
- if s.blitted {
- s.c.DeleteBuffer(s.quad)
- s.c.DeleteProgram(s.prog)
- }
- s.c = nil
-}
-
-const (
- blitVSrc = `
-#version 100
-
-precision highp float;
-
-attribute vec2 pos;
-attribute vec2 uv;
-
-varying vec2 vUV;
-
-void main() {
- gl_Position = vec4(pos, 0, 1);
- vUV = uv;
-}
-`
- blitFSrc = `
-#version 100
-
-precision mediump float;
-
-uniform sampler2D tex;
-varying vec2 vUV;
-
-vec3 gamma(vec3 rgb) {
- vec3 exp = vec3(1.055)*pow(rgb, vec3(0.41666)) - vec3(0.055);
- vec3 lin = rgb * vec3(12.92);
- bvec3 cut = lessThan(rgb, vec3(0.0031308));
- return vec3(cut.r ? lin.r : exp.r, cut.g ? lin.g : exp.g, cut.b ? lin.b : exp.b);
-}
-
-void main() {
- vec4 col = texture2D(tex, vUV);
- vec3 rgb = col.rgb;
- rgb = gamma(rgb);
- gl_FragColor = vec4(rgb, col.a);
-}
-`
-)
diff --git a/vendor/gioui.org/app/internal/window/GioView.java b/vendor/gioui.org/app/internal/window/GioView.java
deleted file mode 100644
index be90c50..0000000
--- a/vendor/gioui.org/app/internal/window/GioView.java
+++ /dev/null
@@ -1,255 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package org.gioui;
-
-import java.lang.Class;
-import java.lang.IllegalAccessException;
-import java.lang.InstantiationException;
-import java.lang.ExceptionInInitializerError;
-import java.lang.SecurityException;
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Build;
-import android.text.Editable;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.Choreographer;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.WindowInsets;
-import android.view.Surface;
-import android.view.SurfaceView;
-import android.view.SurfaceHolder;
-import android.view.inputmethod.BaseInputConnection;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
-
-import java.io.UnsupportedEncodingException;
-
-public final class GioView extends SurfaceView implements Choreographer.FrameCallback {
- private final static Object initLock = new Object();
- private static boolean jniLoaded;
-
- private final SurfaceHolder.Callback surfCallbacks;
- private final View.OnFocusChangeListener focusCallback;
- private final InputMethodManager imm;
- private final float scrollXScale;
- private final float scrollYScale;
-
- private long nhandle;
-
- public GioView(Context context) {
- this(context, null);
- }
-
- public GioView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- // Late initialization of the Go runtime to wait for a valid context.
- Gio.init(context.getApplicationContext());
-
- ViewConfiguration conf = ViewConfiguration.get(context);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- scrollXScale = conf.getScaledHorizontalScrollFactor();
- scrollYScale = conf.getScaledVerticalScrollFactor();
- } else {
- float listItemHeight = 48; // dp
- float px = TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP,
- listItemHeight,
- getResources().getDisplayMetrics()
- );
- scrollXScale = px;
- scrollYScale = px;
- }
-
- nhandle = onCreateView(this);
- imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
- setFocusable(true);
- setFocusableInTouchMode(true);
- focusCallback = new View.OnFocusChangeListener() {
- @Override public void onFocusChange(View v, boolean focus) {
- GioView.this.onFocusChange(nhandle, focus);
- }
- };
- setOnFocusChangeListener(focusCallback);
- surfCallbacks = new SurfaceHolder.Callback() {
- @Override public void surfaceCreated(SurfaceHolder holder) {
- // Ignore; surfaceChanged is guaranteed to be called immediately after this.
- }
- @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- onSurfaceChanged(nhandle, getHolder().getSurface());
- }
- @Override public void surfaceDestroyed(SurfaceHolder holder) {
- onSurfaceDestroyed(nhandle);
- }
- };
- getHolder().addCallback(surfCallbacks);
- }
-
- @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
- onKeyEvent(nhandle, keyCode, event.getUnicodeChar(), event.getEventTime());
- return false;
- }
-
- @Override public boolean onGenericMotionEvent(MotionEvent event) {
- dispatchMotionEvent(event);
- return true;
- }
-
- @Override public boolean onTouchEvent(MotionEvent event) {
- // Ask for unbuffered events. Flutter and Chrome does it
- // so I assume its good for us as well.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- requestUnbufferedDispatch(event);
- }
-
- dispatchMotionEvent(event);
- return true;
- }
-
- private void dispatchMotionEvent(MotionEvent event) {
- for (int j = 0; j < event.getHistorySize(); j++) {
- long time = event.getHistoricalEventTime(j);
- for (int i = 0; i < event.getPointerCount(); i++) {
- onTouchEvent(
- nhandle,
- event.ACTION_MOVE,
- event.getPointerId(i),
- event.getToolType(i),
- event.getHistoricalX(i, j),
- event.getHistoricalY(i, j),
- scrollXScale*event.getHistoricalAxisValue(MotionEvent.AXIS_HSCROLL, i, j),
- scrollYScale*event.getHistoricalAxisValue(MotionEvent.AXIS_VSCROLL, i, j),
- event.getButtonState(),
- time);
- }
- }
- int act = event.getActionMasked();
- int idx = event.getActionIndex();
- for (int i = 0; i < event.getPointerCount(); i++) {
- int pact = event.ACTION_MOVE;
- if (i == idx) {
- pact = act;
- }
- onTouchEvent(
- nhandle,
- pact,
- event.getPointerId(i),
- event.getToolType(i),
- event.getX(i), event.getY(i),
- scrollXScale*event.getAxisValue(MotionEvent.AXIS_HSCROLL, i),
- scrollYScale*event.getAxisValue(MotionEvent.AXIS_VSCROLL, i),
- event.getButtonState(),
- event.getEventTime());
- }
- }
-
- @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- return new InputConnection(this);
- }
-
- void showTextInput() {
- post(new Runnable() {
- @Override public void run() {
- GioView.this.requestFocus();
- imm.showSoftInput(GioView.this, 0);
- }
- });
- }
-
- void hideTextInput() {
- post(new Runnable() {
- @Override public void run() {
- imm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
- });
- }
-
- @Override protected boolean fitSystemWindows(Rect insets) {
- onWindowInsets(nhandle, insets.top, insets.right, insets.bottom, insets.left);
- return true;
- }
-
- void postFrameCallback() {
- Choreographer.getInstance().removeFrameCallback(this);
- Choreographer.getInstance().postFrameCallback(this);
- }
-
- @Override public void doFrame(long nanos) {
- onFrameCallback(nhandle, nanos);
- }
-
- int getDensity() {
- return getResources().getDisplayMetrics().densityDpi;
- }
-
- float getFontScale() {
- return getResources().getConfiguration().fontScale;
- }
-
- void start() {
- onStartView(nhandle);
- }
-
- void stop() {
- onStopView(nhandle);
- }
-
- void destroy() {
- setOnFocusChangeListener(null);
- getHolder().removeCallback(surfCallbacks);
- onDestroyView(nhandle);
- nhandle = 0;
- }
-
- void configurationChanged() {
- onConfigurationChanged(nhandle);
- }
-
- void lowMemory() {
- onLowMemory();
- }
-
- boolean backPressed() {
- return onBack(nhandle);
- }
-
- static private native long onCreateView(GioView view);
- static private native void onDestroyView(long handle);
- static private native void onStartView(long handle);
- static private native void onStopView(long handle);
- static private native void onSurfaceDestroyed(long handle);
- static private native void onSurfaceChanged(long handle, Surface surface);
- static private native void onConfigurationChanged(long handle);
- static private native void onWindowInsets(long handle, int top, int right, int bottom, int left);
- static private native void onLowMemory();
- static private native void onTouchEvent(long handle, int action, int pointerID, int tool, float x, float y, float scrollX, float scrollY, int buttons, long time);
- static private native void onKeyEvent(long handle, int code, int character, long time);
- static private native void onFrameCallback(long handle, long nanos);
- static private native boolean onBack(long handle);
- static private native void onFocusChange(long handle, boolean focus);
-
- private static class InputConnection extends BaseInputConnection {
- private final Editable editable;
-
- InputConnection(View view) {
- // Passing false enables "dummy mode", where the BaseInputConnection
- // attempts to convert IME operations to key events.
- super(view, false);
- editable = Editable.Factory.getInstance().newEditable("");
- }
-
- @Override public Editable getEditable() {
- return editable;
- }
- }
-}
diff --git a/vendor/gioui.org/app/internal/window/d3d11_windows.go b/vendor/gioui.org/app/internal/window/d3d11_windows.go
deleted file mode 100644
index f1e06a6..0000000
--- a/vendor/gioui.org/app/internal/window/d3d11_windows.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package window
-
-import (
- "gioui.org/app/internal/d3d11"
- "gioui.org/gpu/backend"
-)
-
-type d3d11Context struct {
- win *window
- swchain *d3d11.SwapChain
- fbo *d3d11.Framebuffer
- backend backend.Device
- *d3d11.Device
- width, height int
-}
-
-func init() {
- backends = append(backends, gpuAPI{
- priority: 1,
- initializer: func(w *window) (Context, error) {
- hwnd, _, _ := w.HWND()
- dev, err := d3d11.NewDevice()
- if err != nil {
- return nil, err
- }
- swchain, err := dev.CreateSwapChain(hwnd)
- if err != nil {
- dev.Release()
- return nil, err
- }
- return &d3d11Context{win: w, Device: dev, swchain: swchain}, nil
- },
- })
-}
-
-func (c *d3d11Context) Backend() (backend.Device, error) {
- backend, err := d3d11.NewBackend(c.Device)
- if err != nil {
- return nil, err
- }
- c.backend = backend
- c.backend.BindFramebuffer(c.fbo)
- return backend, nil
-}
-
-func (c *d3d11Context) Present() error {
- if err := c.swchain.Present(); err != nil {
- if err, ok := err.(d3d11.ErrorCode); ok {
- switch err.Code {
- case d3d11.DXGI_STATUS_OCCLUDED:
- // Ignore
- return nil
- case d3d11.DXGI_ERROR_DEVICE_RESET, d3d11.DXGI_ERROR_DEVICE_REMOVED, d3d11.D3DDDIERR_DEVICEREMOVED:
- return ErrDeviceLost
- }
- }
- }
- return nil
-}
-
-func (c *d3d11Context) MakeCurrent() error {
- _, width, height := c.win.HWND()
- if c.fbo != nil && width == c.width && height == c.height {
- c.backend.BindFramebuffer(c.fbo)
- return nil
- }
- if c.fbo != nil {
- c.fbo.Release()
- c.fbo = nil
- }
- if err := c.swchain.Resize(); err != nil {
- return err
- }
- c.width = width
- c.height = height
- fbo, err := c.swchain.Framebuffer(c.Device)
- if err != nil {
- return err
- }
- c.fbo = fbo
- if c.backend != nil {
- c.backend.BindFramebuffer(c.fbo)
- }
- return nil
-}
-
-func (c *d3d11Context) Lock() {}
-
-func (c *d3d11Context) Unlock() {}
-
-func (c *d3d11Context) Release() {
- if c.fbo != nil {
- c.fbo.Release()
- }
- c.swchain.Release()
- c.Device.Release()
- c.fbo = nil
- c.swchain = nil
- c.Device = nil
-}
diff --git a/vendor/gioui.org/app/internal/window/egl_android.go b/vendor/gioui.org/app/internal/window/egl_android.go
deleted file mode 100644
index 19c8d63..0000000
--- a/vendor/gioui.org/app/internal/window/egl_android.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package window
-
-/*
-#include <EGL/egl.h>
-*/
-import "C"
-
-import (
- "unsafe"
-
- "gioui.org/app/internal/egl"
-)
-
-type context struct {
- win *window
- *egl.Context
-}
-
-func (w *window) NewContext() (Context, error) {
- ctx, err := egl.NewContext(nil)
- if err != nil {
- return nil, err
- }
- return &context{win: w, Context: ctx}, nil
-}
-
-func (c *context) Release() {
- if c.Context != nil {
- c.Context.Release()
- c.Context = nil
- }
-}
-
-func (c *context) MakeCurrent() error {
- c.Context.ReleaseSurface()
- win, width, height := c.win.nativeWindow(c.Context.VisualID())
- if win == nil {
- return nil
- }
- eglSurf := egl.NativeWindowType(unsafe.Pointer(win))
- if err := c.Context.CreateSurface(eglSurf, width, height); err != nil {
- return err
- }
- if err := c.Context.MakeCurrent(); err != nil {
- return err
- }
- return nil
-}
-
-func (c *context) Lock() {}
-
-func (c *context) Unlock() {}
diff --git a/vendor/gioui.org/app/internal/window/egl_x11.go b/vendor/gioui.org/app/internal/window/egl_x11.go
deleted file mode 100644
index ffe69c6..0000000
--- a/vendor/gioui.org/app/internal/window/egl_x11.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build linux,!android,!nox11 freebsd openbsd
-
-package window
-
-import (
- "unsafe"
-
- "gioui.org/app/internal/egl"
-)
-
-type x11Context struct {
- win *x11Window
- *egl.Context
-}
-
-func (w *x11Window) NewContext() (Context, error) {
- disp := egl.NativeDisplayType(unsafe.Pointer(w.display()))
- ctx, err := egl.NewContext(disp)
- if err != nil {
- return nil, err
- }
- return &x11Context{win: w, Context: ctx}, nil
-}
-
-func (c *x11Context) Release() {
- if c.Context != nil {
- c.Context.Release()
- c.Context = nil
- }
-}
-
-func (c *x11Context) MakeCurrent() error {
- c.Context.ReleaseSurface()
- win, width, height := c.win.window()
- eglSurf := egl.NativeWindowType(uintptr(win))
- if err := c.Context.CreateSurface(eglSurf, width, height); err != nil {
- return err
- }
- if err := c.Context.MakeCurrent(); err != nil {
- return err
- }
- c.Context.EnableVSync(true)
- return nil
-}
-
-func (c *x11Context) Lock() {}
-
-func (c *x11Context) Unlock() {}
diff --git a/vendor/gioui.org/app/internal/window/gl_js.go b/vendor/gioui.org/app/internal/window/gl_js.go
deleted file mode 100644
index 0adbdf4..0000000
--- a/vendor/gioui.org/app/internal/window/gl_js.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package window
-
-import (
- "errors"
- "syscall/js"
-
- "gioui.org/app/internal/glimpl"
- "gioui.org/app/internal/srgb"
- "gioui.org/gpu/backend"
- "gioui.org/gpu/gl"
-)
-
-type context struct {
- ctx js.Value
- cnv js.Value
- f *glimpl.Functions
- srgbFBO *srgb.FBO
-}
-
-func newContext(w *window) (*context, error) {
- args := map[string]interface{}{
- // Enable low latency rendering.
- // See https://developers.google.com/web/updates/2019/05/desynchronized.
- "desynchronized": true,
- "preserveDrawingBuffer": true,
- }
- version := 2
- ctx := w.cnv.Call("getContext", "webgl2", args)
- if ctx.IsNull() {
- version = 1
- ctx = w.cnv.Call("getContext", "webgl", args)
- }
- if ctx.IsNull() {
- return nil, errors.New("app: webgl is not supported")
- }
- f := &glimpl.Functions{Ctx: ctx}
- if err := f.Init(version); err != nil {
- return nil, err
- }
- c := &context{
- ctx: ctx,
- cnv: w.cnv,
- f: f,
- }
- return c, nil
-}
-
-func (c *context) Backend() (backend.Device, error) {
- return gl.NewBackend(c.f)
-}
-
-func (c *context) Release() {
- if c.srgbFBO != nil {
- c.srgbFBO.Release()
- c.srgbFBO = nil
- }
-}
-
-func (c *context) Present() error {
- if c.srgbFBO != nil {
- c.srgbFBO.Blit()
- }
- if c.srgbFBO != nil {
- c.srgbFBO.AfterPresent()
- }
- if c.ctx.Call("isContextLost").Bool() {
- return errors.New("context lost")
- }
- return nil
-}
-
-func (c *context) Lock() {}
-
-func (c *context) Unlock() {}
-
-func (c *context) MakeCurrent() error {
- if c.srgbFBO == nil {
- var err error
- c.srgbFBO, err = srgb.New(c.f)
- if err != nil {
- c.Release()
- c.srgbFBO = nil
- return err
- }
- }
- w, h := c.cnv.Get("width").Int(), c.cnv.Get("height").Int()
- if err := c.srgbFBO.Refresh(w, h); err != nil {
- c.Release()
- return err
- }
- return nil
-}
-
-func (w *window) NewContext() (Context, error) {
- return newContext(w)
-}
diff --git a/vendor/gioui.org/app/internal/window/gl_macos.go b/vendor/gioui.org/app/internal/window/gl_macos.go
deleted file mode 100644
index e4e293d..0000000
--- a/vendor/gioui.org/app/internal/window/gl_macos.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build darwin,!ios
-
-package window
-
-import (
- "gioui.org/app/internal/glimpl"
- "gioui.org/gpu/backend"
- "gioui.org/gpu/gl"
-)
-
-/*
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreGraphics/CoreGraphics.h>
-#include <AppKit/AppKit.h>
-#include <OpenGL/gl3.h>
-
-__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLView(void);
-__attribute__ ((visibility ("hidden"))) CFTypeRef gio_contextForView(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx);
-__attribute__ ((visibility ("hidden"))) void gio_flushContextBuffer(CFTypeRef ctx);
-__attribute__ ((visibility ("hidden"))) void gio_clearCurrentContext(void);
-__attribute__ ((visibility ("hidden"))) void gio_lockContext(CFTypeRef ctxRef);
-__attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef);
-*/
-import "C"
-
-type context struct {
- c *glimpl.Functions
- ctx C.CFTypeRef
- view C.CFTypeRef
-}
-
-func init() {
- viewFactory = func() C.CFTypeRef {
- return C.gio_createGLView()
- }
-}
-
-func newContext(w *window) (*context, error) {
- view := w.contextView()
- ctx := C.gio_contextForView(view)
- c := &context{
- ctx: ctx,
- c: new(glimpl.Functions),
- view: view,
- }
- return c, nil
-}
-
-func (c *context) Backend() (backend.Device, error) {
- return gl.NewBackend(c.c)
-}
-
-func (c *context) Release() {
- c.Lock()
- defer c.Unlock()
- C.gio_clearCurrentContext()
- // We could release the context with [view clearGLContext]
- // and rely on [view openGLContext] auto-creating a new context.
- // However that second context is not properly set up by
- // OpenGLContextView, so we'll stay on the safe side and keep
- // the first context around.
-}
-
-func (c *context) Present() error {
- // Assume the caller already locked the context.
- C.glFlush()
- return nil
-}
-
-func (c *context) Lock() {
- C.gio_lockContext(c.ctx)
-}
-
-func (c *context) Unlock() {
- C.gio_unlockContext(c.ctx)
-}
-
-func (c *context) MakeCurrent() error {
- c.Lock()
- defer c.Unlock()
- C.gio_makeCurrentContext(c.ctx)
- return nil
-}
-
-func (w *window) NewContext() (Context, error) {
- return newContext(w)
-}
diff --git a/vendor/gioui.org/app/internal/window/gl_macos.m b/vendor/gioui.org/app/internal/window/gl_macos.m
deleted file mode 100644
index 0d7f772..0000000
--- a/vendor/gioui.org/app/internal/window/gl_macos.m
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build darwin,!ios
-
-@import AppKit;
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <OpenGL/OpenGL.h>
-#include <OpenGL/gl3.h>
-#include "_cgo_export.h"
-
-static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFloat dy) {
- NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
- if (!event.hasPreciseScrollingDeltas) {
- // dx and dy are in rows and columns.
- dx *= 10;
- dy *= 10;
- }
- gio_onMouse((__bridge CFTypeRef)view, typ, [NSEvent pressedMouseButtons], p.x, p.y, dx, dy, [event timestamp], [event modifierFlags]);
-}
-
-@interface GioView : NSOpenGLView
-@end
-
-@implementation GioView
-- (instancetype)initWithFrame:(NSRect)frameRect
- pixelFormat:(NSOpenGLPixelFormat *)format {
- return [super initWithFrame:frameRect pixelFormat:format];
-}
-- (void)prepareOpenGL {
- [super prepareOpenGL];
- // Bind a default VBA to emulate OpenGL ES 2.
- GLuint defVBA;
- glGenVertexArrays(1, &defVBA);
- glBindVertexArray(defVBA);
- glEnable(GL_FRAMEBUFFER_SRGB);
-}
-- (BOOL)isFlipped {
- return YES;
-}
-- (void)update {
- [super update];
- [self setNeedsDisplay:YES];
-}
-- (void)drawRect:(NSRect)r {
- gio_onDraw((__bridge CFTypeRef)self);
-}
-- (void)mouseDown:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
-}
-- (void)mouseUp:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
-}
-- (void)middleMouseDown:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
-}
-- (void)middletMouseUp:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
-}
-- (void)rightMouseDown:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
-}
-- (void)rightMouseUp:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
-}
-- (void)mouseMoved:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
-}
-- (void)mouseDragged:(NSEvent *)event {
- handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
-}
-- (void)scrollWheel:(NSEvent *)event {
- CGFloat dx = -event.scrollingDeltaX;
- CGFloat dy = -event.scrollingDeltaY;
- handleMouse(self, event, GIO_MOUSE_SCROLL, dx, dy);
-}
-- (void)keyDown:(NSEvent *)event {
- NSString *keys = [event charactersIgnoringModifiers];
- gio_onKeys((__bridge CFTypeRef)self, (char *)[keys UTF8String], [event timestamp], [event modifierFlags]);
- [self interpretKeyEvents:[NSArray arrayWithObject:event]];
-}
-- (void)insertText:(id)string {
- const char *utf8 = [string UTF8String];
- gio_onText((__bridge CFTypeRef)self, (char *)utf8);
-}
-- (void)doCommandBySelector:(SEL)sel {
- // Don't pass commands up the responder chain.
- // They will end up in a beep.
-}
-@end
-
-CFTypeRef gio_createGLView(void) {
- @autoreleasepool {
- NSOpenGLPixelFormatAttribute attr[] = {
- NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
- NSOpenGLPFAColorSize, 24,
- NSOpenGLPFADepthSize, 16,
- NSOpenGLPFAAccelerated,
- // Opt-in to automatic GPU switching. CGL-only property.
- kCGLPFASupportsAutomaticGraphicsSwitching,
- NSOpenGLPFAAllowOfflineRenderers,
- 0
- };
- id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
-
- NSRect frame = NSMakeRect(0, 0, 0, 0);
- GioView* view = [[GioView alloc] initWithFrame:frame pixelFormat:pixFormat];
-
- [view setWantsBestResolutionOpenGLSurface:YES];
- [view setWantsLayer:YES]; // The default in Mojave.
-
- return CFBridgingRetain(view);
- }
-}
-
-void gio_setNeedsDisplay(CFTypeRef viewRef) {
- NSOpenGLView *view = (__bridge NSOpenGLView *)viewRef;
- [view setNeedsDisplay:YES];
-}
-
-CFTypeRef gio_contextForView(CFTypeRef viewRef) {
- NSOpenGLView *view = (__bridge NSOpenGLView *)viewRef;
- return (__bridge CFTypeRef)view.openGLContext;
-}
-
-void gio_clearCurrentContext(void) {
- [NSOpenGLContext clearCurrentContext];
-}
-
-void gio_makeCurrentContext(CFTypeRef ctxRef) {
- NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
- [ctx makeCurrentContext];
-}
-
-void gio_lockContext(CFTypeRef ctxRef) {
- NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
- CGLLockContext([ctx CGLContextObj]);
-}
-
-void gio_unlockContext(CFTypeRef ctxRef) {
- NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
- CGLUnlockContext([ctx CGLContextObj]);
-}
diff --git a/vendor/gioui.org/app/internal/window/os_android.c b/vendor/gioui.org/app/internal/window/os_android.c
deleted file mode 100644
index 8a2c62d..0000000
--- a/vendor/gioui.org/app/internal/window/os_android.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-#include <jni.h>
-#include "_cgo_export.h"
-
-jint gio_jni_GetEnv(JavaVM *vm, JNIEnv **env, jint version) {
- return (*vm)->GetEnv(vm, (void **)env, version);
-}
-
-jint gio_jni_GetJavaVM(JNIEnv *env, JavaVM **jvm) {
- return (*env)->GetJavaVM(env, jvm);
-}
-
-jint gio_jni_AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) {
- return (*vm)->AttachCurrentThread(vm, p_env, thr_args);
-}
-
-jint gio_jni_DetachCurrentThread(JavaVM *vm) {
- return (*vm)->DetachCurrentThread(vm);
-}
-
-jobject gio_jni_NewGlobalRef(JNIEnv *env, jobject obj) {
- return (*env)->NewGlobalRef(env, obj);
-}
-
-void gio_jni_DeleteGlobalRef(JNIEnv *env, jobject obj) {
- (*env)->DeleteGlobalRef(env, obj);
-}
-
-jclass gio_jni_GetObjectClass(JNIEnv *env, jobject obj) {
- return (*env)->GetObjectClass(env, obj);
-}
-
-jmethodID gio_jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
- return (*env)->GetMethodID(env, clazz, name, sig);
-}
-
-jmethodID gio_jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
- return (*env)->GetStaticMethodID(env, clazz, name, sig);
-}
-
-jfloat gio_jni_CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID) {
- return (*env)->CallFloatMethod(env, obj, methodID);
-}
-
-jint gio_jni_CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID) {
- return (*env)->CallIntMethod(env, obj, methodID);
-}
-
-void gio_jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args) {
- (*env)->CallStaticVoidMethodA(env, cls, methodID, args);
-}
-
-void gio_jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args) {
- (*env)->CallVoidMethodA(env, obj, methodID, args);
-}
-
-jbyte *gio_jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr) {
- return (*env)->GetByteArrayElements(env, arr, NULL);
-}
-
-void gio_jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *bytes) {
- (*env)->ReleaseByteArrayElements(env, arr, bytes, JNI_ABORT);
-}
-
-jsize gio_jni_GetArrayLength(JNIEnv *env, jbyteArray arr) {
- return (*env)->GetArrayLength(env, arr);
-}
-
-jstring gio_jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len) {
- return (*env)->NewString(env, unicodeChars, len);
-}
-
-jsize gio_jni_GetStringLength(JNIEnv *env, jstring str) {
- return (*env)->GetStringLength(env, str);
-}
-
-const jchar *gio_jni_GetStringChars(JNIEnv *env, jstring str) {
- return (*env)->GetStringChars(env, str, NULL);
-}
-
-jthrowable gio_jni_ExceptionOccurred(JNIEnv *env) {
- return (*env)->ExceptionOccurred(env);
-}
-
-void gio_jni_ExceptionClear(JNIEnv *env) {
- (*env)->ExceptionClear(env);
-}
-
-jobject gio_jni_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args) {
- return (*env)->CallObjectMethodA(env, obj, method, args);
-}
-
-jobject gio_jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) {
- return (*env)->CallStaticObjectMethodA(env, cls, method, args);
-}
diff --git a/vendor/gioui.org/app/internal/window/os_android.go b/vendor/gioui.org/app/internal/window/os_android.go
deleted file mode 100644
index 3458b26..0000000
--- a/vendor/gioui.org/app/internal/window/os_android.go
+++ /dev/null
@@ -1,684 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package window
-
-/*
-#cgo CFLAGS: -Werror
-#cgo LDFLAGS: -landroid
-
-#include <android/native_window_jni.h>
-#include <android/configuration.h>
-#include <android/keycodes.h>
-#include <android/input.h>
-#include <stdlib.h>
-
-__attribute__ ((visibility ("hidden"))) jint gio_jni_GetEnv(JavaVM *vm, JNIEnv **env, jint version);
-__attribute__ ((visibility ("hidden"))) jint gio_jni_GetJavaVM(JNIEnv *env, JavaVM **jvm);
-__attribute__ ((visibility ("hidden"))) jint gio_jni_AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args);
-__attribute__ ((visibility ("hidden"))) jint gio_jni_DetachCurrentThread(JavaVM *vm);
-
-__attribute__ ((visibility ("hidden"))) jobject gio_jni_NewGlobalRef(JNIEnv *env, jobject obj);
-__attribute__ ((visibility ("hidden"))) void gio_jni_DeleteGlobalRef(JNIEnv *env, jobject obj);
-__attribute__ ((visibility ("hidden"))) jclass gio_jni_GetObjectClass(JNIEnv *env, jobject obj);
-__attribute__ ((visibility ("hidden"))) jmethodID gio_jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
-__attribute__ ((visibility ("hidden"))) jmethodID gio_jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
-__attribute__ ((visibility ("hidden"))) jfloat gio_jni_CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID);
-__attribute__ ((visibility ("hidden"))) jint gio_jni_CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID);
-__attribute__ ((visibility ("hidden"))) void gio_jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args);
-__attribute__ ((visibility ("hidden"))) void gio_jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
-__attribute__ ((visibility ("hidden"))) jbyte *gio_jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr);
-__attribute__ ((visibility ("hidden"))) void gio_jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *bytes);
-__attribute__ ((visibility ("hidden"))) jsize gio_jni_GetArrayLength(JNIEnv *env, jbyteArray arr);
-__attribute__ ((visibility ("hidden"))) jstring gio_jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len);
-__attribute__ ((visibility ("hidden"))) jsize gio_jni_GetStringLength(JNIEnv *env, jstring str);
-__attribute__ ((visibility ("hidden"))) const jchar *gio_jni_GetStringChars(JNIEnv *env, jstring str);
-__attribute__ ((visibility ("hidden"))) jthrowable gio_jni_ExceptionOccurred(JNIEnv *env);
-__attribute__ ((visibility ("hidden"))) void gio_jni_ExceptionClear(JNIEnv *env);
-__attribute__ ((visibility ("hidden"))) jobject gio_jni_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args);
-__attribute__ ((visibility ("hidden"))) jobject gio_jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args);
-*/
-import "C"
-
-import (
- "errors"
- "fmt"
- "image"
- "reflect"
- "runtime"
- "runtime/debug"
- "sync"
- "time"
- "unicode/utf16"
- "unsafe"
-
- "gioui.org/f32"
- "gioui.org/io/key"
- "gioui.org/io/pointer"
- "gioui.org/io/system"
- "gioui.org/unit"
-)
-
-type window struct {
- callbacks Callbacks
-
- view C.jobject
-
- dpi int
- fontScale float32
- insets system.Insets
-
- stage system.Stage
- started bool
-
- mu sync.Mutex
- win *C.ANativeWindow
- animating bool
-
- // Cached Java methods.
- mgetDensity C.jmethodID
- mgetFontScale C.jmethodID
- mshowTextInput C.jmethodID
- mhideTextInput C.jmethodID
- mpostFrameCallback C.jmethodID
-}
-
-type jvalue uint64 // The largest JNI type fits in 64 bits.
-
-var dataDirChan = make(chan string, 1)
-
-var android struct {
- // mu protects all fields of this structure. However, once a
- // non-nil jvm is returned from javaVM, all the other fields may
- // be accessed unlocked.
- mu sync.Mutex
- jvm *C.JavaVM
-
- // appCtx is the global Android App context.
- appCtx C.jobject
- // gioCls is the class of the Gio class.
- gioCls C.jclass
-
- mwriteClipboard C.jmethodID
- mreadClipboard C.jmethodID
- mwakeupMainThread C.jmethodID
-}
-
-var views = make(map[C.jlong]*window)
-
-var mainWindow = newWindowRendezvous()
-
-var mainFuncs = make(chan func(env *C.JNIEnv), 1)
-
-func getMethodID(env *C.JNIEnv, class C.jclass, method, sig string) C.jmethodID {
- m := C.CString(method)
- defer C.free(unsafe.Pointer(m))
- s := C.CString(sig)
- defer C.free(unsafe.Pointer(s))
- jm := C.gio_jni_GetMethodID(env, class, m, s)
- if err := exception(env); err != nil {
- panic(err)
- }
- return jm
-}
-
-func getStaticMethodID(env *C.JNIEnv, class C.jclass, method, sig string) C.jmethodID {
- m := C.CString(method)
- defer C.free(unsafe.Pointer(m))
- s := C.CString(sig)
- defer C.free(unsafe.Pointer(s))
- jm := C.gio_jni_GetStaticMethodID(env, class, m, s)
- if err := exception(env); err != nil {
- panic(err)
- }
- return jm
-}
-
-//export Java_org_gioui_Gio_runGoMain
-func Java_org_gioui_Gio_runGoMain(env *C.JNIEnv, class C.jclass, jdataDir C.jbyteArray, context C.jobject) {
- initJVM(env, class, context)
- dirBytes := C.gio_jni_GetByteArrayElements(env, jdataDir)
- if dirBytes == nil {
- panic("runGoMain: GetByteArrayElements failed")
- }
- n := C.gio_jni_GetArrayLength(env, jdataDir)
- dataDir := C.GoStringN((*C.char)(unsafe.Pointer(dirBytes)), n)
- dataDirChan <- dataDir
- C.gio_jni_ReleaseByteArrayElements(env, jdataDir, dirBytes)
-
- runMain()
-}
-
-func initJVM(env *C.JNIEnv, gio C.jclass, ctx C.jobject) {
- android.mu.Lock()
- defer android.mu.Unlock()
- if res := C.gio_jni_GetJavaVM(env, &android.jvm); res != 0 {
- panic("gio: GetJavaVM failed")
- }
- android.appCtx = C.gio_jni_NewGlobalRef(env, ctx)
- android.gioCls = C.jclass(C.gio_jni_NewGlobalRef(env, C.jobject(gio)))
- android.mwriteClipboard = getStaticMethodID(env, gio, "writeClipboard", "(Landroid/content/Context;Ljava/lang/String;)V")
- android.mreadClipboard = getStaticMethodID(env, gio, "readClipboard", "(Landroid/content/Context;)Ljava/lang/String;")
- android.mwakeupMainThread = getStaticMethodID(env, gio, "wakeupMainThread", "()V")
-}
-
-func JavaVM() uintptr {
- jvm := javaVM()
- return uintptr(unsafe.Pointer(jvm))
-}
-
-func javaVM() *C.JavaVM {
- android.mu.Lock()
- defer android.mu.Unlock()
- return android.jvm
-}
-
-func AppContext() uintptr {
- android.mu.Lock()
- defer android.mu.Unlock()
- return uintptr(android.appCtx)
-}
-
-func GetDataDir() string {
- return <-dataDirChan
-}
-
-//export Java_org_gioui_GioView_onCreateView
-func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.jobject) C.jlong {
- view = C.gio_jni_NewGlobalRef(env, view)
- w := &window{
- view: view,
- mgetDensity: getMethodID(env, class, "getDensity", "()I"),
- mgetFontScale: getMethodID(env, class, "getFontScale", "()F"),
- mshowTextInput: getMethodID(env, class, "showTextInput", "()V"),
- mhideTextInput: getMethodID(env, class, "hideTextInput", "()V"),
- mpostFrameCallback: getMethodID(env, class, "postFrameCallback", "()V"),
- }
- wopts := <-mainWindow.out
- w.callbacks = wopts.window
- w.callbacks.SetDriver(w)
- handle := C.jlong(view)
- views[handle] = w
- w.loadConfig(env, class)
- w.setStage(system.StagePaused)
- return handle
-}
-
-//export Java_org_gioui_GioView_onDestroyView
-func Java_org_gioui_GioView_onDestroyView(env *C.JNIEnv, class C.jclass, handle C.jlong) {
- w := views[handle]
- w.callbacks.SetDriver(nil)
- delete(views, handle)
- C.gio_jni_DeleteGlobalRef(env, w.view)
- w.view = 0
-}
-
-//export Java_org_gioui_GioView_onStopView
-func Java_org_gioui_GioView_onStopView(env *C.JNIEnv, class C.jclass, handle C.jlong) {
- w := views[handle]
- w.started = false
- w.setStage(system.StagePaused)
-}
-
-//export Java_org_gioui_GioView_onStartView
-func Java_org_gioui_GioView_onStartView(env *C.JNIEnv, class C.jclass, handle C.jlong) {
- w := views[handle]
- w.started = true
- if w.aNativeWindow() != nil {
- w.setVisible()
- }
-}
-
-//export Java_org_gioui_GioView_onSurfaceDestroyed
-func Java_org_gioui_GioView_onSurfaceDestroyed(env *C.JNIEnv, class C.jclass, handle C.jlong) {
- w := views[handle]
- w.mu.Lock()
- w.win = nil
- w.mu.Unlock()
- w.setStage(system.StagePaused)
-}
-
-//export Java_org_gioui_GioView_onSurfaceChanged
-func Java_org_gioui_GioView_onSurfaceChanged(env *C.JNIEnv, class C.jclass, handle C.jlong, surf C.jobject) {
- w := views[handle]
- w.mu.Lock()
- w.win = C.ANativeWindow_fromSurface(env, surf)
- w.mu.Unlock()
- if w.started {
- w.setVisible()
- }
-}
-
-//export Java_org_gioui_GioView_onLowMemory
-func Java_org_gioui_GioView_onLowMemory() {
- runtime.GC()
- debug.FreeOSMemory()
-}
-
-//export Java_org_gioui_GioView_onConfigurationChanged
-func Java_org_gioui_GioView_onConfigurationChanged(env *C.JNIEnv, class C.jclass, view C.jlong) {
- w := views[view]
- w.loadConfig(env, class)
- if w.stage >= system.StageRunning {
- w.draw(true)
- }
-}
-
-//export Java_org_gioui_GioView_onFrameCallback
-func Java_org_gioui_GioView_onFrameCallback(env *C.JNIEnv, class C.jclass, view C.jlong, nanos C.jlong) {
- w, exist := views[view]
- if !exist {
- return
- }
- if w.stage < system.StageRunning {
- return
- }
- w.mu.Lock()
- anim := w.animating
- w.mu.Unlock()
- if anim {
- runInJVM(javaVM(), func(env *C.JNIEnv) {
- callVoidMethod(env, w.view, w.mpostFrameCallback)
- })
- w.draw(false)
- }
-}
-
-//export Java_org_gioui_GioView_onBack
-func Java_org_gioui_GioView_onBack(env *C.JNIEnv, class C.jclass, view C.jlong) C.jboolean {
- w := views[view]
- ev := &system.CommandEvent{Type: system.CommandBack}
- w.callbacks.Event(ev)
- if ev.Cancel {
- return C.JNI_TRUE
- }
- return C.JNI_FALSE
-}
-
-//export Java_org_gioui_GioView_onFocusChange
-func Java_org_gioui_GioView_onFocusChange(env *C.JNIEnv, class C.jclass, view C.jlong, focus C.jboolean) {
- w := views[view]
- w.callbacks.Event(key.FocusEvent{Focus: focus == C.JNI_TRUE})
-}
-
-//export Java_org_gioui_GioView_onWindowInsets
-func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C.jlong, top, right, bottom, left C.jint) {
- w := views[view]
- w.insets = system.Insets{
- Top: unit.Px(float32(top)),
- Right: unit.Px(float32(right)),
- Bottom: unit.Px(float32(bottom)),
- Left: unit.Px(float32(left)),
- }
- if w.stage >= system.StageRunning {
- w.draw(true)
- }
-}
-
-func (w *window) setVisible() {
- win := w.aNativeWindow()
- width, height := C.ANativeWindow_getWidth(win), C.ANativeWindow_getHeight(win)
- if width == 0 || height == 0 {
- return
- }
- w.setStage(system.StageRunning)
- w.draw(true)
-}
-
-func (w *window) setStage(stage system.Stage) {
- if stage == w.stage {
- return
- }
- w.stage = stage
- w.callbacks.Event(system.StageEvent{stage})
-}
-
-func (w *window) nativeWindow(visID int) (*C.ANativeWindow, int, int) {
- win := w.aNativeWindow()
- var width, height int
- if win != nil {
- if C.ANativeWindow_setBuffersGeometry(win, 0, 0, C.int32_t(visID)) != 0 {
- panic(errors.New("ANativeWindow_setBuffersGeometry failed"))
- }
- w, h := C.ANativeWindow_getWidth(win), C.ANativeWindow_getHeight(win)
- width, height = int(w), int(h)
- }
- return win, width, height
-}
-
-func (w *window) aNativeWindow() *C.ANativeWindow {
- w.mu.Lock()
- defer w.mu.Unlock()
- return w.win
-}
-
-func (w *window) loadConfig(env *C.JNIEnv, class C.jclass) {
- dpi := int(C.gio_jni_CallIntMethod(env, w.view, w.mgetDensity))
- w.fontScale = float32(C.gio_jni_CallFloatMethod(env, w.view, w.mgetFontScale))
- switch dpi {
- case C.ACONFIGURATION_DENSITY_NONE,
- C.ACONFIGURATION_DENSITY_DEFAULT,
- C.ACONFIGURATION_DENSITY_ANY:
- // Assume standard density.
- w.dpi = C.ACONFIGURATION_DENSITY_MEDIUM
- default:
- w.dpi = int(dpi)
- }
-}
-
-func (w *window) SetAnimating(anim bool) {
- w.mu.Lock()
- w.animating = anim
- w.mu.Unlock()
- if anim {
- runOnMain(func(env *C.JNIEnv) {
- if w.view == 0 {
- // View was destroyed while switching to main thread.
- return
- }
- callVoidMethod(env, w.view, w.mpostFrameCallback)
- })
- }
-}
-
-func (w *window) draw(sync bool) {
- win := w.aNativeWindow()
- width, height := C.ANativeWindow_getWidth(win), C.ANativeWindow_getHeight(win)
- if width == 0 || height == 0 {
- return
- }
- const inchPrDp = 1.0 / 160
- ppdp := float32(w.dpi) * inchPrDp
- w.callbacks.Event(FrameEvent{
- FrameEvent: system.FrameEvent{
- Now: time.Now(),
- Size: image.Point{
- X: int(width),
- Y: int(height),
- },
- Insets: w.insets,
- Metric: unit.Metric{
- PxPerDp: ppdp,
- PxPerSp: w.fontScale * ppdp,
- },
- },
- Sync: sync,
- })
-}
-
-type keyMapper func(devId, keyCode C.int32_t) rune
-
-func runInJVM(jvm *C.JavaVM, f func(env *C.JNIEnv)) {
- if jvm == nil {
- panic("nil JVM")
- }
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
- var env *C.JNIEnv
- if res := C.gio_jni_GetEnv(jvm, &env, C.JNI_VERSION_1_6); res != C.JNI_OK {
- if res != C.JNI_EDETACHED {
- panic(fmt.Errorf("JNI GetEnv failed with error %d", res))
- }
- if C.gio_jni_AttachCurrentThread(jvm, &env, nil) != C.JNI_OK {
- panic(errors.New("runInJVM: AttachCurrentThread failed"))
- }
- defer C.gio_jni_DetachCurrentThread(jvm)
- }
-
- f(env)
-}
-
-func convertKeyCode(code C.jint) (string, bool) {
- var n string
- switch code {
- case C.AKEYCODE_DPAD_UP:
- n = key.NameUpArrow
- case C.AKEYCODE_DPAD_DOWN:
- n = key.NameDownArrow
- case C.AKEYCODE_DPAD_LEFT:
- n = key.NameLeftArrow
- case C.AKEYCODE_DPAD_RIGHT:
- n = key.NameRightArrow
- case C.AKEYCODE_FORWARD_DEL:
- n = key.NameDeleteForward
- case C.AKEYCODE_DEL:
- n = key.NameDeleteBackward
- default:
- return "", false
- }
- return n, true
-}
-
-//export Java_org_gioui_GioView_onKeyEvent
-func Java_org_gioui_GioView_onKeyEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, keyCode, r C.jint, t C.jlong) {
- w := views[handle]
- if n, ok := convertKeyCode(keyCode); ok {
- w.callbacks.Event(key.Event{Name: n})
- }
- if r != 0 {
- w.callbacks.Event(key.EditEvent{Text: string(rune(r))})
- }
-}
-
-//export Java_org_gioui_GioView_onTouchEvent
-func Java_org_gioui_GioView_onTouchEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, action, pointerID, tool C.jint, x, y, scrollX, scrollY C.jfloat, jbtns C.jint, t C.jlong) {
- w := views[handle]
- var typ pointer.Type
- switch action {
- case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN:
- typ = pointer.Press
- case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP:
- typ = pointer.Release
- case C.AMOTION_EVENT_ACTION_CANCEL:
- typ = pointer.Cancel
- case C.AMOTION_EVENT_ACTION_MOVE:
- typ = pointer.Move
- case C.AMOTION_EVENT_ACTION_SCROLL:
- typ = pointer.Scroll
- default:
- return
- }
- var src pointer.Source
- var btns pointer.Buttons
- if jbtns&C.AMOTION_EVENT_BUTTON_PRIMARY != 0 {
- btns |= pointer.ButtonLeft
- }
- if jbtns&C.AMOTION_EVENT_BUTTON_SECONDARY != 0 {
- btns |= pointer.ButtonRight
- }
- if jbtns&C.AMOTION_EVENT_BUTTON_TERTIARY != 0 {
- btns |= pointer.ButtonMiddle
- }
- switch tool {
- case C.AMOTION_EVENT_TOOL_TYPE_FINGER:
- src = pointer.Touch
- case C.AMOTION_EVENT_TOOL_TYPE_MOUSE:
- src = pointer.Mouse
- case C.AMOTION_EVENT_TOOL_TYPE_UNKNOWN:
- // For example, triggered via 'adb shell input tap'.
- // Instead of discarding it, treat it as a touch event.
- src = pointer.Touch
- default:
- return
- }
- w.callbacks.Event(pointer.Event{
- Type: typ,
- Source: src,
- Buttons: btns,
- PointerID: pointer.ID(pointerID),
- Time: time.Duration(t) * time.Millisecond,
- Position: f32.Point{X: float32(x), Y: float32(y)},
- Scroll: f32.Pt(float32(scrollX), float32(scrollY)),
- })
-}
-
-func (w *window) ShowTextInput(show bool) {
- if w.view == 0 {
- return
- }
- runInJVM(javaVM(), func(env *C.JNIEnv) {
- if show {
- callVoidMethod(env, w.view, w.mshowTextInput)
- } else {
- callVoidMethod(env, w.view, w.mhideTextInput)
- }
- })
-}
-
-func javaString(env *C.JNIEnv, str string) C.jstring {
- if str == "" {
- return 0
- }
- utf16Chars := utf16.Encode([]rune(str))
- return C.gio_jni_NewString(env, (*C.jchar)(unsafe.Pointer(&utf16Chars[0])), C.int(len(utf16Chars)))
-}
-
-// Do invokes the function with a global JNI handle to the view. If
-// the view is destroyed, Do returns false and does not invoke the
-// function.
-//
-// NOTE: Do must be invoked on the Android main thread.
-func (w *window) Do(f func(view uintptr)) bool {
- if w.view == 0 {
- return false
- }
- runInJVM(javaVM(), func(env *C.JNIEnv) {
- view := C.gio_jni_NewGlobalRef(env, w.view)
- defer C.gio_jni_DeleteGlobalRef(env, view)
- f(uintptr(view))
- })
- return true
-}
-
-func varArgs(args []jvalue) *C.jvalue {
- if len(args) == 0 {
- return nil
- }
- return (*C.jvalue)(unsafe.Pointer(&args[0]))
-}
-
-func callStaticVoidMethod(env *C.JNIEnv, cls C.jclass, method C.jmethodID, args ...jvalue) error {
- C.gio_jni_CallStaticVoidMethodA(env, cls, method, varArgs(args))
- return exception(env)
-}
-
-func callStaticObjectMethod(env *C.JNIEnv, cls C.jclass, method C.jmethodID, args ...jvalue) (C.jobject, error) {
- res := C.gio_jni_CallStaticObjectMethodA(env, cls, method, varArgs(args))
- return res, exception(env)
-}
-
-func callVoidMethod(env *C.JNIEnv, obj C.jobject, method C.jmethodID, args ...jvalue) error {
- C.gio_jni_CallVoidMethodA(env, obj, method, varArgs(args))
- return exception(env)
-}
-
-func callObjectMethod(env *C.JNIEnv, obj C.jobject, method C.jmethodID, args ...jvalue) (C.jobject, error) {
- res := C.gio_jni_CallObjectMethodA(env, obj, method, varArgs(args))
- return res, exception(env)
-}
-
-// exception returns an error corresponding to the pending
-// exception, or nil if no exception is pending. The pending
-// exception is cleared.
-func exception(env *C.JNIEnv) error {
- thr := C.gio_jni_ExceptionOccurred(env)
- if thr == 0 {
- return nil
- }
- C.gio_jni_ExceptionClear(env)
- cls := getObjectClass(env, C.jobject(thr))
- toString := getMethodID(env, cls, "toString", "()Ljava/lang/String;")
- msg, err := callObjectMethod(env, C.jobject(thr), toString)
- if err != nil {
- return err
- }
- return errors.New(goString(env, C.jstring(msg)))
-}
-
-func getObjectClass(env *C.JNIEnv, obj C.jobject) C.jclass {
- if obj == 0 {
- panic("null object")
- }
- cls := C.gio_jni_GetObjectClass(env, C.jobject(obj))
- if err := exception(env); err != nil {
- // GetObjectClass should never fail.
- panic(err)
- }
- return cls
-}
-
-// goString converts the JVM jstring to a Go string.
-func goString(env *C.JNIEnv, str C.jstring) string {
- if str == 0 {
- return ""
- }
- strlen := C.gio_jni_GetStringLength(env, C.jstring(str))
- chars := C.gio_jni_GetStringChars(env, C.jstring(str))
- var utf16Chars []uint16
- hdr := (*reflect.SliceHeader)(unsafe.Pointer(&utf16Chars))
- hdr.Data = uintptr(unsafe.Pointer(chars))
- hdr.Cap = int(strlen)
- hdr.Len = int(strlen)
- utf8 := utf16.Decode(utf16Chars)
- return string(utf8)
-}
-
-func Main() {
-}
-
-func NewWindow(window Callbacks, opts *Options) error {
- mainWindow.in <- windowAndOptions{window, opts}
- return <-mainWindow.errs
-}
-
-func (w *window) WriteClipboard(s string) {
- runOnMain(func(env *C.JNIEnv) {
- jstr := javaString(env, s)
- callStaticVoidMethod(env, android.gioCls, android.mwriteClipboard,
- jvalue(android.appCtx), jvalue(jstr))
- })
-}
-
-func (w *window) ReadClipboard() {
- runOnMain(func(env *C.JNIEnv) {
- c, err := callStaticObjectMethod(env, android.gioCls, android.mreadClipboard,
- jvalue(android.appCtx))
- if err != nil {
- return
- }
- content := goString(env, C.jstring(c))
- w.callbacks.Event(system.ClipboardEvent{Text: content})
- })
-}
-
-// Close the window. Not implemented for Android.
-func (w *window) Close() {}
-
-// RunOnMain is the exported version of runOnMain without a JNI
-// environement.
-func RunOnMain(f func()) {
- runOnMain(func(_ *C.JNIEnv) {
- f()
- })
-}
-
-// runOnMain runs a function on the Java main thread.
-func runOnMain(f func(env *C.JNIEnv)) {
- go func() {
- mainFuncs <- f
- runInJVM(javaVM(), func(env *C.JNIEnv) {
- callStaticVoidMethod(env, android.gioCls, android.mwakeupMainThread)
- })
- }()
-}
-
-//export Java_org_gioui_Gio_scheduleMainFuncs
-func Java_org_gioui_Gio_scheduleMainFuncs(env *C.JNIEnv, cls C.jclass) {
- for {
- select {
- case f := <-mainFuncs:
- f(env)
- default:
- return
- }
- }
-}
diff --git a/vendor/gioui.org/app/internal/window/os_darwin.m b/vendor/gioui.org/app/internal/window/os_darwin.m
deleted file mode 100644
index dc4f00b..0000000
--- a/vendor/gioui.org/app/internal/window/os_darwin.m
+++ /dev/null
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-@import Dispatch;
-@import Foundation;
-
-#include "_cgo_export.h"
-
-void gio_wakeupMainThread(void) {
- dispatch_async(dispatch_get_main_queue(), ^{
- gio_dispatchMainFuncs();
- });
-}
-
-NSUInteger gio_nsstringLength(CFTypeRef cstr) {
- NSString *str = (__bridge NSString *)cstr;
- return [str length];
-}
-
-void gio_nsstringGetCharacters(CFTypeRef cstr, unichar *chars, NSUInteger loc, NSUInteger length) {
- NSString *str = (__bridge NSString *)cstr;
- [str getCharacters:chars range:NSMakeRange(loc, length)];
-}
diff --git a/vendor/gioui.org/app/internal/window/os_macos.go b/vendor/gioui.org/app/internal/window/os_macos.go
deleted file mode 100644
index ef95b70..0000000
--- a/vendor/gioui.org/app/internal/window/os_macos.go
+++ /dev/null
@@ -1,460 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build darwin,!ios
-
-package window
-
-import (
- "errors"
- "image"
- "runtime"
- "time"
- "unicode"
- "unicode/utf16"
- "unsafe"
-
- "gioui.org/f32"
- "gioui.org/io/key"
- "gioui.org/io/pointer"
- "gioui.org/io/system"
- "gioui.org/unit"
-
- _ "gioui.org/app/internal/cocoainit"
-)
-
-/*
-#cgo CFLAGS: -DGL_SILENCE_DEPRECATION -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c
-
-#include <AppKit/AppKit.h>
-
-#define GIO_MOUSE_MOVE 1
-#define GIO_MOUSE_UP 2
-#define GIO_MOUSE_DOWN 3
-#define GIO_MOUSE_SCROLL 4
-
-__attribute__ ((visibility ("hidden"))) void gio_main(void);
-__attribute__ ((visibility ("hidden"))) CGFloat gio_viewWidth(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) CGFloat gio_viewHeight(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) CGFloat gio_getViewBackingScale(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) CGFloat gio_getScreenBackingScale(void);
-__attribute__ ((visibility ("hidden"))) CFTypeRef gio_readClipboard(void);
-__attribute__ ((visibility ("hidden"))) void gio_writeClipboard(unichar *chars, NSUInteger length);
-__attribute__ ((visibility ("hidden"))) void gio_setNeedsDisplay(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat height, CGFloat minWidth, CGFloat minHeight, CGFloat maxWidth, CGFloat maxHeight);
-__attribute__ ((visibility ("hidden"))) void gio_makeKeyAndOrderFront(CFTypeRef windowRef);
-__attribute__ ((visibility ("hidden"))) NSPoint gio_cascadeTopLeftFromPoint(CFTypeRef windowRef, NSPoint topLeft);
-__attribute__ ((visibility ("hidden"))) void gio_close(CFTypeRef windowRef);
-*/
-import "C"
-
-func init() {
- // Darwin requires that UI operations happen on the main thread only.
- runtime.LockOSThread()
-}
-
-type window struct {
- view C.CFTypeRef
- window C.CFTypeRef
- w Callbacks
- stage system.Stage
- displayLink *displayLink
-
- scale float32
-}
-
-// viewMap is the mapping from Cocoa NSViews to Go windows.
-var viewMap = make(map[C.CFTypeRef]*window)
-
-var viewFactory func() C.CFTypeRef
-
-// launched is closed when applicationDidFinishLaunching is called.
-var launched = make(chan struct{})
-
-// nextTopLeft is the offset to use for the next window's call to
-// cascadeTopLeftFromPoint.
-var nextTopLeft C.NSPoint
-
-// mustView is like lookoupView, except that it panics
-// if the view isn't mapped.
-func mustView(view C.CFTypeRef) *window {
- w, ok := lookupView(view)
- if !ok {
- panic("no window for view")
- }
- return w
-}
-
-func lookupView(view C.CFTypeRef) (*window, bool) {
- w, exists := viewMap[view]
- if !exists {
- return nil, false
- }
- return w, true
-}
-
-func deleteView(view C.CFTypeRef) {
- delete(viewMap, view)
-}
-
-func insertView(view C.CFTypeRef, w *window) {
- viewMap[view] = w
-}
-
-func (w *window) contextView() C.CFTypeRef {
- return w.view
-}
-
-func (w *window) ReadClipboard() {
- runOnMain(func() {
- content := nsstringToString(C.gio_readClipboard())
- w.w.Event(system.ClipboardEvent{Text: content})
- })
-}
-
-func (w *window) WriteClipboard(s string) {
- u16 := utf16.Encode([]rune(s))
- runOnMain(func() {
- var chars *C.unichar
- if len(u16) > 0 {
- chars = (*C.unichar)(unsafe.Pointer(&u16[0]))
- }
- C.gio_writeClipboard(chars, C.NSUInteger(len(u16)))
- })
-}
-
-func (w *window) ShowTextInput(show bool) {}
-
-func (w *window) SetAnimating(anim bool) {
- if anim {
- w.displayLink.Start()
- } else {
- w.displayLink.Stop()
- }
-}
-
-func (w *window) Close() {
- runOnMain(func() {
- // Make sure the view is still valid. The window might've been closed
- // during the switch to the main thread.
- if w.view != 0 {
- C.gio_close(w.window)
- }
- })
-}
-
-func (w *window) setStage(stage system.Stage) {
- if stage == w.stage {
- return
- }
- w.stage = stage
- w.w.Event(system.StageEvent{Stage: stage})
-}
-
-//export gio_onKeys
-func gio_onKeys(view C.CFTypeRef, cstr *C.char, ti C.double, mods C.NSUInteger) {
- str := C.GoString(cstr)
- kmods := convertMods(mods)
- w := mustView(view)
- for _, k := range str {
- if n, ok := convertKey(k); ok {
- w.w.Event(key.Event{
- Name: n,
- Modifiers: kmods,
- })
- }
- }
-}
-
-//export gio_onText
-func gio_onText(view C.CFTypeRef, cstr *C.char) {
- str := C.GoString(cstr)
- w := mustView(view)
- w.w.Event(key.EditEvent{Text: str})
-}
-
-//export gio_onMouse
-func gio_onMouse(view C.CFTypeRef, cdir C.int, cbtns C.NSUInteger, x, y, dx, dy C.CGFloat, ti C.double, mods C.NSUInteger) {
- var typ pointer.Type
- switch cdir {
- case C.GIO_MOUSE_MOVE:
- typ = pointer.Move
- case C.GIO_MOUSE_UP:
- typ = pointer.Release
- case C.GIO_MOUSE_DOWN:
- typ = pointer.Press
- case C.GIO_MOUSE_SCROLL:
- typ = pointer.Scroll
- default:
- panic("invalid direction")
- }
- var btns pointer.Buttons
- if cbtns&(1<<0) != 0 {
- btns |= pointer.ButtonLeft
- }
- if cbtns&(1<<1) != 0 {
- btns |= pointer.ButtonRight
- }
- if cbtns&(1<<2) != 0 {
- btns |= pointer.ButtonMiddle
- }
- t := time.Duration(float64(ti)*float64(time.Second) + .5)
- w := mustView(view)
- xf, yf := float32(x)*w.scale, float32(y)*w.scale
- dxf, dyf := float32(dx)*w.scale, float32(dy)*w.scale
- w.w.Event(pointer.Event{
- Type: typ,
- Source: pointer.Mouse,
- Time: t,
- Buttons: btns,
- Position: f32.Point{X: xf, Y: yf},
- Scroll: f32.Point{X: dxf, Y: dyf},
- Modifiers: convertMods(mods),
- })
-}
-
-//export gio_onDraw
-func gio_onDraw(view C.CFTypeRef) {
- w := mustView(view)
- w.draw()
-}
-
-//export gio_onFocus
-func gio_onFocus(view C.CFTypeRef, focus C.BOOL) {
- w := mustView(view)
- w.w.Event(key.FocusEvent{Focus: focus == C.YES})
-}
-
-//export gio_onChangeScreen
-func gio_onChangeScreen(view C.CFTypeRef, did uint64) {
- w := mustView(view)
- w.displayLink.SetDisplayID(did)
-}
-
-func (w *window) draw() {
- w.scale = float32(C.gio_getViewBackingScale(w.view))
- wf, hf := float32(C.gio_viewWidth(w.view)), float32(C.gio_viewHeight(w.view))
- if wf == 0 || hf == 0 {
- return
- }
- width := int(wf*w.scale + .5)
- height := int(hf*w.scale + .5)
- cfg := configFor(w.scale)
- w.setStage(system.StageRunning)
- w.w.Event(FrameEvent{
- FrameEvent: system.FrameEvent{
- Now: time.Now(),
- Size: image.Point{
- X: width,
- Y: height,
- },
- Metric: cfg,
- },
- Sync: true,
- })
-}
-
-func configFor(scale float32) unit.Metric {
- return unit.Metric{
- PxPerDp: scale,
- PxPerSp: scale,
- }
-}
-
-//export gio_onClose
-func gio_onClose(view C.CFTypeRef) {
- w := mustView(view)
- w.displayLink.Close()
- deleteView(view)
- w.w.Event(system.DestroyEvent{})
- C.CFRelease(w.view)
- w.view = 0
- C.CFRelease(w.window)
- w.window = 0
-}
-
-//export gio_onHide
-func gio_onHide(view C.CFTypeRef) {
- w := mustView(view)
- w.setStage(system.StagePaused)
-}
-
-//export gio_onShow
-func gio_onShow(view C.CFTypeRef) {
- w := mustView(view)
- w.setStage(system.StageRunning)
-}
-
-//export gio_onAppHide
-func gio_onAppHide() {
- for _, w := range viewMap {
- w.setStage(system.StagePaused)
- }
-}
-
-//export gio_onAppShow
-func gio_onAppShow() {
- for _, w := range viewMap {
- w.setStage(system.StageRunning)
- }
-}
-
-//export gio_onFinishLaunching
-func gio_onFinishLaunching() {
- close(launched)
-}
-
-func NewWindow(win Callbacks, opts *Options) error {
- <-launched
- errch := make(chan error)
- runOnMain(func() {
- w, err := newWindow(opts)
- if err != nil {
- errch <- err
- return
- }
- screenScale := float32(C.gio_getScreenBackingScale())
- cfg := configFor(screenScale)
- width := cfg.Px(opts.Width)
- height := cfg.Px(opts.Height)
- // Window sizes is in unscaled screen coordinates, not device pixels.
- width = int(float32(width) / screenScale)
- height = int(float32(height) / screenScale)
- minWidth := cfg.Px(opts.MinWidth)
- minHeight := cfg.Px(opts.MinHeight)
- minWidth = int(float32(minWidth) / screenScale)
- minHeight = int(float32(minHeight) / screenScale)
- maxWidth := cfg.Px(opts.MaxWidth)
- maxHeight := cfg.Px(opts.MaxHeight)
- maxWidth = int(float32(maxWidth) / screenScale)
- maxHeight = int(float32(maxHeight) / screenScale)
- title := C.CString(opts.Title)
- defer C.free(unsafe.Pointer(title))
- errch <- nil
- win.SetDriver(w)
- w.w = win
- w.window = C.gio_createWindow(w.view, title, C.CGFloat(width), C.CGFloat(height),
- C.CGFloat(minWidth), C.CGFloat(minHeight), C.CGFloat(maxWidth), C.CGFloat(maxHeight))
- if nextTopLeft.x == 0 && nextTopLeft.y == 0 {
- // cascadeTopLeftFromPoint treats (0, 0) as a no-op,
- // and just returns the offset we need for the first window.
- nextTopLeft = C.gio_cascadeTopLeftFromPoint(w.window, nextTopLeft)
- }
- nextTopLeft = C.gio_cascadeTopLeftFromPoint(w.window, nextTopLeft)
- C.gio_makeKeyAndOrderFront(w.window)
- })
- return <-errch
-}
-
-func newWindow(opts *Options) (*window, error) {
- view := viewFactory()
- if view == 0 {
- return nil, errors.New("CreateWindow: failed to create view")
- }
- scale := float32(C.gio_getViewBackingScale(view))
- w := &window{
- view: view,
- scale: scale,
- }
- dl, err := NewDisplayLink(func() {
- runOnMain(func() {
- if w.view != 0 {
- C.gio_setNeedsDisplay(w.view)
- }
- })
- })
- w.displayLink = dl
- if err != nil {
- C.CFRelease(view)
- return nil, err
- }
- insertView(view, w)
- return w, nil
-}
-
-func Main() {
- C.gio_main()
-}
-
-func convertKey(k rune) (string, bool) {
- var n string
- switch k {
- case 0x1b:
- n = key.NameEscape
- case C.NSLeftArrowFunctionKey:
- n = key.NameLeftArrow
- case C.NSRightArrowFunctionKey:
- n = key.NameRightArrow
- case C.NSUpArrowFunctionKey:
- n = key.NameUpArrow
- case C.NSDownArrowFunctionKey:
- n = key.NameDownArrow
- case 0xd:
- n = key.NameReturn
- case 0x3:
- n = key.NameEnter
- case C.NSHomeFunctionKey:
- n = key.NameHome
- case C.NSEndFunctionKey:
- n = key.NameEnd
- case 0x7f:
- n = key.NameDeleteBackward
- case C.NSDeleteFunctionKey:
- n = key.NameDeleteForward
- case C.NSPageUpFunctionKey:
- n = key.NamePageUp
- case C.NSPageDownFunctionKey:
- n = key.NamePageDown
- case C.NSF1FunctionKey:
- n = "F1"
- case C.NSF2FunctionKey:
- n = "F2"
- case C.NSF3FunctionKey:
- n = "F3"
- case C.NSF4FunctionKey:
- n = "F4"
- case C.NSF5FunctionKey:
- n = "F5"
- case C.NSF6FunctionKey:
- n = "F6"
- case C.NSF7FunctionKey:
- n = "F7"
- case C.NSF8FunctionKey:
- n = "F8"
- case C.NSF9FunctionKey:
- n = "F9"
- case C.NSF10FunctionKey:
- n = "F10"
- case C.NSF11FunctionKey:
- n = "F11"
- case C.NSF12FunctionKey:
- n = "F12"
- case 0x09, 0x19:
- n = key.NameTab
- case 0x20:
- n = "Space"
- default:
- k = unicode.ToUpper(k)
- if !unicode.IsPrint(k) {
- return "", false
- }
- n = string(k)
- }
- return n, true
-}
-
-func convertMods(mods C.NSUInteger) key.Modifiers {
- var kmods key.Modifiers
- if mods&C.NSAlternateKeyMask != 0 {
- kmods |= key.ModAlt
- }
- if mods&C.NSControlKeyMask != 0 {
- kmods |= key.ModCtrl
- }
- if mods&C.NSCommandKeyMask != 0 {
- kmods |= key.ModCommand
- }
- if mods&C.NSShiftKeyMask != 0 {
- kmods |= key.ModShift
- }
- return kmods
-}
diff --git a/vendor/gioui.org/app/internal/window/os_unix.go b/vendor/gioui.org/app/internal/window/os_unix.go
deleted file mode 100644
index baaebb5..0000000
--- a/vendor/gioui.org/app/internal/window/os_unix.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build linux,!android freebsd openbsd
-
-package window
-
-import (
- "errors"
-)
-
-func Main() {
- select {}
-}
-
-// instead of creating files with build tags for each combination of wayland +/- x11
-// let each driver initialize these variables with their own version of createWindow.
-var wlDriver, x11Driver func(Callbacks, *Options) error
-
-func NewWindow(window Callbacks, opts *Options) error {
- var errFirst, err error
- if wlDriver != nil {
- if err = wlDriver(window, opts); err == nil {
- return nil
- }
- errFirst = err
- }
- if x11Driver != nil {
- if err = x11Driver(window, opts); err == nil {
- return nil
- }
- if errFirst == nil {
- errFirst = err
- }
- }
- if errFirst != nil {
- return errFirst
- }
- return errors.New("app: no window driver available")
-}
diff --git a/vendor/gioui.org/app/internal/window/window.go b/vendor/gioui.org/app/internal/window/window.go
deleted file mode 100644
index 30ba360..0000000
--- a/vendor/gioui.org/app/internal/window/window.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// Package window implements platform specific windows
-// and GPU contexts.
-package window
-
-import (
- "errors"
-
- "gioui.org/gpu/backend"
- "gioui.org/io/event"
- "gioui.org/io/system"
- "gioui.org/unit"
-)
-
-type Options struct {
- Width, Height unit.Value
- MinWidth, MinHeight unit.Value
- MaxWidth, MaxHeight unit.Value
- Title string
-}
-
-type FrameEvent struct {
- system.FrameEvent
-
- Sync bool
-}
-
-type Callbacks interface {
- SetDriver(d Driver)
- Event(e event.Event)
-}
-
-type Context interface {
- Backend() (backend.Device, error)
- Present() error
- MakeCurrent() error
- Release()
- Lock()
- Unlock()
-}
-
-// ErrDeviceLost is returned from Context.Present when
-// the underlying GPU device is gone and should be
-// recreated.
-var ErrDeviceLost = errors.New("GPU device lost")
-
-// Driver is the interface for the platform implementation
-// of a window.
-type Driver interface {
- // SetAnimating sets the animation flag. When the window is animating,
- // FrameEvents are delivered as fast as the display can handle them.
- SetAnimating(anim bool)
- // ShowTextInput updates the virtual keyboard state.
- ShowTextInput(show bool)
- NewContext() (Context, error)
-
- // ReadClipboard requests the clipboard content.
- ReadClipboard()
- // WriteClipboard requests a clipboard write.
- WriteClipboard(s string)
-
- // Close the window.
- Close()
-}
-
-type windowRendezvous struct {
- in chan windowAndOptions
- out chan windowAndOptions
- errs chan error
-}
-
-type windowAndOptions struct {
- window Callbacks
- opts *Options
-}
-
-func newWindowRendezvous() *windowRendezvous {
- wr := &windowRendezvous{
- in: make(chan windowAndOptions),
- out: make(chan windowAndOptions),
- errs: make(chan error),
- }
- go func() {
- var main windowAndOptions
- var out chan windowAndOptions
- for {
- select {
- case w := <-wr.in:
- var err error
- if main.window != nil {
- err = errors.New("multiple windows are not supported")
- }
- wr.errs <- err
- main = w
- out = wr.out
- case out <- main:
- }
- }
- }()
- return wr
-}
diff --git a/vendor/gioui.org/app/internal/windows/windows.go b/vendor/gioui.org/app/internal/windows/windows.go
index 9006326..65a01d3 100644
--- a/vendor/gioui.org/app/internal/windows/windows.go
+++ b/vendor/gioui.org/app/internal/windows/windows.go
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: Unlicense OR MIT
+//go:build windows
// +build windows
package windows
@@ -54,14 +55,44 @@ type MinMaxInfo struct {
PtMaxTrackSize Point
}
+type WindowPlacement struct {
+ length uint32
+ flags uint32
+ showCmd uint32
+ ptMinPosition Point
+ ptMaxPosition Point
+ rcNormalPosition Rect
+ rcDevice Rect
+}
+
+type MonitorInfo struct {
+ cbSize uint32
+ Monitor Rect
+ WorkArea Rect
+ Flags uint32
+}
+
const (
+ TRUE = 1
+
CS_HREDRAW = 0x0002
CS_VREDRAW = 0x0001
CS_OWNDC = 0x0020
CW_USEDEFAULT = -2147483648
- IDC_ARROW = 32512
+ GWL_STYLE = ^(uint32(16) - 1) // -16
+ HWND_TOPMOST = ^(uint32(1) - 1) // -1
+
+ HTCLIENT = 1
+
+ IDC_ARROW = 32512
+ IDC_IBEAM = 32513
+ IDC_HAND = 32649
+ IDC_CROSS = 32515
+ IDC_SIZENS = 32645
+ IDC_SIZEWE = 32644
+ IDC_SIZEALL = 32646
INFINITE = 0xFFFFFFFF
@@ -77,6 +108,13 @@ const (
SW_SHOWDEFAULT = 10
+ SWP_FRAMECHANGED = 0x0020
+ SWP_NOMOVE = 0x0002
+ SWP_NOOWNERZORDER = 0x0200
+ SWP_NOSIZE = 0x0001
+ SWP_NOZORDER = 0x0004
+ SWP_SHOWWINDOW = 0x0040
+
USER_TIMER_MINIMUM = 0x0000000A
VK_CONTROL = 0x11
@@ -142,14 +180,17 @@ const (
WM_MBUTTONUP = 0x0208
WM_MOUSEMOVE = 0x0200
WM_MOUSEWHEEL = 0x020A
+ WM_MOUSEHWHEEL = 0x020E
WM_PAINT = 0x000F
WM_CLOSE = 0x0010
WM_QUIT = 0x0012
+ WM_SETCURSOR = 0x0020
WM_SETFOCUS = 0x0007
WM_KILLFOCUS = 0x0008
WM_SHOWWINDOW = 0x0018
WM_SIZE = 0x0005
WM_SYSKEYDOWN = 0x0104
+ WM_SYSKEYUP = 0x0105
WM_RBUTTONDOWN = 0x0204
WM_RBUTTONUP = 0x0205
WM_TIMER = 0x0113
@@ -159,6 +200,7 @@ const (
WS_CLIPCHILDREN = 0x00010000
WS_CLIPSIBLINGS = 0x04000000
+ WS_MAXIMIZE = 0x01000000
WS_VISIBLE = 0x10000000
WS_OVERLAPPED = 0x00000000
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
@@ -185,6 +227,19 @@ const (
GHND = 0x0042
CF_UNICODETEXT = 13
+ IMAGE_BITMAP = 0
+ IMAGE_ICON = 1
+ IMAGE_CURSOR = 2
+
+ LR_CREATEDIBSECTION = 0x00002000
+ LR_DEFAULTCOLOR = 0x00000000
+ LR_DEFAULTSIZE = 0x00000040
+ LR_LOADFROMFILE = 0x00000010
+ LR_LOADMAP3DCOLORS = 0x00001000
+ LR_LOADTRANSPARENT = 0x00000020
+ LR_MONOCHROME = 0x00000001
+ LR_SHARED = 0x00008000
+ LR_VGACOLOR = 0x00000080
)
var (
@@ -207,12 +262,20 @@ var (
_GetClientRect = user32.NewProc("GetClientRect")
_GetClipboardData = user32.NewProc("GetClipboardData")
_GetDC = user32.NewProc("GetDC")
+ _GetDpiForWindow = user32.NewProc("GetDpiForWindow")
_GetKeyState = user32.NewProc("GetKeyState")
_GetMessage = user32.NewProc("GetMessageW")
_GetMessageTime = user32.NewProc("GetMessageTime")
+ _GetMonitorInfo = user32.NewProc("GetMonitorInfoW")
+ _GetWindowLong = user32.NewProc("GetWindowLongPtrW")
+ _GetWindowLong32 = user32.NewProc("GetWindowLongW")
+ _GetWindowPlacement = user32.NewProc("GetWindowPlacement")
_KillTimer = user32.NewProc("KillTimer")
_LoadCursor = user32.NewProc("LoadCursorW")
+ _LoadImage = user32.NewProc("LoadImageW")
_MonitorFromPoint = user32.NewProc("MonitorFromPoint")
+ _MonitorFromWindow = user32.NewProc("MonitorFromWindow")
+ _MoveWindow = user32.NewProc("MoveWindow")
_MsgWaitForMultipleObjectsEx = user32.NewProc("MsgWaitForMultipleObjectsEx")
_OpenClipboard = user32.NewProc("OpenClipboard")
_PeekMessage = user32.NewProc("PeekMessageW")
@@ -224,11 +287,17 @@ var (
_ScreenToClient = user32.NewProc("ScreenToClient")
_ShowWindow = user32.NewProc("ShowWindow")
_SetCapture = user32.NewProc("SetCapture")
+ _SetCursor = user32.NewProc("SetCursor")
_SetClipboardData = user32.NewProc("SetClipboardData")
_SetForegroundWindow = user32.NewProc("SetForegroundWindow")
_SetFocus = user32.NewProc("SetFocus")
_SetProcessDPIAware = user32.NewProc("SetProcessDPIAware")
_SetTimer = user32.NewProc("SetTimer")
+ _SetWindowLong = user32.NewProc("SetWindowLongPtrW")
+ _SetWindowLong32 = user32.NewProc("SetWindowLongW")
+ _SetWindowPlacement = user32.NewProc("SetWindowPlacement")
+ _SetWindowPos = user32.NewProc("SetWindowPos")
+ _SetWindowText = user32.NewProc("SetWindowTextW")
_TranslateMessage = user32.NewProc("TranslateMessage")
_UnregisterClass = user32.NewProc("UnregisterClassW")
_UpdateWindow = user32.NewProc("UpdateWindow")
@@ -343,7 +412,7 @@ func getDpiForMonitor(hmonitor syscall.Handle, dpiType uint32) int {
// GetSystemDPI returns the effective DPI of the system.
func GetSystemDPI() int {
- // Check for getDpiForMonitor, introduced in Windows 8.1.
+ // Check for GetDpiForMonitor, introduced in Windows 8.1.
if _GetDpiForMonitor.Find() == nil {
hmon := monitorFromPoint(Point{}, MONITOR_DEFAULTTOPRIMARY)
return getDpiForMonitor(hmon, MDT_EFFECTIVE_DPI)
@@ -377,6 +446,66 @@ func GetMessageTime() time.Duration {
return time.Duration(r) * time.Millisecond
}
+// GetWindowDPI returns the effective DPI of the window.
+func GetWindowDPI(hwnd syscall.Handle) int {
+ // Check for GetDpiForWindow, introduced in Windows 10.
+ if _GetDpiForWindow.Find() == nil {
+ dpi, _, _ := _GetDpiForWindow.Call(uintptr(hwnd))
+ return int(dpi)
+ } else {
+ return GetSystemDPI()
+ }
+}
+
+func GetWindowPlacement(hwnd syscall.Handle) *WindowPlacement {
+ var wp WindowPlacement
+ wp.length = uint32(unsafe.Sizeof(wp))
+ _GetWindowPlacement.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&wp)))
+ return &wp
+}
+
+func GetMonitorInfo(hwnd syscall.Handle) MonitorInfo {
+ var mi MonitorInfo
+ mi.cbSize = uint32(unsafe.Sizeof(mi))
+ v, _, _ := _MonitorFromWindow.Call(uintptr(hwnd), MONITOR_DEFAULTTOPRIMARY)
+ _GetMonitorInfo.Call(v, uintptr(unsafe.Pointer(&mi)))
+ return mi
+}
+
+func GetWindowLong(hwnd syscall.Handle) (style uintptr) {
+ if runtime.GOARCH == "386" {
+ style, _, _ = _GetWindowLong32.Call(uintptr(hwnd), uintptr(GWL_STYLE))
+ } else {
+ style, _, _ = _GetWindowLong.Call(uintptr(hwnd), uintptr(GWL_STYLE))
+ }
+ return
+}
+
+func SetWindowLong(hwnd syscall.Handle, idx uint32, style uintptr) {
+ if runtime.GOARCH == "386" {
+ _SetWindowLong32.Call(uintptr(hwnd), uintptr(idx), style)
+ } else {
+ _SetWindowLong.Call(uintptr(hwnd), uintptr(idx), style)
+ }
+}
+
+func SetWindowPlacement(hwnd syscall.Handle, wp *WindowPlacement) {
+ _SetWindowPlacement.Call(uintptr(hwnd), uintptr(unsafe.Pointer(wp)))
+}
+
+func SetWindowPos(hwnd syscall.Handle, hwndInsertAfter uint32, x, y, dx, dy int32, style uintptr) {
+ _SetWindowPos.Call(uintptr(hwnd), uintptr(hwndInsertAfter),
+ uintptr(x), uintptr(y),
+ uintptr(dx), uintptr(dy),
+ style,
+ )
+}
+
+func SetWindowText(hwnd syscall.Handle, title string) {
+ wname := syscall.StringToUTF16Ptr(title)
+ _SetWindowText.Call(uintptr(hwnd), uintptr(unsafe.Pointer(wname)))
+}
+
func GlobalAlloc(size int) (syscall.Handle, error) {
r, _, err := _GlobalAlloc.Call(GHND, uintptr(size))
if r == 0 {
@@ -417,6 +546,22 @@ func LoadCursor(curID uint16) (syscall.Handle, error) {
return syscall.Handle(h), nil
}
+func LoadImage(hInst syscall.Handle, res uint32, typ uint32, cx, cy int, fuload uint32) (syscall.Handle, error) {
+ h, _, err := _LoadImage.Call(uintptr(hInst), uintptr(res), uintptr(typ), uintptr(cx), uintptr(cy), uintptr(fuload))
+ if h == 0 {
+ return 0, fmt.Errorf("LoadImageW failed: %v", err)
+ }
+ return syscall.Handle(h), nil
+}
+
+func MoveWindow(hwnd syscall.Handle, x, y, width, height int32, repaint bool) {
+ var paint uintptr
+ if repaint {
+ paint = TRUE
+ }
+ _MoveWindow.Call(uintptr(hwnd), uintptr(x), uintptr(y), uintptr(width), uintptr(height), paint)
+}
+
func monitorFromPoint(pt Point, flags uint32) syscall.Handle {
r, _, _ := _MonitorFromPoint.Call(uintptr(pt.X), uintptr(pt.Y), uintptr(flags))
return syscall.Handle(r)
@@ -500,6 +645,10 @@ func SetClipboardData(format uint32, mem syscall.Handle) error {
return nil
}
+func SetCursor(h syscall.Handle) {
+ _SetCursor.Call(uintptr(h))
+}
+
func SetTimer(hwnd syscall.Handle, nIDEvent uintptr, uElapse uint32, timerProc uintptr) error {
r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), uintptr(uElapse), timerProc)
if r == 0 {
@@ -530,6 +679,10 @@ func UpdateWindow(hwnd syscall.Handle) {
_UpdateWindow.Call(uintptr(hwnd))
}
+func (p WindowPlacement) Rect() Rect {
+ return p.rcNormalPosition
+}
+
// issue34474KeepAlive calls runtime.KeepAlive as a
// workaround for golang.org/issue/34474.
func issue34474KeepAlive(v interface{}) {
diff --git a/vendor/gioui.org/app/internal/xkb/xkb_unix.go b/vendor/gioui.org/app/internal/xkb/xkb_unix.go
index 3525692..68b1329 100644
--- a/vendor/gioui.org/app/internal/xkb/xkb_unix.go
+++ b/vendor/gioui.org/app/internal/xkb/xkb_unix.go
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: Unlicense OR MIT
+//go:build (linux && !android) || freebsd || openbsd
// +build linux,!android freebsd openbsd
// Package xkb implements a Go interface for the X Keyboard Extension library.
@@ -150,7 +151,7 @@ func (x *Context) Modifiers() key.Modifiers {
return mods
}
-func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
+func (x *Context) DispatchKey(keyCode uint32, state key.State) (events []event.Event) {
if x.state == nil {
return
}
@@ -163,6 +164,7 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
cmd := key.Event{
Name: name,
Modifiers: x.Modifiers(),
+ State: state,
}
// Ensure that a physical backtab key is translated to
// Shift-Tab.
@@ -185,7 +187,10 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
C.xkb_compose_state_reset(x.compState)
str = x.utf8Buf[:size]
case C.XKB_COMPOSE_NOTHING:
- str = x.charsForKeycode(kc)
+ mod := x.Modifiers()
+ if mod&(key.ModCtrl|key.ModAlt|key.ModSuper) == 0 {
+ str = x.charsForKeycode(kc)
+ }
}
// Report only printable runes.
var n int
@@ -198,7 +203,7 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
str = str[:len(str)-s]
}
}
- if len(str) > 0 {
+ if state == key.Press && len(str) > 0 {
events = append(events, key.EditEvent{Text: string(str)})
}
return
@@ -230,7 +235,7 @@ func convertKeysym(s C.xkb_keysym_t) (string, bool) {
if 'a' <= s && s <= 'z' {
return string(rune(s - 'a' + 'A')), true
}
- if ' ' <= s && s <= '~' {
+ if ' ' < s && s <= '~' {
return string(rune(s)), true
}
var n string
@@ -288,7 +293,7 @@ func convertKeysym(s C.xkb_keysym_t) (string, bool) {
case C.XKB_KEY_Tab, C.XKB_KEY_KP_Tab, C.XKB_KEY_ISO_Left_Tab:
n = key.NameTab
case 0x20, C.XKB_KEY_KP_Space:
- n = "Space"
+ n = key.NameSpace
default:
return "", false
}
diff --git a/vendor/gioui.org/app/loop.go b/vendor/gioui.org/app/loop.go
deleted file mode 100644
index 0b2195a..0000000
--- a/vendor/gioui.org/app/loop.go
+++ /dev/null
@@ -1,157 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package app
-
-import (
- "image"
- "runtime"
-
- "gioui.org/app/internal/window"
- "gioui.org/gpu"
- "gioui.org/op"
-)
-
-type renderLoop struct {
- summary string
- drawing bool
- err error
-
- frames chan frame
- results chan frameResult
- refresh chan struct{}
- refreshErr chan error
- ack chan struct{}
- stop chan struct{}
- stopped chan struct{}
-}
-
-type frame struct {
- viewport image.Point
- ops *op.Ops
-}
-
-type frameResult struct {
- profile string
- err error
-}
-
-func newLoop(ctx window.Context) (*renderLoop, error) {
- l := &renderLoop{
- frames: make(chan frame),
- results: make(chan frameResult),
- refresh: make(chan struct{}),
- refreshErr: make(chan error),
- // Ack is buffered so GPU commands can be issued after
- // ack'ing the frame.
- ack: make(chan struct{}, 1),
- stop: make(chan struct{}),
- stopped: make(chan struct{}),
- }
- if err := l.renderLoop(ctx); err != nil {
- return nil, err
- }
- return l, nil
-}
-
-func (l *renderLoop) renderLoop(ctx window.Context) error {
- // GL Operations must happen on a single OS thread, so
- // pass initialization result through a channel.
- initErr := make(chan error)
- go func() {
- defer close(l.stopped)
- runtime.LockOSThread()
- // Don't UnlockOSThread to avoid reuse by the Go runtime.
-
- if err := ctx.MakeCurrent(); err != nil {
- initErr <- err
- return
- }
- b, err := ctx.Backend()
- if err != nil {
- initErr <- err
- return
- }
- g, err := gpu.New(b)
- if err != nil {
- initErr <- err
- return
- }
- defer ctx.Release()
- initErr <- nil
- loop:
- for {
- select {
- case <-l.refresh:
- l.refreshErr <- ctx.MakeCurrent()
- case frame := <-l.frames:
- ctx.Lock()
- g.Collect(frame.viewport, frame.ops)
- // Signal that we're done with the frame ops.
- l.ack <- struct{}{}
- g.BeginFrame()
- var res frameResult
- res.err = ctx.Present()
- g.EndFrame()
- res.profile = g.Profile()
- ctx.Unlock()
- l.results <- res
- case <-l.stop:
- break loop
- }
- }
- }()
- return <-initErr
-}
-
-func (l *renderLoop) Release() {
- // Flush error.
- l.Flush()
- close(l.stop)
- <-l.stopped
- l.stop = nil
-}
-
-func (l *renderLoop) Flush() error {
- if l.drawing {
- st := <-l.results
- l.setErr(st.err)
- if st.profile != "" {
- l.summary = st.profile
- }
- l.drawing = false
- }
- return l.err
-}
-
-func (l *renderLoop) Summary() string {
- return l.summary
-}
-
-func (l *renderLoop) Refresh() {
- if l.err != nil {
- return
- }
- // Make sure any pending frame is complete.
- l.Flush()
- l.refresh <- struct{}{}
- l.setErr(<-l.refreshErr)
-}
-
-// Draw initiates a draw of a frame. It returns a channel
-// than signals when the frame is no longer being accessed.
-func (l *renderLoop) Draw(viewport image.Point, frameOps *op.Ops) <-chan struct{} {
- if l.err != nil {
- l.ack <- struct{}{}
- return l.ack
- }
- l.Flush()
- l.frames <- frame{viewport, frameOps}
- l.drawing = true
- return l.ack
-}
-
-func (l *renderLoop) setErr(err error) {
- if l.err == nil {
- l.err = err
- }
-}
diff --git a/vendor/gioui.org/app/metal_darwin.go b/vendor/gioui.org/app/metal_darwin.go
new file mode 100644
index 0000000..06b89f3
--- /dev/null
+++ b/vendor/gioui.org/app/metal_darwin.go
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build !nometal
+// +build !nometal
+
+package app
+
+import (
+ "errors"
+
+ "gioui.org/gpu"
+)
+
+/*
+#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
+
+@import Metal;
+@import QuartzCore.CAMetalLayer;
+
+#include <CoreFoundation/CoreFoundation.h>
+
+static CFTypeRef createMetalDevice(void) {
+ @autoreleasepool {
+ id<MTLDevice> dev = MTLCreateSystemDefaultDevice();
+ return CFBridgingRetain(dev);
+ }
+}
+
+static void setupLayer(CFTypeRef layerRef, CFTypeRef devRef) {
+ @autoreleasepool {
+ CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
+ id<MTLDevice> dev = (__bridge id<MTLDevice>)devRef;
+ layer.device = dev;
+ // Package gpu assumes an sRGB-encoded framebuffer.
+ layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
+ if (@available(iOS 11.0, *)) {
+ // Never let nextDrawable time out and return nil.
+ layer.allowsNextDrawableTimeout = NO;
+ }
+ }
+}
+
+static CFTypeRef nextDrawable(CFTypeRef layerRef) {
+ @autoreleasepool {
+ CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
+ return CFBridgingRetain([layer nextDrawable]);
+ }
+}
+
+static CFTypeRef drawableTexture(CFTypeRef drawableRef) {
+ @autoreleasepool {
+ id<CAMetalDrawable> drawable = (__bridge id<CAMetalDrawable>)drawableRef;
+ return CFBridgingRetain(drawable.texture);
+ }
+}
+
+static void presentDrawable(CFTypeRef queueRef, CFTypeRef drawableRef) {
+ @autoreleasepool {
+ id<MTLDrawable> drawable = (__bridge id<MTLDrawable>)drawableRef;
+ id<MTLCommandQueue> queue = (__bridge id<MTLCommandQueue>)queueRef;
+ id<MTLCommandBuffer> cmdBuffer = [queue commandBuffer];
+ [cmdBuffer presentDrawable:drawable];
+ [cmdBuffer commit];
+ }
+}
+
+static CFTypeRef newCommandQueue(CFTypeRef devRef) {
+ @autoreleasepool {
+ id<MTLDevice> dev = (__bridge id<MTLDevice>)devRef;
+ return CFBridgingRetain([dev newCommandQueue]);
+ }
+}
+*/
+import "C"
+
+type mtlContext struct {
+ dev C.CFTypeRef
+ view C.CFTypeRef
+ layer C.CFTypeRef
+ queue C.CFTypeRef
+ drawable C.CFTypeRef
+ texture C.CFTypeRef
+}
+
+func newMtlContext(w *window) (*mtlContext, error) {
+ dev := C.createMetalDevice()
+ if dev == 0 {
+ return nil, errors.New("metal: MTLCreateSystemDefaultDevice failed")
+ }
+ view := w.contextView()
+ layer := getMetalLayer(view)
+ if layer == 0 {
+ C.CFRelease(dev)
+ return nil, errors.New("metal: CAMetalLayer construction failed")
+ }
+ queue := C.newCommandQueue(dev)
+ if layer == 0 {
+ C.CFRelease(dev)
+ C.CFRelease(layer)
+ return nil, errors.New("metal: [MTLDevice newCommandQueue] failed")
+ }
+ C.setupLayer(layer, dev)
+ c := &mtlContext{
+ dev: dev,
+ view: view,
+ layer: layer,
+ queue: queue,
+ }
+ return c, nil
+}
+
+func (c *mtlContext) RenderTarget() (gpu.RenderTarget, error) {
+ if c.drawable != 0 || c.texture != 0 {
+ return nil, errors.New("metal:a previous RenderTarget wasn't Presented")
+ }
+ c.drawable = C.nextDrawable(c.layer)
+ if c.drawable == 0 {
+ return nil, errors.New("metal: [CAMetalLayer nextDrawable] failed")
+ }
+ c.texture = C.drawableTexture(c.drawable)
+ if c.texture == 0 {
+ return nil, errors.New("metal: CADrawable.texture is nil")
+ }
+ return gpu.MetalRenderTarget{
+ Texture: uintptr(c.texture),
+ }, nil
+}
+
+func (c *mtlContext) API() gpu.API {
+ return gpu.Metal{
+ Device: uintptr(c.dev),
+ Queue: uintptr(c.queue),
+ PixelFormat: int(C.MTLPixelFormatBGRA8Unorm_sRGB),
+ }
+}
+
+func (c *mtlContext) Release() {
+ C.CFRelease(c.queue)
+ C.CFRelease(c.dev)
+ C.CFRelease(c.layer)
+ if c.drawable != 0 {
+ C.CFRelease(c.drawable)
+ }
+ if c.texture != 0 {
+ C.CFRelease(c.texture)
+ }
+ *c = mtlContext{}
+}
+
+func (c *mtlContext) Present() error {
+ C.CFRelease(c.texture)
+ c.texture = 0
+ C.presentDrawable(c.queue, c.drawable)
+ C.CFRelease(c.drawable)
+ c.drawable = 0
+ return nil
+}
+
+func (c *mtlContext) Lock() error {
+ return nil
+}
+
+func (c *mtlContext) Unlock() {}
+
+func (c *mtlContext) Refresh() error {
+ resizeDrawable(c.view, c.layer)
+ return nil
+}
+
+func (w *window) NewContext() (context, error) {
+ return newMtlContext(w)
+}
diff --git a/vendor/gioui.org/app/metal_ios.go b/vendor/gioui.org/app/metal_ios.go
new file mode 100644
index 0000000..860ba1a
--- /dev/null
+++ b/vendor/gioui.org/app/metal_ios.go
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build !nometal
+// +build !nometal
+
+package app
+
+/*
+#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
+
+@import UIKit;
+
+@import QuartzCore.CAMetalLayer;
+
+#include <CoreFoundation/CoreFoundation.h>
+
+Class gio_layerClass(void) {
+ return [CAMetalLayer class];
+}
+
+static CFTypeRef getMetalLayer(CFTypeRef viewRef) {
+ @autoreleasepool {
+ UIView *view = (__bridge UIView *)viewRef;
+ return CFBridgingRetain(view.layer);
+ }
+}
+
+static void resizeDrawable(CFTypeRef viewRef, CFTypeRef layerRef) {
+ @autoreleasepool {
+ UIView *view = (__bridge UIView *)viewRef;
+ CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
+ layer.contentsScale = view.contentScaleFactor;
+ CGSize size = layer.bounds.size;
+ size.width *= layer.contentsScale;
+ size.height *= layer.contentsScale;
+ layer.drawableSize = size;
+ }
+}
+*/
+import "C"
+
+func getMetalLayer(view C.CFTypeRef) C.CFTypeRef {
+ return C.getMetalLayer(view)
+}
+
+func resizeDrawable(view, layer C.CFTypeRef) {
+ C.resizeDrawable(view, layer)
+}
diff --git a/vendor/gioui.org/app/metal_macos.go b/vendor/gioui.org/app/metal_macos.go
new file mode 100644
index 0000000..7db06a9
--- /dev/null
+++ b/vendor/gioui.org/app/metal_macos.go
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build darwin && !ios && !nometal
+// +build darwin,!ios,!nometal
+
+package app
+
+/*
+#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
+
+@import AppKit;
+
+@import QuartzCore.CAMetalLayer;
+
+#include <CoreFoundation/CoreFoundation.h>
+
+CALayer *gio_layerFactory(void) {
+ @autoreleasepool {
+ return [CAMetalLayer layer];
+ }
+}
+
+static CFTypeRef getMetalLayer(CFTypeRef viewRef) {
+ @autoreleasepool {
+ NSView *view = (__bridge NSView *)viewRef;
+ return CFBridgingRetain(view.layer);
+ }
+}
+
+static void resizeDrawable(CFTypeRef viewRef, CFTypeRef layerRef) {
+ @autoreleasepool {
+ NSView *view = (__bridge NSView *)viewRef;
+ CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
+ CGSize size = layer.bounds.size;
+ size.width *= layer.contentsScale;
+ size.height *= layer.contentsScale;
+ layer.drawableSize = size;
+ }
+}
+*/
+import "C"
+
+func getMetalLayer(view C.CFTypeRef) C.CFTypeRef {
+ return C.getMetalLayer(view)
+}
+
+func resizeDrawable(view, layer C.CFTypeRef) {
+ C.resizeDrawable(view, layer)
+}
diff --git a/vendor/gioui.org/app/os.go b/vendor/gioui.org/app/os.go
new file mode 100644
index 0000000..fc5c266
--- /dev/null
+++ b/vendor/gioui.org/app/os.go
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+// package app implements platform specific windows
+// and GPU contexts.
+package app
+
+import (
+ "errors"
+ "image"
+ "image/color"
+
+ "gioui.org/io/key"
+
+ "gioui.org/gpu"
+ "gioui.org/io/pointer"
+ "gioui.org/io/system"
+ "gioui.org/unit"
+)
+
+type size struct {
+ Width unit.Value
+ Height unit.Value
+}
+
+// errOutOfDate is reported when the GPU surface dimensions or properties no
+// longer match the window.
+var errOutOfDate = errors.New("app: GPU surface out of date")
+
+// Config describes a Window configuration.
+type Config struct {
+ // Size is the window dimensions (Width, Height).
+ Size image.Point
+ // MaxSize is the window maximum allowed dimensions.
+ MaxSize image.Point
+ // MinSize is the window minimum allowed dimensions.
+ MinSize image.Point
+ // Title is the window title displayed in its decoration bar.
+ Title string
+ // WindowMode is the window mode.
+ Mode WindowMode
+ // StatusColor is the color of the Android status bar.
+ StatusColor color.NRGBA
+ // NavigationColor is the color of the navigation bar
+ // on Android, or the address bar in browsers.
+ NavigationColor color.NRGBA
+ // Orientation is the current window orientation.
+ Orientation Orientation
+ // CustomRenderer is true when the window content is rendered by the
+ // client.
+ CustomRenderer bool
+}
+
+// ConfigEvent is sent whenever the configuration of a Window changes.
+type ConfigEvent struct {
+ Config Config
+}
+
+func (c *Config) apply(m unit.Metric, options []Option) {
+ for _, o := range options {
+ o(m, c)
+ }
+}
+
+type wakeupEvent struct{}
+
+// WindowMode is the window mode (WindowMode.Option sets it).
+//
+// Supported platforms are macOS, X11, Windows, Android and JS.
+type WindowMode uint8
+
+const (
+ // Windowed is the normal window mode with OS specific window decorations.
+ Windowed WindowMode = iota
+ // Fullscreen is the full screen window mode.
+ Fullscreen
+)
+
+func (m WindowMode) Option() Option {
+ return func(_ unit.Metric, cnf *Config) {
+ cnf.Mode = m
+ }
+}
+
+func (m WindowMode) String() string {
+ switch m {
+ case Windowed:
+ return "windowed"
+ case Fullscreen:
+ return "fullscreen"
+ }
+ return ""
+}
+
+// Orientation is the orientation of the app (Orientation.Option sets it).
+//
+// Supported platforms are Android and JS.
+type Orientation uint8
+
+const (
+ // AnyOrientation allows the window to be freely orientated.
+ AnyOrientation Orientation = iota
+ // LandscapeOrientation constrains the window to landscape orientations.
+ LandscapeOrientation
+ // PortraitOrientation constrains the window to portrait orientations.
+ PortraitOrientation
+)
+
+func (o Orientation) Option() Option {
+ return func(_ unit.Metric, cnf *Config) {
+ cnf.Orientation = o
+ }
+}
+
+func (o Orientation) String() string {
+ switch o {
+ case AnyOrientation:
+ return "any"
+ case LandscapeOrientation:
+ return "landscape"
+ case PortraitOrientation:
+ return "portrait"
+ }
+ return ""
+}
+
+type frameEvent struct {
+ system.FrameEvent
+
+ Sync bool
+}
+
+type context interface {
+ API() gpu.API
+ RenderTarget() (gpu.RenderTarget, error)
+ Present() error
+ Refresh() error
+ Release()
+ Lock() error
+ Unlock()
+}
+
+// Driver is the interface for the platform implementation
+// of a window.
+type driver interface {
+ // SetAnimating sets the animation flag. When the window is animating,
+ // FrameEvents are delivered as fast as the display can handle them.
+ SetAnimating(anim bool)
+
+ // ShowTextInput updates the virtual keyboard state.
+ ShowTextInput(show bool)
+
+ SetInputHint(mode key.InputHint)
+
+ NewContext() (context, error)
+
+ // ReadClipboard requests the clipboard content.
+ ReadClipboard()
+ // WriteClipboard requests a clipboard write.
+ WriteClipboard(s string)
+
+ // Configure the window.
+ Configure([]Option)
+
+ // SetCursor updates the current cursor to name.
+ SetCursor(name pointer.CursorName)
+
+ // Raise the window at the top.
+ Raise()
+
+ // Close the window.
+ Close()
+
+ // Wakeup wakes up the event loop and sends a WakeupEvent.
+ Wakeup()
+
+ // Maximize will make the window as large as possible, but keep the frame decorations.
+ Maximize()
+ // Center will place the window at monitor center.
+ Center()
+}
+
+type windowRendezvous struct {
+ in chan windowAndConfig
+ out chan windowAndConfig
+ errs chan error
+}
+
+type windowAndConfig struct {
+ window *callbacks
+ options []Option
+}
+
+func newWindowRendezvous() *windowRendezvous {
+ wr := &windowRendezvous{
+ in: make(chan windowAndConfig),
+ out: make(chan windowAndConfig),
+ errs: make(chan error),
+ }
+ go func() {
+ var main windowAndConfig
+ var out chan windowAndConfig
+ for {
+ select {
+ case w := <-wr.in:
+ var err error
+ if main.window != nil {
+ err = errors.New("multiple windows are not supported")
+ }
+ wr.errs <- err
+ main = w
+ out = wr.out
+ case out <- main:
+ }
+ }
+ }()
+ return wr
+}
+
+func (wakeupEvent) ImplementsEvent() {}
+func (ConfigEvent) ImplementsEvent() {}
diff --git a/vendor/gioui.org/app/os_android.go b/vendor/gioui.org/app/os_android.go
new file mode 100644
index 0000000..51d8289
--- /dev/null
+++ b/vendor/gioui.org/app/os_android.go
@@ -0,0 +1,1283 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package app
+
+/*
+#cgo CFLAGS: -Werror
+#cgo LDFLAGS: -landroid
+
+#include <android/native_window_jni.h>
+#include <android/configuration.h>
+#include <android/keycodes.h>
+#include <android/input.h>
+#include <stdlib.h>
+
+static jint jni_GetEnv(JavaVM *vm, JNIEnv **env, jint version) {
+ return (*vm)->GetEnv(vm, (void **)env, version);
+}
+
+static jint jni_GetJavaVM(JNIEnv *env, JavaVM **jvm) {
+ return (*env)->GetJavaVM(env, jvm);
+}
+
+static jint jni_AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) {
+ return (*vm)->AttachCurrentThread(vm, p_env, thr_args);
+}
+
+static jint jni_DetachCurrentThread(JavaVM *vm) {
+ return (*vm)->DetachCurrentThread(vm);
+}
+
+static jobject jni_NewGlobalRef(JNIEnv *env, jobject obj) {
+ return (*env)->NewGlobalRef(env, obj);
+}
+
+static void jni_DeleteGlobalRef(JNIEnv *env, jobject obj) {
+ (*env)->DeleteGlobalRef(env, obj);
+}
+
+static jclass jni_GetObjectClass(JNIEnv *env, jobject obj) {
+ return (*env)->GetObjectClass(env, obj);
+}
+
+static jmethodID jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
+ return (*env)->GetMethodID(env, clazz, name, sig);
+}
+
+static jmethodID jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
+ return (*env)->GetStaticMethodID(env, clazz, name, sig);
+}
+
+static jfloat jni_CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID) {
+ return (*env)->CallFloatMethod(env, obj, methodID);
+}
+
+static jint jni_CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID) {
+ return (*env)->CallIntMethod(env, obj, methodID);
+}
+
+static void jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args) {
+ (*env)->CallStaticVoidMethodA(env, cls, methodID, args);
+}
+
+static void jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args) {
+ (*env)->CallVoidMethodA(env, obj, methodID, args);
+}
+
+static jboolean jni_CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args) {
+ return (*env)->CallBooleanMethodA(env, obj, methodID, args);
+}
+
+static jbyte *jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr) {
+ return (*env)->GetByteArrayElements(env, arr, NULL);
+}
+
+static void jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *bytes) {
+ (*env)->ReleaseByteArrayElements(env, arr, bytes, JNI_ABORT);
+}
+
+static jsize jni_GetArrayLength(JNIEnv *env, jbyteArray arr) {
+ return (*env)->GetArrayLength(env, arr);
+}
+
+static jstring jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len) {
+ return (*env)->NewString(env, unicodeChars, len);
+}
+
+static jsize jni_GetStringLength(JNIEnv *env, jstring str) {
+ return (*env)->GetStringLength(env, str);
+}
+
+static const jchar *jni_GetStringChars(JNIEnv *env, jstring str) {
+ return (*env)->GetStringChars(env, str, NULL);
+}
+
+static jthrowable jni_ExceptionOccurred(JNIEnv *env) {
+ return (*env)->ExceptionOccurred(env);
+}
+
+static void jni_ExceptionClear(JNIEnv *env) {
+ (*env)->ExceptionClear(env);
+}
+
+static jobject jni_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args) {
+ return (*env)->CallObjectMethodA(env, obj, method, args);
+}
+
+static jobject jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) {
+ return (*env)->CallStaticObjectMethodA(env, cls, method, args);
+}
+
+static jclass jni_FindClass(JNIEnv *env, char *name) {
+ return (*env)->FindClass(env, name);
+}
+
+static jobject jni_NewObjectA(JNIEnv *env, jclass cls, jmethodID cons, jvalue *args) {
+ return (*env)->NewObjectA(env, cls, cons, args);
+}
+*/
+import "C"
+
+import (
+ "errors"
+ "fmt"
+ "image"
+ "image/color"
+ "os"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "runtime/debug"
+ "sync"
+ "time"
+ "unicode/utf16"
+ "unsafe"
+
+ "gioui.org/internal/f32color"
+
+ "gioui.org/f32"
+ "gioui.org/io/clipboard"
+ "gioui.org/io/key"
+ "gioui.org/io/pointer"
+ "gioui.org/io/router"
+ "gioui.org/io/semantic"
+ "gioui.org/io/system"
+ "gioui.org/unit"
+)
+
+type window struct {
+ callbacks *callbacks
+
+ view C.jobject
+
+ dpi int
+ fontScale float32
+ insets system.Insets
+
+ stage system.Stage
+ started bool
+ animating bool
+
+ win *C.ANativeWindow
+ config Config
+
+ semantic struct {
+ hoverID router.SemanticID
+ rootID router.SemanticID
+ focusID router.SemanticID
+ diffs []router.SemanticID
+ }
+}
+
+// gioView hold cached JNI methods for GioView.
+var gioView struct {
+ once sync.Once
+ getDensity C.jmethodID
+ getFontScale C.jmethodID
+ showTextInput C.jmethodID
+ hideTextInput C.jmethodID
+ setInputHint C.jmethodID
+ postInvalidate C.jmethodID // requests draw, called from non-UI thread
+ invalidate C.jmethodID // requests draw, called from UI thread
+ setCursor C.jmethodID
+ setOrientation C.jmethodID
+ setNavigationColor C.jmethodID
+ setStatusColor C.jmethodID
+ setFullscreen C.jmethodID
+ unregister C.jmethodID
+ sendA11yEvent C.jmethodID
+ sendA11yChange C.jmethodID
+ isA11yActive C.jmethodID
+}
+
+// ViewEvent is sent whenever the Window's underlying Android view
+// changes.
+type ViewEvent struct {
+ // View is a JNI global reference to the android.view.View
+ // instance backing the Window. The reference is valid until
+ // the next ViewEvent is received.
+ // A zero View means that there is currently no view attached.
+ View uintptr
+}
+
+type jvalue uint64 // The largest JNI type fits in 64 bits.
+
+var dataDirChan = make(chan string, 1)
+
+var android struct {
+ // mu protects all fields of this structure. However, once a
+ // non-nil jvm is returned from javaVM, all the other fields may
+ // be accessed unlocked.
+ mu sync.Mutex
+ jvm *C.JavaVM
+
+ // appCtx is the global Android App context.
+ appCtx C.jobject
+ // gioCls is the class of the Gio class.
+ gioCls C.jclass
+
+ mwriteClipboard C.jmethodID
+ mreadClipboard C.jmethodID
+ mwakeupMainThread C.jmethodID
+
+ // android.view.accessibility.AccessibilityNodeInfo class.
+ accessibilityNodeInfo struct {
+ cls C.jclass
+ // addChild(View, int)
+ addChild C.jmethodID
+ // setBoundsInScreen(Rect)
+ setBoundsInScreen C.jmethodID
+ // setText(CharSequence)
+ setText C.jmethodID
+ // setContentDescription(CharSequence)
+ setContentDescription C.jmethodID
+ // setParent(View, int)
+ setParent C.jmethodID
+ // addAction(int)
+ addAction C.jmethodID
+ // setClassName(CharSequence)
+ setClassName C.jmethodID
+ // setCheckable(boolean)
+ setCheckable C.jmethodID
+ // setSelected(boolean)
+ setSelected C.jmethodID
+ // setChecked(boolean)
+ setChecked C.jmethodID
+ // setEnabled(boolean)
+ setEnabled C.jmethodID
+ // setAccessibilityFocused(boolean)
+ setAccessibilityFocused C.jmethodID
+ }
+
+ // android.graphics.Rect class.
+ rect struct {
+ cls C.jclass
+ // (int, int, int, int) constructor.
+ cons C.jmethodID
+ }
+
+ strings struct {
+ // "android.view.View"
+ androidViewView C.jstring
+ // "android.widget.Button"
+ androidWidgetButton C.jstring
+ // "android.widget.CheckBox"
+ androidWidgetCheckBox C.jstring
+ // "android.widget.EditText"
+ androidWidgetEditText C.jstring
+ // "android.widget.RadioButton"
+ androidWidgetRadioButton C.jstring
+ // "android.widget.Switch"
+ androidWidgetSwitch C.jstring
+ }
+}
+
+// view maps from GioView JNI refenreces to windows.
+var views = make(map[C.jlong]*window)
+
+var windows = make(map[*callbacks]*window)
+
+var mainWindow = newWindowRendezvous()
+
+var mainFuncs = make(chan func(env *C.JNIEnv), 1)
+
+var (
+ dataDirOnce sync.Once
+ dataPath string
+)
+
+var (
+ newAndroidVulkanContext func(w *window) (context, error)
+ newAndroidGLESContext func(w *window) (context, error)
+)
+
+// AccessibilityNodeProvider.HOST_VIEW_ID.
+const HOST_VIEW_ID = -1
+
+const (
+ // AccessibilityEvent constants.
+ TYPE_VIEW_HOVER_ENTER = 128
+ TYPE_VIEW_HOVER_EXIT = 256
+)
+
+const (
+ // AccessibilityNodeInfo constants.
+ ACTION_ACCESSIBILITY_FOCUS = 64
+ ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128
+ ACTION_CLICK = 16
+)
+
+func (w *window) NewContext() (context, error) {
+ funcs := []func(w *window) (context, error){newAndroidVulkanContext, newAndroidGLESContext}
+ var firstErr error
+ for _, f := range funcs {
+ if f == nil {
+ continue
+ }
+ c, err := f(w)
+ if err != nil {
+ if firstErr == nil {
+ firstErr = err
+ }
+ continue
+ }
+ return c, nil
+ }
+ if firstErr != nil {
+ return nil, firstErr
+ }
+ return nil, errors.New("x11: no available GPU backends")
+}
+
+func dataDir() (string, error) {
+ dataDirOnce.Do(func() {
+ dataPath = <-dataDirChan
+ // Set XDG_CACHE_HOME to make os.UserCacheDir work.
+ if _, exists := os.LookupEnv("XDG_CACHE_HOME"); !exists {
+ cachePath := filepath.Join(dataPath, "cache")
+ os.Setenv("XDG_CACHE_HOME", cachePath)
+ }
+ // Set XDG_CONFIG_HOME to make os.UserConfigDir work.
+ if _, exists := os.LookupEnv("XDG_CONFIG_HOME"); !exists {
+ cfgPath := filepath.Join(dataPath, "config")
+ os.Setenv("XDG_CONFIG_HOME", cfgPath)
+ }
+ // Set HOME to make os.UserHomeDir work.
+ if _, exists := os.LookupEnv("HOME"); !exists {
+ os.Setenv("HOME", dataPath)
+ }
+ })
+ return dataPath, nil
+}
+
+func getMethodID(env *C.JNIEnv, class C.jclass, method, sig string) C.jmethodID {
+ m := C.CString(method)
+ defer C.free(unsafe.Pointer(m))
+ s := C.CString(sig)
+ defer C.free(unsafe.Pointer(s))
+ jm := C.jni_GetMethodID(env, class, m, s)
+ if err := exception(env); err != nil {
+ panic(err)
+ }
+ return jm
+}
+
+func getStaticMethodID(env *C.JNIEnv, class C.jclass, method, sig string) C.jmethodID {
+ m := C.CString(method)
+ defer C.free(unsafe.Pointer(m))
+ s := C.CString(sig)
+ defer C.free(unsafe.Pointer(s))
+ jm := C.jni_GetStaticMethodID(env, class, m, s)
+ if err := exception(env); err != nil {
+ panic(err)
+ }
+ return jm
+}
+
+//export Java_org_gioui_Gio_runGoMain
+func Java_org_gioui_Gio_runGoMain(env *C.JNIEnv, class C.jclass, jdataDir C.jbyteArray, context C.jobject) {
+ initJVM(env, class, context)
+ dirBytes := C.jni_GetByteArrayElements(env, jdataDir)
+ if dirBytes == nil {
+ panic("runGoMain: GetByteArrayElements failed")
+ }
+ n := C.jni_GetArrayLength(env, jdataDir)
+ dataDir := C.GoStringN((*C.char)(unsafe.Pointer(dirBytes)), n)
+ dataDirChan <- dataDir
+ C.jni_ReleaseByteArrayElements(env, jdataDir, dirBytes)
+
+ runMain()
+}
+
+func initJVM(env *C.JNIEnv, gio C.jclass, ctx C.jobject) {
+ android.mu.Lock()
+ defer android.mu.Unlock()
+ if res := C.jni_GetJavaVM(env, &android.jvm); res != 0 {
+ panic("gio: GetJavaVM failed")
+ }
+ android.appCtx = C.jni_NewGlobalRef(env, ctx)
+ android.gioCls = C.jclass(C.jni_NewGlobalRef(env, C.jobject(gio)))
+
+ cls := findClass(env, "android/view/accessibility/AccessibilityNodeInfo")
+ android.accessibilityNodeInfo.cls = C.jclass(C.jni_NewGlobalRef(env, C.jobject(cls)))
+ android.accessibilityNodeInfo.addChild = getMethodID(env, cls, "addChild", "(Landroid/view/View;I)V")
+ android.accessibilityNodeInfo.setBoundsInScreen = getMethodID(env, cls, "setBoundsInScreen", "(Landroid/graphics/Rect;)V")
+ android.accessibilityNodeInfo.setText = getMethodID(env, cls, "setText", "(Ljava/lang/CharSequence;)V")
+ android.accessibilityNodeInfo.setContentDescription = getMethodID(env, cls, "setContentDescription", "(Ljava/lang/CharSequence;)V")
+ android.accessibilityNodeInfo.setParent = getMethodID(env, cls, "setParent", "(Landroid/view/View;I)V")
+ android.accessibilityNodeInfo.addAction = getMethodID(env, cls, "addAction", "(I)V")
+ android.accessibilityNodeInfo.setClassName = getMethodID(env, cls, "setClassName", "(Ljava/lang/CharSequence;)V")
+ android.accessibilityNodeInfo.setCheckable = getMethodID(env, cls, "setCheckable", "(Z)V")
+ android.accessibilityNodeInfo.setSelected = getMethodID(env, cls, "setSelected", "(Z)V")
+ android.accessibilityNodeInfo.setChecked = getMethodID(env, cls, "setChecked", "(Z)V")
+ android.accessibilityNodeInfo.setEnabled = getMethodID(env, cls, "setEnabled", "(Z)V")
+ android.accessibilityNodeInfo.setAccessibilityFocused = getMethodID(env, cls, "setAccessibilityFocused", "(Z)V")
+
+ cls = findClass(env, "android/graphics/Rect")
+ android.rect.cls = C.jclass(C.jni_NewGlobalRef(env, C.jobject(cls)))
+ android.rect.cons = getMethodID(env, cls, "<init>", "(IIII)V")
+ android.mwriteClipboard = getStaticMethodID(env, gio, "writeClipboard", "(Landroid/content/Context;Ljava/lang/String;)V")
+ android.mreadClipboard = getStaticMethodID(env, gio, "readClipboard", "(Landroid/content/Context;)Ljava/lang/String;")
+ android.mwakeupMainThread = getStaticMethodID(env, gio, "wakeupMainThread", "()V")
+
+ intern := func(s string) C.jstring {
+ ref := C.jni_NewGlobalRef(env, C.jobject(javaString(env, s)))
+ return C.jstring(ref)
+ }
+ android.strings.androidViewView = intern("android.view.View")
+ android.strings.androidWidgetButton = intern("android.widget.Button")
+ android.strings.androidWidgetCheckBox = intern("android.widget.CheckBox")
+ android.strings.androidWidgetEditText = intern("android.widget.EditText")
+ android.strings.androidWidgetRadioButton = intern("android.widget.RadioButton")
+ android.strings.androidWidgetSwitch = intern("android.widget.Switch")
+}
+
+// JavaVM returns the global JNI JavaVM.
+func JavaVM() uintptr {
+ jvm := javaVM()
+ return uintptr(unsafe.Pointer(jvm))
+}
+
+func javaVM() *C.JavaVM {
+ android.mu.Lock()
+ defer android.mu.Unlock()
+ return android.jvm
+}
+
+// AppContext returns the global Application context as a JNI jobject.
+func AppContext() uintptr {
+ android.mu.Lock()
+ defer android.mu.Unlock()
+ return uintptr(android.appCtx)
+}
+
+//export Java_org_gioui_GioView_onCreateView
+func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.jobject) C.jlong {
+ gioView.once.Do(func() {
+ m := &gioView
+ m.getDensity = getMethodID(env, class, "getDensity", "()I")
+ m.getFontScale = getMethodID(env, class, "getFontScale", "()F")
+ m.showTextInput = getMethodID(env, class, "showTextInput", "()V")
+ m.hideTextInput = getMethodID(env, class, "hideTextInput", "()V")
+ m.setInputHint = getMethodID(env, class, "setInputHint", "(I)V")
+ m.postInvalidate = getMethodID(env, class, "postInvalidate", "()V")
+ m.invalidate = getMethodID(env, class, "invalidate", "()V")
+ m.setCursor = getMethodID(env, class, "setCursor", "(I)V")
+ m.setOrientation = getMethodID(env, class, "setOrientation", "(II)V")
+ m.setNavigationColor = getMethodID(env, class, "setNavigationColor", "(II)V")
+ m.setStatusColor = getMethodID(env, class, "setStatusColor", "(II)V")
+ m.setFullscreen = getMethodID(env, class, "setFullscreen", "(Z)V")
+ m.unregister = getMethodID(env, class, "unregister", "()V")
+ m.sendA11yEvent = getMethodID(env, class, "sendA11yEvent", "(II)V")
+ m.sendA11yChange = getMethodID(env, class, "sendA11yChange", "(I)V")
+ m.isA11yActive = getMethodID(env, class, "isA11yActive", "()Z")
+ })
+ view = C.jni_NewGlobalRef(env, view)
+ wopts := <-mainWindow.out
+ w, ok := windows[wopts.window]
+ if !ok {
+ w = &window{
+ callbacks: wopts.window,
+ }
+ windows[wopts.window] = w
+ }
+ if w.view != 0 {
+ w.detach(env)
+ }
+ w.view = view
+ w.callbacks.SetDriver(w)
+ handle := C.jlong(view)
+ views[handle] = w
+ w.loadConfig(env, class)
+ w.Configure(wopts.options)
+ w.setStage(system.StagePaused)
+ w.callbacks.Event(ViewEvent{View: uintptr(view)})
+ return handle
+}
+
+//export Java_org_gioui_GioView_onDestroyView
+func Java_org_gioui_GioView_onDestroyView(env *C.JNIEnv, class C.jclass, handle C.jlong) {
+ w := views[handle]
+ w.detach(env)
+}
+
+//export Java_org_gioui_GioView_onStopView
+func Java_org_gioui_GioView_onStopView(env *C.JNIEnv, class C.jclass, handle C.jlong) {
+ w := views[handle]
+ w.started = false
+ w.setStage(system.StagePaused)
+}
+
+//export Java_org_gioui_GioView_onStartView
+func Java_org_gioui_GioView_onStartView(env *C.JNIEnv, class C.jclass, handle C.jlong) {
+ w := views[handle]
+ w.started = true
+ if w.win != nil {
+ w.setVisible(env)
+ }
+}
+
+//export Java_org_gioui_GioView_onSurfaceDestroyed
+func Java_org_gioui_GioView_onSurfaceDestroyed(env *C.JNIEnv, class C.jclass, handle C.jlong) {
+ w := views[handle]
+ w.win = nil
+ w.setStage(system.StagePaused)
+}
+
+//export Java_org_gioui_GioView_onSurfaceChanged
+func Java_org_gioui_GioView_onSurfaceChanged(env *C.JNIEnv, class C.jclass, handle C.jlong, surf C.jobject) {
+ w := views[handle]
+ w.win = C.ANativeWindow_fromSurface(env, surf)
+ if w.started {
+ w.setVisible(env)
+ }
+}
+
+//export Java_org_gioui_GioView_onLowMemory
+func Java_org_gioui_GioView_onLowMemory(env *C.JNIEnv, class C.jclass) {
+ runtime.GC()
+ debug.FreeOSMemory()
+}
+
+//export Java_org_gioui_GioView_onConfigurationChanged
+func Java_org_gioui_GioView_onConfigurationChanged(env *C.JNIEnv, class C.jclass, view C.jlong) {
+ w := views[view]
+ w.loadConfig(env, class)
+ if w.stage >= system.StageRunning {
+ w.draw(env, true)
+ }
+}
+
+//export Java_org_gioui_GioView_onFrameCallback
+func Java_org_gioui_GioView_onFrameCallback(env *C.JNIEnv, class C.jclass, view C.jlong) {
+ w, exist := views[view]
+ if !exist {
+ return
+ }
+ if w.stage < system.StageRunning {
+ return
+ }
+ if w.animating {
+ w.draw(env, false)
+ // Schedule the next draw immediately after this one. Since onFrameCallback runs
+ // on the UI thread, View.invalidate can be used here instead of postInvalidate.
+ callVoidMethod(env, w.view, gioView.invalidate)
+ }
+}
+
+//export Java_org_gioui_GioView_onBack
+func Java_org_gioui_GioView_onBack(env *C.JNIEnv, class C.jclass, view C.jlong) C.jboolean {
+ w := views[view]
+ ev := &system.CommandEvent{Type: system.CommandBack}
+ w.callbacks.Event(ev)
+ if ev.Cancel {
+ return C.JNI_TRUE
+ }
+ return C.JNI_FALSE
+}
+
+//export Java_org_gioui_GioView_onFocusChange
+func Java_org_gioui_GioView_onFocusChange(env *C.JNIEnv, class C.jclass, view C.jlong, focus C.jboolean) {
+ w := views[view]
+ w.callbacks.Event(key.FocusEvent{Focus: focus == C.JNI_TRUE})
+}
+
+//export Java_org_gioui_GioView_onWindowInsets
+func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C.jlong, top, right, bottom, left C.jint) {
+ w := views[view]
+ w.insets = system.Insets{
+ Top: unit.Px(float32(top)),
+ Right: unit.Px(float32(right)),
+ Bottom: unit.Px(float32(bottom)),
+ Left: unit.Px(float32(left)),
+ }
+ if w.stage >= system.StageRunning {
+ w.draw(env, true)
+ }
+}
+
+//export Java_org_gioui_GioView_initializeAccessibilityNodeInfo
+func Java_org_gioui_GioView_initializeAccessibilityNodeInfo(env *C.JNIEnv, class C.jclass, view C.jlong, virtID, screenX, screenY C.jint, info C.jobject) C.jobject {
+ w := views[view]
+ semID := w.semIDFor(virtID)
+ sem, found := w.callbacks.LookupSemantic(semID)
+ if found {
+ off := f32.Pt(float32(screenX), float32(screenY))
+ if err := w.initAccessibilityNodeInfo(env, sem, off, info); err != nil {
+ panic(err)
+ }
+ }
+ return info
+}
+
+//export Java_org_gioui_GioView_onTouchExploration
+func Java_org_gioui_GioView_onTouchExploration(env *C.JNIEnv, class C.jclass, view C.jlong, x, y C.jfloat) {
+ w := views[view]
+ semID, _ := w.callbacks.SemanticAt(f32.Pt(float32(x), float32(y)))
+ if w.semantic.hoverID == semID {
+ return
+ }
+ // Android expects ENTER before EXIT.
+ if semID != 0 {
+ callVoidMethod(env, w.view, gioView.sendA11yEvent, TYPE_VIEW_HOVER_ENTER, jvalue(w.virtualIDFor(semID)))
+ }
+ if prevID := w.semantic.hoverID; prevID != 0 {
+ callVoidMethod(env, w.view, gioView.sendA11yEvent, TYPE_VIEW_HOVER_EXIT, jvalue(w.virtualIDFor(prevID)))
+ }
+ w.semantic.hoverID = semID
+}
+
+//export Java_org_gioui_GioView_onExitTouchExploration
+func Java_org_gioui_GioView_onExitTouchExploration(env *C.JNIEnv, class C.jclass, view C.jlong) {
+ w := views[view]
+ if w.semantic.hoverID != 0 {
+ callVoidMethod(env, w.view, gioView.sendA11yEvent, TYPE_VIEW_HOVER_EXIT, jvalue(w.virtualIDFor(w.semantic.hoverID)))
+ w.semantic.hoverID = 0
+ }
+}
+
+//export Java_org_gioui_GioView_onA11yFocus
+func Java_org_gioui_GioView_onA11yFocus(env *C.JNIEnv, class C.jclass, view C.jlong, virtID C.jint) {
+ w := views[view]
+ if semID := w.semIDFor(virtID); semID != w.semantic.focusID {
+ w.semantic.focusID = semID
+ // Android needs invalidate to refresh the TalkBack focus indicator.
+ callVoidMethod(env, w.view, gioView.invalidate)
+ }
+}
+
+//export Java_org_gioui_GioView_onClearA11yFocus
+func Java_org_gioui_GioView_onClearA11yFocus(env *C.JNIEnv, class C.jclass, view C.jlong, virtID C.jint) {
+ w := views[view]
+ if w.semantic.focusID == w.semIDFor(virtID) {
+ w.semantic.focusID = 0
+ }
+}
+
+func (w *window) initAccessibilityNodeInfo(env *C.JNIEnv, sem router.SemanticNode, off f32.Point, info C.jobject) error {
+ for _, ch := range sem.Children {
+ err := callVoidMethod(env, info, android.accessibilityNodeInfo.addChild, jvalue(w.view), jvalue(w.virtualIDFor(ch.ID)))
+ if err != nil {
+ return err
+ }
+ }
+ if sem.ParentID != 0 {
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setParent, jvalue(w.view), jvalue(w.virtualIDFor(sem.ParentID))); err != nil {
+ return err
+ }
+ b := sem.Desc.Bounds.Add(off)
+ rect, err := newObject(env, android.rect.cls, android.rect.cons,
+ jvalue(b.Min.X),
+ jvalue(b.Min.Y),
+ jvalue(b.Max.X),
+ jvalue(b.Max.Y),
+ )
+ if err != nil {
+ return err
+ }
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setBoundsInScreen, jvalue(rect)); err != nil {
+ return err
+ }
+ }
+ d := sem.Desc
+ if l := d.Label; l != "" {
+ jlbl := javaString(env, l)
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setText, jvalue(jlbl)); err != nil {
+ return err
+ }
+ }
+ if d.Description != "" {
+ jd := javaString(env, d.Description)
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setContentDescription, jvalue(jd)); err != nil {
+ return err
+ }
+ }
+ addAction := func(act C.jint) {
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.addAction, jvalue(act)); err != nil {
+ panic(err)
+ }
+ }
+ if d.Gestures&router.ClickGesture != 0 {
+ addAction(ACTION_CLICK)
+ }
+ clsName := android.strings.androidViewView
+ selectMethod := android.accessibilityNodeInfo.setChecked
+ checkable := false
+ switch d.Class {
+ case semantic.Button:
+ clsName = android.strings.androidWidgetButton
+ case semantic.CheckBox:
+ checkable = true
+ clsName = android.strings.androidWidgetCheckBox
+ case semantic.Editor:
+ clsName = android.strings.androidWidgetEditText
+ case semantic.RadioButton:
+ selectMethod = android.accessibilityNodeInfo.setSelected
+ clsName = android.strings.androidWidgetRadioButton
+ case semantic.Switch:
+ checkable = true
+ clsName = android.strings.androidWidgetSwitch
+ }
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setClassName, jvalue(clsName)); err != nil {
+ panic(err)
+ }
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setCheckable, jvalue(javaBool(checkable))); err != nil {
+ panic(err)
+ }
+ if err := callVoidMethod(env, info, selectMethod, jvalue(javaBool(d.Selected))); err != nil {
+ panic(err)
+ }
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setEnabled, jvalue(javaBool(!d.Disabled))); err != nil {
+ panic(err)
+ }
+ isFocus := w.semantic.focusID == sem.ID
+ if err := callVoidMethod(env, info, android.accessibilityNodeInfo.setAccessibilityFocused, jvalue(javaBool(isFocus))); err != nil {
+ panic(err)
+ }
+ if isFocus {
+ addAction(ACTION_CLEAR_ACCESSIBILITY_FOCUS)
+ } else {
+ addAction(ACTION_ACCESSIBILITY_FOCUS)
+ }
+ return nil
+}
+
+func (w *window) virtualIDFor(id router.SemanticID) C.jint {
+ // TODO: Android virtual IDs are 32-bit Java integers, but childID is a int64.
+ if id == w.semantic.rootID {
+ return HOST_VIEW_ID
+ }
+ return C.jint(id)
+}
+
+func (w *window) semIDFor(virtID C.jint) router.SemanticID {
+ if virtID == HOST_VIEW_ID {
+ return w.semantic.rootID
+ }
+ return router.SemanticID(virtID)
+}
+
+func (w *window) detach(env *C.JNIEnv) {
+ callVoidMethod(env, w.view, gioView.unregister)
+ w.callbacks.Event(ViewEvent{})
+ w.callbacks.SetDriver(nil)
+ delete(views, C.jlong(w.view))
+ C.jni_DeleteGlobalRef(env, w.view)
+ w.view = 0
+}
+
+func (w *window) setVisible(env *C.JNIEnv) {
+ width, height := C.ANativeWindow_getWidth(w.win), C.ANativeWindow_getHeight(w.win)
+ if width == 0 || height == 0 {
+ return
+ }
+ w.setStage(system.StageRunning)
+ w.draw(env, true)
+}
+
+func (w *window) setStage(stage system.Stage) {
+ if stage == w.stage {
+ return
+ }
+ w.stage = stage
+ w.callbacks.Event(system.StageEvent{stage})
+}
+
+func (w *window) setVisual(visID int) error {
+ if C.ANativeWindow_setBuffersGeometry(w.win, 0, 0, C.int32_t(visID)) != 0 {
+ return errors.New("ANativeWindow_setBuffersGeometry failed")
+ }
+ return nil
+}
+
+func (w *window) nativeWindow() (*C.ANativeWindow, int, int) {
+ width, height := C.ANativeWindow_getWidth(w.win), C.ANativeWindow_getHeight(w.win)
+ return w.win, int(width), int(height)
+}
+
+func (w *window) loadConfig(env *C.JNIEnv, class C.jclass) {
+ dpi := int(C.jni_CallIntMethod(env, w.view, gioView.getDensity))
+ w.fontScale = float32(C.jni_CallFloatMethod(env, w.view, gioView.getFontScale))
+ switch dpi {
+ case C.ACONFIGURATION_DENSITY_NONE,
+ C.ACONFIGURATION_DENSITY_DEFAULT,
+ C.ACONFIGURATION_DENSITY_ANY:
+ // Assume standard density.
+ w.dpi = C.ACONFIGURATION_DENSITY_MEDIUM
+ default:
+ w.dpi = int(dpi)
+ }
+}
+
+func (w *window) SetAnimating(anim bool) {
+ w.animating = anim
+ if anim {
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ callVoidMethod(env, w.view, gioView.postInvalidate)
+ })
+ }
+}
+
+func (w *window) draw(env *C.JNIEnv, sync bool) {
+ size := image.Pt(int(C.ANativeWindow_getWidth(w.win)), int(C.ANativeWindow_getHeight(w.win)))
+ if size != w.config.Size {
+ w.config.Size = size
+ w.callbacks.Event(ConfigEvent{Config: w.config})
+ }
+ if size.X == 0 || size.Y == 0 {
+ return
+ }
+ const inchPrDp = 1.0 / 160
+ ppdp := float32(w.dpi) * inchPrDp
+ w.callbacks.Event(frameEvent{
+ FrameEvent: system.FrameEvent{
+ Now: time.Now(),
+ Size: w.config.Size,
+ Insets: w.insets,
+ Metric: unit.Metric{
+ PxPerDp: ppdp,
+ PxPerSp: w.fontScale * ppdp,
+ },
+ },
+ Sync: sync,
+ })
+ a11yActive, err := callBooleanMethod(env, w.view, gioView.isA11yActive)
+ if err != nil {
+ panic(err)
+ }
+ if a11yActive {
+ if newR, oldR := w.callbacks.SemanticRoot(), w.semantic.rootID; newR != oldR {
+ // Remap focus and hover.
+ if oldR == w.semantic.hoverID {
+ w.semantic.hoverID = newR
+ }
+ if oldR == w.semantic.focusID {
+ w.semantic.focusID = newR
+ }
+ w.semantic.rootID = newR
+ callVoidMethod(env, w.view, gioView.sendA11yChange, jvalue(w.virtualIDFor(newR)))
+ }
+ w.semantic.diffs = w.callbacks.AppendSemanticDiffs(w.semantic.diffs[:0])
+ for _, id := range w.semantic.diffs {
+ callVoidMethod(env, w.view, gioView.sendA11yChange, jvalue(w.virtualIDFor(id)))
+ }
+ }
+}
+
+type keyMapper func(devId, keyCode C.int32_t) rune
+
+func runInJVM(jvm *C.JavaVM, f func(env *C.JNIEnv)) {
+ if jvm == nil {
+ panic("nil JVM")
+ }
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+ var env *C.JNIEnv
+ if res := C.jni_GetEnv(jvm, &env, C.JNI_VERSION_1_6); res != C.JNI_OK {
+ if res != C.JNI_EDETACHED {
+ panic(fmt.Errorf("JNI GetEnv failed with error %d", res))
+ }
+ if C.jni_AttachCurrentThread(jvm, &env, nil) != C.JNI_OK {
+ panic(errors.New("runInJVM: AttachCurrentThread failed"))
+ }
+ defer C.jni_DetachCurrentThread(jvm)
+ }
+
+ f(env)
+}
+
+func convertKeyCode(code C.jint) (string, bool) {
+ var n string
+ switch code {
+ case C.AKEYCODE_DPAD_UP:
+ n = key.NameUpArrow
+ case C.AKEYCODE_DPAD_DOWN:
+ n = key.NameDownArrow
+ case C.AKEYCODE_DPAD_LEFT:
+ n = key.NameLeftArrow
+ case C.AKEYCODE_DPAD_RIGHT:
+ n = key.NameRightArrow
+ case C.AKEYCODE_FORWARD_DEL:
+ n = key.NameDeleteForward
+ case C.AKEYCODE_DEL:
+ n = key.NameDeleteBackward
+ case C.AKEYCODE_NUMPAD_ENTER:
+ n = key.NameEnter
+ case C.AKEYCODE_ENTER:
+ n = key.NameEnter
+ default:
+ return "", false
+ }
+ return n, true
+}
+
+//export Java_org_gioui_GioView_onKeyEvent
+func Java_org_gioui_GioView_onKeyEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, keyCode, r C.jint, t C.jlong) {
+ w := views[handle]
+ if n, ok := convertKeyCode(keyCode); ok {
+ w.callbacks.Event(key.Event{Name: n})
+ }
+ if r != 0 && r != '\n' { // Checking for "\n" to prevent duplication with key.NameEnter (gio#224).
+ w.callbacks.Event(key.EditEvent{Text: string(rune(r))})
+ }
+}
+
+//export Java_org_gioui_GioView_onTouchEvent
+func Java_org_gioui_GioView_onTouchEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, action, pointerID, tool C.jint, x, y, scrollX, scrollY C.jfloat, jbtns C.jint, t C.jlong) {
+ w := views[handle]
+ var typ pointer.Type
+ switch action {
+ case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN:
+ typ = pointer.Press
+ case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP:
+ typ = pointer.Release
+ case C.AMOTION_EVENT_ACTION_CANCEL:
+ typ = pointer.Cancel
+ case C.AMOTION_EVENT_ACTION_MOVE:
+ typ = pointer.Move
+ case C.AMOTION_EVENT_ACTION_SCROLL:
+ typ = pointer.Scroll
+ default:
+ return
+ }
+ var src pointer.Source
+ var btns pointer.Buttons
+ if jbtns&C.AMOTION_EVENT_BUTTON_PRIMARY != 0 {
+ btns |= pointer.ButtonPrimary
+ }
+ if jbtns&C.AMOTION_EVENT_BUTTON_SECONDARY != 0 {
+ btns |= pointer.ButtonSecondary
+ }
+ if jbtns&C.AMOTION_EVENT_BUTTON_TERTIARY != 0 {
+ btns |= pointer.ButtonTertiary
+ }
+ switch tool {
+ case C.AMOTION_EVENT_TOOL_TYPE_FINGER:
+ src = pointer.Touch
+ case C.AMOTION_EVENT_TOOL_TYPE_STYLUS:
+ src = pointer.Touch
+ case C.AMOTION_EVENT_TOOL_TYPE_MOUSE:
+ src = pointer.Mouse
+ case C.AMOTION_EVENT_TOOL_TYPE_UNKNOWN:
+ // For example, triggered via 'adb shell input tap'.
+ // Instead of discarding it, treat it as a touch event.
+ src = pointer.Touch
+ default:
+ return
+ }
+ w.callbacks.Event(pointer.Event{
+ Type: typ,
+ Source: src,
+ Buttons: btns,
+ PointerID: pointer.ID(pointerID),
+ Time: time.Duration(t) * time.Millisecond,
+ Position: f32.Point{X: float32(x), Y: float32(y)},
+ Scroll: f32.Pt(float32(scrollX), float32(scrollY)),
+ })
+}
+
+func (w *window) ShowTextInput(show bool) {
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ if show {
+ callVoidMethod(env, w.view, gioView.showTextInput)
+ } else {
+ callVoidMethod(env, w.view, gioView.hideTextInput)
+ }
+ })
+}
+
+func (w *window) SetInputHint(mode key.InputHint) {
+ // Constants defined at https://developer.android.com/reference/android/text/InputType.
+ const (
+ TYPE_NULL = 0
+ TYPE_CLASS_NUMBER = 2
+ TYPE_NUMBER_FLAG_DECIMAL = 8192
+ TYPE_NUMBER_FLAG_SIGNED = 4096
+ TYPE_TEXT_FLAG_NO_SUGGESTIONS = 524288
+ TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 144
+ )
+
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ var m jvalue
+ switch mode {
+ case key.HintNumeric:
+ m = TYPE_CLASS_NUMBER | TYPE_NUMBER_FLAG_DECIMAL | TYPE_NUMBER_FLAG_SIGNED
+ default:
+ // TYPE_NULL, since TYPE_CLASS_TEXT isn't currently supported.
+ m = TYPE_NULL
+ }
+
+ // The TYPE_TEXT_FLAG_NO_SUGGESTIONS and TYPE_TEXT_VARIATION_VISIBLE_PASSWORD are used to fix the
+ // Samsung keyboard compatibility, forcing to disable the suggests/auto-complete. gio#116.
+ m = m | TYPE_TEXT_FLAG_NO_SUGGESTIONS | TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+
+ callVoidMethod(env, w.view, gioView.setInputHint, m)
+ })
+}
+
+func javaBool(b bool) C.jboolean {
+ if b {
+ return C.JNI_TRUE
+ } else {
+ return C.JNI_FALSE
+ }
+}
+
+func javaString(env *C.JNIEnv, str string) C.jstring {
+ if str == "" {
+ return 0
+ }
+ utf16Chars := utf16.Encode([]rune(str))
+ return C.jni_NewString(env, (*C.jchar)(unsafe.Pointer(&utf16Chars[0])), C.int(len(utf16Chars)))
+}
+
+func varArgs(args []jvalue) *C.jvalue {
+ if len(args) == 0 {
+ return nil
+ }
+ return (*C.jvalue)(unsafe.Pointer(&args[0]))
+}
+
+func callStaticVoidMethod(env *C.JNIEnv, cls C.jclass, method C.jmethodID, args ...jvalue) error {
+ C.jni_CallStaticVoidMethodA(env, cls, method, varArgs(args))
+ return exception(env)
+}
+
+func callStaticObjectMethod(env *C.JNIEnv, cls C.jclass, method C.jmethodID, args ...jvalue) (C.jobject, error) {
+ res := C.jni_CallStaticObjectMethodA(env, cls, method, varArgs(args))
+ return res, exception(env)
+}
+
+func callVoidMethod(env *C.JNIEnv, obj C.jobject, method C.jmethodID, args ...jvalue) error {
+ C.jni_CallVoidMethodA(env, obj, method, varArgs(args))
+ return exception(env)
+}
+
+func callBooleanMethod(env *C.JNIEnv, obj C.jobject, method C.jmethodID, args ...jvalue) (bool, error) {
+ res := C.jni_CallBooleanMethodA(env, obj, method, varArgs(args))
+ return res == C.JNI_TRUE, exception(env)
+}
+
+func callObjectMethod(env *C.JNIEnv, obj C.jobject, method C.jmethodID, args ...jvalue) (C.jobject, error) {
+ res := C.jni_CallObjectMethodA(env, obj, method, varArgs(args))
+ return res, exception(env)
+}
+
+func newObject(env *C.JNIEnv, cls C.jclass, method C.jmethodID, args ...jvalue) (C.jobject, error) {
+ res := C.jni_NewObjectA(env, cls, method, varArgs(args))
+ return res, exception(env)
+}
+
+// exception returns an error corresponding to the pending
+// exception, or nil if no exception is pending. The pending
+// exception is cleared.
+func exception(env *C.JNIEnv) error {
+ thr := C.jni_ExceptionOccurred(env)
+ if thr == 0 {
+ return nil
+ }
+ C.jni_ExceptionClear(env)
+ cls := getObjectClass(env, C.jobject(thr))
+ toString := getMethodID(env, cls, "toString", "()Ljava/lang/String;")
+ msg, err := callObjectMethod(env, C.jobject(thr), toString)
+ if err != nil {
+ return err
+ }
+ return errors.New(goString(env, C.jstring(msg)))
+}
+
+func getObjectClass(env *C.JNIEnv, obj C.jobject) C.jclass {
+ if obj == 0 {
+ panic("null object")
+ }
+ cls := C.jni_GetObjectClass(env, C.jobject(obj))
+ if err := exception(env); err != nil {
+ // GetObjectClass should never fail.
+ panic(err)
+ }
+ return cls
+}
+
+// goString converts the JVM jstring to a Go string.
+func goString(env *C.JNIEnv, str C.jstring) string {
+ if str == 0 {
+ return ""
+ }
+ strlen := C.jni_GetStringLength(env, C.jstring(str))
+ chars := C.jni_GetStringChars(env, C.jstring(str))
+ var utf16Chars []uint16
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&utf16Chars))
+ hdr.Data = uintptr(unsafe.Pointer(chars))
+ hdr.Cap = int(strlen)
+ hdr.Len = int(strlen)
+ utf8 := utf16.Decode(utf16Chars)
+ return string(utf8)
+}
+
+func findClass(env *C.JNIEnv, name string) C.jclass {
+ cn := C.CString(name)
+ defer C.free(unsafe.Pointer(cn))
+ return C.jni_FindClass(env, cn)
+}
+
+func osMain() {
+}
+
+func newWindow(window *callbacks, options []Option) error {
+ mainWindow.in <- windowAndConfig{window, options}
+ return <-mainWindow.errs
+}
+
+func (w *window) WriteClipboard(s string) {
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ jstr := javaString(env, s)
+ callStaticVoidMethod(env, android.gioCls, android.mwriteClipboard,
+ jvalue(android.appCtx), jvalue(jstr))
+ })
+}
+
+func (w *window) ReadClipboard() {
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ c, err := callStaticObjectMethod(env, android.gioCls, android.mreadClipboard,
+ jvalue(android.appCtx))
+ if err != nil {
+ return
+ }
+ content := goString(env, C.jstring(c))
+ w.callbacks.Event(clipboard.Event{Text: content})
+ })
+}
+
+func (w *window) Configure(options []Option) {
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ prev := w.config
+ cnf := w.config
+ cnf.apply(unit.Metric{}, options)
+ if prev.Orientation != cnf.Orientation {
+ w.config.Orientation = cnf.Orientation
+ setOrientation(env, w.view, cnf.Orientation)
+ }
+ if prev.NavigationColor != cnf.NavigationColor {
+ w.config.NavigationColor = cnf.NavigationColor
+ setNavigationColor(env, w.view, cnf.NavigationColor)
+ }
+ if prev.StatusColor != cnf.StatusColor {
+ w.config.StatusColor = cnf.StatusColor
+ setStatusColor(env, w.view, cnf.StatusColor)
+ }
+ if prev.Mode != cnf.Mode {
+ switch cnf.Mode {
+ case Fullscreen:
+ callVoidMethod(env, w.view, gioView.setFullscreen, C.JNI_TRUE)
+ w.config.Mode = Fullscreen
+ case Windowed:
+ callVoidMethod(env, w.view, gioView.setFullscreen, C.JNI_FALSE)
+ w.config.Mode = Windowed
+ }
+ }
+ if w.config != prev {
+ w.callbacks.Event(ConfigEvent{Config: w.config})
+ }
+ })
+}
+
+func (w *window) Raise() {}
+
+func (w *window) SetCursor(name pointer.CursorName) {
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ setCursor(env, w.view, name)
+ })
+}
+
+func (w *window) Wakeup() {
+ runOnMain(func(env *C.JNIEnv) {
+ w.callbacks.Event(wakeupEvent{})
+ })
+}
+
+func setCursor(env *C.JNIEnv, view C.jobject, name pointer.CursorName) {
+ var curID int
+ switch name {
+ default:
+ fallthrough
+ case pointer.CursorDefault:
+ curID = 1000 // TYPE_ARROW
+ case pointer.CursorText:
+ curID = 1008 // TYPE_TEXT
+ case pointer.CursorPointer:
+ curID = 1002 // TYPE_HAND
+ case pointer.CursorCrossHair:
+ curID = 1007 // TYPE_CROSSHAIR
+ case pointer.CursorColResize:
+ curID = 1014 // TYPE_HORIZONTAL_DOUBLE_ARROW
+ case pointer.CursorRowResize:
+ curID = 1015 // TYPE_VERTICAL_DOUBLE_ARROW
+ case pointer.CursorNone:
+ curID = 0 // TYPE_NULL
+ }
+ callVoidMethod(env, view, gioView.setCursor, jvalue(curID))
+}
+
+func setOrientation(env *C.JNIEnv, view C.jobject, mode Orientation) {
+ var (
+ id int
+ idFallback int // Used only for SDK 17 or older.
+ )
+ // Constants defined at https://developer.android.com/reference/android/content/pm/ActivityInfo.
+ switch mode {
+ case AnyOrientation:
+ id, idFallback = 2, 2 // SCREEN_ORIENTATION_USER
+ case LandscapeOrientation:
+ id, idFallback = 11, 0 // SCREEN_ORIENTATION_USER_LANDSCAPE (or SCREEN_ORIENTATION_LANDSCAPE)
+ case PortraitOrientation:
+ id, idFallback = 12, 1 // SCREEN_ORIENTATION_USER_PORTRAIT (or SCREEN_ORIENTATION_PORTRAIT)
+ }
+ callVoidMethod(env, view, gioView.setOrientation, jvalue(id), jvalue(idFallback))
+}
+
+func setStatusColor(env *C.JNIEnv, view C.jobject, color color.NRGBA) {
+ callVoidMethod(env, view, gioView.setStatusColor,
+ jvalue(uint32(color.A)<<24|uint32(color.R)<<16|uint32(color.G)<<8|uint32(color.B)),
+ jvalue(int(f32color.LinearFromSRGB(color).Luminance()*255)),
+ )
+}
+
+func setNavigationColor(env *C.JNIEnv, view C.jobject, color color.NRGBA) {
+ callVoidMethod(env, view, gioView.setNavigationColor,
+ jvalue(uint32(color.A)<<24|uint32(color.R)<<16|uint32(color.G)<<8|uint32(color.B)),
+ jvalue(int(f32color.LinearFromSRGB(color).Luminance()*255)),
+ )
+}
+
+// Close the window. Not implemented for Android.
+func (w *window) Close() {}
+
+// Maximize maximizes the window. Not implemented for Android.
+func (w *window) Maximize() {}
+
+// Center the window. Not implemented for Android.
+func (w *window) Center() {}
+
+// runOnMain runs a function on the Java main thread.
+func runOnMain(f func(env *C.JNIEnv)) {
+ go func() {
+ mainFuncs <- f
+ runInJVM(javaVM(), func(env *C.JNIEnv) {
+ callStaticVoidMethod(env, android.gioCls, android.mwakeupMainThread)
+ })
+ }()
+}
+
+//export Java_org_gioui_Gio_scheduleMainFuncs
+func Java_org_gioui_Gio_scheduleMainFuncs(env *C.JNIEnv, cls C.jclass) {
+ for {
+ select {
+ case f := <-mainFuncs:
+ f(env)
+ default:
+ return
+ }
+ }
+}
+
+func (_ ViewEvent) ImplementsEvent() {}
diff --git a/vendor/gioui.org/app/internal/window/os_darwin.go b/vendor/gioui.org/app/os_darwin.go
index a3b77dc..c0554db 100644
--- a/vendor/gioui.org/app/internal/window/os_darwin.go
+++ b/vendor/gioui.org/app/os_darwin.go
@@ -1,18 +1,33 @@
// SPDX-License-Identifier: Unlicense OR MIT
-package window
+package app
/*
#include <Foundation/Foundation.h>
__attribute__ ((visibility ("hidden"))) void gio_wakeupMainThread(void);
-__attribute__ ((visibility ("hidden"))) NSUInteger gio_nsstringLength(CFTypeRef str);
-__attribute__ ((visibility ("hidden"))) void gio_nsstringGetCharacters(CFTypeRef str, unichar *chars, NSUInteger loc, NSUInteger length);
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createDisplayLink(void);
__attribute__ ((visibility ("hidden"))) void gio_releaseDisplayLink(CFTypeRef dl);
__attribute__ ((visibility ("hidden"))) int gio_startDisplayLink(CFTypeRef dl);
__attribute__ ((visibility ("hidden"))) int gio_stopDisplayLink(CFTypeRef dl);
__attribute__ ((visibility ("hidden"))) void gio_setDisplayLinkDisplay(CFTypeRef dl, uint64_t did);
+__attribute__ ((visibility ("hidden"))) void gio_hideCursor();
+__attribute__ ((visibility ("hidden"))) void gio_showCursor();
+__attribute__ ((visibility ("hidden"))) void gio_setCursor(NSUInteger curID);
+
+static bool isMainThread() {
+ return [NSThread isMainThread];
+}
+
+static NSUInteger nsstringLength(CFTypeRef cstr) {
+ NSString *str = (__bridge NSString *)cstr;
+ return [str length];
+}
+
+static void nsstringGetCharacters(CFTypeRef cstr, unichar *chars, NSUInteger loc, NSUInteger length) {
+ NSString *str = (__bridge NSString *)cstr;
+ [str getCharacters:chars range:NSMakeRange(loc, length)];
+}
*/
import "C"
import (
@@ -22,6 +37,8 @@ import (
"time"
"unicode/utf16"
"unsafe"
+
+ "gioui.org/io/pointer"
)
// displayLink is the state for a display link (CVDisplayLinkRef on macOS,
@@ -50,6 +67,10 @@ var mainFuncs = make(chan func(), 1)
// runOnMain runs the function on the main thread.
func runOnMain(f func()) {
+ if C.isMainThread() {
+ f()
+ return
+ }
go func() {
mainFuncs <- f
C.gio_wakeupMainThread()
@@ -71,13 +92,16 @@ func gio_dispatchMainFuncs() {
// nsstringToString converts a NSString to a Go string, and
// releases the original string.
func nsstringToString(str C.CFTypeRef) string {
+ if str == 0 {
+ return ""
+ }
defer C.CFRelease(str)
- n := C.gio_nsstringLength(str)
+ n := C.nsstringLength(str)
if n == 0 {
return ""
}
chars := make([]uint16, n)
- C.gio_nsstringGetCharacters(str, (*C.unichar)(unsafe.Pointer(&chars[0])), 0, n)
+ C.nsstringGetCharacters(str, (*C.unichar)(unsafe.Pointer(&chars[0])), 0, n)
utf8 := utf16.Decode(chars)
return string(utf8)
}
@@ -169,3 +193,45 @@ func gio_onFrameCallback(dl C.CFTypeRef) {
}
}
}
+
+// windowSetCursor updates the cursor from the current one to a new one
+// and returns the new one.
+func windowSetCursor(from, to pointer.CursorName) pointer.CursorName {
+ if from == to {
+ return to
+ }
+ var curID int
+ switch to {
+ default:
+ to = pointer.CursorDefault
+ fallthrough
+ case pointer.CursorDefault:
+ curID = 1
+ case pointer.CursorText:
+ curID = 2
+ case pointer.CursorPointer:
+ curID = 3
+ case pointer.CursorCrossHair:
+ curID = 4
+ case pointer.CursorColResize:
+ curID = 5
+ case pointer.CursorRowResize:
+ curID = 6
+ case pointer.CursorGrab:
+ curID = 7
+ case pointer.CursorNone:
+ C.gio_hideCursor()
+ return to
+ }
+ if from == pointer.CursorNone {
+ C.gio_showCursor()
+ }
+ C.gio_setCursor(C.NSUInteger(curID))
+ return to
+}
+
+func (w *window) Wakeup() {
+ runOnMain(func() {
+ w.w.Event(wakeupEvent{})
+ })
+}
diff --git a/vendor/gioui.org/app/os_darwin.m b/vendor/gioui.org/app/os_darwin.m
new file mode 100644
index 0000000..772cc28
--- /dev/null
+++ b/vendor/gioui.org/app/os_darwin.m
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+@import Dispatch;
+@import Foundation;
+
+#include "_cgo_export.h"
+
+void gio_wakeupMainThread(void) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ gio_dispatchMainFuncs();
+ });
+}
diff --git a/vendor/gioui.org/app/internal/window/os_ios.go b/vendor/gioui.org/app/os_ios.go
index 1865454..f6f6dea 100644
--- a/vendor/gioui.org/app/internal/window/os_ios.go
+++ b/vendor/gioui.org/app/os_ios.go
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: Unlicense OR MIT
+//go:build darwin && ios
// +build darwin,ios
-package window
+package app
/*
#cgo CFLAGS: -DGLES_SILENCE_DEPRECATION -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c
@@ -17,14 +18,55 @@ struct drawParams {
CGFloat top, right, bottom, left;
};
-__attribute__ ((visibility ("hidden"))) void gio_showTextInput(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) void gio_hideTextInput(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) void gio_addLayerToView(CFTypeRef viewRef, CFTypeRef layerRef);
-__attribute__ ((visibility ("hidden"))) void gio_updateView(CFTypeRef viewRef, CFTypeRef layerRef);
-__attribute__ ((visibility ("hidden"))) void gio_removeLayer(CFTypeRef layerRef);
-__attribute__ ((visibility ("hidden"))) struct drawParams gio_viewDrawParams(CFTypeRef viewRef);
-__attribute__ ((visibility ("hidden"))) CFTypeRef gio_readClipboard(void);
-__attribute__ ((visibility ("hidden"))) void gio_writeClipboard(unichar *chars, NSUInteger length);
+static void writeClipboard(unichar *chars, NSUInteger length) {
+ @autoreleasepool {
+ NSString *s = [NSString string];
+ if (length > 0) {
+ s = [NSString stringWithCharacters:chars length:length];
+ }
+ UIPasteboard *p = UIPasteboard.generalPasteboard;
+ p.string = s;
+ }
+}
+
+static CFTypeRef readClipboard(void) {
+ @autoreleasepool {
+ UIPasteboard *p = UIPasteboard.generalPasteboard;
+ return (__bridge_retained CFTypeRef)p.string;
+ }
+}
+
+static void showTextInput(CFTypeRef viewRef) {
+ UIView *view = (__bridge UIView *)viewRef;
+ [view becomeFirstResponder];
+}
+
+static void hideTextInput(CFTypeRef viewRef) {
+ UIView *view = (__bridge UIView *)viewRef;
+ [view resignFirstResponder];
+}
+
+static struct drawParams viewDrawParams(CFTypeRef viewRef) {
+ UIView *v = (__bridge UIView *)viewRef;
+ struct drawParams params;
+ CGFloat scale = v.layer.contentsScale;
+ // Use 163 as the standard ppi on iOS.
+ params.dpi = 163*scale;
+ params.sdpi = params.dpi;
+ UIEdgeInsets insets = v.layoutMargins;
+ if (@available(iOS 11.0, tvOS 11.0, *)) {
+ UIFontMetrics *metrics = [UIFontMetrics defaultMetrics];
+ params.sdpi = [metrics scaledValueForValue:params.sdpi];
+ insets = v.safeAreaInsets;
+ }
+ params.width = v.bounds.size.width*scale;
+ params.height = v.bounds.size.height*scale;
+ params.top = insets.top*scale;
+ params.right = insets.right*scale;
+ params.bottom = insets.bottom*scale;
+ params.left = insets.left*scale;
+ return params;
+}
*/
import "C"
@@ -32,33 +74,36 @@ import (
"image"
"runtime"
"runtime/debug"
- "sync/atomic"
"time"
"unicode/utf16"
"unsafe"
"gioui.org/f32"
+ "gioui.org/io/clipboard"
"gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/io/system"
"gioui.org/unit"
)
+type ViewEvent struct {
+ // ViewController is a CFTypeRef for the UIViewController backing a Window.
+ ViewController uintptr
+}
+
type window struct {
view C.CFTypeRef
- w Callbacks
+ w *callbacks
displayLink *displayLink
- layer C.CFTypeRef
- visible atomic.Value
+ visible bool
+ cursor pointer.CursorName
pointerMap []C.CFTypeRef
}
var mainWindow = newWindowRendezvous()
-var layerFactory func() uintptr
-
var views = make(map[C.CFTypeRef]*window)
func init() {
@@ -67,7 +112,7 @@ func init() {
}
//export onCreate
-func onCreate(view C.CFTypeRef) {
+func onCreate(view, controller C.CFTypeRef) {
w := &window{
view: view,
}
@@ -81,11 +126,9 @@ func onCreate(view C.CFTypeRef) {
wopts := <-mainWindow.out
w.w = wopts.window
w.w.SetDriver(w)
- w.visible.Store(false)
- w.layer = C.CFTypeRef(layerFactory())
- C.gio_addLayerToView(view, w.layer)
views[view] = w
w.w.Event(system.StageEvent{Stage: system.StagePaused})
+ w.w.Event(ViewEvent{ViewController: uintptr(controller)})
}
//export gio_onDraw
@@ -95,18 +138,17 @@ func gio_onDraw(view C.CFTypeRef) {
}
func (w *window) draw(sync bool) {
- params := C.gio_viewDrawParams(w.view)
+ params := C.viewDrawParams(w.view)
if params.width == 0 || params.height == 0 {
return
}
- wasVisible := w.isVisible()
- w.visible.Store(true)
- C.gio_updateView(w.view, w.layer)
+ wasVisible := w.visible
+ w.visible = true
if !wasVisible {
w.w.Event(system.StageEvent{Stage: system.StageRunning})
}
const inchPrDp = 1.0 / 163
- w.w.Event(FrameEvent{
+ w.w.Event(frameEvent{
FrameEvent: system.FrameEvent{
Now: time.Now(),
Size: image.Point{
@@ -131,7 +173,7 @@ func (w *window) draw(sync bool) {
//export onStop
func onStop(view C.CFTypeRef) {
w := views[view]
- w.visible.Store(false)
+ w.visible = false
w.w.Event(system.StageEvent{Stage: system.StagePaused})
}
@@ -139,11 +181,9 @@ func onStop(view C.CFTypeRef) {
func onDestroy(view C.CFTypeRef) {
w := views[view]
delete(views, view)
+ w.w.Event(ViewEvent{})
w.w.Event(system.DestroyEvent{})
w.displayLink.Close()
- C.gio_removeLayer(w.layer)
- C.CFRelease(w.layer)
- w.layer = 0
w.view = 0
}
@@ -220,23 +260,23 @@ func onTouch(last C.int, view, touchRef C.CFTypeRef, phase C.NSInteger, x, y C.C
}
func (w *window) ReadClipboard() {
- runOnMain(func() {
- content := nsstringToString(C.gio_readClipboard())
- w.w.Event(system.ClipboardEvent{Text: content})
- })
+ content := nsstringToString(C.readClipboard())
+ w.w.Event(clipboard.Event{Text: content})
}
func (w *window) WriteClipboard(s string) {
u16 := utf16.Encode([]rune(s))
- runOnMain(func() {
- var chars *C.unichar
- if len(u16) > 0 {
- chars = (*C.unichar)(unsafe.Pointer(&u16[0]))
- }
- C.gio_writeClipboard(chars, C.NSUInteger(len(u16)))
- })
+ var chars *C.unichar
+ if len(u16) > 0 {
+ chars = (*C.unichar)(unsafe.Pointer(&u16[0]))
+ }
+ C.writeClipboard(chars, C.NSUInteger(len(u16)))
}
+func (w *window) Configure([]Option) {}
+
+func (w *window) Raise() {}
+
func (w *window) SetAnimating(anim bool) {
v := w.view
if v == 0 {
@@ -249,6 +289,10 @@ func (w *window) SetAnimating(anim bool) {
}
}
+func (w *window) SetCursor(name pointer.CursorName) {
+ w.cursor = windowSetCursor(w.cursor, name)
+}
+
func (w *window) onKeyCommand(name string) {
w.w.Event(key.Event{
Name: name,
@@ -275,42 +319,40 @@ func (w *window) lookupTouch(last bool, touch C.CFTypeRef) pointer.ID {
return pointer.ID(id)
}
-func (w *window) contextLayer() uintptr {
- return uintptr(w.layer)
-}
-
-func (w *window) isVisible() bool {
- return w.visible.Load().(bool)
+func (w *window) contextView() C.CFTypeRef {
+ return w.view
}
func (w *window) ShowTextInput(show bool) {
- v := w.view
- if v == 0 {
- return
+ if show {
+ C.showTextInput(w.view)
+ } else {
+ C.hideTextInput(w.view)
}
- C.CFRetain(v)
- runOnMain(func() {
- defer C.CFRelease(v)
- if show {
- C.gio_showTextInput(w.view)
- } else {
- C.gio_hideTextInput(w.view)
- }
- })
}
+func (w *window) SetInputHint(_ key.InputHint) {}
+
// Close the window. Not implemented for iOS.
func (w *window) Close() {}
-func NewWindow(win Callbacks, opts *Options) error {
- mainWindow.in <- windowAndOptions{win, opts}
+// Maximize the window. Not implemented for iOS.
+func (w *window) Maximize() {}
+
+// Center the window. Not implemented for iOS.
+func (w *window) Center() {}
+
+func newWindow(win *callbacks, options []Option) error {
+ mainWindow.in <- windowAndConfig{win, options}
return <-mainWindow.errs
}
-func Main() {
+func osMain() {
}
//export gio_runMain
func gio_runMain() {
runMain()
}
+
+func (_ ViewEvent) ImplementsEvent() {}
diff --git a/vendor/gioui.org/app/internal/window/os_ios.m b/vendor/gioui.org/app/os_ios.m
index 66830e4..94f254b 100644
--- a/vendor/gioui.org/app/internal/window/os_ios.m
+++ b/vendor/gioui.org/app/os_ios.m
@@ -8,6 +8,8 @@
#include "_cgo_export.h"
#include "framework_ios.h"
+__attribute__ ((visibility ("hidden"))) Class gio_layerClass(void);
+
@interface GioView: UIView <UIKeyInput>
@end
@@ -28,7 +30,7 @@ CGFloat _keyboardHeight;
#endif
drawView.preservesSuperviewLayoutMargins = YES;
drawView.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0);
- onCreate((__bridge CFTypeRef)drawView);
+ onCreate((__bridge CFTypeRef)drawView, (__bridge CFTypeRef)self);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillChange:)
name:UIKeyboardWillShowNotification
@@ -125,6 +127,9 @@ NSArray<UIKeyCommand *> *_keyCommands;
gio_onFrameCallback((__bridge CFTypeRef)link);
}
++ (Class)layerClass {
+ return gio_layerClass();
+}
- (void)willMoveToWindow:(UIWindow *)newWindow {
if (self.window != nil) {
[[NSNotificationCenter defaultCenter] removeObserver:self
@@ -157,9 +162,6 @@ NSArray<UIKeyCommand *> *_keyCommands;
}
}
-- (void)dealloc {
-}
-
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
handleTouches(0, self, touches, event);
}
@@ -229,74 +231,6 @@ NSArray<UIKeyCommand *> *_keyCommands;
}
@end
-void gio_writeClipboard(unichar *chars, NSUInteger length) {
- @autoreleasepool {
- NSString *s = [NSString string];
- if (length > 0) {
- s = [NSString stringWithCharacters:chars length:length];
- }
- UIPasteboard *p = UIPasteboard.generalPasteboard;
- p.string = s;
- }
-}
-
-CFTypeRef gio_readClipboard(void) {
- @autoreleasepool {
- UIPasteboard *p = UIPasteboard.generalPasteboard;
- return (__bridge_retained CFTypeRef)p.string;
- }
-}
-
-void gio_showTextInput(CFTypeRef viewRef) {
- UIView *view = (__bridge UIView *)viewRef;
- [view becomeFirstResponder];
-}
-
-void gio_hideTextInput(CFTypeRef viewRef) {
- UIView *view = (__bridge UIView *)viewRef;
- [view resignFirstResponder];
-}
-
-void gio_addLayerToView(CFTypeRef viewRef, CFTypeRef layerRef) {
- UIView *view = (__bridge UIView *)viewRef;
- CALayer *layer = (__bridge CALayer *)layerRef;
- [view.layer addSublayer:layer];
-}
-
-void gio_updateView(CFTypeRef viewRef, CFTypeRef layerRef) {
- UIView *view = (__bridge UIView *)viewRef;
- CAEAGLLayer *layer = (__bridge CAEAGLLayer *)layerRef;
- layer.contentsScale = view.contentScaleFactor;
- layer.bounds = view.bounds;
-}
-
-void gio_removeLayer(CFTypeRef layerRef) {
- CALayer *layer = (__bridge CALayer *)layerRef;
- [layer removeFromSuperlayer];
-}
-
-struct drawParams gio_viewDrawParams(CFTypeRef viewRef) {
- UIView *v = (__bridge UIView *)viewRef;
- struct drawParams params;
- CGFloat scale = v.layer.contentsScale;
- // Use 163 as the standard ppi on iOS.
- params.dpi = 163*scale;
- params.sdpi = params.dpi;
- UIEdgeInsets insets = v.layoutMargins;
- if (@available(iOS 11.0, tvOS 11.0, *)) {
- UIFontMetrics *metrics = [UIFontMetrics defaultMetrics];
- params.sdpi = [metrics scaledValueForValue:params.sdpi];
- insets = v.safeAreaInsets;
- }
- params.width = v.bounds.size.width*scale;
- params.height = v.bounds.size.height*scale;
- params.top = insets.top*scale;
- params.right = insets.right*scale;
- params.bottom = insets.bottom*scale;
- params.left = insets.left*scale;
- return params;
-}
-
CFTypeRef gio_createDisplayLink(void) {
CADisplayLink *dl = [CADisplayLink displayLinkWithTarget:[GioView class] selector:@selector(onFrameCallback:)];
dl.paused = YES;
@@ -326,3 +260,15 @@ void gio_releaseDisplayLink(CFTypeRef dlref) {
void gio_setDisplayLinkDisplay(CFTypeRef dl, uint64_t did) {
// Nothing to do on iOS.
}
+
+void gio_hideCursor() {
+ // Not supported.
+}
+
+void gio_showCursor() {
+ // Not supported.
+}
+
+void gio_setCursor(NSUInteger curID) {
+ // Not supported.
+}
diff --git a/vendor/gioui.org/app/internal/window/os_js.go b/vendor/gioui.org/app/os_js.go
index 32235df..5b1388c 100644
--- a/vendor/gioui.org/app/internal/window/os_js.go
+++ b/vendor/gioui.org/app/os_js.go
@@ -1,42 +1,62 @@
// SPDX-License-Identifier: Unlicense OR MIT
-package window
+package app
import (
+ "fmt"
"image"
+ "image/color"
"strings"
- "sync"
"syscall/js"
"time"
"unicode"
"unicode/utf8"
+ "gioui.org/internal/f32color"
+
"gioui.org/f32"
+ "gioui.org/io/clipboard"
"gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/io/system"
"gioui.org/unit"
)
+type ViewEvent struct{}
+
type window struct {
window js.Value
+ document js.Value
+ head js.Value
clipboard js.Value
cnv js.Value
tarea js.Value
- w Callbacks
+ w *callbacks
redraw js.Func
clipboardCallback js.Func
requestAnimationFrame js.Value
+ browserHistory js.Value
+ visualViewport js.Value
+ screenOrientation js.Value
cleanfuncs []func()
touches []js.Value
composing bool
+ requestFocus bool
+
+ chanAnimation chan struct{}
+ chanRedraw chan struct{}
- mu sync.Mutex
+ config Config
+ inset f32.Point
scale float32
animating bool
+ // animRequested tracks whether a requestAnimationFrame callback
+ // is pending.
+ animRequested bool
+ wakeups chan struct{}
}
-func NewWindow(win Callbacks, opts *Options) error {
+func newWindow(win *callbacks, options []Option) error {
doc := js.Global().Get("document")
cont := getContainer(doc)
cnv := createCanvas(doc)
@@ -45,29 +65,55 @@ func NewWindow(win Callbacks, opts *Options) error {
cont.Call("appendChild", tarea)
w := &window{
cnv: cnv,
+ document: doc,
tarea: tarea,
window: js.Global().Get("window"),
+ head: doc.Get("head"),
clipboard: js.Global().Get("navigator").Get("clipboard"),
+ wakeups: make(chan struct{}, 1),
}
w.requestAnimationFrame = w.window.Get("requestAnimationFrame")
+ w.browserHistory = w.window.Get("history")
+ w.visualViewport = w.window.Get("visualViewport")
+ if w.visualViewport.IsUndefined() {
+ w.visualViewport = w.window
+ }
+ if screen := w.window.Get("screen"); screen.Truthy() {
+ w.screenOrientation = screen.Get("orientation")
+ }
+ w.chanAnimation = make(chan struct{}, 1)
+ w.chanRedraw = make(chan struct{}, 1)
w.redraw = w.funcOf(func(this js.Value, args []js.Value) interface{} {
- w.animCallback()
+ w.chanAnimation <- struct{}{}
return nil
})
w.clipboardCallback = w.funcOf(func(this js.Value, args []js.Value) interface{} {
content := args[0].String()
- win.Event(system.ClipboardEvent{Text: content})
+ go win.Event(clipboard.Event{Text: content})
return nil
})
w.addEventListeners()
+ w.addHistory()
w.w = win
+
go func() {
+ defer w.cleanup()
w.w.SetDriver(w)
- w.focus()
+ w.Configure(options)
+ w.blur()
w.w.Event(system.StageEvent{Stage: system.StageRunning})
+ w.resize()
w.draw(true)
- select {}
- w.cleanup()
+ for {
+ select {
+ case <-w.wakeups:
+ w.w.Event(wakeupEvent{})
+ case <-w.chanAnimation:
+ w.animCallback()
+ case <-w.chanRedraw:
+ w.draw(true)
+ }
+ }
}()
return nil
}
@@ -116,8 +162,33 @@ func (w *window) cleanup() {
}
func (w *window) addEventListeners() {
- w.addEventListener(w.window, "resize", func(this js.Value, args []js.Value) interface{} {
- w.draw(true)
+ w.addEventListener(w.visualViewport, "resize", func(this js.Value, args []js.Value) interface{} {
+ w.resize()
+ w.chanRedraw <- struct{}{}
+ return nil
+ })
+ w.addEventListener(w.window, "contextmenu", func(this js.Value, args []js.Value) interface{} {
+ args[0].Call("preventDefault")
+ return nil
+ })
+ w.addEventListener(w.window, "popstate", func(this js.Value, args []js.Value) interface{} {
+ ev := &system.CommandEvent{Type: system.CommandBack}
+ w.w.Event(ev)
+ if ev.Cancel {
+ return w.browserHistory.Call("forward")
+ }
+
+ return w.browserHistory.Call("back")
+ })
+ w.addEventListener(w.document, "visibilitychange", func(this js.Value, args []js.Value) interface{} {
+ ev := system.StageEvent{}
+ switch w.document.Get("visibilityState").String() {
+ case "hidden", "prerender", "unloaded":
+ ev.Stage = system.StagePaused
+ default:
+ ev.Stage = system.StageRunning
+ }
+ w.w.Event(ev)
return nil
})
w.addEventListener(w.cnv, "mousemove", func(this js.Value, args []js.Value) interface{} {
@@ -126,6 +197,10 @@ func (w *window) addEventListeners() {
})
w.addEventListener(w.cnv, "mousedown", func(this js.Value, args []js.Value) interface{} {
w.pointerEvent(pointer.Press, 0, 0, args[0])
+ if w.requestFocus {
+ w.focus()
+ w.requestFocus = false
+ }
return nil
})
w.addEventListener(w.cnv, "mouseup", func(this js.Value, args []js.Value) interface{} {
@@ -149,6 +224,10 @@ func (w *window) addEventListeners() {
})
w.addEventListener(w.cnv, "touchstart", func(this js.Value, args []js.Value) interface{} {
w.touchEvent(pointer.Press, args[0])
+ if w.requestFocus {
+ w.focus() // iOS can only focus inside a Touch event.
+ w.requestFocus = false
+ }
return nil
})
w.addEventListener(w.cnv, "touchend", func(this js.Value, args []js.Value) interface{} {
@@ -177,10 +256,15 @@ func (w *window) addEventListeners() {
})
w.addEventListener(w.tarea, "blur", func(this js.Value, args []js.Value) interface{} {
w.w.Event(key.FocusEvent{Focus: false})
+ w.blur()
return nil
})
w.addEventListener(w.tarea, "keydown", func(this js.Value, args []js.Value) interface{} {
- w.keyEvent(args[0])
+ w.keyEvent(args[0], key.Press)
+ return nil
+ })
+ w.addEventListener(w.tarea, "keyup", func(this js.Value, args []js.Value) interface{} {
+ w.keyEvent(args[0], key.Release)
return nil
})
w.addEventListener(w.tarea, "compositionstart", func(this js.Value, args []js.Value) interface{} {
@@ -199,6 +283,18 @@ func (w *window) addEventListeners() {
w.flushInput()
return nil
})
+ w.addEventListener(w.tarea, "paste", func(this js.Value, args []js.Value) interface{} {
+ if w.clipboard.IsUndefined() {
+ return nil
+ }
+ // Prevents duplicated-paste, since "paste" is already handled through Clipboard API.
+ args[0].Call("preventDefault")
+ return nil
+ })
+}
+
+func (w *window) addHistory() {
+ w.browserHistory.Call("pushState", nil, nil, w.window.Get("location").Get("href"))
}
func (w *window) flushInput() {
@@ -209,18 +305,42 @@ func (w *window) flushInput() {
func (w *window) blur() {
w.tarea.Call("blur")
+ w.requestFocus = false
}
func (w *window) focus() {
w.tarea.Call("focus")
+ w.requestFocus = true
+}
+
+func (w *window) keyboard(hint key.InputHint) {
+ var m string
+ switch hint {
+ case key.HintAny:
+ m = "text"
+ case key.HintText:
+ m = "text"
+ case key.HintNumeric:
+ m = "decimal"
+ case key.HintEmail:
+ m = "email"
+ case key.HintURL:
+ m = "url"
+ case key.HintTelephone:
+ m = "tel"
+ default:
+ m = "text"
+ }
+ w.tarea.Set("inputMode", m)
}
-func (w *window) keyEvent(e js.Value) {
+func (w *window) keyEvent(e js.Value, ks key.State) {
k := e.Get("key").String()
if n, ok := translateKey(k); ok {
cmd := key.Event{
Name: n,
Modifiers: modifiersFor(e),
+ State: ks,
}
w.w.Event(cmd)
}
@@ -230,6 +350,10 @@ func (w *window) keyEvent(e js.Value) {
// KeyEvent.
func modifiersFor(e js.Value) key.Modifiers {
var mods key.Modifiers
+ if e.Get("getModifierState").IsUndefined() {
+ // Some browsers doesn't support getModifierState.
+ return mods
+ }
if e.Call("getModifierState", "Alt").Bool() {
mods |= key.ModAlt
}
@@ -248,9 +372,7 @@ func (w *window) touchEvent(typ pointer.Type, e js.Value) {
changedTouches := e.Get("changedTouches")
n := changedTouches.Length()
rect := w.cnv.Call("getBoundingClientRect")
- w.mu.Lock()
scale := w.scale
- w.mu.Unlock()
var mods key.Modifiers
if e.Get("shiftKey").Bool() {
mods |= key.ModShift
@@ -277,7 +399,7 @@ func (w *window) touchEvent(typ pointer.Type, e js.Value) {
Position: pos,
PointerID: pid,
Time: t,
- Modifiers: modifiersFor(e),
+ Modifiers: mods,
})
}
}
@@ -300,9 +422,7 @@ func (w *window) pointerEvent(typ pointer.Type, dx, dy float32, e js.Value) {
rect := w.cnv.Call("getBoundingClientRect")
x -= rect.Get("left").Float()
y -= rect.Get("top").Float()
- w.mu.Lock()
scale := w.scale
- w.mu.Unlock()
pos := f32.Point{
X: float32(x) * scale,
Y: float32(y) * scale,
@@ -315,13 +435,13 @@ func (w *window) pointerEvent(typ pointer.Type, dx, dy float32, e js.Value) {
jbtns := e.Get("buttons").Int()
var btns pointer.Buttons
if jbtns&1 != 0 {
- btns |= pointer.ButtonLeft
+ btns |= pointer.ButtonPrimary
}
if jbtns&2 != 0 {
- btns |= pointer.ButtonRight
+ btns |= pointer.ButtonSecondary
}
if jbtns&4 != 0 {
- btns |= pointer.ButtonMiddle
+ btns |= pointer.ButtonTertiary
}
w.w.Event(pointer.Event{
Type: typ,
@@ -343,7 +463,7 @@ func (w *window) addEventListener(this js.Value, event string, f func(this js.Va
}
// funcOf is like js.FuncOf but adds the js.Func to a list of
-// functions to be released up.
+// functions to be released during cleanup.
func (w *window) funcOf(f func(this js.Value, args []js.Value) interface{}) js.Func {
jsf := js.FuncOf(f)
w.cleanfuncs = append(w.cleanfuncs, jsf.Release)
@@ -351,24 +471,22 @@ func (w *window) funcOf(f func(this js.Value, args []js.Value) interface{}) js.F
}
func (w *window) animCallback() {
- w.mu.Lock()
anim := w.animating
+ w.animRequested = anim
if anim {
w.requestAnimationFrame.Invoke(w.redraw)
}
- w.mu.Unlock()
if anim {
w.draw(false)
}
}
func (w *window) SetAnimating(anim bool) {
- w.mu.Lock()
- defer w.mu.Unlock()
- if anim && !w.animating {
+ w.animating = anim
+ if anim && !w.animRequested {
+ w.animRequested = true
w.requestAnimationFrame.Invoke(w.redraw)
}
- w.animating = anim
}
func (w *window) ReadClipboard() {
@@ -391,6 +509,44 @@ func (w *window) WriteClipboard(s string) {
w.clipboard.Call("writeText", s)
}
+func (w *window) Configure(options []Option) {
+ prev := w.config
+ cnf := w.config
+ cnf.apply(unit.Metric{}, options)
+ if prev.Title != cnf.Title {
+ w.config.Title = cnf.Title
+ w.document.Set("title", cnf.Title)
+ }
+ if prev.Mode != cnf.Mode {
+ w.windowMode(cnf.Mode)
+ }
+ if prev.NavigationColor != cnf.NavigationColor {
+ w.config.NavigationColor = cnf.NavigationColor
+ w.navigationColor(cnf.NavigationColor)
+ }
+ if prev.Orientation != cnf.Orientation {
+ w.config.Orientation = cnf.Orientation
+ w.orientation(cnf.Orientation)
+ }
+ if w.config != prev {
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
+}
+
+func (w *window) Raise() {}
+
+func (w *window) SetCursor(name pointer.CursorName) {
+ style := w.cnv.Get("style")
+ style.Set("cursor", string(name))
+}
+
+func (w *window) Wakeup() {
+ select {
+ case w.wakeups <- struct{}{}:
+ default:
+ }
+}
+
func (w *window) ShowTextInput(show bool) {
// Run in a goroutine to avoid a deadlock if the
// focus change result in an event.
@@ -403,49 +559,119 @@ func (w *window) ShowTextInput(show bool) {
}()
}
+func (w *window) SetInputHint(mode key.InputHint) {
+ w.keyboard(mode)
+}
+
// Close the window. Not implemented for js.
func (w *window) Close() {}
+// Maximize the window. Not implemented for js.
+func (w *window) Maximize() {}
+
+// Center the window. Not implemented for js.
+func (w *window) Center() {}
+
+func (w *window) resize() {
+ w.scale = float32(w.window.Get("devicePixelRatio").Float())
+
+ rect := w.cnv.Call("getBoundingClientRect")
+ size := image.Point{
+ X: int(float32(rect.Get("width").Float()) * w.scale),
+ Y: int(float32(rect.Get("height").Float()) * w.scale),
+ }
+ if size != w.config.Size {
+ w.config.Size = size
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
+
+ if vx, vy := w.visualViewport.Get("width"), w.visualViewport.Get("height"); !vx.IsUndefined() && !vy.IsUndefined() {
+ w.inset.X = float32(w.config.Size.X) - float32(vx.Float())*w.scale
+ w.inset.Y = float32(w.config.Size.Y) - float32(vy.Float())*w.scale
+ }
+
+ if w.config.Size.X == 0 || w.config.Size.Y == 0 {
+ return
+ }
+
+ w.cnv.Set("width", w.config.Size.X)
+ w.cnv.Set("height", w.config.Size.Y)
+}
+
func (w *window) draw(sync bool) {
- width, height, scale, cfg := w.config()
- if cfg == (unit.Metric{}) || width == 0 || height == 0 {
+ size, insets, metric := w.getConfig()
+ if metric == (unit.Metric{}) || size.X == 0 || size.Y == 0 {
return
}
- w.mu.Lock()
- w.scale = float32(scale)
- w.mu.Unlock()
- w.w.Event(FrameEvent{
+ w.w.Event(frameEvent{
FrameEvent: system.FrameEvent{
- Now: time.Now(),
- Size: image.Point{
- X: width,
- Y: height,
- },
- Metric: cfg,
+ Now: time.Now(),
+ Size: size,
+ Insets: insets,
+ Metric: metric,
},
Sync: sync,
})
}
-func (w *window) config() (int, int, float32, unit.Metric) {
- rect := w.cnv.Call("getBoundingClientRect")
- width, height := rect.Get("width").Float(), rect.Get("height").Float()
- scale := w.window.Get("devicePixelRatio").Float()
- width *= scale
- height *= scale
- iw, ih := int(width+.5), int(height+.5)
- // Adjust internal size of canvas if necessary.
- if cw, ch := w.cnv.Get("width").Int(), w.cnv.Get("height").Int(); iw != cw || ih != ch {
- w.cnv.Set("width", iw)
- w.cnv.Set("height", ih)
+func (w *window) getConfig() (image.Point, system.Insets, unit.Metric) {
+ return image.Pt(w.config.Size.X, w.config.Size.Y), system.Insets{
+ Bottom: unit.Px(w.inset.Y),
+ Right: unit.Px(w.inset.X),
+ }, unit.Metric{
+ PxPerDp: w.scale,
+ PxPerSp: w.scale,
+ }
+}
+
+func (w *window) windowMode(mode WindowMode) {
+ switch mode {
+ case Windowed:
+ if !w.document.Get("fullscreenElement").Truthy() {
+ return // Browser is already Windowed.
+ }
+ if !w.document.Get("exitFullscreen").Truthy() {
+ return // Browser doesn't support such feature.
+ }
+ w.document.Call("exitFullscreen")
+ w.config.Mode = Windowed
+ case Fullscreen:
+ elem := w.document.Get("documentElement")
+ if !elem.Get("requestFullscreen").Truthy() {
+ return // Browser doesn't support such feature.
+ }
+ elem.Call("requestFullscreen")
+ w.config.Mode = Fullscreen
+ }
+}
+
+func (w *window) orientation(mode Orientation) {
+ if j := w.screenOrientation; !j.Truthy() || !j.Get("unlock").Truthy() || !j.Get("lock").Truthy() {
+ return // Browser don't support Screen Orientation API.
}
- return iw, ih, float32(scale), unit.Metric{
- PxPerDp: float32(scale),
- PxPerSp: float32(scale),
+
+ switch mode {
+ case AnyOrientation:
+ w.screenOrientation.Call("unlock")
+ case LandscapeOrientation:
+ w.screenOrientation.Call("lock", "landscape").Call("then", w.redraw)
+ case PortraitOrientation:
+ w.screenOrientation.Call("lock", "portrait").Call("then", w.redraw)
}
}
-func Main() {
+func (w *window) navigationColor(c color.NRGBA) {
+ theme := w.head.Call("querySelector", `meta[name="theme-color"]`)
+ if !theme.Truthy() {
+ theme = w.document.Call("createElement", "meta")
+ theme.Set("name", "theme-color")
+ w.head.Call("appendChild", theme)
+ }
+ rgba := f32color.NRGBAToRGBA(c)
+ theme.Set("content", fmt.Sprintf("#%06X", []uint8{rgba.R, rgba.G, rgba.B}))
+}
+
+func osMain() {
select {}
}
@@ -479,7 +705,7 @@ func translateKey(k string) (string, bool) {
case "Tab":
n = key.NameTab
case " ":
- n = "Space"
+ n = key.NameSpace
case "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12":
n = k
default:
@@ -492,3 +718,5 @@ func translateKey(k string) (string, bool) {
}
return n, true
}
+
+func (_ ViewEvent) ImplementsEvent() {}
diff --git a/vendor/gioui.org/app/os_macos.go b/vendor/gioui.org/app/os_macos.go
new file mode 100644
index 0000000..270db6a
--- /dev/null
+++ b/vendor/gioui.org/app/os_macos.go
@@ -0,0 +1,663 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build darwin && !ios
+// +build darwin,!ios
+
+package app
+
+import (
+ "errors"
+ "image"
+ "runtime"
+ "time"
+ "unicode"
+ "unicode/utf16"
+ "unsafe"
+
+ "gioui.org/f32"
+ "gioui.org/io/clipboard"
+ "gioui.org/io/key"
+ "gioui.org/io/pointer"
+ "gioui.org/io/system"
+ "gioui.org/unit"
+
+ _ "gioui.org/internal/cocoainit"
+)
+
+/*
+#cgo CFLAGS: -DGL_SILENCE_DEPRECATION -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c
+
+#include <AppKit/AppKit.h>
+
+#define MOUSE_MOVE 1
+#define MOUSE_UP 2
+#define MOUSE_DOWN 3
+#define MOUSE_SCROLL 4
+
+__attribute__ ((visibility ("hidden"))) void gio_main(void);
+__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createView(void);
+__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat height, CGFloat minWidth, CGFloat minHeight, CGFloat maxWidth, CGFloat maxHeight);
+
+static void writeClipboard(unichar *chars, NSUInteger length) {
+ @autoreleasepool {
+ NSString *s = [NSString string];
+ if (length > 0) {
+ s = [NSString stringWithCharacters:chars length:length];
+ }
+ NSPasteboard *p = NSPasteboard.generalPasteboard;
+ [p declareTypes:@[NSPasteboardTypeString] owner:nil];
+ [p setString:s forType:NSPasteboardTypeString];
+ }
+}
+
+static CFTypeRef readClipboard(void) {
+ @autoreleasepool {
+ NSPasteboard *p = NSPasteboard.generalPasteboard;
+ NSString *content = [p stringForType:NSPasteboardTypeString];
+ return (__bridge_retained CFTypeRef)content;
+ }
+}
+
+static CGFloat viewHeight(CFTypeRef viewRef) {
+ NSView *view = (__bridge NSView *)viewRef;
+ return [view bounds].size.height;
+}
+
+static CGFloat viewWidth(CFTypeRef viewRef) {
+ NSView *view = (__bridge NSView *)viewRef;
+ return [view bounds].size.width;
+}
+
+static CGFloat getScreenBackingScale(void) {
+ return [NSScreen.mainScreen backingScaleFactor];
+}
+
+static CGFloat getViewBackingScale(CFTypeRef viewRef) {
+ NSView *view = (__bridge NSView *)viewRef;
+ return [view.window backingScaleFactor];
+}
+
+static void setNeedsDisplay(CFTypeRef viewRef) {
+ NSView *view = (__bridge NSView *)viewRef;
+ [view setNeedsDisplay:YES];
+}
+
+static NSPoint cascadeTopLeftFromPoint(CFTypeRef windowRef, NSPoint topLeft) {
+ NSWindow *window = (__bridge NSWindow *)windowRef;
+ return [window cascadeTopLeftFromPoint:topLeft];
+}
+
+static void makeKeyAndOrderFront(CFTypeRef windowRef) {
+ NSWindow *window = (__bridge NSWindow *)windowRef;
+ [window makeKeyAndOrderFront:nil];
+}
+
+static void toggleFullScreen(CFTypeRef windowRef) {
+ NSWindow *window = (__bridge NSWindow *)windowRef;
+ [window toggleFullScreen:nil];
+}
+
+static NSWindowStyleMask getWindowStyleMask(CFTypeRef windowRef) {
+ NSWindow *window = (__bridge NSWindow *)windowRef;
+ return [window styleMask];
+}
+
+static void closeWindow(CFTypeRef windowRef) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ [window performClose:nil];
+}
+
+static void setSize(CFTypeRef windowRef, CGFloat width, CGFloat height) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ NSSize size = NSMakeSize(width, height);
+ [window setContentSize:size];
+}
+
+static void setMinSize(CFTypeRef windowRef, CGFloat width, CGFloat height) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ window.contentMinSize = NSMakeSize(width, height);
+}
+
+static void setMaxSize(CFTypeRef windowRef, CGFloat width, CGFloat height) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ window.contentMaxSize = NSMakeSize(width, height);
+}
+
+static void setScreenFrame(CFTypeRef windowRef, CGFloat x, CGFloat y, CGFloat w, CGFloat h) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ NSRect r = NSMakeRect(x, y, w, h);
+ [window setFrame:r display:YES];
+}
+
+static NSRect getScreenFrame(CFTypeRef windowRef) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ return [[window screen] frame];
+}
+
+static void setTitle(CFTypeRef windowRef, const char *title) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ window.title = [NSString stringWithUTF8String: title];
+}
+
+static CFTypeRef layerForView(CFTypeRef viewRef) {
+ NSView *view = (__bridge NSView *)viewRef;
+ return (__bridge CFTypeRef)view.layer;
+}
+
+static void raiseWindow(CFTypeRef windowRef) {
+ NSWindow* window = (__bridge NSWindow *)windowRef;
+ [window makeKeyAndOrderFront:nil];
+}
+
+*/
+import "C"
+
+func init() {
+ // Darwin requires that UI operations happen on the main thread only.
+ runtime.LockOSThread()
+}
+
+// ViewEvent notified the client of changes to the window AppKit handles.
+// The handles are retained until another ViewEvent is sent.
+type ViewEvent struct {
+ // View is a CFTypeRef for the NSView for the window.
+ View uintptr
+ // Layer is a CFTypeRef of the CALayer of View.
+ Layer uintptr
+}
+
+type window struct {
+ view C.CFTypeRef
+ window C.CFTypeRef
+ w *callbacks
+ stage system.Stage
+ displayLink *displayLink
+ cursor pointer.CursorName
+
+ scale float32
+ config Config
+}
+
+// viewMap is the mapping from Cocoa NSViews to Go windows.
+var viewMap = make(map[C.CFTypeRef]*window)
+
+// launched is closed when applicationDidFinishLaunching is called.
+var launched = make(chan struct{})
+
+// nextTopLeft is the offset to use for the next window's call to
+// cascadeTopLeftFromPoint.
+var nextTopLeft C.NSPoint
+
+// mustView is like lookupView, except that it panics
+// if the view isn't mapped.
+func mustView(view C.CFTypeRef) *window {
+ w, ok := lookupView(view)
+ if !ok {
+ panic("no window for view")
+ }
+ return w
+}
+
+func lookupView(view C.CFTypeRef) (*window, bool) {
+ w, exists := viewMap[view]
+ if !exists {
+ return nil, false
+ }
+ return w, true
+}
+
+func deleteView(view C.CFTypeRef) {
+ delete(viewMap, view)
+}
+
+func insertView(view C.CFTypeRef, w *window) {
+ viewMap[view] = w
+}
+
+func (w *window) contextView() C.CFTypeRef {
+ return w.view
+}
+
+func (w *window) ReadClipboard() {
+ content := nsstringToString(C.readClipboard())
+ w.w.Event(clipboard.Event{Text: content})
+}
+
+func (w *window) WriteClipboard(s string) {
+ u16 := utf16.Encode([]rune(s))
+ var chars *C.unichar
+ if len(u16) > 0 {
+ chars = (*C.unichar)(unsafe.Pointer(&u16[0]))
+ }
+ C.writeClipboard(chars, C.NSUInteger(len(u16)))
+}
+
+func (w *window) updateWindowMode() {
+ style := int(C.getWindowStyleMask(w.window))
+ if style&C.NSWindowStyleMaskFullScreen > 0 {
+ w.config.Mode = Fullscreen
+ } else {
+ w.config.Mode = Windowed
+ }
+}
+
+func (w *window) Configure(options []Option) {
+ screenScale := float32(C.getScreenBackingScale())
+ cfg := configFor(screenScale)
+ prev := w.config
+ w.updateWindowMode()
+ cnf := w.config
+ cnf.apply(cfg, options)
+ cnf.Size = cnf.Size.Div(int(screenScale))
+ cnf.MinSize = cnf.MinSize.Div(int(screenScale))
+ cnf.MaxSize = cnf.MaxSize.Div(int(screenScale))
+
+ if cnf.Mode != Fullscreen && prev.Size != cnf.Size {
+ w.config.Size = cnf.Size
+ C.setSize(w.window, C.CGFloat(cnf.Size.X), C.CGFloat(cnf.Size.Y))
+ }
+ if prev.MinSize != cnf.MinSize {
+ w.config.MinSize = cnf.MinSize
+ C.setMinSize(w.window, C.CGFloat(cnf.MinSize.X), C.CGFloat(cnf.MinSize.Y))
+ }
+ if prev.MaxSize != cnf.MaxSize {
+ w.config.MaxSize = cnf.MaxSize
+ C.setMaxSize(w.window, C.CGFloat(cnf.MaxSize.X), C.CGFloat(cnf.MaxSize.Y))
+ }
+
+ if prev.Title != cnf.Title {
+ w.config.Title = cnf.Title
+ title := C.CString(cnf.Title)
+ defer C.free(unsafe.Pointer(title))
+ C.setTitle(w.window, title)
+ }
+ if prev.Mode != cnf.Mode {
+ switch cnf.Mode {
+ case Windowed, Fullscreen:
+ w.config.Mode = cnf.Mode
+ C.toggleFullScreen(w.window)
+ }
+ }
+ if w.config != prev {
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
+}
+
+func (w *window) SetCursor(name pointer.CursorName) {
+ w.cursor = windowSetCursor(w.cursor, name)
+}
+
+func (w *window) ShowTextInput(show bool) {}
+
+func (w *window) SetInputHint(_ key.InputHint) {}
+
+func (w *window) SetAnimating(anim bool) {
+ if anim {
+ w.displayLink.Start()
+ } else {
+ w.displayLink.Stop()
+ }
+}
+
+func (w *window) Raise() {
+ C.raiseWindow(w.window)
+}
+
+func (w *window) runOnMain(f func()) {
+ runOnMain(func() {
+ // Make sure the view is still valid. The window might've been closed
+ // during the switch to the main thread.
+ if w.view != 0 {
+ f()
+ }
+ })
+}
+
+func (w *window) Close() {
+ C.closeWindow(w.window)
+}
+
+// Maximize the window.
+func (w *window) Maximize() {
+ r := C.getScreenFrame(w.window) // the screen size of the window
+ C.setScreenFrame(w.window, C.CGFloat(0), C.CGFloat(0), r.size.width, r.size.height)
+}
+
+// Center the window.
+func (w *window) Center() {
+ r := C.getScreenFrame(w.window) // the screen size of the window
+
+ screenScale := float32(C.getScreenBackingScale())
+ sz := w.config.Size.Div(int(screenScale))
+ x := (int(r.size.width) - sz.X) / 2
+ y := (int(r.size.height) - sz.Y) / 2
+
+ C.setScreenFrame(w.window, C.CGFloat(x), C.CGFloat(y), C.CGFloat(sz.X), C.CGFloat(sz.Y))
+}
+
+func (w *window) setStage(stage system.Stage) {
+ if stage == w.stage {
+ return
+ }
+ w.stage = stage
+ w.w.Event(system.StageEvent{Stage: stage})
+}
+
+//export gio_onKeys
+func gio_onKeys(view C.CFTypeRef, cstr *C.char, ti C.double, mods C.NSUInteger, keyDown C.bool) {
+ str := C.GoString(cstr)
+ kmods := convertMods(mods)
+ ks := key.Release
+ if keyDown {
+ ks = key.Press
+ }
+ w := mustView(view)
+ for _, k := range str {
+ if n, ok := convertKey(k); ok {
+ w.w.Event(key.Event{
+ Name: n,
+ Modifiers: kmods,
+ State: ks,
+ })
+ }
+ }
+}
+
+//export gio_onText
+func gio_onText(view C.CFTypeRef, cstr *C.char) {
+ str := C.GoString(cstr)
+ w := mustView(view)
+ w.w.Event(key.EditEvent{Text: str})
+}
+
+//export gio_onMouse
+func gio_onMouse(view C.CFTypeRef, cdir C.int, cbtns C.NSUInteger, x, y, dx, dy C.CGFloat, ti C.double, mods C.NSUInteger) {
+ var typ pointer.Type
+ switch cdir {
+ case C.MOUSE_MOVE:
+ typ = pointer.Move
+ case C.MOUSE_UP:
+ typ = pointer.Release
+ case C.MOUSE_DOWN:
+ typ = pointer.Press
+ case C.MOUSE_SCROLL:
+ typ = pointer.Scroll
+ default:
+ panic("invalid direction")
+ }
+ var btns pointer.Buttons
+ if cbtns&(1<<0) != 0 {
+ btns |= pointer.ButtonPrimary
+ }
+ if cbtns&(1<<1) != 0 {
+ btns |= pointer.ButtonSecondary
+ }
+ if cbtns&(1<<2) != 0 {
+ btns |= pointer.ButtonTertiary
+ }
+ t := time.Duration(float64(ti)*float64(time.Second) + .5)
+ w := mustView(view)
+ xf, yf := float32(x)*w.scale, float32(y)*w.scale
+ dxf, dyf := float32(dx)*w.scale, float32(dy)*w.scale
+ w.w.Event(pointer.Event{
+ Type: typ,
+ Source: pointer.Mouse,
+ Time: t,
+ Buttons: btns,
+ Position: f32.Point{X: xf, Y: yf},
+ Scroll: f32.Point{X: dxf, Y: dyf},
+ Modifiers: convertMods(mods),
+ })
+}
+
+//export gio_onDraw
+func gio_onDraw(view C.CFTypeRef) {
+ w := mustView(view)
+ w.draw()
+}
+
+//export gio_onFocus
+func gio_onFocus(view C.CFTypeRef, focus C.int) {
+ w := mustView(view)
+ w.w.Event(key.FocusEvent{Focus: focus == 1})
+ w.SetCursor(w.cursor)
+}
+
+//export gio_onChangeScreen
+func gio_onChangeScreen(view C.CFTypeRef, did uint64) {
+ w := mustView(view)
+ w.displayLink.SetDisplayID(did)
+}
+
+func (w *window) draw() {
+ w.scale = float32(C.getViewBackingScale(w.view))
+ wf, hf := float32(C.viewWidth(w.view)), float32(C.viewHeight(w.view))
+ sz := image.Point{
+ X: int(wf*w.scale + .5),
+ Y: int(hf*w.scale + .5),
+ }
+ if sz != w.config.Size {
+ w.config.Size = sz
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
+ if sz.X == 0 || sz.Y == 0 {
+ return
+ }
+ cfg := configFor(w.scale)
+ w.setStage(system.StageRunning)
+ w.w.Event(frameEvent{
+ FrameEvent: system.FrameEvent{
+ Now: time.Now(),
+ Size: w.config.Size,
+ Metric: cfg,
+ },
+ Sync: true,
+ })
+}
+
+func configFor(scale float32) unit.Metric {
+ return unit.Metric{
+ PxPerDp: scale,
+ PxPerSp: scale,
+ }
+}
+
+//export gio_onClose
+func gio_onClose(view C.CFTypeRef) {
+ w := mustView(view)
+ w.w.Event(ViewEvent{})
+ deleteView(view)
+ w.w.Event(system.DestroyEvent{})
+ w.displayLink.Close()
+ C.CFRelease(w.view)
+ C.CFRelease(w.window)
+ w.view = 0
+ w.window = 0
+ w.displayLink = nil
+}
+
+//export gio_onHide
+func gio_onHide(view C.CFTypeRef) {
+ w := mustView(view)
+ w.setStage(system.StagePaused)
+}
+
+//export gio_onShow
+func gio_onShow(view C.CFTypeRef) {
+ w := mustView(view)
+ w.setStage(system.StageRunning)
+}
+
+//export gio_onFullscreen
+func gio_onFullscreen(view C.CFTypeRef) {
+ w := mustView(view)
+ w.config.Mode = Fullscreen
+ w.w.Event(ConfigEvent{Config: w.config})
+}
+
+//export gio_onWindowed
+func gio_onWindowed(view C.CFTypeRef) {
+ w := mustView(view)
+ w.config.Mode = Windowed
+ w.w.Event(ConfigEvent{Config: w.config})
+}
+
+//export gio_onAppHide
+func gio_onAppHide() {
+ for _, w := range viewMap {
+ w.setStage(system.StagePaused)
+ }
+}
+
+//export gio_onAppShow
+func gio_onAppShow() {
+ for _, w := range viewMap {
+ w.setStage(system.StageRunning)
+ }
+}
+
+//export gio_onFinishLaunching
+func gio_onFinishLaunching() {
+ close(launched)
+}
+
+func newWindow(win *callbacks, options []Option) error {
+ <-launched
+ errch := make(chan error)
+ runOnMain(func() {
+ w, err := newOSWindow()
+ if err != nil {
+ errch <- err
+ return
+ }
+ errch <- nil
+ w.w = win
+ w.window = C.gio_createWindow(w.view, nil, 0, 0, 0, 0, 0, 0)
+ win.SetDriver(w)
+ w.Configure(options)
+ if nextTopLeft.x == 0 && nextTopLeft.y == 0 {
+ // cascadeTopLeftFromPoint treats (0, 0) as a no-op,
+ // and just returns the offset we need for the first window.
+ nextTopLeft = C.cascadeTopLeftFromPoint(w.window, nextTopLeft)
+ }
+ nextTopLeft = C.cascadeTopLeftFromPoint(w.window, nextTopLeft)
+ C.makeKeyAndOrderFront(w.window)
+ layer := C.layerForView(w.view)
+ w.w.Event(ViewEvent{View: uintptr(w.view), Layer: uintptr(layer)})
+ })
+ return <-errch
+}
+
+func newOSWindow() (*window, error) {
+ view := C.gio_createView()
+ if view == 0 {
+ return nil, errors.New("CreateWindow: failed to create view")
+ }
+ scale := float32(C.getViewBackingScale(view))
+ w := &window{
+ view: view,
+ scale: scale,
+ }
+ dl, err := NewDisplayLink(func() {
+ w.runOnMain(func() {
+ C.setNeedsDisplay(w.view)
+ })
+ })
+ w.displayLink = dl
+ if err != nil {
+ C.CFRelease(view)
+ return nil, err
+ }
+ insertView(view, w)
+ return w, nil
+}
+
+func osMain() {
+ C.gio_main()
+}
+
+func convertKey(k rune) (string, bool) {
+ var n string
+ switch k {
+ case 0x1b:
+ n = key.NameEscape
+ case C.NSLeftArrowFunctionKey:
+ n = key.NameLeftArrow
+ case C.NSRightArrowFunctionKey:
+ n = key.NameRightArrow
+ case C.NSUpArrowFunctionKey:
+ n = key.NameUpArrow
+ case C.NSDownArrowFunctionKey:
+ n = key.NameDownArrow
+ case 0xd:
+ n = key.NameReturn
+ case 0x3:
+ n = key.NameEnter
+ case C.NSHomeFunctionKey:
+ n = key.NameHome
+ case C.NSEndFunctionKey:
+ n = key.NameEnd
+ case 0x7f:
+ n = key.NameDeleteBackward
+ case C.NSDeleteFunctionKey:
+ n = key.NameDeleteForward
+ case C.NSPageUpFunctionKey:
+ n = key.NamePageUp
+ case C.NSPageDownFunctionKey:
+ n = key.NamePageDown
+ case C.NSF1FunctionKey:
+ n = "F1"
+ case C.NSF2FunctionKey:
+ n = "F2"
+ case C.NSF3FunctionKey:
+ n = "F3"
+ case C.NSF4FunctionKey:
+ n = "F4"
+ case C.NSF5FunctionKey:
+ n = "F5"
+ case C.NSF6FunctionKey:
+ n = "F6"
+ case C.NSF7FunctionKey:
+ n = "F7"
+ case C.NSF8FunctionKey:
+ n = "F8"
+ case C.NSF9FunctionKey:
+ n = "F9"
+ case C.NSF10FunctionKey:
+ n = "F10"
+ case C.NSF11FunctionKey:
+ n = "F11"
+ case C.NSF12FunctionKey:
+ n = "F12"
+ case 0x09, 0x19:
+ n = key.NameTab
+ case 0x20:
+ n = key.NameSpace
+ default:
+ k = unicode.ToUpper(k)
+ if !unicode.IsPrint(k) {
+ return "", false
+ }
+ n = string(k)
+ }
+ return n, true
+}
+
+func convertMods(mods C.NSUInteger) key.Modifiers {
+ var kmods key.Modifiers
+ if mods&C.NSAlternateKeyMask != 0 {
+ kmods |= key.ModAlt
+ }
+ if mods&C.NSControlKeyMask != 0 {
+ kmods |= key.ModCtrl
+ }
+ if mods&C.NSCommandKeyMask != 0 {
+ kmods |= key.ModCommand
+ }
+ if mods&C.NSShiftKeyMask != 0 {
+ kmods |= key.ModShift
+ }
+ return kmods
+}
+
+func (_ ViewEvent) ImplementsEvent() {}
diff --git a/vendor/gioui.org/app/internal/window/os_macos.m b/vendor/gioui.org/app/os_macos.m
index b8c0dee..f65099b 100644
--- a/vendor/gioui.org/app/internal/window/os_macos.m
+++ b/vendor/gioui.org/app/os_macos.m
@@ -6,6 +6,8 @@
#include "_cgo_export.h"
+__attribute__ ((visibility ("hidden"))) CALayer *gio_layerFactory(void);
+
@interface GioAppDelegate : NSObject<NSApplicationDelegate>
@end
@@ -21,6 +23,14 @@
NSWindow *window = (NSWindow *)[notification object];
gio_onShow((__bridge CFTypeRef)window.contentView);
}
+- (void)windowWillEnterFullScreen:(NSNotification *)notification {
+ NSWindow *window = (NSWindow *)[notification object];
+ gio_onFullscreen((__bridge CFTypeRef)window.contentView);
+}
+- (void)windowWillExitFullScreen:(NSNotification *)notification {
+ NSWindow *window = (NSWindow *)[notification object];
+ gio_onWindowed((__bridge CFTypeRef)window.contentView);
+}
- (void)windowDidChangeScreen:(NSNotification *)notification {
NSWindow *window = (NSWindow *)[notification object];
CGDirectDisplayID dispID = [[[window screen] deviceDescription][@"NSScreenNumber"] unsignedIntValue];
@@ -29,11 +39,11 @@
}
- (void)windowDidBecomeKey:(NSNotification *)notification {
NSWindow *window = (NSWindow *)[notification object];
- gio_onFocus((__bridge CFTypeRef)window.contentView, YES);
+ gio_onFocus((__bridge CFTypeRef)window.contentView, 1);
}
- (void)windowDidResignKey:(NSNotification *)notification {
NSWindow *window = (NSWindow *)[notification object];
- gio_onFocus((__bridge CFTypeRef)window.contentView, NO);
+ gio_onFocus((__bridge CFTypeRef)window.contentView, 0);
}
- (void)windowWillClose:(NSNotification *)notification {
NSWindow *window = (NSWindow *)[notification object];
@@ -42,49 +52,92 @@
}
@end
-// Delegates are weakly referenced from their peers. Nothing
-// else holds a strong reference to our window delegate, so
-// keep a single global reference instead.
-static GioWindowDelegate *globalWindowDel;
-
-void gio_writeClipboard(unichar *chars, NSUInteger length) {
- @autoreleasepool {
- NSString *s = [NSString string];
- if (length > 0) {
- s = [NSString stringWithCharacters:chars length:length];
- }
- NSPasteboard *p = NSPasteboard.generalPasteboard;
- [p declareTypes:@[NSPasteboardTypeString] owner:nil];
- [p setString:s forType:NSPasteboardTypeString];
+static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFloat dy) {
+ NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
+ if (!event.hasPreciseScrollingDeltas) {
+ // dx and dy are in rows and columns.
+ dx *= 10;
+ dy *= 10;
}
+ // Origin is in the lower left corner. Convert to upper left.
+ CGFloat height = view.bounds.size.height;
+ gio_onMouse((__bridge CFTypeRef)view, typ, [NSEvent pressedMouseButtons], p.x, height - p.y, dx, dy, [event timestamp], [event modifierFlags]);
}
-CFTypeRef gio_readClipboard(void) {
- @autoreleasepool {
- NSPasteboard *p = NSPasteboard.generalPasteboard;
- NSString *content = [p stringForType:NSPasteboardTypeString];
- return (__bridge_retained CFTypeRef)content;
- }
-}
+@interface GioView : NSView <CALayerDelegate>
+@end
-CGFloat gio_viewHeight(CFTypeRef viewRef) {
- NSView *view = (__bridge NSView *)viewRef;
- return [view bounds].size.height;
+@implementation GioView
+- (void)setFrameSize:(NSSize)newSize {
+ [super setFrameSize:newSize];
+ [self setNeedsDisplay:YES];
}
-
-CGFloat gio_viewWidth(CFTypeRef viewRef) {
- NSView *view = (__bridge NSView *)viewRef;
- return [view bounds].size.width;
+// drawRect is called when OpenGL is used, displayLayer otherwise.
+// Don't know why.
+- (void)drawRect:(NSRect)r {
+ gio_onDraw((__bridge CFTypeRef)self);
}
-
-CGFloat gio_getScreenBackingScale(void) {
- return [NSScreen.mainScreen backingScaleFactor];
+- (void)displayLayer:(CALayer *)layer {
+ layer.contentsScale = self.window.backingScaleFactor;
+ gio_onDraw((__bridge CFTypeRef)self);
}
-
-CGFloat gio_getViewBackingScale(CFTypeRef viewRef) {
- NSView *view = (__bridge NSView *)viewRef;
- return [view.window backingScaleFactor];
+- (CALayer *)makeBackingLayer {
+ CALayer *layer = gio_layerFactory();
+ layer.delegate = self;
+ return layer;
+}
+- (void)mouseDown:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_DOWN, 0, 0);
+}
+- (void)mouseUp:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_UP, 0, 0);
+}
+- (void)middleMouseDown:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_DOWN, 0, 0);
+}
+- (void)middletMouseUp:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_UP, 0, 0);
+}
+- (void)rightMouseDown:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_DOWN, 0, 0);
+}
+- (void)rightMouseUp:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_UP, 0, 0);
}
+- (void)mouseMoved:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_MOVE, 0, 0);
+}
+- (void)mouseDragged:(NSEvent *)event {
+ handleMouse(self, event, MOUSE_MOVE, 0, 0);
+}
+- (void)scrollWheel:(NSEvent *)event {
+ CGFloat dx = -event.scrollingDeltaX;
+ CGFloat dy = -event.scrollingDeltaY;
+ handleMouse(self, event, MOUSE_SCROLL, dx, dy);
+}
+- (void)keyDown:(NSEvent *)event {
+ NSString *keys = [event charactersIgnoringModifiers];
+ gio_onKeys((__bridge CFTypeRef)self, (char *)[keys UTF8String], [event timestamp], [event modifierFlags], true);
+ [self interpretKeyEvents:[NSArray arrayWithObject:event]];
+}
+- (void)keyUp:(NSEvent *)event {
+ NSString *keys = [event charactersIgnoringModifiers];
+ gio_onKeys((__bridge CFTypeRef)self, (char *)[keys UTF8String], [event timestamp], [event modifierFlags], false);
+}
+- (void)insertText:(id)string {
+ const char *utf8 = [string UTF8String];
+ gio_onText((__bridge CFTypeRef)self, (char *)utf8);
+}
+- (void)doCommandBySelector:(SEL)sel {
+ // Don't pass commands up the responder chain.
+ // They will end up in a beep.
+}
+@end
+
+// Delegates are weakly referenced from their peers. Nothing
+// else holds a strong reference to our window delegate, so
+// keep a single global reference instead.
+static GioWindowDelegate *globalWindowDel;
static CVReturn displayLinkCallback(CVDisplayLinkRef dl, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) {
gio_onFrameCallback(dl);
@@ -114,14 +167,47 @@ void gio_setDisplayLinkDisplay(CFTypeRef dl, uint64_t did) {
CVDisplayLinkSetCurrentCGDisplay((CVDisplayLinkRef)dl, (CGDirectDisplayID)did);
}
-NSPoint gio_cascadeTopLeftFromPoint(CFTypeRef windowRef, NSPoint topLeft) {
- NSWindow *window = (__bridge NSWindow *)windowRef;
- return [window cascadeTopLeftFromPoint:topLeft];
+void gio_hideCursor() {
+ @autoreleasepool {
+ [NSCursor hide];
+ }
+}
+
+void gio_showCursor() {
+ @autoreleasepool {
+ [NSCursor unhide];
+ }
}
-void gio_makeKeyAndOrderFront(CFTypeRef windowRef) {
- NSWindow *window = (__bridge NSWindow *)windowRef;
- [window makeKeyAndOrderFront:nil];
+void gio_setCursor(NSUInteger curID) {
+ @autoreleasepool {
+ switch (curID) {
+ case 1:
+ [NSCursor.arrowCursor set];
+ break;
+ case 2:
+ [NSCursor.IBeamCursor set];
+ break;
+ case 3:
+ [NSCursor.pointingHandCursor set];
+ break;
+ case 4:
+ [NSCursor.crosshairCursor set];
+ break;
+ case 5:
+ [NSCursor.resizeLeftRightCursor set];
+ break;
+ case 6:
+ [NSCursor.resizeUpDownCursor set];
+ break;
+ case 7:
+ [NSCursor.openHandCursor set];
+ break;
+ default:
+ [NSCursor.arrowCursor set];
+ break;
+ }
+ }
}
CFTypeRef gio_createWindow(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat height, CGFloat minWidth, CGFloat minHeight, CGFloat maxWidth, CGFloat maxHeight) {
@@ -143,7 +229,9 @@ CFTypeRef gio_createWindow(CFTypeRef viewRef, const char *title, CGFloat width,
window.contentMaxSize = NSMakeSize(maxWidth, maxHeight);
}
[window setAcceptsMouseMovedEvents:YES];
- window.title = [NSString stringWithUTF8String: title];
+ if (title != nil) {
+ window.title = [NSString stringWithUTF8String: title];
+ }
NSView *view = (__bridge NSView *)viewRef;
[window setContentView:view];
[window makeFirstResponder:view];
@@ -153,14 +241,20 @@ CFTypeRef gio_createWindow(CFTypeRef viewRef, const char *title, CGFloat width,
}
}
-void gio_close(CFTypeRef windowRef) {
- NSWindow* window = (__bridge NSWindow *)windowRef;
- [window performClose:nil];
+CFTypeRef gio_createView(void) {
+ @autoreleasepool {
+ NSRect frame = NSMakeRect(0, 0, 0, 0);
+ GioView* view = [[GioView alloc] initWithFrame:frame];
+ view.wantsLayer = YES;
+ view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
+ return CFBridgingRetain(view);
+ }
}
@implementation GioAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
- [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+ [NSApp activateIgnoringOtherApps:YES];
gio_onFinishLaunching();
}
- (void)applicationDidHide:(NSNotification *)aNotification {
@@ -176,7 +270,6 @@ void gio_main() {
[NSApplication sharedApplication];
GioAppDelegate *del = [[GioAppDelegate alloc] init];
[NSApp setDelegate:del];
- [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
NSMenuItem *mainMenu = [NSMenuItem new];
diff --git a/vendor/gioui.org/app/os_unix.go b/vendor/gioui.org/app/os_unix.go
new file mode 100644
index 0000000..ee831b3
--- /dev/null
+++ b/vendor/gioui.org/app/os_unix.go
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build (linux && !android) || freebsd || openbsd
+// +build linux,!android freebsd openbsd
+
+package app
+
+import (
+ "errors"
+ "unsafe"
+)
+
+type ViewEvent struct {
+ // Display is a pointer to the X11 Display created by XOpenDisplay.
+ Display unsafe.Pointer
+ // Window is the X11 window ID as returned by XCreateWindow.
+ Window uintptr
+}
+
+func osMain() {
+ select {}
+}
+
+type windowDriver func(*callbacks, []Option) error
+
+// Instead of creating files with build tags for each combination of wayland +/- x11
+// let each driver initialize these variables with their own version of createWindow.
+var wlDriver, x11Driver windowDriver
+
+func newWindow(window *callbacks, options []Option) error {
+ var errFirst error
+ for _, d := range []windowDriver{x11Driver, wlDriver} {
+ if d == nil {
+ continue
+ }
+ err := d(window, options)
+ if err == nil {
+ return nil
+ }
+ if errFirst == nil {
+ errFirst = err
+ }
+ }
+ if errFirst != nil {
+ return errFirst
+ }
+ return errors.New("app: no window driver available")
+}
+
+func (_ ViewEvent) ImplementsEvent() {}
diff --git a/vendor/gioui.org/app/internal/window/os_wayland.c b/vendor/gioui.org/app/os_wayland.c
index 5c1c075..b137e1f 100644
--- a/vendor/gioui.org/app/internal/window/os_wayland.c
+++ b/vendor/gioui.org/app/os_wayland.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: Unlicense OR MIT
-// +build linux,!android,!nowayland freebsd
+//go:build ((linux && !android) || freebsd) && !nowayland
+// +build linux,!android freebsd
+// +build !nowayland
#include <wayland-client.h>
#include "wayland_xdg_shell.h"
diff --git a/vendor/gioui.org/app/internal/window/os_wayland.go b/vendor/gioui.org/app/os_wayland.go
index 4a456ce..ac7aa17 100644
--- a/vendor/gioui.org/app/internal/window/os_wayland.go
+++ b/vendor/gioui.org/app/os_wayland.go
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: Unlicense OR MIT
-// +build linux,!android,!nowayland freebsd
+//go:build ((linux && !android) || freebsd) && !nowayland
+// +build linux,!android freebsd
+// +build !nowayland
-package window
+package app
import (
"bytes"
@@ -19,14 +21,16 @@ import (
"time"
"unsafe"
+ syscall "golang.org/x/sys/unix"
+
"gioui.org/app/internal/xkb"
"gioui.org/f32"
"gioui.org/internal/fling"
+ "gioui.org/io/clipboard"
"gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/io/system"
"gioui.org/unit"
- syscall "golang.org/x/sys/unix"
)
// Use wayland-scanner to generate glue code for the xdg-shell and xdg-decoration extensions.
@@ -39,9 +43,9 @@ import (
//go:generate wayland-scanner client-header /usr/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml wayland_xdg_decoration.h
//go:generate wayland-scanner private-code /usr/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml wayland_xdg_decoration.c
-//go:generate sed -i "1s;^;// +build linux,!android,!nowayland freebsd\\n\\n;" wayland_xdg_shell.c
-//go:generate sed -i "1s;^;// +build linux,!android,!nowayland freebsd\\n\\n;" wayland_xdg_decoration.c
-//go:generate sed -i "1s;^;// +build linux,!android,!nowayland freebsd\\n\\n;" wayland_text_input.c
+//go:generate sed -i "1s;^;//go:build ((linux \\&\\& !android) || freebsd) \\&\\& !nowayland\\n// +build linux,!android freebsd\\n// +build !nowayland\\n\\n;" wayland_xdg_shell.c
+//go:generate sed -i "1s;^;//go:build ((linux \\&\\& !android) || freebsd) \\&\\& !nowayland\\n// +build linux,!android freebsd\\n// +build !nowayland\\n\\n;" wayland_xdg_decoration.c
+//go:generate sed -i "1s;^;//go:build ((linux \\&\\& !android) || freebsd) \\&\\& !nowayland\\n// +build linux,!android freebsd\\n// +build !nowayland\\n\\n;" wayland_text_input.c
/*
#cgo linux pkg-config: wayland-client wayland-cursor
@@ -133,7 +137,7 @@ type repeatState struct {
delay time.Duration
key uint32
- win Callbacks
+ win *callbacks
stopC chan struct{}
start time.Duration
@@ -143,7 +147,7 @@ type repeatState struct {
}
type window struct {
- w Callbacks
+ w *callbacks
disp *wlDisplay
surf *C.struct_wl_surface
wmSurf *C.struct_xdg_surface
@@ -177,19 +181,17 @@ type window struct {
dead bool
lastFrameCallback *C.struct_wl_callback
- mu sync.Mutex
animating bool
needAck bool
// The most recent configure serial waiting to be ack'ed.
serial C.uint32_t
- width int
- height int
newScale bool
scale int
- // readClipboard tracks whether a ClipboardEvent is requested.
- readClipboard bool
- // writeClipboard is set whenever a clipboard write is requested.
- writeClipboard *string
+ // size is the unscaled window size (unlike config.Size which is scaled).
+ size image.Point
+ config Config
+
+ wakeups chan struct{}
}
type poller struct {
@@ -218,25 +220,34 @@ var callbackMap sync.Map
// order of preference.
var clipboardMimeTypes = []string{"text/plain;charset=utf8", "UTF8_STRING", "text/plain", "TEXT", "STRING"}
+var (
+ newWaylandEGLContext func(w *window) (context, error)
+ newWaylandVulkanContext func(w *window) (context, error)
+)
+
func init() {
wlDriver = newWLWindow
}
-func newWLWindow(window Callbacks, opts *Options) error {
+func newWLWindow(callbacks *callbacks, options []Option) error {
d, err := newWLDisplay()
if err != nil {
return err
}
- w, err := d.createNativeWindow(opts)
+ w, err := d.createNativeWindow(options)
if err != nil {
d.destroy()
return err
}
- w.w = window
+ w.w = callbacks
go func() {
defer d.destroy()
defer w.destroy()
+
w.w.SetDriver(w)
+ // Finish and commit setup from createNativeWindow.
+ w.Configure(options)
+ C.wl_surface_commit(w.surf)
if err := w.loop(); err != nil {
panic(err)
}
@@ -280,13 +291,16 @@ func (d *wlDisplay) readClipboard() (io.ReadCloser, error) {
if err != nil {
return nil, err
}
+ // wl_data_offer_receive performs and implicit dup(2) of the write end
+ // of the pipe. Close our version.
+ defer w.Close()
cmimeType := C.CString(s.mimeType)
defer C.free(unsafe.Pointer(cmimeType))
C.wl_data_offer_receive(s.clipboard, cmimeType, C.int(w.Fd()))
return r, nil
}
-func (d *wlDisplay) createNativeWindow(opts *Options) (*window, error) {
+func (d *wlDisplay) createNativeWindow(options []Option) (*window, error) {
if d.compositor == nil {
return nil, errors.New("wayland: no compositor available")
}
@@ -313,6 +327,7 @@ func (d *wlDisplay) createNativeWindow(opts *Options) (*window, error) {
newScale: scale != 1,
ppdp: ppdp,
ppsp: ppdp,
+ wakeups: make(chan struct{}, 1),
}
w.surf = C.wl_compositor_create_surface(d.compositor)
if w.surf == nil {
@@ -351,20 +366,13 @@ func (d *wlDisplay) createNativeWindow(opts *Options) (*window, error) {
C.wl_surface_add_listener(w.surf, &C.gio_surface_listener, unsafe.Pointer(w.surf))
C.xdg_surface_add_listener(w.wmSurf, &C.gio_xdg_surface_listener, unsafe.Pointer(w.surf))
C.xdg_toplevel_add_listener(w.topLvl, &C.gio_xdg_toplevel_listener, unsafe.Pointer(w.surf))
- title := C.CString(opts.Title)
- C.xdg_toplevel_set_title(w.topLvl, title)
- C.free(unsafe.Pointer(title))
- _, _, cfg := w.config()
- w.width = cfg.Px(opts.Width)
- w.height = cfg.Px(opts.Height)
if d.decor != nil {
// Request server side decorations.
w.decor = C.zxdg_decoration_manager_v1_get_toplevel_decoration(d.decor, w.topLvl)
C.zxdg_toplevel_decoration_v1_set_mode(w.decor, C.ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
}
w.updateOpaqueRegion()
- C.wl_surface_commit(w.surf)
return w, nil
}
@@ -471,10 +479,8 @@ func gio_onSeatName(data unsafe.Pointer, seat *C.struct_wl_seat, name *C.char) {
//export gio_onXdgSurfaceConfigure
func gio_onXdgSurfaceConfigure(data unsafe.Pointer, wmSurf *C.struct_xdg_surface, serial C.uint32_t) {
w := callbackLoad(data).(*window)
- w.mu.Lock()
w.serial = serial
w.needAck = true
- w.mu.Unlock()
w.setStage(system.StageRunning)
w.draw(true)
}
@@ -489,10 +495,7 @@ func gio_onToplevelClose(data unsafe.Pointer, topLvl *C.struct_xdg_toplevel) {
func gio_onToplevelConfigure(data unsafe.Pointer, topLvl *C.struct_xdg_toplevel, width, height C.int32_t, states *C.struct_wl_array) {
w := callbackLoad(data).(*window)
if width != 0 && height != 0 {
- w.mu.Lock()
- defer w.mu.Unlock()
- w.width = int(width)
- w.height = int(height)
+ w.size = image.Pt(int(width), int(height))
w.updateOpaqueRegion()
}
}
@@ -584,10 +587,11 @@ func gio_onRegistryGlobal(data unsafe.Pointer, reg *C.struct_wl_registry, name C
break
}
d.seat = &wlSeat{
- disp: d,
- name: name,
- seat: s,
- offers: make(map[*C.struct_wl_data_offer][]string),
+ disp: d,
+ name: name,
+ seat: s,
+ offers: make(map[*C.struct_wl_data_offer][]string),
+ touchFoci: make(map[C.int32_t]*window),
}
callbackStore(unsafe.Pointer(s), d.seat)
C.wl_seat_add_listener(s, &C.gio_seat_listener, unsafe.Pointer(s))
@@ -763,16 +767,7 @@ func gio_onPointerEnter(data unsafe.Pointer, pointer *C.struct_wl_pointer, seria
s.serial = serial
w := callbackLoad(unsafe.Pointer(surf)).(*window)
s.pointerFocus = w
- // Get images[0].
- img := *w.cursor.cursor.images
- buf := C.wl_cursor_image_get_buffer(img)
- if buf == nil {
- return
- }
- C.wl_pointer_set_cursor(pointer, serial, w.cursor.surf, C.int32_t(img.hotspot_x), C.int32_t(img.hotspot_y))
- C.wl_surface_attach(w.cursor.surf, buf, 0, 0)
- C.wl_surface_damage(w.cursor.surf, 0, 0, C.int32_t(img.width), C.int32_t(img.height))
- C.wl_surface_commit(w.cursor.surf)
+ w.setCursor(pointer, serial)
w.lastPos = f32.Point{X: fromFixed(x), Y: fromFixed(y)}
}
@@ -804,11 +799,11 @@ func gio_onPointerButton(data unsafe.Pointer, p *C.struct_wl_pointer, serial, t,
var btn pointer.Buttons
switch wbtn {
case BTN_LEFT:
- btn = pointer.ButtonLeft
+ btn = pointer.ButtonPrimary
case BTN_RIGHT:
- btn = pointer.ButtonRight
+ btn = pointer.ButtonSecondary
case BTN_MIDDLE:
- btn = pointer.ButtonMiddle
+ btn = pointer.ButtonTertiary
default:
return
}
@@ -867,15 +862,13 @@ func (w *window) flushFling() {
w.fling.xExtrapolation = fling.Extrapolation{}
w.fling.yExtrapolation = fling.Extrapolation{}
vel := float32(math.Sqrt(float64(estx.Velocity*estx.Velocity + esty.Velocity*esty.Velocity)))
- _, _, c := w.config()
+ _, c := w.getConfig()
if !w.fling.anim.Start(c, time.Now(), vel) {
return
}
invDist := 1 / vel
w.fling.dir.X = estx.Velocity * invDist
w.fling.dir.Y = esty.Velocity * invDist
- // Wake up the window loop.
- w.disp.wakeup()
}
//export gio_onPointerAxisSource
@@ -903,17 +896,94 @@ func gio_onPointerAxisDiscrete(data unsafe.Pointer, p *C.struct_wl_pointer, axis
}
func (w *window) ReadClipboard() {
- w.mu.Lock()
- w.readClipboard = true
- w.mu.Unlock()
- w.disp.wakeup()
+ r, err := w.disp.readClipboard()
+ // Send empty responses on unavailable clipboards or errors.
+ if r == nil || err != nil {
+ w.w.Event(clipboard.Event{})
+ return
+ }
+ // Don't let slow clipboard transfers block event loop.
+ go func() {
+ defer r.Close()
+ data, _ := ioutil.ReadAll(r)
+ w.w.Event(clipboard.Event{Text: string(data)})
+ }()
}
func (w *window) WriteClipboard(s string) {
- w.mu.Lock()
- w.writeClipboard = &s
- w.mu.Unlock()
- w.disp.wakeup()
+ w.disp.writeClipboard([]byte(s))
+}
+
+func (w *window) Configure(options []Option) {
+ _, cfg := w.getConfig()
+ prev := w.config
+ cnf := w.config
+ cnf.apply(cfg, options)
+ if prev.Size != cnf.Size {
+ w.size = image.Pt(cnf.Size.X/w.scale, cnf.Size.Y/w.scale)
+ w.config.Size = cnf.Size
+ }
+ if prev.Title != cnf.Title {
+ w.config.Title = cnf.Title
+ title := C.CString(cnf.Title)
+ C.xdg_toplevel_set_title(w.topLvl, title)
+ C.free(unsafe.Pointer(title))
+ }
+ if w.config != prev {
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
+}
+
+func (w *window) Raise() {}
+
+func (w *window) SetCursor(name pointer.CursorName) {
+ ptr := w.disp.seat.pointer
+ if ptr == nil {
+ return
+ }
+ if name == pointer.CursorNone {
+ C.wl_pointer_set_cursor(ptr, w.serial, nil, 0, 0)
+ return
+ }
+ switch name {
+ default:
+ fallthrough
+ case pointer.CursorDefault:
+ name = "left_ptr"
+ case pointer.CursorText:
+ name = "xterm"
+ case pointer.CursorPointer:
+ name = "hand1"
+ case pointer.CursorCrossHair:
+ name = "crosshair"
+ case pointer.CursorRowResize:
+ name = "top_side"
+ case pointer.CursorColResize:
+ name = "left_side"
+ case pointer.CursorGrab:
+ name = "hand1"
+ }
+ cname := C.CString(string(name))
+ defer C.free(unsafe.Pointer(cname))
+ c := C.wl_cursor_theme_get_cursor(w.cursor.theme, cname)
+ if c == nil {
+ return
+ }
+ w.cursor.cursor = c
+ w.setCursor(ptr, w.serial)
+}
+
+func (w *window) setCursor(pointer *C.struct_wl_pointer, serial C.uint32_t) {
+ // Get images[0].
+ img := *w.cursor.cursor.images
+ buf := C.wl_cursor_image_get_buffer(img)
+ if buf == nil {
+ return
+ }
+ C.wl_pointer_set_cursor(pointer, serial, w.cursor.surf, C.int32_t(img.hotspot_x), C.int32_t(img.hotspot_y))
+ C.wl_surface_attach(w.cursor.surf, buf, 0, 0)
+ C.wl_surface_damage(w.cursor.surf, 0, 0, C.int32_t(img.width), C.int32_t(img.height))
+ C.wl_surface_commit(w.cursor.surf)
}
func (w *window) resetFling() {
@@ -963,13 +1033,14 @@ func gio_onKeyboardKey(data unsafe.Pointer, keyboard *C.struct_wl_keyboard, seri
t := time.Duration(timestamp) * time.Millisecond
s.disp.repeat.Stop(t)
w.resetFling()
- if state != C.WL_KEYBOARD_KEY_STATE_PRESSED {
- return
- }
kc := mapXKBKeycode(uint32(keyCode))
- for _, e := range w.disp.xkb.DispatchKey(kc) {
+ ks := mapXKBKeyState(uint32(state))
+ for _, e := range w.disp.xkb.DispatchKey(kc, ks) {
w.w.Event(e)
}
+ if state != C.WL_KEYBOARD_KEY_STATE_PRESSED {
+ return
+ }
if w.disp.xkb.IsRepeatKey(kc) {
w.disp.repeat.Start(w, kc, t)
}
@@ -980,6 +1051,15 @@ func mapXKBKeycode(keyCode uint32) uint32 {
return keyCode + 8
}
+func mapXKBKeyState(state uint32) key.State {
+ switch state {
+ case C.WL_KEYBOARD_KEY_STATE_RELEASED:
+ return key.Release
+ default:
+ return key.Press
+ }
+}
+
func (r *repeatState) Start(w *window, keyCode uint32, t time.Duration) {
if r.rate <= 0 {
return
@@ -1045,7 +1125,7 @@ func (r *repeatState) Repeat(d *wlDisplay) {
if r.last+delay > now {
break
}
- for _, e := range d.xkb.DispatchKey(r.key) {
+ for _, e := range d.xkb.DispatchKey(r.key, key.Press) {
r.win.Event(e)
}
r.last += delay
@@ -1068,43 +1148,21 @@ func (w *window) loop() error {
if err := w.disp.dispatch(&p); err != nil {
return err
}
+ select {
+ case <-w.wakeups:
+ w.w.Event(wakeupEvent{})
+ default:
+ }
if w.dead {
w.w.Event(system.DestroyEvent{})
break
}
- w.process()
+ // pass false to skip unnecessary drawing.
+ w.draw(false)
}
return nil
}
-func (w *window) process() {
- w.mu.Lock()
- readClipboard := w.readClipboard
- writeClipboard := w.writeClipboard
- w.readClipboard = false
- w.writeClipboard = nil
- w.mu.Unlock()
- if readClipboard {
- r, err := w.disp.readClipboard()
- // Send empty responses on unavailable clipboards or errors.
- if r == nil || err != nil {
- w.w.Event(system.ClipboardEvent{})
- return
- }
- // Don't let slow clipboard transfers block event loop.
- go func() {
- defer r.Close()
- data, _ := ioutil.ReadAll(r)
- w.w.Event(system.ClipboardEvent{Text: string(data)})
- }()
- }
- if writeClipboard != nil {
- w.disp.writeClipboard([]byte(*writeClipboard))
- }
- // pass false to skip unnecessary drawing.
- w.draw(false)
-}
-
func (d *wlDisplay) dispatch(p *poller) error {
dispfd := C.wl_display_get_fd(d.disp)
// Poll for events and notifications.
@@ -1147,11 +1205,16 @@ func (d *wlDisplay) dispatch(p *poller) error {
return nil
}
+func (w *window) Wakeup() {
+ select {
+ case w.wakeups <- struct{}{}:
+ default:
+ }
+ w.disp.wakeup()
+}
+
func (w *window) SetAnimating(anim bool) {
- w.mu.Lock()
w.animating = anim
- w.mu.Unlock()
- w.disp.wakeup()
}
// Wakeup wakes up the event loop through the notification pipe.
@@ -1322,7 +1385,7 @@ func (w *window) onPointerMotion(x, y C.wl_fixed_t, t C.uint32_t) {
func (w *window) updateOpaqueRegion() {
reg := C.wl_compositor_create_region(w.disp.compositor)
- C.wl_region_add(reg, 0, 0, C.int32_t(w.width), C.int32_t(w.height))
+ C.wl_region_add(reg, 0, 0, C.int32_t(w.size.X), C.int32_t(w.size.Y))
C.wl_surface_set_opaque_region(w.surf, reg)
C.wl_region_destroy(reg)
}
@@ -1340,12 +1403,10 @@ func (w *window) updateOutputs() {
}
}
}
- w.mu.Lock()
if found && scale != w.scale {
w.scale = scale
w.newScale = true
}
- w.mu.Unlock()
if !found {
w.setStage(system.StagePaused)
} else {
@@ -1354,9 +1415,9 @@ func (w *window) updateOutputs() {
}
}
-func (w *window) config() (int, int, unit.Metric) {
- width, height := w.width*w.scale, w.height*w.scale
- return width, height, unit.Metric{
+func (w *window) getConfig() (image.Point, unit.Metric) {
+ size := w.size.Mul(w.scale)
+ return size, unit.Metric{
PxPerDp: w.ppdp * float32(w.scale),
PxPerSp: w.ppsp * float32(w.scale),
}
@@ -1364,14 +1425,16 @@ func (w *window) config() (int, int, unit.Metric) {
func (w *window) draw(sync bool) {
w.flushScroll()
- w.mu.Lock()
anim := w.animating || w.fling.anim.Active()
dead := w.dead
- w.mu.Unlock()
if dead || (!anim && !sync) {
return
}
- width, height, cfg := w.config()
+ size, cfg := w.getConfig()
+ if size != w.config.Size {
+ w.config.Size = size
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
if cfg == (unit.Metric{}) {
return
}
@@ -1380,13 +1443,10 @@ func (w *window) draw(sync bool) {
// Use the surface as listener data for gio_onFrameDone.
C.wl_callback_add_listener(w.lastFrameCallback, &C.gio_callback_listener, unsafe.Pointer(w.surf))
}
- w.w.Event(FrameEvent{
+ w.w.Event(frameEvent{
FrameEvent: system.FrameEvent{
- Now: time.Now(),
- Size: image.Point{
- X: width,
- Y: height,
- },
+ Now: time.Now(),
+ Size: w.config.Size,
Metric: cfg,
},
Sync: sync,
@@ -1398,7 +1458,7 @@ func (w *window) setStage(s system.Stage) {
return
}
w.stage = s
- w.w.Event(system.StageEvent{s})
+ w.w.Event(system.StageEvent{Stage: s})
}
func (w *window) display() *C.struct_wl_display {
@@ -1410,18 +1470,50 @@ func (w *window) surface() (*C.struct_wl_surface, int, int) {
C.xdg_surface_ack_configure(w.wmSurf, w.serial)
w.needAck = false
}
- width, height, scale := w.width, w.height, w.scale
if w.newScale {
- C.wl_surface_set_buffer_scale(w.surf, C.int32_t(scale))
+ C.wl_surface_set_buffer_scale(w.surf, C.int32_t(w.scale))
w.newScale = false
}
- return w.surf, width * scale, height * scale
+ sz, _ := w.getConfig()
+ return w.surf, sz.X, sz.Y
}
func (w *window) ShowTextInput(show bool) {}
-// Close the window. Not implemented for Wayland.
-func (w *window) Close() {}
+func (w *window) SetInputHint(_ key.InputHint) {}
+
+// Close the window.
+func (w *window) Close() {
+ w.dead = true
+}
+
+// Maximize the window. Not implemented for Wayland.
+func (w *window) Maximize() {}
+
+// Center the window. Not implemented for Wayland.
+func (w *window) Center() {}
+
+func (w *window) NewContext() (context, error) {
+ var firstErr error
+ if f := newWaylandVulkanContext; f != nil {
+ c, err := f(w)
+ if err == nil {
+ return c, nil
+ }
+ firstErr = err
+ }
+ if f := newWaylandEGLContext; f != nil {
+ c, err := f(w)
+ if err == nil {
+ return c, nil
+ }
+ firstErr = err
+ }
+ if firstErr != nil {
+ return nil, firstErr
+ }
+ return nil, errors.New("wayland: no available GPU backends")
+}
// detectUIScale reports the system UI scale, or 1.0 if it fails.
func detectUIScale() float32 {
diff --git a/vendor/gioui.org/app/internal/window/os_windows.go b/vendor/gioui.org/app/os_windows.go
index 247f10a..ecbffb4 100644
--- a/vendor/gioui.org/app/internal/window/os_windows.go
+++ b/vendor/gioui.org/app/os_windows.go
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Unlicense OR MIT
-package window
+package app
import (
"errors"
@@ -13,23 +13,23 @@ import (
"sync"
"time"
"unicode"
- "unicode/utf16"
"unsafe"
syscall "golang.org/x/sys/windows"
"gioui.org/app/internal/windows"
"gioui.org/unit"
+ gowindows "golang.org/x/sys/windows"
"gioui.org/f32"
+ "gioui.org/io/clipboard"
"gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/io/system"
)
-type winConstraints struct {
- minWidth, minHeight int32
- maxWidth, maxHeight int32
+type ViewEvent struct {
+ HWND uintptr
}
type winDeltas struct {
@@ -40,69 +40,80 @@ type winDeltas struct {
type window struct {
hwnd syscall.Handle
hdc syscall.Handle
- w Callbacks
- width int
- height int
+ w *callbacks
stage system.Stage
- dead bool
pointerBtns pointer.Buttons
- mu sync.Mutex
+ // cursorIn tracks whether the cursor was inside the window according
+ // to the most recent WM_SETCURSOR.
+ cursorIn bool
+ cursor syscall.Handle
+
+ // placement saves the previous window position when in full screen mode.
+ placement *windows.WindowPlacement
+
animating bool
- minmax winConstraints
deltas winDeltas
- opts *Options
+ config Config
}
-const _WM_REDRAW = windows.WM_USER + 0
+const _WM_WAKEUP = windows.WM_USER + iota
type gpuAPI struct {
priority int
- initializer func(w *window) (Context, error)
+ initializer func(w *window) (context, error)
}
-// backends is the list of potential Context
-// implementations.
-var backends []gpuAPI
+// drivers is the list of potential Context implementations.
+var drivers []gpuAPI
// winMap maps win32 HWNDs to *windows.
var winMap sync.Map
+// iconID is the ID of the icon in the resource file.
+const iconID = 1
+
var resources struct {
once sync.Once
// handle is the module handle from GetModuleHandle.
handle syscall.Handle
// class is the Gio window class from RegisterClassEx.
class uint16
- // cursor is the arrow cursor resource
+ // cursor is the arrow cursor resource.
cursor syscall.Handle
}
-func Main() {
+func osMain() {
select {}
}
-func NewWindow(window Callbacks, opts *Options) error {
+func newWindow(window *callbacks, options []Option) error {
cerr := make(chan error)
go func() {
- // Call win32 API from a single OS thread.
+ // GetMessage and PeekMessage can filter on a window HWND, but
+ // then thread-specific messages such as WM_QUIT are ignored.
+ // Instead lock the thread so window messages arrive through
+ // unfiltered GetMessage calls.
runtime.LockOSThread()
- w, err := createNativeWindow(opts)
+ w, err := createNativeWindow()
if err != nil {
cerr <- err
return
}
- defer w.destroy()
cerr <- nil
winMap.Store(w.hwnd, w)
defer winMap.Delete(w.hwnd)
w.w = window
w.w.SetDriver(w)
- defer w.w.Event(system.DestroyEvent{})
+ w.w.Event(ViewEvent{HWND: uintptr(w.hwnd)})
+ w.Configure(options)
windows.ShowWindow(w.hwnd, windows.SW_SHOWDEFAULT)
windows.SetForegroundWindow(w.hwnd)
windows.SetFocus(w.hwnd)
+ // Since the window class for the cursor is null,
+ // set it here to show the cursor.
+ w.SetCursor(pointer.CursorDefault)
if err := w.loop(); err != nil {
panic(err)
}
@@ -118,17 +129,18 @@ func initResources() error {
return err
}
resources.handle = hInst
- curs, err := windows.LoadCursor(windows.IDC_ARROW)
+ c, err := windows.LoadCursor(windows.IDC_ARROW)
if err != nil {
return err
}
- resources.cursor = curs
+ resources.cursor = c
+ icon, _ := windows.LoadImage(hInst, iconID, windows.IMAGE_ICON, 0, 0, windows.LR_DEFAULTSIZE|windows.LR_SHARED)
wcls := windows.WndClassEx{
CbSize: uint32(unsafe.Sizeof(windows.WndClassEx{})),
Style: windows.CS_HREDRAW | windows.CS_VREDRAW | windows.CS_OWNDC,
LpfnWndProc: syscall.NewCallback(windowProc),
HInstance: hInst,
- HCursor: curs,
+ HIcon: icon,
LpszClassName: syscall.StringToUTF16Ptr("GioWindow"),
}
cls, err := windows.RegisterClassEx(&wcls)
@@ -139,16 +151,7 @@ func initResources() error {
return nil
}
-func getWindowConstraints(cfg unit.Metric, opts *Options, d winDeltas) winConstraints {
- var minmax winConstraints
- minmax.minWidth = int32(cfg.Px(opts.MinWidth))
- minmax.minHeight = int32(cfg.Px(opts.MinHeight))
- minmax.maxWidth = int32(cfg.Px(opts.MaxWidth))
- minmax.maxHeight = int32(cfg.Px(opts.MaxHeight))
- return minmax
-}
-
-func createNativeWindow(opts *Options) (*window, error) {
+func createNativeWindow() (*window, error) {
var resErr error
resources.once.Do(func() {
resErr = initResources()
@@ -156,28 +159,15 @@ func createNativeWindow(opts *Options) (*window, error) {
if resErr != nil {
return nil, resErr
}
- cfg := configForDC()
- wr := windows.Rect{
- Right: int32(cfg.Px(opts.Width)),
- Bottom: int32(cfg.Px(opts.Height)),
- }
dwStyle := uint32(windows.WS_OVERLAPPEDWINDOW)
dwExStyle := uint32(windows.WS_EX_APPWINDOW | windows.WS_EX_WINDOWEDGE)
- deltas := winDeltas{
- width: wr.Right,
- height: wr.Bottom,
- }
- windows.AdjustWindowRectEx(&wr, dwStyle, 0, dwExStyle)
- deltas.width = wr.Right - wr.Left - deltas.width
- deltas.height = wr.Bottom - wr.Top - deltas.height
hwnd, err := windows.CreateWindowEx(dwExStyle,
resources.class,
- opts.Title,
+ "",
dwStyle|windows.WS_CLIPSIBLINGS|windows.WS_CLIPCHILDREN,
windows.CW_USEDEFAULT, windows.CW_USEDEFAULT,
- wr.Right-wr.Left,
- wr.Bottom-wr.Top,
+ windows.CW_USEDEFAULT, windows.CW_USEDEFAULT,
0,
0,
resources.handle,
@@ -186,10 +176,7 @@ func createNativeWindow(opts *Options) (*window, error) {
return nil, err
}
w := &window{
- hwnd: hwnd,
- minmax: getWindowConstraints(cfg, opts, deltas),
- deltas: deltas,
- opts: opts,
+ hwnd: hwnd,
}
w.hdc, err = windows.GetDC(hwnd)
if err != nil {
@@ -210,7 +197,7 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
case windows.WM_UNICHAR:
if wParam == windows.UNICODE_NOCHAR {
// Tell the system that we accept WM_UNICHAR messages.
- return 1
+ return windows.TRUE
}
fallthrough
case windows.WM_CHAR:
@@ -218,29 +205,44 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
w.w.Event(key.EditEvent{Text: string(r)})
}
// The message is processed.
- return 1
+ return windows.TRUE
case windows.WM_DPICHANGED:
// Let Windows know we're prepared for runtime DPI changes.
- return 1
+ return windows.TRUE
case windows.WM_ERASEBKGND:
// Avoid flickering between GPU content and background color.
- return 1
- case windows.WM_KEYDOWN, windows.WM_SYSKEYDOWN:
+ return windows.TRUE
+ case windows.WM_KEYDOWN, windows.WM_KEYUP, windows.WM_SYSKEYDOWN, windows.WM_SYSKEYUP:
if n, ok := convertKeyCode(wParam); ok {
- w.w.Event(key.Event{Name: n, Modifiers: getModifiers()})
+ e := key.Event{
+ Name: n,
+ Modifiers: getModifiers(),
+ State: key.Press,
+ }
+ if msg == windows.WM_KEYUP || msg == windows.WM_SYSKEYUP {
+ e.State = key.Release
+ }
+
+ w.w.Event(e)
+
+ if (wParam == windows.VK_F10) && (msg == windows.WM_SYSKEYDOWN || msg == windows.WM_SYSKEYUP) {
+ // Reserve F10 for ourselves, and don't let it open the system menu. Other Windows programs
+ // such as cmd.exe and graphical debuggers also reserve F10.
+ return 0
+ }
}
case windows.WM_LBUTTONDOWN:
- w.pointerButton(pointer.ButtonLeft, true, lParam, getModifiers())
+ w.pointerButton(pointer.ButtonPrimary, true, lParam, getModifiers())
case windows.WM_LBUTTONUP:
- w.pointerButton(pointer.ButtonLeft, false, lParam, getModifiers())
+ w.pointerButton(pointer.ButtonPrimary, false, lParam, getModifiers())
case windows.WM_RBUTTONDOWN:
- w.pointerButton(pointer.ButtonRight, true, lParam, getModifiers())
+ w.pointerButton(pointer.ButtonSecondary, true, lParam, getModifiers())
case windows.WM_RBUTTONUP:
- w.pointerButton(pointer.ButtonRight, false, lParam, getModifiers())
+ w.pointerButton(pointer.ButtonSecondary, false, lParam, getModifiers())
case windows.WM_MBUTTONDOWN:
- w.pointerButton(pointer.ButtonMiddle, true, lParam, getModifiers())
+ w.pointerButton(pointer.ButtonTertiary, true, lParam, getModifiers())
case windows.WM_MBUTTONUP:
- w.pointerButton(pointer.ButtonMiddle, false, lParam, getModifiers())
+ w.pointerButton(pointer.ButtonTertiary, false, lParam, getModifiers())
case windows.WM_CANCELMODE:
w.w.Event(pointer.Event{
Type: pointer.Cancel,
@@ -260,9 +262,19 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
Time: windows.GetMessageTime(),
})
case windows.WM_MOUSEWHEEL:
- w.scrollEvent(wParam, lParam)
+ w.scrollEvent(wParam, lParam, false)
+ case windows.WM_MOUSEHWHEEL:
+ w.scrollEvent(wParam, lParam, true)
case windows.WM_DESTROY:
- w.dead = true
+ w.w.Event(ViewEvent{})
+ w.w.Event(system.DestroyEvent{})
+ if w.hdc != 0 {
+ windows.ReleaseDC(w.hdc)
+ w.hdc = 0
+ }
+ // The system destroys the HWND for us.
+ w.hwnd = 0
+ windows.PostQuitMessage(0)
case windows.WM_PAINT:
w.draw(true)
case windows.WM_SIZE:
@@ -270,22 +282,51 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
case windows.SIZE_MINIMIZED:
w.setStage(system.StagePaused)
case windows.SIZE_MAXIMIZED, windows.SIZE_RESTORED:
+ var triggerEvent bool
+ // Check the window size change.
+ var r windows.Rect
+ windows.GetClientRect(w.hwnd, &r)
+ size := image.Point{
+ X: int(r.Right - r.Left),
+ Y: int(r.Bottom - r.Top),
+ }
+ if size != w.config.Size {
+ w.config.Size = size
+ triggerEvent = true
+ }
+ // Check the window mode.
+ mode := w.config.Mode
+ w.updateWindowMode()
+ if mode != w.config.Mode {
+ triggerEvent = true
+ }
+ if triggerEvent {
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
w.setStage(system.StageRunning)
}
case windows.WM_GETMINMAXINFO:
mm := (*windows.MinMaxInfo)(unsafe.Pointer(uintptr(lParam)))
- if w.minmax.minWidth > 0 || w.minmax.minHeight > 0 {
+ if p := w.config.MinSize; p.X > 0 || p.Y > 0 {
mm.PtMinTrackSize = windows.Point{
- w.minmax.minWidth+w.deltas.width,
- w.minmax.minHeight+w.deltas.height,
+ X: int32(p.X) + w.deltas.width,
+ Y: int32(p.Y) + w.deltas.height,
}
}
- if w.minmax.maxWidth > 0 || w.minmax.maxHeight > 0 {
+ if p := w.config.MaxSize; p.X > 0 || p.Y > 0 {
mm.PtMaxTrackSize = windows.Point{
- w.minmax.maxWidth+w.deltas.width,
- w.minmax.maxHeight+w.deltas.height,
+ X: int32(p.X) + w.deltas.width,
+ Y: int32(p.Y) + w.deltas.height,
}
}
+ case windows.WM_SETCURSOR:
+ w.cursorIn = (lParam & 0xffff) == windows.HTCLIENT
+ if w.cursorIn {
+ windows.SetCursor(w.cursor)
+ return windows.TRUE
+ }
+ case _WM_WAKEUP:
+ w.w.Event(wakeupEvent{})
}
return windows.DefWindowProc(hwnd, msg, wParam, lParam)
@@ -341,7 +382,7 @@ func coordsFromlParam(lParam uintptr) (int, int) {
return x, y
}
-func (w *window) scrollEvent(wParam, lParam uintptr) {
+func (w *window) scrollEvent(wParam, lParam uintptr, horizontal bool) {
x, y := coordsFromlParam(lParam)
// The WM_MOUSEWHEEL coordinates are in screen coordinates, in contrast
// to other mouse events.
@@ -349,12 +390,18 @@ func (w *window) scrollEvent(wParam, lParam uintptr) {
windows.ScreenToClient(w.hwnd, &np)
p := f32.Point{X: float32(np.X), Y: float32(np.Y)}
dist := float32(int16(wParam >> 16))
+ var sp f32.Point
+ if horizontal {
+ sp.X = dist
+ } else {
+ sp.Y = -dist
+ }
w.w.Event(pointer.Event{
Type: pointer.Scroll,
Source: pointer.Mouse,
Position: p,
Buttons: w.pointerBtns,
- Scroll: f32.Point{Y: -dist},
+ Scroll: sp,
Time: windows.GetMessageTime(),
})
}
@@ -362,18 +409,19 @@ func (w *window) scrollEvent(wParam, lParam uintptr) {
// Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20060126-00/?p=32513/
func (w *window) loop() error {
msg := new(windows.Msg)
- for !w.dead {
- w.mu.Lock()
+loop:
+ for {
anim := w.animating
- w.mu.Unlock()
- if anim && !windows.PeekMessage(msg, w.hwnd, 0, 0, windows.PM_NOREMOVE) {
+ if anim && !windows.PeekMessage(msg, 0, 0, 0, windows.PM_NOREMOVE) {
w.draw(false)
continue
}
- windows.GetMessage(msg, w.hwnd, 0, 0)
- if msg.Message == windows.WM_QUIT {
- windows.PostQuitMessage(msg.WParam)
- break
+ switch ret := windows.GetMessage(msg, 0, 0, 0); ret {
+ case -1:
+ return errors.New("GetMessage failed")
+ case 0:
+ // WM_QUIT received.
+ break loop
}
windows.TranslateMessage(msg)
windows.DispatchMessage(msg)
@@ -382,65 +430,44 @@ func (w *window) loop() error {
}
func (w *window) SetAnimating(anim bool) {
- w.mu.Lock()
w.animating = anim
- w.mu.Unlock()
- if anim {
- w.postRedraw()
- }
}
-func (w *window) postRedraw() {
- if err := windows.PostMessage(w.hwnd, _WM_REDRAW, 0, 0); err != nil {
+func (w *window) Wakeup() {
+ if err := windows.PostMessage(w.hwnd, _WM_WAKEUP, 0, 0); err != nil {
panic(err)
}
}
func (w *window) setStage(s system.Stage) {
- w.stage = s
- w.w.Event(system.StageEvent{Stage: s})
+ if s != w.stage {
+ w.stage = s
+ w.w.Event(system.StageEvent{Stage: s})
+ }
}
func (w *window) draw(sync bool) {
- var r windows.Rect
- windows.GetClientRect(w.hwnd, &r)
- w.width = int(r.Right - r.Left)
- w.height = int(r.Bottom - r.Top)
- if w.width == 0 || w.height == 0 {
+ if w.config.Size.X == 0 || w.config.Size.Y == 0 {
return
}
- cfg := configForDC()
- w.minmax = getWindowConstraints(cfg, w.opts, w.deltas)
- w.w.Event(FrameEvent{
+ dpi := windows.GetWindowDPI(w.hwnd)
+ cfg := configForDPI(dpi)
+ w.w.Event(frameEvent{
FrameEvent: system.FrameEvent{
- Now: time.Now(),
- Size: image.Point{
- X: w.width,
- Y: w.height,
- },
+ Now: time.Now(),
+ Size: w.config.Size,
Metric: cfg,
},
Sync: sync,
})
}
-func (w *window) destroy() {
- if w.hdc != 0 {
- windows.ReleaseDC(w.hdc)
- w.hdc = 0
- }
- if w.hwnd != 0 {
- windows.DestroyWindow(w.hwnd)
- w.hwnd = 0
- }
-}
-
-func (w *window) NewContext() (Context, error) {
- sort.Slice(backends, func(i, j int) bool {
- return backends[i].priority < backends[j].priority
+func (w *window) NewContext() (context, error) {
+ sort.Slice(drivers, func(i, j int) bool {
+ return drivers[i].priority < drivers[j].priority
})
var errs []string
- for _, b := range backends {
+ for _, b := range drivers {
ctx, err := b.initializer(w)
if err == nil {
return ctx, nil
@@ -450,7 +477,7 @@ func (w *window) NewContext() (Context, error) {
if len(errs) > 0 {
return nil, fmt.Errorf("NewContext: failed to create a GPU device, tried: %s", strings.Join(errs, ", "))
}
- return nil, errors.New("NewContext: no available backends")
+ return nil, errors.New("NewContext: no available GPU drivers")
}
func (w *window) ReadClipboard() {
@@ -471,25 +498,142 @@ func (w *window) readClipboard() error {
return err
}
defer windows.GlobalUnlock(mem)
- // Look for terminating null character.
- n := 0
- for {
- ch := *(*uint16)(unsafe.Pointer(ptr + uintptr(n)*2))
- if ch == 0 {
- break
+ content := gowindows.UTF16PtrToString((*uint16)(unsafe.Pointer(ptr)))
+ w.w.Event(clipboard.Event{Text: content})
+ return nil
+}
+
+func (w *window) updateWindowMode() {
+ p := windows.GetWindowPlacement(w.hwnd)
+ r := p.Rect()
+ mi := windows.GetMonitorInfo(w.hwnd)
+ if r == mi.Monitor {
+ w.config.Mode = Fullscreen
+ } else {
+ w.config.Mode = Windowed
+ }
+}
+
+func (w *window) Configure(options []Option) {
+ dpi := windows.GetSystemDPI()
+ cfg := configForDPI(dpi)
+ prev := w.config
+ w.updateWindowMode()
+ cnf := w.config
+ cnf.apply(cfg, options)
+
+ if cnf.Mode != Fullscreen && prev.Size != cnf.Size {
+ width := int32(cnf.Size.X)
+ height := int32(cnf.Size.Y)
+ w.config.Size = cnf.Size
+
+ // Include the window decorations.
+ wr := windows.Rect{
+ Right: width,
+ Bottom: height,
}
- n++
+ dwStyle := uint32(windows.WS_OVERLAPPEDWINDOW)
+ dwExStyle := uint32(windows.WS_EX_APPWINDOW | windows.WS_EX_WINDOWEDGE)
+ windows.AdjustWindowRectEx(&wr, dwStyle, 0, dwExStyle)
+
+ dw, dh := width, height
+ width = wr.Right - wr.Left
+ height = wr.Bottom - wr.Top
+ w.deltas.width = width - dw
+ w.deltas.height = height - dh
+
+ windows.MoveWindow(w.hwnd, 0, 0, width, height, true)
+ }
+ if prev.MinSize != cnf.MinSize {
+ w.config.MinSize = cnf.MinSize
+ }
+ if prev.MaxSize != cnf.MaxSize {
+ w.config.MaxSize = cnf.MaxSize
+ }
+ if prev.Title != cnf.Title {
+ w.config.Title = cnf.Title
+ windows.SetWindowText(w.hwnd, cnf.Title)
+ }
+ if prev.Mode != cnf.Mode {
+ w.SetWindowMode(cnf.Mode)
+ }
+ if w.config != prev {
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
+}
+
+// Maximize the window. It will have no effect when in fullscreen mode.
+func (w *window) Maximize() {
+ if w.config.Mode == Fullscreen {
+ return
+ }
+ style := windows.GetWindowLong(w.hwnd)
+ windows.SetWindowLong(w.hwnd, windows.GWL_STYLE, style|windows.WS_OVERLAPPEDWINDOW|windows.WS_MAXIMIZE)
+ mi := windows.GetMonitorInfo(w.hwnd)
+ windows.SetWindowPos(w.hwnd, 0,
+ mi.Monitor.Left, mi.Monitor.Top,
+ mi.Monitor.Right-mi.Monitor.Left,
+ mi.Monitor.Bottom-mi.Monitor.Top,
+ windows.SWP_NOOWNERZORDER|windows.SWP_FRAMECHANGED,
+ )
+}
+
+// Center will place window at monitor center.
+func (w *window) Center() {
+ // Make sure that the window is sizeable
+ style := windows.GetWindowLong(w.hwnd) & (^uintptr(windows.WS_MAXIMIZE))
+ windows.SetWindowLong(w.hwnd, windows.GWL_STYLE, style|windows.WS_OVERLAPPEDWINDOW)
+
+ // Find with/height including the window decorations.
+ wr := windows.Rect{
+ Right: int32(w.config.Size.X),
+ Bottom: int32(w.config.Size.Y),
+ }
+ dwStyle := uint32(windows.WS_OVERLAPPEDWINDOW)
+ dwExStyle := uint32(windows.WS_EX_APPWINDOW | windows.WS_EX_WINDOWEDGE)
+ windows.AdjustWindowRectEx(&wr, dwStyle, 0, dwExStyle)
+ width := wr.Right - wr.Left
+ height := wr.Bottom - wr.Top
+
+ // Move to center of current monitor
+ mi := windows.GetMonitorInfo(w.hwnd).Monitor
+ x := mi.Left + (mi.Right-mi.Left-width)/2
+ y := mi.Top + (mi.Bottom-mi.Top-height)/2
+ windows.MoveWindow(w.hwnd, x, y, width, height, true)
+}
+
+func (w *window) SetWindowMode(mode WindowMode) {
+ // https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353
+ switch mode {
+ case Windowed:
+ if w.placement == nil {
+ return
+ }
+ w.config.Mode = Windowed
+ windows.SetWindowPlacement(w.hwnd, w.placement)
+ w.placement = nil
+ style := windows.GetWindowLong(w.hwnd)
+ windows.SetWindowLong(w.hwnd, windows.GWL_STYLE, style|windows.WS_OVERLAPPEDWINDOW)
+ windows.SetWindowPos(w.hwnd, windows.HWND_TOPMOST,
+ 0, 0, 0, 0,
+ windows.SWP_NOOWNERZORDER|windows.SWP_FRAMECHANGED,
+ )
+ case Fullscreen:
+ if w.placement != nil {
+ return
+ }
+ w.config.Mode = Fullscreen
+ w.placement = windows.GetWindowPlacement(w.hwnd)
+ style := windows.GetWindowLong(w.hwnd)
+ windows.SetWindowLong(w.hwnd, windows.GWL_STYLE, style&^windows.WS_OVERLAPPEDWINDOW)
+ mi := windows.GetMonitorInfo(w.hwnd)
+ windows.SetWindowPos(w.hwnd, 0,
+ mi.Monitor.Left, mi.Monitor.Top,
+ mi.Monitor.Right-mi.Monitor.Left,
+ mi.Monitor.Bottom-mi.Monitor.Top,
+ windows.SWP_NOOWNERZORDER|windows.SWP_FRAMECHANGED,
+ )
}
- var u16 []uint16
- hdr := (*reflect.SliceHeader)(unsafe.Pointer(&u16))
- hdr.Data = ptr
- hdr.Cap = n
- hdr.Len = n
- content := string(utf16.Decode(u16))
- go func() {
- w.w.Event(system.ClipboardEvent{Text: content})
- }()
- return nil
}
func (w *window) WriteClipboard(s string) {
@@ -497,9 +641,6 @@ func (w *window) WriteClipboard(s string) {
}
func (w *window) writeClipboard(s string) error {
- u16 := utf16.Encode([]rune(s))
- // Data must be null terminated.
- u16 = append(u16, 0)
if err := windows.OpenClipboard(w.hwnd); err != nil {
return err
}
@@ -507,6 +648,10 @@ func (w *window) writeClipboard(s string) error {
if err := windows.EmptyClipboard(); err != nil {
return err
}
+ u16, err := gowindows.UTF16FromString(s)
+ if err != nil {
+ return err
+ }
n := len(u16) * int(unsafe.Sizeof(u16[0]))
mem, err := windows.GlobalAlloc(n)
if err != nil {
@@ -531,20 +676,64 @@ func (w *window) writeClipboard(s string) error {
return nil
}
+func (w *window) SetCursor(name pointer.CursorName) {
+ c, err := loadCursor(name)
+ if err != nil {
+ c = resources.cursor
+ }
+ w.cursor = c
+ if w.cursorIn {
+ windows.SetCursor(w.cursor)
+ }
+}
+
+func loadCursor(name pointer.CursorName) (syscall.Handle, error) {
+ var curID uint16
+ switch name {
+ default:
+ fallthrough
+ case pointer.CursorDefault:
+ return resources.cursor, nil
+ case pointer.CursorText:
+ curID = windows.IDC_IBEAM
+ case pointer.CursorPointer:
+ curID = windows.IDC_HAND
+ case pointer.CursorCrossHair:
+ curID = windows.IDC_CROSS
+ case pointer.CursorColResize:
+ curID = windows.IDC_SIZEWE
+ case pointer.CursorRowResize:
+ curID = windows.IDC_SIZENS
+ case pointer.CursorGrab:
+ curID = windows.IDC_SIZEALL
+ case pointer.CursorNone:
+ return 0, nil
+ }
+ return windows.LoadCursor(curID)
+}
+
func (w *window) ShowTextInput(show bool) {}
+func (w *window) SetInputHint(_ key.InputHint) {}
+
func (w *window) HDC() syscall.Handle {
return w.hdc
}
func (w *window) HWND() (syscall.Handle, int, int) {
- return w.hwnd, w.width, w.height
+ return w.hwnd, w.config.Size.X, w.config.Size.Y
}
func (w *window) Close() {
windows.PostMessage(w.hwnd, windows.WM_CLOSE, 0, 0)
}
+func (w *window) Raise() {
+ windows.SetForegroundWindow(w.hwnd)
+ windows.SetWindowPos(w.hwnd, windows.HWND_TOPMOST, 0, 0, 0, 0,
+ windows.SWP_NOMOVE|windows.SWP_NOSIZE|windows.SWP_SHOWWINDOW)
+}
+
func convertKeyCode(code uintptr) (string, bool) {
if '0' <= code && code <= '9' || 'A' <= code && code <= 'Z' {
return string(rune(code)), true
@@ -602,7 +791,7 @@ func convertKeyCode(code uintptr) (string, bool) {
case windows.VK_TAB:
r = key.NameTab
case windows.VK_SPACE:
- r = "Space"
+ r = key.NameSpace
case windows.VK_OEM_1:
r = ";"
case windows.VK_OEM_PLUS:
@@ -631,8 +820,7 @@ func convertKeyCode(code uintptr) (string, bool) {
return r, true
}
-func configForDC() unit.Metric {
- dpi := windows.GetSystemDPI()
+func configForDPI(dpi int) unit.Metric {
const inchPrDp = 1.0 / 96.0
ppdp := float32(dpi) * inchPrDp
return unit.Metric{
@@ -640,3 +828,5 @@ func configForDC() unit.Metric {
PxPerSp: ppdp,
}
}
+
+func (_ ViewEvent) ImplementsEvent() {}
diff --git a/vendor/gioui.org/app/internal/window/os_x11.go b/vendor/gioui.org/app/os_x11.go
index 69108c6..1c75247 100644
--- a/vendor/gioui.org/app/internal/window/os_x11.go
+++ b/vendor/gioui.org/app/os_x11.go
@@ -1,14 +1,16 @@
// SPDX-License-Identifier: Unlicense OR MIT
-// +build linux,!android,!nox11 freebsd openbsd
+//go:build ((linux && !android) || freebsd || openbsd) && !nox11
+// +build linux,!android freebsd openbsd
+// +build !nox11
-package window
+package app
/*
-#cgo openbsd CFLAGS: -I/usr/X11R6/include -I/usr/local/include
-#cgo openbsd LDFLAGS: -L/usr/X11R6/lib -L/usr/local/lib
-#cgo freebsd openbsd LDFLAGS: -lX11 -lxkbcommon -lxkbcommon-x11 -lX11-xcb
-#cgo linux pkg-config: x11 xkbcommon xkbcommon-x11 x11-xcb
+#cgo freebsd openbsd CFLAGS: -I/usr/X11R6/include -I/usr/local/include
+#cgo freebsd openbsd LDFLAGS: -L/usr/X11R6/lib -L/usr/local/lib
+#cgo freebsd openbsd LDFLAGS: -lX11 -lxkbcommon -lxkbcommon-x11 -lX11-xcb -lXcursor -lXfixes
+#cgo linux pkg-config: x11 xkbcommon xkbcommon-x11 x11-xcb xcursor xfixes
#include <stdlib.h>
#include <locale.h>
@@ -18,6 +20,8 @@ package window
#include <X11/Xresource.h>
#include <X11/XKBlib.h>
#include <X11/Xlib-xcb.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/Xcursor/Xcursor.h>
#include <xkbcommon/xkbcommon-x11.h>
*/
@@ -34,17 +38,24 @@ import (
"unsafe"
"gioui.org/f32"
+ "gioui.org/io/clipboard"
"gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/io/system"
"gioui.org/unit"
- "gioui.org/app/internal/xkb"
syscall "golang.org/x/sys/unix"
+
+ "gioui.org/app/internal/xkb"
+)
+
+const (
+ _NET_WM_STATE_REMOVE = 0
+ _NET_WM_STATE_ADD = 1
)
type x11Window struct {
- w Callbacks
+ w *callbacks
x *C.Display
xkb *xkb.Context
xkbEventBase C.int
@@ -53,68 +64,213 @@ type x11Window struct {
atoms struct {
// "UTF8_STRING".
utf8string C.Atom
+ // "text/plain;charset=utf-8".
+ plaintext C.Atom
// "TARGETS"
targets C.Atom
// "CLIPBOARD".
clipboard C.Atom
+ // "PRIMARY".
+ primary C.Atom
// "CLIPBOARD_CONTENT", the clipboard destination property.
clipboardContent C.Atom
// "WM_DELETE_WINDOW"
evDelWindow C.Atom
// "ATOM"
atom C.Atom
+ // "GTK_TEXT_BUFFER_CONTENTS"
+ gtk_text_buffer_contents C.Atom
+ // "_NET_WM_NAME"
+ wmName C.Atom
+ // "_NET_WM_STATE"
+ wmState C.Atom
+ // "_NET_WM_STATE_FULLSCREEN"
+ wmStateFullscreen C.Atom
+ // "_NET_ACTIVE_WINDOW"
+ wmActiveWindow C.Atom
+ // _NET_WM_STATE_MAXIMIZED_HORZ
+ wmStateMaximizedHorz C.Atom
+ // _NET_WM_STATE_MAXIMIZED_VERT
+ wmStateMaximizedVert C.Atom
}
stage system.Stage
- cfg unit.Metric
- width int
- height int
+ metric unit.Metric
notify struct {
read, write int
}
dead bool
- mu sync.Mutex
animating bool
pointerBtns pointer.Buttons
clipboard struct {
- read bool
- write *string
content []byte
}
+ cursor pointer.CursorName
+ config Config
+
+ wakeups chan struct{}
+}
+
+var (
+ newX11EGLContext func(w *x11Window) (context, error)
+ newX11VulkanContext func(w *x11Window) (context, error)
+)
+
+func (w *x11Window) NewContext() (context, error) {
+ var firstErr error
+ if f := newX11VulkanContext; f != nil {
+ c, err := f(w)
+ if err == nil {
+ return c, nil
+ }
+ firstErr = err
+ }
+ if f := newX11EGLContext; f != nil {
+ c, err := f(w)
+ if err == nil {
+ return c, nil
+ }
+ firstErr = err
+ }
+ if firstErr != nil {
+ return nil, firstErr
+ }
+ return nil, errors.New("x11: no available GPU backends")
}
func (w *x11Window) SetAnimating(anim bool) {
- w.mu.Lock()
w.animating = anim
- w.mu.Unlock()
- if anim {
- w.wakeup()
- }
}
func (w *x11Window) ReadClipboard() {
- w.mu.Lock()
- w.clipboard.read = true
- w.mu.Unlock()
- w.wakeup()
+ C.XDeleteProperty(w.x, w.xw, w.atoms.clipboardContent)
+ C.XConvertSelection(w.x, w.atoms.clipboard, w.atoms.utf8string, w.atoms.clipboardContent, w.xw, C.CurrentTime)
}
func (w *x11Window) WriteClipboard(s string) {
- w.mu.Lock()
- w.clipboard.write = &s
- w.mu.Unlock()
- w.wakeup()
+ w.clipboard.content = []byte(s)
+ C.XSetSelectionOwner(w.x, w.atoms.clipboard, w.xw, C.CurrentTime)
+ C.XSetSelectionOwner(w.x, w.atoms.primary, w.xw, C.CurrentTime)
+}
+
+func (w *x11Window) Configure(options []Option) {
+ var shints C.XSizeHints
+ prev := w.config
+ cnf := w.config
+ cnf.apply(w.metric, options)
+ if prev.MinSize != cnf.MinSize {
+ w.config.MinSize = cnf.MinSize
+ shints.min_width = C.int(cnf.MinSize.X)
+ shints.min_height = C.int(cnf.MinSize.Y)
+ shints.flags = C.PMinSize
+ }
+ if prev.MaxSize != cnf.MaxSize {
+ w.config.MaxSize = cnf.MaxSize
+ shints.max_width = C.int(cnf.MaxSize.X)
+ shints.max_height = C.int(cnf.MaxSize.Y)
+ shints.flags = shints.flags | C.PMaxSize
+ }
+ if shints.flags != 0 {
+ C.XSetWMNormalHints(w.x, w.xw, &shints)
+ }
+
+ if cnf.Mode != Fullscreen && prev.Size != cnf.Size {
+ w.config.Size = cnf.Size
+ C.XResizeWindow(w.x, w.xw, C.uint(cnf.Size.X), C.uint(cnf.Size.Y))
+ }
+
+ if prev.Title != cnf.Title {
+ title := cnf.Title
+ ctitle := C.CString(title)
+ defer C.free(unsafe.Pointer(ctitle))
+ C.XStoreName(w.x, w.xw, ctitle)
+ // set _NET_WM_NAME as well for UTF-8 support in window title.
+ C.XSetTextProperty(w.x, w.xw,
+ &C.XTextProperty{
+ value: (*C.uchar)(unsafe.Pointer(ctitle)),
+ encoding: w.atoms.utf8string,
+ format: 8,
+ nitems: C.ulong(len(title)),
+ },
+ w.atoms.wmName)
+ }
+
+ if prev.Mode != cnf.Mode {
+ w.SetWindowMode(cnf.Mode)
+ }
+ if w.config != prev {
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
+}
+
+func (w *x11Window) Raise() {
+ var xev C.XEvent
+ ev := (*C.XClientMessageEvent)(unsafe.Pointer(&xev))
+ *ev = C.XClientMessageEvent{
+ _type: C.ClientMessage,
+ display: w.x,
+ window: w.xw,
+ message_type: w.atoms.wmActiveWindow,
+ format: 32,
+ }
+ C.XSendEvent(
+ w.x,
+ C.XDefaultRootWindow(w.x), // MUST be the root window
+ C.False,
+ C.SubstructureNotifyMask|C.SubstructureRedirectMask,
+ &xev,
+ )
+ C.XMapRaised(w.display(), w.xw)
+}
+
+func (w *x11Window) SetCursor(name pointer.CursorName) {
+ switch name {
+ case pointer.CursorNone:
+ w.cursor = name
+ C.XFixesHideCursor(w.x, w.xw)
+ return
+ case pointer.CursorGrab:
+ name = "hand1"
+ }
+ if w.cursor == pointer.CursorNone {
+ C.XFixesShowCursor(w.x, w.xw)
+ }
+ cname := C.CString(string(name))
+ defer C.free(unsafe.Pointer(cname))
+ c := C.XcursorLibraryLoadCursor(w.x, cname)
+ if c == 0 {
+ name = pointer.CursorDefault
+ }
+ w.cursor = name
+ // If c if null (i.e. name was not found),
+ // XDefineCursor will use the default cursor.
+ C.XDefineCursor(w.x, w.xw, c)
+}
+
+func (w *x11Window) SetWindowMode(mode WindowMode) {
+ var action C.long
+ switch mode {
+ case Windowed:
+ action = _NET_WM_STATE_REMOVE
+ case Fullscreen:
+ action = _NET_WM_STATE_ADD
+ default:
+ return
+ }
+ w.config.Mode = mode
+ // "A Client wishing to change the state of a window MUST send
+ // a _NET_WM_STATE client message to the root window."
+ w.sendWMStateEvent(action, w.atoms.wmStateFullscreen, 0)
}
func (w *x11Window) ShowTextInput(show bool) {}
+func (w *x11Window) SetInputHint(_ key.InputHint) {}
+
// Close the window.
func (w *x11Window) Close() {
- w.mu.Lock()
- defer w.mu.Unlock()
-
var xev C.XEvent
ev := (*C.XClientMessageEvent)(unsafe.Pointer(&xev))
*ev = C.XClientMessageEvent{
@@ -130,9 +286,62 @@ func (w *x11Window) Close() {
C.XSendEvent(w.x, w.xw, C.False, C.NoEventMask, &xev)
}
+// Maximize the window.
+func (w *x11Window) Maximize() {
+ w.sendWMStateEvent(_NET_WM_STATE_ADD, w.atoms.wmStateMaximizedHorz, w.atoms.wmStateMaximizedVert)
+}
+
+// Center the window.
+func (w *x11Window) Center() {
+ screen := C.XDefaultScreen(w.x)
+ width := C.XDisplayWidth(w.x, screen)
+ height := C.XDisplayHeight(w.x, screen)
+
+ var attrs C.XWindowAttributes
+ C.XGetWindowAttributes(w.x, w.xw, &attrs)
+ width -= attrs.border_width
+ height -= attrs.border_width
+
+ sz := w.config.Size
+ x := (int(width) - sz.X) / 2
+ y := (int(height) - sz.Y) / 2
+
+ C.XMoveResizeWindow(w.x, w.xw, C.int(x), C.int(y), C.uint(sz.X), C.uint(sz.Y))
+}
+
+// action is one of _NET_WM_STATE_REMOVE, _NET_WM_STATE_ADD.
+func (w *x11Window) sendWMStateEvent(action C.long, atom1, atom2 C.ulong) {
+ var xev C.XEvent
+ ev := (*C.XClientMessageEvent)(unsafe.Pointer(&xev))
+ *ev = C.XClientMessageEvent{
+ _type: C.ClientMessage,
+ display: w.x,
+ window: w.xw,
+ message_type: w.atoms.wmState,
+ format: 32,
+ }
+ data := (*[5]C.long)(unsafe.Pointer(&ev.data))
+ data[0] = C.long(action)
+ data[1] = C.long(atom1)
+ data[2] = C.long(atom2)
+ data[3] = 1 // application
+
+ C.XSendEvent(
+ w.x,
+ C.XDefaultRootWindow(w.x), // MUST be the root window
+ C.False,
+ C.SubstructureNotifyMask|C.SubstructureRedirectMask,
+ &xev,
+ )
+}
+
var x11OneByte = make([]byte, 1)
-func (w *x11Window) wakeup() {
+func (w *x11Window) Wakeup() {
+ select {
+ case w.wakeups <- struct{}{}:
+ default:
+ }
if _, err := syscall.Write(w.notify.write, x11OneByte); err != nil && err != syscall.EAGAIN {
panic(fmt.Errorf("failed to write to pipe: %v", err))
}
@@ -143,7 +352,7 @@ func (w *x11Window) display() *C.Display {
}
func (w *x11Window) window() (C.Window, int, int) {
- return w.xw, w.width, w.height
+ return w.xw, w.config.Size.X, w.config.Size.Y
}
func (w *x11Window) setStage(s system.Stage) {
@@ -151,7 +360,7 @@ func (w *x11Window) setStage(s system.Stage) {
return
}
w.stage = s
- w.w.Event(system.StageEvent{s})
+ w.w.Event(system.StageEvent{Stage: s})
}
func (w *x11Window) loop() {
@@ -174,9 +383,7 @@ loop:
// This fixes an issue on Xephyr where on startup XPending() > 0 but
// poll will still block. This also prevents no-op calls to poll.
if syn = h.handleEvents(); !syn {
- w.mu.Lock()
anim = w.animating
- w.mu.Unlock()
if !anim {
// Clear poll events.
*xEvents = 0
@@ -205,34 +412,22 @@ loop:
panic(fmt.Errorf("x11 loop: read from notify pipe failed: %w", err))
}
}
+ select {
+ case <-w.wakeups:
+ w.w.Event(wakeupEvent{})
+ default:
+ }
- if anim || syn {
- w.w.Event(FrameEvent{
+ if (anim || syn) && w.config.Size.X != 0 && w.config.Size.Y != 0 {
+ w.w.Event(frameEvent{
FrameEvent: system.FrameEvent{
- Now: time.Now(),
- Size: image.Point{
- X: w.width,
- Y: w.height,
- },
- Metric: w.cfg,
+ Now: time.Now(),
+ Size: w.config.Size,
+ Metric: w.metric,
},
Sync: syn,
})
}
- w.mu.Lock()
- readClipboard := w.clipboard.read
- writeClipboard := w.clipboard.write
- w.clipboard.read = false
- w.clipboard.write = nil
- w.mu.Unlock()
- if readClipboard {
- C.XDeleteProperty(w.x, w.xw, w.atoms.clipboardContent)
- C.XConvertSelection(w.x, w.atoms.clipboard, w.atoms.utf8string, w.atoms.clipboardContent, w.xw, C.CurrentTime)
- }
- if writeClipboard != nil {
- w.clipboard.content = []byte(*writeClipboard)
- C.XSetSelectionOwner(w.x, w.atoms.clipboard, w.xw, C.CurrentTime)
- }
}
w.w.Event(system.DestroyEvent{Err: nil})
}
@@ -301,12 +496,15 @@ func (h *x11EventHandler) handleEvents() bool {
h.w.xkb.UpdateMask(uint32(state.base_mods), uint32(state.latched_mods), uint32(state.locked_mods),
uint32(state.base_group), uint32(state.latched_group), uint32(state.locked_group))
}
- case C.KeyPress:
+ case C.KeyPress, C.KeyRelease:
+ ks := key.Press
+ if _type == C.KeyRelease {
+ ks = key.Release
+ }
kevt := (*C.XKeyPressedEvent)(unsafe.Pointer(xev))
- for _, e := range h.w.xkb.DispatchKey(uint32(kevt.keycode)) {
+ for _, e := range h.w.xkb.DispatchKey(uint32(kevt.keycode), ks) {
w.w.Event(e)
}
- case C.KeyRelease:
case C.ButtonPress, C.ButtonRelease:
bevt := (*C.XButtonEvent)(unsafe.Pointer(xev))
ev := pointer.Event{
@@ -326,11 +524,11 @@ func (h *x11EventHandler) handleEvents() bool {
const scrollScale = 10
switch bevt.button {
case C.Button1:
- btn = pointer.ButtonLeft
+ btn = pointer.ButtonPrimary
case C.Button2:
- btn = pointer.ButtonMiddle
+ btn = pointer.ButtonTertiary
case C.Button3:
- btn = pointer.ButtonRight
+ btn = pointer.ButtonSecondary
case C.Button4:
// scroll up
ev.Type = pointer.Scroll
@@ -339,6 +537,15 @@ func (h *x11EventHandler) handleEvents() bool {
// scroll down
ev.Type = pointer.Scroll
ev.Scroll.Y = +scrollScale
+ case 6:
+ // http://xahlee.info/linux/linux_x11_mouse_button_number.html
+ // scroll left
+ ev.Type = pointer.Scroll
+ ev.Scroll.X = -scrollScale * 2
+ case 7:
+ // scroll right
+ ev.Type = pointer.Scroll
+ ev.Scroll.X = +scrollScale * 2
default:
continue
}
@@ -372,8 +579,10 @@ func (h *x11EventHandler) handleEvents() bool {
w.w.Event(key.FocusEvent{Focus: false})
case C.ConfigureNotify: // window configuration change
cevt := (*C.XConfigureEvent)(unsafe.Pointer(xev))
- w.width = int(cevt.width)
- w.height = int(cevt.height)
+ if sz := image.Pt(int(cevt.width), int(cevt.height)); sz != w.config.Size {
+ w.config.Size = sz
+ w.w.Event(ConfigEvent{Config: w.config})
+ }
// redraw will be done by a later expose event
case C.SelectionNotify:
cevt := (*C.XSelectionEvent)(unsafe.Pointer(xev))
@@ -394,10 +603,10 @@ func (h *x11EventHandler) handleEvents() bool {
break
}
str := C.GoStringN((*C.char)(unsafe.Pointer(text.value)), C.int(text.nitems))
- w.w.Event(system.ClipboardEvent{Text: str})
+ w.w.Event(clipboard.Event{Text: str})
case C.SelectionRequest:
cevt := (*C.XSelectionRequestEvent)(unsafe.Pointer(xev))
- if cevt.selection != w.atoms.clipboard || cevt.property == C.None {
+ if (cevt.selection != w.atoms.clipboard && cevt.selection != w.atoms.primary) || cevt.property == C.None {
// Unsupported clipboard or obsolete requestor.
break
}
@@ -418,21 +627,27 @@ func (h *x11EventHandler) handleEvents() bool {
switch cevt.target {
case w.atoms.targets:
// The requestor wants the supported clipboard
- // formats. First write the formats...
- formats := []uint32{uint32(w.atoms.utf8string)}
+ // formats. First write the targets...
+ formats := [...]C.long{
+ C.long(w.atoms.targets),
+ C.long(w.atoms.utf8string),
+ C.long(w.atoms.plaintext),
+ // GTK clients need this.
+ C.long(w.atoms.gtk_text_buffer_contents),
+ }
C.XChangeProperty(w.x, cevt.requestor, cevt.property, w.atoms.atom,
32 /* bitwidth of formats */, C.PropModeReplace,
- (*C.uchar)(unsafe.Pointer(&formats[0])), C.int(len(formats)),
+ (*C.uchar)(unsafe.Pointer(&formats)), C.int(len(formats)),
)
// ...then notify the requestor.
notify()
- case w.atoms.utf8string:
+ case w.atoms.plaintext, w.atoms.utf8string, w.atoms.gtk_text_buffer_contents:
content := w.clipboard.content
var ptr *C.uchar
if len(content) > 0 {
ptr = (*C.uchar)(unsafe.Pointer(&content[0]))
}
- C.XChangeProperty(w.x, cevt.requestor, cevt.property, w.atoms.utf8string,
+ C.XChangeProperty(w.x, cevt.requestor, cevt.property, cevt.target,
8 /* bitwidth */, C.PropModeReplace,
ptr, C.int(len(content)),
)
@@ -458,7 +673,7 @@ func init() {
x11Driver = newX11Window
}
-func newX11Window(gioWin Callbacks, opts *Options) error {
+func newX11Window(gioWin *callbacks, options []Option) error {
var err error
pipe := make([]int, 2)
@@ -498,6 +713,10 @@ func newX11Window(gioWin Callbacks, opts *Options) error {
ppsp := x11DetectUIScale(dpy)
cfg := unit.Metric{PxPerDp: ppsp, PxPerSp: ppsp}
+ // Only use cnf for getting the window size.
+ var cnf Config
+ cnf.apply(cfg, options)
+
swa := C.XSetWindowAttributes{
event_mask: C.ExposureMask | C.FocusChangeMask | // update
C.KeyPressMask | C.KeyReleaseMask | // keyboard
@@ -508,17 +727,17 @@ func newX11Window(gioWin Callbacks, opts *Options) error {
override_redirect: C.False,
}
win := C.XCreateWindow(dpy, C.XDefaultRootWindow(dpy),
- 0, 0, C.uint(cfg.Px(opts.Width)), C.uint(cfg.Px(opts.Height)),
+ 0, 0, C.uint(cnf.Size.X), C.uint(cnf.Size.Y),
0, C.CopyFromParent, C.InputOutput, nil,
C.CWEventMask|C.CWBackPixmap|C.CWOverrideRedirect, &swa)
w := &x11Window{
w: gioWin, x: dpy, xw: win,
- width: cfg.Px(opts.Width),
- height: cfg.Px(opts.Height),
- cfg: cfg,
+ metric: cfg,
xkb: xkb,
xkbEventBase: xkbEventBase,
+ wakeups: make(chan struct{}, 1),
+ config: Config{Size: cnf.Size},
}
w.notify.read = pipe[0]
w.notify.write = pipe[1]
@@ -533,57 +752,40 @@ func newX11Window(gioWin Callbacks, opts *Options) error {
hints.flags = C.InputHint
C.XSetWMHints(dpy, win, &hints)
- var shints C.XSizeHints
- if opts.MinWidth.V != 0 || opts.MinHeight.V != 0 {
- shints.min_width = C.int(cfg.Px(opts.MinWidth))
- shints.min_height = C.int(cfg.Px(opts.MinHeight))
- shints.flags = C.PMinSize
- }
- if opts.MaxWidth.V != 0 || opts.MaxHeight.V != 0 {
- shints.max_width = C.int(cfg.Px(opts.MaxWidth))
- shints.max_height = C.int(cfg.Px(opts.MaxHeight))
- shints.flags = shints.flags | C.PMaxSize
- }
- if shints.flags != 0 {
- C.XSetWMNormalHints(dpy, win, &shints)
- }
-
name := C.CString(filepath.Base(os.Args[0]))
defer C.free(unsafe.Pointer(name))
wmhints := C.XClassHint{name, name}
C.XSetClassHint(dpy, win, &wmhints)
w.atoms.utf8string = w.atom("UTF8_STRING", false)
+ w.atoms.plaintext = w.atom("text/plain;charset=utf-8", false)
+ w.atoms.gtk_text_buffer_contents = w.atom("GTK_TEXT_BUFFER_CONTENTS", false)
w.atoms.evDelWindow = w.atom("WM_DELETE_WINDOW", false)
w.atoms.clipboard = w.atom("CLIPBOARD", false)
+ w.atoms.primary = w.atom("PRIMARY", false)
w.atoms.clipboardContent = w.atom("CLIPBOARD_CONTENT", false)
w.atoms.atom = w.atom("ATOM", false)
w.atoms.targets = w.atom("TARGETS", false)
-
- // set the name
- ctitle := C.CString(opts.Title)
- defer C.free(unsafe.Pointer(ctitle))
- C.XStoreName(dpy, win, ctitle)
- // set _NET_WM_NAME as well for UTF-8 support in window title.
- C.XSetTextProperty(dpy, win,
- &C.XTextProperty{
- value: (*C.uchar)(unsafe.Pointer(ctitle)),
- encoding: w.atoms.utf8string,
- format: 8,
- nitems: C.ulong(len(opts.Title)),
- },
- w.atom("_NET_WM_NAME", false))
+ w.atoms.wmName = w.atom("_NET_WM_NAME", false)
+ w.atoms.wmState = w.atom("_NET_WM_STATE", false)
+ w.atoms.wmStateFullscreen = w.atom("_NET_WM_STATE_FULLSCREEN", false)
+ w.atoms.wmActiveWindow = w.atom("_NET_ACTIVE_WINDOW", false)
+ w.atoms.wmStateMaximizedHorz = w.atom("_NET_WM_STATE_MAXIMIZED_HORZ", false)
+ w.atoms.wmStateMaximizedVert = w.atom("_NET_WM_STATE_MAXIMIZED_VERT", false)
// extensions
C.XSetWMProtocols(dpy, win, &w.atoms.evDelWindow, 1)
- // make the window visible on the screen
- C.XMapWindow(dpy, win)
-
go func() {
w.w.SetDriver(w)
+ w.Configure(options)
+
+ // make the window visible on the screen
+ C.XMapWindow(dpy, win)
+ w.w.Event(ViewEvent{Display: unsafe.Pointer(dpy), Window: uintptr(win)})
w.setStage(system.StageRunning)
w.loop()
+ w.w.Event(ViewEvent{})
w.destroy()
}()
return nil
diff --git a/vendor/gioui.org/app/internal/window/runmain.go b/vendor/gioui.org/app/runmain.go
index f9de5d0..a1c1e3d 100644
--- a/vendor/gioui.org/app/internal/window/runmain.go
+++ b/vendor/gioui.org/app/runmain.go
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: Unlicense OR MIT
+//go:build android || (darwin && ios)
// +build android darwin,ios
-package window
+package app
// Android only supports non-Java programs as c-shared libraries.
// Unfortunately, Go does not run a program's main function in
diff --git a/vendor/gioui.org/app/sigpipe_darwin.go b/vendor/gioui.org/app/sigpipe_darwin.go
deleted file mode 100644
index aca19b7..0000000
--- a/vendor/gioui.org/app/sigpipe_darwin.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-// +build !go1.14
-
-// Work around golang.org/issue/33384, fixed in CL 191785,
-// to be released in Go 1.14.
-
-package app
-
-import (
- "os"
- "os/signal"
- "syscall"
-)
-
-func init() {
- signal.Notify(make(chan os.Signal), syscall.SIGPIPE)
-}
diff --git a/vendor/gioui.org/app/vulkan.go b/vendor/gioui.org/app/vulkan.go
new file mode 100644
index 0000000..630c254
--- /dev/null
+++ b/vendor/gioui.org/app/vulkan.go
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build (linux || freebsd) && !novulkan
+// +build linux freebsd
+// +build !novulkan
+
+package app
+
+import (
+ "errors"
+ "unsafe"
+
+ "gioui.org/gpu"
+ "gioui.org/internal/vk"
+)
+
+type vkContext struct {
+ physDev vk.PhysicalDevice
+ inst vk.Instance
+ dev vk.Device
+ queueFam int
+ queue vk.Queue
+ acquireSem vk.Semaphore
+ presentSem vk.Semaphore
+
+ swchain vk.Swapchain
+ imgs []vk.Image
+ views []vk.ImageView
+ fbos []vk.Framebuffer
+ format vk.Format
+ presentIdx int
+}
+
+func newVulkanContext(inst vk.Instance, surf vk.Surface) (*vkContext, error) {
+ physDev, qFam, err := vk.ChoosePhysicalDevice(inst, surf)
+ if err != nil {
+ return nil, err
+ }
+ dev, err := vk.CreateDeviceAndQueue(physDev, qFam, "VK_KHR_swapchain")
+ if err != nil {
+ return nil, err
+ }
+ if err != nil {
+ vk.DestroyDevice(dev)
+ return nil, err
+ }
+ acquireSem, err := vk.CreateSemaphore(dev)
+ if err != nil {
+ vk.DestroyDevice(dev)
+ return nil, err
+ }
+ presentSem, err := vk.CreateSemaphore(dev)
+ if err != nil {
+ vk.DestroySemaphore(dev, acquireSem)
+ vk.DestroyDevice(dev)
+ return nil, err
+ }
+ c := &vkContext{
+ physDev: physDev,
+ inst: inst,
+ dev: dev,
+ queueFam: qFam,
+ queue: vk.GetDeviceQueue(dev, qFam, 0),
+ acquireSem: acquireSem,
+ presentSem: presentSem,
+ }
+ return c, nil
+}
+
+func (c *vkContext) RenderTarget() (gpu.RenderTarget, error) {
+ vk.DeviceWaitIdle(c.dev)
+
+ imgIdx, err := vk.AcquireNextImage(c.dev, c.swchain, c.acquireSem, 0)
+ if err := mapSurfaceErr(err); err != nil {
+ return nil, err
+ }
+ c.presentIdx = imgIdx
+ return gpu.VulkanRenderTarget{
+ WaitSem: uint64(c.acquireSem),
+ SignalSem: uint64(c.presentSem),
+ Framebuffer: uint64(c.fbos[imgIdx]),
+ Image: uint64(c.imgs[imgIdx]),
+ }, nil
+}
+
+func (c *vkContext) api() gpu.API {
+ return gpu.Vulkan{
+ PhysDevice: unsafe.Pointer(c.physDev),
+ Device: unsafe.Pointer(c.dev),
+ Format: int(c.format),
+ QueueFamily: c.queueFam,
+ QueueIndex: 0,
+ }
+}
+
+func mapErr(err error) error {
+ var vkErr vk.Error
+ if errors.As(err, &vkErr) && vkErr == vk.ERROR_DEVICE_LOST {
+ return gpu.ErrDeviceLost
+ }
+ return err
+}
+
+func mapSurfaceErr(err error) error {
+ var vkErr vk.Error
+ if !errors.As(err, &vkErr) {
+ return err
+ }
+ switch {
+ case vkErr == vk.SUBOPTIMAL_KHR:
+ // Android reports VK_SUBOPTIMAL_KHR when presenting to a rotated
+ // swapchain (preTransform != currentTransform). However, we don't
+ // support transforming the output ourselves, so we'll live with it.
+ return nil
+ case vkErr == vk.ERROR_OUT_OF_DATE_KHR:
+ return errOutOfDate
+ case vkErr == vk.ERROR_SURFACE_LOST_KHR:
+ // Treating a lost surface as a lost device isn't accurate, but
+ // probably not worth optimizing.
+ return gpu.ErrDeviceLost
+ }
+ return mapErr(err)
+}
+
+func (c *vkContext) release() {
+ vk.DeviceWaitIdle(c.dev)
+
+ c.destroySwapchain()
+ vk.DestroySemaphore(c.dev, c.acquireSem)
+ vk.DestroySemaphore(c.dev, c.presentSem)
+ vk.DestroyDevice(c.dev)
+ *c = vkContext{}
+}
+
+func (c *vkContext) present() error {
+ return mapSurfaceErr(vk.PresentQueue(c.queue, c.swchain, c.presentSem, c.presentIdx))
+}
+
+func (c *vkContext) destroyImageViews() {
+ for _, f := range c.fbos {
+ vk.DestroyFramebuffer(c.dev, f)
+ }
+ c.fbos = nil
+ for _, view := range c.views {
+ vk.DestroyImageView(c.dev, view)
+ }
+ c.views = nil
+}
+
+func (c *vkContext) destroySwapchain() {
+ vk.DeviceWaitIdle(c.dev)
+
+ c.destroyImageViews()
+ if c.swchain != 0 {
+ vk.DestroySwapchain(c.dev, c.swchain)
+ c.swchain = 0
+ }
+}
+
+func (c *vkContext) refresh(surf vk.Surface, width, height int) error {
+ vk.DeviceWaitIdle(c.dev)
+
+ c.destroyImageViews()
+ // Check whether size is valid. That's needed on X11, where ConfigureNotify
+ // is not always synchronized with the window extent.
+ caps, err := vk.GetPhysicalDeviceSurfaceCapabilities(c.physDev, surf)
+ if err != nil {
+ return err
+ }
+ minExt, maxExt := caps.MinExtent(), caps.MaxExtent()
+ if width < minExt.X || maxExt.X < width || height < minExt.Y || maxExt.Y < height {
+ return errOutOfDate
+ }
+ swchain, imgs, format, err := vk.CreateSwapchain(c.physDev, c.dev, surf, width, height, c.swchain)
+ if c.swchain != 0 {
+ vk.DestroySwapchain(c.dev, c.swchain)
+ c.swchain = 0
+ }
+ if err := mapSurfaceErr(err); err != nil {
+ return err
+ }
+ c.swchain = swchain
+ c.imgs = imgs
+ c.format = format
+ pass, err := vk.CreateRenderPass(
+ c.dev,
+ format,
+ vk.ATTACHMENT_LOAD_OP_CLEAR,
+ vk.IMAGE_LAYOUT_UNDEFINED,
+ vk.IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ nil,
+ )
+ if err := mapErr(err); err != nil {
+ return err
+ }
+ defer vk.DestroyRenderPass(c.dev, pass)
+ for _, img := range imgs {
+ view, err := vk.CreateImageView(c.dev, img, format)
+ if err := mapErr(err); err != nil {
+ return err
+ }
+ c.views = append(c.views, view)
+ fbo, err := vk.CreateFramebuffer(c.dev, pass, view, width, height)
+ if err := mapErr(err); err != nil {
+ return err
+ }
+ c.fbos = append(c.fbos, fbo)
+ }
+ return nil
+}
diff --git a/vendor/gioui.org/app/vulkan_android.go b/vendor/gioui.org/app/vulkan_android.go
new file mode 100644
index 0000000..3758d04
--- /dev/null
+++ b/vendor/gioui.org/app/vulkan_android.go
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build !novulkan
+// +build !novulkan
+
+package app
+
+import (
+ "unsafe"
+
+ "gioui.org/gpu"
+ "gioui.org/internal/vk"
+)
+
+type wlVkContext struct {
+ win *window
+ inst vk.Instance
+ surf vk.Surface
+ ctx *vkContext
+}
+
+func init() {
+ newAndroidVulkanContext = func(w *window) (context, error) {
+ inst, err := vk.CreateInstance("VK_KHR_surface", "VK_KHR_android_surface")
+ if err != nil {
+ return nil, err
+ }
+ window, _, _ := w.nativeWindow()
+ surf, err := vk.CreateAndroidSurface(inst, unsafe.Pointer(window))
+ if err != nil {
+ vk.DestroyInstance(inst)
+ return nil, err
+ }
+ ctx, err := newVulkanContext(inst, surf)
+ if err != nil {
+ vk.DestroySurface(inst, surf)
+ vk.DestroyInstance(inst)
+ return nil, err
+ }
+ c := &wlVkContext{
+ win: w,
+ inst: inst,
+ surf: surf,
+ ctx: ctx,
+ }
+ return c, nil
+ }
+}
+
+func (c *wlVkContext) RenderTarget() (gpu.RenderTarget, error) {
+ return c.ctx.RenderTarget()
+}
+
+func (c *wlVkContext) API() gpu.API {
+ return c.ctx.api()
+}
+
+func (c *wlVkContext) Release() {
+ c.ctx.release()
+ if c.surf != 0 {
+ vk.DestroySurface(c.inst, c.surf)
+ }
+ vk.DestroyInstance(c.inst)
+ *c = wlVkContext{}
+}
+
+func (c *wlVkContext) Present() error {
+ return c.ctx.present()
+}
+
+func (c *wlVkContext) Lock() error {
+ return nil
+}
+
+func (c *wlVkContext) Unlock() {}
+
+func (c *wlVkContext) Refresh() error {
+ win, w, h := c.win.nativeWindow()
+ if c.surf != 0 {
+ c.ctx.destroySwapchain()
+ vk.DestroySurface(c.inst, c.surf)
+ c.surf = 0
+ }
+ surf, err := vk.CreateAndroidSurface(c.inst, unsafe.Pointer(win))
+ if err != nil {
+ return err
+ }
+ c.surf = surf
+ return c.ctx.refresh(c.surf, w, h)
+}
diff --git a/vendor/gioui.org/app/vulkan_wayland.go b/vendor/gioui.org/app/vulkan_wayland.go
new file mode 100644
index 0000000..7bf0662
--- /dev/null
+++ b/vendor/gioui.org/app/vulkan_wayland.go
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build ((linux && !android) || freebsd) && !nowayland && !novulkan
+// +build linux,!android freebsd
+// +build !nowayland
+// +build !novulkan
+
+package app
+
+import (
+ "unsafe"
+
+ "gioui.org/gpu"
+ "gioui.org/internal/vk"
+)
+
+type wlVkContext struct {
+ win *window
+ inst vk.Instance
+ surf vk.Surface
+ ctx *vkContext
+}
+
+func init() {
+ newWaylandVulkanContext = func(w *window) (context, error) {
+ inst, err := vk.CreateInstance("VK_KHR_surface", "VK_KHR_wayland_surface")
+ if err != nil {
+ return nil, err
+ }
+ disp := w.display()
+ wlSurf, _, _ := w.surface()
+ surf, err := vk.CreateWaylandSurface(inst, unsafe.Pointer(disp), unsafe.Pointer(wlSurf))
+ if err != nil {
+ vk.DestroyInstance(inst)
+ return nil, err
+ }
+ ctx, err := newVulkanContext(inst, surf)
+ if err != nil {
+ vk.DestroySurface(inst, surf)
+ vk.DestroyInstance(inst)
+ return nil, err
+ }
+ c := &wlVkContext{
+ win: w,
+ inst: inst,
+ surf: surf,
+ ctx: ctx,
+ }
+ return c, nil
+ }
+}
+
+func (c *wlVkContext) RenderTarget() (gpu.RenderTarget, error) {
+ return c.ctx.RenderTarget()
+}
+
+func (c *wlVkContext) API() gpu.API {
+ return c.ctx.api()
+}
+
+func (c *wlVkContext) Release() {
+ c.ctx.release()
+ vk.DestroySurface(c.inst, c.surf)
+ vk.DestroyInstance(c.inst)
+ *c = wlVkContext{}
+}
+
+func (c *wlVkContext) Present() error {
+ return c.ctx.present()
+}
+
+func (c *wlVkContext) Lock() error {
+ return nil
+}
+
+func (c *wlVkContext) Unlock() {}
+
+func (c *wlVkContext) Refresh() error {
+ _, w, h := c.win.surface()
+ return c.ctx.refresh(c.surf, w, h)
+}
diff --git a/vendor/gioui.org/app/vulkan_x11.go b/vendor/gioui.org/app/vulkan_x11.go
new file mode 100644
index 0000000..cf97774
--- /dev/null
+++ b/vendor/gioui.org/app/vulkan_x11.go
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build ((linux && !android) || freebsd) && !nox11 && !novulkan
+// +build linux,!android freebsd
+// +build !nox11
+// +build !novulkan
+
+package app
+
+import (
+ "unsafe"
+
+ "gioui.org/gpu"
+ "gioui.org/internal/vk"
+)
+
+type x11VkContext struct {
+ win *x11Window
+ inst vk.Instance
+ surf vk.Surface
+ ctx *vkContext
+}
+
+func init() {
+ newX11VulkanContext = func(w *x11Window) (context, error) {
+ inst, err := vk.CreateInstance("VK_KHR_surface", "VK_KHR_xlib_surface")
+ if err != nil {
+ return nil, err
+ }
+ disp := w.display()
+ window, _, _ := w.window()
+ surf, err := vk.CreateXlibSurface(inst, unsafe.Pointer(disp), uintptr(window))
+ if err != nil {
+ vk.DestroyInstance(inst)
+ return nil, err
+ }
+ ctx, err := newVulkanContext(inst, surf)
+ if err != nil {
+ vk.DestroySurface(inst, surf)
+ vk.DestroyInstance(inst)
+ return nil, err
+ }
+ c := &x11VkContext{
+ win: w,
+ inst: inst,
+ surf: surf,
+ ctx: ctx,
+ }
+ return c, nil
+ }
+}
+
+func (c *x11VkContext) RenderTarget() (gpu.RenderTarget, error) {
+ return c.ctx.RenderTarget()
+}
+
+func (c *x11VkContext) API() gpu.API {
+ return c.ctx.api()
+}
+
+func (c *x11VkContext) Release() {
+ c.ctx.release()
+ vk.DestroySurface(c.inst, c.surf)
+ vk.DestroyInstance(c.inst)
+ *c = x11VkContext{}
+}
+
+func (c *x11VkContext) Present() error {
+ return c.ctx.present()
+}
+
+func (c *x11VkContext) Lock() error {
+ return nil
+}
+
+func (c *x11VkContext) Unlock() {}
+
+func (c *x11VkContext) Refresh() error {
+ _, w, h := c.win.window()
+ return c.ctx.refresh(c.surf, w, h)
+}
diff --git a/vendor/gioui.org/app/internal/window/wayland_text_input.c b/vendor/gioui.org/app/wayland_text_input.c
index a69af09..65de0bb 100644
--- a/vendor/gioui.org/app/internal/window/wayland_text_input.c
+++ b/vendor/gioui.org/app/wayland_text_input.c
@@ -1,6 +1,8 @@
-// +build linux,!android,!nowayland freebsd
+//go:build ((linux && !android) || freebsd) && !nowayland
+// +build linux,!android freebsd
+// +build !nowayland
-/* Generated by wayland-scanner 1.17.0 */
+/* Generated by wayland-scanner 1.19.0 */
/*
* Copyright © 2012, 2013 Intel Corporation
@@ -48,7 +50,7 @@ extern const struct wl_interface wl_seat_interface;
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface zwp_text_input_v3_interface;
-static const struct wl_interface *types[] = {
+static const struct wl_interface *text_input_unstable_v3_types[] = {
NULL,
NULL,
NULL,
@@ -60,23 +62,23 @@ static const struct wl_interface *types[] = {
};
static const struct wl_message zwp_text_input_v3_requests[] = {
- { "destroy", "", types + 0 },
- { "enable", "", types + 0 },
- { "disable", "", types + 0 },
- { "set_surrounding_text", "sii", types + 0 },
- { "set_text_change_cause", "u", types + 0 },
- { "set_content_type", "uu", types + 0 },
- { "set_cursor_rectangle", "iiii", types + 0 },
- { "commit", "", types + 0 },
+ { "destroy", "", text_input_unstable_v3_types + 0 },
+ { "enable", "", text_input_unstable_v3_types + 0 },
+ { "disable", "", text_input_unstable_v3_types + 0 },
+ { "set_surrounding_text", "sii", text_input_unstable_v3_types + 0 },
+ { "set_text_change_cause", "u", text_input_unstable_v3_types + 0 },
+ { "set_content_type", "uu", text_input_unstable_v3_types + 0 },
+ { "set_cursor_rectangle", "iiii", text_input_unstable_v3_types + 0 },
+ { "commit", "", text_input_unstable_v3_types + 0 },
};
static const struct wl_message zwp_text_input_v3_events[] = {
- { "enter", "o", types + 4 },
- { "leave", "o", types + 5 },
- { "preedit_string", "?sii", types + 0 },
- { "commit_string", "?s", types + 0 },
- { "delete_surrounding_text", "uu", types + 0 },
- { "done", "u", types + 0 },
+ { "enter", "o", text_input_unstable_v3_types + 4 },
+ { "leave", "o", text_input_unstable_v3_types + 5 },
+ { "preedit_string", "?sii", text_input_unstable_v3_types + 0 },
+ { "commit_string", "?s", text_input_unstable_v3_types + 0 },
+ { "delete_surrounding_text", "uu", text_input_unstable_v3_types + 0 },
+ { "done", "u", text_input_unstable_v3_types + 0 },
};
WL_PRIVATE const struct wl_interface zwp_text_input_v3_interface = {
@@ -86,8 +88,8 @@ WL_PRIVATE const struct wl_interface zwp_text_input_v3_interface = {
};
static const struct wl_message zwp_text_input_manager_v3_requests[] = {
- { "destroy", "", types + 0 },
- { "get_text_input", "no", types + 6 },
+ { "destroy", "", text_input_unstable_v3_types + 0 },
+ { "get_text_input", "no", text_input_unstable_v3_types + 6 },
};
WL_PRIVATE const struct wl_interface zwp_text_input_manager_v3_interface = {
diff --git a/vendor/gioui.org/app/internal/window/wayland_text_input.h b/vendor/gioui.org/app/wayland_text_input.h
index 8a6f8dd..882da43 100644
--- a/vendor/gioui.org/app/internal/window/wayland_text_input.h
+++ b/vendor/gioui.org/app/wayland_text_input.h
@@ -1,4 +1,4 @@
-/* Generated by wayland-scanner 1.17.0 */
+/* Generated by wayland-scanner 1.19.0 */
#ifndef TEXT_INPUT_UNSTABLE_V3_CLIENT_PROTOCOL_H
#define TEXT_INPUT_UNSTABLE_V3_CLIENT_PROTOCOL_H
@@ -71,6 +71,8 @@ struct wl_surface;
struct zwp_text_input_manager_v3;
struct zwp_text_input_v3;
+#ifndef ZWP_TEXT_INPUT_V3_INTERFACE
+#define ZWP_TEXT_INPUT_V3_INTERFACE
/**
* @page page_iface_zwp_text_input_v3 zwp_text_input_v3
* @section page_iface_zwp_text_input_v3_desc Description
@@ -135,6 +137,9 @@ struct zwp_text_input_v3;
* needs to be resent by the client.
*/
extern const struct wl_interface zwp_text_input_v3_interface;
+#endif
+#ifndef ZWP_TEXT_INPUT_MANAGER_V3_INTERFACE
+#define ZWP_TEXT_INPUT_MANAGER_V3_INTERFACE
/**
* @page page_iface_zwp_text_input_manager_v3 zwp_text_input_manager_v3
* @section page_iface_zwp_text_input_manager_v3_desc Description
@@ -149,6 +154,7 @@ extern const struct wl_interface zwp_text_input_v3_interface;
* A factory for text-input objects. This object is a global singleton.
*/
extern const struct wl_interface zwp_text_input_manager_v3_interface;
+#endif
#ifndef ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_ENUM
#define ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_ENUM
@@ -310,6 +316,9 @@ struct zwp_text_input_v3_listener {
* Notification that this seat's text-input focus is on a certain
* surface.
*
+ * If client has created multiple text input objects, compositor
+ * must send this event to all of them.
+ *
* When the seat has the keyboard capability the text-input focus
* follows the keyboard focus. This event sets the current surface
* for the text-input object.
@@ -325,7 +334,9 @@ struct zwp_text_input_v3_listener {
* previously set.
*
* The leave notification clears the current surface. It is sent
- * before the enter notification for the new focus.
+ * before the enter notification for the new focus. After leave
+ * event, compositor must ignore requests from any text input
+ * instances until next enter event.
*
* When the seat has the keyboard capability the text-input focus
* follows the keyboard focus.
@@ -559,6 +570,12 @@ zwp_text_input_v3_destroy(struct zwp_text_input_v3 *zwp_text_input_v3)
* zwp_text_input_v3.disable when there is no longer any input focus on
* the current surface.
*
+ * Clients must not enable more than one text input on the single seat
+ * and should disable the current text input before enabling the new one.
+ * At most one instance of text input may be in enabled state per instance,
+ * Requests to enable the another text input when some text input is active
+ * must be ignored by compositor.
+ *
* This request resets all state associated with previous enable, disable,
* set_surrounding_text, set_text_change_cause, set_content_type, and
* set_cursor_rectangle requests, as well as the state associated with
diff --git a/vendor/gioui.org/app/internal/window/wayland_xdg_decoration.c b/vendor/gioui.org/app/wayland_xdg_decoration.c
index fa13d7c..ee94c60 100644
--- a/vendor/gioui.org/app/internal/window/wayland_xdg_decoration.c
+++ b/vendor/gioui.org/app/wayland_xdg_decoration.c
@@ -1,6 +1,8 @@
-// +build linux,!android,!nowayland freebsd
+//go:build ((linux && !android) || freebsd) && !nowayland
+// +build linux,!android freebsd
+// +build !nowayland
-/* Generated by wayland-scanner 1.17.0 */
+/* Generated by wayland-scanner 1.19.0 */
/*
* Copyright © 2018 Simon Ser
@@ -42,15 +44,15 @@
extern const struct wl_interface xdg_toplevel_interface;
extern const struct wl_interface zxdg_toplevel_decoration_v1_interface;
-static const struct wl_interface *types[] = {
+static const struct wl_interface *xdg_decoration_unstable_v1_types[] = {
NULL,
&zxdg_toplevel_decoration_v1_interface,
&xdg_toplevel_interface,
};
static const struct wl_message zxdg_decoration_manager_v1_requests[] = {
- { "destroy", "", types + 0 },
- { "get_toplevel_decoration", "no", types + 1 },
+ { "destroy", "", xdg_decoration_unstable_v1_types + 0 },
+ { "get_toplevel_decoration", "no", xdg_decoration_unstable_v1_types + 1 },
};
WL_PRIVATE const struct wl_interface zxdg_decoration_manager_v1_interface = {
@@ -60,13 +62,13 @@ WL_PRIVATE const struct wl_interface zxdg_decoration_manager_v1_interface = {
};
static const struct wl_message zxdg_toplevel_decoration_v1_requests[] = {
- { "destroy", "", types + 0 },
- { "set_mode", "u", types + 0 },
- { "unset_mode", "", types + 0 },
+ { "destroy", "", xdg_decoration_unstable_v1_types + 0 },
+ { "set_mode", "u", xdg_decoration_unstable_v1_types + 0 },
+ { "unset_mode", "", xdg_decoration_unstable_v1_types + 0 },
};
static const struct wl_message zxdg_toplevel_decoration_v1_events[] = {
- { "configure", "u", types + 0 },
+ { "configure", "u", xdg_decoration_unstable_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface zxdg_toplevel_decoration_v1_interface = {
diff --git a/vendor/gioui.org/app/internal/window/wayland_xdg_decoration.h b/vendor/gioui.org/app/wayland_xdg_decoration.h
index 044ea2e..004d342 100644
--- a/vendor/gioui.org/app/internal/window/wayland_xdg_decoration.h
+++ b/vendor/gioui.org/app/wayland_xdg_decoration.h
@@ -1,4 +1,4 @@
-/* Generated by wayland-scanner 1.17.0 */
+/* Generated by wayland-scanner 1.19.0 */
#ifndef XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H
@@ -45,6 +45,8 @@ struct xdg_toplevel;
struct zxdg_decoration_manager_v1;
struct zxdg_toplevel_decoration_v1;
+#ifndef ZXDG_DECORATION_MANAGER_V1_INTERFACE
+#define ZXDG_DECORATION_MANAGER_V1_INTERFACE
/**
* @page page_iface_zxdg_decoration_manager_v1 zxdg_decoration_manager_v1
* @section page_iface_zxdg_decoration_manager_v1_desc Description
@@ -101,6 +103,9 @@ struct zxdg_toplevel_decoration_v1;
* interface version number is reset.
*/
extern const struct wl_interface zxdg_decoration_manager_v1_interface;
+#endif
+#ifndef ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE
+#define ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE
/**
* @page page_iface_zxdg_toplevel_decoration_v1 zxdg_toplevel_decoration_v1
* @section page_iface_zxdg_toplevel_decoration_v1_desc Description
@@ -125,6 +130,7 @@ extern const struct wl_interface zxdg_decoration_manager_v1_interface;
* xdg_toplevel.
*/
extern const struct wl_interface zxdg_toplevel_decoration_v1_interface;
+#endif
#define ZXDG_DECORATION_MANAGER_V1_DESTROY 0
#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION 1
@@ -332,7 +338,7 @@ zxdg_toplevel_decoration_v1_destroy(struct zxdg_toplevel_decoration_v1 *zxdg_top
* that the client prefers the provided decoration mode.
*
* After requesting a decoration mode, the compositor will respond by
- * emitting a xdg_surface.configure event. The client should then update
+ * emitting an xdg_surface.configure event. The client should then update
* its content, drawing it without decorations if the received mode is
* server-side decorations. The client must also acknowledge the configure
* when committing the new content (see xdg_surface.ack_configure).
@@ -341,7 +347,7 @@ zxdg_toplevel_decoration_v1_destroy(struct zxdg_toplevel_decoration_v1 *zxdg_top
* different mode instead.
*
* Clients whose decoration mode depend on the xdg_toplevel state may send
- * a set_mode request in response to a xdg_surface.configure event and wait
+ * a set_mode request in response to an xdg_surface.configure event and wait
* for the next xdg_surface.configure event to prevent unwanted state.
* Such clients are responsible for preventing configure loops and must
* make sure not to send multiple successive set_mode requests with the
diff --git a/vendor/gioui.org/app/internal/window/wayland_xdg_shell.c b/vendor/gioui.org/app/wayland_xdg_shell.c
index 1947847..54fe5cf 100644
--- a/vendor/gioui.org/app/internal/window/wayland_xdg_shell.c
+++ b/vendor/gioui.org/app/wayland_xdg_shell.c
@@ -1,6 +1,8 @@
-// +build linux,!android,!nowayland freebsd
+//go:build ((linux && !android) || freebsd) && !nowayland
+// +build linux,!android freebsd
+// +build !nowayland
-/* Generated by wayland-scanner 1.17.0 */
+/* Generated by wayland-scanner 1.19.0 */
/*
* Copyright © 2008-2013 Kristian Høgsberg
@@ -52,7 +54,7 @@ extern const struct wl_interface xdg_positioner_interface;
extern const struct wl_interface xdg_surface_interface;
extern const struct wl_interface xdg_toplevel_interface;
-static const struct wl_interface *types[] = {
+static const struct wl_interface *xdg_shell_types[] = {
NULL,
NULL,
NULL,
@@ -77,100 +79,107 @@ static const struct wl_interface *types[] = {
&wl_output_interface,
&wl_seat_interface,
NULL,
+ &xdg_positioner_interface,
+ NULL,
};
static const struct wl_message xdg_wm_base_requests[] = {
- { "destroy", "", types + 0 },
- { "create_positioner", "n", types + 4 },
- { "get_xdg_surface", "no", types + 5 },
- { "pong", "u", types + 0 },
+ { "destroy", "", xdg_shell_types + 0 },
+ { "create_positioner", "n", xdg_shell_types + 4 },
+ { "get_xdg_surface", "no", xdg_shell_types + 5 },
+ { "pong", "u", xdg_shell_types + 0 },
};
static const struct wl_message xdg_wm_base_events[] = {
- { "ping", "u", types + 0 },
+ { "ping", "u", xdg_shell_types + 0 },
};
WL_PRIVATE const struct wl_interface xdg_wm_base_interface = {
- "xdg_wm_base", 2,
+ "xdg_wm_base", 3,
4, xdg_wm_base_requests,
1, xdg_wm_base_events,
};
static const struct wl_message xdg_positioner_requests[] = {
- { "destroy", "", types + 0 },
- { "set_size", "ii", types + 0 },
- { "set_anchor_rect", "iiii", types + 0 },
- { "set_anchor", "u", types + 0 },
- { "set_gravity", "u", types + 0 },
- { "set_constraint_adjustment", "u", types + 0 },
- { "set_offset", "ii", types + 0 },
+ { "destroy", "", xdg_shell_types + 0 },
+ { "set_size", "ii", xdg_shell_types + 0 },
+ { "set_anchor_rect", "iiii", xdg_shell_types + 0 },
+ { "set_anchor", "u", xdg_shell_types + 0 },
+ { "set_gravity", "u", xdg_shell_types + 0 },
+ { "set_constraint_adjustment", "u", xdg_shell_types + 0 },
+ { "set_offset", "ii", xdg_shell_types + 0 },
+ { "set_reactive", "3", xdg_shell_types + 0 },
+ { "set_parent_size", "3ii", xdg_shell_types + 0 },
+ { "set_parent_configure", "3u", xdg_shell_types + 0 },
};
WL_PRIVATE const struct wl_interface xdg_positioner_interface = {
- "xdg_positioner", 2,
- 7, xdg_positioner_requests,
+ "xdg_positioner", 3,
+ 10, xdg_positioner_requests,
0, NULL,
};
static const struct wl_message xdg_surface_requests[] = {
- { "destroy", "", types + 0 },
- { "get_toplevel", "n", types + 7 },
- { "get_popup", "n?oo", types + 8 },
- { "set_window_geometry", "iiii", types + 0 },
- { "ack_configure", "u", types + 0 },
+ { "destroy", "", xdg_shell_types + 0 },
+ { "get_toplevel", "n", xdg_shell_types + 7 },
+ { "get_popup", "n?oo", xdg_shell_types + 8 },
+ { "set_window_geometry", "iiii", xdg_shell_types + 0 },
+ { "ack_configure", "u", xdg_shell_types + 0 },
};
static const struct wl_message xdg_surface_events[] = {
- { "configure", "u", types + 0 },
+ { "configure", "u", xdg_shell_types + 0 },
};
WL_PRIVATE const struct wl_interface xdg_surface_interface = {
- "xdg_surface", 2,
+ "xdg_surface", 3,
5, xdg_surface_requests,
1, xdg_surface_events,
};
static const struct wl_message xdg_toplevel_requests[] = {
- { "destroy", "", types + 0 },
- { "set_parent", "?o", types + 11 },
- { "set_title", "s", types + 0 },
- { "set_app_id", "s", types + 0 },
- { "show_window_menu", "ouii", types + 12 },
- { "move", "ou", types + 16 },
- { "resize", "ouu", types + 18 },
- { "set_max_size", "ii", types + 0 },
- { "set_min_size", "ii", types + 0 },
- { "set_maximized", "", types + 0 },
- { "unset_maximized", "", types + 0 },
- { "set_fullscreen", "?o", types + 21 },
- { "unset_fullscreen", "", types + 0 },
- { "set_minimized", "", types + 0 },
+ { "destroy", "", xdg_shell_types + 0 },
+ { "set_parent", "?o", xdg_shell_types + 11 },
+ { "set_title", "s", xdg_shell_types + 0 },
+ { "set_app_id", "s", xdg_shell_types + 0 },
+ { "show_window_menu", "ouii", xdg_shell_types + 12 },
+ { "move", "ou", xdg_shell_types + 16 },
+ { "resize", "ouu", xdg_shell_types + 18 },
+ { "set_max_size", "ii", xdg_shell_types + 0 },
+ { "set_min_size", "ii", xdg_shell_types + 0 },
+ { "set_maximized", "", xdg_shell_types + 0 },
+ { "unset_maximized", "", xdg_shell_types + 0 },
+ { "set_fullscreen", "?o", xdg_shell_types + 21 },
+ { "unset_fullscreen", "", xdg_shell_types + 0 },
+ { "set_minimized", "", xdg_shell_types + 0 },
};
static const struct wl_message xdg_toplevel_events[] = {
- { "configure", "iia", types + 0 },
- { "close", "", types + 0 },
+ { "configure", "iia", xdg_shell_types + 0 },
+ { "close", "", xdg_shell_types + 0 },
};
WL_PRIVATE const struct wl_interface xdg_toplevel_interface = {
- "xdg_toplevel", 2,
+ "xdg_toplevel", 3,
14, xdg_toplevel_requests,
2, xdg_toplevel_events,
};
static const struct wl_message xdg_popup_requests[] = {
- { "destroy", "", types + 0 },
- { "grab", "ou", types + 22 },
+ { "destroy", "", xdg_shell_types + 0 },
+ { "grab", "ou", xdg_shell_types + 22 },
+ { "reposition", "3ou", xdg_shell_types + 24 },
};
static const struct wl_message xdg_popup_events[] = {
- { "configure", "iiii", types + 0 },
- { "popup_done", "", types + 0 },
+ { "configure", "iiii", xdg_shell_types + 0 },
+ { "popup_done", "", xdg_shell_types + 0 },
+ { "repositioned", "3u", xdg_shell_types + 0 },
};
WL_PRIVATE const struct wl_interface xdg_popup_interface = {
- "xdg_popup", 2,
- 2, xdg_popup_requests,
- 2, xdg_popup_events,
+ "xdg_popup", 3,
+ 3, xdg_popup_requests,
+ 3, xdg_popup_events,
};
diff --git a/vendor/gioui.org/app/internal/window/wayland_xdg_shell.h b/vendor/gioui.org/app/wayland_xdg_shell.h
index 1f4bfb5..1db8fd9 100644
--- a/vendor/gioui.org/app/internal/window/wayland_xdg_shell.h
+++ b/vendor/gioui.org/app/wayland_xdg_shell.h
@@ -1,4 +1,4 @@
-/* Generated by wayland-scanner 1.17.0 */
+/* Generated by wayland-scanner 1.19.0 */
#ifndef XDG_SHELL_CLIENT_PROTOCOL_H
#define XDG_SHELL_CLIENT_PROTOCOL_H
@@ -58,6 +58,8 @@ struct xdg_surface;
struct xdg_toplevel;
struct xdg_wm_base;
+#ifndef XDG_WM_BASE_INTERFACE
+#define XDG_WM_BASE_INTERFACE
/**
* @page page_iface_xdg_wm_base xdg_wm_base
* @section page_iface_xdg_wm_base_desc Description
@@ -80,6 +82,9 @@ struct xdg_wm_base;
* creating transient windows such as popup menus.
*/
extern const struct wl_interface xdg_wm_base_interface;
+#endif
+#ifndef XDG_POSITIONER_INTERFACE
+#define XDG_POSITIONER_INTERFACE
/**
* @page page_iface_xdg_positioner xdg_positioner
* @section page_iface_xdg_positioner_desc Description
@@ -130,6 +135,9 @@ extern const struct wl_interface xdg_wm_base_interface;
* positioning a surface raises an error.
*/
extern const struct wl_interface xdg_positioner_interface;
+#endif
+#ifndef XDG_SURFACE_INTERFACE
+#define XDG_SURFACE_INTERFACE
/**
* @page page_iface_xdg_surface xdg_surface
* @section page_iface_xdg_surface_desc Description
@@ -159,6 +167,11 @@ extern const struct wl_interface xdg_positioner_interface;
* manipulate a buffer prior to the first xdg_surface.configure call must
* also be treated as errors.
*
+ * After creating a role-specific object and setting it up, the client must
+ * perform an initial commit without any buffer attached. The compositor
+ * will reply with an xdg_surface.configure event. The client must
+ * acknowledge it and is then allowed to attach a buffer to map the surface.
+ *
* Mapping an xdg_surface-based role surface is defined as making it
* possible for the surface to be shown by the compositor. Note that
* a mapped surface is not guaranteed to be visible once it is mapped.
@@ -204,6 +217,11 @@ extern const struct wl_interface xdg_positioner_interface;
* manipulate a buffer prior to the first xdg_surface.configure call must
* also be treated as errors.
*
+ * After creating a role-specific object and setting it up, the client must
+ * perform an initial commit without any buffer attached. The compositor
+ * will reply with an xdg_surface.configure event. The client must
+ * acknowledge it and is then allowed to attach a buffer to map the surface.
+ *
* Mapping an xdg_surface-based role surface is defined as making it
* possible for the surface to be shown by the compositor. Note that
* a mapped surface is not guaranteed to be visible once it is mapped.
@@ -220,6 +238,9 @@ extern const struct wl_interface xdg_positioner_interface;
* has not been destroyed.
*/
extern const struct wl_interface xdg_surface_interface;
+#endif
+#ifndef XDG_TOPLEVEL_INTERFACE
+#define XDG_TOPLEVEL_INTERFACE
/**
* @page page_iface_xdg_toplevel xdg_toplevel
* @section page_iface_xdg_toplevel_desc Description
@@ -234,7 +255,11 @@ extern const struct wl_interface xdg_surface_interface;
* by the compositor until it is explicitly mapped again.
* All active operations (e.g., move, resize) are canceled and all
* attributes (e.g. title, state, stacking, ...) are discarded for
- * an xdg_toplevel surface when it is unmapped.
+ * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
+ * the state it had right after xdg_surface.get_toplevel. The client
+ * can re-map the toplevel by perfoming a commit without any buffer
+ * attached, waiting for a configure event and handling it as usual (see
+ * xdg_surface description).
*
* Attaching a null buffer to a toplevel unmaps the surface.
* @section page_iface_xdg_toplevel_api API
@@ -253,11 +278,18 @@ extern const struct wl_interface xdg_surface_interface;
* by the compositor until it is explicitly mapped again.
* All active operations (e.g., move, resize) are canceled and all
* attributes (e.g. title, state, stacking, ...) are discarded for
- * an xdg_toplevel surface when it is unmapped.
+ * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
+ * the state it had right after xdg_surface.get_toplevel. The client
+ * can re-map the toplevel by perfoming a commit without any buffer
+ * attached, waiting for a configure event and handling it as usual (see
+ * xdg_surface description).
*
* Attaching a null buffer to a toplevel unmaps the surface.
*/
extern const struct wl_interface xdg_toplevel_interface;
+#endif
+#ifndef XDG_POPUP_INTERFACE
+#define XDG_POPUP_INTERFACE
/**
* @page page_iface_xdg_popup xdg_popup
* @section page_iface_xdg_popup_desc Description
@@ -284,12 +316,6 @@ extern const struct wl_interface xdg_toplevel_interface;
* The parent of an xdg_popup must be mapped (see the xdg_surface
* description) before the xdg_popup itself.
*
- * The x and y arguments passed when creating the popup object specify
- * where the top left of the popup should be placed, relative to the
- * local surface coordinates of the parent surface. See
- * xdg_surface.get_popup. An xdg_popup must intersect with or be at least
- * partially adjacent to its parent surface.
- *
* The client must call wl_surface.commit on the corresponding wl_surface
* for the xdg_popup state to take effect.
* @section page_iface_xdg_popup_api API
@@ -320,16 +346,11 @@ extern const struct wl_interface xdg_toplevel_interface;
* The parent of an xdg_popup must be mapped (see the xdg_surface
* description) before the xdg_popup itself.
*
- * The x and y arguments passed when creating the popup object specify
- * where the top left of the popup should be placed, relative to the
- * local surface coordinates of the parent surface. See
- * xdg_surface.get_popup. An xdg_popup must intersect with or be at least
- * partially adjacent to its parent surface.
- *
* The client must call wl_surface.commit on the corresponding wl_surface
* for the xdg_popup state to take effect.
*/
extern const struct wl_interface xdg_popup_interface;
+#endif
#ifndef XDG_WM_BASE_ERROR_ENUM
#define XDG_WM_BASE_ERROR_ENUM
@@ -587,6 +608,9 @@ enum xdg_positioner_constraint_adjustment {
#define XDG_POSITIONER_SET_GRAVITY 4
#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT 5
#define XDG_POSITIONER_SET_OFFSET 6
+#define XDG_POSITIONER_SET_REACTIVE 7
+#define XDG_POSITIONER_SET_PARENT_SIZE 8
+#define XDG_POSITIONER_SET_PARENT_CONFIGURE 9
/**
@@ -617,6 +641,18 @@ enum xdg_positioner_constraint_adjustment {
* @ingroup iface_xdg_positioner
*/
#define XDG_POSITIONER_SET_OFFSET_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION 3
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_PARENT_SIZE_SINCE_VERSION 3
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION 3
/** @ingroup iface_xdg_positioner */
static inline void
@@ -769,6 +805,56 @@ xdg_positioner_set_offset(struct xdg_positioner *xdg_positioner, int32_t x, int3
XDG_POSITIONER_SET_OFFSET, x, y);
}
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * When set reactive, the surface is reconstrained if the conditions used
+ * for constraining changed, e.g. the parent window moved.
+ *
+ * If the conditions changed and the popup was reconstrained, an
+ * xdg_popup.configure event is sent with updated geometry, followed by an
+ * xdg_surface.configure event.
+ */
+static inline void
+xdg_positioner_set_reactive(struct xdg_positioner *xdg_positioner)
+{
+ wl_proxy_marshal((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_REACTIVE);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Set the parent window geometry the compositor should use when
+ * positioning the popup. The compositor may use this information to
+ * determine the future state the popup should be constrained using. If
+ * this doesn't match the dimension of the parent the popup is eventually
+ * positioned against, the behavior is undefined.
+ *
+ * The arguments are given in the surface-local coordinate space.
+ */
+static inline void
+xdg_positioner_set_parent_size(struct xdg_positioner *xdg_positioner, int32_t parent_width, int32_t parent_height)
+{
+ wl_proxy_marshal((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_PARENT_SIZE, parent_width, parent_height);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Set the serial of an xdg_surface.configure event this positioner will be
+ * used in response to. The compositor may use this information together
+ * with set_parent_size to determine what future state the popup should be
+ * constrained using.
+ */
+static inline void
+xdg_positioner_set_parent_configure(struct xdg_positioner *xdg_positioner, uint32_t serial)
+{
+ wl_proxy_marshal((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_PARENT_CONFIGURE, serial);
+}
+
#ifndef XDG_SURFACE_ERROR_ENUM
#define XDG_SURFACE_ERROR_ENUM
enum xdg_surface_error {
@@ -1691,6 +1777,12 @@ struct xdg_popup_listener {
* The x and y arguments represent the position the popup was
* placed at given the xdg_positioner rule, relative to the upper
* left corner of the window geometry of the parent surface.
+ *
+ * For version 2 or older, the configure event for an xdg_popup is
+ * only ever sent once for the initial configuration. Starting with
+ * version 3, it may be sent again if the popup is setup with an
+ * xdg_positioner with set_reactive requested, or in response to
+ * xdg_popup.reposition requests.
* @param x x position relative to parent surface window geometry
* @param y y position relative to parent surface window geometry
* @param width window geometry width
@@ -1711,6 +1803,32 @@ struct xdg_popup_listener {
*/
void (*popup_done)(void *data,
struct xdg_popup *xdg_popup);
+ /**
+ * signal the completion of a repositioned request
+ *
+ * The repositioned event is sent as part of a popup
+ * configuration sequence, together with xdg_popup.configure and
+ * lastly xdg_surface.configure to notify the completion of a
+ * reposition request.
+ *
+ * The repositioned event is to notify about the completion of a
+ * xdg_popup.reposition request. The token argument is the token
+ * passed in the xdg_popup.reposition request.
+ *
+ * Immediately after this event is emitted, xdg_popup.configure and
+ * xdg_surface.configure will be sent with the updated size and
+ * position, as well as a new configure serial.
+ *
+ * The client should optionally update the content of the popup,
+ * but must acknowledge the new popup configuration for the new
+ * position to take effect. See xdg_surface.ack_configure for
+ * details.
+ * @param token reposition request token
+ * @since 3
+ */
+ void (*repositioned)(void *data,
+ struct xdg_popup *xdg_popup,
+ uint32_t token);
};
/**
@@ -1726,6 +1844,7 @@ xdg_popup_add_listener(struct xdg_popup *xdg_popup,
#define XDG_POPUP_DESTROY 0
#define XDG_POPUP_GRAB 1
+#define XDG_POPUP_REPOSITION 2
/**
* @ingroup iface_xdg_popup
@@ -1735,6 +1854,10 @@ xdg_popup_add_listener(struct xdg_popup *xdg_popup,
* @ingroup iface_xdg_popup
*/
#define XDG_POPUP_POPUP_DONE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_REPOSITIONED_SINCE_VERSION 3
/**
* @ingroup iface_xdg_popup
@@ -1744,6 +1867,10 @@ xdg_popup_add_listener(struct xdg_popup *xdg_popup,
* @ingroup iface_xdg_popup
*/
#define XDG_POPUP_GRAB_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_REPOSITION_SINCE_VERSION 3
/** @ingroup iface_xdg_popup */
static inline void
@@ -1835,6 +1962,40 @@ xdg_popup_grab(struct xdg_popup *xdg_popup, struct wl_seat *seat, uint32_t seria
XDG_POPUP_GRAB, seat, serial);
}
+/**
+ * @ingroup iface_xdg_popup
+ *
+ * Reposition an already-mapped popup. The popup will be placed given the
+ * details in the passed xdg_positioner object, and a
+ * xdg_popup.repositioned followed by xdg_popup.configure and
+ * xdg_surface.configure will be emitted in response. Any parameters set
+ * by the previous positioner will be discarded.
+ *
+ * The passed token will be sent in the corresponding
+ * xdg_popup.repositioned event. The new popup position will not take
+ * effect until the corresponding configure event is acknowledged by the
+ * client. See xdg_popup.repositioned for details. The token itself is
+ * opaque, and has no other special meaning.
+ *
+ * If multiple reposition requests are sent, the compositor may skip all
+ * but the last one.
+ *
+ * If the popup is repositioned in response to a configure event for its
+ * parent, the client should send an xdg_positioner.set_parent_configure
+ * and possibly an xdg_positioner.set_parent_size request to allow the
+ * compositor to properly constrain the popup.
+ *
+ * If the popup is repositioned together with a parent that is being
+ * resized, but not in response to a configure event, the client should
+ * send an xdg_positioner.set_parent_size request.
+ */
+static inline void
+xdg_popup_reposition(struct xdg_popup *xdg_popup, struct xdg_positioner *positioner, uint32_t token)
+{
+ wl_proxy_marshal((struct wl_proxy *) xdg_popup,
+ XDG_POPUP_REPOSITION, positioner, token);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/vendor/gioui.org/app/window.go b/vendor/gioui.org/app/window.go
index 2c9860c..ada92fb 100644
--- a/vendor/gioui.org/app/window.go
+++ b/vendor/gioui.org/app/window.go
@@ -6,10 +6,14 @@ import (
"errors"
"fmt"
"image"
+ "image/color"
+ "runtime"
"time"
- "gioui.org/app/internal/window"
+ "gioui.org/f32"
+ "gioui.org/gpu"
"gioui.org/io/event"
+ "gioui.org/io/pointer"
"gioui.org/io/profile"
"gioui.org/io/router"
"gioui.org/io/system"
@@ -19,24 +23,32 @@ import (
_ "gioui.org/app/internal/log"
)
-// WindowOption configures a Window.
-type Option func(opts *window.Options)
+// Option configures a window.
+type Option func(unit.Metric, *Config)
// Window represents an operating system window.
type Window struct {
- driver window.Driver
- loop *renderLoop
+ ctx context
+ gpu gpu.GPU
// driverFuncs is a channel of functions to run when
// the Window has a valid driver.
- driverFuncs chan func()
-
- out chan event.Event
- in chan event.Event
- ack chan struct{}
- invalidates chan struct{}
- frames chan *op.Ops
- frameAck chan struct{}
+ driverFuncs chan func(d driver)
+ // wakeups wakes up the native event loop to send a
+ // WakeupEvent that flushes driverFuncs.
+ wakeups chan struct{}
+ // wakeupFuncs is sent wakeup functions when the driver changes.
+ wakeupFuncs chan func()
+ // redraws is notified when a redraw is requested by the client.
+ redraws chan struct{}
+ // immediateRedraws is like redraw but doesn't need a wakeup.
+ immediateRedraws chan struct{}
+ // scheduledRedraws is sent the most recent delayed redraw time.
+ scheduledRedraws chan time.Time
+
+ out chan event.Event
+ frames chan *op.Ops
+ frameAck chan struct{}
// dead is closed when the window is destroyed.
dead chan struct{}
@@ -46,13 +58,33 @@ type Window struct {
nextFrame time.Time
delayedDraw *time.Timer
- queue queue
+ queue queue
+ cursor pointer.CursorName
callbacks callbacks
+
+ nocontext bool
+
+ // semantic data, lazily evaluated if requested by a backend to speed up
+ // the cases where semantic data is not needed.
+ semantic struct {
+ // uptodate tracks whether the fields below are up to date.
+ uptodate bool
+ root router.SemanticID
+ prevTree []router.SemanticNode
+ tree []router.SemanticNode
+ ids map[router.SemanticID]router.SemanticNode
+ }
+}
+
+type semanticResult struct {
+ found bool
+ node router.SemanticNode
}
type callbacks struct {
w *Window
+ d driver
}
// queue is an event.Queue implementation that distributes system events
@@ -61,12 +93,6 @@ type queue struct {
q router.Router
}
-// driverEvent is sent when a new native driver
-// is available for the Window.
-type driverEvent struct {
- driver window.Driver
-}
-
// Pre-allocate the ack event to avoid garbage.
var ackEvent event.Event
@@ -74,35 +100,37 @@ var ackEvent event.Event
// options. The options are hints; the platform is free to
// ignore or adjust them.
//
-// If the current program is running on iOS and Android,
+// If the current program is running on iOS or Android,
// NewWindow returns the window previously created by the
// platform.
//
// Calling NewWindow more than once is not supported on
// iOS, Android, WebAssembly.
func NewWindow(options ...Option) *Window {
- opts := &window.Options{
- Width: unit.Dp(800),
- Height: unit.Dp(600),
- Title: "Gio",
- }
-
- for _, o := range options {
- o(opts)
+ defaultOptions := []Option{
+ Size(unit.Dp(800), unit.Dp(600)),
+ Title("Gio"),
}
+ options = append(defaultOptions, options...)
+ var cnf Config
+ cnf.apply(unit.Metric{}, options)
w := &Window{
- in: make(chan event.Event),
- out: make(chan event.Event),
- ack: make(chan struct{}),
- invalidates: make(chan struct{}, 1),
- frames: make(chan *op.Ops),
- frameAck: make(chan struct{}),
- driverFuncs: make(chan func()),
- dead: make(chan struct{}),
+ out: make(chan event.Event),
+ immediateRedraws: make(chan struct{}, 0),
+ redraws: make(chan struct{}, 1),
+ scheduledRedraws: make(chan time.Time, 1),
+ frames: make(chan *op.Ops),
+ frameAck: make(chan struct{}),
+ driverFuncs: make(chan func(d driver), 1),
+ wakeups: make(chan struct{}, 1),
+ wakeupFuncs: make(chan func()),
+ dead: make(chan struct{}),
+ nocontext: cnf.CustomRenderer,
}
+ w.semantic.ids = make(map[router.SemanticID]router.SemanticNode)
w.callbacks.w = w
- go w.run(opts)
+ go w.run(options)
return w
}
@@ -111,141 +139,260 @@ func (w *Window) Events() <-chan event.Event {
return w.out
}
-// update updates the Window. Paint operations updates the
-// window contents, input operations declare input handlers,
-// and so on. The supplied operations list completely replaces
-// the window state from previous calls.
+// update updates the window contents, input operations declare input handlers,
+// and so on. The supplied operations list completely replaces the window state
+// from previous calls.
func (w *Window) update(frame *op.Ops) {
w.frames <- frame
<-w.frameAck
}
-func (w *Window) validateAndProcess(frameStart time.Time, size image.Point, sync bool, frame *op.Ops) error {
+func (w *Window) validateAndProcess(d driver, frameStart time.Time, size image.Point, sync bool, frame *op.Ops) error {
for {
- if w.loop != nil {
- if err := w.loop.Flush(); err != nil {
+ if w.gpu == nil && !w.nocontext {
+ var err error
+ if w.ctx == nil {
+ w.ctx, err = d.NewContext()
+ if err != nil {
+ return err
+ }
+ sync = true
+ }
+ }
+ if sync && w.ctx != nil {
+ if err := w.ctx.Refresh(); err != nil {
+ if errors.Is(err, errOutOfDate) {
+ // Surface couldn't be created for transient reasons. Skip
+ // this frame and wait for the next.
+ return nil
+ }
w.destroyGPU()
- if err == window.ErrDeviceLost {
+ if errors.Is(err, gpu.ErrDeviceLost) {
continue
}
return err
}
}
- if w.loop == nil {
- var ctx window.Context
- ctx, err := w.driver.NewContext()
- if err != nil {
+ if w.gpu == nil && !w.nocontext {
+ if err := w.ctx.Lock(); err != nil {
+ w.destroyGPU()
return err
}
- w.loop, err = newLoop(ctx)
+ gpu, err := gpu.New(w.ctx.API())
+ w.ctx.Unlock()
if err != nil {
- ctx.Release()
+ w.destroyGPU()
return err
}
+ w.gpu = gpu
}
- w.processFrame(frameStart, size, frame)
- if sync {
- if err := w.loop.Flush(); err != nil {
+ if w.gpu != nil {
+ if err := w.render(frame, size); err != nil {
+ if errors.Is(err, errOutOfDate) {
+ // GPU surface needs refreshing.
+ sync = true
+ continue
+ }
w.destroyGPU()
- if err == window.ErrDeviceLost {
+ if errors.Is(err, gpu.ErrDeviceLost) {
continue
}
return err
}
}
+ w.processFrame(d, frameStart, frame)
return nil
}
}
-func (w *Window) processFrame(frameStart time.Time, size image.Point, frame *op.Ops) {
- sync := w.loop.Draw(size, frame)
+func (w *Window) render(frame *op.Ops, viewport image.Point) error {
+ if err := w.ctx.Lock(); err != nil {
+ return err
+ }
+ defer w.ctx.Unlock()
+ if runtime.GOOS == "js" {
+ // Use transparent black when Gio is embedded, to allow mixing of Gio and
+ // foreign content below.
+ w.gpu.Clear(color.NRGBA{A: 0x00, R: 0x00, G: 0x00, B: 0x00})
+ } else {
+ w.gpu.Clear(color.NRGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff})
+ }
+ target, err := w.ctx.RenderTarget()
+ if err != nil {
+ return err
+ }
+ if err := w.gpu.Frame(frame, target, viewport); err != nil {
+ return err
+ }
+ return w.ctx.Present()
+}
+
+func (w *Window) processFrame(d driver, frameStart time.Time, frame *op.Ops) {
w.queue.q.Frame(frame)
+ for k := range w.semantic.ids {
+ delete(w.semantic.ids, k)
+ }
+ w.semantic.uptodate = false
switch w.queue.q.TextInputState() {
case router.TextInputOpen:
- w.driver.ShowTextInput(true)
+ d.ShowTextInput(true)
case router.TextInputClose:
- w.driver.ShowTextInput(false)
+ d.ShowTextInput(false)
+ }
+ if hint, ok := w.queue.q.TextInputHint(); ok {
+ d.SetInputHint(hint)
+ }
+ if txt, ok := w.queue.q.WriteClipboard(); ok {
+ w.WriteClipboard(txt)
+ }
+ if w.queue.q.ReadClipboard() {
+ w.ReadClipboard()
}
- if w.queue.q.Profiling() {
+ if w.queue.q.Profiling() && w.gpu != nil {
frameDur := time.Since(frameStart)
frameDur = frameDur.Truncate(100 * time.Microsecond)
q := 100 * time.Microsecond
- timings := fmt.Sprintf("tot:%7s %s", frameDur.Round(q), w.loop.Summary())
- w.queue.q.Add(profile.Event{Timings: timings})
+ timings := fmt.Sprintf("tot:%7s %s", frameDur.Round(q), w.gpu.Profile())
+ w.queue.q.Queue(profile.Event{Timings: timings})
}
if t, ok := w.queue.q.WakeupTime(); ok {
w.setNextFrame(t)
}
- w.updateAnimation()
- // Wait for the GPU goroutine to finish processing frame.
- <-sync
+ w.updateAnimation(d)
}
-// Invalidate the window such that a FrameEvent will be generated
-// immediately. If the window is inactive, the event is sent when the
-// window becomes active.
+// Invalidate the window such that a FrameEvent will be generated immediately.
+// If the window is inactive, the event is sent when the window becomes active.
+//
+// Note that Invalidate is intended for externally triggered updates, such as a
+// response from a network request. InvalidateOp is more efficient for animation
+// and similar internal updates.
+//
// Invalidate is safe for concurrent use.
func (w *Window) Invalidate() {
select {
- case w.invalidates <- struct{}{}:
+ case w.immediateRedraws <- struct{}{}:
+ return
default:
}
+ select {
+ case w.redraws <- struct{}{}:
+ w.wakeup()
+ default:
+ }
+}
+
+// Option applies the options to the window.
+func (w *Window) Option(opts ...Option) {
+ w.driverDefer(func(d driver) {
+ d.Configure(opts)
+ })
}
// ReadClipboard initiates a read of the clipboard in the form
-// of a system.ClipboardEvent. Multiple reads may be coalescedd
+// of a clipboard.Event. Multiple reads may be coalesced
// to a single event.
func (w *Window) ReadClipboard() {
- w.driverDo(func() {
- w.driver.ReadClipboard()
+ w.driverDefer(func(d driver) {
+ d.ReadClipboard()
})
}
// WriteClipboard writes a string to the clipboard.
func (w *Window) WriteClipboard(s string) {
- w.driverDo(func() {
- w.driver.WriteClipboard(s)
+ w.driverDefer(func(d driver) {
+ d.WriteClipboard(s)
+ })
+}
+
+// SetCursorName changes the current window cursor to name.
+func (w *Window) SetCursorName(name pointer.CursorName) {
+ w.driverDefer(func(d driver) {
+ d.SetCursor(name)
})
}
// Close the window. The window's event loop should exit when it receives
// system.DestroyEvent.
//
-// Currently, only macOS, Windows and X11 drivers implement this functionality,
+// Currently, only macOS, Windows, X11 and Wayland drivers implement this functionality,
// all others are stubbed.
func (w *Window) Close() {
- w.driverDo(func() {
- w.driver.Close()
+ w.driverDefer(func(d driver) {
+ d.Close()
})
}
-// driverDo calls f as soon as the window has a valid driver attached,
-// or does nothing if the window is destroyed while waiting.
-func (w *Window) driverDo(f func()) {
- go func() {
- select {
- case w.driverFuncs <- f:
- case <-w.dead:
- }
- }()
+// Maximize the window.
+// Note: only implemented on Windows, macOS and X11.
+func (w *Window) Maximize() {
+ w.driverDefer(func(d driver) {
+ d.Maximize()
+ })
}
-func (w *Window) updateAnimation() {
- animate := false
- if w.delayedDraw != nil {
- w.delayedDraw.Stop()
- w.delayedDraw = nil
+// Center the window.
+// Note: only implemented on Windows, macOS and X11.
+func (w *Window) Center() {
+ w.driverDefer(func(d driver) {
+ d.Center()
+ })
+}
+
+// Run f in the same thread as the native window event loop, and wait for f to
+// return or the window to close. Run is guaranteed not to deadlock if it is
+// invoked during the handling of a ViewEvent, system.FrameEvent,
+// system.StageEvent; call Run in a separate goroutine to avoid deadlock in all
+// other cases.
+//
+// Note that most programs should not call Run; configuring a Window with
+// CustomRenderer is a notable exception.
+func (w *Window) Run(f func()) {
+ done := make(chan struct{})
+ w.driverDefer(func(d driver) {
+ defer close(done)
+ f()
+ })
+ select {
+ case <-done:
+ case <-w.dead:
}
+}
+
+// driverDefer is like Run but can be run from any context. It doesn't wait
+// for f to return.
+func (w *Window) driverDefer(f func(d driver)) {
+ select {
+ case w.driverFuncs <- f:
+ w.wakeup()
+ case <-w.dead:
+ }
+}
+
+func (w *Window) updateAnimation(d driver) {
+ animate := false
if w.stage >= system.StageRunning && w.hasNextFrame {
if dt := time.Until(w.nextFrame); dt <= 0 {
animate = true
} else {
- w.delayedDraw = time.NewTimer(dt)
+ // Schedule redraw.
+ select {
+ case <-w.scheduledRedraws:
+ default:
+ }
+ w.scheduledRedraws <- w.nextFrame
}
}
if animate != w.animating {
w.animating = animate
- w.driver.SetAnimating(animate)
+ d.SetAnimating(animate)
+ }
+}
+
+func (w *Window) wakeup() {
+ select {
+ case w.wakeups <- struct{}{}:
+ default:
}
}
@@ -256,164 +403,289 @@ func (w *Window) setNextFrame(at time.Time) {
}
}
-func (c *callbacks) SetDriver(d window.Driver) {
- c.Event(driverEvent{d})
+func (c *callbacks) SetDriver(d driver) {
+ c.d = d
+ var wakeup func()
+ if d != nil {
+ wakeup = d.Wakeup
+ }
+ c.w.wakeupFuncs <- wakeup
}
func (c *callbacks) Event(e event.Event) {
- select {
- case c.w.in <- e:
- <-c.w.ack
- case <-c.w.dead:
+ if c.d == nil {
+ panic("event while no driver active")
}
+ c.w.processEvent(c.d, e)
+ c.w.updateState(c.d)
+}
+
+// SemanticRoot returns the ID of the semantic root.
+func (c *callbacks) SemanticRoot() router.SemanticID {
+ c.w.updateSemantics()
+ return c.w.semantic.root
}
-func (w *Window) waitAck() {
- // Send a dummy event; when it gets through we
- // know the application has processed the previous event.
- w.out <- ackEvent
+// LookupSemantic looks up a semantic node from an ID. The zero ID denotes the root.
+func (c *callbacks) LookupSemantic(semID router.SemanticID) (router.SemanticNode, bool) {
+ c.w.updateSemantics()
+ n, found := c.w.semantic.ids[semID]
+ return n, found
}
-// Prematurely destroy the window and wait for the native window
-// destroy event.
-func (w *Window) destroy(err error) {
- w.destroyGPU()
- // Ack the current event.
- w.ack <- struct{}{}
- w.out <- system.DestroyEvent{Err: err}
- close(w.dead)
- for e := range w.in {
- w.ack <- struct{}{}
- if _, ok := e.(system.DestroyEvent); ok {
+func (c *callbacks) AppendSemanticDiffs(diffs []router.SemanticID) []router.SemanticID {
+ c.w.updateSemantics()
+ if tree := c.w.semantic.prevTree; len(tree) > 0 {
+ c.w.collectSemanticDiffs(&diffs, c.w.semantic.prevTree[0])
+ }
+ return diffs
+}
+
+func (c *callbacks) SemanticAt(pos f32.Point) (router.SemanticID, bool) {
+ c.w.updateSemantics()
+ return c.w.queue.q.SemanticAt(pos)
+}
+
+func (w *Window) waitAck(d driver) {
+ for {
+ select {
+ case f := <-w.driverFuncs:
+ f(d)
+ case w.out <- ackEvent:
+ // A dummy event went through, so we know the application has processed the previous event.
return
+ case <-w.immediateRedraws:
+ // Invalidate was called during frame processing.
+ w.setNextFrame(time.Time{})
}
}
}
func (w *Window) destroyGPU() {
- if w.loop != nil {
- w.loop.Release()
- w.loop = nil
+ if w.gpu != nil {
+ w.ctx.Lock()
+ w.gpu.Release()
+ w.ctx.Unlock()
+ w.gpu = nil
+ }
+ if w.ctx != nil {
+ w.ctx.Release()
+ w.ctx = nil
}
}
// waitFrame waits for the client to either call FrameEvent.Frame
// or to continue event handling. It returns whether the client
// called Frame or not.
-func (w *Window) waitFrame() (*op.Ops, bool) {
+func (w *Window) waitFrame(d driver) (*op.Ops, bool) {
+ for {
+ select {
+ case f := <-w.driverFuncs:
+ f(d)
+ case frame := <-w.frames:
+ // The client called FrameEvent.Frame.
+ return frame, true
+ case w.out <- ackEvent:
+ // The client ignored FrameEvent and continued processing
+ // events.
+ return nil, false
+ case <-w.immediateRedraws:
+ // Invalidate was called during frame processing.
+ w.setNextFrame(time.Time{})
+ }
+ }
+}
+
+// updateSemantics refreshes the semantics tree, the id to node map and the ids of
+// updated nodes.
+func (w *Window) updateSemantics() {
+ if w.semantic.uptodate {
+ return
+ }
+ w.semantic.uptodate = true
+ w.semantic.prevTree, w.semantic.tree = w.semantic.tree, w.semantic.prevTree
+ w.semantic.tree = w.queue.q.AppendSemantics(w.semantic.tree[:0])
+ w.semantic.root = w.semantic.tree[0].ID
+ for _, n := range w.semantic.tree {
+ w.semantic.ids[n.ID] = n
+ }
+}
+
+// collectSemanticDiffs traverses the previous semantic tree, noting changed nodes.
+func (w *Window) collectSemanticDiffs(diffs *[]router.SemanticID, n router.SemanticNode) {
+ newNode, exists := w.semantic.ids[n.ID]
+ // Ignore deleted nodes, as their disappearance will be reported through an
+ // ancestor node.
+ if !exists {
+ return
+ }
+ diff := newNode.Desc != n.Desc || len(n.Children) != len(newNode.Children)
+ for i, ch := range n.Children {
+ if !diff {
+ newCh := newNode.Children[i]
+ diff = ch.ID != newCh.ID
+ }
+ w.collectSemanticDiffs(diffs, ch)
+ }
+ if diff {
+ *diffs = append(*diffs, n.ID)
+ }
+}
+
+func (w *Window) updateState(d driver) {
+ for {
+ select {
+ case f := <-w.driverFuncs:
+ f(d)
+ case <-w.redraws:
+ w.setNextFrame(time.Time{})
+ w.updateAnimation(d)
+ default:
+ return
+ }
+ }
+}
+
+func (w *Window) processEvent(d driver, e event.Event) {
select {
- case frame := <-w.frames:
- // The client called FrameEvent.Frame.
- return frame, true
- case w.out <- ackEvent:
- // The client ignored FrameEvent and continued processing
- // events.
- return nil, false
+ case <-w.dead:
+ return
+ default:
+ }
+ switch e2 := e.(type) {
+ case system.StageEvent:
+ if e2.Stage < system.StageRunning {
+ if w.gpu != nil {
+ w.ctx.Lock()
+ w.gpu.Release()
+ w.gpu = nil
+ w.ctx.Unlock()
+ }
+ }
+ w.stage = e2.Stage
+ w.updateAnimation(d)
+ w.out <- e
+ w.waitAck(d)
+ case frameEvent:
+ if e2.Size == (image.Point{}) {
+ panic(errors.New("internal error: zero-sized Draw"))
+ }
+ if w.stage < system.StageRunning {
+ // No drawing if not visible.
+ break
+ }
+ frameStart := time.Now()
+ w.hasNextFrame = false
+ e2.Frame = w.update
+ e2.Queue = &w.queue
+ w.out <- e2.FrameEvent
+ frame, gotFrame := w.waitFrame(d)
+ err := w.validateAndProcess(d, frameStart, e2.Size, e2.Sync, frame)
+ if gotFrame {
+ // We're done with frame, let the client continue.
+ w.frameAck <- struct{}{}
+ }
+ if err != nil {
+ w.destroyGPU()
+ w.out <- system.DestroyEvent{Err: err}
+ close(w.dead)
+ close(w.out)
+ break
+ }
+ w.updateCursor()
+ case *system.CommandEvent:
+ w.out <- e
+ w.waitAck(d)
+ case system.DestroyEvent:
+ w.destroyGPU()
+ w.out <- e2
+ close(w.dead)
+ close(w.out)
+ case ViewEvent:
+ w.out <- e2
+ w.waitAck(d)
+ case wakeupEvent:
+ case event.Event:
+ if w.queue.q.Queue(e2) {
+ w.setNextFrame(time.Time{})
+ w.updateAnimation(d)
+ }
+ w.updateCursor()
+ w.out <- e
}
}
-func (w *Window) run(opts *window.Options) {
- defer close(w.in)
- defer close(w.out)
- if err := window.NewWindow(&w.callbacks, opts); err != nil {
+func (w *Window) run(options []Option) {
+ if err := newWindow(&w.callbacks, options); err != nil {
w.out <- system.DestroyEvent{Err: err}
+ close(w.dead)
+ close(w.out)
return
}
+ var wakeup func()
+ var timer *time.Timer
for {
- var driverFuncs chan func()
- if w.driver != nil {
- driverFuncs = w.driverFuncs
- }
- var timer <-chan time.Time
- if w.delayedDraw != nil {
- timer = w.delayedDraw.C
+ var (
+ wakeups <-chan struct{}
+ timeC <-chan time.Time
+ )
+ if wakeup != nil {
+ wakeups = w.wakeups
+ if timer != nil {
+ timeC = timer.C
+ }
}
select {
- case <-timer:
- w.setNextFrame(time.Time{})
- w.updateAnimation()
- case <-w.invalidates:
- w.setNextFrame(time.Time{})
- w.updateAnimation()
- case f := <-driverFuncs:
- f()
- case e := <-w.in:
- switch e2 := e.(type) {
- case system.StageEvent:
- if w.loop != nil {
- if e2.Stage < system.StageRunning {
- w.destroyGPU()
- } else {
- w.loop.Refresh()
- }
- }
- w.stage = e2.Stage
- w.updateAnimation()
- w.out <- e
- w.waitAck()
- case window.FrameEvent:
- if e2.Size == (image.Point{}) {
- panic(errors.New("internal error: zero-sized Draw"))
- }
- if w.stage < system.StageRunning {
- // No drawing if not visible.
- break
- }
- frameStart := time.Now()
- w.hasNextFrame = false
- e2.Frame = w.update
- e2.Queue = &w.queue
- w.out <- e2.FrameEvent
- if w.loop != nil {
- if e2.Sync {
- w.loop.Refresh()
- }
- }
- frame, gotFrame := w.waitFrame()
- err := w.validateAndProcess(frameStart, e2.Size, e2.Sync, frame)
- if gotFrame {
- // We're done with frame, let the client continue.
- w.frameAck <- struct{}{}
- }
- if err != nil {
- w.destroyGPU()
- w.destroy(err)
- return
- }
- case *system.CommandEvent:
- w.out <- e
- w.waitAck()
- case driverEvent:
- w.driver = e2.driver
- case system.DestroyEvent:
- w.destroyGPU()
- w.out <- e2
- w.ack <- struct{}{}
- return
- case event.Event:
- if w.queue.q.Add(e2) {
- w.setNextFrame(time.Time{})
- w.updateAnimation()
- }
- w.out <- e
+ case t := <-w.scheduledRedraws:
+ if timer != nil {
+ timer.Stop()
}
- w.ack <- struct{}{}
+ timer = time.NewTimer(time.Until(t))
+ case <-w.dead:
+ return
+ case <-timeC:
+ select {
+ case w.redraws <- struct{}{}:
+ wakeup()
+ default:
+ }
+ case <-wakeups:
+ wakeup()
+ case wakeup = <-w.wakeupFuncs:
}
}
}
+func (w *Window) updateCursor() {
+ if c := w.queue.q.Cursor(); c != w.cursor {
+ w.cursor = c
+ w.SetCursorName(c)
+ }
+}
+
+// Raise requests that the platform bring this window to the top of all open windows.
+// Some platforms do not allow this except under certain circumstances, such as when
+// a window from the same application already has focus. If the platform does not
+// support it, this method will do nothing.
+func (w *Window) Raise() {
+ w.driverDefer(func(d driver) {
+ d.Raise()
+ })
+}
+
func (q *queue) Events(k event.Tag) []event.Event {
return q.q.Events(k)
}
// Title sets the title of the window.
func Title(t string) Option {
- return func(opts *window.Options) {
- opts.Title = t
+ return func(_ unit.Metric, cnf *Config) {
+ cnf.Title = t
}
}
-// Size sets the size of the window.
+// Size sets the size of the window. The option is ignored
+// in Fullscreen mode.
func Size(w, h unit.Value) Option {
if w.V <= 0 {
panic("width must be larger than or equal to 0")
@@ -421,9 +693,11 @@ func Size(w, h unit.Value) Option {
if h.V <= 0 {
panic("height must be larger than or equal to 0")
}
- return func(opts *window.Options) {
- opts.Width = w
- opts.Height = h
+ return func(m unit.Metric, cnf *Config) {
+ cnf.Size = image.Point{
+ X: m.Px(w),
+ Y: m.Px(h),
+ }
}
}
@@ -435,9 +709,11 @@ func MaxSize(w, h unit.Value) Option {
if h.V <= 0 {
panic("height must be larger than or equal to 0")
}
- return func(opts *window.Options) {
- opts.MaxWidth = w
- opts.MaxHeight = h
+ return func(m unit.Metric, cnf *Config) {
+ cnf.MaxSize = image.Point{
+ X: m.Px(w),
+ Y: m.Px(h),
+ }
}
}
@@ -449,10 +725,32 @@ func MinSize(w, h unit.Value) Option {
if h.V <= 0 {
panic("height must be larger than or equal to 0")
}
- return func(opts *window.Options) {
- opts.MinWidth = w
- opts.MinHeight = h
+ return func(m unit.Metric, cnf *Config) {
+ cnf.MinSize = image.Point{
+ X: m.Px(w),
+ Y: m.Px(h),
+ }
}
}
-func (driverEvent) ImplementsEvent() {}
+// StatusColor sets the color of the Android status bar.
+func StatusColor(color color.NRGBA) Option {
+ return func(_ unit.Metric, cnf *Config) {
+ cnf.StatusColor = color
+ }
+}
+
+// NavigationColor sets the color of the navigation bar on Android, or the address bar in browsers.
+func NavigationColor(color color.NRGBA) Option {
+ return func(_ unit.Metric, cnf *Config) {
+ cnf.NavigationColor = color
+ }
+}
+
+// CustomRenderer controls whether the window contents is
+// rendered by the client. If true, no GPU context is created.
+func CustomRenderer(custom bool) Option {
+ return func(_ unit.Metric, cnf *Config) {
+ cnf.CustomRenderer = custom
+ }
+}