Allow set_background_image to work over SSH

This commit is contained in:
Kovid Goyal 2020-02-01 11:35:12 +05:30
parent eb57d0d431
commit cf1b7c0adb
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 46 additions and 10 deletions

View File

@ -21,6 +21,9 @@ from .tabs import SpecialWindow
from .utils import natsort_ints from .utils import natsort_ints
no_response = object()
class MatchError(ValueError): class MatchError(ValueError):
hide_traceback = True hide_traceback = True
@ -1280,37 +1283,66 @@ How the image should be displayed. The value of configured will use the configur
) )
def cmd_set_background_image(global_opts, opts, args): def cmd_set_background_image(global_opts, opts, args):
''' '''
path: Path to a PNG image data+: Chunk of at most 512 bytes of PNG data, base64 encoded. Must send an empty chunk to indicate end of image.
img_id+: Unique uuid (as string) used for chunking
match: Window to change opacity in match: Window to change opacity in
layout: The image layout layout: The image layout
all: Boolean indicating operate on all windows all: Boolean indicating operate on all windows
configured: Boolean indicating if the configured value should be changed configured: Boolean indicating if the configured value should be changed
''' '''
import imghdr
from uuid import uuid4
from base64 import standard_b64encode
if not args: if not args:
raise SystemExit('Must specify path to PNG image') raise SystemExit('Must specify path to PNG image')
path = args[0] path = args[0]
import imghdr ret = {'match': opts.match, 'configured': opts.configured, 'layout': opts.layout, 'all': opts.all, 'img_id': str(uuid4())}
if imghdr.what(path) != 'png': if imghdr.what(path) != 'png':
raise SystemExit('{} is not a PNG image'.format(path)) raise SystemExit('{} is not a PNG image'.format(path))
return {
'path': path, 'match': opts.match, 'configured': opts.configured, def file_pipe(path):
'layout': opts.layout, 'all': opts.all, with open(path, 'rb') as f:
} while True:
data = f.read(512)
if not data:
break
ret['data'] = standard_b64encode(data).decode('ascii')
yield ret
ret['data'] = ''
yield ret
return file_pipe(path)
def set_background_image(boss, window, payload): def set_background_image(boss, window, payload):
from base64 import standard_b64decode
import tempfile
pg = cmd_set_background_image.payload_get pg = cmd_set_background_image.payload_get
data = pg(payload, 'data')
img_id = pg(payload, 'img_id')
if img_id != set_background_image.current_img_id:
set_background_image.current_img_id = img_id
set_background_image.current_file_obj = tempfile.NamedTemporaryFile()
if data:
set_background_image.current_file_obj.write(standard_b64decode(data))
return no_response
f = set_background_image.current_file_obj
set_background_image.current_file_obj = None
f.flush()
windows = windows_for_payload(boss, window, payload) windows = windows_for_payload(boss, window, payload)
os_windows = tuple({w.os_window_id for w in windows}) os_windows = tuple({w.os_window_id for w in windows})
layout = pg(payload, 'layout') layout = pg(payload, 'layout')
try: try:
if layout: if layout:
set_background_image_impl(pg(payload, 'path'), os_windows, pg(payload, 'configured'), layout) set_background_image_impl(f.name, os_windows, pg(payload, 'configured'), layout)
else: else:
set_background_image_impl(pg(payload, 'path'), os_windows, pg(payload, 'configured')) set_background_image_impl(f.name, os_windows, pg(payload, 'configured'))
except ValueError as err: except ValueError as err:
err.hide_traceback = True err.hide_traceback = True
raise raise
set_background_image.current_img_id = set_background_image.current_file_obj = None
# }}} # }}}

View File

@ -7,11 +7,13 @@ import os
import re import re
import sys import sys
import types import types
from functools import partial
from contextlib import suppress from contextlib import suppress
from functools import partial
from .cli import emph, parse_args from .cli import emph, parse_args
from .cmds import cmap, parse_subcommand_cli from .cmds import (
cmap, no_response as no_response_sentinel, parse_subcommand_cli
)
from .constants import appname, version from .constants import appname, version
from .fast_data_types import read_command_response from .fast_data_types import read_command_response
from .utils import TTYIO, parse_address_spec from .utils import TTYIO, parse_address_spec
@ -34,6 +36,8 @@ def handle_cmd(boss, window, cmd):
if no_response: # don't report errors if --no-response was used if no_response: # don't report errors if --no-response was used
return return
raise raise
if ans is no_response_sentinel:
return
response = {'ok': True} response = {'ok': True}
if ans is not None: if ans is not None:
response['data'] = ans response['data'] = ans