mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-09-20 02:57:19 +03:00
macOS: Make full screening of kitty much faster by using the "traditional full screen" mode of cocoa, similar to iTerm and MacVim
Hopefully workaround a bug in glfw that causes crashes when unplugging monitors with full screen windows. Fixes #911 Fixes #898
This commit is contained in:
parent
21d586cc86
commit
ec1f219850
@ -25,6 +25,11 @@ Changelog
|
||||
on macs thicker, which makes it similar to the result of
|
||||
sub-pixel antialiasing (:pull:`950`)
|
||||
|
||||
- macOS: Make full screening of kitty much faster by using the "traditional full
|
||||
screen" mode of cocoa, similar to iTerm and MacVim (:iss:`911`). Also should
|
||||
hopefully workaround a bug in glfw that causes crashes when unplugging
|
||||
monitors with full screen windows. (:iss:`898`)
|
||||
|
||||
- Fix drag-scrolling not working when the mouse leaves the window confines
|
||||
(:iss:`917`)
|
||||
|
||||
|
3
glfw/cocoa_platform.h
vendored
3
glfw/cocoa_platform.h
vendored
@ -39,6 +39,7 @@ typedef void* id;
|
||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,int);
|
||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||
|
||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||
{
|
||||
@ -102,6 +103,8 @@ typedef struct _GLFWwindowNS
|
||||
|
||||
// The text input filter callback
|
||||
GLFWcocoatextinputfilterfun textInputFilterCallback;
|
||||
// The toggle fullscreen intercept callback
|
||||
GLFWcocoatogglefullscreenfun toggleFullscreenCallback;
|
||||
// Dead key state
|
||||
UInt32 deadKeyState;
|
||||
} _GLFWwindowNS;
|
||||
|
@ -563,6 +563,10 @@ - (void)dealloc
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (_GLFWwindow*)glfwWindow {
|
||||
return window;
|
||||
}
|
||||
|
||||
- (BOOL)isOpaque
|
||||
{
|
||||
return [window->ns.object isOpaque];
|
||||
@ -1040,6 +1044,18 @@ - (BOOL)canBecomeMainWindow
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)toggleFullScreen:(nullable id)sender
|
||||
{
|
||||
GLFWContentView *view = [self contentView];
|
||||
if (view)
|
||||
{
|
||||
_GLFWwindow *window = [view glfwWindow];
|
||||
if (window && window->ns.toggleFullscreenCallback && window->ns.toggleFullscreenCallback((GLFWwindow*)window) == 1)
|
||||
return;
|
||||
}
|
||||
[super toggleFullScreen:sender];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -2114,6 +2130,14 @@ GLFWAPI GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow *hand
|
||||
return previous;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *handle, GLFWcocoatogglefullscreenfun callback) {
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(nil);
|
||||
GLFWcocoatogglefullscreenfun previous = window->ns.toggleFullscreenCallback;
|
||||
window->ns.toggleFullscreenCallback = callback;
|
||||
return previous;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) {
|
||||
GLFWapplicationshouldhandlereopenfun previous = handle_reopen_callback;
|
||||
handle_reopen_callback = callback;
|
||||
|
@ -194,6 +194,7 @@ def generate_wrappers(glfw_header, glfw_native_header):
|
||||
void* glfwGetCocoaWindow(GLFWwindow* window)
|
||||
uint32_t glfwGetCocoaMonitor(GLFWmonitor* monitor)
|
||||
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
|
||||
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
||||
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
||||
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, void* cocoa_mods)
|
||||
void* glfwGetX11Display(void)
|
||||
@ -213,11 +214,13 @@ def generate_wrappers(glfw_header, glfw_native_header):
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int);
|
||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||
|
||||
{}
|
||||
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int);
|
||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||
|
||||
{}
|
||||
|
||||
const char* load_glfw(const char* path);
|
||||
|
@ -224,6 +224,24 @@ + (GlobalMenuTarget *) shared_instance
|
||||
[window makeKeyWindow];
|
||||
}
|
||||
|
||||
bool
|
||||
cocoa_toggle_fullscreen(void *w) {
|
||||
NSWindow *window = (NSWindow*)w;
|
||||
NSWindowStyleMask sm = [window styleMask];
|
||||
bool made_fullscreen;
|
||||
if (!(sm & NSWindowStyleMaskFullScreen)) {
|
||||
made_fullscreen = true;
|
||||
sm |= NSWindowStyleMaskBorderless | NSWindowStyleMaskFullScreen;
|
||||
[[NSApplication sharedApplication] setPresentationOptions: NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock];
|
||||
} else {
|
||||
made_fullscreen = false;
|
||||
sm &= ~(NSWindowStyleMaskBorderless | NSWindowStyleMaskFullScreen);
|
||||
[[NSApplication sharedApplication] setPresentationOptions: NSApplicationPresentationDefault];
|
||||
}
|
||||
[window setStyleMask: sm];
|
||||
return made_fullscreen;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
cocoa_get_lang(PyObject UNUSED *self) {
|
||||
NSString* locale = nil;
|
||||
|
2
kitty/glfw-wrapper.c
generated
2
kitty/glfw-wrapper.c
generated
@ -362,6 +362,8 @@ load_glfw(const char* path) {
|
||||
|
||||
*(void **) (&glfwSetCocoaTextInputFilter_impl) = dlsym(handle, "glfwSetCocoaTextInputFilter");
|
||||
|
||||
*(void **) (&glfwSetCocoaToggleFullscreenIntercept_impl) = dlsym(handle, "glfwSetCocoaToggleFullscreenIntercept");
|
||||
|
||||
*(void **) (&glfwSetApplicationShouldHandleReopen_impl) = dlsym(handle, "glfwSetApplicationShouldHandleReopen");
|
||||
|
||||
*(void **) (&glfwGetCocoaKeyEquivalent_impl) = dlsym(handle, "glfwGetCocoaKeyEquivalent");
|
||||
|
10
kitty/glfw-wrapper.h
generated
10
kitty/glfw-wrapper.h
generated
@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int);
|
||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||
|
||||
|
||||
|
||||
@ -1386,6 +1384,10 @@ typedef struct GLFWgamepadstate
|
||||
*/
|
||||
|
||||
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int);
|
||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||
|
||||
typedef int (*glfwInit_func)();
|
||||
glfwInit_func glfwInit_impl;
|
||||
#define glfwInit glfwInit_impl
|
||||
@ -1854,6 +1856,10 @@ typedef GLFWcocoatextinputfilterfun (*glfwSetCocoaTextInputFilter_func)(GLFWwind
|
||||
glfwSetCocoaTextInputFilter_func glfwSetCocoaTextInputFilter_impl;
|
||||
#define glfwSetCocoaTextInputFilter glfwSetCocoaTextInputFilter_impl
|
||||
|
||||
typedef GLFWcocoatogglefullscreenfun (*glfwSetCocoaToggleFullscreenIntercept_func)(GLFWwindow*, GLFWcocoatogglefullscreenfun);
|
||||
glfwSetCocoaToggleFullscreenIntercept_func glfwSetCocoaToggleFullscreenIntercept_impl;
|
||||
#define glfwSetCocoaToggleFullscreenIntercept glfwSetCocoaToggleFullscreenIntercept_impl
|
||||
|
||||
typedef GLFWapplicationshouldhandlereopenfun (*glfwSetApplicationShouldHandleReopen_func)(GLFWapplicationshouldhandlereopenfun);
|
||||
glfwSetApplicationShouldHandleReopen_func glfwSetApplicationShouldHandleReopen_impl;
|
||||
#define glfwSetApplicationShouldHandleReopen glfwSetApplicationShouldHandleReopen_impl
|
||||
|
79
kitty/glfw.c
79
kitty/glfw.c
@ -10,6 +10,7 @@
|
||||
#include "glfw-wrapper.h"
|
||||
extern bool cocoa_make_window_resizable(void *w, bool);
|
||||
extern void cocoa_focus_window(void *w);
|
||||
extern bool cocoa_toggle_fullscreen(void *w);
|
||||
extern void cocoa_create_global_menu(void);
|
||||
extern void cocoa_set_hide_from_tasks(void);
|
||||
extern void cocoa_set_titlebar_color(void *w, color_type color);
|
||||
@ -355,11 +356,55 @@ set_os_window_dpi(OSWindow *w) {
|
||||
get_window_dpi(w->handle, &w->logical_dpi_x, &w->logical_dpi_y);
|
||||
}
|
||||
|
||||
static bool
|
||||
toggle_fullscreen_for_os_window(OSWindow *w) {
|
||||
int width, height, x, y;
|
||||
glfwGetWindowSize(w->handle, &width, &height);
|
||||
glfwGetWindowPos(w->handle, &x, &y);
|
||||
#ifdef __APPLE__
|
||||
if (cocoa_toggle_fullscreen(glfwGetCocoaWindow(w->handle))) {
|
||||
w->before_fullscreen.is_set = true;
|
||||
w->before_fullscreen.w = width; w->before_fullscreen.h = height; w->before_fullscreen.x = x; w->before_fullscreen.y = y;
|
||||
return true;
|
||||
}
|
||||
if (w->before_fullscreen.is_set) {
|
||||
glfwSetWindowSize(w->handle, w->before_fullscreen.w, w->before_fullscreen.h);
|
||||
glfwSetWindowPos(w->handle, w->before_fullscreen.x, w->before_fullscreen.y);
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
GLFWmonitor *monitor;
|
||||
if ((monitor = glfwGetWindowMonitor(w->handle)) == NULL) {
|
||||
// make fullscreen
|
||||
monitor = current_monitor(w->handle);
|
||||
if (monitor == NULL) { PyErr_Print(); return false; }
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
w->before_fullscreen.is_set = true;
|
||||
w->before_fullscreen.w = width; w->before_fullscreen.h = height; w->before_fullscreen.x = x; w->before_fullscreen.y = y;
|
||||
glfwGetWindowSize(w->handle, &w->before_fullscreen.w, &w->before_fullscreen.h);
|
||||
glfwGetWindowPos(w->handle, &w->before_fullscreen.x, &w->before_fullscreen.y);
|
||||
glfwSetWindowMonitor(w->handle, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||
return true;
|
||||
} else {
|
||||
// make windowed
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
if (w->before_fullscreen.is_set) glfwSetWindowMonitor(w->handle, NULL, w->before_fullscreen.x, w->before_fullscreen.y, w->before_fullscreen.w, w->before_fullscreen.h, mode->refreshRate);
|
||||
else glfwSetWindowMonitor(w->handle, NULL, 0, 0, 600, 400, mode->refreshRate);
|
||||
#ifdef __APPLE__
|
||||
if (glfwGetCocoaWindow) cocoa_make_window_resizable(glfwGetCocoaWindow(w->handle), OPT(macos_window_resizable));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
static int
|
||||
filter_option(int key UNUSED, int mods, unsigned int scancode UNUSED) {
|
||||
return ((mods == GLFW_MOD_ALT) || (mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT))) ? 1 : 0;
|
||||
}
|
||||
|
||||
static GLFWwindow *application_quit_canary = NULL;
|
||||
|
||||
static int
|
||||
@ -370,6 +415,14 @@ on_application_reopen(int has_visible_windows) {
|
||||
unjam_event_loop();
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
intercept_cocoa_fullscreen(GLFWwindow *w) {
|
||||
if (!set_callback_window(w)) return 0;
|
||||
toggle_fullscreen_for_os_window(global_state.callback_os_window);
|
||||
global_state.callback_os_window = NULL;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
@ -504,6 +557,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
|
||||
glfwSwapInterval(OPT(sync_to_monitor) ? 1 : 0);
|
||||
#ifdef __APPLE__
|
||||
if (OPT(macos_option_as_alt)) glfwSetCocoaTextInputFilter(glfw_window, filter_option);
|
||||
glfwSetCocoaToggleFullscreenIntercept(glfw_window, intercept_cocoa_fullscreen);
|
||||
#endif
|
||||
send_prerendered_sprites_for_window(w);
|
||||
if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo);
|
||||
@ -702,29 +756,10 @@ set_clipboard_string(PyObject UNUSED *self, PyObject *args) {
|
||||
|
||||
static PyObject*
|
||||
toggle_fullscreen(PYNOARG) {
|
||||
GLFWmonitor *monitor;
|
||||
OSWindow *w = current_os_window();
|
||||
if (!w || !w->handle) Py_RETURN_NONE;
|
||||
if ((monitor = glfwGetWindowMonitor(w->handle)) == NULL) {
|
||||
// make fullscreen
|
||||
monitor = current_monitor(w->handle);
|
||||
if (monitor == NULL) return NULL;
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
w->before_fullscreen.is_set = true;
|
||||
glfwGetWindowSize(w->handle, &w->before_fullscreen.w, &w->before_fullscreen.h);
|
||||
glfwGetWindowPos(w->handle, &w->before_fullscreen.x, &w->before_fullscreen.y);
|
||||
glfwSetWindowMonitor(w->handle, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
// make windowed
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
if (w->before_fullscreen.is_set) glfwSetWindowMonitor(w->handle, NULL, w->before_fullscreen.x, w->before_fullscreen.y, w->before_fullscreen.w, w->before_fullscreen.h, mode->refreshRate);
|
||||
else glfwSetWindowMonitor(w->handle, NULL, 0, 0, 600, 400, mode->refreshRate);
|
||||
#ifdef __APPLE__
|
||||
if (glfwGetCocoaWindow) cocoa_make_window_resizable(glfwGetCocoaWindow(w->handle), OPT(macos_window_resizable));
|
||||
#endif
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
if (!w) Py_RETURN_NONE;
|
||||
if (toggle_fullscreen_for_os_window(w)) { Py_RETURN_TRUE; }
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
Loading…
Reference in New Issue
Block a user