mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-19 15:08:09 +02:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79b130ed23 | ||
|
|
75e8b16ea3 | ||
|
|
1b35708d89 | ||
|
|
ebff343a55 | ||
|
|
c7b91e5f19 | ||
|
|
b9d52dfaf7 | ||
|
|
2c8f66586f | ||
|
|
219bf564f7 | ||
|
|
291be6f5a6 | ||
|
|
1da2344aa3 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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]
|
||||
----------------------
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
3
glfw/cocoa_platform.h
vendored
3
glfw/cocoa_platform.h
vendored
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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*);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
2
kitty/options/types.py
generated
2
kitty/options/types.py
generated
@@ -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')),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user