Get rid of ctypes based loading of libglfw/libX11
This commit is contained in:
parent
b6be6ee1e7
commit
cfc99baac4
23
glfw/glfw.py
23
glfw/glfw.py
@ -94,12 +94,13 @@ class Arg:
|
||||
|
||||
class Function:
|
||||
|
||||
def __init__(self, declaration):
|
||||
def __init__(self, declaration, check_fail=True):
|
||||
self.check_fail = check_fail
|
||||
m = re.match(
|
||||
r'(.+?)\s+(glfw[A-Z][a-zA-Z0-9]+)[(](.+)[)]$', declaration
|
||||
)
|
||||
if m is None:
|
||||
raise SystemExit('Failed to parse ' + declaration)
|
||||
raise SystemExit('Failed to parse ' + repr(declaration))
|
||||
self.restype = m.group(1).strip()
|
||||
self.name = m.group(2)
|
||||
args = m.group(3).strip().split(',')
|
||||
@ -121,9 +122,10 @@ class Function:
|
||||
ans = '*(void **) (&{name}_impl) = dlsym(handle, "{name}");'.format(
|
||||
name=self.name
|
||||
)
|
||||
ans += '\n if ({name}_impl == NULL) fail("Failed to load glfw function {name} with error: %s", dlerror());'.format(
|
||||
name=self.name
|
||||
)
|
||||
if self.check_fail:
|
||||
ans += '\n if ({name}_impl == NULL) fail("Failed to load glfw function {name} with error: %s", dlerror());'.format(
|
||||
name=self.name
|
||||
)
|
||||
return ans
|
||||
|
||||
|
||||
@ -138,6 +140,17 @@ def generate_wrappers(glfw_header, glfw_native_header):
|
||||
if 'VkInstance' in decl:
|
||||
continue
|
||||
functions.append(Function(decl))
|
||||
for line in '''\
|
||||
void* glfwGetCocoaWindow(GLFWwindow* window)
|
||||
uint32_t glfwGetCocoaMonitor(GLFWmonitor* monitor)
|
||||
void* glfwGetX11Display(void)
|
||||
int32_t glfwGetX11Window(GLFWwindow* window)
|
||||
void glfwSetX11SelectionString(const char* string)
|
||||
const char* glfwGetX11SelectionString(void)
|
||||
'''.splitlines():
|
||||
if line:
|
||||
functions.append(Function(line.strip(), check_fail=False))
|
||||
|
||||
declarations = [f.declaration() for f in functions]
|
||||
p = src.find(' * GLFW API tokens')
|
||||
p = src.find('*/', p)
|
||||
|
||||
@ -4,11 +4,10 @@
|
||||
|
||||
import os
|
||||
import pwd
|
||||
import ctypes
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
|
||||
from .fast_data_types import set_boss as set_c_boss, handle_for_window_id
|
||||
from .fast_data_types import set_boss as set_c_boss
|
||||
|
||||
appname = 'kitty'
|
||||
version = (0, 5, 1)
|
||||
@ -59,67 +58,4 @@ except KeyError:
|
||||
print('Failed to read login shell from /etc/passwd for current user, falling back to /bin/sh', file=sys.stderr)
|
||||
shell_path = '/bin/sh'
|
||||
|
||||
GLint = ctypes.c_int if ctypes.sizeof(ctypes.c_int) == 4 else ctypes.c_long
|
||||
GLuint = ctypes.c_uint if ctypes.sizeof(ctypes.c_uint) == 4 else ctypes.c_ulong
|
||||
GLfloat = ctypes.c_float
|
||||
if ctypes.sizeof(GLfloat) != 4:
|
||||
raise RuntimeError('float size is not 4')
|
||||
if ctypes.sizeof(GLint) != 4:
|
||||
raise RuntimeError('int size is not 4')
|
||||
|
||||
|
||||
def get_glfw_lib_name():
|
||||
try:
|
||||
for line in open('/proc/self/maps'):
|
||||
lib = line.split()[-1]
|
||||
if '/libglfw.so' in lib:
|
||||
return lib
|
||||
except Exception as err:
|
||||
try:
|
||||
print(str(err), file=sys.stderr)
|
||||
except Exception:
|
||||
pass
|
||||
return 'libglfw.so.3'
|
||||
|
||||
|
||||
def glfw_lib():
|
||||
ans = getattr(glfw_lib, 'ans', None)
|
||||
if ans is None:
|
||||
ans = glfw_lib.ans = ctypes.CDLL('libglfw.3.dylib' if isosx else get_glfw_lib_name())
|
||||
return ans
|
||||
|
||||
|
||||
def selection_clipboard_funcs():
|
||||
ans = getattr(selection_clipboard_funcs, 'ans', None)
|
||||
if ans is None:
|
||||
lib = glfw_lib()
|
||||
if hasattr(lib, 'glfwGetX11SelectionString'):
|
||||
g = lib.glfwGetX11SelectionString
|
||||
g.restype = ctypes.c_char_p
|
||||
g.argtypes = []
|
||||
s = lib.glfwSetX11SelectionString
|
||||
s.restype = None
|
||||
s.argtypes = [ctypes.c_char_p]
|
||||
ans = g, s
|
||||
else:
|
||||
ans = None, None
|
||||
selection_clipboard_funcs.ans = ans
|
||||
return ans
|
||||
|
||||
|
||||
def x11_window_id(window_id):
|
||||
lib = glfw_lib()
|
||||
lib.glfwGetX11Window.restype = ctypes.c_int32
|
||||
lib.glfwGetX11Window.argtypes = [ctypes.c_void_p]
|
||||
return lib.glfwGetX11Window(handle_for_window_id(window_id))
|
||||
|
||||
|
||||
def x11_display():
|
||||
lib = glfw_lib()
|
||||
ans = lib.glfwGetX11Display
|
||||
ans.restype = ctypes.c_void_p
|
||||
ans.argtypes = []
|
||||
return ans()
|
||||
|
||||
|
||||
iswayland = not isosx and hasattr(glfw_lib(), 'glfwGetWaylandDisplay')
|
||||
iswayland = False
|
||||
|
||||
12
kitty/glfw-wrapper.c
generated
12
kitty/glfw-wrapper.c
generated
@ -341,6 +341,18 @@ load_glfw(const char* path) {
|
||||
*(void **) (&glfwGetRequiredInstanceExtensions_impl) = dlsym(handle, "glfwGetRequiredInstanceExtensions");
|
||||
if (glfwGetRequiredInstanceExtensions_impl == NULL) fail("Failed to load glfw function glfwGetRequiredInstanceExtensions with error: %s", dlerror());
|
||||
|
||||
*(void **) (&glfwGetCocoaWindow_impl) = dlsym(handle, "glfwGetCocoaWindow");
|
||||
|
||||
*(void **) (&glfwGetCocoaMonitor_impl) = dlsym(handle, "glfwGetCocoaMonitor");
|
||||
|
||||
*(void **) (&glfwGetX11Display_impl) = dlsym(handle, "glfwGetX11Display");
|
||||
|
||||
*(void **) (&glfwGetX11Window_impl) = dlsym(handle, "glfwGetX11Window");
|
||||
|
||||
*(void **) (&glfwSetX11SelectionString_impl) = dlsym(handle, "glfwSetX11SelectionString");
|
||||
|
||||
*(void **) (&glfwGetX11SelectionString_impl) = dlsym(handle, "glfwGetX11SelectionString");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
24
kitty/glfw-wrapper.h
generated
24
kitty/glfw-wrapper.h
generated
@ -1783,4 +1783,28 @@ typedef const char** (*glfwGetRequiredInstanceExtensions_func)(uint32_t*);
|
||||
glfwGetRequiredInstanceExtensions_func glfwGetRequiredInstanceExtensions_impl;
|
||||
#define glfwGetRequiredInstanceExtensions glfwGetRequiredInstanceExtensions_impl
|
||||
|
||||
typedef void* (*glfwGetCocoaWindow_func)(GLFWwindow*);
|
||||
glfwGetCocoaWindow_func glfwGetCocoaWindow_impl;
|
||||
#define glfwGetCocoaWindow glfwGetCocoaWindow_impl
|
||||
|
||||
typedef uint32_t (*glfwGetCocoaMonitor_func)(GLFWmonitor*);
|
||||
glfwGetCocoaMonitor_func glfwGetCocoaMonitor_impl;
|
||||
#define glfwGetCocoaMonitor glfwGetCocoaMonitor_impl
|
||||
|
||||
typedef void* (*glfwGetX11Display_func)();
|
||||
glfwGetX11Display_func glfwGetX11Display_impl;
|
||||
#define glfwGetX11Display glfwGetX11Display_impl
|
||||
|
||||
typedef int32_t (*glfwGetX11Window_func)(GLFWwindow*);
|
||||
glfwGetX11Window_func glfwGetX11Window_impl;
|
||||
#define glfwGetX11Window glfwGetX11Window_impl
|
||||
|
||||
typedef void (*glfwSetX11SelectionString_func)(const char*);
|
||||
glfwSetX11SelectionString_func glfwSetX11SelectionString_impl;
|
||||
#define glfwSetX11SelectionString glfwSetX11SelectionString_impl
|
||||
|
||||
typedef const char* (*glfwGetX11SelectionString_func)();
|
||||
glfwGetX11SelectionString_func glfwGetX11SelectionString_impl;
|
||||
#define glfwGetX11SelectionString glfwGetX11SelectionString_impl
|
||||
|
||||
const char* load_glfw(const char* path);
|
||||
|
||||
43
kitty/glfw.c
43
kitty/glfw.c
@ -537,6 +537,45 @@ primary_monitor_content_scale(PyObject UNUSED *self) {
|
||||
return Py_BuildValue("ff", xscale, yscale);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
x11_display(PyObject UNUSED *self) {
|
||||
if (glfwGetX11Display) {
|
||||
return PyLong_FromVoidPtr(glfwGetX11Display());
|
||||
} else fprintf(stderr, "Failed to load glfwGetX11Display\n");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
x11_window_id(PyObject UNUSED *self, PyObject *os_wid) {
|
||||
if (glfwGetX11Window) {
|
||||
id_type os_window_id = PyLong_AsUnsignedLongLong(os_wid);
|
||||
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) return Py_BuildValue("l", (long)glfwGetX11Window(w->handle));
|
||||
}
|
||||
}
|
||||
else { PyErr_SetString(PyExc_RuntimeError, "Failed to load glfwGetX11Window"); return NULL; }
|
||||
PyErr_SetString(PyExc_ValueError, "No OSWindow with the specified id found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
get_primary_selection(PyObject UNUSED *self) {
|
||||
if (glfwGetX11SelectionString) {
|
||||
return Py_BuildValue("y", glfwGetX11SelectionString());
|
||||
} else fprintf(stderr, "Failed to load glfwGetX11SelectionString\n");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
set_primary_selection(PyObject UNUSED *self, PyObject *args) {
|
||||
char *text;
|
||||
if (!PyArg_ParseTuple(args, "s", &text)) return NULL;
|
||||
if (glfwSetX11SelectionString) glfwSetX11SelectionString(text);
|
||||
else fprintf(stderr, "Failed to load glfwSetX11SelectionString\n");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
os_window_should_close(PyObject UNUSED *self, PyObject *args) {
|
||||
int q = -1001;
|
||||
@ -584,6 +623,10 @@ static PyMethodDef module_methods[] = {
|
||||
METHODB(glfw_window_hint, METH_VARARGS),
|
||||
METHODB(os_window_should_close, METH_VARARGS),
|
||||
METHODB(os_window_swap_buffers, METH_VARARGS),
|
||||
METHODB(get_primary_selection, METH_NOARGS),
|
||||
METHODB(x11_display, METH_NOARGS),
|
||||
METHODB(x11_window_id, METH_O),
|
||||
METHODB(set_primary_selection, METH_VARARGS),
|
||||
{"glfw_init", (PyCFunction)glfw_init, METH_VARARGS, ""},
|
||||
{"glfw_terminate", (PyCFunction)glfw_terminate, METH_NOARGS, ""},
|
||||
{"glfw_wait_events", (PyCFunction)glfw_wait_events, METH_VARARGS, ""},
|
||||
|
||||
@ -17,13 +17,10 @@ from contextlib import contextmanager
|
||||
from functools import lru_cache
|
||||
from time import monotonic
|
||||
|
||||
from .constants import (
|
||||
appname, isosx, iswayland, selection_clipboard_funcs, x11_display,
|
||||
x11_window_id
|
||||
)
|
||||
from .constants import appname, isosx, iswayland
|
||||
from .fast_data_types import (
|
||||
GLSL_VERSION, glfw_get_physical_dpi, glfw_primary_monitor_content_scale,
|
||||
redirect_std_streams, wcwidth as wcwidth_impl
|
||||
redirect_std_streams, wcwidth as wcwidth_impl, x11_display, x11_window_id
|
||||
)
|
||||
from .rgb import Color, to_color
|
||||
|
||||
@ -75,43 +72,6 @@ def sanitize_title(x):
|
||||
return re.sub(r'\s+', ' ', re.sub(r'[\0-\x19]', '', x))
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def load_libx11():
|
||||
import ctypes
|
||||
from ctypes.util import find_library
|
||||
libx11 = ctypes.CDLL(find_library('X11'))
|
||||
|
||||
def cdef(name, restype, *argtypes):
|
||||
f = getattr(libx11, name)
|
||||
if restype is not None:
|
||||
f.restype = restype
|
||||
if argtypes:
|
||||
f.argtypes = argtypes
|
||||
return f
|
||||
|
||||
return cdef('XResourceManagerString', ctypes.c_char_p, ctypes.c_void_p)
|
||||
|
||||
|
||||
def parse_xrdb(raw):
|
||||
q = 'Xft.dpi:\t'
|
||||
for line in raw.decode('utf-8', 'replace').splitlines():
|
||||
if line.startswith(q):
|
||||
return float(line[len(q):])
|
||||
|
||||
|
||||
def x11_dpi():
|
||||
if iswayland:
|
||||
return
|
||||
XResourceManagerString = load_libx11()
|
||||
display = x11_display()
|
||||
if display:
|
||||
try:
|
||||
raw = XResourceManagerString(display)
|
||||
return parse_xrdb(raw)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def get_logical_dpi(override_dpi=None):
|
||||
# See https://github.com/glfw/glfw/issues/1019 for why we cant use
|
||||
# glfw_get_physical_dpi()
|
||||
@ -122,14 +82,8 @@ def get_logical_dpi(override_dpi=None):
|
||||
# TODO: Investigate if this needs a different implementation on OS X
|
||||
get_logical_dpi.ans = glfw_get_physical_dpi()
|
||||
else:
|
||||
try:
|
||||
xscale, yscale = glfw_primary_monitor_content_scale()
|
||||
except NotImplementedError: # glfw < 3.3
|
||||
xdpi = ydpi = x11_dpi()
|
||||
if xdpi is None:
|
||||
xdpi, ydpi = glfw_get_physical_dpi()
|
||||
else:
|
||||
xdpi, ydpi = xscale * 96.0, yscale * 96.0
|
||||
xscale, yscale = glfw_primary_monitor_content_scale()
|
||||
xdpi, ydpi = xscale * 96.0, yscale * 96.0
|
||||
get_logical_dpi.ans = xdpi, ydpi
|
||||
return get_logical_dpi.ans
|
||||
|
||||
@ -163,32 +117,19 @@ def parse_color_set(raw):
|
||||
|
||||
|
||||
def set_primary_selection(text):
|
||||
if isosx:
|
||||
return # There is no primary selection on OS X
|
||||
if isinstance(text, str):
|
||||
text = text.encode('utf-8')
|
||||
s = selection_clipboard_funcs()[1]
|
||||
if s is None:
|
||||
p = subprocess.Popen(['xsel', '-i', '-p'], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
p.stdin.write(text), p.stdin.close()
|
||||
p.wait()
|
||||
else:
|
||||
s(text)
|
||||
if isosx or iswayland:
|
||||
return # There is no primary selection
|
||||
if isinstance(text, bytes):
|
||||
text = text.decode('utf-8')
|
||||
from kitty.fast_data_types import set_primary_selection
|
||||
set_primary_selection(text)
|
||||
|
||||
|
||||
def get_primary_selection():
|
||||
if isosx:
|
||||
return '' # There is no primary selection on OS X
|
||||
g = selection_clipboard_funcs()[0]
|
||||
if g is None:
|
||||
# We cannot use check_output as we set a SIGCHLD handler to reap zombies
|
||||
ans = subprocess.Popen(['xsel', '-p'], stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE).stdout.read().decode('utf-8')
|
||||
if ans:
|
||||
# Without this for some reason repeated pastes dont work
|
||||
set_primary_selection(ans)
|
||||
else:
|
||||
ans = (g() or b'').decode('utf-8', 'replace')
|
||||
return ans
|
||||
if isosx or iswayland:
|
||||
return '' # There is no primary selection
|
||||
from kitty.fast_data_types import get_primary_selection
|
||||
return (get_primary_selection() or b'').decode('utf-8', 'replace')
|
||||
|
||||
|
||||
def base64_encode(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user