Implement automatic tmux passthrough for icat
This commit is contained in:
parent
8bd814444c
commit
defac0c061
@ -40,6 +40,8 @@ Detailed list of changes
|
|||||||
|
|
||||||
- Text rendering: Use sRGB correct linear gamma blending for nicer font rendering and better color accuracy with transparent windows. See the option :opt:`text_composition_strategy` for details. The obsolete :opt:`macos_thicken_font` will make the font too thick and needs to be removed manually if it is configured. (:pull:`5969`)
|
- Text rendering: Use sRGB correct linear gamma blending for nicer font rendering and better color accuracy with transparent windows. See the option :opt:`text_composition_strategy` for details. The obsolete :opt:`macos_thicken_font` will make the font too thick and needs to be removed manually if it is configured. (:pull:`5969`)
|
||||||
|
|
||||||
|
- icat kitten: Support display of images inside tmux (:pull:`5664`)
|
||||||
|
|
||||||
- Graphics protocol: Add support for displaying images inside programs that do not support the protocol such as vim and tmux (:pull:`5664`)
|
- Graphics protocol: Add support for displaying images inside programs that do not support the protocol such as vim and tmux (:pull:`5664`)
|
||||||
|
|
||||||
- Fix a regression in 0.27.0 that broke ``kitty @ set-font-size 0`` (:iss:`5992`)
|
- Fix a regression in 0.27.0 that broke ``kitty @ set-font-size 0`` (:iss:`5992`)
|
||||||
|
|||||||
@ -190,7 +190,17 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.TransferMode == "detect" || opts.DetectSupport {
|
passthrough_mode := no_passthrough
|
||||||
|
switch opts.Passthrough {
|
||||||
|
case "tmux":
|
||||||
|
passthrough_mode = tmux_passthrough
|
||||||
|
case "detect":
|
||||||
|
if tui.TmuxSocketAddress() != "" {
|
||||||
|
passthrough_mode = tmux_passthrough
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if passthrough_mode == no_passthrough && (opts.TransferMode == "detect" || opts.DetectSupport) {
|
||||||
memory, files, direct, err := DetectSupport(time.Duration(opts.DetectionTimeout * float64(time.Second)))
|
memory, files, direct, err := DetectSupport(time.Duration(opts.DetectionTimeout * float64(time.Second)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 1, err
|
return 1, err
|
||||||
@ -210,6 +220,12 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
|
|||||||
transfer_by_file = unsupported
|
transfer_by_file = unsupported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if passthrough_mode != no_passthrough {
|
||||||
|
// tmux doesnt allow responses from the terminal so we cant detect if memory or file based transferring is supported
|
||||||
|
transfer_by_memory = unsupported
|
||||||
|
transfer_by_file = unsupported
|
||||||
|
transfer_by_stream = supported
|
||||||
|
}
|
||||||
if opts.DetectSupport {
|
if opts.DetectSupport {
|
||||||
if transfer_by_memory == supported {
|
if transfer_by_memory == supported {
|
||||||
print_error("memory")
|
print_error("memory")
|
||||||
@ -221,9 +237,13 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
use_unicode_placeholder := opts.UnicodePlaceholder
|
use_unicode_placeholder := opts.UnicodePlaceholder
|
||||||
|
if passthrough_mode != no_passthrough {
|
||||||
|
use_unicode_placeholder = true
|
||||||
|
}
|
||||||
for num_of_items > 0 {
|
for num_of_items > 0 {
|
||||||
imgd := <-output_channel
|
imgd := <-output_channel
|
||||||
imgd.use_unicode_placeholder = use_unicode_placeholder
|
imgd.use_unicode_placeholder = use_unicode_placeholder
|
||||||
|
imgd.passthrough_mode = passthrough_mode
|
||||||
num_of_items--
|
num_of_items--
|
||||||
if imgd.err != nil {
|
if imgd.err != nil {
|
||||||
print_error("Failed to process \x1b[31m%s\x1b[39m: %s\r\n", imgd.source_name, imgd.err)
|
print_error("Failed to process \x1b[31m%s\x1b[39m: %s\r\n", imgd.source_name, imgd.err)
|
||||||
|
|||||||
@ -187,6 +187,7 @@ type image_data struct {
|
|||||||
move_to struct{ x, y int }
|
move_to struct{ x, y int }
|
||||||
width_cells, height_cells int
|
width_cells, height_cells int
|
||||||
use_unicode_placeholder bool
|
use_unicode_placeholder bool
|
||||||
|
passthrough_mode passthrough_type
|
||||||
|
|
||||||
// for error reporting
|
// for error reporting
|
||||||
err error
|
err error
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"kitty/tools/tui"
|
||||||
"kitty/tools/tui/graphics"
|
"kitty/tools/tui/graphics"
|
||||||
"kitty/tools/tui/loop"
|
"kitty/tools/tui/loop"
|
||||||
"kitty/tools/utils"
|
"kitty/tools/utils"
|
||||||
@ -25,8 +26,26 @@ import (
|
|||||||
|
|
||||||
var _ = fmt.Print
|
var _ = fmt.Print
|
||||||
|
|
||||||
func gc_for_image(imgd *image_data, frame_num int, frame *image_frame) *graphics.GraphicsCommand {
|
type passthrough_type int
|
||||||
|
|
||||||
|
const (
|
||||||
|
no_passthrough passthrough_type = iota
|
||||||
|
tmux_passthrough
|
||||||
|
)
|
||||||
|
|
||||||
|
func new_graphics_command(imgd *image_data) *graphics.GraphicsCommand {
|
||||||
gc := graphics.GraphicsCommand{}
|
gc := graphics.GraphicsCommand{}
|
||||||
|
switch imgd.passthrough_mode {
|
||||||
|
case tmux_passthrough:
|
||||||
|
gc.WrapPrefix = "\033Ptmux;"
|
||||||
|
gc.WrapSuffix = "\033\\"
|
||||||
|
gc.EncodeSerializedDataFunc = func(x string) string { return strings.ReplaceAll(x, "\033", "\033\033") }
|
||||||
|
}
|
||||||
|
return &gc
|
||||||
|
}
|
||||||
|
|
||||||
|
func gc_for_image(imgd *image_data, frame_num int, frame *image_frame) *graphics.GraphicsCommand {
|
||||||
|
gc := new_graphics_command(imgd)
|
||||||
gc.SetDataWidth(uint64(frame.width)).SetDataHeight(uint64(frame.height))
|
gc.SetDataWidth(uint64(frame.width)).SetDataHeight(uint64(frame.height))
|
||||||
gc.SetQuiet(graphics.GRT_quiet_silent)
|
gc.SetQuiet(graphics.GRT_quiet_silent)
|
||||||
gc.SetFormat(frame.transmission_format)
|
gc.SetFormat(frame.transmission_format)
|
||||||
@ -63,7 +82,7 @@ func gc_for_image(imgd *image_data, frame_num int, frame *image_frame) *graphics
|
|||||||
}
|
}
|
||||||
gc.SetLeftEdge(uint64(frame.left)).SetTopEdge(uint64(frame.top))
|
gc.SetLeftEdge(uint64(frame.left)).SetTopEdge(uint64(frame.top))
|
||||||
}
|
}
|
||||||
return &gc
|
return gc
|
||||||
}
|
}
|
||||||
|
|
||||||
func transmit_shm(imgd *image_data, frame_num int, frame *image_frame) (err error) {
|
func transmit_shm(imgd *image_data, frame_num int, frame *image_frame) (err error) {
|
||||||
@ -315,6 +334,13 @@ func transmit_image(imgd *image_data) {
|
|||||||
imgd.err = fmt.Errorf("Image too large to be displayed using Unicode placeholders. Maximum size is %dx%d cells", len(images.NumberToDiacritic), len(images.NumberToDiacritic))
|
imgd.err = fmt.Errorf("Image too large to be displayed using Unicode placeholders. Maximum size is %dx%d cells", len(images.NumberToDiacritic), len(images.NumberToDiacritic))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
switch imgd.passthrough_mode {
|
||||||
|
case tmux_passthrough:
|
||||||
|
imgd.err = tui.TmuxAllowPassthrough()
|
||||||
|
if imgd.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
fmt.Print("\r")
|
fmt.Print("\r")
|
||||||
if !imgd.use_unicode_placeholder {
|
if !imgd.use_unicode_placeholder {
|
||||||
if imgd.move_x_by > 0 {
|
if imgd.move_x_by > 0 {
|
||||||
@ -324,7 +350,7 @@ func transmit_image(imgd *image_data) {
|
|||||||
fmt.Printf(loop.MoveCursorToTemplate, imgd.move_to.y, imgd.move_to.x)
|
fmt.Printf(loop.MoveCursorToTemplate, imgd.move_to.y, imgd.move_to.x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame_control_cmd := graphics.GraphicsCommand{}
|
frame_control_cmd := new_graphics_command(imgd)
|
||||||
frame_control_cmd.SetAction(graphics.GRT_action_animate)
|
frame_control_cmd.SetAction(graphics.GRT_action_animate)
|
||||||
if imgd.image_id != 0 {
|
if imgd.image_id != 0 {
|
||||||
frame_control_cmd.SetImageId(imgd.image_id)
|
frame_control_cmd.SetImageId(imgd.image_id)
|
||||||
|
|||||||
@ -467,6 +467,9 @@ type GraphicsCommand struct {
|
|||||||
|
|
||||||
z int32
|
z int32
|
||||||
|
|
||||||
|
WrapPrefix, WrapSuffix string
|
||||||
|
EncodeSerializedDataFunc func(string) string
|
||||||
|
|
||||||
response_message string
|
response_message string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,24 +518,39 @@ func (self GraphicsCommand) String() string {
|
|||||||
return "GraphicsCommand(" + strings.Join(self.serialize_non_default_fields(), ", ") + ")"
|
return "GraphicsCommand(" + strings.Join(self.serialize_non_default_fields(), ", ") + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *GraphicsCommand) WriteMetadata(o io.StringWriter) (err error) {
|
|
||||||
items := self.serialize_non_default_fields()
|
|
||||||
_, err = o.WriteString(strings.Join(items, ","))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *GraphicsCommand) serialize_to(buf io.StringWriter, chunk string) (err error) {
|
func (self *GraphicsCommand) serialize_to(buf io.StringWriter, chunk string) (err error) {
|
||||||
ws := func(s string) {
|
var ws func(string)
|
||||||
_, err = buf.WriteString(s)
|
if self.EncodeSerializedDataFunc == nil {
|
||||||
|
ws = func(s string) {
|
||||||
|
_, err = buf.WriteString(s)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ws = func(s string) {
|
||||||
|
_, err = buf.WriteString(self.EncodeSerializedDataFunc(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.WrapPrefix != "" {
|
||||||
|
_, err = buf.WriteString(self.WrapPrefix)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if self.WrapSuffix != "" {
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
_, err = buf.WriteString(self.WrapSuffix)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ws("\033_G")
|
ws("\033_G")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = self.WriteMetadata(buf)
|
items := self.serialize_non_default_fields()
|
||||||
|
ws(strings.Join(items, ","))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if len(chunk) > 0 {
|
if len(chunk) > 0 {
|
||||||
ws(";")
|
ws(";")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
_, err = buf.WriteString(chunk)
|
ws(chunk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -593,7 +611,9 @@ func (self *GraphicsCommand) WriteWithPayloadTo(o io.StringWriter, payload []byt
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gc = GraphicsCommand{q: self.q, a: self.a}
|
gc = GraphicsCommand{
|
||||||
|
q: self.q, a: self.a, WrapPrefix: self.WrapPrefix, WrapSuffix: self.WrapSuffix,
|
||||||
|
EncodeSerializedDataFunc: self.EncodeSerializedDataFunc}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user