Merge pull request 'redo-event-system' (#1) from redo-event-system into main
Reviewed-on: #1
This commit is contained in:
		
						commit
						acbf2a3954
					
				| @ -1,6 +1,5 @@ | ||||
| package stone | ||||
| 
 | ||||
| import "time" | ||||
| import "image/color" | ||||
| 
 | ||||
| // Application represents an application. | ||||
| @ -12,12 +11,6 @@ type Application struct { | ||||
| 	config Config | ||||
| } | ||||
| 
 | ||||
| // SetSize sets the application's buffer size. This may or may not change the | ||||
| // size of the window, depending on the backend used. | ||||
| func (application *Application) SetSize (width, height int) { | ||||
| 	application.DamageBuffer.SetSize(width, height) | ||||
| } | ||||
| 
 | ||||
| // SetTitle sets the application's title. If in a window, it will appear as the | ||||
| // window's name. | ||||
| func (application *Application) SetTitle (title string) { | ||||
| @ -25,13 +18,11 @@ func (application *Application) SetTitle (title string) { | ||||
| 	application.backend.SetTitle(title) | ||||
| } | ||||
| 
 | ||||
| // Run initializes the application, and then calls callback. Operations inside | ||||
| // of callback are allowed to interact with the application. Depending on the | ||||
| // backend used, this function may bind to the main thread. | ||||
| func (application *Application) Run ( | ||||
| 	callback func (application *Application), | ||||
| ) ( | ||||
| 	err error, | ||||
| // Run initializes the application, starts it, and then returns a channel that | ||||
| // broadcasts events. If no suitable backend can be found, an error is returned. | ||||
| func (application *Application) Run () ( | ||||
| 	channel chan(Event), | ||||
| 	err     error, | ||||
| ) { | ||||
| 	// default values for certain parameters | ||||
| 	width, height := application.Size() | ||||
| @ -51,72 +42,15 @@ func (application *Application) Run ( | ||||
| 
 | ||||
| 	application.backend, err = instantiateBackend(application) | ||||
| 	if err != nil { return } | ||||
| 	application.backend.Run(callback) | ||||
| 	 | ||||
| 	channel = make(chan(Event)) | ||||
| 	go application.backend.Run(channel) | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Await blocks until an event is recieved, or until the specified timeout has | ||||
| // elapsed. If the timeout is zero, it will wait forever. This function returns | ||||
| // true if the backend is still active, and false if it has closed. | ||||
| func (application *Application) Await (timeout time.Duration) (keepRunning bool) { | ||||
| 	keepRunning = application.backend.Await(timeout) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Poll updates the window and checks for new events. This function returns true | ||||
| // if the backend is still active, and false if it has closed. | ||||
| func (application *Application) Poll () (keepRunning bool) { | ||||
| 	keepRunning = application.backend.Poll() | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Title returns the application's title. | ||||
| func (application *Application) Title () (title string) { | ||||
| 	title = application.title | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Config returns a pointer to the application's configuration. | ||||
| func (application *Application) Config () (config *Config) { | ||||
| 	config = &application.config | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // JustPressed returns true if the specified button is pressed, but was not | ||||
| // pressed the last time events were checked. | ||||
| func (application *Application) JustPressed (button Button) (pressed  bool) { | ||||
| 	pressed = application.backend.JustPressed(button) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // JustReleased returns true if the specified button | ||||
| func (application *Application) JustReleased (button Button) (released bool) { | ||||
| 	released = application.backend.JustReleased(button) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (application *Application) Pressed (button Button) (pressed  bool) { | ||||
| 	pressed = application.backend.Pressed(button) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (application *Application) Repeated (button Button) (repeated bool) { | ||||
| 	repeated = application.backend.Repeated(button) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (application *Application) Typed () (text string) { | ||||
| 	text = application.backend.Typed() | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (application *Application) Resized () (resized bool) { | ||||
| 	resized = application.backend.Resized() | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (application *Application) MousePosition () (x, y int) { | ||||
| 	x, y = application.backend.MousePosition() | ||||
| 	return | ||||
| } | ||||
|  | ||||
							
								
								
									
										16
									
								
								backend.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								backend.go
									
									
									
									
									
								
							| @ -1,20 +1,12 @@ | ||||
| package stone | ||||
| 
 | ||||
| import "time" | ||||
| import "image" | ||||
| import "errors" | ||||
| 
 | ||||
| type Backend interface { | ||||
| 	Run           (callback func (application *Application)) () | ||||
| 	Await         (timeout time.Duration) (keepRunning bool) | ||||
| 	Poll          ()                      (keepRunning bool) | ||||
| 	SetTitle      (title string) | ||||
| 	JustPressed   (button Button) (pressed  bool) | ||||
| 	JustReleased  (button Button) (released bool) | ||||
| 	Pressed       (button Button) (pressed  bool) | ||||
| 	Repeated      (button Button) (repeated bool) | ||||
| 	Typed         () (text    string) | ||||
| 	Resized       () (resized bool) | ||||
| 	MousePosition () (x, y int) | ||||
| 	Run      (channel chan(Event)) | ||||
| 	SetTitle (title string) | ||||
| 	SetIcon  (icons []image.Image) | ||||
| } | ||||
| 
 | ||||
| type BackendFactory func (application *Application) (backend Backend, err error) | ||||
|  | ||||
							
								
								
									
										127
									
								
								backends/x/x.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								backends/x/x.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | ||||
| package x | ||||
| 
 | ||||
| import "image" | ||||
| 
 | ||||
| import "github.com/jezek/xgbutil" | ||||
| // import "github.com/jezek/xgbutil/ewmh" | ||||
| 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 { | ||||
| 	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)) { | ||||
| 	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) { | ||||
| 	 | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										12
									
								
								event.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								event.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| package stone | ||||
| 
 | ||||
| type Event interface { } | ||||
| 
 | ||||
| type EventQuit      struct { } | ||||
| type EventPress     Button | ||||
| type EventRelease   Button | ||||
| type EventResize    struct { } | ||||
| type EventMouseMove struct { | ||||
| 	X int | ||||
| 	Y int | ||||
| } | ||||
| @ -1,31 +1,25 @@ | ||||
| package main | ||||
| 
 | ||||
| import "os" | ||||
| import "fmt" | ||||
| import "time" | ||||
| import "git.tebibyte.media/sashakoshka/stone" | ||||
| import _ "git.tebibyte.media/sashakoshka/stone/backends/pixel" | ||||
| import _ "git.tebibyte.media/sashakoshka/stone/backends/x" | ||||
| 
 | ||||
| func main () { | ||||
| 	application := stone.Application { } | ||||
| 	err := application.Run(run) | ||||
| 	application  := &stone.Application { } | ||||
| 	channel, err := application.Run() | ||||
| 	if err != nil { panic(err) } | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
| 		event := <- channel | ||||
| 		switch event.(type) { | ||||
| 		case stone.EventQuit: | ||||
| 			os.Exit(0) | ||||
| 
 | ||||
| 		case stone.EventResize: | ||||
| 			currentTime = time.Now() | ||||
| 
 | ||||
| 			application.ResetDot() | ||||
| @ -43,18 +37,6 @@ func run (application *stone.Application) { | ||||
| 			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 } | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							| @ -4,14 +4,18 @@ go 1.18 | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/faiface/pixel v0.10.0 | ||||
| 	github.com/jezek/xgbutil v0.0.0-20210302171758-530099784e66 | ||||
| 	golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff | ||||
| ) | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 // indirect | ||||
| 	github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 // indirect | ||||
| 	github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 // indirect | ||||
| 	github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 // indirect | ||||
| 	github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 // indirect | ||||
| 	github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72 // indirect | ||||
| 	github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 // indirect | ||||
| 	github.com/jezek/xgb v1.1.0 // indirect | ||||
| 	github.com/pkg/errors v0.8.1 // indirect | ||||
| ) | ||||
|  | ||||
							
								
								
									
										9
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,3 +1,7 @@ | ||||
| github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 h1:1qlsVAQJXZHsaM8b6OLVo6muQUQd4CwkH/D3fnnbHXA= | ||||
| github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= | ||||
| github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 h1:lTG4HQym5oPKjL7nGs+csTgiDna685ZXjxijkne828g= | ||||
| github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= | ||||
| github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 h1:FvZ0mIGh6b3kOITxUnxS3tLZMh7yEoHo75v3/AgUqg0= | ||||
| @ -12,7 +16,12 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72 h1:b+9H1GAsx5 | ||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | ||||
| github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 h1:THttjeRn1iiz69E875U6gAik8KTWk/JYAHoSVpUxBBI= | ||||
| github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= | ||||
| github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= | ||||
| github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= | ||||
| github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= | ||||
| github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= | ||||
| github.com/jezek/xgbutil v0.0.0-20210302171758-530099784e66 h1:+wPhoJD8EH0/bXipIq8Lc2z477jfox9zkXPCJdhvHj8= | ||||
| github.com/jezek/xgbutil v0.0.0-20210302171758-530099784e66/go.mod h1:KACeV+k6b+aoLTVrrurywEbu3UpqoQcQywj4qX8aQKM= | ||||
| github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | ||||
| github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user