mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-19 06:57:57 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e59df1f8 | ||
|
|
c797944923 | ||
|
|
ade4e67b51 | ||
|
|
656f49f2ff | ||
|
|
0045244295 | ||
|
|
6bfb704f6f | ||
|
|
80cebdefcd |
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 (cmd+option+, on macOS) in kitty, to copy debug output about kitty and its
|
||||
Press Ctrl+Shift+F6 (cmd+option+comma 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
|
||||
|
||||
@@ -4,6 +4,17 @@ Changelog
|
||||
|kitty| is a feature-rich, cross-platform, *fast*, GPU based terminal.
|
||||
To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||
|
||||
0.22.2 [2021-08-02]
|
||||
----------------------
|
||||
|
||||
- macOS: Fix a long standing bug that could cause kitty windows to stop
|
||||
updating, that got worse in the previous release (:iss:`3890` and
|
||||
:iss:`2016`)
|
||||
|
||||
- Wayland: A better fix for compositors like sway that can toggle client side
|
||||
decorations on and off (:iss:`3888`)
|
||||
|
||||
|
||||
0.22.1 [2021-07-31]
|
||||
----------------------
|
||||
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
|
||||
// Get the name of the specified display, or NULL
|
||||
//
|
||||
static char* getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||
static char*
|
||||
getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||
{
|
||||
// IOKit doesn't work on Apple Silicon anymore
|
||||
// Luckily, 10.15 introduced -[NSScreen localizedName].
|
||||
@@ -51,8 +52,9 @@ static char* getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||
if ([screen respondsToSelector:@selector(localizedName)])
|
||||
{
|
||||
NSString* name = [screen valueForKey:@"localizedName"];
|
||||
if (name)
|
||||
if (name) {
|
||||
return _glfw_strdup([name UTF8String]);
|
||||
}
|
||||
}
|
||||
}
|
||||
io_iterator_t it;
|
||||
@@ -64,7 +66,7 @@ static char* getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||
&it) != 0)
|
||||
{
|
||||
// This may happen if a desktop Mac is running headless
|
||||
return _glfw_strdup("Display");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((service = IOIteratorNext(it)) != 0)
|
||||
@@ -102,7 +104,7 @@ static char* getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to find service port for display");
|
||||
return _glfw_strdup("Display");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFDictionaryRef names =
|
||||
@@ -115,7 +117,7 @@ static char* getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||
{
|
||||
// This may happen if a desktop Mac is running headless
|
||||
CFRelease(info);
|
||||
return _glfw_strdup("Display");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const CFIndex size =
|
||||
@@ -326,11 +328,9 @@ void _glfwClearDisplayLinks() {
|
||||
if (_glfw.ns.displayLinks.entries[i].displayLink) {
|
||||
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||
_glfw.ns.displayLinks.entries[i].displayLink = nil;
|
||||
_glfw.ns.displayLinks.entries[i].lastRenderFrameRequestedAt = 0;
|
||||
_glfw.ns.displayLinks.entries[i].first_unserviced_render_frame_request_at = 0;
|
||||
}
|
||||
}
|
||||
memset(_glfw.ns.displayLinks.entries, 0, sizeof(_GLFWDisplayLinkNS) * _glfw.ns.displayLinks.count);
|
||||
_glfw.ns.displayLinks.count = 0;
|
||||
}
|
||||
|
||||
@@ -352,16 +352,21 @@ _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry) {
|
||||
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)entry->displayID);
|
||||
}
|
||||
|
||||
static void
|
||||
createDisplayLink(CGDirectDisplayID displayID) {
|
||||
if (_glfw.ns.displayLinks.count >= sizeof(_glfw.ns.displayLinks.entries)/sizeof(_glfw.ns.displayLinks.entries[0]) - 1) return;
|
||||
_GLFWDisplayLinkNS*
|
||||
_glfw_create_display_link(CGDirectDisplayID displayID) {
|
||||
if (_glfw.ns.displayLinks.count >= arraysz(_glfw.ns.displayLinks.entries) - 1) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many monitors cannot create display link");
|
||||
return NULL;
|
||||
}
|
||||
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
|
||||
// already created in this run
|
||||
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return _glfw.ns.displayLinks.entries + i;
|
||||
}
|
||||
_GLFWDisplayLinkNS *entry = &_glfw.ns.displayLinks.entries[_glfw.ns.displayLinks.count++];
|
||||
memset(entry, 0, sizeof(_GLFWDisplayLinkNS));
|
||||
entry->displayID = displayID;
|
||||
_glfw_create_cv_display_link(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
@@ -369,11 +374,13 @@ createDisplayLink(CGDirectDisplayID displayID) {
|
||||
void _glfwPollMonitorsNS(void)
|
||||
{
|
||||
uint32_t displayCount;
|
||||
|
||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||
CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||
_glfwClearDisplayLinks();
|
||||
if (_glfw.hints.init.debugRendering) {
|
||||
fprintf(stderr, "Polling for monitors: %u found\n", displayCount);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _glfw.monitorCount; i++)
|
||||
_glfw.monitors[i]->ns.screen = nil;
|
||||
@@ -390,8 +397,10 @@ void _glfwPollMonitorsNS(void)
|
||||
|
||||
for (uint32_t i = 0; i < displayCount; i++)
|
||||
{
|
||||
if (CGDisplayIsAsleep(displays[i]))
|
||||
if (CGDisplayIsAsleep(displays[i])) {
|
||||
if (_glfw.hints.init.debugRendering) fprintf(stderr, "Ignoring sleeping display: %u", displays[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||
NSScreen* screen = nil;
|
||||
@@ -415,7 +424,9 @@ void _glfwPollMonitorsNS(void)
|
||||
{
|
||||
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
||||
{
|
||||
disconnected[j]->ns.displayID = displays[i];
|
||||
disconnected[j]->ns.screen = screen;
|
||||
_glfw_create_display_link(displays[i]);
|
||||
disconnected[j] = NULL;
|
||||
break;
|
||||
}
|
||||
@@ -426,14 +437,17 @@ void _glfwPollMonitorsNS(void)
|
||||
|
||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||
char* name = getDisplayName(displays[i], screen);
|
||||
if (!name)
|
||||
continue;
|
||||
if (!name) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Failed to get name for display, using generic name");
|
||||
name = _glfw_strdup("Display with no name");
|
||||
}
|
||||
|
||||
_GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height);
|
||||
monitor->ns.displayID = displays[i];
|
||||
monitor->ns.unitNumber = unitNumber;
|
||||
monitor->ns.screen = screen;
|
||||
createDisplayLink(monitor->ns.displayID);
|
||||
_glfw_create_display_link(monitor->ns.displayID);
|
||||
|
||||
free(name);
|
||||
|
||||
|
||||
1
glfw/cocoa_platform.h
vendored
1
glfw/cocoa_platform.h
vendored
@@ -250,3 +250,4 @@ void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
||||
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
||||
void _glfwCocoaPostEmptyEvent(void);
|
||||
void _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry);
|
||||
_GLFWDisplayLinkNS* _glfw_create_display_link(CGDirectDisplayID);
|
||||
|
||||
@@ -337,9 +337,12 @@ requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) {
|
||||
display_link_shutdown_timer = _glfwPlatformAddTimer(DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL, false, _glfwShutdownCVDisplayLink, NULL, NULL);
|
||||
}
|
||||
monotonic_t now = glfwGetTime();
|
||||
bool found_display_link = false;
|
||||
_GLFWDisplayLinkNS *dl = NULL;
|
||||
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||
_GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i];
|
||||
dl = &_glfw.ns.displayLinks.entries[i];
|
||||
if (dl->displayID == displayID) {
|
||||
found_display_link = true;
|
||||
dl->lastRenderFrameRequestedAt = now;
|
||||
if (!dl->first_unserviced_render_frame_request_at) dl->first_unserviced_render_frame_request_at = now;
|
||||
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
||||
@@ -359,6 +362,14 @@ requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) {
|
||||
dl->first_unserviced_render_frame_request_at = 0;
|
||||
}
|
||||
}
|
||||
if (!found_display_link) {
|
||||
dl = _glfw_create_display_link(displayID);
|
||||
if (dl) {
|
||||
dl->lastRenderFrameRequestedAt = now;
|
||||
dl->first_unserviced_render_frame_request_at = now;
|
||||
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
37
glfw/wl_window.c
vendored
37
glfw/wl_window.c
vendored
@@ -254,6 +254,14 @@ dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t height
|
||||
_glfwInputWindowDamage(window);
|
||||
}
|
||||
|
||||
static void
|
||||
inform_compositor_of_window_geometry(_GLFWwindow *window, const char *event) {
|
||||
#define geometry window->wl.decorations.geometry
|
||||
debug("Setting window geometry in %s event: x=%d y=%d %dx%d\n", event, geometry.x, geometry.y, geometry.width, geometry.height);
|
||||
xdg_surface_set_window_geometry(window->wl.xdg.surface, geometry.x, geometry.y, geometry.width, geometry.height);
|
||||
#undef geometry
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xdgDecorationHandleConfigure(void* data,
|
||||
@@ -263,15 +271,22 @@ xdgDecorationHandleConfigure(void* data,
|
||||
_GLFWwindow* window = data;
|
||||
|
||||
bool has_server_side_decorations = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
debug("XDG decoration configure event received: Has server side decorations: %d\n", has_server_side_decorations);
|
||||
if (!has_server_side_decorations && window->wl.decorations.serverSide) {
|
||||
// this can happen for example on sway where it has a "border toggle" function
|
||||
// that turns on/off the server side decorations. In such a case, we dont turn
|
||||
// on client side decorations, as that causes things to break.
|
||||
return;
|
||||
}
|
||||
debug("XDG decoration configure event received: has_server_side_decorations: %d\n", has_server_side_decorations);
|
||||
if (has_server_side_decorations == window->wl.decorations.serverSide) return;
|
||||
window->wl.decorations.serverSide = has_server_side_decorations;
|
||||
int width = window->wl.width, height = window->wl.height;
|
||||
if (window->wl.decorations.serverSide) {
|
||||
free_csd_surfaces(window);
|
||||
height += window->wl.decorations.metrics.visible_titlebar_height;
|
||||
} else {
|
||||
ensure_csd_resources(window);
|
||||
}
|
||||
set_csd_window_geometry(window, &width, &height);
|
||||
dispatchChangesAfterConfigure(window, width, height);
|
||||
ensure_csd_resources(window);
|
||||
wl_surface_commit(window->wl.surface);
|
||||
debug("final window content size: %dx%d\n", window->wl.width, window->wl.height);
|
||||
inform_compositor_of_window_geometry(window, "configure-decorations");
|
||||
}
|
||||
|
||||
static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
|
||||
@@ -405,14 +420,6 @@ _glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) {
|
||||
return !already_fullscreen;
|
||||
}
|
||||
|
||||
static void
|
||||
inform_compositor_of_window_geometry(_GLFWwindow *window, const char *event) {
|
||||
#define geometry window->wl.decorations.geometry
|
||||
debug("Setting window geometry in %s event: x=%d y=%d %dx%d\n", event, geometry.x, geometry.y, geometry.width, geometry.height);
|
||||
xdg_surface_set_window_geometry(window->wl.xdg.surface, geometry.x, geometry.y, geometry.width, geometry.height);
|
||||
#undef geometry
|
||||
}
|
||||
|
||||
static void
|
||||
xdgToplevelHandleConfigure(void* data,
|
||||
struct xdg_toplevel* toplevel UNUSED,
|
||||
|
||||
@@ -182,6 +182,8 @@ def generate_class(defn: Definition, loc: str) -> Tuple[str, str]:
|
||||
a(' config_overrides: typing.Tuple[str, ...] = ()')
|
||||
a('')
|
||||
a(' def __init__(self, options_dict: typing.Optional[typing.Dict[str, typing.Any]] = None) -> None:')
|
||||
if defn.has_color_table:
|
||||
a(' self.color_table = array(self.color_table.typecode, self.color_table)')
|
||||
a(' if options_dict is not None:')
|
||||
a(' for key in option_names:')
|
||||
a(' setattr(self, key, options_dict[key])')
|
||||
|
||||
@@ -23,7 +23,7 @@ class Version(NamedTuple):
|
||||
|
||||
appname: str = 'kitty'
|
||||
kitty_face = '🐱'
|
||||
version: Version = Version(0, 22, 1)
|
||||
version: Version = Version(0, 22, 2)
|
||||
str_version: str = '.'.join(map(str, version))
|
||||
_plat = sys.platform.lower()
|
||||
is_macos: bool = 'darwin' in _plat
|
||||
|
||||
@@ -7,12 +7,14 @@ from functools import partial
|
||||
from pprint import pformat
|
||||
from typing import Callable, Dict, Generator, Iterable, Set, Tuple
|
||||
|
||||
from kittens.tui.operations import colored, styled
|
||||
|
||||
from .cli import version
|
||||
from .conf.utils import KeyAction
|
||||
from .constants import is_macos, is_wayland
|
||||
from kittens.tui.operations import colored
|
||||
from .options.types import Options as KittyOpts, defaults
|
||||
from .options.utils import MouseMap
|
||||
from .rgb import Color, color_as_sharp
|
||||
from .types import MouseEvent, SingleKey
|
||||
from .typing import SequenceMap
|
||||
|
||||
@@ -113,6 +115,7 @@ def compare_opts(opts: KittyOpts, print: Callable) -> None:
|
||||
]
|
||||
field_len = max(map(len, changed_opts)) if changed_opts else 20
|
||||
fmt = '{{:{:d}s}}'.format(field_len)
|
||||
colors = []
|
||||
for f in changed_opts:
|
||||
val = getattr(opts, f)
|
||||
if isinstance(val, dict):
|
||||
@@ -123,7 +126,11 @@ def compare_opts(opts: KittyOpts, print: Callable) -> None:
|
||||
else:
|
||||
print(pformat(val))
|
||||
else:
|
||||
print(title(fmt.format(f)), str(getattr(opts, f)))
|
||||
val = getattr(opts, f)
|
||||
if isinstance(val, Color):
|
||||
colors.append(fmt.format(f) + ' ' + color_as_sharp(val) + ' ' + styled(' ', bg=val))
|
||||
else:
|
||||
print(fmt.format(f), str(getattr(opts, f)))
|
||||
|
||||
compare_mousemaps(opts.mousemap, default_opts.mousemap, print)
|
||||
final_, initial_ = opts.keymap, default_opts.keymap
|
||||
@@ -133,6 +140,9 @@ def compare_opts(opts: KittyOpts, print: Callable) -> None:
|
||||
final.update(final_s)
|
||||
initial.update(initial_s)
|
||||
compare_keymaps(final, initial, print)
|
||||
if colors:
|
||||
print(f'{title("Colors")}:', end='\n\t')
|
||||
print('\n\t'.join(sorted(colors)))
|
||||
|
||||
|
||||
def debug_config(opts: KittyOpts) -> str:
|
||||
|
||||
1
kitty/options/types.py
generated
1
kitty/options/types.py
generated
@@ -606,6 +606,7 @@ class Options:
|
||||
config_overrides: typing.Tuple[str, ...] = ()
|
||||
|
||||
def __init__(self, options_dict: typing.Optional[typing.Dict[str, typing.Any]] = None) -> None:
|
||||
self.color_table = array(self.color_table.typecode, self.color_table)
|
||||
if options_dict is not None:
|
||||
for key in option_names:
|
||||
setattr(self, key, options_dict[key])
|
||||
|
||||
Reference in New Issue
Block a user