x backend has an event loop
This commit is contained in:
		
							parent
							
								
									0c5118b59a
								
							
						
					
					
						commit
						c93ca17fe5
					
				| @ -44,7 +44,13 @@ func (application *Application) Run () ( | ||||
| 	if err != nil { return } | ||||
| 	 | ||||
| 	channel = make(chan(Event)) | ||||
| 	application.backend.Run(channel) | ||||
| 	go application.backend.Run(channel) | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Config returns a pointer to the application's configuration. | ||||
| func (application *Application) Config () (config *Config) { | ||||
| 	config = &application.config | ||||
| 	return | ||||
| } | ||||
|  | ||||
							
								
								
									
										111
									
								
								backends/x/x.go
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								backends/x/x.go
									
									
									
									
									
								
							| @ -4,25 +4,49 @@ import "image" | ||||
| 
 | ||||
| import "github.com/jezek/xgbutil" | ||||
| // 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/xgraphics" | ||||
| 
 | ||||
| import "git.tebibyte.media/sashakoshka/stone" | ||||
| 
 | ||||
| type Backend struct { | ||||
| 	connection *xgbutil.Conn | ||||
| 	window     *xwindow.Window | ||||
| 	canvas     *xgraphics.Image | ||||
| 	application *stone.Application | ||||
| 	config      *stone.Config | ||||
| 	connection  *xgbutil.XUtil | ||||
| 	window      *xwindow.Window | ||||
| 	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)) { | ||||
| 	// TODO: setup | ||||
| 	go backend.mainLoop(channel) | ||||
| } | ||||
| 
 | ||||
| func (backend *Backend) mainLoop (channel chan(stone.Event)) { | ||||
| 	backend.channel = channel | ||||
| 	 | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <- backend.ping.before: | ||||
| 			<- backend.ping.after | ||||
| 
 | ||||
| 		case <- backend.ping.quit: | ||||
| 			backend.shutDown() | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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) 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 "time" | ||||
| import "git.tebibyte.media/sashakoshka/stone" | ||||
| // import _ "git.tebibyte.media/sashakoshka/stone/backends/x" | ||||
| import _ "git.tebibyte.media/sashakoshka/stone/backends/x" | ||||
| 
 | ||||
| func main () { | ||||
| 	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