in shiny/driver/x11driver/screen.go [117:246]
func (s *screenImpl) run() {
keyboardChanged := false
for {
ev, err := s.xc.WaitForEvent()
if err != nil {
log.Printf("x11driver: xproto.WaitForEvent: %v", err)
continue
}
noWindowFound := false
switch ev := ev.(type) {
case xproto.DestroyNotifyEvent:
s.mu.Lock()
delete(s.windows, ev.Window)
s.mu.Unlock()
case shm.CompletionEvent:
s.mu.Lock()
s.completionKeys = append(s.completionKeys, ev.Sequence)
s.handleCompletions()
s.mu.Unlock()
case xproto.ClientMessageEvent:
if ev.Type != s.atomWMProtocols || ev.Format != 32 {
break
}
switch xproto.Atom(ev.Data.Data32[0]) {
case s.atomWMDeleteWindow:
if w := s.findWindow(ev.Window); w != nil {
w.lifecycler.SetDead(true)
w.lifecycler.SendEvent(w, nil)
} else {
noWindowFound = true
}
case s.atomWMTakeFocus:
xproto.SetInputFocus(s.xc, xproto.InputFocusParent, ev.Window, xproto.Timestamp(ev.Data.Data32[1]))
}
case xproto.ConfigureNotifyEvent:
if w := s.findWindow(ev.Window); w != nil {
w.handleConfigureNotify(ev)
} else {
noWindowFound = true
}
case xproto.ExposeEvent:
if w := s.findWindow(ev.Window); w != nil {
// A non-zero Count means that there are more expose events
// coming. For example, a non-rectangular exposure (e.g. from a
// partially overlapped window) will result in multiple expose
// events whose dirty rectangles combine to define the dirty
// region. Go's paint events do not provide dirty regions, so
// we only pass on the final X11 expose event.
if ev.Count == 0 {
w.handleExpose()
}
} else {
noWindowFound = true
}
case xproto.FocusInEvent:
if w := s.findWindow(ev.Event); w != nil {
w.lifecycler.SetFocused(true)
w.lifecycler.SendEvent(w, nil)
} else {
noWindowFound = true
}
case xproto.FocusOutEvent:
if w := s.findWindow(ev.Event); w != nil {
w.lifecycler.SetFocused(false)
w.lifecycler.SendEvent(w, nil)
} else {
noWindowFound = true
}
case xproto.KeyPressEvent:
if keyboardChanged {
keyboardChanged = false
s.initKeyboardMapping()
}
if w := s.findWindow(ev.Event); w != nil {
w.handleKey(ev.Detail, ev.State, key.DirPress)
} else {
noWindowFound = true
}
case xproto.KeyReleaseEvent:
if keyboardChanged {
keyboardChanged = false
s.initKeyboardMapping()
}
if w := s.findWindow(ev.Event); w != nil {
w.handleKey(ev.Detail, ev.State, key.DirRelease)
} else {
noWindowFound = true
}
case xproto.ButtonPressEvent:
if w := s.findWindow(ev.Event); w != nil {
w.handleMouse(ev.EventX, ev.EventY, ev.Detail, ev.State, mouse.DirPress)
} else {
noWindowFound = true
}
case xproto.ButtonReleaseEvent:
if w := s.findWindow(ev.Event); w != nil {
w.handleMouse(ev.EventX, ev.EventY, ev.Detail, ev.State, mouse.DirRelease)
} else {
noWindowFound = true
}
case xproto.MotionNotifyEvent:
if w := s.findWindow(ev.Event); w != nil {
w.handleMouse(ev.EventX, ev.EventY, 0, ev.State, mouse.DirNone)
} else {
noWindowFound = true
}
case xproto.MappingNotifyEvent:
if ev.Request == xproto.MappingModifier || ev.Request == xproto.MappingKeyboard {
keyboardChanged = true
}
}
if noWindowFound {
log.Printf("x11driver: no window found for event %T", ev)
}
}
}