From 2aa01c58a1dbb520ee59ec2d9da41ba7e3a30420 Mon Sep 17 00:00:00 2001 From: itepechi <72330683+itepechi@users.noreply.github.com> Date: Mon, 25 Oct 2021 06:34:52 +0900 Subject: [PATCH 1/6] Add option `background_image_anchor` to configure bgimage position --- kitty/bgimage_vertex.glsl | 3 ++- kitty/boss.py | 7 ++----- kitty/data-types.h | 1 + kitty/fast_data_types.pyi | 3 ++- kitty/graphics.h | 1 + kitty/options/definition.py | 5 +++++ kitty/options/parse.py | 8 ++++++++ kitty/options/to-c-generated.h | 15 +++++++++++++++ kitty/options/to-c.h | 30 ++++++++++++++++++++++++++++++ kitty/options/types.py | 4 ++++ kitty/rc/set_background_image.py | 11 ++++++++++- kitty/shaders.c | 17 ++++++++++++++++- kitty/state.c | 9 +++++++-- kitty/state.h | 1 + 14 files changed, 104 insertions(+), 11 deletions(-) diff --git a/kitty/bgimage_vertex.glsl b/kitty/bgimage_vertex.glsl index 0b2a41cd0..b66a656db 100644 --- a/kitty/bgimage_vertex.glsl +++ b/kitty/bgimage_vertex.glsl @@ -9,6 +9,7 @@ #define tex_bottom 1 uniform float tiled; +uniform vec2 translate; // [ left, top ] uniform vec4 sizes; // [ window_width, window_height, image_width, image_height ] out vec2 texcoord; @@ -37,6 +38,6 @@ float tiling_factor(int i) { void main() { vec2 tex_coords = tex_map[gl_VertexID]; - texcoord = vec2(tex_coords[0] * tiling_factor(0), tex_coords[1] * tiling_factor(1)); + texcoord = vec2(tex_coords[0] * tiling_factor(0) - translate[0], tex_coords[1] * tiling_factor(1) - translate[1]); gl_Position = vec4(pos_map[gl_VertexID], 0, 1); } diff --git a/kitty/boss.py b/kitty/boss.py index e1121cfbb..0a481fb6a 100755 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1975,11 +1975,8 @@ class Boss: self.choose_entry('Choose an OS window to move the tab to', items, chosen) - def set_background_image(self, path: Optional[str], os_windows: Tuple[int, ...], configured: bool, layout: Optional[str]) -> None: - if layout: - set_background_image(path, os_windows, configured, layout) - else: - set_background_image(path, os_windows, configured) + def set_background_image(self, path: Optional[str], os_windows: Tuple[int, ...], configured: bool, layout: Optional[str], anchor: Optional[str]) -> None: + set_background_image(path, os_windows, configured, layout, anchor) for os_window_id in os_windows: self.default_bg_changed_for(os_window_id) diff --git a/kitty/data-types.h b/kitty/data-types.h index 91cf1f504..a9c558447 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -65,6 +65,7 @@ typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOC typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape; typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn; typedef enum { TILING, SCALED, MIRRORED } BackgroundImageLayout; +typedef enum { NORTHWEST, NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, CENTER } BackgroundImageAnchor; #define MAX_CHILDREN 512 #define BLANK_CHAR 0 diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index e58f1549d..c9468d27c 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -598,7 +598,8 @@ def set_background_image( path: Optional[str], os_window_ids: Tuple[int, ...], configured: bool = True, - layout_name: Optional[str] = None + layout_name: Optional[str] = None, + anchor_name: Optional[str] = None ) -> None: pass diff --git a/kitty/graphics.h b/kitty/graphics.h index 55015e88a..4a25fb739 100644 --- a/kitty/graphics.h +++ b/kitty/graphics.h @@ -66,6 +66,7 @@ typedef struct { unsigned int height, width; uint8_t* bitmap; uint32_t refcnt; + BackgroundImageAnchor anchor; } BackgroundImage; typedef struct { diff --git a/kitty/options/definition.py b/kitty/options/definition.py index ab2c5ba5a..ff95b3127 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1110,6 +1110,11 @@ opt('background_image_layout', 'tiled', long_text='Whether to tile or scale the background image.' ) +opt('background_image_anchor', 'northwest', + choices=('northwest', 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'center'), ctype='bganchor', + long_text='Where to position the background image in the window.' + ) + opt('background_image_linear', 'no', option_type='to_bool', ctype='bool', long_text='When background image is scaled, whether linear interpolation should be used.' diff --git a/kitty/options/parse.py b/kitty/options/parse.py index bd1b7f9a8..97b542609 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -57,6 +57,14 @@ class Parser: def background_image(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['background_image'] = config_or_absolute_path(val) + def background_image_anchor(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: + val = val.lower() + if val not in self.choices_for_background_image_anchor: + raise ValueError(f"The value {val} is not a valid choice for background_image_anchor") + ans["background_image_anchor"] = val + + choices_for_background_image_anchor = frozenset(('northwest', 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'center')) + def background_image_layout(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: val = val.lower() if val not in self.choices_for_background_image_layout: diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h index 6e26952f7..348e1a257 100644 --- a/kitty/options/to-c-generated.h +++ b/kitty/options/to-c-generated.h @@ -694,6 +694,19 @@ convert_from_opts_background_image_layout(PyObject *py_opts, Options *opts) { Py_DECREF(ret); } +static void +convert_from_python_background_image_anchor(PyObject *val, Options *opts) { + opts->background_image_anchor = bganchor(val); +} + +static void +convert_from_opts_background_image_anchor(PyObject *py_opts, Options *opts) { + PyObject *ret = PyObject_GetAttrString(py_opts, "background_image_anchor"); + if (ret == NULL) return; + convert_from_python_background_image_anchor(ret, opts); + Py_DECREF(ret); +} + static void convert_from_python_background_image_linear(PyObject *val, Options *opts) { opts->background_image_linear = PyObject_IsTrue(val); @@ -1049,6 +1062,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) { if (PyErr_Occurred()) return false; convert_from_opts_background_image_layout(py_opts, opts); if (PyErr_Occurred()) return false; + convert_from_opts_background_image_anchor(py_opts, opts); + if (PyErr_Occurred()) return false; convert_from_opts_background_image_linear(py_opts, opts); if (PyErr_Occurred()) return false; convert_from_opts_dynamic_background_opacity(py_opts, opts); diff --git a/kitty/options/to-c.h b/kitty/options/to-c.h index cbbd84334..5e9e41ff3 100644 --- a/kitty/options/to-c.h +++ b/kitty/options/to-c.h @@ -77,6 +77,36 @@ bglayout(PyObject *layout_name) { return TILING; } +static BackgroundImageAnchor +bganchor(PyObject *anchor_name) { + const char *name = PyUnicode_AsUTF8(anchor_name); + if (strcmp(name, "north") == 0) { + return NORTH; + } + else if (strcmp(name, "northeast") == 0) { + return NORTHEAST; + } + else if (strcmp(name, "east") == 0) { + return EAST; + } + else if (strcmp(name, "southeast") == 0) { + return SOUTHEAST; + } + else if (strcmp(name, "south") == 0) { + return SOUTH; + } + else if (strcmp(name, "southwest") == 0) { + return SOUTHWEST; + } + else if (strcmp(name, "west") == 0) { + return WEST; + } + else if (strcmp(name, "center") == 0) { + return CENTER; + } + return NORTHWEST; +} + #define STR_SETTER(name) { \ free(opts->name); opts->name = NULL; \ if (src == Py_None || !PyUnicode_Check(src)) return; \ diff --git a/kitty/options/types.py b/kitty/options/types.py index a0b832312..595468e2e 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -14,6 +14,7 @@ from kitty.types import FloatEdges, SingleKey import kitty.types if typing.TYPE_CHECKING: + choices_for_background_image_anchor = typing.Literal['northwest', 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'center'] choices_for_background_image_layout = typing.Literal['mirror-tiled', 'scaled', 'tiled'] choices_for_default_pointer_shape = typing.Literal['arrow', 'beam', 'hand'] choices_for_linux_display_server = typing.Literal['auto', 'wayland', 'x11'] @@ -27,6 +28,7 @@ if typing.TYPE_CHECKING: choices_for_tab_powerline_style = typing.Literal['angled', 'round', 'slanted'] choices_for_tab_switch_strategy = typing.Literal['last', 'left', 'previous', 'right'] else: + choices_for_background_image_anchor = str choices_for_background_image_layout = str choices_for_default_pointer_shape = str choices_for_linux_display_server = str @@ -53,6 +55,7 @@ option_names = ( # {{{ 'allow_remote_control', 'background', 'background_image', + 'background_image_anchor', 'background_image_layout', 'background_image_linear', 'background_opacity', @@ -453,6 +456,7 @@ class Options: allow_remote_control: str = 'n' background: Color = Color(0, 0, 0) background_image: typing.Optional[str] = None + background_image_anchor: choices_for_background_image_anchor = 'northwest' background_image_layout: choices_for_background_image_layout = 'tiled' background_image_linear: bool = False background_opacity: float = 1.0 diff --git a/kitty/rc/set_background_image.py b/kitty/rc/set_background_image.py index 9d7c4dfe4..7eb41961b 100644 --- a/kitty/rc/set_background_image.py +++ b/kitty/rc/set_background_image.py @@ -24,6 +24,7 @@ class SetBackgroundImage(RemoteCommand): img_id+: Unique uuid (as string) used for chunking match: Window to change opacity in layout: The image layout + anchor: The image anchor all: Boolean indicating operate on all windows configured: Boolean indicating if the configured value should be changed ''' @@ -52,6 +53,12 @@ choices=tiled,scaled,mirror-tiled,configured How the image should be displayed. The value of configured will use the configured value. +--anchor +type=choices +choices=northwest,north,northeast,east,southeast,south,southwest,west,northwest,north,center,configured +Where the image should be positioned. The value of configured will use the configured value. + + --no-response type=bool-set default=false @@ -74,6 +81,7 @@ failed, the command will exit with a success code. 'match': opts.match, 'configured': opts.configured, 'layout': opts.layout, + 'anchor': opts.anchor, 'all': opts.all, 'img_id': str(uuid4()) } @@ -110,6 +118,7 @@ failed, the command will exit with a success code. windows = self.windows_for_payload(boss, window, payload_get) os_windows = tuple({w.os_window_id for w in windows}) layout = payload_get('layout') + anchor = payload_get('anchor') if data == '-': path = None else: @@ -120,7 +129,7 @@ failed, the command will exit with a success code. f.flush() try: - boss.set_background_image(path, os_windows, payload_get('configured'), layout) + boss.set_background_image(path, os_windows, payload_get('configured'), layout, anchor) except ValueError as err: err.hide_traceback = True # type: ignore raise diff --git a/kitty/shaders.c b/kitty/shaders.c index 598ed91fc..78f0219e0 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -166,7 +166,7 @@ typedef struct { static CellProgramLayout cell_program_layouts[NUM_PROGRAMS]; static ssize_t blit_vertex_array; typedef struct { - GLint image_location, tiled_location, sizes_location, opacity_location, premult_location; + GLint image_location, tiled_location, translate_location, sizes_location, opacity_location, premult_location; } BGImageProgramLayout; static BGImageProgramLayout bgimage_program_layout = {0}; typedef struct { @@ -199,6 +199,7 @@ init_cell_program(void) { bgimage_program_layout.opacity_location = get_uniform_location(BGIMAGE_PROGRAM, "opacity"); bgimage_program_layout.sizes_location = get_uniform_location(BGIMAGE_PROGRAM, "sizes"); bgimage_program_layout.tiled_location = get_uniform_location(BGIMAGE_PROGRAM, "tiled"); + bgimage_program_layout.translate_location = get_uniform_location(BGIMAGE_PROGRAM, "translate"); bgimage_program_layout.premult_location = get_uniform_location(BGIMAGE_PROGRAM, "premult"); tint_program_layout.tint_color_location = get_uniform_location(TINT_PROGRAM, "tint_color"); tint_program_layout.edges_location = get_uniform_location(TINT_PROGRAM, "edges"); @@ -415,6 +416,20 @@ draw_bg(OSWindow *w) { glUniform1f(bgimage_program_layout.tiled_location, tiled); bgimage_constants_set = true; } + float translate_left = 0.0f, translate_top = 0.0f; + if (OPT(background_image_layout) != SCALED) { + if (w->bgimage->anchor == NORTH || w->bgimage->anchor == CENTER || w->bgimage->anchor == SOUTH) { + translate_left = ((float)w->window_width / 2.0f - (float)w->bgimage->width / 2.0f) / (float)w->bgimage->width; + } else if (w->bgimage->anchor == NORTHEAST || w->bgimage->anchor == EAST || w->bgimage->anchor == SOUTHEAST) { + translate_left = ((float)w->window_width - (float)w->bgimage->width) / (float)w->bgimage->width; + } + if (w->bgimage->anchor == WEST || w->bgimage->anchor == CENTER || w->bgimage->anchor == EAST) { + translate_top = ((float)w->window_height / 2.0f - (float)w->bgimage->height / 2.0f) / (float)w->bgimage->height; + } else if (w->bgimage->anchor == SOUTHWEST || w->bgimage->anchor == SOUTH || w->bgimage->anchor == SOUTHEAST) { + translate_top = ((float)w->window_height - (float)w->bgimage->height) / (float)w->bgimage->height; + } + } + glUniform2f(bgimage_program_layout.translate_location, (GLfloat)translate_left, (GLfloat)translate_top); glUniform4f(bgimage_program_layout.sizes_location, (GLfloat)w->window_width, (GLfloat)w->window_height, (GLfloat)w->bgimage->width, (GLfloat)w->bgimage->height); glUniform1f(bgimage_program_layout.premult_location, w->is_semi_transparent ? 1.f : 0.f); diff --git a/kitty/state.c b/kitty/state.c index 49264d291..9de2462ec 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -180,6 +180,7 @@ add_os_window() { global_state.bgimage = calloc(1, sizeof(BackgroundImage)); if (!global_state.bgimage) fatal("Out of memory allocating the global bg image object"); global_state.bgimage->refcnt++; + global_state.bgimage->anchor = OPT(background_image_anchor); size_t size; if (png_path_to_bitmap(OPT(background_image), &global_state.bgimage->bitmap, &global_state.bgimage->width, &global_state.bgimage->height, &size)) { send_bgimage_to_gpu(OPT(background_image_layout), global_state.bgimage); @@ -961,11 +962,13 @@ static PyObject* pyset_background_image(PyObject *self UNUSED, PyObject *args) { const char *path; PyObject *layout_name = NULL; + PyObject *anchor_name = NULL; PyObject *os_window_ids; int configured = 0; - PA("zO!|pU", &path, &PyTuple_Type, &os_window_ids, &configured, &layout_name); + PA("zO!|pOO", &path, &PyTuple_Type, &os_window_ids, &configured, &layout_name, &anchor_name); size_t size; - BackgroundImageLayout layout = layout_name ? bglayout(layout_name) : OPT(background_image_layout); + BackgroundImageLayout layout = PyUnicode_Check(layout_name) ? bglayout(layout_name) : OPT(background_image_layout); + BackgroundImageAnchor anchor = PyUnicode_Check(anchor_name) ? bganchor(anchor_name) : OPT(background_image_anchor); BackgroundImage *bgimage = NULL; if (path) { bgimage = calloc(1, sizeof(BackgroundImage)); @@ -983,6 +986,7 @@ pyset_background_image(PyObject *self UNUSED, PyObject *args) { global_state.bgimage = bgimage; if (bgimage) bgimage->refcnt++; OPT(background_image_layout) = layout; + OPT(background_image_anchor) = anchor; } for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(os_window_ids); i++) { id_type os_window_id = PyLong_AsUnsignedLongLong(PyTuple_GET_ITEM(os_window_ids, i)); @@ -990,6 +994,7 @@ pyset_background_image(PyObject *self UNUSED, PyObject *args) { make_os_window_context_current(os_window); free_bgimage(&os_window->bgimage, true); os_window->bgimage = bgimage; + os_window->bgimage->anchor = anchor; os_window->render_calls = 0; if (bgimage) bgimage->refcnt++; END_WITH_OS_WINDOW diff --git a/kitty/state.h b/kitty/state.h index 0f05ff719..9780bb214 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -47,6 +47,7 @@ typedef struct { char* background_image; BackgroundImageLayout background_image_layout; + BackgroundImageAnchor background_image_anchor; bool background_image_linear; float background_tint; From cae31ab336ca523fce072141dd09e1f00d2b27eb Mon Sep 17 00:00:00 2001 From: itepechi <72330683+itepechi@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:06:00 +0900 Subject: [PATCH 2/6] Read/Write bganchor directly from the options' state Slight performance improvement, maybe? Also, `kitty/graphics.h` has been reverted to the original version; this version would be better in that aspect too. --- kitty/graphics.h | 1 - kitty/shaders.c | 10 +++++----- kitty/state.c | 2 -- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/kitty/graphics.h b/kitty/graphics.h index 4a25fb739..55015e88a 100644 --- a/kitty/graphics.h +++ b/kitty/graphics.h @@ -66,7 +66,6 @@ typedef struct { unsigned int height, width; uint8_t* bitmap; uint32_t refcnt; - BackgroundImageAnchor anchor; } BackgroundImage; typedef struct { diff --git a/kitty/shaders.c b/kitty/shaders.c index 78f0219e0..9c3ce2e5b 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -417,15 +417,15 @@ draw_bg(OSWindow *w) { bgimage_constants_set = true; } float translate_left = 0.0f, translate_top = 0.0f; - if (OPT(background_image_layout) != SCALED) { - if (w->bgimage->anchor == NORTH || w->bgimage->anchor == CENTER || w->bgimage->anchor == SOUTH) { + if (OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED) { + if (OPT(background_image_anchor) == NORTH || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == SOUTH) { translate_left = ((float)w->window_width / 2.0f - (float)w->bgimage->width / 2.0f) / (float)w->bgimage->width; - } else if (w->bgimage->anchor == NORTHEAST || w->bgimage->anchor == EAST || w->bgimage->anchor == SOUTHEAST) { + } else if (OPT(background_image_anchor) == NORTHEAST || OPT(background_image_anchor) == EAST || OPT(background_image_anchor) == SOUTHEAST) { translate_left = ((float)w->window_width - (float)w->bgimage->width) / (float)w->bgimage->width; } - if (w->bgimage->anchor == WEST || w->bgimage->anchor == CENTER || w->bgimage->anchor == EAST) { + if (OPT(background_image_anchor) == WEST || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == EAST) { translate_top = ((float)w->window_height / 2.0f - (float)w->bgimage->height / 2.0f) / (float)w->bgimage->height; - } else if (w->bgimage->anchor == SOUTHWEST || w->bgimage->anchor == SOUTH || w->bgimage->anchor == SOUTHEAST) { + } else if (OPT(background_image_anchor) == SOUTHWEST || OPT(background_image_anchor) == SOUTH || OPT(background_image_anchor) == SOUTHEAST) { translate_top = ((float)w->window_height - (float)w->bgimage->height) / (float)w->bgimage->height; } } diff --git a/kitty/state.c b/kitty/state.c index 9de2462ec..b1243971d 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -180,7 +180,6 @@ add_os_window() { global_state.bgimage = calloc(1, sizeof(BackgroundImage)); if (!global_state.bgimage) fatal("Out of memory allocating the global bg image object"); global_state.bgimage->refcnt++; - global_state.bgimage->anchor = OPT(background_image_anchor); size_t size; if (png_path_to_bitmap(OPT(background_image), &global_state.bgimage->bitmap, &global_state.bgimage->width, &global_state.bgimage->height, &size)) { send_bgimage_to_gpu(OPT(background_image_layout), global_state.bgimage); @@ -994,7 +993,6 @@ pyset_background_image(PyObject *self UNUSED, PyObject *args) { make_os_window_context_current(os_window); free_bgimage(&os_window->bgimage, true); os_window->bgimage = bgimage; - os_window->bgimage->anchor = anchor; os_window->render_calls = 0; if (bgimage) bgimage->refcnt++; END_WITH_OS_WINDOW From 86d7aaa03a6440c1e9fe2d4f186684ee2a474748 Mon Sep 17 00:00:00 2001 From: itepechi <72330683+itepechi@users.noreply.github.com> Date: Tue, 26 Oct 2021 03:18:36 +0900 Subject: [PATCH 3/6] Add `clamped` to option `background_image_layout` --- kitty/bgimage_vertex.glsl | 12 ++++-------- kitty/data-types.h | 2 +- kitty/options/definition.py | 4 ++-- kitty/options/parse.py | 2 +- kitty/options/to-c.h | 1 + kitty/options/types.py | 2 +- kitty/rc/set_background_image.py | 2 +- kitty/shaders.c | 10 +++++----- kitty/state.c | 1 + 9 files changed, 17 insertions(+), 19 deletions(-) diff --git a/kitty/bgimage_vertex.glsl b/kitty/bgimage_vertex.glsl index b66a656db..c6f0f7433 100644 --- a/kitty/bgimage_vertex.glsl +++ b/kitty/bgimage_vertex.glsl @@ -8,7 +8,7 @@ #define tex_right 1 #define tex_bottom 1 -uniform float tiled; +uniform float unscaled; uniform vec2 translate; // [ left, top ] uniform vec4 sizes; // [ window_width, window_height, image_width, image_height ] @@ -28,16 +28,12 @@ const vec2 tex_map[] = vec2[4]( ); -float scale_factor(float window, float image) { - return window / image; -} - -float tiling_factor(int i) { - return tiled * scale_factor(sizes[i], sizes[i + 2]) + (1 - tiled); +float unscaling_factor(int i) { + return unscaled * (sizes[i] / sizes[i + 2]) + (1 - unscaled); } void main() { vec2 tex_coords = tex_map[gl_VertexID]; - texcoord = vec2(tex_coords[0] * tiling_factor(0) - translate[0], tex_coords[1] * tiling_factor(1) - translate[1]); + texcoord = vec2(tex_coords[0] * unscaling_factor(0) - translate[0], tex_coords[1] * unscaling_factor(1) - translate[1]); gl_Position = vec4(pos_map[gl_VertexID], 0, 1); } diff --git a/kitty/data-types.h b/kitty/data-types.h index a9c558447..b7845659f 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -64,7 +64,7 @@ typedef enum MouseTrackingModes { NO_TRACKING, BUTTON_MODE, MOTION_MODE, ANY_MOD typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL, SGR_PIXEL_PROTOCOL} MouseTrackingProtocol; typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape; typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn; -typedef enum { TILING, SCALED, MIRRORED } BackgroundImageLayout; +typedef enum { TILING, SCALED, MIRRORED, CLAMPED } BackgroundImageLayout; typedef enum { NORTHWEST, NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, CENTER } BackgroundImageAnchor; #define MAX_CHILDREN 512 diff --git a/kitty/options/definition.py b/kitty/options/definition.py index ff95b3127..8c4a65bf4 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1106,8 +1106,8 @@ opt('background_image', 'none', ) opt('background_image_layout', 'tiled', - choices=('mirror-tiled', 'scaled', 'tiled'), ctype='bglayout', - long_text='Whether to tile or scale the background image.' + choices=('mirror-tiled', 'scaled', 'tiled', 'clamped'), ctype='bglayout', + long_text='Whether to tile, scale or clamp the background image.' ) opt('background_image_anchor', 'northwest', diff --git a/kitty/options/parse.py b/kitty/options/parse.py index 97b542609..c8aae2ead 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -71,7 +71,7 @@ class Parser: raise ValueError(f"The value {val} is not a valid choice for background_image_layout") ans["background_image_layout"] = val - choices_for_background_image_layout = frozenset(('mirror-tiled', 'scaled', 'tiled')) + choices_for_background_image_layout = frozenset(('mirror-tiled', 'scaled', 'tiled', 'clamped')) def background_image_linear(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['background_image_linear'] = to_bool(val) diff --git a/kitty/options/to-c.h b/kitty/options/to-c.h index 5e9e41ff3..7e9c7bbf7 100644 --- a/kitty/options/to-c.h +++ b/kitty/options/to-c.h @@ -72,6 +72,7 @@ bglayout(PyObject *layout_name) { case 't': return TILING; case 'm': return MIRRORED; case 's': return SCALED; + case 'c': return CLAMPED; default: break; } return TILING; diff --git a/kitty/options/types.py b/kitty/options/types.py index 595468e2e..885157b87 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -15,7 +15,7 @@ import kitty.types if typing.TYPE_CHECKING: choices_for_background_image_anchor = typing.Literal['northwest', 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'center'] - choices_for_background_image_layout = typing.Literal['mirror-tiled', 'scaled', 'tiled'] + choices_for_background_image_layout = typing.Literal['mirror-tiled', 'scaled', 'tiled', 'clamped'] choices_for_default_pointer_shape = typing.Literal['arrow', 'beam', 'hand'] choices_for_linux_display_server = typing.Literal['auto', 'wayland', 'x11'] choices_for_macos_show_window_title_in = typing.Literal['all', 'menubar', 'none', 'window'] diff --git a/kitty/rc/set_background_image.py b/kitty/rc/set_background_image.py index 7eb41961b..57390c848 100644 --- a/kitty/rc/set_background_image.py +++ b/kitty/rc/set_background_image.py @@ -49,7 +49,7 @@ Change the configured background image which is used for new OS windows. --layout type=choices -choices=tiled,scaled,mirror-tiled,configured +choices=tiled,scaled,mirror-tiled,clamped,configured How the image should be displayed. The value of configured will use the configured value. diff --git a/kitty/shaders.c b/kitty/shaders.c index 9c3ce2e5b..05c03abb9 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -166,7 +166,7 @@ typedef struct { static CellProgramLayout cell_program_layouts[NUM_PROGRAMS]; static ssize_t blit_vertex_array; typedef struct { - GLint image_location, tiled_location, translate_location, sizes_location, opacity_location, premult_location; + GLint image_location, unscaled_location, translate_location, sizes_location, opacity_location, premult_location; } BGImageProgramLayout; static BGImageProgramLayout bgimage_program_layout = {0}; typedef struct { @@ -198,7 +198,7 @@ init_cell_program(void) { bgimage_program_layout.image_location = get_uniform_location(BGIMAGE_PROGRAM, "image"); bgimage_program_layout.opacity_location = get_uniform_location(BGIMAGE_PROGRAM, "opacity"); bgimage_program_layout.sizes_location = get_uniform_location(BGIMAGE_PROGRAM, "sizes"); - bgimage_program_layout.tiled_location = get_uniform_location(BGIMAGE_PROGRAM, "tiled"); + bgimage_program_layout.unscaled_location = get_uniform_location(BGIMAGE_PROGRAM, "unscaled"); bgimage_program_layout.translate_location = get_uniform_location(BGIMAGE_PROGRAM, "translate"); bgimage_program_layout.premult_location = get_uniform_location(BGIMAGE_PROGRAM, "premult"); tint_program_layout.tint_color_location = get_uniform_location(TINT_PROGRAM, "tint_color"); @@ -408,16 +408,16 @@ draw_bg(OSWindow *w) { bind_program(BGIMAGE_PROGRAM); bind_vertex_array(blit_vertex_array); + const bool unscaled = OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED || OPT(background_image_layout) == CLAMPED; static bool bgimage_constants_set = false; if (!bgimage_constants_set) { glUniform1i(bgimage_program_layout.image_location, BGIMAGE_UNIT); glUniform1f(bgimage_program_layout.opacity_location, OPT(background_opacity)); - GLfloat tiled = (OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED) ? 1 : 0; - glUniform1f(bgimage_program_layout.tiled_location, tiled); + glUniform1f(bgimage_program_layout.unscaled_location, (GLfloat)unscaled); bgimage_constants_set = true; } float translate_left = 0.0f, translate_top = 0.0f; - if (OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED) { + if (unscaled) { if (OPT(background_image_anchor) == NORTH || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == SOUTH) { translate_left = ((float)w->window_width / 2.0f - (float)w->bgimage->width / 2.0f) / (float)w->bgimage->width; } else if (OPT(background_image_anchor) == NORTHEAST || OPT(background_image_anchor) == EAST || OPT(background_image_anchor) == SOUTHEAST) { diff --git a/kitty/state.c b/kitty/state.c index b1243971d..3ab1caad9 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -137,6 +137,7 @@ send_bgimage_to_gpu(BackgroundImageLayout layout, BackgroundImage *bgimage) { RepeatStrategy r; switch (layout) { case SCALED: + case CLAMPED: r = REPEAT_CLAMP; break; case MIRRORED: r = REPEAT_MIRROR; break; From 87d79c7415ef2a858ef43c94417152749d6c5212 Mon Sep 17 00:00:00 2001 From: itepechi <72330683+itepechi@users.noreply.github.com> Date: Wed, 27 Oct 2021 04:58:08 +0900 Subject: [PATCH 4/6] Change the naming of directions in option `background_image_anchor` for consistency Replaced cardinal directions with "relative" directions. --- kitty/data-types.h | 2 +- kitty/options/definition.py | 4 ++-- kitty/options/parse.py | 2 +- kitty/options/to-c.h | 39 +++++++++++++------------------- kitty/options/types.py | 4 ++-- kitty/rc/set_background_image.py | 2 +- kitty/shaders.c | 8 +++---- 7 files changed, 27 insertions(+), 34 deletions(-) diff --git a/kitty/data-types.h b/kitty/data-types.h index b7845659f..a1b9d3898 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -65,7 +65,7 @@ typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOC typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape; typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn; typedef enum { TILING, SCALED, MIRRORED, CLAMPED } BackgroundImageLayout; -typedef enum { NORTHWEST, NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, CENTER } BackgroundImageAnchor; +typedef enum { TOP_LEFT, TOP, TOP_RIGHT, LEFT, CENTER, RIGHT, BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT } BackgroundImageAnchor; #define MAX_CHILDREN 512 #define BLANK_CHAR 0 diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 8c4a65bf4..55d654ed3 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1110,8 +1110,8 @@ opt('background_image_layout', 'tiled', long_text='Whether to tile, scale or clamp the background image.' ) -opt('background_image_anchor', 'northwest', - choices=('northwest', 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'center'), ctype='bganchor', +opt('background_image_anchor', 'top-left', + choices=('top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right'), ctype='bganchor', long_text='Where to position the background image in the window.' ) diff --git a/kitty/options/parse.py b/kitty/options/parse.py index c8aae2ead..3356bfef9 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -63,7 +63,7 @@ class Parser: raise ValueError(f"The value {val} is not a valid choice for background_image_anchor") ans["background_image_anchor"] = val - choices_for_background_image_anchor = frozenset(('northwest', 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'center')) + choices_for_background_image_anchor = frozenset(('top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right')) def background_image_layout(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: val = val.lower() diff --git a/kitty/options/to-c.h b/kitty/options/to-c.h index 7e9c7bbf7..32f48409e 100644 --- a/kitty/options/to-c.h +++ b/kitty/options/to-c.h @@ -81,31 +81,24 @@ bglayout(PyObject *layout_name) { static BackgroundImageAnchor bganchor(PyObject *anchor_name) { const char *name = PyUnicode_AsUTF8(anchor_name); - if (strcmp(name, "north") == 0) { - return NORTH; - } - else if (strcmp(name, "northeast") == 0) { - return NORTHEAST; - } - else if (strcmp(name, "east") == 0) { - return EAST; - } - else if (strcmp(name, "southeast") == 0) { - return SOUTHEAST; - } - else if (strcmp(name, "south") == 0) { - return SOUTH; - } - else if (strcmp(name, "southwest") == 0) { - return SOUTHWEST; - } - else if (strcmp(name, "west") == 0) { - return WEST; - } - else if (strcmp(name, "center") == 0) { + if (strcmp(name, "top") == 0) { + return TOP; + } else if (strcmp(name, "top-right") == 0) { + return TOP_RIGHT; + } else if (strcmp(name, "left") == 0) { + return LEFT; + } else if (strcmp(name, "center") == 0) { return CENTER; + } else if (strcmp(name, "right") == 0) { + return RIGHT; + } else if (strcmp(name, "bottom-left") == 0) { + return BOTTOM_LEFT; + } else if (strcmp(name, "bottom") == 0) { + return BOTTOM; + } else if (strcmp(name, "bottom-right") == 0) { + return BOTTOM_RIGHT; } - return NORTHWEST; + return TOP_LEFT; } #define STR_SETTER(name) { \ diff --git a/kitty/options/types.py b/kitty/options/types.py index 885157b87..154a31b1d 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -14,7 +14,7 @@ from kitty.types import FloatEdges, SingleKey import kitty.types if typing.TYPE_CHECKING: - choices_for_background_image_anchor = typing.Literal['northwest', 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'center'] + choices_for_background_image_anchor = typing.Literal['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right'] choices_for_background_image_layout = typing.Literal['mirror-tiled', 'scaled', 'tiled', 'clamped'] choices_for_default_pointer_shape = typing.Literal['arrow', 'beam', 'hand'] choices_for_linux_display_server = typing.Literal['auto', 'wayland', 'x11'] @@ -456,7 +456,7 @@ class Options: allow_remote_control: str = 'n' background: Color = Color(0, 0, 0) background_image: typing.Optional[str] = None - background_image_anchor: choices_for_background_image_anchor = 'northwest' + background_image_anchor: choices_for_background_image_anchor = 'top-left' background_image_layout: choices_for_background_image_layout = 'tiled' background_image_linear: bool = False background_opacity: float = 1.0 diff --git a/kitty/rc/set_background_image.py b/kitty/rc/set_background_image.py index 57390c848..7cfe93c11 100644 --- a/kitty/rc/set_background_image.py +++ b/kitty/rc/set_background_image.py @@ -55,7 +55,7 @@ How the image should be displayed. The value of configured will use the configur --anchor type=choices -choices=northwest,north,northeast,east,southeast,south,southwest,west,northwest,north,center,configured +choices=top-left,top,top-right,left,center,right,bottom-left,bottom,bottom-right,configured Where the image should be positioned. The value of configured will use the configured value. diff --git a/kitty/shaders.c b/kitty/shaders.c index 05c03abb9..76a4d9f73 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -418,14 +418,14 @@ draw_bg(OSWindow *w) { } float translate_left = 0.0f, translate_top = 0.0f; if (unscaled) { - if (OPT(background_image_anchor) == NORTH || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == SOUTH) { + if (OPT(background_image_anchor) == TOP || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == BOTTOM) { translate_left = ((float)w->window_width / 2.0f - (float)w->bgimage->width / 2.0f) / (float)w->bgimage->width; - } else if (OPT(background_image_anchor) == NORTHEAST || OPT(background_image_anchor) == EAST || OPT(background_image_anchor) == SOUTHEAST) { + } else if (OPT(background_image_anchor) == TOP_RIGHT || OPT(background_image_anchor) == RIGHT || OPT(background_image_anchor) == BOTTOM_RIGHT) { translate_left = ((float)w->window_width - (float)w->bgimage->width) / (float)w->bgimage->width; } - if (OPT(background_image_anchor) == WEST || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == EAST) { + if (OPT(background_image_anchor) == LEFT || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == RIGHT) { translate_top = ((float)w->window_height / 2.0f - (float)w->bgimage->height / 2.0f) / (float)w->bgimage->height; - } else if (OPT(background_image_anchor) == SOUTHWEST || OPT(background_image_anchor) == SOUTH || OPT(background_image_anchor) == SOUTHEAST) { + } else if (OPT(background_image_anchor) == BOTTOM_LEFT || OPT(background_image_anchor) == BOTTOM || OPT(background_image_anchor) == BOTTOM_RIGHT) { translate_top = ((float)w->window_height - (float)w->bgimage->height) / (float)w->bgimage->height; } } From dac1612cb0c92302ba42f063c85f49347ea8e7b2 Mon Sep 17 00:00:00 2001 From: itepechi <72330683+itepechi@users.noreply.github.com> Date: Thu, 28 Oct 2021 18:22:06 +0900 Subject: [PATCH 5/6] Calculate background image position on the GPU --- kitty/bgimage_vertex.glsl | 14 +++++++++----- kitty/shaders.c | 24 ++++++++++++------------ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/kitty/bgimage_vertex.glsl b/kitty/bgimage_vertex.glsl index c6f0f7433..7e2c171d0 100644 --- a/kitty/bgimage_vertex.glsl +++ b/kitty/bgimage_vertex.glsl @@ -8,8 +8,8 @@ #define tex_right 1 #define tex_bottom 1 -uniform float unscaled; -uniform vec2 translate; // [ left, top ] +uniform float rescaled; +uniform vec2 transform; // [ pos_left_relative, pos_top_relative ] uniform vec4 sizes; // [ window_width, window_height, image_width, image_height ] out vec2 texcoord; @@ -28,12 +28,16 @@ const vec2 tex_map[] = vec2[4]( ); -float unscaling_factor(int i) { - return unscaled * (sizes[i] / sizes[i + 2]) + (1 - unscaled); +float scaling_factor(int i) { + return rescaled * (sizes[i] / sizes[i + 2]) + (1 - rescaled); +} + +float position_divisor(int i) { + return (sizes[i] - sizes[i + 2]) * transform[i] / sizes[i + 2]; } void main() { vec2 tex_coords = tex_map[gl_VertexID]; - texcoord = vec2(tex_coords[0] * unscaling_factor(0) - translate[0], tex_coords[1] * unscaling_factor(1) - translate[1]); + texcoord = vec2(tex_coords[0] * scaling_factor(0) - position_divisor(0), tex_coords[1] * scaling_factor(1) - position_divisor(1)); gl_Position = vec4(pos_map[gl_VertexID], 0, 1); } diff --git a/kitty/shaders.c b/kitty/shaders.c index 76a4d9f73..9276c01e7 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -166,7 +166,7 @@ typedef struct { static CellProgramLayout cell_program_layouts[NUM_PROGRAMS]; static ssize_t blit_vertex_array; typedef struct { - GLint image_location, unscaled_location, translate_location, sizes_location, opacity_location, premult_location; + GLint image_location, rescaled_location, transform_location, sizes_location, opacity_location, premult_location; } BGImageProgramLayout; static BGImageProgramLayout bgimage_program_layout = {0}; typedef struct { @@ -198,8 +198,8 @@ init_cell_program(void) { bgimage_program_layout.image_location = get_uniform_location(BGIMAGE_PROGRAM, "image"); bgimage_program_layout.opacity_location = get_uniform_location(BGIMAGE_PROGRAM, "opacity"); bgimage_program_layout.sizes_location = get_uniform_location(BGIMAGE_PROGRAM, "sizes"); - bgimage_program_layout.unscaled_location = get_uniform_location(BGIMAGE_PROGRAM, "unscaled"); - bgimage_program_layout.translate_location = get_uniform_location(BGIMAGE_PROGRAM, "translate"); + bgimage_program_layout.rescaled_location = get_uniform_location(BGIMAGE_PROGRAM, "rescaled"); + bgimage_program_layout.transform_location = get_uniform_location(BGIMAGE_PROGRAM, "transform"); bgimage_program_layout.premult_location = get_uniform_location(BGIMAGE_PROGRAM, "premult"); tint_program_layout.tint_color_location = get_uniform_location(TINT_PROGRAM, "tint_color"); tint_program_layout.edges_location = get_uniform_location(TINT_PROGRAM, "edges"); @@ -408,28 +408,28 @@ draw_bg(OSWindow *w) { bind_program(BGIMAGE_PROGRAM); bind_vertex_array(blit_vertex_array); - const bool unscaled = OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED || OPT(background_image_layout) == CLAMPED; + const bool rescaled = OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED || OPT(background_image_layout) == CLAMPED; static bool bgimage_constants_set = false; if (!bgimage_constants_set) { glUniform1i(bgimage_program_layout.image_location, BGIMAGE_UNIT); glUniform1f(bgimage_program_layout.opacity_location, OPT(background_opacity)); - glUniform1f(bgimage_program_layout.unscaled_location, (GLfloat)unscaled); + glUniform1f(bgimage_program_layout.rescaled_location, (GLfloat)rescaled); bgimage_constants_set = true; } - float translate_left = 0.0f, translate_top = 0.0f; - if (unscaled) { + float pos_left_relative = 0.0f, pos_top_relative = 0.0f; + if (rescaled) { if (OPT(background_image_anchor) == TOP || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == BOTTOM) { - translate_left = ((float)w->window_width / 2.0f - (float)w->bgimage->width / 2.0f) / (float)w->bgimage->width; + pos_left_relative = 0.5f; } else if (OPT(background_image_anchor) == TOP_RIGHT || OPT(background_image_anchor) == RIGHT || OPT(background_image_anchor) == BOTTOM_RIGHT) { - translate_left = ((float)w->window_width - (float)w->bgimage->width) / (float)w->bgimage->width; + pos_left_relative = 1.0f; } if (OPT(background_image_anchor) == LEFT || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == RIGHT) { - translate_top = ((float)w->window_height / 2.0f - (float)w->bgimage->height / 2.0f) / (float)w->bgimage->height; + pos_top_relative = 0.5f; } else if (OPT(background_image_anchor) == BOTTOM_LEFT || OPT(background_image_anchor) == BOTTOM || OPT(background_image_anchor) == BOTTOM_RIGHT) { - translate_top = ((float)w->window_height - (float)w->bgimage->height) / (float)w->bgimage->height; + pos_top_relative = 1.0f; } } - glUniform2f(bgimage_program_layout.translate_location, (GLfloat)translate_left, (GLfloat)translate_top); + glUniform2f(bgimage_program_layout.transform_location, (GLfloat)pos_left_relative, (GLfloat)pos_top_relative); glUniform4f(bgimage_program_layout.sizes_location, (GLfloat)w->window_width, (GLfloat)w->window_height, (GLfloat)w->bgimage->width, (GLfloat)w->bgimage->height); glUniform1f(bgimage_program_layout.premult_location, w->is_semi_transparent ? 1.f : 0.f); From 9289c2de69265e437a75cc8c312cb43ffc707595 Mon Sep 17 00:00:00 2001 From: itepechi <72330683+itepechi@users.noreply.github.com> Date: Sat, 30 Oct 2021 03:07:03 +0900 Subject: [PATCH 6/6] Refactor `background_image_anchor` for cleaner code --- kitty/bgimage_vertex.glsl | 4 ++-- kitty/data-types.h | 4 +++- kitty/options/to-c.h | 28 +++++++++++----------------- kitty/shaders.c | 22 +++++++--------------- 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/kitty/bgimage_vertex.glsl b/kitty/bgimage_vertex.glsl index 7e2c171d0..707000af2 100644 --- a/kitty/bgimage_vertex.glsl +++ b/kitty/bgimage_vertex.glsl @@ -8,7 +8,7 @@ #define tex_right 1 #define tex_bottom 1 -uniform float rescaled; +uniform float adjust_scale; uniform vec2 transform; // [ pos_left_relative, pos_top_relative ] uniform vec4 sizes; // [ window_width, window_height, image_width, image_height ] @@ -29,7 +29,7 @@ const vec2 tex_map[] = vec2[4]( float scaling_factor(int i) { - return rescaled * (sizes[i] / sizes[i + 2]) + (1 - rescaled); + return adjust_scale * (sizes[i] / sizes[i + 2]) + (1 - adjust_scale); } float position_divisor(int i) { diff --git a/kitty/data-types.h b/kitty/data-types.h index a1b9d3898..b2c490370 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -65,7 +65,9 @@ typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOC typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape; typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn; typedef enum { TILING, SCALED, MIRRORED, CLAMPED } BackgroundImageLayout; -typedef enum { TOP_LEFT, TOP, TOP_RIGHT, LEFT, CENTER, RIGHT, BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT } BackgroundImageAnchor; +typedef struct { + float x, y; +} BackgroundImageAnchor; #define MAX_CHILDREN 512 #define BLANK_CHAR 0 diff --git a/kitty/options/to-c.h b/kitty/options/to-c.h index 32f48409e..9213b0f10 100644 --- a/kitty/options/to-c.h +++ b/kitty/options/to-c.h @@ -81,24 +81,18 @@ bglayout(PyObject *layout_name) { static BackgroundImageAnchor bganchor(PyObject *anchor_name) { const char *name = PyUnicode_AsUTF8(anchor_name); - if (strcmp(name, "top") == 0) { - return TOP; - } else if (strcmp(name, "top-right") == 0) { - return TOP_RIGHT; - } else if (strcmp(name, "left") == 0) { - return LEFT; - } else if (strcmp(name, "center") == 0) { - return CENTER; - } else if (strcmp(name, "right") == 0) { - return RIGHT; - } else if (strcmp(name, "bottom-left") == 0) { - return BOTTOM_LEFT; - } else if (strcmp(name, "bottom") == 0) { - return BOTTOM; - } else if (strcmp(name, "bottom-right") == 0) { - return BOTTOM_RIGHT; + BackgroundImageAnchor anchor = { .x = 0.5f, .y = 0.5f }; + if (strstr(name, "top") != NULL) { + anchor.y = 0.0f; + } else if (strstr(name, "bottom") != NULL) { + anchor.y = 1.0f; } - return TOP_LEFT; + if (strstr(name, "left") != NULL) { + anchor.x = 0.0f; + } else if (strstr(name, "right") != NULL) { + anchor.x = 1.0f; + } + return anchor; } #define STR_SETTER(name) { \ diff --git a/kitty/shaders.c b/kitty/shaders.c index 9276c01e7..61cc40e5b 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -166,7 +166,7 @@ typedef struct { static CellProgramLayout cell_program_layouts[NUM_PROGRAMS]; static ssize_t blit_vertex_array; typedef struct { - GLint image_location, rescaled_location, transform_location, sizes_location, opacity_location, premult_location; + GLint image_location, adjust_scale_location, transform_location, sizes_location, opacity_location, premult_location; } BGImageProgramLayout; static BGImageProgramLayout bgimage_program_layout = {0}; typedef struct { @@ -198,7 +198,7 @@ init_cell_program(void) { bgimage_program_layout.image_location = get_uniform_location(BGIMAGE_PROGRAM, "image"); bgimage_program_layout.opacity_location = get_uniform_location(BGIMAGE_PROGRAM, "opacity"); bgimage_program_layout.sizes_location = get_uniform_location(BGIMAGE_PROGRAM, "sizes"); - bgimage_program_layout.rescaled_location = get_uniform_location(BGIMAGE_PROGRAM, "rescaled"); + bgimage_program_layout.adjust_scale_location = get_uniform_location(BGIMAGE_PROGRAM, "adjust_scale"); bgimage_program_layout.transform_location = get_uniform_location(BGIMAGE_PROGRAM, "transform"); bgimage_program_layout.premult_location = get_uniform_location(BGIMAGE_PROGRAM, "premult"); tint_program_layout.tint_color_location = get_uniform_location(TINT_PROGRAM, "tint_color"); @@ -408,26 +408,18 @@ draw_bg(OSWindow *w) { bind_program(BGIMAGE_PROGRAM); bind_vertex_array(blit_vertex_array); - const bool rescaled = OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED || OPT(background_image_layout) == CLAMPED; + const bool adjust_scale = OPT(background_image_layout) == TILING || OPT(background_image_layout) == MIRRORED || OPT(background_image_layout) == CLAMPED; static bool bgimage_constants_set = false; if (!bgimage_constants_set) { glUniform1i(bgimage_program_layout.image_location, BGIMAGE_UNIT); glUniform1f(bgimage_program_layout.opacity_location, OPT(background_opacity)); - glUniform1f(bgimage_program_layout.rescaled_location, (GLfloat)rescaled); + glUniform1f(bgimage_program_layout.adjust_scale_location, (GLfloat)adjust_scale); bgimage_constants_set = true; } float pos_left_relative = 0.0f, pos_top_relative = 0.0f; - if (rescaled) { - if (OPT(background_image_anchor) == TOP || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == BOTTOM) { - pos_left_relative = 0.5f; - } else if (OPT(background_image_anchor) == TOP_RIGHT || OPT(background_image_anchor) == RIGHT || OPT(background_image_anchor) == BOTTOM_RIGHT) { - pos_left_relative = 1.0f; - } - if (OPT(background_image_anchor) == LEFT || OPT(background_image_anchor) == CENTER || OPT(background_image_anchor) == RIGHT) { - pos_top_relative = 0.5f; - } else if (OPT(background_image_anchor) == BOTTOM_LEFT || OPT(background_image_anchor) == BOTTOM || OPT(background_image_anchor) == BOTTOM_RIGHT) { - pos_top_relative = 1.0f; - } + if (adjust_scale) { + pos_left_relative = OPT(background_image_anchor).x; + pos_top_relative = OPT(background_image_anchor).y; } glUniform2f(bgimage_program_layout.transform_location, (GLfloat)pos_left_relative, (GLfloat)pos_top_relative); glUniform4f(bgimage_program_layout.sizes_location,