Compare commits

..

10 Commits

Author SHA1 Message Date
Kovid Goyal
79b130ed23 version 0.21.1 2021-06-14 07:47:32 +05:30
Kovid Goyal
75e8b16ea3 Dont limit the number of possible cocoa pending actions to the number of bits in an int 2021-06-14 07:34:28 +05:30
Kovid Goyal
1b35708d89 macOS: Fix a crash when rendering ligatures larger than 128 characters
Fixes #3724
2021-06-14 07:15:52 +05:30
Kovid Goyal
ebff343a55 macOS: Add reload config to kitty global menu 2021-06-13 20:34:27 +05:30
Kovid Goyal
c7b91e5f19 Cocoa grabs control+function key presses so use dedicated cmd based shortcuts for those on macOS 2021-06-13 18:20:14 +05:30
Kovid Goyal
b9d52dfaf7 Update Changelog 2021-06-13 10:01:38 +05:30
Kovid Goyal
2c8f66586f macOS: Fix a regression in the previous release that broke rendering of strikeout
The new cell height code forgot to adjust strikeout position.
Fixes #3717
2021-06-13 09:29:30 +05:30
Kovid Goyal
219bf564f7 Fix #3719 2021-06-13 09:07:08 +05:30
Kovid Goyal
291be6f5a6 Silence incorrect compiler warning on older gcc 2021-06-12 13:15:05 +05:30
Kovid Goyal
1da2344aa3 Fix a possible crash when handling mouse clicks 2021-06-12 13:03:47 +05:30
16 changed files with 135 additions and 79 deletions

View File

@@ -22,7 +22,7 @@ If applicable, add screenshots to help explain your problem.
**Environment details**
```
Press Ctrl+Shift+F6 in kitty, to copy debug output about kitty and its
Press Ctrl+Shift+F6 (cmd+option+, on macOS) in kitty, to copy debug output about kitty and its
configuration to the clipboard and paste it here.
On older versions of kitty, run kitty --debug-config instead

View File

@@ -116,8 +116,8 @@ Toggle maximized :sc:`toggle_maximized`
Input unicode character :sc:`input_unicode_character` (also :kbd:`^+⌘+space` on macOS)
Click URL using the keyboard :sc:`open_url`
Reset the terminal :sc:`reset_terminal`
Reload :file:`kitty.conf` :sc:`reload_config_file`
Debug :file:`kitty.conf` :sc:`debug_config`
Reload :file:`kitty.conf` :sc:`reload_config_file` (also :kbd:`^+⌘+f5` on macOS)
Debug :file:`kitty.conf` :sc:`debug_config` (also :kbd:`⌘+option+f6` on macOS)
Pass current selection to program :sc:`pass_selection_to_program`
Edit |kitty| config file :sc:`edit_config_file`
Open a |kitty| shell :sc:`kitty_shell`

View File

@@ -4,6 +4,19 @@ Changelog
|kitty| is a feature-rich, cross-platform, *fast*, GPU based terminal.
To update |kitty|, :doc:`follow the instructions <binary>`.
0.21.1 [2021-06-14]
----------------------
- macOS: Fix a regression in the previous release that broke rendering of
strikeout (:iss:`3717`)
- macOS: Fix a crash when rendering ligatures larger than 128 characters
(:iss:`3724`)
- Fix a regression in the previous release that could cause a crash when
changing layouts and mousing (:iss:`3713`)
0.21.0 [2021-06-12]
----------------------

View File

@@ -47,7 +47,7 @@ static char* getDisplayName(CGDirectDisplayID displayID)
io_service_t service;
CFDictionaryRef info;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
if (IOServiceGetMatchingServices(kIOMainPortDefault,
IOServiceMatching("IODisplayConnect"),
&it) != 0)
{
@@ -245,7 +245,7 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID)
io_iterator_t it;
io_service_t service;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
if (IOServiceGetMatchingServices(kIOMainPortDefault,
IOServiceMatching("IOFramebuffer"),
&it) != 0)
{

View File

@@ -39,6 +39,9 @@ typedef void* CVDisplayLinkRef;
// NOTE: Many Cocoa enum values have been renamed and we need to build across
// SDK versions where one is unavailable or the other deprecated
// We use the newer names in code and these macros to handle compatibility
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 120000) // Before macOS 12 Monterey
#define kIOMainPortDefault kIOMasterPortDefault
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
#define NSEventMaskAny NSAnyEventMask

View File

@@ -944,7 +944,8 @@ process_pending_closes(ChildMonitor *self) {
// If we create new OS windows during wait_events(), using global menu actions
// via the mouse causes a crash because of the way autorelease pools work in
// glfw/cocoa. So we use a flag instead.
static CocoaPendingAction cocoa_pending_actions = NO_COCOA_PENDING_ACTION;
static bool cocoa_pending_actions[NUM_COCOA_PENDING_ACTIONS] = {0};
static bool has_cocoa_pending_actions = false;
typedef struct {
char* wd;
char **open_files;
@@ -964,7 +965,8 @@ set_cocoa_pending_action(CocoaPendingAction action, const char *wd) {
cocoa_pending_actions_data.wd = strdup(wd);
}
}
cocoa_pending_actions |= action;
cocoa_pending_actions[action] = true;
has_cocoa_pending_actions = true;
// The main loop may be blocking on the event queue, if e.g. unfocused.
// Unjam it so the pending action is processed right now.
wakeup_main_loop();
@@ -997,21 +999,22 @@ process_global_state(void *data) {
if (parse_input(self)) input_read = true;
render(now, input_read);
#ifdef __APPLE__
if (cocoa_pending_actions) {
if (cocoa_pending_actions & PREFERENCES_WINDOW) { call_boss(edit_config_file, NULL); }
if (cocoa_pending_actions & NEW_OS_WINDOW) { call_boss(new_os_window, NULL); }
if (cocoa_pending_actions & CLOSE_OS_WINDOW) { call_boss(close_os_window, NULL); }
if (cocoa_pending_actions & CLOSE_TAB) { call_boss(close_tab, NULL); }
if (cocoa_pending_actions & NEW_TAB) { call_boss(new_tab, NULL); }
if (cocoa_pending_actions & NEXT_TAB) { call_boss(next_tab, NULL); }
if (cocoa_pending_actions & PREVIOUS_TAB) { call_boss(previous_tab, NULL); }
if (cocoa_pending_actions & DETACH_TAB) { call_boss(detach_tab, NULL); }
if (cocoa_pending_actions & NEW_WINDOW) { call_boss(new_window, NULL); }
if (cocoa_pending_actions & CLOSE_WINDOW) { call_boss(close_window, NULL); }
if (cocoa_pending_actions & RESET_TERMINAL) { call_boss(clear_terminal, "sO", "reset", Py_True ); }
if (has_cocoa_pending_actions) {
if (cocoa_pending_actions[PREFERENCES_WINDOW]) { call_boss(edit_config_file, NULL); }
if (cocoa_pending_actions[NEW_OS_WINDOW]) { call_boss(new_os_window, NULL); }
if (cocoa_pending_actions[CLOSE_OS_WINDOW]) { call_boss(close_os_window, NULL); }
if (cocoa_pending_actions[CLOSE_TAB]) { call_boss(close_tab, NULL); }
if (cocoa_pending_actions[NEW_TAB]) { call_boss(new_tab, NULL); }
if (cocoa_pending_actions[NEXT_TAB]) { call_boss(next_tab, NULL); }
if (cocoa_pending_actions[PREVIOUS_TAB]) { call_boss(previous_tab, NULL); }
if (cocoa_pending_actions[DETACH_TAB]) { call_boss(detach_tab, NULL); }
if (cocoa_pending_actions[NEW_WINDOW]) { call_boss(new_window, NULL); }
if (cocoa_pending_actions[CLOSE_WINDOW]) { call_boss(close_window, NULL); }
if (cocoa_pending_actions[RESET_TERMINAL]) { call_boss(clear_terminal, "sO", "reset", Py_True ); }
if (cocoa_pending_actions[RELOAD_CONFIG]) { call_boss(load_config_file, NULL); }
if (cocoa_pending_actions_data.wd) {
if (cocoa_pending_actions & NEW_OS_WINDOW_WITH_WD) { call_boss(new_os_window_with_wd, "s", cocoa_pending_actions_data.wd); }
if (cocoa_pending_actions & NEW_TAB_WITH_WD) { call_boss(new_tab_with_wd, "s", cocoa_pending_actions_data.wd); }
if (cocoa_pending_actions[NEW_OS_WINDOW_WITH_WD]) { call_boss(new_os_window_with_wd, "s", cocoa_pending_actions_data.wd); }
if (cocoa_pending_actions[NEW_TAB_WITH_WD]) { call_boss(new_tab_with_wd, "s", cocoa_pending_actions_data.wd); }
free(cocoa_pending_actions_data.wd);
cocoa_pending_actions_data.wd = NULL;
}
@@ -1025,7 +1028,8 @@ process_global_state(void *data) {
}
cocoa_pending_actions_data.open_files_count = 0;
}
cocoa_pending_actions = 0;
memset(cocoa_pending_actions, 0, sizeof(cocoa_pending_actions));
has_cocoa_pending_actions = false;
}
#endif
report_reaped_pids();

View File

@@ -91,6 +91,7 @@ PENDING(previous_tab, PREVIOUS_TAB)
PENDING(new_window, NEW_WINDOW)
PENDING(close_window, CLOSE_WINDOW)
PENDING(reset_terminal, RESET_TERMINAL)
PENDING(reload_config, RELOAD_CONFIG)
- (void)open_kitty_website_url:(id)sender {
(void)sender;
@@ -117,7 +118,7 @@ typedef struct {
NSEventModifierFlags mods;
} GlobalShortcut;
typedef struct {
GlobalShortcut new_os_window, close_os_window, close_tab, edit_config_file;
GlobalShortcut new_os_window, close_os_window, close_tab, edit_config_file, reload_config;
GlobalShortcut previous_tab, next_tab, new_tab, new_window, close_window, reset_terminal;
} GlobalShortcuts;
static GlobalShortcuts global_shortcuts;
@@ -132,7 +133,7 @@ cocoa_set_global_shortcut(PyObject *self UNUSED, PyObject *args) {
#define Q(x) if (strcmp(name, #x) == 0) gs = &global_shortcuts.x
Q(new_os_window); else Q(close_os_window); else Q(close_tab); else Q(edit_config_file);
else Q(new_tab); else Q(next_tab); else Q(previous_tab);
else Q(new_window); else Q(close_window); else Q(reset_terminal);
else Q(new_window); else Q(close_window); else Q(reset_terminal); else Q(reload_config);
#undef Q
if (gs == NULL) { PyErr_SetString(PyExc_KeyError, "Unknown shortcut name"); return NULL; }
int cocoa_mods;
@@ -380,6 +381,7 @@ cocoa_create_global_menu(void) {
keyEquivalent:@""];
[appMenu addItem:[NSMenuItem separatorItem]];
MENU_ITEM(appMenu, @"Preferences…", edit_config_file);
MENU_ITEM(appMenu, @"Reload preferences", reload_config);
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", app_name]
action:@selector(hide:)

View File

@@ -23,7 +23,7 @@ class Version(NamedTuple):
appname: str = 'kitty'
kitty_face = '🐱'
version: Version = Version(0, 21, 0)
version: Version = Version(0, 21, 1)
str_version: str = '.'.join(map(str, version))
_plat = sys.platform.lower()
is_macos: bool = 'darwin' in _plat

View File

@@ -342,7 +342,6 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
}
*cell_width = MAX(1u, width);
*underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
*strikethrough_position = (unsigned int)floor(*baseline * 0.65);
*strikethrough_thickness = *underline_thickness;
// float line_height = MAX(1, floor(self->ascent + self->descent + MAX(0, self->leading) + 0.5));
// Let CoreText's layout engine calculate the line height. Slower, but hopefully more accurate.
@@ -373,6 +372,7 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
// Not sure if we should add this to bounds ascent and then round it or add
// it to already rounded baseline and round again.
*underline_position = (unsigned int)floor(bounds_ascent - self->underline_position + 0.5);
*strikethrough_position = (unsigned int)floor(*baseline * 0.65);
debug("Cell height calculation:\n");
debug("\tline height from line origins: %f\n", line_height);
@@ -381,7 +381,7 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
debug("\tbounds metrics: ascent: %f\n", bounds_ascent);
debug("\tline metrics: ascent: %f descent: %f leading: %f\n", typographic_ascent, typographic_descent, typographic_leading);
debug("\tfont metrics: ascent: %f descent: %f leading: %f underline_position: %f\n", self->ascent, self->descent, self->leading, self->underline_position);
debug("\tcell_height: %u baseline: %u underline_position: %u\n", *cell_height, *baseline, *underline_position);
debug("\tcell_height: %u baseline: %u underline_position: %u strikethrough_position: %u\n", *cell_height, *baseline, *underline_position, *strikethrough_position);
CFRelease(test_frame); CFRelease(path); CFRelease(framesetter);
@@ -415,16 +415,20 @@ specialize_font_descriptor(PyObject *base_descriptor, FONTS_DATA_HANDLE fg UNUSE
return base_descriptor;
}
static uint8_t *render_buf = NULL;
static size_t render_buf_sz = 0;
static CGGlyph glyphs[128];
static CGRect boxes[128];
static CGPoint positions[128];
static CGSize advances[128];
struct RenderBuffers {
uint8_t *render_buf;
size_t render_buf_sz, sz;
CGGlyph *glyphs;
CGRect *boxes;
CGPoint *positions;
CGSize *advances;
};
static struct RenderBuffers buffers = {0};
static void
finalize(void) {
free(render_buf);
free(buffers.render_buf); free(buffers.glyphs); free(buffers.boxes); free(buffers.positions); free(buffers.advances);
memset(&buffers, 0, sizeof(struct RenderBuffers));
if (all_fonts_collection_data) CFRelease(all_fonts_collection_data);
}
@@ -442,7 +446,7 @@ render_color_glyph(CTFontRef font, uint8_t *buf, int glyph_id, unsigned int widt
CGContextSetTextDrawingMode(ctx, kCGTextFill);
CGGlyph glyph = glyph_id;
CGContextSetTextMatrix(ctx, transform);
CGContextSetTextPosition(ctx, -boxes[0].origin.x, MAX(2, height - baseline));
CGContextSetTextPosition(ctx, -buffers.boxes[0].origin.x, MAX(2, height - baseline));
CGPoint p = CGPointMake(0, 0);
CTFontDrawGlyphs(font, &glyph, &p, 1, ctx);
CGContextRelease(ctx);
@@ -455,21 +459,30 @@ render_color_glyph(CTFontRef font, uint8_t *buf, int glyph_id, unsigned int widt
}
}
static inline void
ensure_render_space(size_t width, size_t height) {
if (render_buf_sz >= width * height) return;
free(render_buf);
render_buf_sz = width * height;
render_buf = malloc(render_buf_sz);
if (render_buf == NULL) fatal("Out of memory");
static void
ensure_render_space(size_t width, size_t height, size_t num_glyphs) {
if (buffers.render_buf_sz < width * height) {
free(buffers.render_buf); buffers.render_buf = NULL;
buffers.render_buf_sz = width * height;
buffers.render_buf = malloc(buffers.render_buf_sz);
if (buffers.render_buf == NULL) fatal("Out of memory");
}
if (buffers.sz < num_glyphs) {
buffers.sz = MAX(128, num_glyphs * 2);
buffers.advances = calloc(sizeof(buffers.advances[0]), buffers.sz);
buffers.boxes = calloc(sizeof(buffers.boxes[0]), buffers.sz);
buffers.glyphs = calloc(sizeof(buffers.glyphs[0]), buffers.sz);
buffers.positions = calloc(sizeof(buffers.positions[0]), buffers.sz);
if (!buffers.advances || !buffers.boxes || !buffers.glyphs || !buffers.positions) fatal("Out of memory");
}
}
static inline void
render_glyphs(CTFontRef font, unsigned int width, unsigned int height, unsigned int baseline, unsigned int num_glyphs) {
memset(render_buf, 0, width * height);
memset(buffers.render_buf, 0, width * height);
CGColorSpaceRef gray_color_space = CGColorSpaceCreateDeviceGray();
if (gray_color_space == NULL) fatal("Out of memory");
CGContextRef render_ctx = CGBitmapContextCreate(render_buf, width, height, 8, width, gray_color_space, (kCGBitmapAlphaInfoMask & kCGImageAlphaNone));
CGContextRef render_ctx = CGBitmapContextCreate(buffers.render_buf, width, height, 8, width, gray_color_space, (kCGBitmapAlphaInfoMask & kCGImageAlphaNone));
if (render_ctx == NULL) fatal("Out of memory");
CGContextSetShouldAntialias(render_ctx, true);
CGContextSetShouldSmoothFonts(render_ctx, true);
@@ -479,7 +492,7 @@ render_glyphs(CTFontRef font, unsigned int width, unsigned int height, unsigned
CGContextSetTextDrawingMode(render_ctx, kCGTextFillStroke);
CGContextSetTextMatrix(render_ctx, CGAffineTransformIdentity);
CGContextSetTextPosition(render_ctx, 0, height - baseline);
CTFontDrawGlyphs(font, glyphs, positions, num_glyphs, render_ctx);
CTFontDrawGlyphs(font, buffers.glyphs, buffers.positions, num_glyphs, render_ctx);
CGContextRelease(render_ctx);
CGColorSpaceRelease(gray_color_space);
}
@@ -492,19 +505,20 @@ render_simple_text_impl(PyObject *s, const char *text, unsigned int baseline) {
unichar chars[num_chars];
CGSize local_advances[num_chars];
for (size_t i = 0; i < num_chars; i++) chars[i] = text[i];
CTFontGetGlyphsForCharacters(font, chars, glyphs, num_chars);
CTFontGetAdvancesForGlyphs(font, kCTFontOrientationDefault, glyphs, local_advances, num_chars);
CGRect bounding_box = CTFontGetBoundingRectsForGlyphs(font, kCTFontOrientationDefault, glyphs, boxes, num_chars);
ensure_render_space(0, 0, num_chars);
CTFontGetGlyphsForCharacters(font, chars, buffers.glyphs, num_chars);
CTFontGetAdvancesForGlyphs(font, kCTFontOrientationDefault, buffers.glyphs, local_advances, num_chars);
CGRect bounding_box = CTFontGetBoundingRectsForGlyphs(font, kCTFontOrientationDefault, buffers.glyphs, buffers.boxes, num_chars);
CGFloat x = 0, y = 0;
for (size_t i = 0; i < num_chars; i++) {
positions[i] = CGPointMake(x, y);
buffers.positions[i] = CGPointMake(x, y);
x += local_advances[i].width; y += local_advances[i].height;
}
StringCanvas ans = { .width = (size_t)ceil(x), .height = (size_t)(2 * bounding_box.size.height) };
ensure_render_space(ans.width, ans.height);
ensure_render_space(ans.width, ans.height, num_chars);
render_glyphs(font, ans.width, ans.height, baseline, num_chars);
ans.canvas = malloc(ans.width * ans.height);
if (ans.canvas) memcpy(ans.canvas, render_buf, ans.width * ans.height);
if (ans.canvas) memcpy(ans.canvas, buffers.render_buf, ans.width * ans.height);
return ans;
}
@@ -512,12 +526,13 @@ render_simple_text_impl(PyObject *s, const char *text, unsigned int baseline) {
static inline bool
do_render(CTFontRef ct_font, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *hb_positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored, bool allow_resize, FONTS_DATA_HANDLE fg, bool center_glyph) {
unsigned int canvas_width = cell_width * num_cells;
CGRect br = CTFontGetBoundingRectsForGlyphs(ct_font, kCTFontOrientationHorizontal, glyphs, boxes, num_glyphs);
ensure_render_space(canvas_width, cell_height, num_glyphs);
CGRect br = CTFontGetBoundingRectsForGlyphs(ct_font, kCTFontOrientationHorizontal, buffers.glyphs, buffers.boxes, num_glyphs);
const bool debug_rendering = false;
if (allow_resize) {
// Resize glyphs that would bleed into neighboring cells, by scaling the font size
float right = 0;
for (unsigned i=0; i < num_glyphs; i++) right = MAX(right, boxes[i].origin.x + boxes[i].size.width);
for (unsigned i=0; i < num_glyphs; i++) right = MAX(right, buffers.boxes[i].origin.x + buffers.boxes[i].size.width);
if (!bold && !italic && right > canvas_width + 1) {
if (debug_rendering) printf("resizing glyphs, right: %f canvas_width: %u\n", right, canvas_width);
CGFloat sz = CTFontGetSize(ct_font);
@@ -529,19 +544,18 @@ do_render(CTFontRef ct_font, bool bold, bool italic, hb_glyph_info_t *info, hb_g
}
}
CGFloat x = 0, y = 0;
CTFontGetAdvancesForGlyphs(ct_font, kCTFontOrientationDefault, glyphs, advances, num_glyphs);
CTFontGetAdvancesForGlyphs(ct_font, kCTFontOrientationDefault, buffers.glyphs, buffers.advances, num_glyphs);
for (unsigned i=0; i < num_glyphs; i++) {
positions[i].x = x; positions[i].y = y;
if (debug_rendering) printf("x=%f origin=%f width=%f advance=%f\n", x, boxes[i].origin.x, boxes[i].size.width, advances[i].width);
x += advances[i].width; y += advances[i].height;
buffers.positions[i].x = x; buffers.positions[i].y = y;
if (debug_rendering) printf("x=%f origin=%f width=%f advance=%f\n", x, buffers.boxes[i].origin.x, buffers.boxes[i].size.width, buffers.advances[i].width);
x += buffers.advances[i].width; y += buffers.advances[i].height;
}
if (*was_colored) {
render_color_glyph(ct_font, (uint8_t*)canvas, info[0].codepoint, cell_width * num_cells, cell_height, baseline);
} else {
ensure_render_space(canvas_width, cell_height);
render_glyphs(ct_font, canvas_width, cell_height, baseline, num_glyphs);
Region src = {.bottom=cell_height, .right=canvas_width}, dest = {.bottom=cell_height, .right=canvas_width};
render_alpha_mask(render_buf, canvas, &src, &dest, canvas_width, canvas_width);
render_alpha_mask(buffers.render_buf, canvas, &src, &dest, canvas_width, canvas_width);
}
if (num_cells && (center_glyph || (num_cells == 2 && *was_colored))) {
if (debug_rendering) printf("centering glyphs: center_glyph: %d\n", center_glyph);
@@ -557,7 +571,8 @@ do_render(CTFontRef ct_font, bool bold, bool italic, hb_glyph_info_t *info, hb_g
bool
render_glyphs_in_cells(PyObject *s, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *hb_positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored, FONTS_DATA_HANDLE fg, bool center_glyph) {
CTFace *self = (CTFace*)s;
for (unsigned i=0; i < num_glyphs; i++) glyphs[i] = info[i].codepoint;
ensure_render_space(128, 128, num_glyphs);
for (unsigned i=0; i < num_glyphs; i++) buffers.glyphs[i] = info[i].codepoint;
return do_render(self->ct_font, bold, italic, info, hb_positions, num_glyphs, canvas, cell_width, cell_height, num_cells, baseline, was_colored, true, fg, center_glyph);
}

View File

@@ -560,10 +560,10 @@ END_ALLOW_CASE_RANGE
static PyObject* box_drawing_function = NULL, *prerender_function = NULL, *descriptor_for_idx = NULL;
void
render_alpha_mask(uint8_t *alpha_mask, pixel* dest, Region *src_rect, Region *dest_rect, size_t src_stride, size_t dest_stride) {
render_alpha_mask(const uint8_t *alpha_mask, pixel* dest, Region *src_rect, Region *dest_rect, size_t src_stride, size_t dest_stride) {
for (size_t sr = src_rect->top, dr = dest_rect->top; sr < src_rect->bottom && dr < dest_rect->bottom; sr++, dr++) {
pixel *d = dest + dest_stride * dr;
uint8_t *s = alpha_mask + src_stride * sr;
const uint8_t *s = alpha_mask + src_stride * sr;
for(size_t sc = src_rect->left, dc = dest_rect->left; sc < src_rect->right && dc < dest_rect->right; sc++, dc++) {
uint8_t src_alpha = d[dc] & 0xff;
uint8_t alpha = s[sc];

View File

@@ -33,7 +33,7 @@ PyObject* face_from_descriptor(PyObject*, FONTS_DATA_HANDLE);
const char* postscript_name_for_face(const PyObject*);
void sprite_tracker_current_layout(FONTS_DATA_HANDLE data, unsigned int *x, unsigned int *y, unsigned int *z);
void render_alpha_mask(uint8_t *alpha_mask, pixel* dest, Region *src_rect, Region *dest_rect, size_t src_stride, size_t dest_stride);
void render_alpha_mask(const uint8_t *alpha_mask, pixel* dest, Region *src_rect, Region *dest_rect, size_t src_stride, size_t dest_stride);
void render_line(FONTS_DATA_HANDLE, Line *line, index_type lnum, Cursor *cursor, DisableLigature);
void sprite_tracker_set_limits(size_t max_texture_size, size_t max_array_len);
typedef void (*free_extra_data_func)(void*);

View File

@@ -143,6 +143,9 @@ def _run_app(opts: Options, args: CLIOptions, bad_lines: Sequence[BadLine] = ())
val = get_macos_shortcut_for(opts, 'clear_terminal', args=('reset', True), lookup_name='reset_terminal')
if val is not None:
global_shortcuts['reset_terminal'] = val
val = get_macos_shortcut_for(opts, 'load_config_file', args=(), lookup_name='reload_config')
if val is not None:
global_shortcuts['reload_config'] = val
if is_macos and opts.macos_custom_beam_cursor:
set_custom_ibeam_cursor()
if not is_wayland() and not is_macos: # no window icons on wayland

View File

@@ -3329,6 +3329,11 @@ the new conf settings *replace* the old ones.
'''
)
map('Reload kitty.conf',
'reload_config_file cmd+control+, load_config_file',
only='macos'
)
map('Debug kitty configuration',
'debug_config kitty_mod+f6 debug_config',
long_text='''
@@ -3337,6 +3342,12 @@ its host environment. Useful for debugging issues.
'''
)
map('Debug kitty configuration',
'debug_config cmd+option+, debug_config',
only='macos'
)
map('Send arbitrary text on key presses',
'send_text ctrl+shift+alt+h send_text all Hello World',
add_to_default=False,

View File

@@ -848,6 +848,8 @@ if is_macos:
defaults.map.append(KeyDefinition(False, KeyAction('kitten', ('unicode_input',)), 12, False, 32, ()))
defaults.map.append(KeyDefinition(False, KeyAction('edit_config_file'), 8, False, 44, ()))
defaults.map.append(KeyDefinition(False, KeyAction('clear_terminal', ('reset', True)), 10, False, 114, ()))
defaults.map.append(KeyDefinition(False, KeyAction('load_config_file'), 12, False, 44, ()))
defaults.map.append(KeyDefinition(False, KeyAction('debug_config'), 10, False, 44, ()))
defaults.mouse_map = [
# click_url_or_select
MouseMapping(0, 0, -2, False, KeyAction('mouse_click_url_or_select')),

View File

@@ -2167,11 +2167,12 @@ screen_detect_url(Screen *screen, unsigned int x, unsigned int y) {
bool has_url = false;
index_type url_start, url_end = 0;
Line *line = screen_visual_line(screen, y);
if (!line || x >= screen->columns) return false;
if (line->cpu_cells[x].hyperlink_id) {
screen_mark_hyperlink(screen, x, y);
return true;
}
char_type sentinel;
char_type sentinel = 0;
if (line) {
url_start = line_url_start_at(line, x);
if (url_start < line->xnum) {

View File

@@ -263,21 +263,23 @@ void send_prerendered_sprites_for_window(OSWindow *w);
#ifdef __APPLE__
void get_cocoa_key_equivalent(uint32_t, int, char *key, size_t key_sz, int*);
typedef enum {
NO_COCOA_PENDING_ACTION = 0,
PREFERENCES_WINDOW = 1,
NEW_OS_WINDOW = 2,
NEW_OS_WINDOW_WITH_WD = 4,
NEW_TAB_WITH_WD = 8,
CLOSE_OS_WINDOW = 16,
CLOSE_TAB = 32,
NEW_TAB = 64,
NEXT_TAB = 128,
PREVIOUS_TAB = 256,
DETACH_TAB = 512,
OPEN_FILE = 1024,
NEW_WINDOW = 2048,
CLOSE_WINDOW = 4096,
RESET_TERMINAL = 8192,
PREFERENCES_WINDOW,
NEW_OS_WINDOW,
NEW_OS_WINDOW_WITH_WD,
NEW_TAB_WITH_WD,
CLOSE_OS_WINDOW,
CLOSE_TAB,
NEW_TAB,
NEXT_TAB,
PREVIOUS_TAB,
DETACH_TAB,
OPEN_FILE,
NEW_WINDOW,
CLOSE_WINDOW,
RESET_TERMINAL,
RELOAD_CONFIG,
NUM_COCOA_PENDING_ACTIONS
} CocoaPendingAction;
void set_cocoa_pending_action(CocoaPendingAction action, const char*);
#endif