github.com/acrespo/mobile@v0.0.0-20190107162257-dc0771356504/app/x11.go (about)

     1  // Copyright 2014 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  // +build linux,!android
     6  
     7  package app
     8  
     9  /*
    10  Simple on-screen app debugging for X11. Not an officially supported
    11  development target for apps, as screens with mice are very different
    12  than screens with touch panels.
    13  */
    14  
    15  /*
    16  #cgo LDFLAGS: -lEGL -lGLESv2 -lX11
    17  
    18  void createWindow(void);
    19  void processEvents(void);
    20  void swapBuffers(void);
    21  */
    22  import "C"
    23  import (
    24  	"runtime"
    25  	"time"
    26  
    27  	"golang.org/x/mobile/event/lifecycle"
    28  	"golang.org/x/mobile/event/paint"
    29  	"golang.org/x/mobile/event/size"
    30  	"golang.org/x/mobile/event/touch"
    31  	"golang.org/x/mobile/geom"
    32  )
    33  
    34  func init() {
    35  	theApp.registerGLViewportFilter()
    36  }
    37  
    38  func main(f func(App)) {
    39  	runtime.LockOSThread()
    40  
    41  	workAvailable := theApp.worker.WorkAvailable()
    42  
    43  	C.createWindow()
    44  
    45  	// TODO: send lifecycle events when e.g. the X11 window is iconified or moved off-screen.
    46  	theApp.sendLifecycle(lifecycle.StageFocused)
    47  
    48  	// TODO: translate X11 expose events to shiny paint events, instead of
    49  	// sending this synthetic paint event as a hack.
    50  	theApp.eventsIn <- paint.Event{}
    51  
    52  	donec := make(chan struct{})
    53  	go func() {
    54  		f(theApp)
    55  		close(donec)
    56  	}()
    57  
    58  	// TODO: can we get the actual vsync signal?
    59  	ticker := time.NewTicker(time.Second / 60)
    60  	defer ticker.Stop()
    61  	var tc <-chan time.Time
    62  
    63  	for {
    64  		select {
    65  		case <-donec:
    66  			return
    67  		case <-workAvailable:
    68  			theApp.worker.DoWork()
    69  		case <-theApp.publish:
    70  			C.swapBuffers()
    71  			tc = ticker.C
    72  		case <-tc:
    73  			tc = nil
    74  			theApp.publishResult <- PublishResult{}
    75  		}
    76  		C.processEvents()
    77  	}
    78  }
    79  
    80  //export onResize
    81  func onResize(w, h int) {
    82  	// TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM
    83  	// is probably the best place to start looking.
    84  	pixelsPerPt := float32(1)
    85  	theApp.eventsIn <- size.Event{
    86  		WidthPx:     w,
    87  		HeightPx:    h,
    88  		WidthPt:     geom.Pt(w),
    89  		HeightPt:    geom.Pt(h),
    90  		PixelsPerPt: pixelsPerPt,
    91  	}
    92  }
    93  
    94  func sendTouch(t touch.Type, x, y float32) {
    95  	theApp.eventsIn <- touch.Event{
    96  		X:        x,
    97  		Y:        y,
    98  		Sequence: 0, // TODO: button??
    99  		Type:     t,
   100  	}
   101  }
   102  
   103  //export onTouchBegin
   104  func onTouchBegin(x, y float32) { sendTouch(touch.TypeBegin, x, y) }
   105  
   106  //export onTouchMove
   107  func onTouchMove(x, y float32) { sendTouch(touch.TypeMove, x, y) }
   108  
   109  //export onTouchEnd
   110  func onTouchEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) }
   111  
   112  var stopped bool
   113  
   114  //export onStop
   115  func onStop() {
   116  	if stopped {
   117  		return
   118  	}
   119  	stopped = true
   120  	theApp.sendLifecycle(lifecycle.StageDead)
   121  	theApp.eventsIn <- stopPumping{}
   122  }