~eliasnaur/gio-patches

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
8 3

[PATCH gio] app/internal/wm: use Option method to initialize windows

~pierrec
Details
Message ID
<161736927664.9206.5988759538078666758-0@git.sr.ht>
DKIM signature
missing
Download raw message
Patch: +207 -110
From: pierre <pierre.curto@gmail.com>

Added (*w.window).Option methods to the backends and use them for setting the initial options passed into NewWindow.

Signed-off-by: pierre <pierre.curto@gmail.com>
---
-

 app/internal/windows/windows.go | 17 ++++++-
 app/internal/wm/os_android.go   |  2 +
 app/internal/wm/os_ios.go       |  2 +
 app/internal/wm/os_js.go        | 10 ++--
 app/internal/wm/os_macos.go     | 90 ++++++++++++++++++++-------------
 app/internal/wm/os_macos.m      | 25 ++++++++-
 app/internal/wm/os_wayland.go   | 24 +++++----
 app/internal/wm/os_windows.go   | 66 +++++++++++++++---------
 app/internal/wm/os_x11.go       | 78 +++++++++++++++-------------
 app/internal/wm/window.go       |  3 ++
 10 files changed, 207 insertions(+), 110 deletions(-)

diff --git a/app/internal/windows/windows.go b/app/internal/windows/windows.go
index 1601172e..8af575e7 100644
--- a/app/internal/windows/windows.go
+++ b/app/internal/windows/windows.go
@@ -271,6 +271,7 @@ var (
	_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")
@@ -289,8 +290,9 @@ var (
	_SetProcessDPIAware          = user32.NewProc("SetProcessDPIAware")
	_SetTimer                    = user32.NewProc("SetTimer")
	_SetWindowLong               = user32.NewProc("SetWindowLongPtrW")
	_SetWindowPos                = user32.NewProc("SetWindowPos")
	_SetWindowPlacement          = user32.NewProc("SetWindowPlacement")
	_SetWindowPos                = user32.NewProc("SetWindowPos")
	_SetWindowText               = user32.NewProc("SetWindowTextW")
	_TranslateMessage            = user32.NewProc("TranslateMessage")
	_UnregisterClass             = user32.NewProc("UnregisterClassW")
	_UpdateWindow                = user32.NewProc("UpdateWindow")
@@ -486,6 +488,11 @@ func SetWindowPos(hwnd syscall.Handle, hwndInsertAfter uint32, x, y, dx, dy int3
	)
}

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 {
@@ -534,6 +541,14 @@ func LoadImage(hInst syscall.Handle, res uint32, typ uint32, cx, cy int, fuload
	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)
diff --git a/app/internal/wm/os_android.go b/app/internal/wm/os_android.go
index 3b463cdf..287ef5bf 100644
--- a/app/internal/wm/os_android.go
+++ b/app/internal/wm/os_android.go
@@ -676,6 +676,8 @@ func (w *window) ReadClipboard() {
	})
}

func (w *window) Option(opts *Options) {}

func (w *window) SetCursor(name pointer.CursorName) {
	w.setState(func(state *windowState) {
		state.cursor = &name
diff --git a/app/internal/wm/os_ios.go b/app/internal/wm/os_ios.go
index a5d023a5..1730af2c 100644
--- a/app/internal/wm/os_ios.go
+++ b/app/internal/wm/os_ios.go
@@ -239,6 +239,8 @@ func (w *window) WriteClipboard(s string) {
	})
}

func (w *window) Option(opts *Options) {}

func (w *window) SetAnimating(anim bool) {
	v := w.view
	if v == 0 {
diff --git a/app/internal/wm/os_js.go b/app/internal/wm/os_js.go
index 7eb627b9..b24419a7 100644
--- a/app/internal/wm/os_js.go
+++ b/app/internal/wm/os_js.go
@@ -82,9 +82,7 @@ func NewWindow(win Callbacks, opts *Options) error {
	})
	w.addEventListeners()
	w.addHistory()
	if o := opts.WindowMode; o != nil {
		w.windowMode(*o)
	}
	w.Option(opts)
	w.w = win

	go func() {
@@ -476,6 +474,12 @@ func (w *window) WriteClipboard(s string) {
	w.clipboard.Call("writeText", s)
}

func (w *window) Option(opts *Options) {
	if o := opts.WindowMode; o != nil {
		w.windowMode(*o)
	}
}

func (w *window) SetCursor(name pointer.CursorName) {
	style := w.cnv.Get("style")
	style.Set("cursor", string(name))
diff --git a/app/internal/wm/os_macos.go b/app/internal/wm/os_macos.go
index b82c8d0f..d088a924 100644
--- a/app/internal/wm/os_macos.go
+++ b/app/internal/wm/os_macos.go
@@ -46,6 +46,10 @@ __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef vie
__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);
__attribute__ ((visibility ("hidden"))) void gio_setSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
__attribute__ ((visibility ("hidden"))) void gio_setMinSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
__attribute__ ((visibility ("hidden"))) void gio_setMaxSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
__attribute__ ((visibility ("hidden"))) void gio_setTitle(CFTypeRef windowRef, const char *title);
*/
import "C"

@@ -126,6 +130,45 @@ func (w *window) WriteClipboard(s string) {
	})
}

func (w *window) Option(opts *Options) {
	w.runOnMain(func() {
		screenScale := float32(C.gio_getScreenBackingScale())
		cfg := configFor(screenScale)
		val := func(v unit.Value) float32 {
			return float32(cfg.Px(v)) / screenScale
		}
		if o := opts.Size; o != nil {
			width := val(o.Width)
			height := val(o.Height)
			if width > 0 || height > 0 {
				C.gio_setSize(w.window, C.CGFloat(width), C.CGFloat(height))
			}
		}
		if o := opts.MinSize; o != nil {
			width := val(o.Width)
			height := val(o.Height)
			if width > 0 || height > 0 {
				C.gio_setMinSize(w.window, C.CGFloat(width), C.CGFloat(height))
			}
		}
		if o := opts.MaxSize; o != nil {
			width := val(o.Width)
			height := val(o.Height)
			if width > 0 || height > 0 {
				C.gio_setMaxSize(w.window, C.CGFloat(width), C.CGFloat(height))
			}
		}
		if o := opts.Title; o != nil {
			title := C.CString(*o)
			defer C.free(unsafe.Pointer(title))
			C.gio_setTitle(w.window, title)
		}
		if o := opts.WindowMode; o != nil {
			w.SetWindowMode(*o)
		}
	})
}

func (w *window) SetWindowMode(mode WindowMode) {
	switch mode {
	case w.mode:
@@ -150,16 +193,22 @@ func (w *window) SetAnimating(anim bool) {
	}
}

func (w *window) Close() {
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 {
			C.gio_close(w.window)
			f()
		}
	})
}

func (w *window) Close() {
	w.runOnMain(func() {
		C.gio_close(w.window)
	})
}

func (w *window) setStage(stage system.Stage) {
	if stage == w.stage {
		return
@@ -336,35 +385,11 @@ func NewWindow(win Callbacks, opts *Options) error {
			errch <- err
			return
		}
		screenScale := float32(C.gio_getScreenBackingScale())
		cfg := configFor(screenScale)
		// Window sizes is in unscaled screen coordinates, not device pixels.
		var width, height int
		if o := opts.Size; o != nil {
			width = int(float32(cfg.Px(o.Width)) / screenScale)
			height = int(float32(cfg.Px(o.Height)) / screenScale)
		}
		var minWidth, minHeight int
		if o := opts.MinSize; o != nil {
			minWidth = int(float32(cfg.Px(o.Width)) / screenScale)
			minHeight = int(float32(cfg.Px(o.Height)) / screenScale)
		}
		var maxWidth, maxHeight int
		if o := opts.MaxSize; o != nil {
			maxWidth = int(float32(cfg.Px(o.Width)) / screenScale)
			maxHeight = int(float32(cfg.Px(o.Height)) / screenScale)
		}
		var title string
		if o := opts.Title; o != nil {
			title = *o
		}
		ctitle := C.CString(title)
		defer C.free(unsafe.Pointer(ctitle))
		errch <- nil
		win.SetDriver(w)
		w.w = win
		w.window = C.gio_createWindow(w.view, ctitle, C.CGFloat(width), C.CGFloat(height),
			C.CGFloat(minWidth), C.CGFloat(minHeight), C.CGFloat(maxWidth), C.CGFloat(maxHeight))
		w.window = C.gio_createWindow(w.view, nil, 0, 0, 0, 0, 0, 0)
		w.Option(opts)
		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.
@@ -372,9 +397,6 @@ func NewWindow(win Callbacks, opts *Options) error {
		}
		nextTopLeft = C.gio_cascadeTopLeftFromPoint(w.window, nextTopLeft)
		C.gio_makeKeyAndOrderFront(w.window)
		if o := opts.WindowMode; o != nil {
			w.SetWindowMode(*o)
		}
	})
	return <-errch
}
@@ -390,10 +412,8 @@ func newWindow(opts *Options) (*window, error) {
		scale: scale,
	}
	dl, err := NewDisplayLink(func() {
		runOnMain(func() {
			if w.view != 0 {
				C.gio_setNeedsDisplay(w.view)
			}
		w.runOnMain(func() {
			C.gio_setNeedsDisplay(w.view)
		})
	})
	w.displayLink = dl
diff --git a/app/internal/wm/os_macos.m b/app/internal/wm/os_macos.m
index 24c906cb..7980d532 100644
--- a/app/internal/wm/os_macos.m
+++ b/app/internal/wm/os_macos.m
@@ -191,7 +191,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];
@@ -206,6 +208,27 @@ void gio_close(CFTypeRef windowRef) {
  [window performClose:nil];
}

void gio_setSize(CFTypeRef windowRef, CGFloat width, CGFloat height) {
  NSWindow* window = (__bridge NSWindow *)windowRef;
  NSSize size = NSMakeSize(width, height);
  [window setContentSize:size];
}

void gio_setMinSize(CFTypeRef windowRef, CGFloat width, CGFloat height) {
  NSWindow* window = (__bridge NSWindow *)windowRef;
  window.contentMinSize = NSMakeSize(width, height);
}

void gio_setMaxSize(CFTypeRef windowRef, CGFloat width, CGFloat height) {
  NSWindow* window = (__bridge NSWindow *)windowRef;
  window.contentMaxSize = NSMakeSize(width, height);
}

void gio_setTitle(CFTypeRef windowRef, const char *title) {
  NSWindow* window = (__bridge NSWindow *)windowRef;
  window.title = [NSString stringWithUTF8String: title];
}

@implementation GioAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	[[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
diff --git a/app/internal/wm/os_wayland.go b/app/internal/wm/os_wayland.go
index 4a52078c..1e8c59d9 100644
--- a/app/internal/wm/os_wayland.go
+++ b/app/internal/wm/os_wayland.go
@@ -357,17 +357,8 @@ func (d *wlDisplay) createNativeWindow(opts *Options) (*window, error) {
	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))

	if o := opts.Title; o != nil {
		title := C.CString(*o)
		C.xdg_toplevel_set_title(w.topLvl, title)
		C.free(unsafe.Pointer(title))
	}
	w.Option(opts)

	_, _, cfg := w.config()
	if o := opts.Size; o != nil {
		w.width = cfg.Px(o.Width)
		w.height = cfg.Px(o.Height)
	}
	if d.decor != nil {
		// Request server side decorations.
		w.decor = C.zxdg_decoration_manager_v1_get_toplevel_decoration(d.decor, w.topLvl)
@@ -918,6 +909,19 @@ func (w *window) WriteClipboard(s string) {
	w.disp.wakeup()
}

func (w *window) Option(opts *Options) {
	_, _, cfg := w.config()
	if o := opts.Size; o != nil {
		w.width = cfg.Px(o.Width)
		w.height = cfg.Px(o.Height)
	}
	if o := opts.Title; o != nil {
		title := C.CString(*o)
		C.xdg_toplevel_set_title(w.topLvl, title)
		C.free(unsafe.Pointer(title))
	}
}

func (w *window) SetCursor(name pointer.CursorName) {
	if name == pointer.CursorNone {
		C.wl_pointer_set_cursor(w.disp.seat.pointer, w.serial, nil, 0, 0)
diff --git a/app/internal/wm/os_windows.go b/app/internal/wm/os_windows.go
index fe2daf4e..611c7cb0 100644
--- a/app/internal/wm/os_windows.go
+++ b/app/internal/wm/os_windows.go
@@ -116,15 +116,13 @@ func NewWindow(window Callbacks, opts *Options) error {
		w.w = window
		w.w.SetDriver(w)
		defer w.w.Event(system.DestroyEvent{})
		w.Option(opts)
		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 o := opts.WindowMode; o != nil {
			w.SetWindowMode(*o)
		}
		if err := w.loop(); err != nil {
			panic(err)
		}
@@ -185,33 +183,15 @@ func createNativeWindow(opts *Options) (*window, error) {
	}
	dpi := windows.GetSystemDPI()
	cfg := configForDPI(dpi)
	var wr windows.Rect
	if o := opts.Size; o != nil {
		wr.Right = int32(cfg.Px(o.Width))
		wr.Bottom = int32(cfg.Px(o.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

	var title string
	if o := opts.Title; o != nil {
		title = *o
	}

	hwnd, err := windows.CreateWindowEx(dwExStyle,
		resources.class,
		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,
@@ -222,7 +202,6 @@ func createNativeWindow(opts *Options) (*window, error) {
	w := &window{
		hwnd:   hwnd,
		minmax: getWindowConstraints(cfg, opts),
		deltas: deltas,
		opts:   opts,
	}
	w.hdc, err = windows.GetDC(hwnd)
@@ -540,6 +519,45 @@ func (w *window) readClipboard() error {
	return nil
}

func (w *window) Option(opts *Options) {
	if o := opts.Size; o != nil {
		dpi := windows.GetSystemDPI()
		cfg := configForDPI(dpi)
		width := int32(cfg.Px(o.Width))
		height := int32(cfg.Px(o.Height))

		// Include the window decorations.
		wr := windows.Rect{
			Right:  width,
			Bottom: height,
		}
		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

		w.opts.Size = o
		windows.MoveWindow(w.hwnd, 0, 0, width, height, true)
	}
	if o := opts.MinSize; o != nil {
		w.opts.MinSize = o
	}
	if o := opts.MaxSize; o != nil {
		w.opts.MaxSize = o
	}
	if o := opts.Title; o != nil {
		windows.SetWindowText(w.hwnd, *opts.Title)
	}
	if o := opts.WindowMode; o != nil {
		w.SetWindowMode(*o)
	}
}

func (w *window) SetWindowMode(mode WindowMode) {
	// https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353
	switch mode {
diff --git a/app/internal/wm/os_x11.go b/app/internal/wm/os_x11.go
index 671fd4a9..b921d468 100644
--- a/app/internal/wm/os_x11.go
+++ b/app/internal/wm/os_x11.go
@@ -123,6 +123,47 @@ func (w *x11Window) WriteClipboard(s string) {
	w.wakeup()
}

func (w *x11Window) Option(opts *Options) {
	dpy := w.x
	win := w.xw
	cfg := w.cfg
	var shints C.XSizeHints
	if o := opts.MinSize; o != nil {
		shints.min_width = C.int(cfg.Px(o.Width))
		shints.min_height = C.int(cfg.Px(o.Height))
		shints.flags = C.PMinSize
	}
	if o := opts.MaxSize; o != nil {
		shints.max_width = C.int(cfg.Px(o.Width))
		shints.max_height = C.int(cfg.Px(o.Height))
		shints.flags = shints.flags | C.PMaxSize
	}
	if shints.flags != 0 {
		C.XSetWMNormalHints(dpy, win, &shints)
	}

	var title string
	if o := opts.Title; o != nil {
		title = *o
	}
	ctitle := C.CString(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(title)),
		},
		w.atoms.wmName)

	if o := opts.WindowMode; o != nil {
		w.SetWindowMode(*o)
	}
}

func (w *x11Window) SetCursor(name pointer.CursorName) {
	switch name {
	case pointer.CursorNone:
@@ -607,21 +648,6 @@ func newX11Window(gioWin Callbacks, opts *Options) error {
	hints.flags = C.InputHint
	C.XSetWMHints(dpy, win, &hints)

	var shints C.XSizeHints
	if o := opts.MinSize; o != nil && (o.Width.V != 0 || o.Height.V != 0) {
		shints.min_width = C.int(cfg.Px(o.Width))
		shints.min_height = C.int(cfg.Px(o.Height))
		shints.flags = C.PMinSize
	}
	if o := opts.MaxSize; o != nil && (o.Width.V != 0 || o.Height.V != 0) {
		shints.max_width = C.int(cfg.Px(o.Width))
		shints.max_height = C.int(cfg.Px(o.Height))
		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}
@@ -639,30 +665,10 @@ func newX11Window(gioWin Callbacks, opts *Options) error {
	w.atoms.wmState = w.atom("_NET_WM_STATE", false)
	w.atoms.wmStateFullscreen = w.atom("_NET_WM_STATE_FULLSCREEN", false)

	// set the name
	var title string
	if o := opts.Title; o != nil {
		title = *o
	}
	ctitle := C.CString(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(title)),
		},
		w.atoms.wmName)

	// extensions
	C.XSetWMProtocols(dpy, win, &w.atoms.evDelWindow, 1)

	if o := opts.WindowMode; o != nil {
		w.SetWindowMode(*o)
	}
	w.Option(opts)

	// make the window visible on the screen
	C.XMapWindow(dpy, win)
diff --git a/app/internal/wm/window.go b/app/internal/wm/window.go
index 7eb51f2d..168d4d6d 100644
--- a/app/internal/wm/window.go
+++ b/app/internal/wm/window.go
@@ -74,6 +74,9 @@ type Driver interface {
	// WriteClipboard requests a clipboard write.
	WriteClipboard(s string)

	// Option processes option changes.
	Option(opts *Options)

	// SetCursor updates the current cursor to name.
	SetCursor(name pointer.CursorName)

-- 
2.30.2

[gio/patches] build success

builds.sr.ht
Details
Message ID
<CAD9ZVRLS4DV.1IOKTP8RVTB2Q@cirno2>
In-Reply-To
<161736927664.9206.5988759538078666758-0@git.sr.ht> (view parent)
DKIM signature
missing
Download raw message
gio/patches: SUCCESS in 20m33s

[app/internal/wm: use Option method to initialize windows][0] from [~pierrec][1]

[0]: https://lists.sr.ht/~eliasnaur/gio-patches/patches/21741
[1]: mailto:pierre.curto@gmail.com

✓ #475499 SUCCESS gio/patches/freebsd.yml https://builds.sr.ht/~eliasnaur/job/475499
✓ #475500 SUCCESS gio/patches/linux.yml   https://builds.sr.ht/~eliasnaur/job/475500
✓ #475498 SUCCESS gio/patches/apple.yml   https://builds.sr.ht/~eliasnaur/job/475498
✓ #475501 SUCCESS gio/patches/openbsd.yml https://builds.sr.ht/~eliasnaur/job/475501
Details
Message ID
<CADAHBD1SZIW.FI55YV0WEYTR@testmac>
In-Reply-To
<161736927664.9206.5988759538078666758-0@git.sr.ht> (view parent)
DKIM signature
fail
Download raw message
DKIM signature: fail
On Fri Apr 2, 2021 at 14:45 CEST, ~pierrec wrote:
> From: pierre <pierre.curto@gmail.com>
>
> Added (*w.window).Option methods to the backends and use them for setting the initial options passed into NewWindow.
>
> Signed-off-by: pierre <pierre.curto@gmail.com>
> ---
> diff --git a/app/internal/wm/os_macos.go b/app/internal/wm/os_macos.go
> index b82c8d0f..d088a924 100644
> --- a/app/internal/wm/os_macos.go
> +++ b/app/internal/wm/os_macos.go
> @@ -46,6 +46,10 @@ __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef vie
>  __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);
> +__attribute__ ((visibility ("hidden"))) void gio_setSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> +__attribute__ ((visibility ("hidden"))) void gio_setMinSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> +__attribute__ ((visibility ("hidden"))) void gio_setMaxSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> +__attribute__ ((visibility ("hidden"))) void gio_setTitle(CFTypeRef windowRef, const char *title);
>  */
>  import "C"
>  
> @@ -126,6 +130,45 @@ func (w *window) WriteClipboard(s string) {
>  	})
>  }
>  
> +func (w *window) Option(opts *Options) {
> +	w.runOnMain(func() {

It occurred to me that runOnMain will always queue the closure and
run it later, even if called from the main thread. On the other hand,
the initializing call to w.Option assumes the options will be applied
immediately (otherwise, there may be a brief moment where the window
properties don't match the initial set of options).

This change looks good, but you should add a change before it that
runs the runOnMain closure if [NSThread isMainThread] returns TRUE[0].

> +		screenScale := float32(C.gio_getScreenBackingScale())
> +		cfg := configFor(screenScale)
> +		val := func(v unit.Value) float32 {
> +			return float32(cfg.Px(v)) / screenScale
> +		}
> +		if o := opts.Size; o != nil {
> +			width := val(o.Width)
> +			height := val(o.Height)
> +			if width > 0 || height > 0 {
> +				C.gio_setSize(w.window, C.CGFloat(width), C.CGFloat(height))
> +			}
> +		}
> +		if o := opts.MinSize; o != nil {
> +			width := val(o.Width)
> +			height := val(o.Height)
> +			if width > 0 || height > 0 {
> +				C.gio_setMinSize(w.window, C.CGFloat(width), C.CGFloat(height))
> +			}
> +		}
> +		if o := opts.MaxSize; o != nil {
> +			width := val(o.Width)
> +			height := val(o.Height)
> +			if width > 0 || height > 0 {
> +				C.gio_setMaxSize(w.window, C.CGFloat(width), C.CGFloat(height))
> +			}
> +		}
> +		if o := opts.Title; o != nil {
> +			title := C.CString(*o)
> +			defer C.free(unsafe.Pointer(title))
> +			C.gio_setTitle(w.window, title)
> +		}
> +		if o := opts.WindowMode; o != nil {
> +			w.SetWindowMode(*o)
> +		}
> +	})
> +}
> +
>  func (w *window) SetWindowMode(mode WindowMode) {
>  	switch mode {
>  	case w.mode:

[0] https://developer.apple.com/documentation/foundation/nsthread/1412704-ismainthread
Details
Message ID
<CAG3idSek-wFb1nm_HvWOX=bngHdDgUPyaYxdPkKzEw+DRZbk2Q@mail.gmail.com>
In-Reply-To
<CADAHBD1SZIW.FI55YV0WEYTR@testmac> (view parent)
DKIM signature
pass
Download raw message
Le ven. 2 avr. 2021 à 15:57, Elias Naur <mail@eliasnaur.com> a écrit :
>
> On Fri Apr 2, 2021 at 14:45 CEST, ~pierrec wrote:
> > From: pierre <pierre.curto@gmail.com>
> >
> > Added (*w.window).Option methods to the backends and use them for setting the initial options passed into NewWindow.
> >
> > Signed-off-by: pierre <pierre.curto@gmail.com>
> > ---
> > diff --git a/app/internal/wm/os_macos.go b/app/internal/wm/os_macos.go
> > index b82c8d0f..d088a924 100644
> > --- a/app/internal/wm/os_macos.go
> > +++ b/app/internal/wm/os_macos.go
> > @@ -46,6 +46,10 @@ __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef vie
> >  __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);
> > +__attribute__ ((visibility ("hidden"))) void gio_setSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > +__attribute__ ((visibility ("hidden"))) void gio_setMinSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > +__attribute__ ((visibility ("hidden"))) void gio_setMaxSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > +__attribute__ ((visibility ("hidden"))) void gio_setTitle(CFTypeRef windowRef, const char *title);
> >  */
> >  import "C"
> >
> > @@ -126,6 +130,45 @@ func (w *window) WriteClipboard(s string) {
> >       })
> >  }
> >
> > +func (w *window) Option(opts *Options) {
> > +     w.runOnMain(func() {
>
> It occurred to me that runOnMain will always queue the closure and
> run it later, even if called from the main thread. On the other hand,
> the initializing call to w.Option assumes the options will be applied
> immediately (otherwise, there may be a brief moment where the window
> properties don't match the initial set of options).
>
> This change looks good, but you should add a change before it that
> runs the runOnMain closure if [NSThread isMainThread] returns TRUE[0].
>

So if I understood well, something like:

func (w *window) Option(opts *Options) {
    f := func() { ... }
    w.runOnMain(func() {
      if C.gio_isMainThread() {
         f()
         return
      }
      w.runOnMain(f)
   })
}


> > +             screenScale := float32(C.gio_getScreenBackingScale())
> > +             cfg := configFor(screenScale)
> > +             val := func(v unit.Value) float32 {
> > +                     return float32(cfg.Px(v)) / screenScale
> > +             }
> > +             if o := opts.Size; o != nil {
> > +                     width := val(o.Width)
> > +                     height := val(o.Height)
> > +                     if width > 0 || height > 0 {
> > +                             C.gio_setSize(w.window, C.CGFloat(width), C.CGFloat(height))
> > +                     }
> > +             }
> > +             if o := opts.MinSize; o != nil {
> > +                     width := val(o.Width)
> > +                     height := val(o.Height)
> > +                     if width > 0 || height > 0 {
> > +                             C.gio_setMinSize(w.window, C.CGFloat(width), C.CGFloat(height))
> > +                     }
> > +             }
> > +             if o := opts.MaxSize; o != nil {
> > +                     width := val(o.Width)
> > +                     height := val(o.Height)
> > +                     if width > 0 || height > 0 {
> > +                             C.gio_setMaxSize(w.window, C.CGFloat(width), C.CGFloat(height))
> > +                     }
> > +             }
> > +             if o := opts.Title; o != nil {
> > +                     title := C.CString(*o)
> > +                     defer C.free(unsafe.Pointer(title))
> > +                     C.gio_setTitle(w.window, title)
> > +             }
> > +             if o := opts.WindowMode; o != nil {
> > +                     w.SetWindowMode(*o)
> > +             }
> > +     })
> > +}
> > +
> >  func (w *window) SetWindowMode(mode WindowMode) {
> >       switch mode {
> >       case w.mode:
>
> [0] https://developer.apple.com/documentation/foundation/nsthread/1412704-ismainthread
Details
Message ID
<CADB7C8NHQIT.Z75IQ9IIHRSP@themachine>
In-Reply-To
<CAG3idSek-wFb1nm_HvWOX=bngHdDgUPyaYxdPkKzEw+DRZbk2Q@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
On Fri Apr 2, 2021 at 16:24, Pierre Curto wrote:
> Le ven. 2 avr. 2021 à 15:57, Elias Naur <mail@eliasnaur.com> a écrit :
> >
> > On Fri Apr 2, 2021 at 14:45 CEST, ~pierrec wrote:
> > > From: pierre <pierre.curto@gmail.com>
> > >
> > > Added (*w.window).Option methods to the backends and use them for setting the initial options passed into NewWindow.
> > >
> > > Signed-off-by: pierre <pierre.curto@gmail.com>
> > > ---
> > > diff --git a/app/internal/wm/os_macos.go b/app/internal/wm/os_macos.go
> > > index b82c8d0f..d088a924 100644
> > > --- a/app/internal/wm/os_macos.go
> > > +++ b/app/internal/wm/os_macos.go
> > > @@ -46,6 +46,10 @@ __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef vie
> > >  __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);
> > > +__attribute__ ((visibility ("hidden"))) void gio_setSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > > +__attribute__ ((visibility ("hidden"))) void gio_setMinSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > > +__attribute__ ((visibility ("hidden"))) void gio_setMaxSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > > +__attribute__ ((visibility ("hidden"))) void gio_setTitle(CFTypeRef windowRef, const char *title);
> > >  */
> > >  import "C"
> > >
> > > @@ -126,6 +130,45 @@ func (w *window) WriteClipboard(s string) {
> > >       })
> > >  }
> > >
> > > +func (w *window) Option(opts *Options) {
> > > +     w.runOnMain(func() {
> >
> > It occurred to me that runOnMain will always queue the closure and
> > run it later, even if called from the main thread. On the other hand,
> > the initializing call to w.Option assumes the options will be applied
> > immediately (otherwise, there may be a brief moment where the window
> > properties don't match the initial set of options).
> >
> > This change looks good, but you should add a change before it that
> > runs the runOnMain closure if [NSThread isMainThread] returns TRUE[0].
> >
>
> So if I understood well, something like:
>
> func (w *window) Option(opts *Options) {
>     f := func() { ... }
>     w.runOnMain(func() {
>       if C.gio_isMainThread() {
>          f()
>          return
>       }
>       w.runOnMain(f)
>    })
> }
>

Almost, but I'd like you to change the runOnMain function in
os_darwin.go so all callers benefit.

Elias
Details
Message ID
<CAG3idSd++p4SC0tGRm=9v=W=7Xr+VdU+AVFFMfWAr0Ws7wqnMg@mail.gmail.com>
In-Reply-To
<CADB7C8NHQIT.Z75IQ9IIHRSP@themachine> (view parent)
DKIM signature
pass
Download raw message
But, isn't gio_dispatchMainFuncs (via gio_wakeupMainThread in
os_darwin.m) always called while on the main thread?

If I had that check in gio_dispatchMainFuncs (os_darwin.go), then f
needs to be requeued but it will lose its position. Is that OK?

Le ven. 2 avr. 2021 à 16:31, Elias Naur <mail@eliasnaur.com> a écrit :
>
> On Fri Apr 2, 2021 at 16:24, Pierre Curto wrote:
> > Le ven. 2 avr. 2021 à 15:57, Elias Naur <mail@eliasnaur.com> a écrit :
> > >
> > > On Fri Apr 2, 2021 at 14:45 CEST, ~pierrec wrote:
> > > > From: pierre <pierre.curto@gmail.com>
> > > >
> > > > Added (*w.window).Option methods to the backends and use them for setting the initial options passed into NewWindow.
> > > >
> > > > Signed-off-by: pierre <pierre.curto@gmail.com>
> > > > ---
> > > > diff --git a/app/internal/wm/os_macos.go b/app/internal/wm/os_macos.go
> > > > index b82c8d0f..d088a924 100644
> > > > --- a/app/internal/wm/os_macos.go
> > > > +++ b/app/internal/wm/os_macos.go
> > > > @@ -46,6 +46,10 @@ __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef vie
> > > >  __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);
> > > > +__attribute__ ((visibility ("hidden"))) void gio_setSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > > > +__attribute__ ((visibility ("hidden"))) void gio_setMinSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > > > +__attribute__ ((visibility ("hidden"))) void gio_setMaxSize(CFTypeRef windowRef, CGFloat width, CGFloat height);
> > > > +__attribute__ ((visibility ("hidden"))) void gio_setTitle(CFTypeRef windowRef, const char *title);
> > > >  */
> > > >  import "C"
> > > >
> > > > @@ -126,6 +130,45 @@ func (w *window) WriteClipboard(s string) {
> > > >       })
> > > >  }
> > > >
> > > > +func (w *window) Option(opts *Options) {
> > > > +     w.runOnMain(func() {
> > >
> > > It occurred to me that runOnMain will always queue the closure and
> > > run it later, even if called from the main thread. On the other hand,
> > > the initializing call to w.Option assumes the options will be applied
> > > immediately (otherwise, there may be a brief moment where the window
> > > properties don't match the initial set of options).
> > >
> > > This change looks good, but you should add a change before it that
> > > runs the runOnMain closure if [NSThread isMainThread] returns TRUE[0].
> > >
> >
> > So if I understood well, something like:
> >
> > func (w *window) Option(opts *Options) {
> >     f := func() { ... }
> >     w.runOnMain(func() {
> >       if C.gio_isMainThread() {
> >          f()
> >          return
> >       }
> >       w.runOnMain(f)
> >    })
> > }
> >
>
> Almost, but I'd like you to change the runOnMain function in
> os_darwin.go so all callers benefit.
>
> Elias
Details
Message ID
<CADCA3HYLH0G.1SHS5M7XBAMNL@testmac>
In-Reply-To
<CAG3idSd++p4SC0tGRm=9v=W=7Xr+VdU+AVFFMfWAr0Ws7wqnMg@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +4 -0
On Fri Apr 2, 2021 at 17:01 CEST, Pierre Curto wrote:
> But, isn't gio_dispatchMainFuncs (via gio_wakeupMainThread in
> os_darwin.m) always called while on the main thread?
>
> If I had that check in gio_dispatchMainFuncs (os_darwin.go), then f
> needs to be requeued but it will lose its position. Is that OK?
>

I had in mind (incomplete):

diff --git a/app/internal/wm/os_darwin.go b/app/internal/wm/os_darwin.go
index d804c9cf..36518b6c 100644
--- a/app/internal/wm/os_darwin.go
+++ b/app/internal/wm/os_darwin.go
@@ -55,6 +55,10 @@ var mainFuncs = make(chan func(), 1)

// runOnMain runs the function on the main thread.
func runOnMain(f func()) {
	if gio_isMainThread() {
		f()
		return
	}
	go func() {
		mainFuncs <- f
		C.gio_wakeupMainThread()


Elias
Details
Message ID
<CAG3idScAMc9+ogh=qY3Q_OgWPs9vLztcHjToUw9ROxo+ne+SRg@mail.gmail.com>
In-Reply-To
<CADCA3HYLH0G.1SHS5M7XBAMNL@testmac> (view parent)
DKIM signature
pass
Download raw message
I see.
Should this be a separate patch or not?

Le ven. 2 avr. 2021 à 17:22, Elias Naur <mail@eliasnaur.com> a écrit :
>
> On Fri Apr 2, 2021 at 17:01 CEST, Pierre Curto wrote:
> > But, isn't gio_dispatchMainFuncs (via gio_wakeupMainThread in
> > os_darwin.m) always called while on the main thread?
> >
> > If I had that check in gio_dispatchMainFuncs (os_darwin.go), then f
> > needs to be requeued but it will lose its position. Is that OK?
> >
>
> I had in mind (incomplete):
>
> diff --git a/app/internal/wm/os_darwin.go b/app/internal/wm/os_darwin.go
> index d804c9cf..36518b6c 100644
> --- a/app/internal/wm/os_darwin.go
> +++ b/app/internal/wm/os_darwin.go
> @@ -55,6 +55,10 @@ var mainFuncs = make(chan func(), 1)
>
>  // runOnMain runs the function on the main thread.
>  func runOnMain(f func()) {
> +       if gio_isMainThread() {
> +               f()
> +               return
> +       }
>         go func() {
>                 mainFuncs <- f
>                 C.gio_wakeupMainThread()
>
>
> Elias
Details
Message ID
<CADCTW6LDVDS.ZF19POWUQ0SL@testmac>
In-Reply-To
<CAG3idScAMc9+ogh=qY3Q_OgWPs9vLztcHjToUw9ROxo+ne+SRg@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
On Fri Apr 2, 2021 at 17:36 CEST, Pierre Curto wrote:
> I see.
> Should this be a separate patch or not?
>

Separate, please. Your change is large, and runOnMain is subtle.

Elias
Reply to thread Export thread (mbox)