Applications can now manually call a screen redraw in a way that I think is thread safe
This commit is contained in:
		
							parent
							
								
									ea32b7899b
								
							
						
					
					
						commit
						05c448f058
					
				| @ -46,6 +46,11 @@ func (application *Application) Run () ( | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Draw "commits" changes made in the buffer to the display. | ||||
| func (application *Application) Draw () { | ||||
| 	application.backend.Draw() | ||||
| } | ||||
| 
 | ||||
| // SetTitle sets the application's title. If in a window, it will appear as the | ||||
| // window's name. | ||||
| func (application *Application) SetTitle (title string) (err error) { | ||||
|  | ||||
| @ -7,6 +7,7 @@ type Backend interface { | ||||
| 	Run      (channel chan(Event)) | ||||
| 	SetTitle (title string) (err error) | ||||
| 	SetIcon  (icons []image.Image) (err error) | ||||
| 	Draw     () | ||||
| } | ||||
| 
 | ||||
| type BackendFactory func (application *Application) (backend Backend, err error) | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| package x | ||||
| 
 | ||||
| import "os" | ||||
| import "sync" | ||||
| import "image" | ||||
| import "image/draw" | ||||
| import "golang.org/x/image/font" | ||||
| @ -28,6 +29,8 @@ type Backend struct { | ||||
| 	canvas      *xgraphics.Image | ||||
| 	channel     chan(stone.Event) | ||||
| 
 | ||||
| 	drawLock sync.Mutex | ||||
| 
 | ||||
| 	ping struct { | ||||
| 		before chan(struct { }) | ||||
| 		after  chan(struct { }) | ||||
| @ -80,6 +83,17 @@ func (backend *Backend) Run (channel chan(stone.Event)) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (backend *Backend) Draw () { | ||||
| 	backend.drawLock.Lock() | ||||
| 	defer backend.drawLock.Unlock() | ||||
| 	 | ||||
| 	backend.drawCells(true) | ||||
| 	backend.canvas.XDraw() | ||||
| 	backend.canvas.XPaint(backend.window.Id) | ||||
| 	// FIXME use this instead once it works | ||||
| 	// backend.updateWindowAreas(...) | ||||
| } | ||||
| 
 | ||||
| func (backend *Backend) SetTitle (title string) (err error) { | ||||
| 	err = ewmh.WmNameSet(backend.connection, backend.window.Id, title) | ||||
| 	return | ||||
| @ -191,6 +205,9 @@ func (backend *Backend) calculateWindowSize () (x, y int) { | ||||
| } | ||||
| 
 | ||||
| func (backend *Backend) reallocateCanvas () { | ||||
| 	backend.drawLock.Lock() | ||||
| 	defer backend.drawLock.Unlock() | ||||
| 	 | ||||
| 	if backend.canvas != nil { | ||||
| 		backend.canvas.Destroy() | ||||
| 	} | ||||
|  | ||||
| @ -8,8 +8,11 @@ import _ "image/png" | ||||
| import "git.tebibyte.media/sashakoshka/stone" | ||||
| import _ "git.tebibyte.media/sashakoshka/stone/backends/x" | ||||
| 
 | ||||
| var application = &stone.Application { } | ||||
| var currentTime = time.Time { } | ||||
| var tickPing    = make(chan(struct { })) | ||||
| 
 | ||||
| func main () { | ||||
| 	application  := &stone.Application { } | ||||
| 	application.SetTitle("hellorld") | ||||
| 	application.SetSize(12, 2) | ||||
| 
 | ||||
| @ -29,32 +32,51 @@ func main () { | ||||
| 	channel, err := application.Run() | ||||
| 	if err != nil { panic(err) } | ||||
| 	 | ||||
| 	currentTime := time.Time { } | ||||
| 	redraw() | ||||
| 	application.Draw() | ||||
| 	go tick() | ||||
| 
 | ||||
| 	for { | ||||
| 		event := <- channel | ||||
| 		switch event.(type) { | ||||
| 		case stone.EventQuit: | ||||
| 			os.Exit(0) | ||||
| 		select { | ||||
| 		case <- tickPing: | ||||
| 			redraw() | ||||
| 			application.Draw() | ||||
| 		 | ||||
| 		case event := <- channel: | ||||
| 			switch event.(type) { | ||||
| 			case stone.EventQuit: | ||||
| 				os.Exit(0) | ||||
| 
 | ||||
| 		case stone.EventResize: | ||||
| 			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)) | ||||
| 			case stone.EventResize: | ||||
| 				redraw() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func redraw () { | ||||
| 	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)) | ||||
| } | ||||
| 
 | ||||
| func tick () { | ||||
| 	for { | ||||
| 		tickPing <- struct { } { } | ||||
| 		time.Sleep(time.Second) | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user