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  }