redo-event-system #1
@ -44,7 +44,13 @@ func (application *Application) Run () (
 | 
				
			|||||||
	if err != nil { return }
 | 
						if err != nil { return }
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	channel = make(chan(Event))
 | 
						channel = make(chan(Event))
 | 
				
			||||||
	application.backend.Run(channel)
 | 
						go application.backend.Run(channel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Config returns a pointer to the application's configuration.
 | 
				
			||||||
 | 
					func (application *Application) Config () (config *Config) {
 | 
				
			||||||
 | 
						config = &application.config
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										105
									
								
								backends/x/x.go
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								backends/x/x.go
									
									
									
									
									
								
							@ -4,25 +4,49 @@ import "image"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import "github.com/jezek/xgbutil"
 | 
					import "github.com/jezek/xgbutil"
 | 
				
			||||||
// import "github.com/jezek/xgbutil/ewmh"
 | 
					// import "github.com/jezek/xgbutil/ewmh"
 | 
				
			||||||
// import "github.com/jezek/xgbutil/xevent"
 | 
					import "github.com/jezek/xgbutil/xevent"
 | 
				
			||||||
import "github.com/jezek/xgbutil/xwindow"
 | 
					import "github.com/jezek/xgbutil/xwindow"
 | 
				
			||||||
import "github.com/jezek/xgbutil/xgraphics"
 | 
					import "github.com/jezek/xgbutil/xgraphics"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "git.tebibyte.media/sashakoshka/stone"
 | 
					import "git.tebibyte.media/sashakoshka/stone"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Backend struct {
 | 
					type Backend struct {
 | 
				
			||||||
	connection *xgbutil.Conn
 | 
						application *stone.Application
 | 
				
			||||||
 | 
						config      *stone.Config
 | 
				
			||||||
 | 
						connection  *xgbutil.XUtil
 | 
				
			||||||
	window      *xwindow.Window
 | 
						window      *xwindow.Window
 | 
				
			||||||
	canvas      *xgraphics.Image
 | 
						canvas      *xgraphics.Image
 | 
				
			||||||
 | 
						channel     chan(stone.Event)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ping struct {
 | 
				
			||||||
 | 
							before chan(struct { })
 | 
				
			||||||
 | 
							after  chan(struct { })
 | 
				
			||||||
 | 
							quit   chan(struct { })
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						metrics struct {
 | 
				
			||||||
 | 
							cellWidth  int
 | 
				
			||||||
 | 
							cellHeight int
 | 
				
			||||||
 | 
							padding    int
 | 
				
			||||||
 | 
							paddingX   int
 | 
				
			||||||
 | 
							paddingY   int
 | 
				
			||||||
 | 
							descent    int
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (backend *Backend) Run (channel chan(stone.Event)) {
 | 
					func (backend *Backend) Run (channel chan(stone.Event)) {
 | 
				
			||||||
	// TODO: setup
 | 
						backend.channel = channel
 | 
				
			||||||
	go backend.mainLoop(channel)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
func (backend *Backend) mainLoop (channel chan(stone.Event)) {
 | 
						for {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <- backend.ping.before:
 | 
				
			||||||
 | 
								<- backend.ping.after
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case <- backend.ping.quit:
 | 
				
			||||||
 | 
								backend.shutDown()
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (backend *Backend) SetTitle (title string) {
 | 
					func (backend *Backend) SetTitle (title string) {
 | 
				
			||||||
@ -32,3 +56,72 @@ func (backend *Backend) SetTitle (title string) {
 | 
				
			|||||||
func (backend *Backend) SetIcon (icons []image.Image) {
 | 
					func (backend *Backend) SetIcon (icons []image.Image) {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (backend *Backend) shutDown () {
 | 
				
			||||||
 | 
						backend.channel <- stone.EventQuit { }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// calculateWindowSize calculates window bounds based on the internal buffer
 | 
				
			||||||
 | 
					// size.
 | 
				
			||||||
 | 
					func (backend *Backend) calculateWindowSize () (x, y int) {
 | 
				
			||||||
 | 
						width, height := backend.application.Size()
 | 
				
			||||||
 | 
						x =
 | 
				
			||||||
 | 
							width * backend.metrics.cellWidth +
 | 
				
			||||||
 | 
							backend.metrics.padding * 2
 | 
				
			||||||
 | 
						y =
 | 
				
			||||||
 | 
							height * backend.metrics.cellHeight +
 | 
				
			||||||
 | 
							backend.metrics.padding * 2
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// factory instantiates an X backend.
 | 
				
			||||||
 | 
					func factory (application *stone.Application) (output stone.Backend, err error) {
 | 
				
			||||||
 | 
						backend := &Backend {
 | 
				
			||||||
 | 
							application: application,
 | 
				
			||||||
 | 
							config:      application.Config(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// calculate metrics
 | 
				
			||||||
 | 
						// TODO: base these off of font metrics
 | 
				
			||||||
 | 
						backend.metrics.cellWidth  = 8
 | 
				
			||||||
 | 
						backend.metrics.cellHeight = 16
 | 
				
			||||||
 | 
						backend.metrics.padding =
 | 
				
			||||||
 | 
							backend.config.Padding() *
 | 
				
			||||||
 | 
							backend.metrics.cellHeight
 | 
				
			||||||
 | 
						backend.metrics.paddingX = backend.metrics.padding
 | 
				
			||||||
 | 
						backend.metrics.paddingY = backend.metrics.padding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// connect to X
 | 
				
			||||||
 | 
						backend.connection, err = xgbutil.NewConn()
 | 
				
			||||||
 | 
						if err != nil { return }
 | 
				
			||||||
 | 
						backend.window, err = xwindow.Generate(backend.connection)
 | 
				
			||||||
 | 
						if err != nil { return }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// create the window
 | 
				
			||||||
 | 
						windowWidth, windowHeight := backend.calculateWindowSize()
 | 
				
			||||||
 | 
						backend.window.Create (
 | 
				
			||||||
 | 
							backend.connection.RootWin(),
 | 
				
			||||||
 | 
							0, 0, windowWidth, windowHeight,
 | 
				
			||||||
 | 
							0)
 | 
				
			||||||
 | 
						backend.window.Map()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// attatch graceful close handler
 | 
				
			||||||
 | 
						backend.window.WMGracefulClose (func (window *xwindow.Window) {
 | 
				
			||||||
 | 
							backend.window.Destroy()
 | 
				
			||||||
 | 
							backend.shutDown()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// start event loop
 | 
				
			||||||
 | 
						backend.ping.before,
 | 
				
			||||||
 | 
						backend.ping.after,
 | 
				
			||||||
 | 
						backend.ping.quit = xevent.MainPing(backend.connection)
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						output = backend
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// init registers this backend when the program starts.
 | 
				
			||||||
 | 
					func init () {
 | 
				
			||||||
 | 
						stone.RegisterBackend(factory)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ import "os"
 | 
				
			|||||||
import "fmt"
 | 
					import "fmt"
 | 
				
			||||||
import "time"
 | 
					import "time"
 | 
				
			||||||
import "git.tebibyte.media/sashakoshka/stone"
 | 
					import "git.tebibyte.media/sashakoshka/stone"
 | 
				
			||||||
// import _ "git.tebibyte.media/sashakoshka/stone/backends/x"
 | 
					import _ "git.tebibyte.media/sashakoshka/stone/backends/x"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main () {
 | 
					func main () {
 | 
				
			||||||
	application  := &stone.Application { }
 | 
						application  := &stone.Application { }
 | 
				
			||||||
@ -40,51 +40,3 @@ func main () {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// func run (application *stone.Application) {
 | 
					 | 
				
			||||||
	// currentTime := time.Time { }
 | 
					 | 
				
			||||||
	// frameDelay  := time.Second / 2
 | 
					 | 
				
			||||||
	// textBuffer  := ""
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	// for {
 | 
					 | 
				
			||||||
		// typed := application.Typed()
 | 
					 | 
				
			||||||
		// textBuffer += typed
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
		// shouldRender :=
 | 
					 | 
				
			||||||
			// application.Resized() ||
 | 
					 | 
				
			||||||
			// time.Since(currentTime) > frameDelay ||
 | 
					 | 
				
			||||||
			// len(typed) > 0
 | 
					 | 
				
			||||||
			// 
 | 
					 | 
				
			||||||
		// if shouldRender {
 | 
					 | 
				
			||||||
			// currentTime = time.Now()
 | 
					 | 
				
			||||||
// 
 | 
					 | 
				
			||||||
			// application.ResetDot()
 | 
					 | 
				
			||||||
			// fmt.Fprintln(application, "hellorld!")
 | 
					 | 
				
			||||||
// 
 | 
					 | 
				
			||||||
			// hour   := currentTime.Hour()
 | 
					 | 
				
			||||||
			// minute := currentTime.Minute()
 | 
					 | 
				
			||||||
			// second := currentTime.Second()
 | 
					 | 
				
			||||||
// 
 | 
					 | 
				
			||||||
			// application.SetRune(0, 1, rune(hour / 10 + 48))
 | 
					 | 
				
			||||||
			// application.SetRune(1, 1, rune(hour % 10 + 48))
 | 
					 | 
				
			||||||
			// application.SetRune(2, 1, ':')
 | 
					 | 
				
			||||||
			// application.SetRune(3, 1, rune(minute / 10 + 48))
 | 
					 | 
				
			||||||
			// application.SetRune(4, 1, rune(minute % 10 + 48))
 | 
					 | 
				
			||||||
			// application.SetRune(5, 1, ':')
 | 
					 | 
				
			||||||
			// application.SetRune(6, 1, rune(second / 10 + 48))
 | 
					 | 
				
			||||||
			// application.SetRune(7, 1, rune(second % 10 + 48))
 | 
					 | 
				
			||||||
// 
 | 
					 | 
				
			||||||
			// application.Dot.X = 0
 | 
					 | 
				
			||||||
			// application.Dot.Y = 2
 | 
					 | 
				
			||||||
			// fmt.Fprintln(application, textBuffer)
 | 
					 | 
				
			||||||
// 
 | 
					 | 
				
			||||||
		// }
 | 
					 | 
				
			||||||
// 
 | 
					 | 
				
			||||||
		// if application.Pressed(stone.MouseButtonLeft) {
 | 
					 | 
				
			||||||
			// x, y := application.MousePosition()
 | 
					 | 
				
			||||||
			// application.SetRune(x, y, '#')
 | 
					 | 
				
			||||||
		// }
 | 
					 | 
				
			||||||
		// 
 | 
					 | 
				
			||||||
		// if !application.Await(frameDelay) { break }
 | 
					 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user