diff --git a/ChangeLog.md b/ChangeLog.md
index a5e14b1..e8a5237 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,4 +1,7 @@
+# 0.7.6
+- Now it only redraws the screen when there are changes (like frame draw requests from wayland, mouse movement, etc), reducing CPU usage, and network bandwidth for remote sessions.
+- Moved profiling code behind a build tag to reduce binary size for normal users.
# 0.7.5
- Converted code to entriely go (with a tiny bit of c). THis simplifies the build process and reduces dependencies. This lets us easily port to new platforms like arm64.
diff --git a/Makefile b/Makefile
index 81a9a30..daba74b 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
.DELETE_ON_ERROR:
-bin_name := dist/$(if $(PLATFORM),$(PLATFORM)/,)$(if $(STATIC_BUILD),static,)/term.everything❗mmulet.com-dont_forget_to_chmod_+x_this_file
+bin_name := dist/$(if $(PLATFORM),$(PLATFORM)/,)$(if $(STATIC_BUILD),static,)/$(ARCH_PREFIX)term.everything❗mmulet.com-dont_forget_to_chmod_+x_this_file
protocols_files := $(shell find ./wayland/generate)
diff --git a/Readme.md b/Readme.md
index 5e45c43..728eab4 100755
--- a/Readme.md
+++ b/Readme.md
@@ -4,7 +4,7 @@
@@ -91,7 +91,7 @@ And this isn't even full resolution! Checkout the [full vid in in the discussion
Check out the [help file here](./resources/help.md) for a usage guide on how to use `term.everything❗`
## Contributing
-term.everything❗ is written in developer friendly [Typescript](https://www.typescriptlang.org/) using the [bun](https://bun.com/) engine, with a just a smidge of C++.
+term.everything❗ is written in developer friendly [Go](https://go.dev/), with a just a smidge of C.
See [./Contributing.md](./Contributing.md).
## Legal:
diff --git a/distribute.sh b/distribute.sh
index 26cb0d2..30f84a1 100755
--- a/distribute.sh
+++ b/distribute.sh
@@ -57,7 +57,7 @@ fi
if [ -z "${PLATFORM+x}" ]; then
PLATFORM_ARG=""
else
- PLATFORM_ARG="--platform $PLATFORM -e PLATFORM=$PLATFORM -e MULTI_PLATFORM=1"
+ PLATFORM_ARG="--platform $PLATFORM -e PLATFORM=$PLATFORM -e MULTI_PLATFORM=1 -e ARCH_PREFIX=$ARCH_PREFIX"
fi
$PODMAN run \
diff --git a/main.go b/main.go
index d75f313..f7256b1 100644
--- a/main.go
+++ b/main.go
@@ -1,22 +1,11 @@
package main
import (
- "log"
- "net/http"
- _ "net/http/pprof"
-
"github.com/mmulet/term.everything/termeverything"
)
//go:generate go generate ./wayland
-func init() {
- go func() {
- log.Println("pprof at http://127.0.0.1:6060/debug/pprof/")
- _ = http.ListenAndServe("127.0.0.1:6060", nil)
- }()
-}
-
func main() {
termeverything.MainLoop()
}
diff --git a/resources/HowIDidIt.md b/resources/HowIDidIt.md
index a1e76cc..72e3422 100644
--- a/resources/HowIDidIt.md
+++ b/resources/HowIDidIt.md
@@ -40,7 +40,7 @@ So, this means we can do anything we want, so let's output to the terminal!
I take the output given to us by the client and convert the images to terminal
output, the utf8 characters with ansi escape codes via the [chafa library](https://github.com/hpjansson/chafa/). For input, I take the keyboard and mouse (yes terminals support mice)
-from the stdin. And that's it! Of course, there are about 10K lines of code needed to actually do this in practice, but if you're interested in that I invite you to [check out the source code](../src/).
+from the stdin. And that's it! Of course, there are about 10K lines of code needed to actually do this in practice, but if you're interested in that I invite you to [check out the source code](../termeverything/).
## What else can you do with wayland
I have many other crazy ideas of what else to do custom wayland display server, so stay tuned.
diff --git a/resources/multiplatform.sh b/resources/multiplatform.sh
index 717ed46..b711b32 100755
--- a/resources/multiplatform.sh
+++ b/resources/multiplatform.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-PLATFORM=linux/aarch64 ./distribute.sh
-PLATFORM=linux/amd64 ./distribute.sh
\ No newline at end of file
+PLATFORM=linux/aarch64 ARCH_PREFIX=ARM- ./distribute.sh
+PLATFORM=linux/amd64 ARCH_PREFIX= ./distribute.sh
\ No newline at end of file
diff --git a/termeverything/ParseArgs.go b/termeverything/ParseArgs.go
index 091f0b5..808f79f 100644
--- a/termeverything/ParseArgs.go
+++ b/termeverything/ParseArgs.go
@@ -14,7 +14,7 @@ var helpFile string
//go:embed resources/LICENSES.txt
var licensesFile string
-const version = "0.7.5"
+const version = "0.7.6"
type CommandLineArgs struct {
WaylandDisplayNameArg string
diff --git a/termeverything/TerminalDrawLoop.go b/termeverything/TerminalDrawLoop.go
index ca204ca..feab3ad 100644
--- a/termeverything/TerminalDrawLoop.go
+++ b/termeverything/TerminalDrawLoop.go
@@ -1,6 +1,7 @@
package termeverything
import (
+ "os"
"slices"
"strconv"
"time"
@@ -10,6 +11,18 @@ import (
"github.com/mmulet/term.everything/wayland/protocols"
)
+type FrameInputState struct {
+ KeysPressedThisFrame map[Linux_Event_Codes]bool
+ MouseMoveThisFrame bool
+}
+
+func MakeFrameInputState() FrameInputState {
+ return FrameInputState{
+ KeysPressedThisFrame: make(map[Linux_Event_Codes]bool),
+ MouseMoveThisFrame: false,
+ }
+}
+
type TerminalDrawLoop struct {
VirtualMonitorSize wayland.Size
@@ -42,7 +55,10 @@ type TerminalDrawLoop struct {
StatusLine *Status_Line
- GetClients chan *wayland.Client
+ GetClients chan *wayland.Client
+ FirstDrawDone bool
+ LastDrawSize framebuffertoansi.WinSize
+ FrameInputState FrameInputState
}
func MakeTerminalDrawLoop(desktop_size wayland.Size,
@@ -74,6 +90,7 @@ func MakeTerminalDrawLoop(desktop_size wayland.Size,
StatusLine: MakeStatusLine(),
FrameEvents: frameEvents,
GetClients: make(chan *wayland.Client, 32),
+ FrameInputState: MakeFrameInputState(),
}
if args != nil && args.MaxFrameRate != "" {
if fps, err := strconv.ParseFloat(args.MaxFrameRate, 64); err == nil && fps > 0 {
@@ -98,17 +115,7 @@ func (tw *TerminalDrawLoop) GetAppTitle() *string {
return nil
}
-func (tw *TerminalDrawLoop) DrawToTerminal(start_of_frame float64, status_line string) {
- if tw.MinTerminalTimeSeconds != nil {
- last := 0.0
- if tw.TimeOfLastTerminalDraw != nil {
- last = *tw.TimeOfLastTerminalDraw
- }
- if start_of_frame-last < *tw.MinTerminalTimeSeconds {
- return
- }
- tw.TimeOfLastTerminalDraw = &start_of_frame
- }
+func (tw *TerminalDrawLoop) DrawToTerminal(status_line string) {
// if protocols.DebugRequests {
// fmt.Println("Debugging!!!")
@@ -116,28 +123,25 @@ func (tw *TerminalDrawLoop) DrawToTerminal(start_of_frame float64, status_line s
// fmt.Println("Not debugging.")
// }
- if !protocols.DebugRequests {
- var statusLine *string
- if !tw.HideStatusBar {
- statusLine = &status_line
- }
-
- widthCells, heightCells := tw.DrawState.DrawDesktop(
- tw.Desktop.Buffer,
- tw.VirtualMonitorSize.Width,
- tw.VirtualMonitorSize.Height,
- statusLine,
- )
- tw.SharedRenderedScreenSize.WidthCells = &widthCells
- tw.SharedRenderedScreenSize.HeightCells = &heightCells
+ var statusLine *string
+ if !tw.HideStatusBar {
+ statusLine = &status_line
}
+ widthCells, heightCells := tw.DrawState.DrawDesktop(
+ tw.Desktop.Buffer,
+ tw.VirtualMonitorSize.Width,
+ tw.VirtualMonitorSize.Height,
+ statusLine,
+ )
+ tw.SharedRenderedScreenSize.WidthCells = &widthCells
+ tw.SharedRenderedScreenSize.HeightCells = &heightCells
+
}
func (tw *TerminalDrawLoop) MainLoop() {
- keys_pressed_this_frame := map[Linux_Event_Codes]bool{}
for {
- tw.DrawClients(keys_pressed_this_frame)
+ tw.DrawClients()
timeout := time.After(time.Duration(tw.DesiredFrameTimeSeconds * float64(time.Second)))
for {
@@ -145,9 +149,10 @@ func (tw *TerminalDrawLoop) MainLoop() {
case code := <-tw.FrameEvents:
switch c := code.(type) {
case *KeyCode:
- keys_pressed_this_frame[c.KeyCode] = true
+ tw.FrameInputState.KeysPressedThisFrame[c.KeyCode] = true
case *PointerMove:
tw.StatusLine.UpdateMousePosition(c)
+ tw.FrameInputState.MouseMoveThisFrame = true
case *PointerButtonPress:
tw.StatusLine.HandleTerminalMousePress(true)
case *PointerButtonRelease:
@@ -170,8 +175,8 @@ func (tw *TerminalDrawLoop) MainLoop() {
}
}
-func (tw *TerminalDrawLoop) DrawClients(keys_pressed_this_frame map[Linux_Event_Codes]bool) {
-
+func (tw *TerminalDrawLoop) DrawClients() {
+ defer tw.ResetFrameState()
start_of_frame := float64(time.Now().UnixMilli()) / 1000.0
var delta_time float64
if tw.TimeOfStartOfLastFrame != nil {
@@ -179,12 +184,13 @@ func (tw *TerminalDrawLoop) DrawClients(keys_pressed_this_frame map[Linux_Event_
} else {
delta_time = tw.DesiredFrameTimeSeconds
}
-
+ num_draw_requests := 0
for _, s := range tw.Clients {
for {
select {
case callback_id := <-s.FrameDrawRequests:
protocols.WlCallback_done(s, callback_id, uint32(time.Now().UnixMilli()))
+ num_draw_requests++
default:
goto DoneCallbacks
}
@@ -224,9 +230,11 @@ func (tw *TerminalDrawLoop) DrawClients(keys_pressed_this_frame map[Linux_Event_
tw.Desktop.DrawClients(tw.Clients)
- status_line := tw.StatusLine.Draw(delta_time, tw.GetAppTitle(), keys_pressed_this_frame)
+ status_line := tw.StatusLine.Draw(delta_time, tw.GetAppTitle(), tw.FrameInputState.KeysPressedThisFrame)
- tw.DrawToTerminal(start_of_frame, status_line)
+ if tw.ShouldDrawFrame(start_of_frame, num_draw_requests) {
+ tw.DrawToTerminal(status_line)
+ }
// const draw_time = Date.now();
@@ -239,5 +247,43 @@ func (tw *TerminalDrawLoop) DrawClients(keys_pressed_this_frame map[Linux_Event_
tw.StatusLine.PostFrame(delta_time)
- clear(keys_pressed_this_frame)
+}
+
+func (tw *TerminalDrawLoop) ResetFrameState() {
+ tw.FrameInputState.MouseMoveThisFrame = false
+ clear(tw.FrameInputState.KeysPressedThisFrame)
+}
+
+func (tw *TerminalDrawLoop) ShouldDrawFrame(start_of_frame float64, num_draw_requests int) (should_draw bool) {
+ defer func() {
+ if should_draw {
+ tw.FirstDrawDone = true
+ }
+ }()
+ if tw.MinTerminalTimeSeconds != nil {
+ last := 0.0
+ if tw.TimeOfLastTerminalDraw != nil {
+ last = *tw.TimeOfLastTerminalDraw
+ }
+ if start_of_frame-last < *tw.MinTerminalTimeSeconds {
+ return false
+ }
+ tw.TimeOfLastTerminalDraw = &start_of_frame
+ }
+ if protocols.DebugRequests {
+ return false
+ }
+
+ if winsize, err := framebuffertoansi.GetWinsize(os.Stdout.Fd()); err == nil {
+ defer func() {
+ tw.LastDrawSize = winsize
+ }()
+ if winsize != tw.LastDrawSize {
+ return true
+ }
+ }
+ if num_draw_requests == 0 {
+ return tw.FrameInputState.MouseMoveThisFrame || !tw.FirstDrawDone
+ }
+ return true
}
diff --git a/termeverything/profile.go b/termeverything/profile.go
new file mode 100644
index 0000000..f13b43f
--- /dev/null
+++ b/termeverything/profile.go
@@ -0,0 +1,18 @@
+//go:build profile
+// +build profile
+
+package termeverything
+
+import (
+ _ "net/http/pprof"
+
+ "log"
+ "net/http"
+)
+
+func init() {
+ go func() {
+ log.Println("pprof at http://127.0.0.1:6060/debug/pprof/")
+ _ = http.ListenAndServe("127.0.0.1:6060", nil)
+ }()
+}