From 8a56135a398e3bf244c3d59b5ae672a11783a178 Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Wed, 6 Mar 2019 13:35:10 +0000 Subject: [PATCH 1/6] Update CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f59944e..8a40976 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @liamg +* @liamg @MaxRis From efb31fd15e5acd8ceffefefe667d23143de86537 Mon Sep 17 00:00:00 2001 From: Michael Herrmann Date: Fri, 22 Mar 2019 17:14:14 +0100 Subject: [PATCH 2/6] Fix windows launcher (#255) * Add Windows launcher The launcher looks at directory "Versions" next to its executable. It finds the latest version and runs the executable in that directory with the same name as itself. For instance: Aminal.exe <- the launcher Versions/ 1.0.0/ Aminal.exe 1.0.1/ Aminal.exe In this example, running the top-level Aminal.exe (the launcher) starts Versions/1.0.1/Aminal.exe. Having a launcher allows Aminal to be updated while it is running. For example, version 1.0.1 could be downloaded without disturbing running instances of Aminal 1.0.0. * Implement a command-line installer for Windows It can be generated with the Make target installer-windows. It requires that you ran Make target launcher-windows before. * Implement Uninstaller for Windows * Codesign Windows auto-update executables * Don't require Admin privileges for Win uninstaller * Remove references to fman * Explain automatic updates in windows.md * Limit installer go packages compilation only to Windows platform * Fix Windows launcher * gofmt for launcher.go --- Makefile | 3 ++- windows/launcher/launcher.go | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 6de5891..deb15d5 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,8 @@ launcher-windows: build-windows if exist "bin\windows\Aminal" rmdir /S /Q "bin\windows\Aminal" mkdir "bin\windows\Aminal\Versions\${VERSION}" go build -o "bin\windows\Aminal\${BINARY}.exe" -ldflags "-H windowsgui" "${GEN_SRC_DIR}\launcher" - copy ${BINARY}-windows-amd64.exe "bin\windows\Aminal\Versions\${VERSION}\${BINARY}.exe" /Y + windres -o aminal.syso aminal.rc + go build -o "bin\windows\Aminal\Versions\${VERSION}\${BINARY}.exe" -ldflags "-H windowsgui" IF "${WINDOWS_CODESIGNING_CERT_PW}"=="" ECHO Environment variable WINDOWS_CODESIGNING_CERT_PW is not defined. & exit 1 signtool sign /f windows\codesigning_certificate.pfx /p "${WINDOWS_CODESIGNING_CERT_PW}" /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp bin\windows\Aminal\${BINARY}.exe signtool sign /f windows\codesigning_certificate.pfx /p "${WINDOWS_CODESIGNING_CERT_PW}" /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /as /fd sha256 /td sha256 bin\windows\Aminal\${BINARY}.exe diff --git a/windows/launcher/launcher.go b/windows/launcher/launcher.go index cd5cc5f..73098d8 100644 --- a/windows/launcher/launcher.go +++ b/windows/launcher/launcher.go @@ -23,10 +23,12 @@ import ( "io/ioutil" "os" "os/exec" + "os/user" "path/filepath" "sort" "strconv" "strings" + "syscall" ) type Version struct { @@ -42,8 +44,23 @@ func main() { versionsDir := filepath.Join(executableDir, "Versions") latestVersion, err := getLatestVersion(versionsDir) check(err) - target := filepath.Join(versionsDir, latestVersion, executableName) - cmd := exec.Command(target, os.Args[1:]...) + usr, err := user.Current() + check(err) + cmd := exec.Command("C:\\Windows\\System32\\cmd.exe", "/C", "start", "Aminal", "/B", executableName) + cmd.Dir = usr.HomeDir + latestVersionDir := filepath.Join(versionsDir, latestVersion) + path, pathSet := os.LookupEnv("PATH") + if pathSet { + path += ";" + latestVersionDir + } else { + path = latestVersionDir + } + cmd.Env = append(os.Environ(), "PATH="+path) + const CREATE_NO_WINDOW = 0x08000000 + cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + CreationFlags: CREATE_NO_WINDOW, + } check(cmd.Start()) } From 7ed70154997b5b216bebdc77e5fc4c611a42f564 Mon Sep 17 00:00:00 2001 From: rrrooommmaaa Date: Sat, 23 Mar 2019 01:30:34 +0300 Subject: [PATCH 3/6] correct handling (ignoring) Privacy Message sequence (ESC ^) (#264) --- terminal/ansi.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/terminal/ansi.go b/terminal/ansi.go index e56f697..ee181ac 100644 --- a/terminal/ansi.go +++ b/terminal/ansi.go @@ -17,6 +17,7 @@ var ansiSequenceMap = map[rune]escapeSequenceHandler{ 'P': sixelHandler, 'c': risHandler, //RIS '#': screenStateHandler, + '^': privacyMessageHandler, '(': scs0Handler, // select character set into G0 ')': scs1Handler, // select character set into G1 '*': swallowHandler(1), // character set bullshit @@ -104,3 +105,24 @@ func tabSetHandler(pty chan rune, terminal *Terminal) error { terminal.terminalState.TabSetAtCursor() return nil } + +func privacyMessageHandler(pty chan rune, terminal *Terminal) error { + // Handler should lock the terminal if there will be write operations to any data read by the renderer + // terminal.Lock() + // defer terminal.Unlock() + + isEscaped := false + for { + b := <-pty + if b == 0x18 /*CAN*/ || b == 0x1a /*SUB*/ || (b == 0x5c /*backslash*/ && isEscaped) { + break + } + if isEscaped { + isEscaped = false + } else if b == 0x1b { + isEscaped = true + continue + } + } + return nil +} From 0e8c0d6a9028ce553fd6a24fe07012313b940367 Mon Sep 17 00:00:00 2001 From: rrrooommmaaa Date: Sat, 23 Mar 2019 01:46:29 +0300 Subject: [PATCH 4/6] Smarter URL/URI parsing (#265) * #205 smarter URL/URI parsing * tidy up --- buffer/buffer.go | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/buffer/buffer.go b/buffer/buffer.go index a362a69..6259cf2 100644 --- a/buffer/buffer.go +++ b/buffer/buffer.go @@ -76,23 +76,13 @@ func (buffer *Buffer) GetURLAtPosition(col uint16, viewRow uint16) string { row := buffer.convertViewLineToRawLine((viewRow)) - uint64(buffer.terminalState.scrollLinesFromBottom) cell := buffer.GetRawCell(col, row) - if cell == nil || cell.Rune() == 0x00 { + if cell == nil || isRuneURLSelectionMarker(cell.Rune()) { return "" } - candidate := "" - - for i := col; i >= uint16(0); i-- { - cell := buffer.GetRawCell(i, row) - if cell == nil { - break - } - if isRuneURLSelectionMarker(cell.Rune()) { - break - } - candidate = fmt.Sprintf("%c%s", cell.Rune(), candidate) - } + candidate := string(cell.Rune()) + // First, move forward for i := col + 1; i < buffer.terminalState.viewWidth; i++ { cell := buffer.GetRawCell(i, row) if cell == nil { @@ -104,6 +94,27 @@ func (buffer *Buffer) GetURLAtPosition(col uint16, viewRow uint16) string { candidate = fmt.Sprintf("%s%c", candidate, cell.Rune()) } + // Move backwards + protocolMode := strings.Contains(candidate, "://") + for i := col - 1; i >= uint16(0); i-- { + cell := buffer.GetRawCell(i, row) + if cell == nil { + break + } + c := cell.Rune() + if isRuneURLSelectionMarker(c) { + break + } + // if we're tracking left of :// we want to break on any non-Latin character + if protocolMode && !(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') { + break + } + candidate = fmt.Sprintf("%c%s", c, candidate) + if !protocolMode && c == ':' { + protocolMode = strings.Contains(candidate, "://") + } + } + if candidate == "" || candidate[0] == '/' { return "" } From 745f7a111cf7adf973313ccf5b79cad4f17d1808 Mon Sep 17 00:00:00 2001 From: rrrooommmaaa Date: Sat, 23 Mar 2019 01:49:00 +0300 Subject: [PATCH 5/6] #116 URXVT extended mouse mode support (#267) --- gui/mouse.go | 7 +++++-- terminal/modes.go | 8 ++++++++ terminal/terminal.go | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/gui/mouse.go b/gui/mouse.go index 19703e9..daff8fc 100644 --- a/gui/mouse.go +++ b/gui/mouse.go @@ -412,13 +412,16 @@ func (gui *GUI) emitButtonEventToTerminal(tx int, ty int, button glfw.MouseButto gui.prevMotionTY = ty var packet string - if ext == terminal.MouseExtSGR { + switch ext { + case terminal.MouseExtSGR: final := 'M' if release { final = 'm' } packet = fmt.Sprintf("\x1b[<%d;%d;%d%c", b, tx, ty, final) - } else { + case terminal.MouseExtURXVT: + packet = fmt.Sprintf("\x1b[%d;%d;%dM", b+32, tx, ty) + default: packet = fmt.Sprintf("\x1b[M%c%c%c", (rune(b + 32)), (rune(tx + 32)), (rune(ty + 32))) } gui.logger.Infof("Sending mouse packet: '%v'", packet) diff --git a/terminal/modes.go b/terminal/modes.go index 3630e44..60a8c1f 100644 --- a/terminal/modes.go +++ b/terminal/modes.go @@ -172,6 +172,14 @@ func csiSetMode(modeStr string, enabled bool, terminal *Terminal) error { terminal.logger.Infof("Turning off SGR ext mouse mode") terminal.SetMouseExtMode(MouseExtNone) } + case "?1015": + if enabled { + terminal.logger.Infof("Turning on URXVT ext mouse mode") + terminal.SetMouseExtMode(MouseExtURXVT) + } else { + terminal.logger.Infof("Turning off URXVT ext mouse mode") + terminal.SetMouseExtMode(MouseExtNone) + } case "?1048": if enabled { terminal.ActiveBuffer().SaveCursor() diff --git a/terminal/terminal.go b/terminal/terminal.go index 170031c..f80210c 100644 --- a/terminal/terminal.go +++ b/terminal/terminal.go @@ -31,6 +31,7 @@ const ( MouseExtNone MouseExtMode = iota MouseExtUTF MouseExtSGR + MouseExtURXVT ) type WindowManipulationInterface interface { From f100fac09ed02e19ac5b88087550ff542deb011f Mon Sep 17 00:00:00 2001 From: nikitar020 <42252263+nikitar020@users.noreply.github.com> Date: Sat, 23 Mar 2019 00:52:18 +0200 Subject: [PATCH 6/6] Improve font rendering performance, eliminate excessive memory usage (#271) --- glfont/font.go | 63 ++++++++++++++++++++++------------------------ glfont/truetype.go | 3 +++ gui/fonts.go | 4 +++ gui/gui.go | 2 +- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/glfont/font.go b/glfont/font.go index 190fd39..ac170c0 100644 --- a/glfont/font.go +++ b/glfont/font.go @@ -17,17 +17,19 @@ const DPI = 72 // A Font allows rendering of text to an OpenGL context. type Font struct { - characters map[rune]*character - vao uint32 - vbo uint32 - program uint32 - texture uint32 // Holds the glyph texture id. - color color - ttf *truetype.Font - ttfFace font.Face - scale float32 - linePadding float32 - lineHeight float32 + characters map[rune]*character + vao uint32 + vbo uint32 + program uint32 + uniformLocationResolution int32 + uniformLocationTextColor int32 + texture uint32 // Holds the glyph texture id. + color color + ttf *truetype.Font + ttfFace font.Face + scale float32 + linePadding float32 + lineHeight float32 } type color struct { @@ -46,15 +48,14 @@ func LoadFont(reader io.Reader, scale float32, windowWidth int, windowHeight int panic(err) } - // Activate corresponding render state - gl.UseProgram(program) + font, err := LoadTrueTypeFont(program, reader, scale) + if err != nil { + return nil, err + } - //set screen resolution - resUniform := gl.GetUniformLocation(program, gl.Str("resolution\x00")) - gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) - gl.UseProgram(0) + font.UpdateResolution(windowWidth, windowHeight) - return LoadTrueTypeFont(program, reader, scale) + return font, nil } func (f *Font) Free() { @@ -82,10 +83,8 @@ func (f *Font) SetColor(red float32, green float32, blue float32, alpha float32) func (f *Font) UpdateResolution(windowWidth int, windowHeight int) { gl.UseProgram(f.program) - resUniform := gl.GetUniformLocation(f.program, gl.Str("resolution\x00")) - gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) + gl.Uniform2f(f.uniformLocationResolution, float32(windowWidth), float32(windowHeight)) gl.UseProgram(0) - //f.characters = map[rune]*character{} } func (f *Font) LineHeight() float32 { @@ -112,13 +111,11 @@ func (f *Font) Print(x, y float32, text string) error { // Activate corresponding render state gl.UseProgram(f.program) //set text color - gl.Uniform4f(gl.GetUniformLocation(f.program, gl.Str("textColor\x00")), f.color.r, f.color.g, f.color.b, f.color.a) - //set screen resolution - //resUniform := gl.GetUniformLocation(f.program, gl.Str("resolution\x00")) - //gl.Uniform2f(resUniform, float32(2560), float32(1440)) + gl.Uniform4f(f.uniformLocationTextColor, f.color.r, f.color.g, f.color.b, f.color.a) gl.ActiveTexture(gl.TEXTURE0) gl.BindVertexArray(f.vao) + gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo) // Iterate through all characters in string for i := range indices { @@ -145,7 +142,7 @@ func (f *Font) Print(x, y float32, text string) error { var y2 = ypos + h //setup quad array - var vertices = []float32{ + var vertices = [...]float32{ // X, Y, Z, U, V // Front x1, y1, 0.0, 0.0, @@ -153,25 +150,24 @@ func (f *Font) Print(x, y float32, text string) error { x1, y2, 0.0, 1.0, x1, y2, 0.0, 1.0, x2, y1, 1.0, 0.0, - x2, y2, 1.0, 1.0} + x2, y2, 1.0, 1.0, + } // Render glyph texture over quad gl.BindTexture(gl.TEXTURE_2D, ch.textureID) - // Update content of VBO memory - gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo) - //BufferSubData(target Enum, offset int, data []byte) - gl.BufferSubData(gl.ARRAY_BUFFER, 0, len(vertices)*4, gl.Ptr(vertices)) // Be sure to use glBufferSubData and not glBufferData + // Update content of VBO memory + gl.NamedBufferSubData(f.vbo, 0, len(vertices)*4, gl.Ptr(&vertices[0])) // Be sure to use glBufferSubData and not glBufferData + // Render quad gl.DrawArrays(gl.TRIANGLES, 0, 24) - gl.BindBuffer(gl.ARRAY_BUFFER, 0) // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) x += float32((ch.advance >> 6)) // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) - } //clear opengl textures and programs + gl.BindBuffer(gl.ARRAY_BUFFER, 0) gl.BindVertexArray(0) gl.BindTexture(gl.TEXTURE_2D, 0) gl.UseProgram(0) @@ -308,6 +304,7 @@ func (f *Font) GetRune(r rune) (*character, error) { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) + gl.BindTexture(gl.TEXTURE_2D, 0) char.textureID = texture diff --git a/glfont/truetype.go b/glfont/truetype.go index 57af926..f713084 100644 --- a/glfont/truetype.go +++ b/glfont/truetype.go @@ -30,6 +30,9 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale float32) (*Font, error) f.scale = scale f.characters = map[rune]*character{} f.program = program //set shader program + f.uniformLocationResolution = gl.GetUniformLocation(program, gl.Str("resolution\x00")) + f.uniformLocationTextColor = gl.GetUniformLocation(program, gl.Str("textColor\x00")) + // Read the truetype font. f.ttf, err = truetype.Parse(data) if err != nil { diff --git a/gui/fonts.go b/gui/fonts.go index 911be0e..ffc663c 100644 --- a/gui/fonts.go +++ b/gui/fonts.go @@ -47,3 +47,7 @@ func (gui *GUI) loadFonts(actualWidth int, actualHeight int) error { return nil } + +func (gui *GUI) updateFontsResolution(actualWidth int, actualHeight int) { + gui.fontMap.UpdateResolution(actualWidth, actualHeight) +} diff --git a/gui/gui.go b/gui/gui.go index b35a8b8..6345762 100644 --- a/gui/gui.go +++ b/gui/gui.go @@ -321,7 +321,7 @@ func (gui *GUI) resize(w *glfw.Window, width int, height int) { } gui.logger.Debugf("Updating font resolutions...") - gui.loadFonts(gui.width, gui.height) + gui.updateFontsResolution(gui.width, gui.height) gui.logger.Debugf("Setting renderer area...") gui.renderer.SetArea(0, 0, gui.width-vScrollbarWidth, gui.height)