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 | 	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 | // SetTitle sets the application's title. If in a window, it will appear as the | ||||||
| // window's name. | // window's name. | ||||||
| func (application *Application) SetTitle (title string) (err error) { | func (application *Application) SetTitle (title string) (err error) { | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ type Backend interface { | |||||||
| 	Run      (channel chan(Event)) | 	Run      (channel chan(Event)) | ||||||
| 	SetTitle (title string) (err error) | 	SetTitle (title string) (err error) | ||||||
| 	SetIcon  (icons []image.Image) (err error) | 	SetIcon  (icons []image.Image) (err error) | ||||||
|  | 	Draw     () | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type BackendFactory func (application *Application) (backend Backend, err error) | type BackendFactory func (application *Application) (backend Backend, err error) | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package x | package x | ||||||
| 
 | 
 | ||||||
| import "os" | import "os" | ||||||
|  | import "sync" | ||||||
| import "image" | import "image" | ||||||
| import "image/draw" | import "image/draw" | ||||||
| import "golang.org/x/image/font" | import "golang.org/x/image/font" | ||||||
| @ -28,6 +29,8 @@ type Backend struct { | |||||||
| 	canvas      *xgraphics.Image | 	canvas      *xgraphics.Image | ||||||
| 	channel     chan(stone.Event) | 	channel     chan(stone.Event) | ||||||
| 
 | 
 | ||||||
|  | 	drawLock sync.Mutex | ||||||
|  | 
 | ||||||
| 	ping struct { | 	ping struct { | ||||||
| 		before chan(struct { }) | 		before chan(struct { }) | ||||||
| 		after  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) { | func (backend *Backend) SetTitle (title string) (err error) { | ||||||
| 	err = ewmh.WmNameSet(backend.connection, backend.window.Id, title) | 	err = ewmh.WmNameSet(backend.connection, backend.window.Id, title) | ||||||
| 	return | 	return | ||||||
| @ -191,6 +205,9 @@ func (backend *Backend) calculateWindowSize () (x, y int) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (backend *Backend) reallocateCanvas () { | func (backend *Backend) reallocateCanvas () { | ||||||
|  | 	backend.drawLock.Lock() | ||||||
|  | 	defer backend.drawLock.Unlock() | ||||||
|  | 	 | ||||||
| 	if backend.canvas != nil { | 	if backend.canvas != nil { | ||||||
| 		backend.canvas.Destroy() | 		backend.canvas.Destroy() | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -8,8 +8,11 @@ import _ "image/png" | |||||||
| 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" | ||||||
| 
 | 
 | ||||||
|  | var application = &stone.Application { } | ||||||
|  | var currentTime = time.Time { } | ||||||
|  | var tickPing    = make(chan(struct { })) | ||||||
|  | 
 | ||||||
| func main () { | func main () { | ||||||
| 	application  := &stone.Application { } |  | ||||||
| 	application.SetTitle("hellorld") | 	application.SetTitle("hellorld") | ||||||
| 	application.SetSize(12, 2) | 	application.SetSize(12, 2) | ||||||
| 
 | 
 | ||||||
| @ -29,32 +32,51 @@ func main () { | |||||||
| 	channel, err := application.Run() | 	channel, err := application.Run() | ||||||
| 	if err != nil { panic(err) } | 	if err != nil { panic(err) } | ||||||
| 	 | 	 | ||||||
| 	currentTime := time.Time { } | 	redraw() | ||||||
|  | 	application.Draw() | ||||||
|  | 	go tick() | ||||||
| 
 | 
 | ||||||
| 	for { | 	for { | ||||||
| 		event := <- channel | 		select { | ||||||
| 		switch event.(type) { | 		case <- tickPing: | ||||||
| 		case stone.EventQuit: | 			redraw() | ||||||
| 			os.Exit(0) | 			application.Draw() | ||||||
|  | 		 | ||||||
|  | 		case event := <- channel: | ||||||
|  | 			switch event.(type) { | ||||||
|  | 			case stone.EventQuit: | ||||||
|  | 				os.Exit(0) | ||||||
| 
 | 
 | ||||||
| 		case stone.EventResize: | 			case stone.EventResize: | ||||||
| 			currentTime = time.Now() | 				redraw() | ||||||
| 
 | 			} | ||||||
| 			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 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