app: replace Window.Config with ConfigEvent

Unlike Raise, Close and other fire-and-forget methods on Window,
Config calls driverRun because it needs to wait for the result.
However, driverRun isn't guaranteed to block in all contexts.

This change avoids the synchronization dance altogether by removing the
Config method and introducing a ConfigEvent event. The event also makes
it clear when the configuration changes.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-09-19 09:57:41 +02:00
parent 64bcb1ccd5
commit 18c2ba8e20
9 changed files with 102 additions and 108 deletions
+30 -27
View File
@@ -187,7 +187,9 @@ type window struct {
serial C.uint32_t
newScale bool
scale int
config Config
// size is the unscaled window size (unlike config.Size which is scaled).
size image.Point
config Config
wakeups chan struct{}
}
@@ -222,7 +224,7 @@ func init() {
wlDriver = newWLWindow
}
func newWLWindow(window *callbacks, options []Option) error {
func newWLWindow(callbacks *callbacks, options []Option) error {
d, err := newWLDisplay()
if err != nil {
return err
@@ -232,10 +234,14 @@ func newWLWindow(window *callbacks, options []Option) error {
d.destroy()
return err
}
w.w = window
w.w = callbacks
go func() {
defer d.destroy()
defer w.destroy()
// Finish and commit setup from createNativeWindow.
w.Configure(options)
C.wl_surface_commit(w.surf)
w.w.SetDriver(w)
if err := w.loop(); err != nil {
panic(err)
@@ -356,15 +362,12 @@ func (d *wlDisplay) createNativeWindow(options []Option) (*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))
w.Configure(options)
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
}
@@ -487,8 +490,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.config.Size.X = int(width)
w.config.Size.Y = int(height)
w.size = image.Pt(int(width), int(height))
w.updateOpaqueRegion()
}
}
@@ -855,7 +857,7 @@ 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.getConfig()
_, c := w.getConfig()
if !w.fling.anim.Start(c, time.Now(), vel) {
return
}
@@ -908,11 +910,12 @@ func (w *window) WriteClipboard(s string) {
}
func (w *window) Configure(options []Option) {
_, _, cfg := w.getConfig()
_, 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 {
@@ -921,10 +924,9 @@ func (w *window) Configure(options []Option) {
C.xdg_toplevel_set_title(w.topLvl, title)
C.free(unsafe.Pointer(title))
}
}
func (w *window) Config() Config {
return w.config
if w.config != prev {
w.w.Event(ConfigEvent{Config: w.config})
}
}
func (w *window) Raise() {}
@@ -1374,7 +1376,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.config.Size.X), C.int32_t(w.config.Size.Y))
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)
}
@@ -1404,9 +1406,9 @@ func (w *window) updateOutputs() {
}
}
func (w *window) getConfig() (int, int, unit.Metric) {
width, height := w.config.Size.X*w.scale, w.config.Size.Y*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),
}
@@ -1419,7 +1421,11 @@ func (w *window) draw(sync bool) {
if dead || (!anim && !sync) {
return
}
width, height, cfg := w.getConfig()
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
}
@@ -1430,11 +1436,8 @@ func (w *window) draw(sync bool) {
}
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,
@@ -1458,12 +1461,12 @@ 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.config.Size.X, w.config.Size.Y, 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) {}