github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/shiny/driver/x11driver/window.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x11driver 6 7 // TODO: implement a back buffer. 8 9 import ( 10 "image" 11 "image/color" 12 "image/draw" 13 "sync" 14 15 "github.com/BurntSushi/xgb" 16 "github.com/BurntSushi/xgb/render" 17 "github.com/BurntSushi/xgb/xproto" 18 19 "golang.org/x/exp/shiny/driver/internal/pump" 20 "golang.org/x/exp/shiny/driver/internal/x11key" 21 "golang.org/x/exp/shiny/screen" 22 "golang.org/x/image/math/f64" 23 "golang.org/x/mobile/event/key" 24 "golang.org/x/mobile/event/mouse" 25 "golang.org/x/mobile/event/paint" 26 "golang.org/x/mobile/event/size" 27 "golang.org/x/mobile/geom" 28 ) 29 30 type windowImpl struct { 31 s *screenImpl 32 33 xw xproto.Window 34 xg xproto.Gcontext 35 xp render.Picture 36 37 pump pump.Pump 38 xevents chan xgb.Event 39 40 // This next group of variables are mutable, but are only modified in the 41 // screenImpl.run goroutine. 42 width, height int 43 44 mu sync.Mutex 45 released bool 46 } 47 48 func (w *windowImpl) Events() <-chan interface{} { return w.pump.Events() } 49 func (w *windowImpl) Send(event interface{}) { w.pump.Send(event) } 50 51 func (w *windowImpl) Release() { 52 w.mu.Lock() 53 released := w.released 54 w.released = true 55 w.mu.Unlock() 56 57 if released { 58 return 59 } 60 render.FreePicture(w.s.xc, w.xp) 61 xproto.FreeGC(w.s.xc, w.xg) 62 xproto.DestroyWindow(w.s.xc, w.xw) 63 w.pump.Release() 64 } 65 66 func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { 67 src.(*bufferImpl).upload(w, xproto.Drawable(w.xw), w.xg, w.s.xsi.RootDepth, dp, sr) 68 } 69 70 func (w *windowImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) { 71 fill(w.s.xc, w.xp, dr, src, op) 72 } 73 74 func (w *windowImpl) Draw(src2dst f64.Aff3, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { 75 src.(*textureImpl).draw(w.xp, &src2dst, sr, op, w.width, w.height, opts) 76 } 77 78 func (w *windowImpl) Publish() screen.PublishResult { 79 // TODO. 80 return screen.PublishResult{} 81 } 82 83 func (w *windowImpl) handleConfigureNotify(ev xproto.ConfigureNotifyEvent) { 84 // TODO: lifecycle events. 85 86 newWidth, newHeight := int(ev.Width), int(ev.Height) 87 if w.width == newWidth && w.height == newHeight { 88 return 89 } 90 w.width, w.height = newWidth, newHeight 91 // TODO: don't assume that PixelsPerPt == 1. 92 w.Send(size.Event{ 93 WidthPx: newWidth, 94 HeightPx: newHeight, 95 WidthPt: geom.Pt(newWidth), 96 HeightPt: geom.Pt(newHeight), 97 PixelsPerPt: 1, 98 }) 99 } 100 101 func (w *windowImpl) handleExpose() { 102 w.Send(paint.Event{}) 103 } 104 105 func (w *windowImpl) handleKey(detail xproto.Keycode, state uint16, dir key.Direction) { 106 // The key event's rune depends on whether the shift key is down. 107 unshifted := rune(w.s.keysyms[detail][0]) 108 r := unshifted 109 if state&x11key.ShiftMask != 0 { 110 r = rune(w.s.keysyms[detail][1]) 111 // In X11, a zero xproto.Keysym when shift is down means to use what 112 // the xproto.Keysym is when shift is up. 113 if r == 0 { 114 r = unshifted 115 } 116 } 117 118 // The key event's code is independent of whether the shift key is down. 119 var c key.Code 120 if 0 <= unshifted && unshifted < 0x80 { 121 // TODO: distinguish the regular '2' key and number-pad '2' key (with 122 // Num-Lock). 123 c = x11key.ASCIIKeycodes[unshifted] 124 } else { 125 r, c = -1, x11key.NonUnicodeKeycodes[unshifted] 126 } 127 128 // TODO: Unicode-but-not-ASCII keysyms like the Swiss keyboard's 'รถ'. 129 130 w.Send(key.Event{ 131 Rune: r, 132 Code: c, 133 Modifiers: x11key.KeyModifiers(state), 134 Direction: dir, 135 }) 136 } 137 138 func (w *windowImpl) handleMouse(x, y int16, b xproto.Button, state uint16, dir mouse.Direction) { 139 // TODO: should a mouse.Event have a separate MouseModifiers field, for 140 // which buttons are pressed during a mouse move? 141 w.Send(mouse.Event{ 142 X: float32(x), 143 Y: float32(y), 144 Button: mouse.Button(b), 145 Modifiers: x11key.KeyModifiers(state), 146 Direction: dir, 147 }) 148 }