forked from joejulian/gio
app: fix racing app.Window.Perform and app.Window.Option
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+46
-22
@@ -54,17 +54,16 @@ type Window struct {
|
|||||||
immediateRedraws chan struct{}
|
immediateRedraws chan struct{}
|
||||||
// scheduledRedraws is sent the most recent delayed redraw time.
|
// scheduledRedraws is sent the most recent delayed redraw time.
|
||||||
scheduledRedraws chan time.Time
|
scheduledRedraws chan time.Time
|
||||||
|
// options are the options waiting to be applied.
|
||||||
|
options chan []Option
|
||||||
|
// actions are the actions waiting to be performed.
|
||||||
|
actions chan system.Action
|
||||||
|
|
||||||
out chan event.Event
|
out chan event.Event
|
||||||
frames chan *op.Ops
|
frames chan *op.Ops
|
||||||
frameAck chan struct{}
|
frameAck chan struct{}
|
||||||
closing bool
|
|
||||||
// dead is closed when the window is destroyed.
|
// dead is closed when the window is destroyed.
|
||||||
dead chan struct{}
|
dead chan struct{}
|
||||||
// options are the options waiting to be applied.
|
|
||||||
options []Option
|
|
||||||
// actions are the actions waiting to be performed.
|
|
||||||
actions system.Action
|
|
||||||
|
|
||||||
stage system.Stage
|
stage system.Stage
|
||||||
animating bool
|
animating bool
|
||||||
@@ -154,6 +153,8 @@ func NewWindow(options ...Option) *Window {
|
|||||||
wakeups: make(chan struct{}, 1),
|
wakeups: make(chan struct{}, 1),
|
||||||
wakeupFuncs: make(chan func()),
|
wakeupFuncs: make(chan func()),
|
||||||
dead: make(chan struct{}),
|
dead: make(chan struct{}),
|
||||||
|
options: make(chan []Option, 1),
|
||||||
|
actions: make(chan system.Action, 1),
|
||||||
nocontext: cnf.CustomRenderer,
|
nocontext: cnf.CustomRenderer,
|
||||||
}
|
}
|
||||||
w.imeState.compose = key.Range{Start: -1, End: -1}
|
w.imeState.compose = key.Range{Start: -1, End: -1}
|
||||||
@@ -333,8 +334,18 @@ func (w *Window) Invalidate() {
|
|||||||
|
|
||||||
// Option applies the options to the window.
|
// Option applies the options to the window.
|
||||||
func (w *Window) Option(opts ...Option) {
|
func (w *Window) Option(opts ...Option) {
|
||||||
w.options = append(w.options, opts...)
|
if len(opts) == 0 {
|
||||||
w.wakeup()
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case old := <-w.options:
|
||||||
|
opts = append(old, opts...)
|
||||||
|
case w.options <- opts:
|
||||||
|
w.wakeup()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadClipboard initiates a read of the clipboard in the form
|
// ReadClipboard initiates a read of the clipboard in the form
|
||||||
@@ -445,19 +456,24 @@ func (c *callbacks) Event(e event.Event) bool {
|
|||||||
c.waitEvents = c.waitEvents[:len(c.waitEvents)-1]
|
c.waitEvents = c.waitEvents[:len(c.waitEvents)-1]
|
||||||
handled = c.w.processEvent(c.d, e)
|
handled = c.w.processEvent(c.d, e)
|
||||||
}
|
}
|
||||||
|
closing := false
|
||||||
if _, iswakeup := e.(wakeupEvent); iswakeup {
|
if _, iswakeup := e.(wakeupEvent); iswakeup {
|
||||||
if len(c.w.options) > 0 {
|
select {
|
||||||
c.d.Configure(c.w.options)
|
case opts := <-c.w.options:
|
||||||
c.w.options = nil
|
c.d.Configure(opts)
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
if c.w.actions != 0 {
|
select {
|
||||||
c.d.Perform(c.w.actions)
|
case acts := <-c.w.actions:
|
||||||
c.w.actions = 0
|
// Pospone closing to last.
|
||||||
|
closing = (acts & system.ActionClose) != 0
|
||||||
|
acts &^= system.ActionClose
|
||||||
|
c.d.Perform(acts)
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.w.updateState(c.d)
|
c.w.updateState(c.d)
|
||||||
if c.w.closing {
|
if closing {
|
||||||
c.w.closing = false
|
|
||||||
c.d.Close()
|
c.d.Close()
|
||||||
}
|
}
|
||||||
return handled
|
return handled
|
||||||
@@ -1008,20 +1024,28 @@ func (w *Window) Perform(actions system.Action) {
|
|||||||
walkActions(actions, func(action system.Action) {
|
walkActions(actions, func(action system.Action) {
|
||||||
switch action {
|
switch action {
|
||||||
case system.ActionMinimize:
|
case system.ActionMinimize:
|
||||||
w.options = append(w.options, Minimized.Option())
|
w.Option(Minimized.Option())
|
||||||
case system.ActionMaximize:
|
case system.ActionMaximize:
|
||||||
w.options = append(w.options, Maximized.Option())
|
w.Option(Maximized.Option())
|
||||||
case system.ActionUnmaximize:
|
case system.ActionUnmaximize:
|
||||||
w.options = append(w.options, Windowed.Option())
|
w.Option(Windowed.Option())
|
||||||
case system.ActionClose:
|
|
||||||
w.closing = true
|
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
actions &^= action
|
actions &^= action
|
||||||
})
|
})
|
||||||
w.actions = w.actions | actions
|
if actions == 0 {
|
||||||
w.wakeup()
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case old := <-w.actions:
|
||||||
|
actions |= old
|
||||||
|
case w.actions <- actions:
|
||||||
|
w.wakeup()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *queue) Events(k event.Tag) []event.Event {
|
func (q *queue) Events(k event.Tag) []event.Event {
|
||||||
|
|||||||
Reference in New Issue
Block a user