Skip to content

Commit 632a44d

Browse files
committed
app: ignore Invalidate for Windows not yet created
While here, don't overflow the Windows event queue. Fixes: https://todo.sr.ht/~eliasnaur/gio/596 Signed-off-by: Elias Naur <[email protected]>
1 parent 42357a2 commit 632a44d

File tree

6 files changed

+43
-83
lines changed

6 files changed

+43
-83
lines changed

app/os.go

+3-9
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_unix.go

-24
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"errors"
1010
"unsafe"
1111

12-
"gioui.org/io/event"
1312
"gioui.org/io/pointer"
1413
)
1514

@@ -57,35 +56,12 @@ func newWindow(window *callbacks, options []Option) {
5756
errFirst = err
5857
}
5958
}
60-
window.SetDriver(&dummyDriver{
61-
win: window,
62-
wakeups: make(chan event.Event, 1),
63-
})
6459
if errFirst == nil {
6560
errFirst = errors.New("app: no window driver available")
6661
}
6762
window.ProcessEvent(DestroyEvent{Err: errFirst})
6863
}
6964

70-
type dummyDriver struct {
71-
win *callbacks
72-
wakeups chan event.Event
73-
}
74-
75-
func (d *dummyDriver) Event() event.Event {
76-
if e, ok := d.win.nextEvent(); ok {
77-
return e
78-
}
79-
return <-d.wakeups
80-
}
81-
82-
func (d *dummyDriver) Invalidate() {
83-
select {
84-
case d.wakeups <- wakeupEvent{}:
85-
default:
86-
}
87-
}
88-
8965
// xCursor contains mapping from pointer.Cursor to XCursor.
9066
var xCursor = [...]string{
9167
pointer.CursorDefault: "left_ptr",

app/os_wayland.go

+1-11
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

-12
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

-10
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

+39-17
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 mayInvalidate.
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{}) {
@@ -549,9 +553,19 @@ func (c *callbacks) Invalidate() {
549553
}
550554

551555
func (c *callbacks) nextEvent() (event.Event, bool) {
552-
s := &c.w.coalesced
553-
// Every event counts as a wakeup.
554-
defer func() { s.wakeup = false }()
556+
return c.w.nextEvent()
557+
}
558+
559+
func (w *Window) nextEvent() (event.Event, bool) {
560+
s := &w.coalesced
561+
mayInvalidate := true
562+
defer func() {
563+
// Every event counts as a wakeup.
564+
s.wakeup = false
565+
w.invMu.Lock()
566+
defer w.invMu.Unlock()
567+
w.mayInvalidate = mayInvalidate
568+
}()
555569
switch {
556570
case s.view != nil:
557571
e := *s.view
@@ -561,6 +575,7 @@ func (c *callbacks) nextEvent() (event.Event, bool) {
561575
e := *s.destroy
562576
// Clear pending events after DestroyEvent is delivered.
563577
*s = eventSummary{}
578+
mayInvalidate = false
564579
return e, true
565580
case s.cfg != nil:
566581
e := *s.cfg
@@ -573,6 +588,7 @@ func (c *callbacks) nextEvent() (event.Event, bool) {
573588
case s.wakeup:
574589
return wakeupEvent{}, true
575590
}
591+
mayInvalidate = false
576592
return nil, false
577593
}
578594

@@ -617,7 +633,6 @@ func (w *Window) processEvent(e event.Event) bool {
617633
case DestroyEvent:
618634
w.destroyGPU()
619635
w.driver = nil
620-
w.basic = nil
621636
if q := w.timer.quit; q != nil {
622637
q <- struct{}{}
623638
<-q
@@ -688,10 +703,17 @@ func (w *Window) processEvent(e event.Event) bool {
688703
// [FrameEvent], or until [Invalidate] is called. The window is created
689704
// and shown the first time Event is called.
690705
func (w *Window) Event() event.Event {
691-
if w.basic == nil {
706+
if w.driver == nil {
692707
w.init()
693708
}
694-
return w.basic.Event()
709+
if w.driver == nil {
710+
e, ok := w.nextEvent()
711+
if !ok {
712+
panic("window initializion failed without a DestroyEvent")
713+
}
714+
return e
715+
}
716+
return w.driver.Event()
695717
}
696718

697719
func (w *Window) init() {
@@ -832,7 +854,7 @@ func (w *Window) Perform(actions system.Action) {
832854
if acts == 0 {
833855
return
834856
}
835-
if w.basic == nil {
857+
if w.driver == nil {
836858
w.initialActions = append(w.initialActions, acts)
837859
return
838860
}

0 commit comments

Comments
 (0)