From 6330caad952f3a2c1a14b663b6df5462ce1ea55d Mon Sep 17 00:00:00 2001 From: pierre Date: Fri, 2 Apr 2021 10:22:04 +0200 Subject: [PATCH] app/internal/wm: change Options fields from values to pointers Switching to pointer values in Options, including using window manager defaults for size and title, in preparation for updating options on the fly. Signed-off-by: pierre --- app/internal/wm/os_js.go | 4 +++- app/internal/wm/os_macos.go | 41 +++++++++++++++++++++-------------- app/internal/wm/os_wayland.go | 15 ++++++++----- app/internal/wm/os_windows.go | 30 +++++++++++++++++-------- app/internal/wm/os_x11.go | 35 ++++++++++++++++++++---------- app/internal/wm/window.go | 15 ++++++++----- app/window.go | 31 +++++++++++++++----------- 7 files changed, 110 insertions(+), 61 deletions(-) diff --git a/app/internal/wm/os_js.go b/app/internal/wm/os_js.go index 057fb586..7eb627b9 100644 --- a/app/internal/wm/os_js.go +++ b/app/internal/wm/os_js.go @@ -82,7 +82,9 @@ func NewWindow(win Callbacks, opts *Options) error { }) w.addEventListeners() w.addHistory() - w.windowMode(opts.WindowMode) + if o := opts.WindowMode; o != nil { + w.windowMode(*o) + } w.w = win go func() { diff --git a/app/internal/wm/os_macos.go b/app/internal/wm/os_macos.go index 68ead7b0..b82c8d0f 100644 --- a/app/internal/wm/os_macos.go +++ b/app/internal/wm/os_macos.go @@ -338,25 +338,32 @@ func NewWindow(win Callbacks, opts *Options) error { } 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)) + 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, title, C.CGFloat(width), C.CGFloat(height), + 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)) if nextTopLeft.x == 0 && nextTopLeft.y == 0 { // cascadeTopLeftFromPoint treats (0, 0) as a no-op, @@ -365,7 +372,9 @@ func NewWindow(win Callbacks, opts *Options) error { } nextTopLeft = C.gio_cascadeTopLeftFromPoint(w.window, nextTopLeft) C.gio_makeKeyAndOrderFront(w.window) - w.SetWindowMode(opts.WindowMode) + if o := opts.WindowMode; o != nil { + w.SetWindowMode(*o) + } }) return <-errch } diff --git a/app/internal/wm/os_wayland.go b/app/internal/wm/os_wayland.go index e0dd7230..4a52078c 100644 --- a/app/internal/wm/os_wayland.go +++ b/app/internal/wm/os_wayland.go @@ -356,13 +356,18 @@ 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)) + + if o := opts.Title; o != nil { + title := C.CString(*o) + 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 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) diff --git a/app/internal/wm/os_windows.go b/app/internal/wm/os_windows.go index 29cd8f28..fe2daf4e 100644 --- a/app/internal/wm/os_windows.go +++ b/app/internal/wm/os_windows.go @@ -122,7 +122,9 @@ func NewWindow(window Callbacks, opts *Options) error { // Since the window class for the cursor is null, // set it here to show the cursor. w.SetCursor(pointer.CursorDefault) - w.SetWindowMode(opts.WindowMode) + if o := opts.WindowMode; o != nil { + w.SetWindowMode(*o) + } if err := w.loop(); err != nil { panic(err) } @@ -162,10 +164,14 @@ func initResources() error { func getWindowConstraints(cfg unit.Metric, opts *Options) 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)) + if o := opts.MinSize; o != nil { + minmax.minWidth = int32(cfg.Px(o.Width)) + minmax.minHeight = int32(cfg.Px(o.Height)) + } + if o := opts.MaxSize; o != nil { + minmax.maxWidth = int32(cfg.Px(o.Width)) + minmax.maxHeight = int32(cfg.Px(o.Height)) + } return minmax } @@ -179,9 +185,10 @@ func createNativeWindow(opts *Options) (*window, error) { } dpi := windows.GetSystemDPI() cfg := configForDPI(dpi) - wr := windows.Rect{ - Right: int32(cfg.Px(opts.Width)), - Bottom: int32(cfg.Px(opts.Height)), + 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) @@ -193,9 +200,14 @@ func createNativeWindow(opts *Options) (*window, error) { 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, - opts.Title, + title, dwStyle|windows.WS_CLIPSIBLINGS|windows.WS_CLIPCHILDREN, windows.CW_USEDEFAULT, windows.CW_USEDEFAULT, wr.Right-wr.Left, diff --git a/app/internal/wm/os_x11.go b/app/internal/wm/os_x11.go index a5a25c66..671fd4a9 100644 --- a/app/internal/wm/os_x11.go +++ b/app/internal/wm/os_x11.go @@ -576,15 +576,20 @@ func newX11Window(gioWin Callbacks, opts *Options) error { background_pixmap: C.None, override_redirect: C.False, } + var width, height int + if o := opts.Size; o != nil { + width = cfg.Px(o.Width) + height = cfg.Px(o.Height) + } 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(width), C.uint(height), 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), + width: width, + height: height, cfg: cfg, xkb: xkb, xkbEventBase: xkbEventBase, @@ -603,14 +608,14 @@ func newX11Window(gioWin Callbacks, opts *Options) error { 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)) + 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 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)) + 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 { @@ -635,7 +640,11 @@ func newX11Window(gioWin Callbacks, opts *Options) error { w.atoms.wmStateFullscreen = w.atom("_NET_WM_STATE_FULLSCREEN", false) // set the name - ctitle := C.CString(opts.Title) + 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. @@ -644,14 +653,16 @@ func newX11Window(gioWin Callbacks, opts *Options) error { value: (*C.uchar)(unsafe.Pointer(ctitle)), encoding: w.atoms.utf8string, format: 8, - nitems: C.ulong(len(opts.Title)), + nitems: C.ulong(len(title)), }, w.atoms.wmName) // extensions C.XSetWMProtocols(dpy, win, &w.atoms.evDelWindow, 1) - w.SetWindowMode(opts.WindowMode) + if o := opts.WindowMode; o != nil { + w.SetWindowMode(*o) + } // 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 b33a1b66..7eb51f2d 100644 --- a/app/internal/wm/window.go +++ b/app/internal/wm/window.go @@ -14,12 +14,17 @@ import ( "gioui.org/unit" ) +type Size struct { + Width unit.Value + Height unit.Value +} + type Options struct { - Width, Height unit.Value - MinWidth, MinHeight unit.Value - MaxWidth, MaxHeight unit.Value - Title string - WindowMode WindowMode + Size *Size + MinSize *Size + MaxSize *Size + Title *string + WindowMode *WindowMode } type WindowMode uint8 diff --git a/app/window.go b/app/window.go index 2de6c1ef..e8f691a9 100644 --- a/app/window.go +++ b/app/window.go @@ -84,11 +84,10 @@ var ackEvent event.Event // Calling NewWindow more than once is not supported on // iOS, Android, WebAssembly. func NewWindow(options ...Option) *Window { - opts := &wm.Options{ - Width: unit.Dp(800), - Height: unit.Dp(600), - Title: "Gio", - } + opts := new(wm.Options) + // Default options. + Size(unit.Px(800), unit.Px(600))(opts) + Title("Gio")(opts) for _, o := range options { o(opts) @@ -456,14 +455,14 @@ const ( // Supported platforms are macOS, X11 and Windows. func WindowMode(mode wm.WindowMode) Option { return func(opts *wm.Options) { - opts.WindowMode = mode + opts.WindowMode = &mode } } // Title sets the title of the wm. func Title(t string) Option { return func(opts *wm.Options) { - opts.Title = t + opts.Title = &t } } @@ -476,8 +475,10 @@ func Size(w, h unit.Value) Option { panic("height must be larger than or equal to 0") } return func(opts *wm.Options) { - opts.Width = w - opts.Height = h + opts.Size = &wm.Size{ + Width: w, + Height: h, + } } } @@ -490,8 +491,10 @@ func MaxSize(w, h unit.Value) Option { panic("height must be larger than or equal to 0") } return func(opts *wm.Options) { - opts.MaxWidth = w - opts.MaxHeight = h + opts.MaxSize = &wm.Size{ + Width: w, + Height: h, + } } } @@ -504,8 +507,10 @@ func MinSize(w, h unit.Value) Option { panic("height must be larger than or equal to 0") } return func(opts *wm.Options) { - opts.MinWidth = w - opts.MinHeight = h + opts.MinSize = &wm.Size{ + Width: w, + Height: h, + } } }