Show the window much sooner after creating it

Do not make any OpenGL calls between creation and showing of the window.
Hopefully, that will make the fussy wlroots happy.
This commit is contained in:
Kovid Goyal 2018-05-26 13:19:22 +05:30
parent 1ba76508de
commit 3b04776956
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 69 additions and 52 deletions

View File

@ -12,7 +12,8 @@ from weakref import WeakValueDictionary
from .cli import create_opts, parse_args
from .config import (
MINIMUM_FONT_SIZE, initial_window_size_func, prepare_config_file_for_editing
MINIMUM_FONT_SIZE, initial_window_size_func,
prepare_config_file_for_editing
)
from .config_utils import to_cmdline
from .constants import (
@ -23,7 +24,7 @@ from .fast_data_types import (
create_os_window, current_os_window, destroy_global_data,
get_clipboard_string, glfw_post_empty_event, global_font_size,
mark_os_window_for_close, os_window_font_size, set_clipboard_string,
set_in_sequence_mode, show_window, toggle_fullscreen
set_in_sequence_mode, toggle_fullscreen
)
from .keys import get_shortcut, shortcut_matches
from .remote_control import handle_cmd
@ -31,9 +32,9 @@ from .rgb import Color, color_from_int
from .session import create_session
from .tabs import SpecialWindow, SpecialWindowInstance, TabManager
from .utils import (
end_startup_notification, get_primary_selection, init_startup_notification,
log_error, open_url, parse_address_spec, remove_socket_file, safe_print,
set_primary_selection, single_instance
get_primary_selection, log_error, open_url, parse_address_spec,
remove_socket_file, safe_print, set_primary_selection, single_instance,
startup_notification_handler
)
@ -103,12 +104,11 @@ class Boss:
if os_window_id is None:
opts_for_size = opts_for_size or self.opts
cls = wclass or self.args.cls or appname
os_window_id = create_os_window(initial_window_size_func(opts_for_size, self.cached_values), appname, wname or self.args.name or cls, cls)
if startup_id:
ctx = init_startup_notification(os_window_id, startup_id)
show_window(os_window_id)
if startup_id:
end_startup_notification(ctx)
with startup_notification_handler(do_notify=startup_id is not None, startup_id=startup_id) as pre_show_callback:
os_window_id = create_os_window(
initial_window_size_func(opts_for_size, self.cached_values),
pre_show_callback,
appname, wname or self.args.name or cls, cls)
tm = TabManager(os_window_id, self.opts, self.args, startup_session)
self.os_window_map[os_window_id] = tm
return os_window_id

View File

@ -342,12 +342,22 @@ set_titlebar_color(OSWindow *w, color_type color) {
}
}
static inline PyObject*
native_window_handle(GLFWwindow *w) {
#ifdef __APPLE__
void *ans = glfwGetCocoaWindow(w);
return PyLong_FromVoidPtr(ans);
#endif
if (glfwGetX11Window) return PyLong_FromLong((long)glfwGetX11Window(w));
return Py_None;
}
static PyObject*
create_os_window(PyObject UNUSED *self, PyObject *args) {
int x = -1, y = -1;
char *title, *wm_class_class, *wm_class_name;
PyObject *load_programs = NULL, *get_window_size;
if (!PyArg_ParseTuple(args, "Osss|Oii", &get_window_size, &title, &wm_class_name, &wm_class_class, &load_programs, &x, &y)) return NULL;
PyObject *load_programs = NULL, *get_window_size, *pre_show_callback;
if (!PyArg_ParseTuple(args, "OOsss|Oii", &get_window_size, &pre_show_callback, &title, &wm_class_name, &wm_class_class, &load_programs, &x, &y)) return NULL;
static bool is_first_window = true;
if (is_first_window) {
@ -391,8 +401,12 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, temp_window);
glfwDestroyWindow(temp_window); temp_window = NULL;
if (glfw_window == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; }
PyObject *pret = PyObject_CallFunction(pre_show_callback, "N", native_window_handle(glfw_window));
if (pret == NULL) return NULL;
Py_DECREF(pret);
glfwMakeContextCurrent(glfw_window);
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
glfwShowWindow(glfw_window);
if (is_first_window) {
gl_init();
PyObject *ret = PyObject_CallFunction(load_programs, "i", glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER));
@ -421,6 +435,8 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
w->logical_dpi_x = dpi_x; w->logical_dpi_y = dpi_y;
w->fonts_data = fonts_data;
current_os_window_ctx = glfw_window;
w->shown_once = true;
push_focus_history(w);
glfwSwapInterval(OPT(sync_to_monitor) ? 1 : 0);
#ifdef __APPLE__
if (OPT(macos_option_as_alt)) glfwSetCocoaTextInputFilter(glfw_window, filter_option);
@ -459,25 +475,6 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
return PyLong_FromUnsignedLongLong(w->id);
}
static PyObject*
show_window(PyObject UNUSED *self, PyObject *args) {
id_type os_window_id;
int yes = 1;
if (!PyArg_ParseTuple(args, "K|p", &os_window_id, &yes)) return NULL;
for (size_t i = 0; i < global_state.num_os_windows; i++) {
OSWindow *w = global_state.os_windows + i;
if (w->id == os_window_id) {
if (yes) {
glfwShowWindow(w->handle);
w->shown_once = true;
push_focus_history(w);
} else glfwHideWindow(w->handle);
break;
}
}
Py_RETURN_NONE;
}
void
destroy_os_window(OSWindow *w) {
if (w->handle) {
@ -804,7 +801,6 @@ static PyMethodDef module_methods[] = {
METHODB(get_content_scale_for_window, METH_NOARGS),
METHODB(set_clipboard_string, METH_VARARGS),
METHODB(toggle_fullscreen, METH_NOARGS),
METHODB(show_window, METH_VARARGS),
METHODB(glfw_window_hint, METH_VARARGS),
METHODB(os_window_should_close, METH_VARARGS),
METHODB(os_window_swap_buffers, METH_VARARGS),

View File

@ -16,13 +16,12 @@ from .constants import (
)
from .fast_data_types import (
create_os_window, glfw_init, glfw_terminate, set_default_window_icon,
set_options, show_window
set_options
)
from .fonts.box_drawing import set_scale
from .fonts.render import set_font_family
from .utils import (
detach, end_startup_notification, init_startup_notification, log_error,
single_instance
detach, log_error, single_instance, startup_notification_handler
)
from .window import load_shader_programs
@ -44,19 +43,17 @@ def run_app(opts, args):
set_options(opts, is_wayland, args.debug_gl, args.debug_font_fallback)
set_font_family(opts)
with cached_values_for(run_app.cached_values_name) as cached_values:
window_id = create_os_window(
run_app.initial_window_size_func(opts, cached_values),
appname, args.name or args.cls or appname,
args.cls or appname, load_all_shaders)
run_app.first_window_callback(opts, window_id)
startup_ctx = init_startup_notification(window_id)
show_window(window_id)
with startup_notification_handler(extra_callback=run_app.first_window_callback) as pre_show_callback:
window_id = create_os_window(
run_app.initial_window_size_func(opts, cached_values),
pre_show_callback,
appname, args.name or args.cls or appname,
args.cls or appname, load_all_shaders)
if not is_wayland and not is_macos: # no window icons on wayland
with open(logo_data_file, 'rb') as f:
set_default_window_icon(f.read(), 256, 256)
boss = Boss(window_id, opts, args, cached_values)
boss.start()
end_startup_notification(startup_ctx)
try:
boss.child_monitor.main_loop()
finally:
@ -64,7 +61,7 @@ def run_app(opts, args):
run_app.cached_values_name = 'main'
run_app.first_window_callback = lambda opts, window_id: None
run_app.first_window_callback = lambda window_handle: None
run_app.initial_window_size_func = initial_window_size_func

View File

@ -17,8 +17,7 @@ from .constants import (
appname, is_macos, is_wayland, supports_primary_selection
)
from .fast_data_types import (
GLSL_VERSION, log_error_string, redirect_std_streams, x11_display,
x11_window_id
GLSL_VERSION, log_error_string, redirect_std_streams, x11_display
)
from .rgb import Color, to_color
@ -190,7 +189,7 @@ def adjust_line_height(cell_height, val):
return int(cell_height * val)
def init_startup_notification_x11(window_id, startup_id=None):
def init_startup_notification_x11(window_handle, startup_id=None):
# https://specifications.freedesktop.org/startup-notification-spec/startup-notification-latest.txt
from kitty.fast_data_types import init_x11_startup_notification
sid = startup_id or os.environ.pop('DESKTOP_STARTUP_ID', None) # ensure child processes dont get this env var
@ -199,8 +198,7 @@ def init_startup_notification_x11(window_id, startup_id=None):
display = x11_display()
if not display:
return
window_id = x11_window_id(window_id)
return init_x11_startup_notification(display, window_id, sid)
return init_x11_startup_notification(display, window_handle, sid)
def end_startup_notification_x11(ctx):
@ -208,11 +206,14 @@ def end_startup_notification_x11(ctx):
end_x11_startup_notification(ctx)
def init_startup_notification(window, startup_id=None):
def init_startup_notification(window_handle, startup_id=None):
if is_macos or is_wayland:
return
if window_handle is None:
log_error('Could not perform startup notification as window handle not present')
return
try:
return init_startup_notification_x11(window, startup_id)
return init_startup_notification_x11(window_handle, startup_id)
except Exception:
import traceback
traceback.print_exc()
@ -230,6 +231,29 @@ def end_startup_notification(ctx):
traceback.print_exc()
class startup_notification_handler:
def __init__(self, do_notify=True, startup_id=None, extra_callback=None):
self.do_notify = do_notify
self.startup_id = startup_id
self.extra_callback = extra_callback
self.ctx = None
def __enter__(self):
def pre_show_callback(window_handle):
if self.extra_callback is not None:
self.extra_callback(window_handle)
if self.do_notify:
self.ctx = init_startup_notification(window_handle, self.startup_id)
return pre_show_callback
def __exit__(self, *a):
if self.ctx is not None:
end_startup_notification(self.ctx)
def remove_socket_file(s, path=None):
try:
s.close()