Skip to content

Commit 4759601

Browse files
committed
app: ignore Invalidate for Windows not yet created
While here, don't overflow the Windows event queue. Signed-off-by: Elias Naur <[email protected]>
1 parent 42357a2 commit 4759601

File tree

5 files changed

+31
-59
lines changed

5 files changed

+31
-59
lines changed

app/os.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,19 +173,13 @@ type context interface {
173173
Unlock()
174174
}
175175

176-
// basicDriver is the subset of [driver] that may be called even after
177-
// a window is destroyed.
178-
type basicDriver interface {
176+
// driver is the interface for the platform implementation
177+
// of a window.
178+
type driver interface {
179179
// Event blocks until an event is available and returns it.
180180
Event() event.Event
181181
// Invalidate requests a FrameEvent.
182182
Invalidate()
183-
}
184-
185-
// driver is the interface for the platform implementation
186-
// of a window.
187-
type driver interface {
188-
basicDriver
189183
// SetAnimating sets the animation flag. When the window is animating,
190184
// FrameEvents are delivered as fast as the display can handle them.
191185
SetAnimating(anim bool)

app/os_wayland.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,6 @@ type window struct {
217217
wakeups chan struct{}
218218

219219
closing bool
220-
221-
// invMu avoids the race between the destruction of disp and
222-
// Invalidate waking it up.
223-
invMu sync.Mutex
224220
}
225221

226222
type poller struct {
@@ -1369,10 +1365,8 @@ func (w *window) close(err error) {
13691365
w.ProcessEvent(WaylandViewEvent{})
13701366
w.ProcessEvent(DestroyEvent{Err: err})
13711367
w.destroy()
1372-
w.invMu.Lock()
13731368
w.disp.destroy()
13741369
w.disp = nil
1375-
w.invMu.Unlock()
13761370
}
13771371

13781372
func (w *window) dispatch() {
@@ -1416,11 +1410,7 @@ func (w *window) Invalidate() {
14161410
default:
14171411
return
14181412
}
1419-
w.invMu.Lock()
1420-
defer w.invMu.Unlock()
1421-
if w.disp != nil {
1422-
w.disp.wakeup()
1423-
}
1413+
w.disp.wakeup()
14241414
}
14251415

14261416
func (w *window) Run(f func()) {

app/os_windows.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,6 @@ type window struct {
5454
borderSize image.Point
5555
config Config
5656
loop *eventLoop
57-
58-
// invMu avoids the race between destroying the window and Invalidate.
59-
invMu sync.Mutex
6057
}
6158

6259
const _WM_WAKEUP = windows.WM_USER + iota
@@ -304,10 +301,8 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
304301
windows.ReleaseDC(w.hdc)
305302
w.hdc = 0
306303
}
307-
w.invMu.Lock()
308304
// The system destroys the HWND for us.
309305
w.hwnd = 0
310-
w.invMu.Unlock()
311306
windows.PostQuitMessage(0)
312307
case windows.WM_NCCALCSIZE:
313308
if w.config.Decorated {
@@ -620,13 +615,6 @@ func (w *window) Frame(frame *op.Ops) {
620615
}
621616

622617
func (w *window) wakeup() {
623-
w.invMu.Lock()
624-
defer w.invMu.Unlock()
625-
if w.hwnd == 0 {
626-
w.loop.Wakeup()
627-
w.loop.FlushEvents()
628-
return
629-
}
630618
if err := windows.PostMessage(w.hwnd, _WM_WAKEUP, 0, 0); err != nil {
631619
panic(err)
632620
}

app/os_x11.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,6 @@ type x11Window struct {
113113
wakeups chan struct{}
114114
handler x11EventHandler
115115
buf [100]byte
116-
117-
// invMy avoids the race between destroy and Invalidate.
118-
invMu sync.Mutex
119116
}
120117

121118
var (
@@ -416,11 +413,6 @@ func (w *x11Window) Invalidate() {
416413
case w.wakeups <- struct{}{}:
417414
default:
418415
}
419-
w.invMu.Lock()
420-
defer w.invMu.Unlock()
421-
if w.x == nil {
422-
return
423-
}
424416
if _, err := syscall.Write(w.notify.write, x11OneByte); err != nil && err != syscall.EAGAIN {
425417
panic(fmt.Errorf("failed to write to pipe: %v", err))
426418
}
@@ -509,8 +501,6 @@ func (w *x11Window) dispatch() {
509501
}
510502

511503
func (w *x11Window) destroy() {
512-
w.invMu.Lock()
513-
defer w.invMu.Unlock()
514504
if w.notify.write != 0 {
515505
syscall.Close(w.notify.write)
516506
w.notify.write = 0

app/window.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"image/color"
1010
"reflect"
1111
"runtime"
12+
"sync"
1213
"time"
1314
"unicode/utf8"
1415

@@ -89,8 +90,11 @@ type Window struct {
8990
}
9091
imeState editorState
9192
driver driver
92-
// basic is the driver interface that is needed even after the window is gone.
93-
basic basicDriver
93+
94+
// invMu protects canInvalidate.
95+
invMu sync.Mutex
96+
mayInvalidate bool
97+
9498
// coalesced tracks the most recent events waiting to be delivered
9599
// to the client.
96100
coalesced eventSummary
@@ -272,8 +276,11 @@ func (w *Window) updateState() {
272276
//
273277
// Invalidate is safe for concurrent use.
274278
func (w *Window) Invalidate() {
275-
if w.basic != nil {
276-
w.basic.Invalidate()
279+
w.invMu.Lock()
280+
defer w.invMu.Unlock()
281+
if w.mayInvalidate {
282+
w.mayInvalidate = false
283+
w.driver.Invalidate()
277284
}
278285
}
279286

@@ -283,7 +290,7 @@ func (w *Window) Option(opts ...Option) {
283290
if len(opts) == 0 {
284291
return
285292
}
286-
if w.basic == nil {
293+
if w.driver == nil {
287294
w.initialOpts = append(w.initialOpts, opts...)
288295
return
289296
}
@@ -378,11 +385,8 @@ func (w *Window) setNextFrame(at time.Time) {
378385
}
379386
}
380387

381-
func (c *callbacks) SetDriver(d basicDriver) {
382-
c.w.basic = d
383-
if d, ok := d.(driver); ok {
384-
c.w.driver = d
385-
}
388+
func (c *callbacks) SetDriver(d driver) {
389+
c.w.driver = d
386390
}
387391

388392
func (c *callbacks) ProcessFrame(frame *op.Ops, ack chan<- struct{}) {
@@ -550,8 +554,11 @@ func (c *callbacks) Invalidate() {
550554

551555
func (c *callbacks) nextEvent() (event.Event, bool) {
552556
s := &c.w.coalesced
553-
// Every event counts as a wakeup.
554-
defer func() { s.wakeup = false }()
557+
wakeup := s.wakeup
558+
s.wakeup = false
559+
c.w.invMu.Lock()
560+
c.w.mayInvalidate = true
561+
c.w.invMu.Unlock()
555562
switch {
556563
case s.view != nil:
557564
e := *s.view
@@ -561,6 +568,10 @@ func (c *callbacks) nextEvent() (event.Event, bool) {
561568
e := *s.destroy
562569
// Clear pending events after DestroyEvent is delivered.
563570
*s = eventSummary{}
571+
// Don't allow invalidates from now on.
572+
c.w.invMu.Lock()
573+
c.w.mayInvalidate = false
574+
c.w.invMu.Unlock()
564575
return e, true
565576
case s.cfg != nil:
566577
e := *s.cfg
@@ -570,7 +581,7 @@ func (c *callbacks) nextEvent() (event.Event, bool) {
570581
e := *s.frame
571582
s.frame = nil
572583
return e.FrameEvent, true
573-
case s.wakeup:
584+
case wakeup:
574585
return wakeupEvent{}, true
575586
}
576587
return nil, false
@@ -617,7 +628,6 @@ func (w *Window) processEvent(e event.Event) bool {
617628
case DestroyEvent:
618629
w.destroyGPU()
619630
w.driver = nil
620-
w.basic = nil
621631
if q := w.timer.quit; q != nil {
622632
q <- struct{}{}
623633
<-q
@@ -688,10 +698,10 @@ func (w *Window) processEvent(e event.Event) bool {
688698
// [FrameEvent], or until [Invalidate] is called. The window is created
689699
// and shown the first time Event is called.
690700
func (w *Window) Event() event.Event {
691-
if w.basic == nil {
701+
if w.driver == nil {
692702
w.init()
693703
}
694-
return w.basic.Event()
704+
return w.driver.Event()
695705
}
696706

697707
func (w *Window) init() {
@@ -832,7 +842,7 @@ func (w *Window) Perform(actions system.Action) {
832842
if acts == 0 {
833843
return
834844
}
835-
if w.basic == nil {
845+
if w.driver == nil {
836846
w.initialActions = append(w.initialActions, acts)
837847
return
838848
}

0 commit comments

Comments
 (0)