Compare commits
340 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36a20f7b00 | ||
|
|
35cbf49b08 | ||
|
|
21836cedda | ||
|
|
0a892b72e6 | ||
|
|
2c6e5a6e73 | ||
|
|
2cb25cf5a8 | ||
|
|
e07916425e | ||
|
|
f62e2374e4 | ||
|
|
eb4ee2f0af | ||
|
|
be3c76da20 | ||
|
|
b15e58621c | ||
|
|
601a6c9e3d | ||
|
|
3ff184348e | ||
|
|
c8efcd2be1 | ||
|
|
9c116a2975 | ||
|
|
8818b5d8df | ||
|
|
e96dfadae7 | ||
|
|
deb564e5a6 | ||
|
|
ffc71c348c | ||
|
|
19df7b94ea | ||
|
|
a3ecc79f0d | ||
|
|
b140b15119 | ||
|
|
b7b2b6075a | ||
|
|
7525e152b8 | ||
|
|
bc9dfec615 | ||
|
|
7824739034 | ||
|
|
e7b60a3628 | ||
|
|
97c3061b8f | ||
|
|
1a042c873c | ||
|
|
064aa3a150 | ||
|
|
8a178ebe55 | ||
|
|
9a97f0bced | ||
|
|
5c7471910d | ||
|
|
27b6517594 | ||
|
|
cd4dacb406 | ||
|
|
5f6faa1bf0 | ||
|
|
cfc5a952f8 | ||
|
|
10b186957b | ||
|
|
f597481736 | ||
|
|
9fa97e6187 | ||
|
|
3844321f20 | ||
|
|
8efe08c45b | ||
|
|
c78563b452 | ||
|
|
122e172092 | ||
|
|
8f85c0d167 | ||
|
|
ac6d1ce174 | ||
|
|
03e0bf4c0e | ||
|
|
1cb183f5e1 | ||
|
|
d78a553910 | ||
|
|
1326532850 | ||
|
|
408508247d | ||
|
|
e2be09e028 | ||
|
|
c7c14f184c | ||
|
|
24ca919f33 | ||
|
|
85fe783652 | ||
|
|
04b6bf3b74 | ||
|
|
8b2fb105d0 | ||
|
|
558caa232d | ||
|
|
d8886edbeb | ||
|
|
f72ecf1791 | ||
|
|
45d1b978d8 | ||
|
|
0b780cc065 | ||
|
|
5263f6598c | ||
|
|
f9e60e7ef6 | ||
|
|
45c00d0b1f | ||
|
|
c70e2f7d3e | ||
|
|
1ec0bed1ce | ||
|
|
46b5e4513a | ||
|
|
ffb5196f3b | ||
|
|
107f1af3c4 | ||
|
|
03b1484c96 | ||
|
|
aaf64ad63e | ||
|
|
f548e795d5 | ||
|
|
767da68239 | ||
|
|
f44e0ff4bd | ||
|
|
7f226f2ea1 | ||
|
|
1c82a39a6e | ||
|
|
b70cf276b4 | ||
|
|
80b2df2ef4 | ||
|
|
ad27452275 | ||
|
|
196a0b6b7e | ||
|
|
f356f63994 | ||
|
|
4947fb6b57 | ||
|
|
622f12b84e | ||
|
|
c1f84ce603 | ||
|
|
14912461ad | ||
|
|
a9f265e8b7 | ||
|
|
199ee20adb | ||
|
|
7c3c87abf6 | ||
|
|
b0ad44bcf2 | ||
|
|
9ba808ec3c | ||
|
|
eacf849e3a | ||
|
|
42c2791182 | ||
|
|
390e883ecf | ||
|
|
9fe631ee3f | ||
|
|
82d8c4b230 | ||
|
|
9775bb0a9d | ||
|
|
139c9a2d6d | ||
|
|
542880f87b | ||
|
|
3846286bee | ||
|
|
72be402a2d | ||
|
|
c6b9cb759a | ||
|
|
13ccf269a6 | ||
|
|
fcc7a0255a | ||
|
|
e7447f38cf | ||
|
|
7ae35631a6 | ||
|
|
55ad228166 | ||
|
|
48fb051253 | ||
|
|
f97e8b7eeb | ||
|
|
84f914742b | ||
|
|
0d704f3715 | ||
|
|
d8896eb210 | ||
|
|
b9d74e2012 | ||
|
|
803fba9cfd | ||
|
|
581548ed67 | ||
|
|
9a8c0f8e7e | ||
|
|
328f569c16 | ||
|
|
7931654a7c | ||
|
|
6eb0c10339 | ||
|
|
269f294d19 | ||
|
|
d19e2f1350 | ||
|
|
3b745b82db | ||
|
|
02f30c2a03 | ||
|
|
54002b386a | ||
|
|
0e2ff077af | ||
|
|
012cf70321 | ||
|
|
9da0ba52db | ||
|
|
7bfb07e59e | ||
|
|
9cb2c4b1ff | ||
|
|
8c088fad0f | ||
|
|
392722aed0 | ||
|
|
fabfb30fc4 | ||
|
|
c7cb021e92 | ||
|
|
be05d9c3e9 | ||
|
|
e38690e8d9 | ||
|
|
7172115559 | ||
|
|
7314019832 | ||
|
|
b9684941c4 | ||
|
|
a27289352c | ||
|
|
dc77009e55 | ||
|
|
d12e10830d | ||
|
|
936f6c22f0 | ||
|
|
9712be903d | ||
|
|
7441cefdbb | ||
|
|
7bf83603c8 | ||
|
|
6768bc1705 | ||
|
|
707cb37212 | ||
|
|
1cf0a8b78e | ||
|
|
3d2cb37af0 | ||
|
|
09fbd6f5e0 | ||
|
|
474bef65cb | ||
|
|
e97454c4a5 | ||
|
|
936dc74a27 | ||
|
|
362e4266bb | ||
|
|
d08f2e10f1 | ||
|
|
f1e5ee74a6 | ||
|
|
7832d33348 | ||
|
|
de25f94fae | ||
|
|
98625e9c36 | ||
|
|
5768cc98b6 | ||
|
|
da1cc6c1c5 | ||
|
|
50384fac97 | ||
|
|
424bd8a6cd | ||
|
|
421fae2b57 | ||
|
|
8bb8615a5a | ||
|
|
80f8692e92 | ||
|
|
25623c758d | ||
|
|
e1a0a195a9 | ||
|
|
f8cf49a90c | ||
|
|
ac9f8595c9 | ||
|
|
97f22bbff6 | ||
|
|
d6ddfa9d18 | ||
|
|
5e48ae8bac | ||
|
|
cdd943ded4 | ||
|
|
39b2bf963c | ||
|
|
06827fd437 | ||
|
|
70ccc1cf6d | ||
|
|
f801c47d1e | ||
|
|
01c0e8da93 | ||
|
|
e844ad6db3 | ||
|
|
3f8c042bc3 | ||
|
|
707ad705a4 | ||
|
|
79a780004f | ||
|
|
81b28bc1bd | ||
|
|
e9c4d540b1 | ||
|
|
50d9718c68 | ||
|
|
e39da2b2bb | ||
|
|
f08ec1522a | ||
|
|
e61e93712c | ||
|
|
c9e198e02e | ||
|
|
0ce181b578 | ||
|
|
99950fe448 | ||
|
|
d8daf84a09 | ||
|
|
3d32202b3a | ||
|
|
4f4d562670 | ||
|
|
28fc9c69da | ||
|
|
6edf00e699 | ||
|
|
a0d6445dda | ||
|
|
e74797037c | ||
|
|
3fb125dba7 | ||
|
|
3c8640f9ad | ||
|
|
2e63a4c83f | ||
|
|
9da5bee178 | ||
|
|
2fc6f3b542 | ||
|
|
4754f42e51 | ||
|
|
941fe918fb | ||
|
|
f4e82e972e | ||
|
|
f66dbf111d | ||
|
|
1a2da5c49d | ||
|
|
8327dabb29 | ||
|
|
195ea6c140 | ||
|
|
fcc0707174 | ||
|
|
aa9c3cd634 | ||
|
|
b541341681 | ||
|
|
e5d50aca6d | ||
|
|
b738f4d4ff | ||
|
|
5c38aabf0e | ||
|
|
03e9ed6947 | ||
|
|
63493fad22 | ||
|
|
696b857f91 | ||
|
|
53ae2bbe0d | ||
|
|
01069e919d | ||
|
|
fc0095f505 | ||
|
|
421528e130 | ||
|
|
7b70356515 | ||
|
|
e803505aad | ||
|
|
ad1ff455a0 | ||
|
|
7692cb5c3d | ||
|
|
a94e208db3 | ||
|
|
ba9d5cf3ff | ||
|
|
0dff0d03f9 | ||
|
|
c92aca5d19 | ||
|
|
5762baeed7 | ||
|
|
601cf01222 | ||
|
|
0eef48b516 | ||
|
|
3c1954f329 | ||
|
|
cc29640604 | ||
|
|
d0329460b8 | ||
|
|
717c0c96de | ||
|
|
b3f161efce | ||
|
|
0286940163 | ||
|
|
d4a4ee386f | ||
|
|
33498f9133 | ||
|
|
da3d4d1bef | ||
|
|
c69b8870d2 | ||
|
|
85b55b31b6 | ||
|
|
948919e42b | ||
|
|
85c40090ed | ||
|
|
98b50ec145 | ||
|
|
1ab4f7d2d0 | ||
|
|
98801b6fa6 | ||
|
|
bdd68284b5 | ||
|
|
a61d70ea9a | ||
|
|
e271719dd2 | ||
|
|
a08efa1fc5 | ||
|
|
ffac3600e0 | ||
|
|
6499f8ac24 | ||
|
|
63307cb1d8 | ||
|
|
0a6fb362f6 | ||
|
|
457fcbfb90 | ||
|
|
3b6277b9e2 | ||
|
|
e6e61028b1 | ||
|
|
e9be66126b | ||
|
|
681fe7f2f2 | ||
|
|
0196920533 | ||
|
|
5f5bb3ace0 | ||
|
|
3c970e0122 | ||
|
|
43af6e3b8a | ||
|
|
ac8cfc12fb | ||
|
|
b19472e0f5 | ||
|
|
b4d08044a0 | ||
|
|
b2fe02e63f | ||
|
|
d1a5d30233 | ||
|
|
bba30138e1 | ||
|
|
082546a1e7 | ||
|
|
41ffd58e26 | ||
|
|
b4f24e4e1e | ||
|
|
75c8ffd715 | ||
|
|
688606ff7c | ||
|
|
2e3f9dffa7 | ||
|
|
859033415b | ||
|
|
1f1b52b580 | ||
|
|
4e7bf80447 | ||
|
|
e39df50884 | ||
|
|
8d6a9d45c2 | ||
|
|
0862e85577 | ||
|
|
0b9a37139e | ||
|
|
6357f7b811 | ||
|
|
24197dc422 | ||
|
|
9bc2ab3245 | ||
|
|
bf4e8c490c | ||
|
|
590a4d70ee | ||
|
|
40341d2ddd | ||
|
|
0cd2c41ee3 | ||
|
|
5d65cdb6a8 | ||
|
|
759a15ccbb | ||
|
|
5aead5eebe | ||
|
|
a325a5fdee | ||
|
|
931e91f1a7 | ||
|
|
6e13509720 | ||
|
|
5b4844e71e | ||
|
|
66cbbea9bb | ||
|
|
b65119b8a9 | ||
|
|
86703da917 | ||
|
|
610e9afdf0 | ||
|
|
e3af9f68d3 | ||
|
|
747ac85e7c | ||
|
|
8c23f9e526 | ||
|
|
e6e339fcd3 | ||
|
|
f04680ac47 | ||
|
|
90985cc846 | ||
|
|
63917944f2 | ||
|
|
793605f80f | ||
|
|
93a281c7e3 | ||
|
|
8f1c6c4d74 | ||
|
|
1610dba7ab | ||
|
|
d9d419991c | ||
|
|
f9e86b19aa | ||
|
|
fffb976e43 | ||
|
|
0da566b49f | ||
|
|
da55717d20 | ||
|
|
254836902c | ||
|
|
d01f8d1865 | ||
|
|
a46c3f7007 | ||
|
|
4e58062025 | ||
|
|
aa3be0535f | ||
|
|
8ebf5e007c | ||
|
|
c2957e7f12 | ||
|
|
bf7c26d357 | ||
|
|
0547102bdd | ||
|
|
a07369ce69 | ||
|
|
21c5610431 | ||
|
|
6dbdf72f40 | ||
|
|
76a6bba643 | ||
|
|
b0b8222a96 | ||
|
|
0d87b8fac5 | ||
|
|
5227b1f98b | ||
|
|
c4f7c5c1cd | ||
|
|
33a84a609c | ||
|
|
037111715a |
21
.editorconfig
Normal file
21
.editorconfig
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = spaces
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[{Makefile,*.terminfo}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
# Autogenerated files with tabs below this line.
|
||||||
|
|
||||||
|
[kitty/{unicode-data.c,emoji.h,wcwidth-std.h}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[kittens/unicode_input/names.h]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[glfw/wayland-*-protocol.{c,h}]
|
||||||
|
indent_style = tab
|
||||||
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a bug report
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. XXX
|
||||||
|
2. YYY
|
||||||
|
3. ZZZ
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Enviroment details**
|
||||||
|
OS: Name and version of operating system(s)
|
||||||
|
|
||||||
|
```
|
||||||
|
Output of kitty --debug-config
|
||||||
|
```
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Try to reproduce the problem with `kitty --config NONE` if you cannot then post a minimal kitty.conf that reproduces the problem. If the problem involves interaction with some other terminal program post a minimal config for that program to reproduce the problem as well.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,3 +18,4 @@ __pycache__/
|
|||||||
/docs/generated/
|
/docs/generated/
|
||||||
/.mypy_cache
|
/.mypy_cache
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
bypy/b
|
||||||
|
|||||||
75
bypy/init_env.py
Normal file
75
bypy/init_env.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from bypy.constants import (
|
||||||
|
LIBDIR, PREFIX, PYTHON, SRC as KITTY_DIR, ismacos, worker_env
|
||||||
|
)
|
||||||
|
from bypy.utils import run_shell
|
||||||
|
|
||||||
|
|
||||||
|
def read_src_file(name):
|
||||||
|
with open(os.path.join(KITTY_DIR, 'kitty', name), 'rb') as f:
|
||||||
|
return f.read().decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def initialize_constants():
|
||||||
|
kitty_constants = {}
|
||||||
|
src = read_src_file('constants.py')
|
||||||
|
nv = re.search(r'Version\((\d+), (\d+), (\d+)\)', src)
|
||||||
|
kitty_constants['version'] = '%s.%s.%s' % (nv.group(1), nv.group(2), nv.group(3))
|
||||||
|
kitty_constants['appname'] = re.search(
|
||||||
|
r'appname: str\s+=\s+(u{0,1})[\'"]([^\'"]+)[\'"]', src
|
||||||
|
).group(2)
|
||||||
|
return kitty_constants
|
||||||
|
|
||||||
|
|
||||||
|
def run(*args, **extra_env):
|
||||||
|
env = os.environ.copy()
|
||||||
|
env.update(worker_env)
|
||||||
|
env.update(extra_env)
|
||||||
|
env['SW'] = PREFIX
|
||||||
|
env['LD_LIBRARY_PATH'] = LIBDIR
|
||||||
|
if ismacos:
|
||||||
|
env['PKGCONFIG_EXE'] = os.path.join(PREFIX, 'bin', 'pkg-config')
|
||||||
|
cwd = env.pop('cwd', KITTY_DIR)
|
||||||
|
return subprocess.call(list(args), env=env, cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
|
def build_c_extensions(ext_dir, args):
|
||||||
|
writeable_src_dir = os.path.join(ext_dir, 'src')
|
||||||
|
shutil.copytree(
|
||||||
|
KITTY_DIR, writeable_src_dir, symlinks=True,
|
||||||
|
ignore=shutil.ignore_patterns('b', 'build', 'dist', '*_commands.json', '*.o'))
|
||||||
|
cmd = [PYTHON, 'setup.py']
|
||||||
|
bundle = 'macos-freeze' if ismacos else 'linux-freeze'
|
||||||
|
cmd.append(bundle)
|
||||||
|
dest = kitty_constants['appname'] + ('.app' if ismacos else '')
|
||||||
|
dest = os.path.join(ext_dir, dest)
|
||||||
|
cmd += ['--prefix', dest]
|
||||||
|
if run(*cmd, cwd=writeable_src_dir) != 0:
|
||||||
|
print('Building of kitty package failed', file=sys.stderr)
|
||||||
|
os.chdir(KITTY_DIR)
|
||||||
|
run_shell()
|
||||||
|
raise SystemExit('Building of kitty package failed')
|
||||||
|
return ext_dir
|
||||||
|
|
||||||
|
|
||||||
|
def run_tests(path_to_kitty, cwd_on_failure):
|
||||||
|
ret = run(PYTHON, 'test.py', cwd=cwd_on_failure)
|
||||||
|
if ret != 0:
|
||||||
|
os.chdir(cwd_on_failure)
|
||||||
|
print(
|
||||||
|
'running kitty tests failed with return code:', ret, file=sys.stderr)
|
||||||
|
run_shell()
|
||||||
|
raise SystemExit('running kitty tests failed')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == 'program':
|
||||||
|
kitty_constants = initialize_constants()
|
||||||
3
bypy/linux.conf
Normal file
3
bypy/linux.conf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
image 'https://partner-images.canonical.com/core/xenial/current/ubuntu-xenial-core-cloudimg-{}-root.tar.gz'
|
||||||
|
|
||||||
|
deps 'bison flex libxcursor-dev libxrandr-dev libxi-dev libxinerama-dev libgl1-mesa-dev libxcb-xkb-dev libfontconfig1-dev libdbus-1-dev'
|
||||||
209
bypy/linux/__main__.py
Normal file
209
bypy/linux/__main__.py
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import subprocess
|
||||||
|
import tarfile
|
||||||
|
import time
|
||||||
|
|
||||||
|
from bypy.constants import (
|
||||||
|
OUTPUT_DIR, PREFIX, is64bit, python_major_minor_version
|
||||||
|
)
|
||||||
|
from bypy.utils import get_dll_path, py_compile, walk
|
||||||
|
|
||||||
|
j = os.path.join
|
||||||
|
self_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
arch = 'x86_64' if is64bit else 'i686'
|
||||||
|
|
||||||
|
py_ver = '.'.join(map(str, python_major_minor_version()))
|
||||||
|
iv = globals()['init_env']
|
||||||
|
kitty_constants = iv['kitty_constants']
|
||||||
|
|
||||||
|
|
||||||
|
def binary_includes():
|
||||||
|
return tuple(map(get_dll_path, (
|
||||||
|
'expat', 'sqlite3', 'ffi', 'z', 'lzma', 'png16',
|
||||||
|
|
||||||
|
# dont include freetype because fontconfig is closely coupled to it
|
||||||
|
# and also distros often patch freetype
|
||||||
|
# 'iconv.so.2', 'pcre.so.1', 'graphite2.so.3', 'glib-2.0.so.0', 'freetype.so.6',
|
||||||
|
|
||||||
|
'harfbuzz', 'xkbcommon', 'xkbcommon-x11',
|
||||||
|
'ncursesw', 'readline',
|
||||||
|
))) + (
|
||||||
|
get_dll_path('bz2', 2), get_dll_path('ssl', 3), get_dll_path('crypto', 3),
|
||||||
|
get_dll_path('python' + py_ver, 2),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Env:
|
||||||
|
|
||||||
|
def __init__(self, package_dir):
|
||||||
|
self.base = package_dir
|
||||||
|
self.lib_dir = j(self.base, 'lib')
|
||||||
|
self.py_dir = j(self.lib_dir, 'python' + py_ver)
|
||||||
|
os.makedirs(self.py_dir)
|
||||||
|
self.bin_dir = j(self.base, 'bin')
|
||||||
|
|
||||||
|
|
||||||
|
def ignore_in_lib(base, items, ignored_dirs=None):
|
||||||
|
ans = []
|
||||||
|
if ignored_dirs is None:
|
||||||
|
ignored_dirs = {'.svn', '.bzr', '.git', 'test', 'tests', 'testing'}
|
||||||
|
for name in items:
|
||||||
|
path = j(base, name)
|
||||||
|
if os.path.isdir(path):
|
||||||
|
if name in ignored_dirs or not os.path.exists(j(path, '__init__.py')):
|
||||||
|
if name != 'plugins':
|
||||||
|
ans.append(name)
|
||||||
|
else:
|
||||||
|
if name.rpartition('.')[-1] not in ('so', 'py'):
|
||||||
|
ans.append(name)
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def import_site_packages(srcdir, dest):
|
||||||
|
if not os.path.exists(dest):
|
||||||
|
os.mkdir(dest)
|
||||||
|
for x in os.listdir(srcdir):
|
||||||
|
ext = x.rpartition('.')[-1]
|
||||||
|
f = j(srcdir, x)
|
||||||
|
if ext in ('py', 'so'):
|
||||||
|
shutil.copy2(f, dest)
|
||||||
|
elif ext == 'pth' and x != 'setuptools.pth':
|
||||||
|
for line in open(f, 'rb').read().splitlines():
|
||||||
|
src = os.path.abspath(j(srcdir, line))
|
||||||
|
if os.path.exists(src) and os.path.isdir(src):
|
||||||
|
import_site_packages(src, dest)
|
||||||
|
elif os.path.exists(j(f, '__init__.py')):
|
||||||
|
shutil.copytree(f, j(dest, x), ignore=ignore_in_lib)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_libs(env):
|
||||||
|
print('Copying libs...')
|
||||||
|
|
||||||
|
for x in binary_includes():
|
||||||
|
dest = env.bin_dir if '/bin/' in x else env.lib_dir
|
||||||
|
shutil.copy2(x, dest)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_python(env):
|
||||||
|
print('Copying python...')
|
||||||
|
srcdir = j(PREFIX, 'lib/python' + py_ver)
|
||||||
|
|
||||||
|
for x in os.listdir(srcdir):
|
||||||
|
y = j(srcdir, x)
|
||||||
|
ext = os.path.splitext(x)[1]
|
||||||
|
if os.path.isdir(y) and x not in ('test', 'hotshot', 'distutils', 'tkinter', 'turtledemo',
|
||||||
|
'site-packages', 'idlelib', 'lib2to3', 'dist-packages'):
|
||||||
|
shutil.copytree(y, j(env.py_dir, x), ignore=ignore_in_lib)
|
||||||
|
if os.path.isfile(y) and ext in ('.py', '.so'):
|
||||||
|
shutil.copy2(y, env.py_dir)
|
||||||
|
|
||||||
|
srcdir = j(srcdir, 'site-packages')
|
||||||
|
dest = j(env.py_dir, 'site-packages')
|
||||||
|
import_site_packages(srcdir, dest)
|
||||||
|
py_compile(env.py_dir)
|
||||||
|
py_compile(os.path.join(env.base, 'lib', 'kitty'))
|
||||||
|
|
||||||
|
|
||||||
|
def is_elf(path):
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
return f.read(4) == b'\x7fELF'
|
||||||
|
|
||||||
|
|
||||||
|
def fix_permissions(files):
|
||||||
|
for path in files:
|
||||||
|
os.chmod(path, 0o755)
|
||||||
|
|
||||||
|
|
||||||
|
STRIPCMD = ['strip']
|
||||||
|
|
||||||
|
|
||||||
|
def find_binaries(env):
|
||||||
|
files = {j(env.bin_dir, x) for x in os.listdir(env.bin_dir)} | {
|
||||||
|
x for x in {
|
||||||
|
j(os.path.dirname(env.bin_dir), x) for x in os.listdir(env.bin_dir)} if os.path.exists(x)}
|
||||||
|
for x in walk(env.lib_dir):
|
||||||
|
x = os.path.realpath(x)
|
||||||
|
if x not in files and is_elf(x):
|
||||||
|
files.add(x)
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
def strip_files(files, argv_max=(256 * 1024)):
|
||||||
|
""" Strip a list of files """
|
||||||
|
while files:
|
||||||
|
cmd = list(STRIPCMD)
|
||||||
|
pathlen = sum(len(s) + 1 for s in cmd)
|
||||||
|
while pathlen < argv_max and files:
|
||||||
|
f = files.pop()
|
||||||
|
cmd.append(f)
|
||||||
|
pathlen += len(f) + 1
|
||||||
|
if len(cmd) > len(STRIPCMD):
|
||||||
|
all_files = cmd[len(STRIPCMD):]
|
||||||
|
unwritable_files = tuple(filter(None, (None if os.access(x, os.W_OK) else (x, os.stat(x).st_mode) for x in all_files)))
|
||||||
|
[os.chmod(x, stat.S_IWRITE | old_mode) for x, old_mode in unwritable_files]
|
||||||
|
subprocess.check_call(cmd)
|
||||||
|
[os.chmod(x, old_mode) for x, old_mode in unwritable_files]
|
||||||
|
|
||||||
|
|
||||||
|
def strip_binaries(files):
|
||||||
|
print('Stripping %d files...' % len(files))
|
||||||
|
before = sum(os.path.getsize(x) for x in files)
|
||||||
|
strip_files(files)
|
||||||
|
after = sum(os.path.getsize(x) for x in files)
|
||||||
|
print('Stripped %.1f MB' % ((before - after) / (1024 * 1024.)))
|
||||||
|
|
||||||
|
|
||||||
|
def create_tarfile(env, compression_level='9'):
|
||||||
|
print('Creating archive...')
|
||||||
|
base = OUTPUT_DIR
|
||||||
|
try:
|
||||||
|
shutil.rmtree(base)
|
||||||
|
except EnvironmentError as err:
|
||||||
|
if err.errno != errno.ENOENT:
|
||||||
|
raise
|
||||||
|
os.mkdir(base)
|
||||||
|
dist = os.path.join(base, '%s-%s-%s.tar' % (kitty_constants['appname'], kitty_constants['version'], arch))
|
||||||
|
with tarfile.open(dist, mode='w', format=tarfile.PAX_FORMAT) as tf:
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.chdir(env.base)
|
||||||
|
try:
|
||||||
|
for x in os.listdir('.'):
|
||||||
|
tf.add(x)
|
||||||
|
finally:
|
||||||
|
os.chdir(cwd)
|
||||||
|
print('Compressing archive...')
|
||||||
|
ans = dist.rpartition('.')[0] + '.txz'
|
||||||
|
start_time = time.time()
|
||||||
|
subprocess.check_call(['xz', '--threads=0', '-f', '-' + compression_level, dist])
|
||||||
|
secs = time.time() - start_time
|
||||||
|
print('Compressed in %d minutes %d seconds' % (secs // 60, secs % 60))
|
||||||
|
os.rename(dist + '.xz', ans)
|
||||||
|
print('Archive %s created: %.2f MB' % (
|
||||||
|
os.path.basename(ans), os.stat(ans).st_size / (1024.**2)))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = globals()['args']
|
||||||
|
ext_dir = globals()['ext_dir']
|
||||||
|
if not args.skip_tests:
|
||||||
|
run_tests = iv['run_tests']
|
||||||
|
run_tests(None, os.path.join(ext_dir, 'src'))
|
||||||
|
env = Env(os.path.join(ext_dir, kitty_constants['appname']))
|
||||||
|
copy_libs(env)
|
||||||
|
copy_python(env)
|
||||||
|
files = find_binaries(env)
|
||||||
|
fix_permissions(files)
|
||||||
|
if not args.dont_strip:
|
||||||
|
strip_binaries(files)
|
||||||
|
create_tarfile(env, args.compression_level)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
6
bypy/macos.conf
Normal file
6
bypy/macos.conf
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Requires installation of XCode 10.3 and Python 3 and
|
||||||
|
# python3 -m pip install certifi
|
||||||
|
|
||||||
|
vm_name 'macos-kitty-build'
|
||||||
|
root '/Users/Shared/kitty-build'
|
||||||
|
python '/usr/local/bin/python3'
|
||||||
459
bypy/macos/__main__.py
Normal file
459
bypy/macos/__main__.py
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
from bypy.constants import PREFIX, PYTHON, SW, python_major_minor_version
|
||||||
|
from bypy.macos_sign import (
|
||||||
|
codesign, create_entitlements_file, make_certificate_useable, notarize_app,
|
||||||
|
verify_signature
|
||||||
|
)
|
||||||
|
from bypy.utils import current_dir, py_compile, run_shell, timeit, walk
|
||||||
|
|
||||||
|
iv = globals()['init_env']
|
||||||
|
kitty_constants = iv['kitty_constants']
|
||||||
|
join = os.path.join
|
||||||
|
basename = os.path.basename
|
||||||
|
abspath = os.path.abspath
|
||||||
|
APPNAME = kitty_constants['appname']
|
||||||
|
VERSION = kitty_constants['version']
|
||||||
|
py_ver = '.'.join(map(str, python_major_minor_version()))
|
||||||
|
|
||||||
|
|
||||||
|
def flush(func):
|
||||||
|
def ff(*args, **kwargs):
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.stderr.flush()
|
||||||
|
ret = func(*args, **kwargs)
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.stderr.flush()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
return ff
|
||||||
|
|
||||||
|
|
||||||
|
def flipwritable(fn, mode=None):
|
||||||
|
"""
|
||||||
|
Flip the writability of a file and return the old mode. Returns None
|
||||||
|
if the file is already writable.
|
||||||
|
"""
|
||||||
|
if os.access(fn, os.W_OK):
|
||||||
|
return None
|
||||||
|
old_mode = os.stat(fn).st_mode
|
||||||
|
os.chmod(fn, stat.S_IWRITE | old_mode)
|
||||||
|
return old_mode
|
||||||
|
|
||||||
|
|
||||||
|
STRIPCMD = ('/usr/bin/strip', '-x', '-S', '-')
|
||||||
|
|
||||||
|
|
||||||
|
def strip_files(files, argv_max=(256 * 1024)):
|
||||||
|
"""
|
||||||
|
Strip a list of files
|
||||||
|
"""
|
||||||
|
tostrip = [(fn, flipwritable(fn)) for fn in files if os.path.exists(fn)]
|
||||||
|
while tostrip:
|
||||||
|
cmd = list(STRIPCMD)
|
||||||
|
flips = []
|
||||||
|
pathlen = sum(len(s) + 1 for s in cmd)
|
||||||
|
while pathlen < argv_max:
|
||||||
|
if not tostrip:
|
||||||
|
break
|
||||||
|
added, flip = tostrip.pop()
|
||||||
|
pathlen += len(added) + 1
|
||||||
|
cmd.append(added)
|
||||||
|
flips.append((added, flip))
|
||||||
|
else:
|
||||||
|
cmd.pop()
|
||||||
|
tostrip.append(flips.pop())
|
||||||
|
os.spawnv(os.P_WAIT, cmd[0], cmd)
|
||||||
|
for args in flips:
|
||||||
|
flipwritable(*args)
|
||||||
|
|
||||||
|
|
||||||
|
def files_in(folder):
|
||||||
|
for record in os.walk(folder):
|
||||||
|
for f in record[-1]:
|
||||||
|
yield os.path.join(record[0], f)
|
||||||
|
|
||||||
|
|
||||||
|
def expand_dirs(items, exclude=lambda x: x.endswith('.so')):
|
||||||
|
items = set(items)
|
||||||
|
dirs = set(x for x in items if os.path.isdir(x))
|
||||||
|
items.difference_update(dirs)
|
||||||
|
for x in dirs:
|
||||||
|
items.update({y for y in files_in(x) if not exclude(y)})
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
def do_sign(app_dir):
|
||||||
|
with current_dir(os.path.join(app_dir, 'Contents')):
|
||||||
|
# Sign all .so files
|
||||||
|
so_files = {x for x in files_in('.') if x.endswith('.so')}
|
||||||
|
codesign(so_files)
|
||||||
|
# Sign everything else in Frameworks
|
||||||
|
with current_dir('Frameworks'):
|
||||||
|
fw = set(glob.glob('*.framework'))
|
||||||
|
codesign(fw)
|
||||||
|
items = set(os.listdir('.')) - fw
|
||||||
|
codesign(expand_dirs(items))
|
||||||
|
|
||||||
|
# Now sign the main app
|
||||||
|
codesign(app_dir)
|
||||||
|
verify_signature(app_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def sign_app(app_dir, notarize):
|
||||||
|
# Copied from iTerm2: https://github.com/gnachman/iTerm2/blob/master/iTerm2.entitlements
|
||||||
|
create_entitlements_file({
|
||||||
|
'com.apple.security.automation.apple-events': True,
|
||||||
|
'com.apple.security.cs.allow-jit': True,
|
||||||
|
'com.apple.security.device.audio-input': True,
|
||||||
|
'com.apple.security.device.camera': True,
|
||||||
|
'com.apple.security.personal-information.addressbook': True,
|
||||||
|
'com.apple.security.personal-information.calendars': True,
|
||||||
|
'com.apple.security.personal-information.location': True,
|
||||||
|
'com.apple.security.personal-information.photos-library': True,
|
||||||
|
})
|
||||||
|
with make_certificate_useable():
|
||||||
|
do_sign(app_dir)
|
||||||
|
if notarize:
|
||||||
|
notarize_app(app_dir)
|
||||||
|
|
||||||
|
|
||||||
|
class Freeze(object):
|
||||||
|
|
||||||
|
FID = '@executable_path/../Frameworks'
|
||||||
|
|
||||||
|
def __init__(self, build_dir, dont_strip=False, sign_installers=False, notarize=False):
|
||||||
|
self.build_dir = build_dir
|
||||||
|
self.sign_installers = sign_installers
|
||||||
|
self.notarize = notarize
|
||||||
|
self.dont_strip = dont_strip
|
||||||
|
self.contents_dir = join(self.build_dir, 'Contents')
|
||||||
|
self.resources_dir = join(self.contents_dir, 'Resources')
|
||||||
|
self.frameworks_dir = join(self.contents_dir, 'Frameworks')
|
||||||
|
self.to_strip = []
|
||||||
|
self.warnings = []
|
||||||
|
self.py_ver = py_ver
|
||||||
|
self.python_stdlib = join(self.resources_dir, 'Python', 'lib', 'python' + self.py_ver)
|
||||||
|
self.site_packages = self.python_stdlib # hack to avoid needing to add site-packages to path
|
||||||
|
|
||||||
|
self.run()
|
||||||
|
|
||||||
|
def run_shell(self):
|
||||||
|
with current_dir(self.contents_dir):
|
||||||
|
run_shell()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
ret = 0
|
||||||
|
self.add_python_framework()
|
||||||
|
self.add_site_packages()
|
||||||
|
self.add_stdlib()
|
||||||
|
self.add_misc_libraries()
|
||||||
|
self.compile_py_modules()
|
||||||
|
self.fix_dependencies_in_kitty()
|
||||||
|
if not self.dont_strip:
|
||||||
|
self.strip_files()
|
||||||
|
# self.run_shell()
|
||||||
|
|
||||||
|
ret = self.makedmg(self.build_dir, APPNAME + '-' + VERSION)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def strip_files(self):
|
||||||
|
print('\nStripping files...')
|
||||||
|
strip_files(self.to_strip)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def set_id(self, path_to_lib, new_id):
|
||||||
|
old_mode = flipwritable(path_to_lib)
|
||||||
|
subprocess.check_call(
|
||||||
|
['install_name_tool', '-id', new_id, path_to_lib])
|
||||||
|
if old_mode is not None:
|
||||||
|
flipwritable(path_to_lib, old_mode)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def get_dependencies(self, path_to_lib):
|
||||||
|
install_name = subprocess.check_output(
|
||||||
|
['otool', '-D', path_to_lib]).decode('utf-8').splitlines()[-1].strip()
|
||||||
|
raw = subprocess.check_output(['otool', '-L', path_to_lib]).decode('utf-8')
|
||||||
|
for line in raw.splitlines():
|
||||||
|
if 'compatibility' not in line or line.strip().endswith(':'):
|
||||||
|
continue
|
||||||
|
idx = line.find('(')
|
||||||
|
path = line[:idx].strip()
|
||||||
|
yield path, path == install_name
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def get_local_dependencies(self, path_to_lib):
|
||||||
|
for x, is_id in self.get_dependencies(path_to_lib):
|
||||||
|
for y in (PREFIX + '/lib/', PREFIX + '/python/Python.framework/'):
|
||||||
|
if x.startswith(y):
|
||||||
|
if y == PREFIX + '/python/Python.framework/':
|
||||||
|
y = PREFIX + '/python/'
|
||||||
|
yield x, x[len(y):], is_id
|
||||||
|
break
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def change_dep(self, old_dep, new_dep, is_id, path_to_lib):
|
||||||
|
cmd = ['-id', new_dep] if is_id else ['-change', old_dep, new_dep]
|
||||||
|
subprocess.check_call(['install_name_tool'] + cmd + [path_to_lib])
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def fix_dependencies_in_lib(self, path_to_lib):
|
||||||
|
self.to_strip.append(path_to_lib)
|
||||||
|
old_mode = flipwritable(path_to_lib)
|
||||||
|
for dep, bname, is_id in self.get_local_dependencies(path_to_lib):
|
||||||
|
ndep = self.FID + '/' + bname
|
||||||
|
self.change_dep(dep, ndep, is_id, path_to_lib)
|
||||||
|
ldeps = list(self.get_local_dependencies(path_to_lib))
|
||||||
|
if ldeps:
|
||||||
|
print('\nFailed to fix dependencies in', path_to_lib)
|
||||||
|
print('Remaining local dependencies:', ldeps)
|
||||||
|
raise SystemExit(1)
|
||||||
|
if old_mode is not None:
|
||||||
|
flipwritable(path_to_lib, old_mode)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_python_framework(self):
|
||||||
|
print('\nAdding Python framework')
|
||||||
|
src = join(PREFIX + '/python', 'Python.framework')
|
||||||
|
x = join(self.frameworks_dir, 'Python.framework')
|
||||||
|
curr = os.path.realpath(join(src, 'Versions', 'Current'))
|
||||||
|
currd = join(x, 'Versions', basename(curr))
|
||||||
|
rd = join(currd, 'Resources')
|
||||||
|
os.makedirs(rd)
|
||||||
|
shutil.copy2(join(curr, 'Resources', 'Info.plist'), rd)
|
||||||
|
shutil.copy2(join(curr, 'Python'), currd)
|
||||||
|
self.set_id(
|
||||||
|
join(currd, 'Python'),
|
||||||
|
self.FID + '/Python.framework/Versions/%s/Python' % basename(curr))
|
||||||
|
self.fix_dependencies_in_lib(join(self.contents_dir, 'MacOS', 'kitty'))
|
||||||
|
# The following is needed for codesign
|
||||||
|
with current_dir(x):
|
||||||
|
os.symlink(basename(curr), 'Versions/Current')
|
||||||
|
for y in ('Python', 'Resources'):
|
||||||
|
os.symlink('Versions/Current/%s' % y, y)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def install_dylib(self, path, set_id=True):
|
||||||
|
shutil.copy2(path, self.frameworks_dir)
|
||||||
|
if set_id:
|
||||||
|
self.set_id(
|
||||||
|
join(self.frameworks_dir, basename(path)),
|
||||||
|
self.FID + '/' + basename(path))
|
||||||
|
self.fix_dependencies_in_lib(join(self.frameworks_dir, basename(path)))
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_misc_libraries(self):
|
||||||
|
for x in (
|
||||||
|
'sqlite3.0',
|
||||||
|
'z.1',
|
||||||
|
'harfbuzz.0',
|
||||||
|
'png16.16',
|
||||||
|
'crypto.1.0.0',
|
||||||
|
'ssl.1.0.0',
|
||||||
|
):
|
||||||
|
print('\nAdding', x)
|
||||||
|
x = 'lib%s.dylib' % x
|
||||||
|
src = join(PREFIX, 'lib', x)
|
||||||
|
shutil.copy2(src, self.frameworks_dir)
|
||||||
|
dest = join(self.frameworks_dir, x)
|
||||||
|
self.set_id(dest, self.FID + '/' + x)
|
||||||
|
self.fix_dependencies_in_lib(dest)
|
||||||
|
base = join(self.frameworks_dir, 'kitty')
|
||||||
|
for lib in walk(base):
|
||||||
|
if lib.endswith('.so'):
|
||||||
|
self.set_id(lib, self.FID + '/' + os.path.relpath(lib, self.frameworks_dir))
|
||||||
|
self.fix_dependencies_in_lib(lib)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_package_dir(self, x, dest=None):
|
||||||
|
def ignore(root, files):
|
||||||
|
ans = []
|
||||||
|
for y in files:
|
||||||
|
ext = os.path.splitext(y)[1]
|
||||||
|
if ext not in ('', '.py', '.so') or \
|
||||||
|
(not ext and not os.path.isdir(join(root, y))):
|
||||||
|
ans.append(y)
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
if dest is None:
|
||||||
|
dest = self.site_packages
|
||||||
|
dest = join(dest, basename(x))
|
||||||
|
shutil.copytree(x, dest, symlinks=True, ignore=ignore)
|
||||||
|
self.postprocess_package(x, dest)
|
||||||
|
for f in walk(dest):
|
||||||
|
if f.endswith('.so'):
|
||||||
|
self.fix_dependencies_in_lib(f)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def fix_dependencies_in_kitty(self):
|
||||||
|
for f in walk(join(self.resources_dir, 'kitty')):
|
||||||
|
if f.endswith('.so'):
|
||||||
|
self.fix_dependencies_in_lib(f)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def postprocess_package(self, src_path, dest_path):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_stdlib(self):
|
||||||
|
print('\nAdding python stdlib')
|
||||||
|
src = PREFIX + '/python/Python.framework/Versions/Current/lib/python' + self.py_ver
|
||||||
|
dest = self.python_stdlib
|
||||||
|
if not os.path.exists(dest):
|
||||||
|
os.makedirs(dest)
|
||||||
|
for x in os.listdir(src):
|
||||||
|
if x in ('site-packages', 'config', 'test', 'lib2to3', 'lib-tk',
|
||||||
|
'lib-old', 'idlelib', 'plat-mac', 'plat-darwin',
|
||||||
|
'site.py', 'distutils', 'turtledemo', 'tkinter'):
|
||||||
|
continue
|
||||||
|
x = join(src, x)
|
||||||
|
if os.path.isdir(x):
|
||||||
|
self.add_package_dir(x, dest)
|
||||||
|
elif os.path.splitext(x)[1] in ('.so', '.py'):
|
||||||
|
shutil.copy2(x, dest)
|
||||||
|
dest2 = join(dest, basename(x))
|
||||||
|
if dest2.endswith('.so'):
|
||||||
|
self.fix_dependencies_in_lib(dest2)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_site_packages(self):
|
||||||
|
print('\nAdding site-packages')
|
||||||
|
os.makedirs(self.site_packages)
|
||||||
|
sys_path = json.loads(subprocess.check_output([
|
||||||
|
PYTHON, '-c', 'import sys, json; json.dump(sys.path, sys.stdout)']))
|
||||||
|
paths = reversed(tuple(map(abspath, [x for x in sys_path if x.startswith('/') and not x.startswith('/Library/')])))
|
||||||
|
upaths = []
|
||||||
|
for x in paths:
|
||||||
|
if x not in upaths and (x.endswith('.egg') or x.endswith('/site-packages')):
|
||||||
|
upaths.append(x)
|
||||||
|
for x in upaths:
|
||||||
|
print('\t', x)
|
||||||
|
tdir = None
|
||||||
|
try:
|
||||||
|
if not os.path.isdir(x):
|
||||||
|
zf = zipfile.ZipFile(x)
|
||||||
|
tdir = tempfile.mkdtemp()
|
||||||
|
zf.extractall(tdir)
|
||||||
|
x = tdir
|
||||||
|
self.add_modules_from_dir(x)
|
||||||
|
self.add_packages_from_dir(x)
|
||||||
|
finally:
|
||||||
|
if tdir is not None:
|
||||||
|
shutil.rmtree(tdir)
|
||||||
|
self.remove_bytecode(self.site_packages)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_modules_from_dir(self, src):
|
||||||
|
for x in glob.glob(join(src, '*.py')) + glob.glob(join(src, '*.so')):
|
||||||
|
shutil.copy2(x, self.site_packages)
|
||||||
|
if x.endswith('.so'):
|
||||||
|
self.fix_dependencies_in_lib(x)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def add_packages_from_dir(self, src):
|
||||||
|
for x in os.listdir(src):
|
||||||
|
x = join(src, x)
|
||||||
|
if os.path.isdir(x) and os.path.exists(join(x, '__init__.py')):
|
||||||
|
if self.filter_package(basename(x)):
|
||||||
|
continue
|
||||||
|
self.add_package_dir(x)
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def filter_package(self, name):
|
||||||
|
return name in ('Cython', 'modulegraph', 'macholib', 'py2app',
|
||||||
|
'bdist_mpkg', 'altgraph')
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def remove_bytecode(self, dest):
|
||||||
|
for x in os.walk(dest):
|
||||||
|
root = x[0]
|
||||||
|
for f in x[-1]:
|
||||||
|
if os.path.splitext(f) == '.pyc':
|
||||||
|
os.remove(join(root, f))
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def compile_py_modules(self):
|
||||||
|
print('\nCompiling Python modules')
|
||||||
|
self.remove_bytecode(join(self.resources_dir, 'Python'))
|
||||||
|
py_compile(join(self.resources_dir, 'Python'))
|
||||||
|
self.remove_bytecode(join(self.resources_dir, 'kitty'))
|
||||||
|
py_compile(join(self.resources_dir, 'kitty'))
|
||||||
|
|
||||||
|
@flush
|
||||||
|
def makedmg(self, d, volname, internet_enable=True, format='ULFO'):
|
||||||
|
''' Copy a directory d into a dmg named volname '''
|
||||||
|
print('\nMaking dmg...')
|
||||||
|
sys.stdout.flush()
|
||||||
|
destdir = os.path.join(SW, 'dist')
|
||||||
|
try:
|
||||||
|
shutil.rmtree(destdir)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
os.mkdir(destdir)
|
||||||
|
dmg = os.path.join(destdir, volname + '.dmg')
|
||||||
|
if os.path.exists(dmg):
|
||||||
|
os.unlink(dmg)
|
||||||
|
tdir = tempfile.mkdtemp()
|
||||||
|
appdir = os.path.join(tdir, os.path.basename(d))
|
||||||
|
shutil.copytree(d, appdir, symlinks=True)
|
||||||
|
if self.sign_installers:
|
||||||
|
with timeit() as times:
|
||||||
|
sign_app(appdir, self.notarize)
|
||||||
|
print('Signing completed in %d minutes %d seconds' % tuple(times))
|
||||||
|
os.symlink('/Applications', os.path.join(tdir, 'Applications'))
|
||||||
|
size_in_mb = int(
|
||||||
|
subprocess.check_output(['du', '-s', '-k', tdir]).decode('utf-8')
|
||||||
|
.split()[0]) / 1024.
|
||||||
|
cmd = [
|
||||||
|
'/usr/bin/hdiutil', 'create', '-srcfolder', tdir, '-volname',
|
||||||
|
volname, '-format', format
|
||||||
|
]
|
||||||
|
if 190 < size_in_mb < 250:
|
||||||
|
# We need -size 255m because of a bug in hdiutil. When the size of
|
||||||
|
# srcfolder is close to 200MB hdiutil fails with
|
||||||
|
# diskimages-helper: resize request is above maximum size allowed.
|
||||||
|
cmd += ['-size', '255m']
|
||||||
|
print('\nCreating dmg...')
|
||||||
|
with timeit() as times:
|
||||||
|
subprocess.check_call(cmd + [dmg])
|
||||||
|
if internet_enable:
|
||||||
|
subprocess.check_call(
|
||||||
|
['/usr/bin/hdiutil', 'internet-enable', '-yes', dmg])
|
||||||
|
print('dmg created in %d minutes and %d seconds' % tuple(times))
|
||||||
|
shutil.rmtree(tdir)
|
||||||
|
size = os.stat(dmg).st_size / (1024 * 1024.)
|
||||||
|
print('\nInstaller size: %.2fMB\n' % size)
|
||||||
|
return dmg
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = globals()['args']
|
||||||
|
ext_dir = globals()['ext_dir']
|
||||||
|
if not args.skip_tests:
|
||||||
|
run_tests = iv['run_tests']
|
||||||
|
run_tests(None, os.path.join(ext_dir, 'src'))
|
||||||
|
Freeze(
|
||||||
|
os.path.join(ext_dir, kitty_constants['appname'] + '.app'),
|
||||||
|
dont_strip=args.dont_strip,
|
||||||
|
sign_installers=args.sign_installers,
|
||||||
|
notarize=args.notarize
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
1
bypy/rsync.conf
Normal file
1
bypy/rsync.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
to_vm_excludes '/build /dist /kitty/launcher/kitty /.build-cache /tags __pycache__ /*_commands.json *.so *.pyd *.pyc'
|
||||||
256
bypy/sources.json
Normal file
256
bypy/sources.json
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "zlib",
|
||||||
|
"unix": {
|
||||||
|
"filename": "zlib-1.2.11.tar.xz",
|
||||||
|
"hash": "sha256:4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066",
|
||||||
|
"urls": ["https://zlib.net/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "bzip2",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "bzip2-1.0.8.tar.gz",
|
||||||
|
"hash": "sha256:ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269",
|
||||||
|
"urls": ["https://www.sourceware.org/pub/bzip2/bzip2-latest.tar.gz"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "pkg-config",
|
||||||
|
"os": "macos",
|
||||||
|
"unix": {
|
||||||
|
"filename": "pkg-config-0.29.2.tar.gz",
|
||||||
|
"hash": "sha256:6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591",
|
||||||
|
"urls": ["https://pkg-config.freedesktop.org/releases/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "expat",
|
||||||
|
"unix": {
|
||||||
|
"filename": "expat-2.2.6.tar.bz2",
|
||||||
|
"hash": "sha256:17b43c2716d521369f82fc2dc70f359860e90fa440bea65b3b85f0b246ea81f2",
|
||||||
|
"urls": ["https://github.com/libexpat/libexpat/releases/download/R_2_2_6/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "xkbcommon",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "libxkbcommon-0.10.0.tar.xz",
|
||||||
|
"hash": "sha256:57c3630cdc38fb4734cd57fa349e92244f5ae3862813e533cedbd86721a0b6f2",
|
||||||
|
"urls": ["http://xkbcommon.org/download/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "sqlite",
|
||||||
|
"unix": {
|
||||||
|
"filename": "sqlite-autoconf-3310100.tar.gz",
|
||||||
|
"hash": "sha1:0c30f5b22152a8166aa3bebb0f4bc1f3e9cc508b",
|
||||||
|
"urls": ["https://www.sqlite.org/2020/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "libffi",
|
||||||
|
"unix": {
|
||||||
|
"filename": "libffi-3.2.1.tar.gz",
|
||||||
|
"hash": "sha1:280c265b789e041c02e5c97815793dfc283fb1e6",
|
||||||
|
"urls": ["ftp://sourceware.org/pub/libffi/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "openssl",
|
||||||
|
"unix": {
|
||||||
|
"filename": "openssl-1.0.2u.tar.gz",
|
||||||
|
"hash": "sha256:ecd0c6ffb493dd06707d38b14bb4d8c2288bb7033735606569d8f90f89669d16",
|
||||||
|
"urls": ["https://www.openssl.org/source/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "ncurses",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "ncurses-6.2.tar.gz",
|
||||||
|
"hash": "sha256:30306e0c76e0f9f1f0de987cf1c82a5c21e1ce6568b9227f7da5b71cbea86c9d",
|
||||||
|
"urls": ["https://invisible-mirror.net/archives/ncurses/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "readline",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "readline-8.0.tar.gz",
|
||||||
|
"hash": "sha256:e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461",
|
||||||
|
"urls": ["http://ftp.gnu.org/gnu/readline/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "xz",
|
||||||
|
"os": "macos,linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "xz-5.2.5.tar.gz",
|
||||||
|
"hash": "sha256:f6f4910fd033078738bd82bfba4f49219d03b17eb0794eb91efbae419f4aba10",
|
||||||
|
"urls": ["https://tukaani.org/xz/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "python",
|
||||||
|
"unix": {
|
||||||
|
"filename": "Python-3.8.3.tar.xz",
|
||||||
|
"hash": "sha256:dfab5ec723c218082fe3d5d7ae17ecbdebffa9a1aea4d64aa3a2ecdd2e795864",
|
||||||
|
"urls": ["https://www.python.org/ftp/python/3.8.3/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "setuptools",
|
||||||
|
"unix": {
|
||||||
|
"filename": "setuptools-41.0.1.zip",
|
||||||
|
"hash": "sha256:a222d126f5471598053c9a77f4b5d4f26eaa1f150ad6e01dcf1a42e185d05613",
|
||||||
|
"urls": ["pypi"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "pygments",
|
||||||
|
"unix": {
|
||||||
|
"filename": "Pygments-2.6.1.tar.gz",
|
||||||
|
"hash": "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44",
|
||||||
|
"urls": ["pypi"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "cmake",
|
||||||
|
"os": "macos",
|
||||||
|
"unix": {
|
||||||
|
"filename": "cmake-3.6.0.tar.gz",
|
||||||
|
"hash": "sha1:6b0d2d7d93c2e74f8890c4b8b824deb3b36d24b6",
|
||||||
|
"urls": ["https://cmake.org/files/v3.6/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "libpng",
|
||||||
|
"unix": {
|
||||||
|
"filename": "libpng-1.6.37.tar.xz",
|
||||||
|
"hash": "sha256:505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca",
|
||||||
|
"urls": ["http://downloads.sourceforge.net/sourceforge/libpng/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "graphite",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "graphite2-1.3.5.tgz",
|
||||||
|
"hash": "md5:5b8d22a8bbf031838e31432868c0109c",
|
||||||
|
"urls": ["http://downloads.sourceforge.net/silgraphite/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "pcre",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "pcre-8.42.tar.bz2",
|
||||||
|
"hash": "md5:085b6aa253e0f91cae70b3cdbe8c1ac2",
|
||||||
|
"urls": ["https://ftp.pcre.org/pub/pcre/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "iconv",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "libiconv-1.16.tar.gz",
|
||||||
|
"hash": "sha256:e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04",
|
||||||
|
"urls": ["http://ftp.gnu.org/pub/gnu/libiconv/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "glib",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "glib-2.57.1.tar.xz",
|
||||||
|
"hash": "sha256:d029e7c4536835f1f103472f7510332c28d58b9b7d6cd0e9f45c2653e670d9b4",
|
||||||
|
"urls": ["http://ftp.gnome.org/pub/GNOME/sources/glib/2.57/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "freetype",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "freetype-2.9.1.tar.bz2",
|
||||||
|
"hash": "md5:60ef7d8160cd4bf8cb118ee9d65367ca",
|
||||||
|
"urls": ["https://download.savannah.gnu.org/releases/freetype/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "fontconfig",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "fontconfig-2.12.0.tar.bz2",
|
||||||
|
"hash": "sha256:b433e4efff1f68fdd8aac221ed1df3ff1e580ffedbada020a703fe64017d8224",
|
||||||
|
"urls": ["http://www.fontconfig.org/release/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "harfbuzz",
|
||||||
|
"unix": {
|
||||||
|
"filename": "harfbuzz-1.7.2.tar.bz2",
|
||||||
|
"hash": "sha256:a790585e35c1a87f0dcc23580c84b7cc2324e6f67a2946178d278c2a36c790cb",
|
||||||
|
"urls": ["https://www.freedesktop.org/software/harfbuzz/release/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "libxml2",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "libxml2-2.9.4.tar.gz",
|
||||||
|
"hash": "sha1:958ae70baf186263a4bd801a81dd5d682aedd1db",
|
||||||
|
"urls": ["ftp://xmlsoft.org/libxml2/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "wayland",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "wayland-1.18.0.tar.xz",
|
||||||
|
"hash": "sha256:4675a79f091020817a98fd0484e7208c8762242266967f55a67776936c2e294d",
|
||||||
|
"urls": ["https://wayland.freedesktop.org/releases/{filename}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "wayland-protocols",
|
||||||
|
"os": "linux",
|
||||||
|
"unix": {
|
||||||
|
"filename": "wayland-protocols-1.20.tar.xz",
|
||||||
|
"hash": "sha256:9782b7a1a863d82d7c92478497d13c758f52e7da4f197aa16443f73de77e4de7",
|
||||||
|
"urls": ["https://wayland.freedesktop.org/releases/{filename}"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
@@ -46,7 +46,7 @@ particular desktop, but it should work for most major desktop environments.
|
|||||||
# Place the kitty.desktop file somewhere it can be found by the OS
|
# Place the kitty.desktop file somewhere it can be found by the OS
|
||||||
cp ~/.local/kitty.app/share/applications/kitty.desktop ~/.local/share/applications
|
cp ~/.local/kitty.app/share/applications/kitty.desktop ~/.local/share/applications
|
||||||
# Update the path to the kitty icon in the kitty.desktop file
|
# Update the path to the kitty icon in the kitty.desktop file
|
||||||
sed -i "s/Icon\=kitty/Icon\=\/home\/$USER\/.local\/kitty.app\/share\/icons\/hicolor\/256x256\/apps\/kitty.png/g" ~/.local/share/applications/kitty.desktop
|
sed -i "s|Icon=kitty|Icon=/home/$USER/.local/kitty.app/share/icons/hicolor/256x256/apps/kitty.png|g" ~/.local/share/applications/kitty.desktop
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,194 @@ Changelog
|
|||||||
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
|
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
|
||||||
To update |kitty|, :doc:`follow the instructions <binary>`.
|
To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||||
|
|
||||||
|
0.18.1 [2020-06-23]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- macOS: Fix for diff kitten not working with python 3.8 (:iss:`2780`)
|
||||||
|
|
||||||
|
|
||||||
|
0.18.0 [2020-06-20]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Allow multiple overlay windows per normal window
|
||||||
|
|
||||||
|
- Add an option :opt:`confirm_os_window_close` to ask for confirmation
|
||||||
|
when closing an OS window with multiple kitty windows.
|
||||||
|
|
||||||
|
- Tall and Fat layouts: Add a ``mirrored`` option to put the full size window
|
||||||
|
on the opposite edge of the screen (:iss:`2654`)
|
||||||
|
|
||||||
|
- Tall and Fat layouts: Add mappable actions to increase or decrease the number
|
||||||
|
of full size windows (:iss:`2688`)
|
||||||
|
|
||||||
|
- Allow sending arbitrary signals to the current foreground process in a window
|
||||||
|
using either a mapping in kitty.conf or via remote control (:iss:`2778`)
|
||||||
|
|
||||||
|
- Allow sending the back and forward mouse buttons to terminal applications
|
||||||
|
(:pull:`2742`)
|
||||||
|
|
||||||
|
- **Backwards incompatibility**: The numbers used to encode mouse buttons
|
||||||
|
for the ``send_mouse_event`` function that can be used in kittens have
|
||||||
|
been changed (see :ref:`send_mouse_event`).
|
||||||
|
|
||||||
|
- Add a new mappable ``quit`` action to quit kitty completely.
|
||||||
|
|
||||||
|
- Fix marks using different colors with regexes using only a single color
|
||||||
|
(:pull:`2663`)
|
||||||
|
|
||||||
|
- Linux: Workaround for broken Nvidia drivers for old cards (:iss:`456`)
|
||||||
|
|
||||||
|
- Wayland: Fix kitty being killed on some Wayland compositors if a hidden window
|
||||||
|
has a lot of output (:iss:`2329`)
|
||||||
|
|
||||||
|
- BSD: Fix controlling terminal not being established (:pull:`2686`)
|
||||||
|
|
||||||
|
- Add support for the CSI REP escape code (:pull:`2702`)
|
||||||
|
|
||||||
|
- Wayland: Fix mouse cursor rendering on HiDPI screens (:pull:`2709`)
|
||||||
|
|
||||||
|
- X11: Recompile keymaps on XkbNewKeyboardNotify events (:iss:`2726`)
|
||||||
|
|
||||||
|
- X11: Reduce startup time by ~25% by only querying GLX for framebuffer
|
||||||
|
configurations once (:iss:`2754`)
|
||||||
|
|
||||||
|
- macOS: Notarize the kitty application bundle (:iss:`2040`)
|
||||||
|
|
||||||
|
- Fix the kitty shell launched via a mapping needlessly requiring
|
||||||
|
:opt:`allow_remote_control` to be turned on.
|
||||||
|
|
||||||
|
|
||||||
|
0.17.4 [2020-05-09]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Allow showing the name of the current layout and the number of windows
|
||||||
|
in tab titles (:iss:`2634`)
|
||||||
|
|
||||||
|
- macOS: Fix a regression in the previous release that caused ligatures to be
|
||||||
|
not be centered horizontally (:iss:`2591`)
|
||||||
|
|
||||||
|
- By default, double clicking no longer considers the : as part of words, see
|
||||||
|
:opt:`select_by_word_characters` (:iss:`2602`)
|
||||||
|
|
||||||
|
- Fix a regression that caused clicking in the padding/margins of windows in
|
||||||
|
the stack layout to switch the window to the first window (:iss:`2604`)
|
||||||
|
|
||||||
|
- macOS: Fix a regression that broke drag and drop (:iss:`2605`)
|
||||||
|
|
||||||
|
- Report modifier key state when sending wheel events to the terminal program
|
||||||
|
|
||||||
|
- Fix kitty @ send-text not working with text larger than 1024 bytes when using
|
||||||
|
:option:`kitty --listen-on` (:iss:`2607`)
|
||||||
|
|
||||||
|
- Wayland: Fix OS window title not updating for hidden windows (:iss:`2629`)
|
||||||
|
|
||||||
|
- Fix :opt:`background_tint` making the window semi-transparent (:iss:`2618`)
|
||||||
|
|
||||||
|
|
||||||
|
0.17.3 [2020-04-23]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Allow individually setting margins and padding for each edge (left, right,
|
||||||
|
top, bottom). Margins can also be controlled per window via remote control
|
||||||
|
(:iss:`2546`)
|
||||||
|
|
||||||
|
- Fix reverse video not being rendered correctly when using transparency or a
|
||||||
|
background image (:iss:`2419`)
|
||||||
|
|
||||||
|
- Allow mapping arbitrary remote control commands to key presses in
|
||||||
|
:file:`kitty.conf`
|
||||||
|
|
||||||
|
- X11: Fix crash when doing drag and drop from some applications (:iss:`2505`)
|
||||||
|
|
||||||
|
- Fix :option:`launch --stdin-add-formatting` not working (:iss:`2512`)
|
||||||
|
|
||||||
|
- Update to Unicode 13.0 (:iss:`2513`)
|
||||||
|
|
||||||
|
- Render country flags designated by a pair of unicode codepoints
|
||||||
|
in two cells instead of four.
|
||||||
|
|
||||||
|
- diff kitten: New option to control the background color for filler lines in
|
||||||
|
the margin (:iss:`2518`)
|
||||||
|
|
||||||
|
- Fix specifying options for layouts in the startup session file not working
|
||||||
|
(:iss:`2520`)
|
||||||
|
|
||||||
|
- macOS: Fix incorrect horizontal positioning of some full-width East Asian characters
|
||||||
|
(:iss:`1457`)
|
||||||
|
|
||||||
|
- macOS: Render multi-cell PUA characters centered, matching behavior on other
|
||||||
|
platforms
|
||||||
|
|
||||||
|
- Linux: Ignore keys if they are designated as layout/group/mode switch keys
|
||||||
|
(:iss:`2519`)
|
||||||
|
|
||||||
|
- Marks: Fix marks not handling wide characters and tab characters correctly
|
||||||
|
(:iss:`2534`)
|
||||||
|
|
||||||
|
- Add a new :opt:`listen_on` option in kitty.conf to set :option:`kitty --listen-on`
|
||||||
|
globally. Also allow using environment variables in this option (:iss:`2569`).
|
||||||
|
|
||||||
|
- Allow sending mouse events in kittens (:pull:`2538`)
|
||||||
|
|
||||||
|
- icat kitten: Fix display of 16-bit depth images (:iss:`2542`)
|
||||||
|
|
||||||
|
- Add ncurses specific terminfo definitions for strikethrough (:pull:`2567`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that broke displaying graphics over SSH
|
||||||
|
(:iss:`2568`)
|
||||||
|
|
||||||
|
- Fix :option:`--title` not being applied at window creation time (:iss:`2570`)
|
||||||
|
|
||||||
|
0.17.2 [2020-03-29]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Add a :option:`launch --watcher` option that allows defining callbacks
|
||||||
|
that are called for various events in the window's life-cycle (:iss:`2440`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that broke drawing of borders with non-minimal
|
||||||
|
borders (:iss:`2474`)
|
||||||
|
|
||||||
|
- Hints kitten: Allow copying to primary selection as well as clipboard
|
||||||
|
(:pull:`2487`)
|
||||||
|
|
||||||
|
- Add a new mappable action ``close_other_windows_in_tab`` to close all but the
|
||||||
|
active window (:iss:`2484`)
|
||||||
|
|
||||||
|
- Hints kitten: Adjust the default regex used to detect line numbers to handle
|
||||||
|
line+column numbers (:iss:`2268`)
|
||||||
|
|
||||||
|
- Fix blank space at the start of tab bar in the powerline style when first tab is
|
||||||
|
inactive (:iss:`2478`)
|
||||||
|
|
||||||
|
- Fix regression causing incorrect rendering of separators in tab bar when
|
||||||
|
defining a tab bar background color (:pull:`2480`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that broke the kitty @ launch remote command and
|
||||||
|
also broke the --tab-title option when creating a new tab. (:iss:`2488`)
|
||||||
|
|
||||||
|
- Linux: Fix selection of fonts with multiple width variants not preferring
|
||||||
|
the normal width faces (:iss:`2491`)
|
||||||
|
|
||||||
|
|
||||||
|
0.17.1 [2020-03-24]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Fix :opt:`cursor_underline_thickness` not working (:iss:`2465`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that caused tab bar background to be rendered after
|
||||||
|
the last tab as well (:iss:`2464`)
|
||||||
|
|
||||||
|
- macOS: Fix a regression in 0.17 that caused incorrect variants to be
|
||||||
|
automatically selected for some fonts (:iss:`2462`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that caused kitty @ set-colors to require setting
|
||||||
|
cursor_text_color (:iss:`2470`)
|
||||||
|
|
||||||
|
|
||||||
0.17.0 [2020-03-24]
|
0.17.0 [2020-03-24]
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
- A new :ref:`splits_layout` to arrange windows in arbitrary splits
|
- :ref:`splits_layout` to arrange windows in arbitrary splits
|
||||||
(:iss:`2308`)
|
(:iss:`2308`)
|
||||||
|
|
||||||
- Add support for specifying a background image, see :opt:`background_image`
|
- Add support for specifying a background image, see :opt:`background_image`
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ if you specify a program-to-run you can use the special placeholder
|
|||||||
p('\n\n' + as_rst(
|
p('\n\n' + as_rst(
|
||||||
global_options_spec, message=cli_msg, usage='command ...', appname='kitty @'))
|
global_options_spec, message=cli_msg, usage='command ...', appname='kitty @'))
|
||||||
from kitty.rc.base import cli_params_for
|
from kitty.rc.base import cli_params_for
|
||||||
for cmd_name in all_command_names():
|
for cmd_name in sorted(all_command_names()):
|
||||||
func = command_for_name(cmd_name)
|
func = command_for_name(cmd_name)
|
||||||
p(f'.. _at_{func.name}:\n')
|
p(f'.. _at_{func.name}:\n')
|
||||||
p('kitty @', func.name + '\n' + '-' * 120)
|
p('kitty @', func.name + '\n' + '-' * 120)
|
||||||
@@ -326,7 +326,7 @@ def write_remote_control_protocol_docs() -> None: # {{{
|
|||||||
p(' ', desc), p()
|
p(' ', desc), p()
|
||||||
p(), p()
|
p(), p()
|
||||||
|
|
||||||
with open(f'generated/rc.rst', 'w') as f:
|
with open('generated/rc.rst', 'w') as f:
|
||||||
p = partial(print, file=f)
|
p = partial(print, file=f)
|
||||||
for name in sorted(all_command_names()):
|
for name in sorted(all_command_names()):
|
||||||
cmd = command_for_name(name)
|
cmd = command_for_name(name)
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ only monospace fonts, since every cell in the grid has to be the same size. If
|
|||||||
your font is not listed in ``kitty list-fonts`` it means that it is not
|
your font is not listed in ``kitty list-fonts`` it means that it is not
|
||||||
monospace. On Linux you can list all monospace fonts with::
|
monospace. On Linux you can list all monospace fonts with::
|
||||||
|
|
||||||
fc-list : family spacing | grep -e spacing=100 -e spacing=90
|
fc-list : family spacing outline scalable | grep -e spacing=100 -e spacing=90 | grep -e outline=True | grep -e scalable=True
|
||||||
|
|
||||||
Note that the spacing property is calculated by fontconfig based on actual
|
Note that the spacing property is calculated by fontconfig based on actual
|
||||||
glyph widths in the font. If for some reason fontconfig concludes your favorite
|
glyph widths in the font. If for some reason fontconfig concludes your favorite
|
||||||
@@ -179,7 +179,7 @@ following :file:`~/.config/fontconfig/fonts.conf`::
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||||
<fontconfig>
|
<fontconfig>
|
||||||
<match target="scan">
|
<match target="font">
|
||||||
<test name="family">
|
<test name="family">
|
||||||
<string>Your Font Family Name</string>
|
<string>Your Font Family Name</string>
|
||||||
</test>
|
</test>
|
||||||
|
|||||||
@@ -30,10 +30,11 @@ alpha-blending and text over graphics.
|
|||||||
|
|
||||||
Some programs that use the kitty graphics protocol:
|
Some programs that use the kitty graphics protocol:
|
||||||
|
|
||||||
* `termpdf <https://github.com/dsanson/termpdf>`_ - a terminal PDF/DJVU/CBR viewer
|
* `termpdf.py <https://github.com/dsanson/termpdf.py>`_ - a terminal PDF/DJVU/CBR viewer
|
||||||
* `ranger <https://github.com/ranger/ranger>`_ - a terminal file manager, with
|
* `ranger <https://github.com/ranger/ranger>`_ - a terminal file manager, with
|
||||||
image previews, see this `PR <https://github.com/ranger/ranger/pull/1077>`_
|
image previews, see this `PR <https://github.com/ranger/ranger/pull/1077>`_
|
||||||
* :doc:`kitty-diff <kittens/diff>` - a side-by-side terminal diff program with support for images
|
* :doc:`kitty-diff <kittens/diff>` - a side-by-side terminal diff program with support for images
|
||||||
|
* `pixcat <https://github.com/mirukana/pixcat>`_ - a third party CLI and python library that wraps the graphics protocol
|
||||||
* `neofetch <https://github.com/dylanaraps/neofetch>`_ - A command line system
|
* `neofetch <https://github.com/dylanaraps/neofetch>`_ - A command line system
|
||||||
information tool
|
information tool
|
||||||
|
|
||||||
@@ -262,8 +263,8 @@ received. Finally, terminals must not display anything, until the entire sequenc
|
|||||||
received and validated.
|
received and validated.
|
||||||
|
|
||||||
|
|
||||||
Detecting available transmission mediums
|
Querying support and available transmission mediums
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Since a client has no a-priori knowledge of whether it shares a filesystem/shared memory
|
Since a client has no a-priori knowledge of whether it shares a filesystem/shared memory
|
||||||
with the terminal emulator, it can send an id with the control data, using the ``i`` key
|
with the terminal emulator, it can send an id with the control data, using the ``i`` key
|
||||||
@@ -289,6 +290,27 @@ use the *query action*, set ``a=q``. Then the terminal emulator will try to load
|
|||||||
the image and respond with either OK or an error, as above, but it will not
|
the image and respond with either OK or an error, as above, but it will not
|
||||||
replace an existing image with the same id, nor will it store the image.
|
replace an existing image with the same id, nor will it store the image.
|
||||||
|
|
||||||
|
While as of May 2020, kitty is the only terminal emulator to support this
|
||||||
|
graphics protocol, we intend that any terminal emulator that wishes to support
|
||||||
|
it can. To check if a terminal emulator supports the graphics protocol the best way
|
||||||
|
is to send the above *query action* followed by a request for the
|
||||||
|
`primary device attributes <https://vt100.net/docs/vt510-rm/DA1.html>`. If you
|
||||||
|
get back an answer for the device attributes without getting back an answer for
|
||||||
|
the *query action* the terminal emulator does not support the graphics
|
||||||
|
protocol.
|
||||||
|
|
||||||
|
This means that terminal emulators that support the graphics protocol, **must**
|
||||||
|
reply to *query actions* immediately without processing other input. Most
|
||||||
|
terminal emulators handle input in a FIFO manner, anyway.
|
||||||
|
|
||||||
|
So for example, you could send::
|
||||||
|
|
||||||
|
<ESC>_Gi=31,s=1,v=1,a=q,t=d,f=24;<NUL><NUL><NUL><ESC>\<ESC>[c
|
||||||
|
|
||||||
|
If you get back a response to the graphics query, the terminal emulator supports
|
||||||
|
the protocol, if you get back a response to the device attributes query without
|
||||||
|
a response to the graphics query, it does not.
|
||||||
|
|
||||||
|
|
||||||
Display images on screen
|
Display images on screen
|
||||||
-----------------------------
|
-----------------------------
|
||||||
@@ -368,10 +390,10 @@ Value of ``d`` Meaning
|
|||||||
|
|
||||||
Some examples::
|
Some examples::
|
||||||
|
|
||||||
<ESC>_Ga=d<ESC>\ # delete all visible images
|
<ESC>_Ga=d<ESC>\ # delete all visible images
|
||||||
<ESC>_Ga=d,i=10<ESC>\ # delete the image with id=10
|
<ESC>_Ga=d,d=i,i=10<ESC>\ # delete the image with id=10, without freeing data
|
||||||
<ESC>_Ga=Z,z=-1<ESC>\ # delete the images with z-index -1, also freeing up image data
|
<ESC>_Ga=d,d=Z,z=-1<ESC>\ # delete the images with z-index -1, also freeing up image data
|
||||||
<ESC>_Ga=P,x=3,y=4<ESC>\ # delete all images that intersect the cell at (3, 4)
|
<ESC>_Ga=d,d=p,x=3,y=4<ESC>\ # delete all images that intersect the cell at (3, 4), without freeing data
|
||||||
|
|
||||||
Image persistence and storage quotas
|
Image persistence and storage quotas
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ You can also use your favorite package manager to install the |kitty| package.
|
|||||||
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/kitty>`_,
|
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/kitty>`_,
|
||||||
`Arch Linux <https://www.archlinux.org/packages/community/x86_64/kitty/>`_,
|
`Arch Linux <https://www.archlinux.org/packages/community/x86_64/kitty/>`_,
|
||||||
`Gentoo <https://packages.gentoo.org/packages/x11-terms/kitty>`_,
|
`Gentoo <https://packages.gentoo.org/packages/x11-terms/kitty>`_,
|
||||||
`Fedora <https://copr.fedorainfracloud.org/coprs/gagbo/kitty-latest/>`_,
|
`Fedora <https://src.fedoraproject.org/rpms/kitty>`_,
|
||||||
`Void Linux <https://github.com/void-linux/void-packages/blob/master/srcpkgs/kitty/template>`_,
|
`Void Linux <https://github.com/void-linux/void-packages/blob/master/srcpkgs/kitty/template>`_,
|
||||||
and `Solus <https://dev.getsol.us/source/kitty/>`_.
|
and `Solus <https://dev.getsol.us/source/kitty/>`_.
|
||||||
|
|
||||||
@@ -192,6 +192,12 @@ Similarly, you can detach the current tab, with::
|
|||||||
# asks which OS Window to move the tab into
|
# asks which OS Window to move the tab into
|
||||||
map ctrl+f4 detach_tab ask
|
map ctrl+f4 detach_tab ask
|
||||||
|
|
||||||
|
Finally, you can define a shortcut to close all windows in a tab other than
|
||||||
|
the currently active window::
|
||||||
|
|
||||||
|
map f9 close_other_windows_in_tab
|
||||||
|
|
||||||
|
|
||||||
Other keyboard shortcuts
|
Other keyboard shortcuts
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
@@ -354,11 +360,12 @@ Mouse features
|
|||||||
* You can triple click to select a line and then drag to select more lines.
|
* You can triple click to select a line and then drag to select more lines.
|
||||||
* You can right click to extend a previous selection.
|
* You can right click to extend a previous selection.
|
||||||
* You can hold down :kbd:`ctrl+alt` and drag with the mouse to select in
|
* You can hold down :kbd:`ctrl+alt` and drag with the mouse to select in
|
||||||
columns.
|
columns (see also :opt:`rectangle_select_modifiers`).
|
||||||
* Selecting text automatically copies it to the primary clipboard (on
|
* Selecting text automatically copies it to the primary clipboard (on
|
||||||
platforms with a primary clipboard).
|
platforms with a primary clipboard).
|
||||||
* You can select text with kitty even when a terminal program has grabbed
|
* You can select text with kitty even when a terminal program has grabbed
|
||||||
the mouse by holding down the :kbd:`shift` key.
|
the mouse by holding down the :kbd:`shift` key (see also
|
||||||
|
:opt:`terminal_select_modifiers`).
|
||||||
|
|
||||||
|
|
||||||
Font control
|
Font control
|
||||||
@@ -432,6 +439,15 @@ The list of Frequently Asked Questions (*FAQ*) is :doc:`available here <faq>`.
|
|||||||
|
|
||||||
.. _completion:
|
.. _completion:
|
||||||
|
|
||||||
|
|
||||||
|
Cool integrations for kitty with other CLI tools
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
kitty provides extremely powerful interfaces such as :doc:`remote-control` and
|
||||||
|
:doc:`kittens/custom` and :doc:`kittens/icat`
|
||||||
|
that allow it to be integrated with other tools seamlessly. For a list of such
|
||||||
|
user created integrations, see: :doc:`integrations`.
|
||||||
|
|
||||||
Completion for kitty
|
Completion for kitty
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
|||||||
108
docs/integrations.rst
Normal file
108
docs/integrations.rst
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
Integrations with other tools
|
||||||
|
================================
|
||||||
|
|
||||||
|
kitty provides extremely powerful interfaces such as :doc:`remote-control` and
|
||||||
|
:doc:`kittens/custom` and :doc:`kittens/icat`
|
||||||
|
that allow it to be integrated with other tools seamlessly.
|
||||||
|
|
||||||
|
|
||||||
|
Image and document viewers
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Powered by kitty's :doc:`graphics-protocol` there exist many tools for viewing
|
||||||
|
images and other types of documents directly in your terminal, even over SSH.
|
||||||
|
|
||||||
|
`termpdf.py <https://github.com/dsanson/termpdf.py>`_
|
||||||
|
a terminal PDF/DJVU/CBR viewer
|
||||||
|
|
||||||
|
`mdcat <https://github.com/lunaryorn/mdcat>`_
|
||||||
|
Display markdown files nicely formatted with images in the terminal
|
||||||
|
|
||||||
|
`ranger <https://github.com/ranger/ranger>`_
|
||||||
|
a terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
||||||
|
|
||||||
|
`nnn <https://github.com/jarun/nnn/>`_
|
||||||
|
another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
||||||
|
|
||||||
|
`koneko <https://github.com/twenty5151/koneko>`_
|
||||||
|
browse images from the pixiv artist community directly in kitty
|
||||||
|
|
||||||
|
|
||||||
|
System and data visualisation tools
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
`neofetch <https://github.com/dylanaraps/neofetch>`_
|
||||||
|
A command line system information tool that shows images using kitty's graphics protocol
|
||||||
|
|
||||||
|
`matplotlib <https://github.com/jktr/matplotlib-backend-kitty>`_
|
||||||
|
show matplotlib plots directly in kitty
|
||||||
|
|
||||||
|
`KittyTerminalImages.jl <https://github.com/simonschoelly/KittyTerminalImages.jl>`_
|
||||||
|
show images from Julia directly in kitty
|
||||||
|
|
||||||
|
`gnuplot <http://www.gnuplot.info/>`_
|
||||||
|
a graphing and data visualization tool that can be made to display its
|
||||||
|
output in kitty with the following bash snippet::
|
||||||
|
|
||||||
|
function iplot {
|
||||||
|
cat <<EOF | gnuplot
|
||||||
|
set terminal pngcairo enhanced font 'Fira Sans,10'
|
||||||
|
set autoscale
|
||||||
|
set samples 1000
|
||||||
|
set output '|kitty +kitten icat --stdin yes'
|
||||||
|
set object 1 rectangle from screen 0,0 to screen 1,1 fillcolor rgb"#fdf6e3" behind
|
||||||
|
plot $@
|
||||||
|
set output '/dev/null'
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
Add this to bashrc and then to plot a function, simply do::
|
||||||
|
|
||||||
|
iplot 'sin(x*3)*exp(x*.2)'
|
||||||
|
|
||||||
|
|
||||||
|
Editor integration
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
kitty can be integrated into many different terminal editors to add features
|
||||||
|
such a split windows, previews, REPLs etc.
|
||||||
|
|
||||||
|
|
||||||
|
`kakoune <https://kakoune.org/>`_
|
||||||
|
integrates with kitty to use native kitty windows for its windows/panels and REPLs.
|
||||||
|
|
||||||
|
`vim-slime <https://github.com/jpalardy/vim-slime#kitty>`_
|
||||||
|
uses kitty remote control for a Lisp REPL.
|
||||||
|
|
||||||
|
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
||||||
|
allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
||||||
|
|
||||||
|
`vim-test <https://github.com/vim-test/vim-test>`_
|
||||||
|
allows easily running tests in a terminal window
|
||||||
|
|
||||||
|
|
||||||
|
Scrollback manipulation
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
`kitty-search <https://github.com/trygveaa/kitty-kitten-search>`_
|
||||||
|
Live incremental search of the scrollback buffer.
|
||||||
|
|
||||||
|
`kitty-grab <https://github.com/yurikhan/kitty_grab>`_
|
||||||
|
keyboard based text selection for the kitty scrollback buffer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Miscellaneous
|
||||||
|
------------------
|
||||||
|
|
||||||
|
`kitty-smart-tab <https://github.com/yurikhan/kitty-smart-tab>`_
|
||||||
|
use keys to either control tabs or pass them onto running applications if
|
||||||
|
no tabs are present
|
||||||
|
|
||||||
|
`kitty-smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
||||||
|
use keys to either scroll or pass them onto running applications if
|
||||||
|
no scrollback buffer is present
|
||||||
|
|
||||||
|
`reload keybindings <https://github.com/kovidgoyal/kitty/issues/1292#issuecomment-582388769>`_
|
||||||
|
reload key bindings from :file:`kitty.conf` without needing to restart
|
||||||
|
kitty
|
||||||
@@ -20,24 +20,24 @@ your machine).
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def main(args: List[str]) -> str:
|
def main(args: List[str]) -> str:
|
||||||
# this is the main entry point of the kitten, it will be executed in
|
# this is the main entry point of the kitten, it will be executed in
|
||||||
# the overlay window when the kitten is launched
|
# the overlay window when the kitten is launched
|
||||||
answer = input('Enter some text: ')
|
answer = input('Enter some text: ')
|
||||||
# whatever this function returns will be available in the
|
# whatever this function returns will be available in the
|
||||||
# handle_result() function
|
# handle_result() function
|
||||||
return answer
|
return answer
|
||||||
|
|
||||||
def handle_result(args: List[str], answer: str, target_window_id: int, boss: kitty.boss.Boss) -> None:
|
def handle_result(args: List[str], answer: str, target_window_id: int, boss: kitty.boss.Boss) -> None:
|
||||||
# get the kitty window into which to paste answer
|
# get the kitty window into which to paste answer
|
||||||
w = boss.window_id_map.get(target_window_id)
|
w = boss.window_id_map.get(target_window_id)
|
||||||
if w is not None:
|
if w is not None:
|
||||||
w.paste(answer)
|
w.paste(answer)
|
||||||
|
|
||||||
|
|
||||||
Now in :file:`kitty.conf` add the lines::
|
Now in :file:`kitty.conf` add the lines::
|
||||||
|
|
||||||
map ctrl+k kitten mykitten.py
|
map ctrl+k kitten mykitten.py
|
||||||
|
|
||||||
|
|
||||||
Start kitty and press :kbd:`ctrl+k` and you should see the kitten running.
|
Start kitty and press :kbd:`ctrl+k` and you should see the kitten running.
|
||||||
@@ -53,7 +53,7 @@ Passing arguments to kittens
|
|||||||
You can pass arguments to kittens by defining them in the map directive in
|
You can pass arguments to kittens by defining them in the map directive in
|
||||||
:file:`kitty.conf`. For example::
|
:file:`kitty.conf`. For example::
|
||||||
|
|
||||||
map ctrl+k kitten mykitten.py arg1 arg2
|
map ctrl+k kitten mykitten.py arg1 arg2
|
||||||
|
|
||||||
These will be available as the ``args`` parameter in the ``main()`` and
|
These will be available as the ``args`` parameter in the ``main()`` and
|
||||||
``handle_result()`` functions. Note also that the current working directory
|
``handle_result()`` functions. Note also that the current working directory
|
||||||
@@ -70,17 +70,17 @@ function, telling kitty what kind of input your kitten would like. For example:
|
|||||||
|
|
||||||
.. code-block:: py
|
.. code-block:: py
|
||||||
|
|
||||||
# in main, STDIN is for the kitten process and will contain
|
# in main, STDIN is for the kitten process and will contain
|
||||||
# the contents of the screen
|
# the contents of the screen
|
||||||
def main(args):
|
def main(args):
|
||||||
return sys.stdin.read()
|
return sys.stdin.read()
|
||||||
|
|
||||||
# in handle_result, STDIN is for the kitty process itself, rather
|
# in handle_result, STDIN is for the kitty process itself, rather
|
||||||
# than the kitten process and should not be read from.
|
# than the kitten process and should not be read from.
|
||||||
from kittens.tui.handler import result_handler
|
from kittens.tui.handler import result_handler
|
||||||
@result_handler(type_of_input='text')
|
@result_handler(type_of_input='text')
|
||||||
def handle_result(args, stdin_data, target_window_id, boss):
|
def handle_result(args, stdin_data, target_window_id, boss):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
This will send the plain text of the active window to the kitten's
|
This will send the plain text of the active window to the kitten's
|
||||||
@@ -104,23 +104,23 @@ Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
|||||||
|
|
||||||
.. code-block:: py
|
.. code-block:: py
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from kittens.tui.handler import result_handler
|
from kittens.tui.handler import result_handler
|
||||||
@result_handler(no_ui=True)
|
@result_handler(no_ui=True)
|
||||||
def handle_result(args, answer, target_window_id, boss):
|
def handle_result(args, answer, target_window_id, boss):
|
||||||
tab = boss.active_tab
|
tab = boss.active_tab
|
||||||
if tab is not None:
|
if tab is not None:
|
||||||
if tab.current_layout.name == 'stack':
|
if tab.current_layout.name == 'stack':
|
||||||
tab.last_used_layout()
|
tab.last_used_layout()
|
||||||
else:
|
else:
|
||||||
tab.goto_layout('stack')
|
tab.goto_layout('stack')
|
||||||
|
|
||||||
|
|
||||||
Now in kitty.conf add::
|
Now in kitty.conf add::
|
||||||
|
|
||||||
map f11 kitten zoom_toggle.py
|
map f11 kitten zoom_toggle.py
|
||||||
|
|
||||||
Pressing :kbd:`F11` will now act as a zoom toggle function. You can get even
|
Pressing :kbd:`F11` will now act as a zoom toggle function. You can get even
|
||||||
more fancy, switching the kitty OS window to fullscreen as well as changing the
|
more fancy, switching the kitty OS window to fullscreen as well as changing the
|
||||||
@@ -132,6 +132,35 @@ layout, by simply adding the line::
|
|||||||
To the ``handle_result()`` function, above.
|
To the ``handle_result()`` function, above.
|
||||||
|
|
||||||
|
|
||||||
|
.. _send_mouse_event:
|
||||||
|
|
||||||
|
Sending mouse events
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
If the program running in a window is receiving mouse events you can simulate
|
||||||
|
those using::
|
||||||
|
|
||||||
|
from kitty.fast_data_types import send_mouse_event
|
||||||
|
send_mouse_event(screen, x, y, button, action, mods)
|
||||||
|
|
||||||
|
``screen`` is the ``screen`` attribute of the window you want to send the event
|
||||||
|
to. ``x`` and ``y`` are the 0-indexed coordinates. ``button`` is a number using
|
||||||
|
the same numbering as X11 (left: ``1``, middle: ``2``, right: ``3``, scroll up:
|
||||||
|
``4``, scroll down: ``5``, scroll left: ``6``, scroll right: ``7``, back:
|
||||||
|
``8``, forward: ``9``). ``action`` is one of ``PRESS``, ``RELEASE``, ``DRAG``
|
||||||
|
or ``MOVE``. ``mods`` is a bitmask of ``GLFW_MOD_{mod}`` where ``{mod}`` is one
|
||||||
|
of ``SHIFT``, ``CONTROL`` or ``ALT``. All the mentioned constants are imported
|
||||||
|
from ``kitty.fast_data_types``.
|
||||||
|
|
||||||
|
For example, to send a left click at position x: 2, y: 3 to the active window::
|
||||||
|
|
||||||
|
from kitty.fast_data_types import send_mouse_event, GLFW_MOUSE_BUTTON_LEFT, PRESS
|
||||||
|
send_mouse_event(boss.active_window.screen, 2, 3, GLFW_MOUSE_BUTTON_LEFT, PRESS, 0)
|
||||||
|
|
||||||
|
The function will only send the event if the program is receiving events of
|
||||||
|
that type, and will return ``True`` if it sent the event, and ``False`` if not.
|
||||||
|
|
||||||
|
|
||||||
Debugging kittens
|
Debugging kittens
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -157,11 +186,11 @@ Kittens created by kitty users
|
|||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
||||||
Allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
Allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
||||||
|
|
||||||
`smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
`smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
||||||
Makes the kitty scroll bindings work in full screen applications
|
Makes the kitty scroll bindings work in full screen applications
|
||||||
|
|
||||||
`insert password <https://github.com/kovidgoyal/kitty/issues/1222>`_
|
`insert password <https://github.com/kovidgoyal/kitty/issues/1222>`_
|
||||||
Insert a password from a CLI password manager, taking care to only do it at
|
Insert a password from a CLI password manager, taking care to only do it at
|
||||||
a password prompt.
|
a password prompt.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ like a path or filename followed by a colon and a line number and open
|
|||||||
the file in vim at the specified line number. The patterns and editor
|
the file in vim at the specified line number. The patterns and editor
|
||||||
to be used can be modified using options passed to the kitten. For example::
|
to be used can be modified using options passed to the kitten. For example::
|
||||||
|
|
||||||
map ctrl+g kitten hints --type=linenum --linenum-action=tab nvim +{line} +{path}
|
map ctrl+g kitten hints --type=linenum --linenum-action=tab nvim +{line} {path}
|
||||||
|
|
||||||
will open the selected file in a new tab inside neovim when you press
|
will open the selected file in a new tab inside neovim when you press
|
||||||
:kbd:`ctrl+g`.
|
:kbd:`ctrl+g`.
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ Then you can simply use ``icat image.png`` to view images.
|
|||||||
`ImageMagick <https://www.imagemagick.org>`_ must be installed for ``icat`` to
|
`ImageMagick <https://www.imagemagick.org>`_ must be installed for ``icat`` to
|
||||||
work.
|
work.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
kitty's image display protocol may not work when used within a terminal
|
||||||
|
multiplexer such as ``screen`` or ``tmux``, depending on whether the
|
||||||
|
multiplexer has added support for it or not.
|
||||||
|
|
||||||
|
|
||||||
.. program:: kitty +kitten icat
|
.. program:: kitty +kitten icat
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,35 @@ currently active kitty window. For example::
|
|||||||
map f1 launch my-program @active-kitty-window-id
|
map f1 launch my-program @active-kitty-window-id
|
||||||
|
|
||||||
|
|
||||||
|
Watching launched windows
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The :option:`launch --watcher` option allows you to specify python functions
|
||||||
|
that will be called at specific events, such as when the window is resized or
|
||||||
|
closed. Simply specify the path to a python module that specifies callback
|
||||||
|
functions for the events you are interested in, for example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def on_resize(boss, window, data):
|
||||||
|
# Here data will contain old_geometry and new_geometry
|
||||||
|
|
||||||
|
def on_close(boss, window, data):
|
||||||
|
# called when window is closed, typically when the program running in
|
||||||
|
# it exits.
|
||||||
|
|
||||||
|
|
||||||
|
Every callback is passed a reference to the global ``Boss`` object as well as
|
||||||
|
the ``Window`` object the action is occurring on. The ``data`` object is
|
||||||
|
mapping that contains event dependent data. Some useful methods and attributes
|
||||||
|
for the ``Window`` object are: ``as_text(as_ans=False, add_history=False,
|
||||||
|
add_wrap_markers=False, alternate_screen=False)`` with which you can get the
|
||||||
|
contents of the window and its scrollback buffer. Similarly,
|
||||||
|
``window.child.pid`` is the PID of the processes that was launched
|
||||||
|
in the window and ``window.id`` is the internal kitty ``id`` of the
|
||||||
|
window.
|
||||||
|
|
||||||
|
|
||||||
Syntax reference
|
Syntax reference
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
|||||||
|
|
||||||
There are many different layouts available. They are all enabled by default,
|
There are many different layouts available. They are all enabled by default,
|
||||||
you can switch layouts using :sc:`next_layout`. To control which layouts
|
you can switch layouts using :sc:`next_layout`. To control which layouts
|
||||||
are available use :opt:`enabled_layouts` the first listed layout becomes
|
are available use :opt:`enabled_layouts`, the first listed layout becomes
|
||||||
the default. Individual layouts and how to use them are described below.
|
the default. Individual layouts and how to use them are described below.
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
@@ -46,10 +46,12 @@ Displays one (or optionally more) full height windows on the left half of the
|
|||||||
screen. Remaining windows are tiled vertically on the right half of the screen.
|
screen. Remaining windows are tiled vertically on the right half of the screen.
|
||||||
There are options to control how the screen is split horizontally ``bias``
|
There are options to control how the screen is split horizontally ``bias``
|
||||||
(an integer between ``10`` and ``90``) and options to control how many
|
(an integer between ``10`` and ``90``) and options to control how many
|
||||||
full-height windows there are ``full_size`` (a positive integer). The syntax
|
full-height windows there are ``full_size`` (a positive integer). The
|
||||||
|
``mirrored`` option when set to ``true`` will cause the short windows to be
|
||||||
|
on the left side of the screen instead of the right. The syntax
|
||||||
for the options is shown below::
|
for the options is shown below::
|
||||||
|
|
||||||
enabled_layouts tall:bias=50;full_size=1
|
enabled_layouts tall:bias=50;full_size=1;mirrored=false
|
||||||
|
|
||||||
┌──────────────┬───────────────┐
|
┌──────────────┬───────────────┐
|
||||||
│ │ │
|
│ │ │
|
||||||
@@ -65,6 +67,13 @@ for the options is shown below::
|
|||||||
│ │ │
|
│ │ │
|
||||||
└──────────────┴───────────────┘
|
└──────────────┴───────────────┘
|
||||||
|
|
||||||
|
In addition, you can map keys to increase or decrease the number of full size
|
||||||
|
windows, for example::
|
||||||
|
|
||||||
|
map ctrl+[ layout_action decrease_num_full_size_windows
|
||||||
|
map ctrl+] layout_action increase_num_full_size_windows
|
||||||
|
|
||||||
|
|
||||||
The Fat Layout
|
The Fat Layout
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
@@ -72,10 +81,12 @@ Displays one (or optionally more) full width windows on the top half of the
|
|||||||
screen. Remaining windows are tiled horizontally on the bottom half of the screen.
|
screen. Remaining windows are tiled horizontally on the bottom half of the screen.
|
||||||
There are options to control how the screen is split vertically ``bias``
|
There are options to control how the screen is split vertically ``bias``
|
||||||
(an integer between ``10`` and ``90``) and options to control how many
|
(an integer between ``10`` and ``90``) and options to control how many
|
||||||
full-height windows there are ``full_size`` (a positive integer). The syntax
|
full-height windows there are ``full_size`` (a positive integer). The
|
||||||
for the options is shown below::
|
``mirrored`` option when set to ``true`` will cause the narrow windows to be
|
||||||
|
on the top of the screen instead of the bottom. The syntax for the options is
|
||||||
|
shown below::
|
||||||
|
|
||||||
enabled_layouts fat:bias=50;full_size=1
|
enabled_layouts fat:bias=50;full_size=1;mirrored=false
|
||||||
|
|
||||||
┌──────────────────────────────┐
|
┌──────────────────────────────┐
|
||||||
│ │
|
│ │
|
||||||
@@ -241,7 +252,7 @@ This will have ``2`` instead of a single tall window, that occupy ``70%``
|
|||||||
instead of ``50%`` of available width. ``bias`` can be any number between 10
|
instead of ``50%`` of available width. ``bias`` can be any number between 10
|
||||||
and 90.
|
and 90.
|
||||||
|
|
||||||
Writing a new layout only requires about a hundred lines of code, so if there
|
Writing a new layout only requires about two hundred lines of code, so if there
|
||||||
is some layout you want, take a look at `layout.py
|
is some layout you want, take a look at one of the existing layouts in the
|
||||||
<https://github.com/kovidgoyal/kitty/blob/master/kitty/layout.py>`_ and submit
|
`layout <https://github.com/kovidgoyal/kitty/tree/master/kitty/layout>`_
|
||||||
a pull request!
|
package and submit a pull request!
|
||||||
|
|||||||
@@ -219,6 +219,11 @@ first, for example::
|
|||||||
<ESC>]52;c;!<ESC>\
|
<ESC>]52;c;!<ESC>\
|
||||||
|
|
||||||
Here ``!`` is not valid base64 encoded text, so it clears the clipboard.
|
Here ``!`` is not valid base64 encoded text, so it clears the clipboard.
|
||||||
|
Further, since it is invalid, it should be ignored by terminal emulators
|
||||||
|
that do not support this extension, thereby making it safe to use, simply
|
||||||
|
always send it before starting a new OSC 52 paste, even if you aren't chunking
|
||||||
|
up large pastes, that way kitty wont concatenate your paste, and it will have
|
||||||
|
no ill-effects in other terminal emulators.
|
||||||
|
|
||||||
In case you're using software that can't be easily adapted to this
|
In case you're using software that can't be easily adapted to this
|
||||||
protocol extension, it can be disabled by specifying ``no-append`` to the
|
protocol extension, it can be disabled by specifying ``no-append`` to the
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ In order for control to work, :opt:`allow_remote_control` must be enabled in
|
|||||||
|
|
||||||
Now, in the new |kitty| window, enter the command::
|
Now, in the new |kitty| window, enter the command::
|
||||||
|
|
||||||
kitty @ new-window --title Output --keep-focus cat
|
kitty @ launch --title Output --keep-focus cat
|
||||||
|
|
||||||
This will open a new window, running the ``cat`` program that will appear next
|
This will open a new window, running the ``cat`` program that will appear next
|
||||||
to the current window.
|
to the current window.
|
||||||
@@ -54,7 +54,7 @@ window. Type ``Ctrl+D`` when you are ready to stop.
|
|||||||
|
|
||||||
Now, let's open a new tab::
|
Now, let's open a new tab::
|
||||||
|
|
||||||
kitty @ new-window --new-tab --tab-title "My Tab" --keep-focus bash
|
kitty @ launch --type=tab --tab-title "My Tab" --keep-focus bash
|
||||||
|
|
||||||
This will open a new tab running the bash shell with the title "My Tab".
|
This will open a new tab running the bash shell with the title "My Tab".
|
||||||
We can change the title of the tab with::
|
We can change the title of the tab with::
|
||||||
@@ -134,6 +134,19 @@ still write to the pipes of any other program on the same computer and
|
|||||||
therefore can control |kitty|. It can, however, be useful to block programs
|
therefore can control |kitty|. It can, however, be useful to block programs
|
||||||
running on other computers (for example, over ssh) or as other users.
|
running on other computers (for example, over ssh) or as other users.
|
||||||
|
|
||||||
|
Mapping key presses to remote control commands
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
If you wish to trigger a remote control command easily with just a keypress,
|
||||||
|
you can map it in :file:`kitty.conf`. For example::
|
||||||
|
|
||||||
|
map F1 remote_control set-spacing margin=30
|
||||||
|
|
||||||
|
Then pressing the :kbd:`F1` key will set the active window margins to 30.
|
||||||
|
The syntax for what follows :code:`remote_control` is exactly the same
|
||||||
|
as the syntax for what follows :code:`kitty @` above.
|
||||||
|
|
||||||
|
|
||||||
Documentation for the remote control protocol
|
Documentation for the remote control protocol
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ static inline void
|
|||||||
{parr}
|
{parr}
|
||||||
{keys_enum}
|
{keys_enum}
|
||||||
enum KEYS key = '{initial_key}';
|
enum KEYS key = '{initial_key}';
|
||||||
|
if (screen->parser_buf[pos] == ';') state = AFTER_VALUE;
|
||||||
|
|
||||||
while (pos < screen->parser_buf_pos) {{
|
while (pos < screen->parser_buf_pos) {{
|
||||||
switch(state) {{
|
switch(state) {{
|
||||||
|
|||||||
111
gen-wcwidth.py
111
gen-wcwidth.py
@@ -51,7 +51,8 @@ all_symbols: Set[int] = set()
|
|||||||
name_map: Dict[int, str] = {}
|
name_map: Dict[int, str] = {}
|
||||||
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
|
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
|
||||||
zwj = 0x200d
|
zwj = 0x200d
|
||||||
marks = set(emoji_skin_tone_modifiers) | {zwj}
|
flag_codepoints = frozenset(range(0x1F1E6, 0x1F1E6 + 26))
|
||||||
|
marks = set(emoji_skin_tone_modifiers) | {zwj} | flag_codepoints
|
||||||
not_assigned = set(range(0, sys.maxunicode))
|
not_assigned = set(range(0, sys.maxunicode))
|
||||||
|
|
||||||
|
|
||||||
@@ -103,36 +104,88 @@ def parse_ucd() -> None:
|
|||||||
word_search_map['lamda'] |= word_search_map['lambda']
|
word_search_map['lamda'] |= word_search_map['lambda']
|
||||||
|
|
||||||
|
|
||||||
def split_two(line: str) -> Tuple[Set[int], str]:
|
def parse_range_spec(spec: str) -> Set[int]:
|
||||||
spec, rest = line.split(';', 1)
|
spec = spec.strip()
|
||||||
spec, rest = spec.strip(), rest.strip().split(' ', 1)[0].strip()
|
|
||||||
if '..' in spec:
|
if '..' in spec:
|
||||||
chars_ = tuple(map(lambda x: int(x, 16), filter(None, spec.split('.'))))
|
chars_ = tuple(map(lambda x: int(x, 16), filter(None, spec.split('.'))))
|
||||||
chars = set(range(chars_[0], chars_[1] + 1))
|
chars = set(range(chars_[0], chars_[1] + 1))
|
||||||
else:
|
else:
|
||||||
chars = {int(spec, 16)}
|
chars = {int(spec, 16)}
|
||||||
return chars, rest
|
return chars
|
||||||
|
|
||||||
|
|
||||||
|
def split_two(line: str) -> Tuple[Set[int], str]:
|
||||||
|
spec, rest = line.split(';', 1)
|
||||||
|
spec, rest = spec.strip(), rest.strip().split(' ', 1)[0].strip()
|
||||||
|
return parse_range_spec(spec), rest
|
||||||
|
|
||||||
|
|
||||||
all_emoji: Set[int] = set()
|
all_emoji: Set[int] = set()
|
||||||
emoji_categories: Dict[str, Set[int]] = {}
|
|
||||||
emoji_presentation_bases: Set[int] = set()
|
emoji_presentation_bases: Set[int] = set()
|
||||||
|
narrow_emoji: Set[int] = set()
|
||||||
|
wide_emoji: Set[int] = set()
|
||||||
|
flags: Dict[int, List[int]] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_basic_emoji(spec: str) -> None:
|
||||||
|
parts = list(filter(None, spec.split()))
|
||||||
|
has_emoji_presentation = len(parts) < 2
|
||||||
|
chars = parse_range_spec(parts[0])
|
||||||
|
all_emoji.update(chars)
|
||||||
|
emoji_presentation_bases.update(chars)
|
||||||
|
(wide_emoji if has_emoji_presentation else narrow_emoji).update(chars)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_keycap_sequence(spec: str) -> None:
|
||||||
|
base, fe0f, cc = list(filter(None, spec.split()))
|
||||||
|
chars = parse_range_spec(base)
|
||||||
|
all_emoji.update(chars)
|
||||||
|
emoji_presentation_bases.update(chars)
|
||||||
|
narrow_emoji.update(chars)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_flag_emoji_sequence(spec: str) -> None:
|
||||||
|
a, b = list(filter(None, spec.split()))
|
||||||
|
left, right = int(a, 16), int(b, 16)
|
||||||
|
chars = {left, right}
|
||||||
|
all_emoji.update(chars)
|
||||||
|
wide_emoji.update(chars)
|
||||||
|
emoji_presentation_bases.update(chars)
|
||||||
|
flags.setdefault(left, []).append(right)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_emoji_tag_sequence(spec: str) -> None:
|
||||||
|
a = int(spec.split()[0], 16)
|
||||||
|
all_emoji.add(a)
|
||||||
|
wide_emoji.add(a)
|
||||||
|
emoji_presentation_bases.add(a)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_emoji_modifier_sequence(spec: str) -> None:
|
||||||
|
a, b = list(filter(None, spec.split()))
|
||||||
|
char, mod = int(a, 16), int(b, 16)
|
||||||
|
mod
|
||||||
|
all_emoji.add(char)
|
||||||
|
wide_emoji.add(char)
|
||||||
|
emoji_presentation_bases.add(char)
|
||||||
|
|
||||||
|
|
||||||
def parse_emoji() -> None:
|
def parse_emoji() -> None:
|
||||||
for line in get_data('emoji-data.txt', 'emoji'):
|
for line in get_data('emoji-sequences.txt', 'emoji'):
|
||||||
chars, rest = split_two(line)
|
parts = [x.strip() for x in line.split(';')]
|
||||||
s = emoji_categories.setdefault(rest, set())
|
if len(parts) < 2:
|
||||||
s.update(chars)
|
|
||||||
all_emoji.update(chars)
|
|
||||||
for line in get_data('emoji-variation-sequences.txt', 'emoji'):
|
|
||||||
parts = line.split()
|
|
||||||
base, var = parts[0], parts[1]
|
|
||||||
if base.startswith('#'):
|
|
||||||
continue
|
continue
|
||||||
if var.upper() == 'FE0F':
|
data, etype = parts[:2]
|
||||||
ibase = int(base, 16)
|
if etype == 'Basic_Emoji':
|
||||||
emoji_presentation_bases.add(ibase)
|
parse_basic_emoji(data)
|
||||||
|
elif etype == 'Emoji_Keycap_Sequence':
|
||||||
|
parse_keycap_sequence(data)
|
||||||
|
elif etype == 'RGI_Emoji_Flag_Sequence':
|
||||||
|
parse_flag_emoji_sequence(data)
|
||||||
|
elif etype == 'RGI_Emoji_Tag_Sequence':
|
||||||
|
parse_emoji_tag_sequence(data)
|
||||||
|
elif etype == 'RGI_Emoji_Modifier_Sequence':
|
||||||
|
parse_emoji_modifier_sequence(data)
|
||||||
|
|
||||||
|
|
||||||
doublewidth: Set[int] = set()
|
doublewidth: Set[int] = set()
|
||||||
@@ -204,15 +257,6 @@ def gen_emoji() -> None:
|
|||||||
p('\t}')
|
p('\t}')
|
||||||
p('\treturn false;\n}')
|
p('\treturn false;\n}')
|
||||||
|
|
||||||
p('static inline bool\nis_emoji_modifier(char_type code) {')
|
|
||||||
p('\tswitch(code) {')
|
|
||||||
for spec in get_ranges(list(emoji_categories['Emoji_Modifier'])):
|
|
||||||
write_case(spec, p)
|
|
||||||
p('\t\t\treturn true;')
|
|
||||||
p('\t\tdefault: return false;')
|
|
||||||
p('\t}')
|
|
||||||
p('\treturn false;\n}')
|
|
||||||
|
|
||||||
p('static inline bool\nis_symbol(char_type code) {')
|
p('static inline bool\nis_symbol(char_type code) {')
|
||||||
p('\tswitch(code) {')
|
p('\tswitch(code) {')
|
||||||
for spec in get_ranges(list(all_symbols)):
|
for spec in get_ranges(list(all_symbols)):
|
||||||
@@ -243,7 +287,7 @@ def category_test(
|
|||||||
p('\tswitch(code) {')
|
p('\tswitch(code) {')
|
||||||
for spec in get_ranges(list(chars)):
|
for spec in get_ranges(list(chars)):
|
||||||
write_case(spec, p)
|
write_case(spec, p)
|
||||||
p(f'\t\t\treturn true;')
|
p('\t\t\treturn true;')
|
||||||
p('\t} // }}}\n')
|
p('\t} // }}}\n')
|
||||||
p('\treturn false;\n}\n')
|
p('\treturn false;\n}\n')
|
||||||
|
|
||||||
@@ -377,8 +421,8 @@ def gen_names() -> None:
|
|||||||
p('}; // }}}\n')
|
p('}; // }}}\n')
|
||||||
|
|
||||||
# The trie
|
# The trie
|
||||||
p(f'typedef struct {{ uint32_t children_offset; uint32_t match_offset; }} word_trie;\n')
|
p('typedef struct {{ uint32_t children_offset; uint32_t match_offset; }} word_trie;\n')
|
||||||
all_trie_nodes: List['TrieNode'] = []
|
all_trie_nodes: List['TrieNode'] = [] # noqa
|
||||||
|
|
||||||
class TrieNode:
|
class TrieNode:
|
||||||
|
|
||||||
@@ -427,7 +471,7 @@ def gen_names() -> None:
|
|||||||
def gen_wcwidth() -> None:
|
def gen_wcwidth() -> None:
|
||||||
seen: Set[int] = set()
|
seen: Set[int] = set()
|
||||||
|
|
||||||
def add(p: Callable, comment: str, chars_: Set[int], ret: int) -> None:
|
def add(p: Callable, comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int) -> None:
|
||||||
chars = chars_ - seen
|
chars = chars_ - seen
|
||||||
seen.update(chars)
|
seen.update(chars)
|
||||||
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
||||||
@@ -441,13 +485,14 @@ def gen_wcwidth() -> None:
|
|||||||
p('\tswitch(code) {')
|
p('\tswitch(code) {')
|
||||||
|
|
||||||
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
|
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
|
||||||
|
add(p, 'Flags', flag_codepoints, 2)
|
||||||
add(p, 'Marks', marks | {0}, 0)
|
add(p, 'Marks', marks | {0}, 0)
|
||||||
add(p, 'Non-printing characters', non_printing, -1)
|
add(p, 'Non-printing characters', non_printing, -1)
|
||||||
add(p, 'Private use', class_maps['Co'], -3)
|
add(p, 'Private use', class_maps['Co'], -3)
|
||||||
add(p, 'Text Presentation', emoji_categories['Emoji'] - emoji_categories['Emoji_Presentation'], 1)
|
add(p, 'Text Presentation', narrow_emoji, 1)
|
||||||
add(p, 'East Asian ambiguous width', ambiguous, -2)
|
add(p, 'East Asian ambiguous width', ambiguous, -2)
|
||||||
add(p, 'East Asian double width', doublewidth, 2)
|
add(p, 'East Asian double width', doublewidth, 2)
|
||||||
add(p, 'Emoji Presentation', emoji_categories['Emoji_Presentation'], 2)
|
add(p, 'Emoji Presentation', wide_emoji, 2)
|
||||||
|
|
||||||
add(p, 'Not assigned in the unicode character database', not_assigned, -4)
|
add(p, 'Not assigned in the unicode character database', not_assigned, -4)
|
||||||
|
|
||||||
|
|||||||
18
glfw/backend_utils.c
vendored
18
glfw/backend_utils.c
vendored
@@ -332,3 +332,21 @@ pollForEvents(EventLoopData *eld, monotonic_t timeout, watch_callback_func displ
|
|||||||
}
|
}
|
||||||
return read_ok;
|
return read_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Duplicate a UTF-8 encoded string
|
||||||
|
// but cut it so that it has at most max_length bytes plus the null byte.
|
||||||
|
// This does not take combining characters into account.
|
||||||
|
GLFWAPI char* utf_8_strndup(const char* source, size_t max_length) {
|
||||||
|
if (!source) return NULL;
|
||||||
|
size_t length = strnlen(source, max_length);
|
||||||
|
if (length >= max_length) {
|
||||||
|
for (length = max_length; length > 0; length--) {
|
||||||
|
if ((source[length] & 0xC0) != 0x80) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* result = malloc(length + 1);
|
||||||
|
memcpy(result, source, length);
|
||||||
|
result[length] = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
1
glfw/backend_utils.h
vendored
1
glfw/backend_utils.h
vendored
@@ -95,3 +95,4 @@ unsigned dispatchTimers(EventLoopData *eld);
|
|||||||
void finalizePollData(EventLoopData *eld);
|
void finalizePollData(EventLoopData *eld);
|
||||||
bool initPollData(EventLoopData *eld, int display_fd);
|
bool initPollData(EventLoopData *eld, int display_fd);
|
||||||
void wakeupEventLoop(EventLoopData *eld);
|
void wakeupEventLoop(EventLoopData *eld);
|
||||||
|
char* utf_8_strndup(const char* source, size_t max_length);
|
||||||
|
|||||||
@@ -424,11 +424,7 @@ display_reconfigured(CGDirectDisplayID display UNUSED, CGDisplayChangeSummaryFla
|
|||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||||
{
|
{
|
||||||
(void)sender;
|
(void)sender;
|
||||||
_GLFWwindow* window;
|
if (_glfw.callbacks.application_close) _glfw.callbacks.application_close(0);
|
||||||
|
|
||||||
for (window = _glfw.windowListHead; window; window = window->next)
|
|
||||||
_glfwInputWindowCloseRequest(window);
|
|
||||||
|
|
||||||
return NSTerminateCancel;
|
return NSTerminateCancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -236,26 +236,65 @@ static bool refreshMonitorScreen(_GLFWmonitor* monitor)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a fallback refresh rate for when Core Graphics says it is zero
|
// Returns the display refresh rate queried from the I/O registry
|
||||||
//
|
//
|
||||||
static double getFallbackRefreshRate(_GLFWmonitor* monitor)
|
static double getFallbackRefreshRate(CGDirectDisplayID displayID)
|
||||||
{
|
{
|
||||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
double refreshRate = 60.0;
|
||||||
double refreshRate = CGDisplayModeGetRefreshRate(mode);
|
|
||||||
CGDisplayModeRelease(mode);
|
|
||||||
|
|
||||||
if (refreshRate == 0.0)
|
io_iterator_t it;
|
||||||
|
io_service_t service;
|
||||||
|
|
||||||
|
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||||
|
IOServiceMatching("IOFramebuffer"),
|
||||||
|
&it) != 0)
|
||||||
{
|
{
|
||||||
CVDisplayLinkRef link = NULL;
|
return refreshRate;
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
|
||||||
|
|
||||||
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
|
||||||
if (!(time.flags & kCVTimeIsIndefinite))
|
|
||||||
refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
|
||||||
|
|
||||||
CVDisplayLinkRelease(link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ((service = IOIteratorNext(it)) != 0)
|
||||||
|
{
|
||||||
|
const CFNumberRef indexRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFramebufferOpenGLIndex"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
if (!indexRef)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t index = 0;
|
||||||
|
CFNumberGetValue(indexRef, kCFNumberIntType, &index);
|
||||||
|
CFRelease(indexRef);
|
||||||
|
|
||||||
|
if (CGOpenGLDisplayMaskToDisplayID(1 << index) != displayID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CFNumberRef clockRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFBCurrentPixelClock"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
const CFNumberRef countRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFBCurrentPixelCount"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
if (!clockRef || !countRef)
|
||||||
|
break;
|
||||||
|
|
||||||
|
uint32_t clock = 0, count = 0;
|
||||||
|
CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
|
||||||
|
CFNumberGetValue(countRef, kCFNumberIntType, &count);
|
||||||
|
CFRelease(clockRef);
|
||||||
|
CFRelease(countRef);
|
||||||
|
|
||||||
|
if (clock > 0 && count > 0)
|
||||||
|
refreshRate = clock / (double) count;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease(it);
|
||||||
return refreshRate;
|
return refreshRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,11 +390,15 @@ void _glfwPollMonitorsNS(void)
|
|||||||
_GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height);
|
_GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height);
|
||||||
monitor->ns.displayID = displays[i];
|
monitor->ns.displayID = displays[i];
|
||||||
monitor->ns.unitNumber = unitNumber;
|
monitor->ns.unitNumber = unitNumber;
|
||||||
monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(monitor);
|
|
||||||
createDisplayLink(monitor->ns.displayID);
|
createDisplayLink(monitor->ns.displayID);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
|
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
|
||||||
|
if (CGDisplayModeGetRefreshRate(mode) == 0.0)
|
||||||
|
monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(displays[i]);
|
||||||
|
CGDisplayModeRelease(mode);
|
||||||
|
|
||||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
glfw/cocoa_platform.h
vendored
2
glfw/cocoa_platform.h
vendored
@@ -103,7 +103,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMeta
|
|||||||
#define _glfw_dlclose(handle) dlclose(handle)
|
#define _glfw_dlclose(handle) dlclose(handle)
|
||||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||||
|
|
||||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.view)
|
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.layer)
|
||||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||||
|
|||||||
@@ -1133,7 +1133,7 @@ is_ascii_control_char(char x) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputScroll(window, deltaX, deltaY, flags);
|
_glfwInputScroll(window, deltaX, deltaY, flags, translateFlags([event modifierFlags]));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||||
@@ -1460,6 +1460,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||||
{
|
{
|
||||||
|
// EGL implementation on macOS use CALayer* EGLNativeWindowType so we
|
||||||
|
// need to get the layer for EGL window surface creation.
|
||||||
|
[window->ns.view setWantsLayer:YES];
|
||||||
|
window->ns.layer = [window->ns.view layer];
|
||||||
|
|
||||||
if (!_glfwInitEGL())
|
if (!_glfwInitEGL())
|
||||||
return false;
|
return false;
|
||||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||||
@@ -1522,7 +1527,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window UNUSED, const char* title)
|
|||||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,
|
||||||
int count UNUSED, const GLFWimage* images UNUSED)
|
int count UNUSED, const GLFWimage* images UNUSED)
|
||||||
{
|
{
|
||||||
// Regular windows do not have icons
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
|
"Cocoa: Regular windows do not have icons on macOS");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
@@ -1858,6 +1864,17 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
|||||||
[window->ns.object setAlphaValue:opacity];
|
[window->ns.object setAlphaValue:opacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window UNUSED, bool enabled UNUSED)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||||
|
"Cocoa: Raw mouse motion not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _glfwPlatformRawMouseMotionSupported(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_glfwDispatchRenderFrame(CGDirectDisplayID displayID) {
|
_glfwDispatchRenderFrame(CGDirectDisplayID displayID) {
|
||||||
_GLFWwindow *w = _glfw.windowListHead;
|
_GLFWwindow *w = _glfw.windowListHead;
|
||||||
|
|||||||
168
glfw/context.c
vendored
168
glfw/context.c
vendored
@@ -173,174 +173,6 @@ bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chooses the framebuffer config that best matches the desired one
|
|
||||||
//
|
|
||||||
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
|
||||||
const _GLFWfbconfig* alternatives,
|
|
||||||
unsigned int count)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int missing, leastMissing = UINT_MAX;
|
|
||||||
unsigned int colorDiff, leastColorDiff = UINT_MAX;
|
|
||||||
unsigned int extraDiff, leastExtraDiff = UINT_MAX;
|
|
||||||
const _GLFWfbconfig* current;
|
|
||||||
const _GLFWfbconfig* closest = NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
current = alternatives + i;
|
|
||||||
|
|
||||||
if (desired->stereo > 0 && current->stereo == 0)
|
|
||||||
{
|
|
||||||
// Stereo is a hard constraint
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->doublebuffer != current->doublebuffer)
|
|
||||||
{
|
|
||||||
// Double buffering is a hard constraint
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count number of missing buffers
|
|
||||||
{
|
|
||||||
missing = 0;
|
|
||||||
|
|
||||||
if (desired->alphaBits > 0 && current->alphaBits == 0)
|
|
||||||
missing++;
|
|
||||||
|
|
||||||
if (desired->depthBits > 0 && current->depthBits == 0)
|
|
||||||
missing++;
|
|
||||||
|
|
||||||
if (desired->stencilBits > 0 && current->stencilBits == 0)
|
|
||||||
missing++;
|
|
||||||
|
|
||||||
if (desired->auxBuffers > 0 &&
|
|
||||||
current->auxBuffers < desired->auxBuffers)
|
|
||||||
{
|
|
||||||
missing += desired->auxBuffers - current->auxBuffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->samples > 0 && current->samples == 0)
|
|
||||||
{
|
|
||||||
// Technically, several multisampling buffers could be
|
|
||||||
// involved, but that's a lower level implementation detail and
|
|
||||||
// not important to us here, so we count them as one
|
|
||||||
missing++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->transparent != current->transparent)
|
|
||||||
missing++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These polynomials make many small channel size differences matter
|
|
||||||
// less than one large channel size difference
|
|
||||||
|
|
||||||
// Calculate color channel size difference value
|
|
||||||
{
|
|
||||||
colorDiff = 0;
|
|
||||||
|
|
||||||
if (desired->redBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
colorDiff += (desired->redBits - current->redBits) *
|
|
||||||
(desired->redBits - current->redBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->greenBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
colorDiff += (desired->greenBits - current->greenBits) *
|
|
||||||
(desired->greenBits - current->greenBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->blueBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
colorDiff += (desired->blueBits - current->blueBits) *
|
|
||||||
(desired->blueBits - current->blueBits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate non-color channel size difference value
|
|
||||||
{
|
|
||||||
extraDiff = 0;
|
|
||||||
|
|
||||||
if (desired->alphaBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->alphaBits - current->alphaBits) *
|
|
||||||
(desired->alphaBits - current->alphaBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->depthBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->depthBits - current->depthBits) *
|
|
||||||
(desired->depthBits - current->depthBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->stencilBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->stencilBits - current->stencilBits) *
|
|
||||||
(desired->stencilBits - current->stencilBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumRedBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumRedBits - current->accumRedBits) *
|
|
||||||
(desired->accumRedBits - current->accumRedBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumGreenBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
|
|
||||||
(desired->accumGreenBits - current->accumGreenBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumBlueBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
|
|
||||||
(desired->accumBlueBits - current->accumBlueBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumAlphaBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
|
|
||||||
(desired->accumAlphaBits - current->accumAlphaBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->samples != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->samples - current->samples) *
|
|
||||||
(desired->samples - current->samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->sRGB && !current->sRGB)
|
|
||||||
extraDiff++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out if the current one is better than the best one found so far
|
|
||||||
// Least number of missing buffers is the most important heuristic,
|
|
||||||
// then color buffer size match and lastly size match for other buffers
|
|
||||||
|
|
||||||
if (missing < leastMissing)
|
|
||||||
closest = current;
|
|
||||||
else if (missing == leastMissing)
|
|
||||||
{
|
|
||||||
if ((colorDiff < leastColorDiff) ||
|
|
||||||
(colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
|
|
||||||
{
|
|
||||||
closest = current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == closest)
|
|
||||||
{
|
|
||||||
leastMissing = missing;
|
|
||||||
leastColorDiff = colorDiff;
|
|
||||||
leastExtraDiff = extraDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves the attributes of the current context
|
// Retrieves the attributes of the current context
|
||||||
//
|
//
|
||||||
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||||
|
|||||||
114
glfw/egl_context.c
vendored
114
glfw/egl_context.c
vendored
@@ -76,6 +76,7 @@ static const char* getEGLErrorString(EGLint error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _GLFW_X11
|
||||||
// Returns the specified attribute of the specified EGLConfig
|
// Returns the specified attribute of the specified EGLConfig
|
||||||
//
|
//
|
||||||
static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
||||||
@@ -84,6 +85,7 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
|||||||
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
|
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Return the EGLConfig most closely matching the specified hints
|
// Return the EGLConfig most closely matching the specified hints
|
||||||
//
|
//
|
||||||
@@ -91,39 +93,44 @@ static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
const _GLFWfbconfig* desired,
|
const _GLFWfbconfig* desired,
|
||||||
EGLConfig* result)
|
EGLConfig* result)
|
||||||
{
|
{
|
||||||
EGLConfig* nativeConfigs;
|
EGLConfig configs[512];
|
||||||
_GLFWfbconfig* usableConfigs;
|
int i = 0, nativeCount = 0, ans_idx = 0;
|
||||||
const _GLFWfbconfig* closest;
|
EGLint attributes[64];
|
||||||
int i, nativeCount, usableCount;
|
#define ATTR(k, v) { attributes[i++] = k; attributes[i++] = v; }
|
||||||
|
ATTR(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
|
||||||
|
ATTR(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API) {
|
||||||
|
if (ctxconfig->major == 1) ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT)
|
||||||
|
else ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->client == GLFW_OPENGL_API) ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT);
|
||||||
|
if (desired->samples > 0) ATTR(EGL_SAMPLES, desired->samples);
|
||||||
|
if (desired->depthBits > 0) ATTR(EGL_DEPTH_SIZE, desired->depthBits);
|
||||||
|
if (desired->stencilBits > 0) ATTR(EGL_STENCIL_SIZE, desired->stencilBits);
|
||||||
|
if (desired->redBits > 0) ATTR(EGL_RED_SIZE, desired->redBits);
|
||||||
|
if (desired->greenBits > 0) ATTR(EGL_GREEN_SIZE, desired->greenBits);
|
||||||
|
if (desired->blueBits > 0) ATTR(EGL_BLUE_SIZE, desired->blueBits);
|
||||||
|
if (desired->alphaBits > 0) ATTR(EGL_ALPHA_SIZE, desired->alphaBits);
|
||||||
|
ATTR(EGL_NONE, EGL_NONE);
|
||||||
|
#undef ATTR
|
||||||
|
if (!eglChooseConfig(_glfw.egl.display, attributes, configs, sizeof(configs)/sizeof(configs[0]), &nativeCount)) {
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: eglChooseConfig failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
|
|
||||||
if (!nativeCount)
|
if (!nativeCount)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
|
||||||
eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
|
|
||||||
|
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
|
||||||
usableCount = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < nativeCount; i++)
|
for (i = 0; i < nativeCount; i++)
|
||||||
{
|
{
|
||||||
const EGLConfig n = nativeConfigs[i];
|
|
||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
|
||||||
|
|
||||||
// Only consider RGB(A) EGLConfigs
|
|
||||||
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Only consider window EGLConfigs
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
{
|
{
|
||||||
|
const EGLConfig n = configs[i];
|
||||||
XVisualInfo vi = {0};
|
XVisualInfo vi = {0};
|
||||||
|
|
||||||
// Only consider EGLConfigs with associated Visuals
|
// Only consider EGLConfigs with associated Visuals
|
||||||
@@ -138,55 +145,18 @@ static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
|
XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
|
||||||
if (vis)
|
if (vis)
|
||||||
{
|
{
|
||||||
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
bool transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
||||||
XFree(vis);
|
XFree(vis);
|
||||||
|
if (!transparent) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // _GLFW_X11
|
#endif // _GLFW_X11
|
||||||
|
ans_idx = i;
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
break;
|
||||||
{
|
|
||||||
if (ctxconfig->major == 1)
|
|
||||||
{
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
|
|
||||||
u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
|
|
||||||
u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
|
|
||||||
|
|
||||||
u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
|
|
||||||
u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
|
|
||||||
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
|
||||||
|
|
||||||
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
|
||||||
u->doublebuffer = true;
|
|
||||||
|
|
||||||
u->handle = (uintptr_t) n;
|
|
||||||
usableCount++;
|
|
||||||
}
|
}
|
||||||
|
*result = configs[ans_idx];
|
||||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
return true;
|
||||||
if (closest)
|
|
||||||
*result = (EGLConfig) closest->handle;
|
|
||||||
|
|
||||||
free(nativeConfigs);
|
|
||||||
free(usableConfigs);
|
|
||||||
|
|
||||||
return closest != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void makeContextCurrentEGL(_GLFWwindow* window)
|
static void makeContextCurrentEGL(_GLFWwindow* window)
|
||||||
@@ -340,6 +310,7 @@ bool _glfwInitEGL(void)
|
|||||||
|
|
||||||
glfw_dlsym(_glfw.egl.GetConfigAttrib, _glfw.egl.handle, "eglGetConfigAttrib");
|
glfw_dlsym(_glfw.egl.GetConfigAttrib, _glfw.egl.handle, "eglGetConfigAttrib");
|
||||||
glfw_dlsym(_glfw.egl.GetConfigs, _glfw.egl.handle, "eglGetConfigs");
|
glfw_dlsym(_glfw.egl.GetConfigs, _glfw.egl.handle, "eglGetConfigs");
|
||||||
|
glfw_dlsym(_glfw.egl.ChooseConfig, _glfw.egl.handle, "eglChooseConfig");
|
||||||
glfw_dlsym(_glfw.egl.GetDisplay, _glfw.egl.handle, "eglGetDisplay");
|
glfw_dlsym(_glfw.egl.GetDisplay, _glfw.egl.handle, "eglGetDisplay");
|
||||||
glfw_dlsym(_glfw.egl.GetError, _glfw.egl.handle, "eglGetError");
|
glfw_dlsym(_glfw.egl.GetError, _glfw.egl.handle, "eglGetError");
|
||||||
glfw_dlsym(_glfw.egl.Initialize, _glfw.egl.handle, "eglInitialize");
|
glfw_dlsym(_glfw.egl.Initialize, _glfw.egl.handle, "eglInitialize");
|
||||||
@@ -357,6 +328,7 @@ bool _glfwInitEGL(void)
|
|||||||
|
|
||||||
if (!_glfw.egl.GetConfigAttrib ||
|
if (!_glfw.egl.GetConfigAttrib ||
|
||||||
!_glfw.egl.GetConfigs ||
|
!_glfw.egl.GetConfigs ||
|
||||||
|
!_glfw.egl.ChooseConfig ||
|
||||||
!_glfw.egl.GetDisplay ||
|
!_glfw.egl.GetDisplay ||
|
||||||
!_glfw.egl.GetError ||
|
!_glfw.egl.GetError ||
|
||||||
!_glfw.egl.Initialize ||
|
!_glfw.egl.Initialize ||
|
||||||
@@ -572,18 +544,16 @@ bool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up attributes for surface creation
|
// Set up attributes for surface creation
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
if (fbconfig->sRGB)
|
||||||
{
|
{
|
||||||
int index = 0;
|
if (_glfw.egl.KHR_gl_colorspace)
|
||||||
|
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||||
if (fbconfig->sRGB)
|
|
||||||
{
|
|
||||||
if (_glfw.egl.KHR_gl_colorspace)
|
|
||||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
|
||||||
}
|
|
||||||
|
|
||||||
setAttrib(EGL_NONE, EGL_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setAttrib(EGL_NONE, EGL_NONE);
|
||||||
|
|
||||||
window->context.egl.surface =
|
window->context.egl.surface =
|
||||||
eglCreateWindowSurface(_glfw.egl.display,
|
eglCreateWindowSurface(_glfw.egl.display,
|
||||||
config,
|
config,
|
||||||
|
|||||||
3
glfw/egl_context.h
vendored
3
glfw/egl_context.h
vendored
@@ -120,6 +120,7 @@ typedef void* EGLSurface;
|
|||||||
// EGL function pointer typedefs
|
// EGL function pointer typedefs
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglChooseConfig)(EGLDisplay,EGLint const*,EGLConfig*,EGLint,EGLint*);
|
||||||
typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
|
typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
|
||||||
typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
|
typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
|
||||||
@@ -136,6 +137,7 @@ typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
|
|||||||
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
||||||
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
||||||
#define eglGetConfigs _glfw.egl.GetConfigs
|
#define eglGetConfigs _glfw.egl.GetConfigs
|
||||||
|
#define eglChooseConfig _glfw.egl.ChooseConfig
|
||||||
#define eglGetDisplay _glfw.egl.GetDisplay
|
#define eglGetDisplay _glfw.egl.GetDisplay
|
||||||
#define eglGetError _glfw.egl.GetError
|
#define eglGetError _glfw.egl.GetError
|
||||||
#define eglInitialize _glfw.egl.Initialize
|
#define eglInitialize _glfw.egl.Initialize
|
||||||
@@ -185,6 +187,7 @@ typedef struct _GLFWlibraryEGL
|
|||||||
|
|
||||||
PFN_eglGetConfigAttrib GetConfigAttrib;
|
PFN_eglGetConfigAttrib GetConfigAttrib;
|
||||||
PFN_eglGetConfigs GetConfigs;
|
PFN_eglGetConfigs GetConfigs;
|
||||||
|
PFN_eglChooseConfig ChooseConfig;
|
||||||
PFN_eglGetDisplay GetDisplay;
|
PFN_eglGetDisplay GetDisplay;
|
||||||
PFN_eglGetError GetError;
|
PFN_eglGetError GetError;
|
||||||
PFN_eglInitialize Initialize;
|
PFN_eglInitialize Initialize;
|
||||||
|
|||||||
21
glfw/glfw.py
21
glfw/glfw.py
@@ -6,7 +6,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from typing import Callable, List, Optional, Tuple
|
from typing import Callable, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_linux = 'linux' in _plat
|
is_linux = 'linux' in _plat
|
||||||
@@ -19,6 +19,7 @@ class Env:
|
|||||||
cppflags: List[str] = []
|
cppflags: List[str] = []
|
||||||
cflags: List[str] = []
|
cflags: List[str] = []
|
||||||
ldflags: List[str] = []
|
ldflags: List[str] = []
|
||||||
|
library_paths: Dict[str, List[str]] = {}
|
||||||
ldpaths: List[str] = []
|
ldpaths: List[str] = []
|
||||||
ccver: Tuple[int, int]
|
ccver: Tuple[int, int]
|
||||||
|
|
||||||
@@ -32,13 +33,13 @@ class Env:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
|
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
|
||||||
ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0)
|
library_paths: Dict[str, List[str]] = {}, ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0)
|
||||||
):
|
):
|
||||||
self.cc, self.cppflags, self.cflags, self.ldflags, self.ldpaths = cc, cppflags, cflags, ldflags, [] if ldpaths is None else ldpaths
|
self.cc, self.cppflags, self.cflags, self.ldflags, self.library_paths = cc, cppflags, cflags, ldflags, library_paths
|
||||||
self.ccver = ccver
|
self.ldpaths, self.ccver = [] if ldpaths is None else ldpaths, ccver
|
||||||
|
|
||||||
def copy(self) -> 'Env':
|
def copy(self) -> 'Env':
|
||||||
ans = Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), list(self.ldpaths), self.ccver)
|
ans = Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), dict(self.library_paths), list(self.ldpaths), self.ccver)
|
||||||
ans.all_headers = list(self.all_headers)
|
ans.all_headers = list(self.all_headers)
|
||||||
ans.sources = list(self.sources)
|
ans.sources = list(self.sources)
|
||||||
ans.wayland_packagedir = self.wayland_packagedir
|
ans.wayland_packagedir = self.wayland_packagedir
|
||||||
@@ -55,7 +56,7 @@ def wayland_protocol_file_name(base: str, ext: str = 'c') -> str:
|
|||||||
|
|
||||||
def init_env(env: Env, pkg_config: Callable, at_least_version: Callable, test_compile: Callable, module: str = 'x11') -> Env:
|
def init_env(env: Env, pkg_config: Callable, at_least_version: Callable, test_compile: Callable, module: str = 'x11') -> Env:
|
||||||
ans = env.copy()
|
ans = env.copy()
|
||||||
ans.cflags.append('-fpic')
|
ans.cflags.append('-fPIC')
|
||||||
ans.cppflags.append('-D_GLFW_' + module.upper())
|
ans.cppflags.append('-D_GLFW_' + module.upper())
|
||||||
ans.cppflags.append('-D_GLFW_BUILD_DLL')
|
ans.cppflags.append('-D_GLFW_BUILD_DLL')
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ def init_env(env: Env, pkg_config: Callable, at_least_version: Callable, test_co
|
|||||||
for p in ans.wayland_protocols:
|
for p in ans.wayland_protocols:
|
||||||
ans.sources.append(wayland_protocol_file_name(p))
|
ans.sources.append(wayland_protocol_file_name(p))
|
||||||
ans.all_headers.append(wayland_protocol_file_name(p, 'h'))
|
ans.all_headers.append(wayland_protocol_file_name(p, 'h'))
|
||||||
for dep in 'wayland-egl wayland-client wayland-cursor xkbcommon dbus-1'.split():
|
for dep in 'wayland-client wayland-cursor xkbcommon dbus-1'.split():
|
||||||
ans.cflags.extend(pkg_config(dep, '--cflags-only-I'))
|
ans.cflags.extend(pkg_config(dep, '--cflags-only-I'))
|
||||||
ans.ldpaths.extend(pkg_config(dep, '--libs'))
|
ans.ldpaths.extend(pkg_config(dep, '--libs'))
|
||||||
has_memfd_create = test_compile(env.cc, '-Werror', src='''#define _GNU_SOURCE
|
has_memfd_create = test_compile(env.cc, '-Werror', src='''#define _GNU_SOURCE
|
||||||
@@ -165,7 +166,7 @@ class Function:
|
|||||||
self.args = [Arg('void v')]
|
self.args = [Arg('void v')]
|
||||||
|
|
||||||
def declaration(self) -> str:
|
def declaration(self) -> str:
|
||||||
return 'typedef {restype} (*{name}_func)({args});\n{name}_func {name}_impl;\n#define {name} {name}_impl'.format(
|
return 'typedef {restype} (*{name}_func)({args});\nGFW_EXTERN {name}_func {name}_impl;\n#define {name} {name}_impl'.format(
|
||||||
restype=self.restype,
|
restype=self.restype,
|
||||||
name=self.name,
|
name=self.name,
|
||||||
args=', '.join(a.type for a in self.args)
|
args=', '.join(a.type for a in self.args)
|
||||||
@@ -233,6 +234,9 @@ const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callbac
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "monotonic.h"
|
#include "monotonic.h"
|
||||||
|
|
||||||
|
#ifndef GFW_EXTERN
|
||||||
|
#define GFW_EXTERN extern
|
||||||
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
||||||
@@ -251,6 +255,7 @@ const char* load_glfw(const char* path);
|
|||||||
f.write(header)
|
f.write(header)
|
||||||
|
|
||||||
code = '''
|
code = '''
|
||||||
|
#define GFW_EXTERN
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
#include "glfw-wrapper.h"
|
#include "glfw-wrapper.h"
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|||||||
180
glfw/glfw3.h
vendored
180
glfw/glfw3.h
vendored
@@ -195,7 +195,38 @@ extern "C" {
|
|||||||
|
|
||||||
#endif /*__APPLE__*/
|
#endif /*__APPLE__*/
|
||||||
|
|
||||||
#elif !defined(GLFW_INCLUDE_NONE)
|
#elif defined(GLFW_INCLUDE_GLU)
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
|
||||||
|
#if defined(GLFW_INCLUDE_GLU)
|
||||||
|
#include <OpenGL/glu.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /*__APPLE__*/
|
||||||
|
|
||||||
|
#if defined(GLFW_INCLUDE_GLU)
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*__APPLE__*/
|
||||||
|
|
||||||
|
#elif !defined(GLFW_INCLUDE_NONE) && \
|
||||||
|
!defined(__gl_h_) && \
|
||||||
|
!defined(__gles1_gl_h_) && \
|
||||||
|
!defined(__gles2_gl2_h_) && \
|
||||||
|
!defined(__gles2_gl3_h_) && \
|
||||||
|
!defined(__gles2_gl31_h_) && \
|
||||||
|
!defined(__gles2_gl32_h_) && \
|
||||||
|
!defined(__gl_glcorearb_h_) && \
|
||||||
|
!defined(__gl2_h_) /*legacy*/ && \
|
||||||
|
!defined(__gl3_h_) /*legacy*/ && \
|
||||||
|
!defined(__gl31_h_) /*legacy*/ && \
|
||||||
|
!defined(__gl32_h_) /*legacy*/ && \
|
||||||
|
!defined(__glcorearb_h_) /*legacy*/ && \
|
||||||
|
!defined(__GL_H__) /*non-standard*/ && \
|
||||||
|
!defined(__gltypes_h_) /*non-standard*/ && \
|
||||||
|
!defined(__glee_h_) /*non-standard*/
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
|
||||||
@@ -203,9 +234,6 @@ extern "C" {
|
|||||||
#define GL_GLEXT_LEGACY
|
#define GL_GLEXT_LEGACY
|
||||||
#endif
|
#endif
|
||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl.h>
|
||||||
#if defined(GLFW_INCLUDE_GLU)
|
|
||||||
#include <OpenGL/glu.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /*__APPLE__*/
|
#else /*__APPLE__*/
|
||||||
|
|
||||||
@@ -213,9 +241,6 @@ extern "C" {
|
|||||||
#if defined(GLFW_INCLUDE_GLEXT)
|
#if defined(GLFW_INCLUDE_GLEXT)
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
#endif
|
#endif
|
||||||
#if defined(GLFW_INCLUDE_GLU)
|
|
||||||
#include <GL/glu.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*__APPLE__*/
|
#endif /*__APPLE__*/
|
||||||
|
|
||||||
@@ -806,6 +831,33 @@ extern "C" {
|
|||||||
* @analysis Application programmer error. Fix the offending call.
|
* @analysis Application programmer error. Fix the offending call.
|
||||||
*/
|
*/
|
||||||
#define GLFW_NO_WINDOW_CONTEXT 0x0001000A
|
#define GLFW_NO_WINDOW_CONTEXT 0x0001000A
|
||||||
|
/*! @brief The reuqested feature is not provided by the platform.
|
||||||
|
*
|
||||||
|
* The requested feature is not provided by the platform, so GLFW is unable to
|
||||||
|
* implement it. The documentation for each function notes if it could emit
|
||||||
|
* this error.
|
||||||
|
*
|
||||||
|
* @analysis Platform or platform version limitation. The error can be ignored
|
||||||
|
* unless the feature is critical to the application.
|
||||||
|
*
|
||||||
|
* @par
|
||||||
|
* A function call that emits this error has no effect other than the error and
|
||||||
|
* updating any existing out parameters.
|
||||||
|
*/
|
||||||
|
#define GLFW_FEATURE_UNAVAILABLE 0x0001000C
|
||||||
|
/*! @brief The requested feature is not implemented for the platform.
|
||||||
|
*
|
||||||
|
* The requested feature has not yet been implemented in GLFW for this platform.
|
||||||
|
*
|
||||||
|
* @analysis An incomplete implementation of GLFW for this platform, hopefully
|
||||||
|
* fixed in a future release. The error can be ignored unless the feature is
|
||||||
|
* critical to the application.
|
||||||
|
*
|
||||||
|
* @par
|
||||||
|
* A function call that emits this error has no effect other than the error and
|
||||||
|
* updating any existing out parameters.
|
||||||
|
*/
|
||||||
|
#define GLFW_FEATURE_UNIMPLEMENTED 0x0001000D
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
/*! @addtogroup window
|
/*! @addtogroup window
|
||||||
@@ -1076,6 +1128,7 @@ extern "C" {
|
|||||||
#define GLFW_STICKY_KEYS 0x00033002
|
#define GLFW_STICKY_KEYS 0x00033002
|
||||||
#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
|
#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
|
||||||
#define GLFW_LOCK_KEY_MODS 0x00033004
|
#define GLFW_LOCK_KEY_MODS 0x00033004
|
||||||
|
#define GLFW_RAW_MOUSE_MOTION 0x00033005
|
||||||
|
|
||||||
#define GLFW_CURSOR_NORMAL 0x00034001
|
#define GLFW_CURSOR_NORMAL 0x00034001
|
||||||
#define GLFW_CURSOR_HIDDEN 0x00034002
|
#define GLFW_CURSOR_HIDDEN 0x00034002
|
||||||
@@ -1319,6 +1372,22 @@ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);
|
|||||||
*/
|
*/
|
||||||
typedef void (* GLFWwindowclosefun)(GLFWwindow*);
|
typedef void (* GLFWwindowclosefun)(GLFWwindow*);
|
||||||
|
|
||||||
|
/*! @brief The function pointer type for application close callbacks.
|
||||||
|
*
|
||||||
|
* This is the function pointer type for application close callbacks. A application
|
||||||
|
* close callback function has the following signature:
|
||||||
|
* @code
|
||||||
|
* void function_name(int flags)
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @param[in] flags 0 for a user requested application quit, 1 if a fatal error occurred and application should quit ASAP
|
||||||
|
*
|
||||||
|
* @sa @ref glfwSetApplicationCloseCallback
|
||||||
|
*
|
||||||
|
* @ingroup window
|
||||||
|
*/
|
||||||
|
typedef void (* GLFWapplicationclosefun)(int);
|
||||||
|
|
||||||
/*! @brief The function pointer type for window content refresh callbacks.
|
/*! @brief The function pointer type for window content refresh callbacks.
|
||||||
*
|
*
|
||||||
* This is the function pointer type for window content refresh callbacks.
|
* This is the function pointer type for window content refresh callbacks.
|
||||||
@@ -1550,6 +1619,7 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
|
|||||||
* value 2 for stationary momentum scrolling, value 3 for momentum scrolling
|
* value 2 for stationary momentum scrolling, value 3 for momentum scrolling
|
||||||
* in progress, value 4 for momentum scrolling ended, value 5 for momentum
|
* in progress, value 4 for momentum scrolling ended, value 5 for momentum
|
||||||
* scrolling cancelled and value 6 if scrolling may begin soon.
|
* scrolling cancelled and value 6 if scrolling may begin soon.
|
||||||
|
* @param[int] mods The keyboard modifiers
|
||||||
*
|
*
|
||||||
* @sa @ref scrolling
|
* @sa @ref scrolling
|
||||||
* @sa @ref glfwSetScrollCallback
|
* @sa @ref glfwSetScrollCallback
|
||||||
@@ -1559,7 +1629,7 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
|
|||||||
*
|
*
|
||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
|
typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int,int);
|
||||||
|
|
||||||
/*! @brief The function pointer type for key callbacks.
|
/*! @brief The function pointer type for key callbacks.
|
||||||
*
|
*
|
||||||
@@ -1835,6 +1905,8 @@ GLFWAPI void glfwRemoveTimer(unsigned long long);
|
|||||||
* call this function, as it is called by @ref glfwInit before it returns
|
* call this function, as it is called by @ref glfwInit before it returns
|
||||||
* failure.
|
* failure.
|
||||||
*
|
*
|
||||||
|
* This function has no effect if GLFW is not initialized.
|
||||||
|
*
|
||||||
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
||||||
*
|
*
|
||||||
* @remark This function may be called before @ref glfwInit.
|
* @remark This function may be called before @ref glfwInit.
|
||||||
@@ -2832,21 +2904,21 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
|||||||
* @param[in] images The images to create the icon from. This is ignored if
|
* @param[in] images The images to create the icon from. This is ignored if
|
||||||
* count is zero.
|
* count is zero.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||||
*
|
*
|
||||||
* @pointer_lifetime The specified image data is copied before this function
|
* @pointer_lifetime The specified image data is copied before this function
|
||||||
* returns.
|
* returns.
|
||||||
*
|
*
|
||||||
* @remark @macos The GLFW window has no icon, as it is not a document
|
* @remark @macos Regular windows do not have icons on macOS. This function
|
||||||
* window, so this function does nothing. The dock icon will be the same as
|
* will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as
|
||||||
* the application bundle's icon. For more information on bundles, see the
|
* the application bundle's icon. For more information on bundles, see the
|
||||||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||||
* in the Mac Developer Library.
|
* in the Mac Developer Library.
|
||||||
*
|
*
|
||||||
* @remark @wayland There is no existing protocol to change an icon, the
|
* @remark @wayland There is no existing protocol to change an icon, the
|
||||||
* window will thus inherit the one defined in the application's desktop file.
|
* window will thus inherit the one defined in the application's desktop file.
|
||||||
* This function always emits @ref GLFW_PLATFORM_ERROR.
|
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -2872,12 +2944,12 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
|
|||||||
* @param[out] ypos Where to store the y-coordinate of the upper-left corner of
|
* @param[out] ypos Where to store the y-coordinate of the upper-left corner of
|
||||||
* the content area, or `NULL`.
|
* the content area, or `NULL`.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||||
*
|
*
|
||||||
* @remark @wayland There is no way for an application to retrieve the global
|
* @remark @wayland There is no way for an application to retrieve the global
|
||||||
* position of its windows, this function will always emit @ref
|
* position of its windows. This function will emit @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_FEATURE_UNAVAILABLE.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -2906,12 +2978,12 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
|||||||
* @param[in] xpos The x-coordinate of the upper-left corner of the content area.
|
* @param[in] xpos The x-coordinate of the upper-left corner of the content area.
|
||||||
* @param[in] ypos The y-coordinate of the upper-left corner of the content area.
|
* @param[in] ypos The y-coordinate of the upper-left corner of the content area.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||||
*
|
*
|
||||||
* @remark @wayland There is no way for an application to set the global
|
* @remark @wayland There is no way for an application to set the global
|
||||||
* position of its windows, this function will always emit @ref
|
* position of its windows. This function will emit @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_FEATURE_UNAVAILABLE.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -3289,8 +3361,11 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
|
|||||||
* @param[in] window The window to set the opacity for.
|
* @param[in] window The window to set the opacity for.
|
||||||
* @param[in] opacity The desired opacity of the specified window.
|
* @param[in] opacity The desired opacity of the specified window.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||||
|
*
|
||||||
|
* @remark @wayland There is no way to set an opacity factor for a window.
|
||||||
|
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -3457,11 +3532,11 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
|
|||||||
*
|
*
|
||||||
* @param[in] window The window to give input focus.
|
* @param[in] window The window to give input focus.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
|
||||||
*
|
*
|
||||||
* @remark @wayland It is not possible for an application to bring its windows
|
* @remark @wayland It is not possible for an application to set the input
|
||||||
* to front, this function will always emit @ref GLFW_PLATFORM_ERROR.
|
* focus. This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -3826,6 +3901,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
|
|||||||
* @ingroup window
|
* @ingroup window
|
||||||
*/
|
*/
|
||||||
GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback);
|
GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback);
|
||||||
|
GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun callback);
|
||||||
|
|
||||||
/*! @brief Sets the refresh callback for the specified window.
|
/*! @brief Sets the refresh callback for the specified window.
|
||||||
*
|
*
|
||||||
@@ -4075,11 +4151,13 @@ GLFWAPI void glfwPostEmptyEvent(void);
|
|||||||
*
|
*
|
||||||
* This function returns the value of an input option for the specified window.
|
* This function returns the value of an input option for the specified window.
|
||||||
* The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
|
* The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
|
||||||
* @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS.
|
* @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
|
||||||
|
* @ref GLFW_RAW_MOUSE_MOTION.
|
||||||
*
|
*
|
||||||
* @param[in] window The window to query.
|
* @param[in] window The window to query.
|
||||||
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
|
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
|
||||||
* `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`.
|
* `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
|
||||||
|
* `GLFW_RAW_MOUSE_MOTION`.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_INVALID_ENUM.
|
* GLFW_INVALID_ENUM.
|
||||||
@@ -4098,7 +4176,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
|||||||
*
|
*
|
||||||
* This function sets an input mode option for the specified window. The mode
|
* This function sets an input mode option for the specified window. The mode
|
||||||
* must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
|
* must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
|
||||||
* @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS.
|
* @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
|
||||||
|
* @ref GLFW_RAW_MOUSE_MOTION.
|
||||||
*
|
*
|
||||||
* If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
|
* If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
|
||||||
* modes:
|
* modes:
|
||||||
@@ -4130,13 +4209,21 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
|||||||
* GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
|
* GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
|
||||||
* and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
|
* and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
|
||||||
*
|
*
|
||||||
|
* If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `true`
|
||||||
|
* to enable raw (unscaled and unaccelerated) mouse motion when the cursor is
|
||||||
|
* disabled, or `false` to disable it. If raw motion is not supported,
|
||||||
|
* attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref
|
||||||
|
* glfwRawMouseMotionSupported to check for support.
|
||||||
|
*
|
||||||
* @param[in] window The window whose input mode to set.
|
* @param[in] window The window whose input mode to set.
|
||||||
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
|
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
|
||||||
* `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`.
|
* `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
|
||||||
|
* `GLFW_RAW_MOUSE_MOTION`.
|
||||||
* @param[in] value The new value of the specified input mode.
|
* @param[in] value The new value of the specified input mode.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
* GLFW_INVALID_ENUM, @ref GLFW_PLATFORM_ERROR and @ref
|
||||||
|
* GLFW_FEATURE_UNAVAILABLE (see above).
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -4148,6 +4235,35 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
|
GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
|
||||||
|
|
||||||
|
/*! @brief Returns whether raw mouse motion is supported.
|
||||||
|
*
|
||||||
|
* This function returns whether raw mouse motion is supported on the current
|
||||||
|
* system. This status does not change after GLFW has been initialized so you
|
||||||
|
* only need to check this once. If you attempt to enable raw motion on
|
||||||
|
* a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted.
|
||||||
|
*
|
||||||
|
* Raw mouse motion is closer to the actual motion of the mouse across
|
||||||
|
* a surface. It is not affected by the scaling and acceleration applied to
|
||||||
|
* the motion of the desktop cursor. That processing is suitable for a cursor
|
||||||
|
* while raw motion is better for controlling for example a 3D camera. Because
|
||||||
|
* of this, raw mouse motion is only provided when the cursor is disabled.
|
||||||
|
*
|
||||||
|
* @return `true` if raw mouse motion is supported on the current machine,
|
||||||
|
* or `false` otherwise.
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref raw_mouse_motion
|
||||||
|
* @sa @ref glfwSetInputMode
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup input
|
||||||
|
*/
|
||||||
|
GLFWAPI int glfwRawMouseMotionSupported(void);
|
||||||
|
|
||||||
/*! @brief Returns the layout-specific name of the specified printable key.
|
/*! @brief Returns the layout-specific name of the specified printable key.
|
||||||
*
|
*
|
||||||
* This function returns the name of the specified printable key, encoded as
|
* This function returns the name of the specified printable key, encoded as
|
||||||
|
|||||||
111
glfw/glx_context.c
vendored
111
glfw/glx_context.c
vendored
@@ -47,99 +47,87 @@ static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLXFBConfig*
|
||||||
|
choose_fb_config(const _GLFWfbconfig* desired, bool trust_window_bit, int *nelements) {
|
||||||
|
int attrib_list[64];
|
||||||
|
int pos = 0;
|
||||||
|
#define ATTR(x, y) { attrib_list[pos++] = x; attrib_list[pos++] = y; }
|
||||||
|
|
||||||
|
ATTR(GLX_DOUBLEBUFFER, desired->doublebuffer ? True : False);
|
||||||
|
if (desired->stereo > 0) ATTR(GLX_STEREO, desired->stereo ? True : False);
|
||||||
|
if (desired->auxBuffers > 0) ATTR(GLX_AUX_BUFFERS, desired->auxBuffers);
|
||||||
|
if (_glfw.glx.ARB_multisample && desired->samples > 0) ATTR(GLX_SAMPLES, desired->samples);
|
||||||
|
if (desired->depthBits != GLFW_DONT_CARE) ATTR(GLX_DEPTH_SIZE, desired->depthBits);
|
||||||
|
if (desired->stencilBits != GLFW_DONT_CARE) ATTR(GLX_STENCIL_SIZE, desired->stencilBits);
|
||||||
|
if (desired->redBits != GLFW_DONT_CARE) ATTR(GLX_RED_SIZE, desired->redBits);
|
||||||
|
if (desired->greenBits != GLFW_DONT_CARE) ATTR(GLX_GREEN_SIZE, desired->greenBits);
|
||||||
|
if (desired->blueBits != GLFW_DONT_CARE) ATTR(GLX_BLUE_SIZE, desired->blueBits);
|
||||||
|
if (desired->alphaBits != GLFW_DONT_CARE) ATTR(GLX_ALPHA_SIZE, desired->alphaBits);
|
||||||
|
if (desired->accumRedBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_RED_SIZE, desired->accumRedBits);
|
||||||
|
if (desired->accumGreenBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_GREEN_SIZE, desired->accumGreenBits);
|
||||||
|
if (desired->accumBlueBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_BLUE_SIZE, desired->accumBlueBits);
|
||||||
|
if (desired->accumAlphaBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_ALPHA_SIZE, desired->accumAlphaBits);
|
||||||
|
if (!trust_window_bit) ATTR(GLX_DRAWABLE_TYPE, 0);
|
||||||
|
ATTR(None, None);
|
||||||
|
return glXChooseFBConfig(_glfw.x11.display, _glfw.x11.screen, attrib_list, nelements);
|
||||||
|
#undef ATTR
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Return the GLXFBConfig most closely matching the specified hints
|
// Return the GLXFBConfig most closely matching the specified hints
|
||||||
//
|
//
|
||||||
static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||||
GLXFBConfig* result)
|
GLXFBConfig* result)
|
||||||
{
|
{
|
||||||
GLXFBConfig* nativeConfigs;
|
GLXFBConfig* nativeConfigs;
|
||||||
_GLFWfbconfig* usableConfigs;
|
int i, nativeCount, ans_idx = 0;
|
||||||
const _GLFWfbconfig* closest;
|
|
||||||
int i, nativeCount, usableCount;
|
|
||||||
const char* vendor;
|
const char* vendor;
|
||||||
bool trustWindowBit = true;
|
bool trustWindowBit = true;
|
||||||
|
static _GLFWfbconfig prev_desired = {0};
|
||||||
|
static GLXFBConfig prev_result = 0;
|
||||||
|
if (prev_result != 0 && memcmp(&prev_desired, desired, sizeof(_GLFWfbconfig)) == 0) {
|
||||||
|
*result = prev_result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
prev_desired = *desired;
|
||||||
|
|
||||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||||
if (vendor && strcmp(vendor, "Chromium") == 0)
|
if (vendor && strcmp(vendor, "Chromium") == 0)
|
||||||
trustWindowBit = false;
|
trustWindowBit = false;
|
||||||
|
nativeConfigs = choose_fb_config(desired, trustWindowBit, &nativeCount);
|
||||||
nativeConfigs =
|
|
||||||
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
|
||||||
if (!nativeConfigs || !nativeCount)
|
if (!nativeConfigs || !nativeCount)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
|
||||||
usableCount = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < nativeCount; i++)
|
for (i = 0; i < nativeCount; i++)
|
||||||
{
|
{
|
||||||
const GLXFBConfig n = nativeConfigs[i];
|
const GLXFBConfig n = nativeConfigs[i];
|
||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
bool transparency_matches = true, srgb_matches = true;
|
||||||
|
if (desired->transparent) {
|
||||||
// Only consider RGBA GLXFBConfigs
|
transparency_matches = false;
|
||||||
if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Only consider window GLXFBConfigs
|
|
||||||
if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
|
|
||||||
{
|
|
||||||
if (trustWindowBit)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->transparent)
|
|
||||||
{
|
|
||||||
XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
|
XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
|
||||||
if (vi)
|
if (vi && _glfwIsVisualTransparentX11(vi->visual)) transparency_matches = true;
|
||||||
{
|
|
||||||
u->transparent = _glfwIsVisualTransparentX11(vi->visual);
|
|
||||||
XFree(vi);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
|
if (desired->sRGB && (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)) {
|
||||||
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
|
srgb_matches = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB) ? true : false;
|
||||||
u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
|
}
|
||||||
|
|
||||||
u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
|
if (transparency_matches && srgb_matches) {
|
||||||
u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
|
ans_idx = i; break;
|
||||||
u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE);
|
}
|
||||||
|
|
||||||
u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
|
|
||||||
u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
|
|
||||||
u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
|
|
||||||
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
|
|
||||||
|
|
||||||
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
|
|
||||||
|
|
||||||
if (getGLXFBConfigAttrib(n, GLX_STEREO))
|
|
||||||
u->stereo = true;
|
|
||||||
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
|
|
||||||
u->doublebuffer = true;
|
|
||||||
|
|
||||||
if (_glfw.glx.ARB_multisample)
|
|
||||||
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
|
|
||||||
|
|
||||||
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
|
|
||||||
u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
|
||||||
|
|
||||||
u->handle = (uintptr_t) n;
|
|
||||||
usableCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
*result = nativeConfigs[ans_idx];
|
||||||
if (closest)
|
prev_result = nativeConfigs[ans_idx];
|
||||||
*result = (GLXFBConfig) closest->handle;
|
|
||||||
|
|
||||||
XFree(nativeConfigs);
|
XFree(nativeConfigs);
|
||||||
free(usableConfigs);
|
|
||||||
|
|
||||||
return closest != NULL;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the OpenGL context using legacy API
|
// Create the OpenGL context using legacy API
|
||||||
@@ -287,6 +275,7 @@ bool _glfwInitGLX(void)
|
|||||||
|
|
||||||
glfw_dlsym(_glfw.glx.GetFBConfigs, _glfw.glx.handle, "glXGetFBConfigs");
|
glfw_dlsym(_glfw.glx.GetFBConfigs, _glfw.glx.handle, "glXGetFBConfigs");
|
||||||
glfw_dlsym(_glfw.glx.GetFBConfigAttrib, _glfw.glx.handle, "glXGetFBConfigAttrib");
|
glfw_dlsym(_glfw.glx.GetFBConfigAttrib, _glfw.glx.handle, "glXGetFBConfigAttrib");
|
||||||
|
glfw_dlsym(_glfw.glx.ChooseFBConfig, _glfw.glx.handle, "glXChooseFBConfig");
|
||||||
glfw_dlsym(_glfw.glx.GetClientString, _glfw.glx.handle, "glXGetClientString");
|
glfw_dlsym(_glfw.glx.GetClientString, _glfw.glx.handle, "glXGetClientString");
|
||||||
glfw_dlsym(_glfw.glx.QueryExtension, _glfw.glx.handle, "glXQueryExtension");
|
glfw_dlsym(_glfw.glx.QueryExtension, _glfw.glx.handle, "glXQueryExtension");
|
||||||
glfw_dlsym(_glfw.glx.QueryVersion, _glfw.glx.handle, "glXQueryVersion");
|
glfw_dlsym(_glfw.glx.QueryVersion, _glfw.glx.handle, "glXQueryVersion");
|
||||||
|
|||||||
3
glfw/glx_context.h
vendored
3
glfw/glx_context.h
vendored
@@ -73,6 +73,7 @@ typedef struct __GLXcontext* GLXContext;
|
|||||||
typedef void (*__GLXextproc)(void);
|
typedef void (*__GLXextproc)(void);
|
||||||
|
|
||||||
typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);
|
typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);
|
||||||
|
typedef GLXFBConfig* (*PFNGLXCHOOSEFBCONFIGPROC)(Display*,int,const int*,int*);
|
||||||
typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);
|
typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);
|
||||||
typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);
|
typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);
|
||||||
typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);
|
typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);
|
||||||
@@ -95,6 +96,7 @@ typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLX
|
|||||||
// libGL.so function pointer typedefs
|
// libGL.so function pointer typedefs
|
||||||
#define glXGetFBConfigs _glfw.glx.GetFBConfigs
|
#define glXGetFBConfigs _glfw.glx.GetFBConfigs
|
||||||
#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
|
#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
|
||||||
|
#define glXChooseFBConfig _glfw.glx.ChooseFBConfig
|
||||||
#define glXGetClientString _glfw.glx.GetClientString
|
#define glXGetClientString _glfw.glx.GetClientString
|
||||||
#define glXQueryExtension _glfw.glx.QueryExtension
|
#define glXQueryExtension _glfw.glx.QueryExtension
|
||||||
#define glXQueryVersion _glfw.glx.QueryVersion
|
#define glXQueryVersion _glfw.glx.QueryVersion
|
||||||
@@ -134,6 +136,7 @@ typedef struct _GLFWlibraryGLX
|
|||||||
// GLX 1.3 functions
|
// GLX 1.3 functions
|
||||||
PFNGLXGETFBCONFIGSPROC GetFBConfigs;
|
PFNGLXGETFBCONFIGSPROC GetFBConfigs;
|
||||||
PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib;
|
PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib;
|
||||||
|
PFNGLXCHOOSEFBCONFIGPROC ChooseFBConfig;
|
||||||
PFNGLXGETCLIENTSTRINGPROC GetClientString;
|
PFNGLXGETCLIENTSTRINGPROC GetClientString;
|
||||||
PFNGLXQUERYEXTENSIONPROC QueryExtension;
|
PFNGLXQUERYEXTENSIONPROC QueryExtension;
|
||||||
PFNGLXQUERYVERSIONPROC QueryVersion;
|
PFNGLXQUERYVERSIONPROC QueryVersion;
|
||||||
|
|||||||
11
glfw/init.c
vendored
11
glfw/init.c
vendored
@@ -168,6 +168,10 @@ void _glfwInputError(int code, const char* format, ...)
|
|||||||
strcpy(description, "The requested format is unavailable");
|
strcpy(description, "The requested format is unavailable");
|
||||||
else if (code == GLFW_NO_WINDOW_CONTEXT)
|
else if (code == GLFW_NO_WINDOW_CONTEXT)
|
||||||
strcpy(description, "The specified window has no context");
|
strcpy(description, "The specified window has no context");
|
||||||
|
else if (code == GLFW_FEATURE_UNAVAILABLE)
|
||||||
|
strcpy(description, "The requested feature cannot be implemented for this platform");
|
||||||
|
else if (code == GLFW_FEATURE_UNIMPLEMENTED)
|
||||||
|
strcpy(description, "The requested feature has not yet been implemented for this platform");
|
||||||
else
|
else
|
||||||
strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
|
strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
|
||||||
}
|
}
|
||||||
@@ -363,3 +367,10 @@ GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval,
|
|||||||
GLFWAPI void glfwRemoveTimer(unsigned long long timer_id) {
|
GLFWAPI void glfwRemoveTimer(unsigned long long timer_id) {
|
||||||
_glfwPlatformRemoveTimer(timer_id);
|
_glfwPlatformRemoveTimer(timer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun cbfun)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(_glfw.callbacks.application_close, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|||||||
42
glfw/input.c
vendored
42
glfw/input.c
vendored
@@ -300,10 +300,10 @@ void _glfwInputKeyboard(_GLFWwindow* window, GLFWkeyevent* ev)
|
|||||||
|
|
||||||
// Notifies shared code of a scroll event
|
// Notifies shared code of a scroll event
|
||||||
//
|
//
|
||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags)
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags, int mods)
|
||||||
{
|
{
|
||||||
if (window->callbacks.scroll)
|
if (window->callbacks.scroll)
|
||||||
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset, flags);
|
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset, flags, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notifies shared code of a mouse button click event
|
// Notifies shared code of a mouse button click event
|
||||||
@@ -675,6 +675,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
|||||||
return window->stickyMouseButtons;
|
return window->stickyMouseButtons;
|
||||||
case GLFW_LOCK_KEY_MODS:
|
case GLFW_LOCK_KEY_MODS:
|
||||||
return window->lockKeyMods;
|
return window->lockKeyMods;
|
||||||
|
case GLFW_RAW_MOUSE_MOTION:
|
||||||
|
return window->rawMouseMotion;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||||
@@ -754,10 +756,32 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
{
|
{
|
||||||
window->lockKeyMods = value ? true : false;
|
window->lockKeyMods = value ? true : false;
|
||||||
}
|
}
|
||||||
|
else if (mode == GLFW_RAW_MOUSE_MOTION)
|
||||||
|
{
|
||||||
|
if (!_glfwPlatformRawMouseMotionSupported())
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Raw mouse motion is not supported on this system");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value ? true : false;
|
||||||
|
if (window->rawMouseMotion == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window->rawMouseMotion = value;
|
||||||
|
_glfwPlatformSetRawMouseMotion(window, value);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwRawMouseMotionSupported(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
return _glfwPlatformRawMouseMotionSupported();
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetKeyName(int key, int native_key)
|
GLFWAPI const char* glfwGetKeyName(int key, int native_key)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
@@ -1412,8 +1436,18 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
|||||||
if (e->type == _GLFW_JOYSTICK_AXIS)
|
if (e->type == _GLFW_JOYSTICK_AXIS)
|
||||||
{
|
{
|
||||||
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
|
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
|
||||||
if (value > 0.f)
|
// HACK: This should be baked into the value transform
|
||||||
state->buttons[i] = GLFW_PRESS;
|
// TODO: Bake into transform when implementing output modifiers
|
||||||
|
if (e->axisOffset < 0 || (e->axisOffset == 0 && e->axisScale > 0))
|
||||||
|
{
|
||||||
|
if (value >= 0.f)
|
||||||
|
state->buttons[i] = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value <= 0.f)
|
||||||
|
state->buttons[i] = GLFW_PRESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (e->type == _GLFW_JOYSTICK_HATBIT)
|
else if (e->type == _GLFW_JOYSTICK_HATBIT)
|
||||||
{
|
{
|
||||||
|
|||||||
10
glfw/internal.h
vendored
10
glfw/internal.h
vendored
@@ -429,6 +429,7 @@ struct _GLFWwindow
|
|||||||
char keys[GLFW_KEY_LAST + 1];
|
char keys[GLFW_KEY_LAST + 1];
|
||||||
// Virtual cursor position when cursor is disabled
|
// Virtual cursor position when cursor is disabled
|
||||||
double virtualCursorPosX, virtualCursorPosY;
|
double virtualCursorPosX, virtualCursorPosY;
|
||||||
|
bool rawMouseMotion;
|
||||||
|
|
||||||
_GLFWcontext context;
|
_GLFWcontext context;
|
||||||
|
|
||||||
@@ -601,8 +602,10 @@ struct _GLFWlibrary
|
|||||||
struct {
|
struct {
|
||||||
GLFWmonitorfun monitor;
|
GLFWmonitorfun monitor;
|
||||||
GLFWjoystickfun joystick;
|
GLFWjoystickfun joystick;
|
||||||
|
GLFWapplicationclosefun application_close;
|
||||||
} callbacks;
|
} callbacks;
|
||||||
|
|
||||||
|
|
||||||
// This is defined in the window API's platform.h
|
// This is defined in the window API's platform.h
|
||||||
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
||||||
// This is defined in the context API's context.h
|
// This is defined in the context API's context.h
|
||||||
@@ -631,6 +634,8 @@ const char* _glfwPlatformGetVersionString(void);
|
|||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
|
||||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
||||||
|
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, bool enabled);
|
||||||
|
bool _glfwPlatformRawMouseMotionSupported(void);
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
const GLFWimage* image, int xhot, int yhot, int count);
|
const GLFWimage* image, int xhot, int yhot, int count);
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape);
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape);
|
||||||
@@ -755,7 +760,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
|||||||
|
|
||||||
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods);
|
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods);
|
||||||
void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev);
|
void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev);
|
||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags);
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags, int mods);
|
||||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, bool entered);
|
void _glfwInputCursorEnter(_GLFWwindow* window, bool entered);
|
||||||
@@ -789,9 +794,6 @@ void _glfwDebug(const char* format, ...);
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool _glfwStringInExtensionString(const char* string, const char* extensions);
|
bool _glfwStringInExtensionString(const char* string, const char* extensions);
|
||||||
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
|
||||||
const _GLFWfbconfig* alternatives,
|
|
||||||
unsigned int count);
|
|
||||||
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig);
|
const _GLFWctxconfig* ctxconfig);
|
||||||
bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
||||||
|
|||||||
5
glfw/null_init.c
vendored
5
glfw/null_init.c
vendored
@@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
@@ -36,11 +38,14 @@
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
|
_glfwPollMonitorsNull();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
|
free(_glfw.null.clipboardString);
|
||||||
_glfwTerminateOSMesa();
|
_glfwTerminateOSMesa();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
96
glfw/null_monitor.c
vendored
96
glfw/null_monitor.c
vendored
@@ -29,13 +29,45 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// The the sole (fake) video mode of our (sole) fake monitor
|
||||||
|
//
|
||||||
|
static GLFWvidmode getVideoMode(void)
|
||||||
|
{
|
||||||
|
GLFWvidmode mode;
|
||||||
|
mode.width = 1920;
|
||||||
|
mode.height = 1080;
|
||||||
|
mode.redBits = 8;
|
||||||
|
mode.greenBits = 8;
|
||||||
|
mode.blueBits = 8;
|
||||||
|
mode.refreshRate = 60;
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwPollMonitorsNull(void)
|
||||||
|
{
|
||||||
|
const float dpi = 141.f;
|
||||||
|
const GLFWvidmode mode = getVideoMode();
|
||||||
|
_GLFWmonitor* monitor = _glfwAllocMonitor("Null SuperNoop 0",
|
||||||
|
(int) (mode.width * 25.4f / dpi),
|
||||||
|
(int) (mode.height * 25.4f / dpi));
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor UNUSED)
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
|
_glfwFreeGammaArrays(&monitor->null.ramp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
||||||
@@ -52,26 +84,72 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor UNUSED,
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor UNUSED,
|
||||||
int* xpos UNUSED, int* ypos UNUSED,
|
int* xpos, int* ypos,
|
||||||
int* width UNUSED, int* height UNUSED)
|
int* width, int* height)
|
||||||
{
|
{
|
||||||
|
const GLFWvidmode mode = getVideoMode();
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = 10;
|
||||||
|
if (ypos)
|
||||||
|
ypos = 0;
|
||||||
|
if (width)
|
||||||
|
*width = mode.width;
|
||||||
|
if (height)
|
||||||
|
*height = mode.height - 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor UNUSED, int* found UNUSED)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor UNUSED, int* found)
|
||||||
{
|
{
|
||||||
return NULL;
|
GLFWvidmode* mode = calloc(1, sizeof(GLFWvidmode));
|
||||||
|
*mode = getVideoMode();
|
||||||
|
*found = 1;
|
||||||
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor UNUSED, GLFWvidmode* mode UNUSED)
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor UNUSED, GLFWvidmode* mode)
|
||||||
{
|
{
|
||||||
|
*mode = getVideoMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp UNUSED)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
return false;
|
if (!monitor->null.ramp.size)
|
||||||
|
{
|
||||||
|
_glfwAllocGammaArrays(&monitor->null.ramp, 256);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < monitor->null.ramp.size; i++)
|
||||||
|
{
|
||||||
|
const float gamma = 2.2f;
|
||||||
|
float value;
|
||||||
|
value = i / (float) (monitor->null.ramp.size - 1);
|
||||||
|
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
||||||
|
value = _glfw_fminf(value, 65535.f);
|
||||||
|
|
||||||
|
monitor->null.ramp.red[i] = (unsigned short) value;
|
||||||
|
monitor->null.ramp.green[i] = (unsigned short) value;
|
||||||
|
monitor->null.ramp.blue[i] = (unsigned short) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwAllocGammaArrays(ramp, monitor->null.ramp.size);
|
||||||
|
memcpy(ramp->red, monitor->null.ramp.red, sizeof(short) * ramp->size);
|
||||||
|
memcpy(ramp->green, monitor->null.ramp.green, sizeof(short) * ramp->size);
|
||||||
|
memcpy(ramp->blue, monitor->null.ramp.blue, sizeof(short) * ramp->size);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED, const GLFWgammaramp* ramp UNUSED)
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
|
if (monitor->null.ramp.size != ramp->size)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Null: Gamma ramp size must match current ramp size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(monitor->null.ramp.red, ramp->red, sizeof(short) * ramp->size);
|
||||||
|
memcpy(monitor->null.ramp.green, ramp->green, sizeof(short) * ramp->size);
|
||||||
|
memcpy(monitor->null.ramp.blue, ramp->blue, sizeof(short) * ramp->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
39
glfw/null_platform.h
vendored
39
glfw/null_platform.h
vendored
@@ -27,12 +27,12 @@
|
|||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNull null
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNull null
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE
|
#define _GLFW_PLATFORM_CONTEXT_STATE
|
||||||
#define _GLFW_PLATFORM_MONITOR_STATE
|
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE
|
#define _GLFW_PLATFORM_CURSOR_STATE
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||||
#define _GLFW_EGL_CONTEXT_STATE
|
#define _GLFW_EGL_CONTEXT_STATE
|
||||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||||
@@ -56,7 +56,36 @@
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWwindowNull
|
typedef struct _GLFWwindowNull
|
||||||
{
|
{
|
||||||
int width;
|
int xpos;
|
||||||
int height;
|
int ypos;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
char* title;
|
||||||
|
bool visible;
|
||||||
|
bool iconified;
|
||||||
|
bool maximized;
|
||||||
|
bool resizable;
|
||||||
|
bool decorated;
|
||||||
|
bool floating;
|
||||||
|
bool transparent;
|
||||||
|
float opacity;
|
||||||
} _GLFWwindowNull;
|
} _GLFWwindowNull;
|
||||||
|
|
||||||
|
// Null-specific per-monitor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmonitorNull
|
||||||
|
{
|
||||||
|
GLFWgammaramp ramp;
|
||||||
|
} _GLFWmonitorNull;
|
||||||
|
|
||||||
|
// Null-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryNull
|
||||||
|
{
|
||||||
|
int xcursor;
|
||||||
|
int ycursor;
|
||||||
|
char* clipboardString;
|
||||||
|
_GLFWwindow* focusedWindow;
|
||||||
|
} _GLFWlibraryNull;
|
||||||
|
|
||||||
|
void _glfwPollMonitorsNull(void);
|
||||||
|
|||||||
496
glfw/null_window.c
vendored
496
glfw/null_window.c
vendored
@@ -30,12 +30,71 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "../kitty/monotonic.h"
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static void applySizeLimits(_GLFWwindow* window, int* width, int* height)
|
||||||
|
{
|
||||||
|
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
const float ratio = (float) window->numer / (float) window->denom;
|
||||||
|
*height = (int) (*width / ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->minwidth != GLFW_DONT_CARE && *width < window->minwidth)
|
||||||
|
*width = window->minwidth;
|
||||||
|
else if (window->maxwidth != GLFW_DONT_CARE && *width > window->maxwidth)
|
||||||
|
*width = window->maxwidth;
|
||||||
|
|
||||||
|
if (window->minheight != GLFW_DONT_CARE && *height < window->minheight)
|
||||||
|
*height = window->minheight;
|
||||||
|
else if (window->maxheight != GLFW_DONT_CARE && *height > window->maxheight)
|
||||||
|
*height = window->maxheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fitToMonitor(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
GLFWvidmode mode;
|
||||||
|
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||||
|
_glfwPlatformGetMonitorPos(window->monitor,
|
||||||
|
&window->null.xpos,
|
||||||
|
&window->null.ypos);
|
||||||
|
window->null.width = mode.width;
|
||||||
|
window->null.height = mode.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void acquireMonitor(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
_glfwInputMonitorWindow(window->monitor, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void releaseMonitor(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->monitor->window != window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int createNativeWindow(_GLFWwindow* window,
|
static int createNativeWindow(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig)
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
window->null.width = wndconfig->width;
|
if (window->monitor)
|
||||||
window->null.height = wndconfig->height;
|
fitToMonitor(window);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->null.xpos = 17;
|
||||||
|
window->null.ypos = 17;
|
||||||
|
window->null.width = wndconfig->width;
|
||||||
|
window->null.height = wndconfig->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->null.visible = wndconfig->visible;
|
||||||
|
window->null.decorated = wndconfig->decorated;
|
||||||
|
window->null.maximized = wndconfig->maximized;
|
||||||
|
window->null.floating = wndconfig->floating;
|
||||||
|
window->null.transparent = fbconfig->transparent;
|
||||||
|
window->null.opacity = 1.f;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -50,7 +109,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
if (!createNativeWindow(window, wndconfig))
|
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
@@ -70,11 +129,24 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
{
|
||||||
|
_glfwPlatformShowWindow(window);
|
||||||
|
_glfwPlatformFocusWindow(window);
|
||||||
|
acquireMonitor(window);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
if (window->monitor)
|
||||||
|
releaseMonitor(window);
|
||||||
|
|
||||||
|
if (_glfw.null.focusedWindow == window)
|
||||||
|
_glfw.null.focusedWindow = NULL;
|
||||||
|
|
||||||
if (window->context.destroy)
|
if (window->context.destroy)
|
||||||
window->context.destroy(window);
|
window->context.destroy(window);
|
||||||
}
|
}
|
||||||
@@ -88,20 +160,60 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED, int count UNUSED,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window UNUSED,
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||||
_GLFWmonitor* monitor UNUSED,
|
_GLFWmonitor* monitor,
|
||||||
int xpos UNUSED, int ypos UNUSED,
|
int xpos, int ypos,
|
||||||
int width UNUSED, int height UNUSED,
|
int width, int height,
|
||||||
int refreshRate UNUSED)
|
int refreshRate UNUSED)
|
||||||
{
|
{
|
||||||
|
if (window->monitor == monitor)
|
||||||
|
{
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
_glfwPlatformSetWindowPos(window, xpos, ypos);
|
||||||
|
_glfwPlatformSetWindowSize(window, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
releaseMonitor(window);
|
||||||
|
|
||||||
|
_glfwInputWindowMonitor(window, monitor);
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
{
|
||||||
|
window->null.visible = true;
|
||||||
|
acquireMonitor(window);
|
||||||
|
fitToMonitor(window);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwPlatformSetWindowPos(window, xpos, ypos);
|
||||||
|
_glfwPlatformSetWindowSize(window, width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
{
|
{
|
||||||
|
if (xpos)
|
||||||
|
*xpos = window->null.xpos;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = window->null.ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int ypos UNUSED)
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||||
{
|
{
|
||||||
|
if (window->monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (window->null.xpos != xpos || window->null.ypos != ypos)
|
||||||
|
{
|
||||||
|
window->null.xpos = xpos;
|
||||||
|
window->null.ypos = ypos;
|
||||||
|
_glfwInputWindowPos(window, xpos, ypos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||||
@@ -114,18 +226,34 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
{
|
{
|
||||||
window->null.width = width;
|
if (window->monitor)
|
||||||
window->null.height = height;
|
return;
|
||||||
|
|
||||||
|
if (window->null.width != width || window->null.height != height)
|
||||||
|
{
|
||||||
|
window->null.width = width;
|
||||||
|
window->null.height = height;
|
||||||
|
_glfwInputWindowSize(window, width, height);
|
||||||
|
_glfwInputFramebufferSize(window, width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window UNUSED,
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||||
int minwidth UNUSED, int minheight UNUSED,
|
int minwidth UNUSED, int minheight UNUSED,
|
||||||
int maxwidth UNUSED, int maxheight UNUSED)
|
int maxwidth UNUSED, int maxheight UNUSED)
|
||||||
{
|
{
|
||||||
|
int width = window->null.width;
|
||||||
|
int height = window->null.height;
|
||||||
|
applySizeLimits(window, &width, &height);
|
||||||
|
_glfwPlatformSetWindowSize(window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window UNUSED, int n UNUSED, int d UNUSED)
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n UNUSED, int d UNUSED)
|
||||||
{
|
{
|
||||||
|
int width = window->null.width;
|
||||||
|
int height = window->null.height;
|
||||||
|
applySizeLimits(window, &width, &height);
|
||||||
|
_glfwPlatformSetWindowSize(window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED, int widthincr UNUSED, int heightincr UNUSED)
|
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED, int widthincr UNUSED, int heightincr UNUSED)
|
||||||
@@ -140,10 +268,17 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
|
|||||||
*height = window->null.height;
|
*height = window->null.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window UNUSED,
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
int* left UNUSED, int* top UNUSED,
|
int* left, int* top,
|
||||||
int* right UNUSED, int* bottom UNUSED)
|
int* right, int* bottom)
|
||||||
{
|
{
|
||||||
|
if (window->null.decorated && !window->monitor)
|
||||||
|
{
|
||||||
|
*left = 1;
|
||||||
|
*top = 10;
|
||||||
|
*right = 1;
|
||||||
|
*bottom = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
|
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
|
||||||
@@ -160,59 +295,107 @@ monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
|
|||||||
return ms_to_monotonic_t(500ll);
|
return ms_to_monotonic_t(500ll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window UNUSED)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (_glfw.null.focusedWindow == window)
|
||||||
|
{
|
||||||
|
_glfw.null.focusedWindow = NULL;
|
||||||
|
_glfwInputWindowFocus(window, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window->null.iconified)
|
||||||
|
{
|
||||||
|
window->null.iconified = true;
|
||||||
|
_glfwInputWindowIconify(window, true);
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
releaseMonitor(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->null.iconified)
|
||||||
|
{
|
||||||
|
window->null.iconified = false;
|
||||||
|
_glfwInputWindowIconify(window, false);
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
acquireMonitor(window);
|
||||||
|
}
|
||||||
|
else if (window->null.maximized)
|
||||||
|
{
|
||||||
|
window->null.maximized = false;
|
||||||
|
_glfwInputWindowMaximize(window, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (!window->null.maximized)
|
||||||
|
{
|
||||||
|
window->null.maximized = true;
|
||||||
|
_glfwInputWindowMaximize(window, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return window->null.maximized;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return _glfw.null.xcursor >= window->null.xpos &&
|
||||||
|
_glfw.null.ycursor >= window->null.ypos &&
|
||||||
|
_glfw.null.xcursor <= window->null.xpos + window->null.width - 1 &&
|
||||||
|
_glfw.null.ycursor <= window->null.ypos + window->null.height - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return window->null.transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
|
||||||
|
{
|
||||||
|
window->null.resizable = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
||||||
|
{
|
||||||
|
window->null.decorated = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
||||||
|
{
|
||||||
|
window->null.floating = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return window->null.opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||||
|
{
|
||||||
|
window->null.opacity = opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window UNUSED)
|
bool _glfwPlatformRawMouseMotionSupported(void)
|
||||||
{
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window UNUSED)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
window->null.visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window UNUSED)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _glfwPlatformWindowHovered(_GLFWwindow* window UNUSED)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window UNUSED)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
|
|
||||||
{
|
|
||||||
return 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window UNUSED, float opacity UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -222,21 +405,41 @@ int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window UNUSED)
|
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
if (_glfw.null.focusedWindow == window)
|
||||||
|
{
|
||||||
|
_glfw.null.focusedWindow = NULL;
|
||||||
|
_glfwInputWindowFocus(window, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
window->null.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window UNUSED)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
if (_glfw.null.focusedWindow == window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!window->null.visible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_GLFWwindow* previous = _glfw.null.focusedWindow;
|
||||||
|
_glfw.null.focusedWindow = window;
|
||||||
|
|
||||||
|
if (previous)
|
||||||
|
{
|
||||||
|
_glfwInputWindowFocus(previous, false);
|
||||||
|
if (previous->monitor && previous->autoIconify)
|
||||||
|
_glfwPlatformIconifyWindow(previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputWindowFocus(window, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
|
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
}
|
return _glfw.null.focusedWindow == window;
|
||||||
|
|
||||||
int _glfwPlatformWindowFocused(_GLFWwindow* window UNUSED)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
|
int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
|
||||||
@@ -244,14 +447,14 @@ int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window UNUSED)
|
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return false;
|
return window->null.iconified;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowVisible(_GLFWwindow* window UNUSED)
|
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return false;
|
return window->null.visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
@@ -270,12 +473,18 @@ void _glfwPlatformPostEmptyEvent(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window UNUSED, double* xpos UNUSED, double* ypos UNUSED)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
{
|
{
|
||||||
|
if (xpos)
|
||||||
|
*xpos = _glfw.null.xcursor - window->null.xpos;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = _glfw.null.ycursor - window->null.ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window UNUSED, double x UNUSED, double y UNUSED)
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||||
{
|
{
|
||||||
|
_glfw.null.xcursor = window->null.xpos + (int) x;
|
||||||
|
_glfw.null.ycursor = window->null.ypos + (int) y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window UNUSED, int mode UNUSED)
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window UNUSED, int mode UNUSED)
|
||||||
@@ -302,23 +511,142 @@ void _glfwPlatformSetCursor(_GLFWwindow* window UNUSED, _GLFWcursor* cursor UNUS
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetClipboardString(const char* string UNUSED)
|
void _glfwPlatformSetClipboardString(const char* string)
|
||||||
{
|
{
|
||||||
|
char* copy = _glfw_strdup(string);
|
||||||
|
free(_glfw.null.clipboardString);
|
||||||
|
_glfw.null.clipboardString = copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetClipboardString(void)
|
const char* _glfwPlatformGetClipboardString(void)
|
||||||
{
|
{
|
||||||
|
return _glfw.null.clipboardString;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetNativeKeyName(int native_key)
|
||||||
|
{
|
||||||
|
switch (scancode)
|
||||||
|
{
|
||||||
|
case GLFW_KEY_APOSTROPHE:
|
||||||
|
return "'";
|
||||||
|
case GLFW_KEY_COMMA:
|
||||||
|
return ",";
|
||||||
|
case GLFW_KEY_MINUS:
|
||||||
|
case GLFW_KEY_KP_SUBTRACT:
|
||||||
|
return "-";
|
||||||
|
case GLFW_KEY_PERIOD:
|
||||||
|
case GLFW_KEY_KP_DECIMAL:
|
||||||
|
return ".";
|
||||||
|
case GLFW_KEY_SLASH:
|
||||||
|
case GLFW_KEY_KP_DIVIDE:
|
||||||
|
return "/";
|
||||||
|
case GLFW_KEY_SEMICOLON:
|
||||||
|
return ";";
|
||||||
|
case GLFW_KEY_EQUAL:
|
||||||
|
case GLFW_KEY_KP_EQUAL:
|
||||||
|
return "=";
|
||||||
|
case GLFW_KEY_LEFT_BRACKET:
|
||||||
|
return "[";
|
||||||
|
case GLFW_KEY_RIGHT_BRACKET:
|
||||||
|
return "]";
|
||||||
|
case GLFW_KEY_KP_MULTIPLY:
|
||||||
|
return "*";
|
||||||
|
case GLFW_KEY_KP_ADD:
|
||||||
|
return "+";
|
||||||
|
case GLFW_KEY_BACKSLASH:
|
||||||
|
case GLFW_KEY_WORLD_1:
|
||||||
|
case GLFW_KEY_WORLD_2:
|
||||||
|
return "\\";
|
||||||
|
case GLFW_KEY_0:
|
||||||
|
case GLFW_KEY_KP_0:
|
||||||
|
return "0";
|
||||||
|
case GLFW_KEY_1:
|
||||||
|
case GLFW_KEY_KP_1:
|
||||||
|
return "1";
|
||||||
|
case GLFW_KEY_2:
|
||||||
|
case GLFW_KEY_KP_2:
|
||||||
|
return "2";
|
||||||
|
case GLFW_KEY_3:
|
||||||
|
case GLFW_KEY_KP_3:
|
||||||
|
return "3";
|
||||||
|
case GLFW_KEY_4:
|
||||||
|
case GLFW_KEY_KP_4:
|
||||||
|
return "4";
|
||||||
|
case GLFW_KEY_5:
|
||||||
|
case GLFW_KEY_KP_5:
|
||||||
|
return "5";
|
||||||
|
case GLFW_KEY_6:
|
||||||
|
case GLFW_KEY_KP_6:
|
||||||
|
return "6";
|
||||||
|
case GLFW_KEY_7:
|
||||||
|
case GLFW_KEY_KP_7:
|
||||||
|
return "7";
|
||||||
|
case GLFW_KEY_8:
|
||||||
|
case GLFW_KEY_KP_8:
|
||||||
|
return "8";
|
||||||
|
case GLFW_KEY_9:
|
||||||
|
case GLFW_KEY_KP_9:
|
||||||
|
return "9";
|
||||||
|
case GLFW_KEY_A:
|
||||||
|
return "a";
|
||||||
|
case GLFW_KEY_B:
|
||||||
|
return "b";
|
||||||
|
case GLFW_KEY_C:
|
||||||
|
return "c";
|
||||||
|
case GLFW_KEY_D:
|
||||||
|
return "d";
|
||||||
|
case GLFW_KEY_E:
|
||||||
|
return "e";
|
||||||
|
case GLFW_KEY_F:
|
||||||
|
return "f";
|
||||||
|
case GLFW_KEY_G:
|
||||||
|
return "g";
|
||||||
|
case GLFW_KEY_H:
|
||||||
|
return "h";
|
||||||
|
case GLFW_KEY_I:
|
||||||
|
return "i";
|
||||||
|
case GLFW_KEY_J:
|
||||||
|
return "j";
|
||||||
|
case GLFW_KEY_K:
|
||||||
|
return "k";
|
||||||
|
case GLFW_KEY_L:
|
||||||
|
return "l";
|
||||||
|
case GLFW_KEY_M:
|
||||||
|
return "m";
|
||||||
|
case GLFW_KEY_N:
|
||||||
|
return "n";
|
||||||
|
case GLFW_KEY_O:
|
||||||
|
return "o";
|
||||||
|
case GLFW_KEY_P:
|
||||||
|
return "p";
|
||||||
|
case GLFW_KEY_Q:
|
||||||
|
return "q";
|
||||||
|
case GLFW_KEY_R:
|
||||||
|
return "r";
|
||||||
|
case GLFW_KEY_S:
|
||||||
|
return "s";
|
||||||
|
case GLFW_KEY_T:
|
||||||
|
return "t";
|
||||||
|
case GLFW_KEY_U:
|
||||||
|
return "u";
|
||||||
|
case GLFW_KEY_V:
|
||||||
|
return "v";
|
||||||
|
case GLFW_KEY_W:
|
||||||
|
return "w";
|
||||||
|
case GLFW_KEY_X:
|
||||||
|
return "x";
|
||||||
|
case GLFW_KEY_Y:
|
||||||
|
return "y";
|
||||||
|
case GLFW_KEY_Z:
|
||||||
|
return "z";
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetNativeKeyName(int native_key UNUSED)
|
int _glfwPlatformGetNativeKeyForKey(int key)
|
||||||
{
|
{
|
||||||
return "";
|
return key;
|
||||||
}
|
|
||||||
|
|
||||||
int _glfwPlatformGetNativeKeyForKey(int key UNUSED)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions UNUSED)
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions UNUSED)
|
||||||
@@ -338,6 +666,6 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance UNUSED,
|
|||||||
VkSurfaceKHR* surface UNUSED)
|
VkSurfaceKHR* surface UNUSED)
|
||||||
{
|
{
|
||||||
// This seems like the most appropriate error to return here
|
// This seems like the most appropriate error to return here
|
||||||
return VK_ERROR_INITIALIZATION_FAILED;
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
"headers": [
|
"headers": [
|
||||||
"wl_platform.h",
|
"wl_platform.h",
|
||||||
"posix_thread.h",
|
"posix_thread.h",
|
||||||
|
"wl_cursors.h",
|
||||||
"xkb_glfw.h",
|
"xkb_glfw.h",
|
||||||
"dbus_glfw.h",
|
"dbus_glfw.h",
|
||||||
"ibus_glfw.h",
|
"ibus_glfw.h",
|
||||||
@@ -78,6 +79,7 @@
|
|||||||
"wl_init.c",
|
"wl_init.c",
|
||||||
"wl_monitor.c",
|
"wl_monitor.c",
|
||||||
"wl_window.c",
|
"wl_window.c",
|
||||||
|
"wl_cursors.c",
|
||||||
"posix_thread.c",
|
"posix_thread.c",
|
||||||
"xkb_glfw.c",
|
"xkb_glfw.c",
|
||||||
"dbus_glfw.c",
|
"dbus_glfw.c",
|
||||||
|
|||||||
164
glfw/wl_cursors.c
vendored
Normal file
164
glfw/wl_cursors.c
vendored
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
// Future devs supporting whatever Wayland protocol stabilizes for cursor selection: see _themeAdd.
|
||||||
|
|
||||||
|
#include "wl_cursors.h"
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wl_cursor_theme *theme;
|
||||||
|
int px;
|
||||||
|
int refcount;
|
||||||
|
} _themeData;
|
||||||
|
|
||||||
|
struct _wlCursorThemeManager {
|
||||||
|
size_t count;
|
||||||
|
/** Pointer to the head of an unsorted array of themes with no sentinel.
|
||||||
|
*
|
||||||
|
* The lack of sort (and thus forcing a linear search) is intentional;
|
||||||
|
* in most cases, users are likely to have 1-2 different cursor sizes loaded.
|
||||||
|
* For those cases, we get no benefit from sorting and added constant overheads.
|
||||||
|
*
|
||||||
|
* Don't change this to a flexible array member because that complicates growing/shrinking.
|
||||||
|
*/
|
||||||
|
_themeData *themes;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_themeInit(_themeData *dest, const char *name, int px) {
|
||||||
|
dest->px = px;
|
||||||
|
dest->refcount = 1;
|
||||||
|
if (_glfw.wl.shm) {
|
||||||
|
dest->theme = wl_cursor_theme_load(name, px, _glfw.wl.shm);
|
||||||
|
if(!dest->theme) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Unable to load cursor theme");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dest->theme = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wl_cursor_theme*
|
||||||
|
_themeAdd(int px, _wlCursorThemeManager *manager) {
|
||||||
|
++manager->count;
|
||||||
|
_themeData *temp = realloc(manager->themes, sizeof(_themeData)*manager->count);
|
||||||
|
if (!temp) {
|
||||||
|
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
||||||
|
"OOM during cursor theme management.");
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
manager->themes = temp;
|
||||||
|
_themeInit(manager->themes + manager->count-1,
|
||||||
|
getenv("XCURSOR_THEME"),
|
||||||
|
px);
|
||||||
|
return manager->themes[manager->count-1].theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//WARNING: No input safety checks.
|
||||||
|
static inline void _themeInc(_themeData
|
||||||
|
*theme) {
|
||||||
|
++(theme->refcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WARNING: No input safety checks.
|
||||||
|
// In particular, doesn't check if theme is actually managed by the manager.
|
||||||
|
static void
|
||||||
|
_themeDec(_themeData *theme, _wlCursorThemeManager *manager) {
|
||||||
|
if (--(theme->refcount) == 0) {
|
||||||
|
wl_cursor_theme_destroy(theme->theme);
|
||||||
|
if (--(manager->count) > 0) {
|
||||||
|
const _themeData *last_theme = (manager->themes)+(manager->count);
|
||||||
|
*theme = *last_theme;
|
||||||
|
_themeData *temp = realloc(manager->themes, (manager->count)*sizeof(_themeData));
|
||||||
|
// We're shrinking here, so it's not catastrophic if realloc fails.
|
||||||
|
if (temp) manager->themes = temp;
|
||||||
|
} else {
|
||||||
|
free(manager->themes);
|
||||||
|
manager->themes = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static _wlCursorThemeManager _default = {0};
|
||||||
|
|
||||||
|
_wlCursorThemeManager*
|
||||||
|
_wlCursorThemeManagerDefault() {
|
||||||
|
return &_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_wlCursorThemeManagerDestroy(_wlCursorThemeManager *manager) {
|
||||||
|
if (manager) {
|
||||||
|
for (size_t i = 0; i < manager->count; ++i) {
|
||||||
|
wl_cursor_theme_destroy(manager->themes[i].theme);
|
||||||
|
}
|
||||||
|
free(manager->themes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wl_cursor_theme*
|
||||||
|
_wlCursorThemeManagerGet(_wlCursorThemeManager *manager, int px) {
|
||||||
|
_themeData *themedata = NULL;
|
||||||
|
for (size_t i = 0; i < manager->count; ++i) {
|
||||||
|
_themeData *temp = manager->themes+i;
|
||||||
|
if (temp->px == px) {
|
||||||
|
themedata = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (themedata != NULL) {
|
||||||
|
_themeInc(themedata);
|
||||||
|
return themedata->theme;
|
||||||
|
}
|
||||||
|
return _themeAdd(px, manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_cursor_theme*
|
||||||
|
_wlCursorThemeManage(_wlCursorThemeManager *manager, struct wl_cursor_theme *theme, int px) {
|
||||||
|
//WARNING: Multiple returns.
|
||||||
|
if (manager == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (theme != NULL) {
|
||||||
|
// Search for the provided theme in the manager.
|
||||||
|
_themeData *themedata = NULL;
|
||||||
|
for (size_t i = 0; i < manager->count; ++i) {
|
||||||
|
_themeData *temp = manager->themes+i;
|
||||||
|
if (temp->theme == theme) {
|
||||||
|
themedata = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (themedata != NULL) {
|
||||||
|
// Search succeeded. Check if we can avoid unnecessary operations.
|
||||||
|
if (themedata->px == px) return theme;
|
||||||
|
_themeDec(themedata, manager);
|
||||||
|
} else {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland internal: managed theme isn't in the provided manager");
|
||||||
|
return theme;
|
||||||
|
//^ This is probably the sanest behavior for this situation: do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return px > 0 ? _wlCursorThemeManagerGet(manager, px) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_wlCursorPxFromScale(int scale) {
|
||||||
|
const char *envStr = getenv("XCURSOR_SIZE");
|
||||||
|
if(envStr != NULL) {
|
||||||
|
const int retval = atoi(envStr);
|
||||||
|
//^ atoi here is fine since 0 is an invalid value.
|
||||||
|
if(retval > 0 && retval <= INT_MAX/scale) {
|
||||||
|
return retval*scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 32*scale;
|
||||||
|
}
|
||||||
30
glfw/wl_cursors.h
vendored
Normal file
30
glfw/wl_cursors.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Declarations for a HiDPI-aware cursor theme manager.
|
||||||
|
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
|
typedef struct _wlCursorThemeManager _wlCursorThemeManager;
|
||||||
|
|
||||||
|
/** Returns a pointer to a wlCursorThemeManagerInstance.
|
||||||
|
* Repeatedly calling this function will return the same instance.
|
||||||
|
*
|
||||||
|
* The retrieved instance must be destroyed with _wlCursorThemeManagerDestroy.
|
||||||
|
*/
|
||||||
|
_wlCursorThemeManager* _wlCursorThemeManagerDefault(void);
|
||||||
|
|
||||||
|
/** Set a wl_cursor_theme pointer variable to a pointer to a managed cursor theme.
|
||||||
|
* Pass the desired px as the third argument.
|
||||||
|
* Returns a pointer to a managed theme, or NULL if the desired px is 0 or an error occurs.
|
||||||
|
*
|
||||||
|
* The passed theme pointer must either be NULL or a pointer to a theme managed by the passed manager.
|
||||||
|
* The provided pointer may be invalidated if it's non-NULL.
|
||||||
|
*/
|
||||||
|
struct wl_cursor_theme*
|
||||||
|
_wlCursorThemeManage(_wlCursorThemeManager*, struct wl_cursor_theme*, int);
|
||||||
|
|
||||||
|
void _wlCursorThemeManagerDestroy(_wlCursorThemeManager*);
|
||||||
|
|
||||||
|
/** Helper method to determine the appropriate size in pixels for a given scale.
|
||||||
|
*
|
||||||
|
* Reads XCURSOR_SIZE if it's set and is valid, else defaults to 32*scale.
|
||||||
|
*/
|
||||||
|
int _wlCursorPxFromScale(int);
|
||||||
69
glfw/wl_init.c
vendored
69
glfw/wl_init.c
vendored
@@ -113,7 +113,7 @@ static void pointerHandleEnter(void* data UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
window->wl.decorations.focus = focus;
|
window->wl.decorations.focus = focus;
|
||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.pointerFocus = window;
|
_glfw.wl.pointerFocus = window;
|
||||||
|
|
||||||
window->wl.hovered = true;
|
window->wl.hovered = true;
|
||||||
@@ -134,20 +134,26 @@ static void pointerHandleLeave(void* data UNUSED,
|
|||||||
|
|
||||||
window->wl.hovered = false;
|
window->wl.hovered = false;
|
||||||
|
|
||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
_glfwInputCursorEnter(window, false);
|
_glfwInputCursorEnter(window, false);
|
||||||
_glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
|
_glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setCursor(GLFWCursorShape shape)
|
static void setCursor(GLFWCursorShape shape, _GLFWwindow* window)
|
||||||
{
|
{
|
||||||
struct wl_buffer* buffer;
|
struct wl_buffer* buffer;
|
||||||
struct wl_cursor* cursor;
|
struct wl_cursor* cursor;
|
||||||
struct wl_cursor_image* image;
|
struct wl_cursor_image* image;
|
||||||
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
||||||
|
const int scale = window->wl.scale;
|
||||||
|
|
||||||
cursor = _glfwLoadCursor(shape);
|
window->wl.cursorTheme = _wlCursorThemeManage(
|
||||||
|
_glfw.wl.cursorThemeManager,
|
||||||
|
window->wl.cursorTheme,
|
||||||
|
_wlCursorPxFromScale(scale)
|
||||||
|
);
|
||||||
|
cursor = _glfwLoadCursor(shape, window->wl.cursorTheme);
|
||||||
if (!cursor) return;
|
if (!cursor) return;
|
||||||
// TODO: handle animated cursors too.
|
// TODO: handle animated cursors too.
|
||||||
image = cursor->images[0];
|
image = cursor->images[0];
|
||||||
@@ -158,10 +164,11 @@ static void setCursor(GLFWCursorShape shape)
|
|||||||
buffer = wl_cursor_image_get_buffer(image);
|
buffer = wl_cursor_image_get_buffer(image);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return;
|
return;
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
|
||||||
surface,
|
surface,
|
||||||
image->hotspot_x,
|
image->hotspot_x / scale,
|
||||||
image->hotspot_y);
|
image->hotspot_y / scale);
|
||||||
|
wl_surface_set_buffer_scale(surface, scale);
|
||||||
wl_surface_attach(surface, buffer, 0, 0);
|
wl_surface_attach(surface, buffer, 0, 0);
|
||||||
wl_surface_damage(surface, 0, 0,
|
wl_surface_damage(surface, 0, 0,
|
||||||
image->width, image->height);
|
image->width, image->height);
|
||||||
@@ -225,7 +232,7 @@ static void pointerHandleMotion(void* data UNUSED,
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if (_glfw.wl.cursorPreviousShape != cursorShape)
|
if (_glfw.wl.cursorPreviousShape != cursorShape)
|
||||||
setCursor(cursorShape);
|
setCursor(cursorShape, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleButton(void* data UNUSED,
|
static void pointerHandleButton(void* data UNUSED,
|
||||||
@@ -301,7 +308,7 @@ static void pointerHandleButton(void* data UNUSED,
|
|||||||
if (window->wl.decorations.focus != mainWindow)
|
if (window->wl.decorations.focus != mainWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.serial = serial;
|
||||||
|
|
||||||
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
|
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
|
||||||
* codes. */
|
* codes. */
|
||||||
@@ -334,7 +341,7 @@ static void pointerHandleAxis(void* data UNUSED,
|
|||||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
y = wl_fixed_to_double(value) * -1;
|
y = wl_fixed_to_double(value) * -1;
|
||||||
|
|
||||||
_glfwInputScroll(window, x, y, 1);
|
_glfwInputScroll(window, x, y, 1, _glfw.wl.xkb.states.modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_pointer_listener pointerListener = {
|
static const struct wl_pointer_listener pointerListener = {
|
||||||
@@ -372,7 +379,7 @@ static void keyboardHandleKeymap(void* data UNUSED,
|
|||||||
|
|
||||||
static void keyboardHandleEnter(void* data UNUSED,
|
static void keyboardHandleEnter(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard UNUSED,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial UNUSED,
|
uint32_t serial,
|
||||||
struct wl_surface* surface,
|
struct wl_surface* surface,
|
||||||
struct wl_array* keys)
|
struct wl_array* keys)
|
||||||
{
|
{
|
||||||
@@ -388,6 +395,7 @@ static void keyboardHandleEnter(void* data UNUSED,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.keyboardFocus = window;
|
_glfw.wl.keyboardFocus = window;
|
||||||
_glfwInputWindowFocus(window, true);
|
_glfwInputWindowFocus(window, true);
|
||||||
uint32_t* key;
|
uint32_t* key;
|
||||||
@@ -403,7 +411,7 @@ static void keyboardHandleEnter(void* data UNUSED,
|
|||||||
|
|
||||||
static void keyboardHandleLeave(void* data UNUSED,
|
static void keyboardHandleLeave(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard UNUSED,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial UNUSED,
|
uint32_t serial,
|
||||||
struct wl_surface* surface UNUSED)
|
struct wl_surface* surface UNUSED)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
||||||
@@ -411,6 +419,7 @@ static void keyboardHandleLeave(void* data UNUSED,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.keyboardFocus = NULL;
|
_glfw.wl.keyboardFocus = NULL;
|
||||||
_glfwInputWindowFocus(window, false);
|
_glfwInputWindowFocus(window, false);
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 0);
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 0);
|
||||||
@@ -427,7 +436,7 @@ dispatchPendingKeyRepeats(id_type timer_id UNUSED, void *data UNUSED) {
|
|||||||
|
|
||||||
static void keyboardHandleKey(void* data UNUSED,
|
static void keyboardHandleKey(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard UNUSED,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial UNUSED,
|
uint32_t serial,
|
||||||
uint32_t time UNUSED,
|
uint32_t time UNUSED,
|
||||||
uint32_t key,
|
uint32_t key,
|
||||||
uint32_t state)
|
uint32_t state)
|
||||||
@@ -436,6 +445,8 @@ static void keyboardHandleKey(void* data UNUSED,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
|
||||||
|
_glfw.wl.serial = serial;
|
||||||
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
|
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
|
||||||
bool repeatable = false;
|
bool repeatable = false;
|
||||||
_glfw.wl.keyRepeatInfo.key = 0;
|
_glfw.wl.keyRepeatInfo.key = 0;
|
||||||
@@ -454,12 +465,13 @@ static void keyboardHandleKey(void* data UNUSED,
|
|||||||
|
|
||||||
static void keyboardHandleModifiers(void* data UNUSED,
|
static void keyboardHandleModifiers(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard UNUSED,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial UNUSED,
|
uint32_t serial,
|
||||||
uint32_t modsDepressed,
|
uint32_t modsDepressed,
|
||||||
uint32_t modsLatched,
|
uint32_t modsLatched,
|
||||||
uint32_t modsLocked,
|
uint32_t modsLocked,
|
||||||
uint32_t group)
|
uint32_t group)
|
||||||
{
|
{
|
||||||
|
_glfw.wl.serial = serial;
|
||||||
glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group);
|
glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -775,26 +787,14 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
if (_glfw.wl.shm)
|
if (_glfw.wl.shm)
|
||||||
{
|
{
|
||||||
const char *cursorTheme = getenv("XCURSOR_THEME"), *cursorSizeStr = getenv("XCURSOR_SIZE");
|
_glfw.wl.cursorThemeManager = _wlCursorThemeManagerDefault();
|
||||||
char *cursorSizeEnd;
|
_glfw.wl.cursorSurface =
|
||||||
int cursorSize = 32;
|
|
||||||
if (cursorSizeStr)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
long cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
|
|
||||||
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
|
|
||||||
cursorSize = (int)cursorSizeLong;
|
|
||||||
}
|
|
||||||
_glfw.wl.cursorTheme = wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
|
|
||||||
if (!_glfw.wl.cursorTheme)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Unable to load default cursor theme");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_glfw.wl.cursorSurface =
|
|
||||||
wl_compositor_create_surface(_glfw.wl.compositor);
|
wl_compositor_create_surface(_glfw.wl.compositor);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfw.wl.cursorThemeManager = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -814,8 +814,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
glfw_xkb_release(&_glfw.wl.xkb);
|
glfw_xkb_release(&_glfw.wl.xkb);
|
||||||
glfw_dbus_terminate(&_glfw.wl.dbus);
|
glfw_dbus_terminate(&_glfw.wl.dbus);
|
||||||
|
|
||||||
if (_glfw.wl.cursorTheme)
|
|
||||||
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
|
||||||
if (_glfw.wl.cursor.handle)
|
if (_glfw.wl.cursor.handle)
|
||||||
{
|
{
|
||||||
_glfw_dlclose(_glfw.wl.cursor.handle);
|
_glfw_dlclose(_glfw.wl.cursor.handle);
|
||||||
@@ -824,6 +822,9 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
if (_glfw.wl.cursorSurface)
|
if (_glfw.wl.cursorSurface)
|
||||||
wl_surface_destroy(_glfw.wl.cursorSurface);
|
wl_surface_destroy(_glfw.wl.cursorSurface);
|
||||||
|
if (_glfw.wl.cursorThemeManager) {
|
||||||
|
_wlCursorThemeManagerDestroy(_glfw.wl.cursorThemeManager);
|
||||||
|
}
|
||||||
if (_glfw.wl.subcompositor)
|
if (_glfw.wl.subcompositor)
|
||||||
wl_subcompositor_destroy(_glfw.wl.subcompositor);
|
wl_subcompositor_destroy(_glfw.wl.subcompositor);
|
||||||
if (_glfw.wl.compositor)
|
if (_glfw.wl.compositor)
|
||||||
|
|||||||
4
glfw/wl_monitor.c
vendored
4
glfw/wl_monitor.c
vendored
@@ -202,7 +202,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
|
|
||||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp UNUSED)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
"Wayland: Gamma ramp access is not available");
|
"Wayland: Gamma ramp access is not available");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp
|
|||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED,
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED,
|
||||||
const GLFWgammaramp* ramp UNUSED)
|
const GLFWgammaramp* ramp UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
"Wayland: Gamma ramp access is not available");
|
"Wayland: Gamma ramp access is not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
glfw/wl_platform.h
vendored
28
glfw/wl_platform.h
vendored
@@ -52,6 +52,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||||||
#include "xkb_glfw.h"
|
#include "xkb_glfw.h"
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
#include "osmesa_context.h"
|
#include "osmesa_context.h"
|
||||||
|
#include "wl_cursors.h"
|
||||||
|
|
||||||
#include "wayland-xdg-shell-client-protocol.h"
|
#include "wayland-xdg-shell-client-protocol.h"
|
||||||
#include "wayland-viewporter-client-protocol.h"
|
#include "wayland-viewporter-client-protocol.h"
|
||||||
@@ -76,18 +77,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||||||
#define _GLFW_PLATFORM_CONTEXT_STATE
|
#define _GLFW_PLATFORM_CONTEXT_STATE
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||||
|
|
||||||
struct wl_cursor_image {
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
uint32_t hotspot_x;
|
|
||||||
uint32_t hotspot_y;
|
|
||||||
uint32_t delay;
|
|
||||||
};
|
|
||||||
struct wl_cursor {
|
|
||||||
unsigned int image_count;
|
|
||||||
struct wl_cursor_image** images;
|
|
||||||
char* name;
|
|
||||||
};
|
|
||||||
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
|
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
|
||||||
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
|
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
|
||||||
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
|
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
|
||||||
@@ -148,6 +137,7 @@ typedef struct _GLFWwindowWayland
|
|||||||
|
|
||||||
_GLFWcursor* currentCursor;
|
_GLFWcursor* currentCursor;
|
||||||
double cursorPosX, cursorPosY;
|
double cursorPosX, cursorPosY;
|
||||||
|
struct wl_cursor_theme* cursorTheme;
|
||||||
|
|
||||||
char* title;
|
char* title;
|
||||||
char appId[256];
|
char appId[256];
|
||||||
@@ -236,10 +226,9 @@ typedef struct _GLFWlibraryWayland
|
|||||||
int compositorVersion;
|
int compositorVersion;
|
||||||
int seatVersion;
|
int seatVersion;
|
||||||
|
|
||||||
struct wl_cursor_theme* cursorTheme;
|
|
||||||
struct wl_surface* cursorSurface;
|
struct wl_surface* cursorSurface;
|
||||||
GLFWCursorShape cursorPreviousShape;
|
GLFWCursorShape cursorPreviousShape;
|
||||||
uint32_t pointerSerial;
|
uint32_t serial;
|
||||||
|
|
||||||
int32_t keyboardRepeatRate;
|
int32_t keyboardRepeatRate;
|
||||||
monotonic_t keyboardRepeatDelay;
|
monotonic_t keyboardRepeatDelay;
|
||||||
@@ -278,6 +267,8 @@ typedef struct _GLFWlibraryWayland
|
|||||||
size_t dataOffersCounter;
|
size_t dataOffersCounter;
|
||||||
_GLFWWaylandDataOffer dataOffers[8];
|
_GLFWWaylandDataOffer dataOffers[8];
|
||||||
char* primarySelectionString;
|
char* primarySelectionString;
|
||||||
|
|
||||||
|
_wlCursorThemeManager* cursorThemeManager;
|
||||||
} _GLFWlibraryWayland;
|
} _GLFWlibraryWayland;
|
||||||
|
|
||||||
// Wayland-specific per-monitor data
|
// Wayland-specific per-monitor data
|
||||||
@@ -291,8 +282,7 @@ typedef struct _GLFWmonitorWayland
|
|||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int scale;
|
int scale;
|
||||||
|
} _GLFWmonitorWayland;
|
||||||
} _GLFWmonitorWayland;
|
|
||||||
|
|
||||||
// Wayland-specific per-cursor data
|
// Wayland-specific per-cursor data
|
||||||
//
|
//
|
||||||
@@ -303,6 +293,10 @@ typedef struct _GLFWcursorWayland
|
|||||||
int width, height;
|
int width, height;
|
||||||
int xhot, yhot;
|
int xhot, yhot;
|
||||||
int currentImage;
|
int currentImage;
|
||||||
|
/** The scale of the cursor, or 0 if the cursor should be loaded late, or -1 if the cursor variable itself is unused. */
|
||||||
|
int scale;
|
||||||
|
/** Cursor shape stored to allow late cursor loading in setCursorImage. */
|
||||||
|
GLFWCursorShape shape;
|
||||||
} _GLFWcursorWayland;
|
} _GLFWcursorWayland;
|
||||||
|
|
||||||
|
|
||||||
@@ -310,5 +304,5 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
|||||||
void _glfwSetupWaylandDataDevice(void);
|
void _glfwSetupWaylandDataDevice(void);
|
||||||
void _glfwSetupWaylandPrimarySelectionDevice(void);
|
void _glfwSetupWaylandPrimarySelectionDevice(void);
|
||||||
void animateCursorImage(id_type timer_id, void *data);
|
void animateCursorImage(id_type timer_id, void *data);
|
||||||
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape);
|
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape, struct wl_cursor_theme*);
|
||||||
void destroy_data_offer(_GLFWWaylandDataOffer*);
|
void destroy_data_offer(_GLFWWaylandDataOffer*);
|
||||||
|
|||||||
277
glfw/wl_window.c
vendored
277
glfw/wl_window.c
vendored
@@ -41,8 +41,67 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_cursor_theme(_GLFWwindow* window) {
|
||||||
|
window->wl.cursorTheme = _wlCursorThemeManage(
|
||||||
|
_glfw.wl.cursorThemeManager, window->wl.cursorTheme, _wlCursorPxFromScale(window->wl.scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setCursorImage(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
_GLFWcursorWayland defaultCursor = {.shape = GLFW_ARROW_CURSOR};
|
||||||
|
_GLFWcursorWayland* cursorWayland = window->cursor ? &window->cursor->wl : &defaultCursor;
|
||||||
|
struct wl_cursor_image* image = NULL;
|
||||||
|
struct wl_buffer* buffer = NULL;
|
||||||
|
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
||||||
|
const int scale = window->wl.scale;
|
||||||
|
|
||||||
|
if (cursorWayland->scale < 0) {
|
||||||
|
buffer = cursorWayland->buffer;
|
||||||
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 0);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (cursorWayland->scale != scale) {
|
||||||
|
if (!window->wl.cursorTheme) load_cursor_theme(window);
|
||||||
|
struct wl_cursor *newCursor = _glfwLoadCursor(cursorWayland->shape, window->wl.cursorTheme);
|
||||||
|
if (newCursor != NULL) {
|
||||||
|
cursorWayland->cursor = newCursor;
|
||||||
|
cursorWayland->scale = scale;
|
||||||
|
} else {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: late cursor load failed; proceeding with existing cursor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cursorWayland->cursor)
|
||||||
|
return;
|
||||||
|
image = cursorWayland->cursor->images[cursorWayland->currentImage];
|
||||||
|
buffer = wl_cursor_image_get_buffer(image);
|
||||||
|
if (image->delay && window->cursor) {
|
||||||
|
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, ms_to_monotonic_t(image->delay));
|
||||||
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 1);
|
||||||
|
} else {
|
||||||
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cursorWayland->width = image->width;
|
||||||
|
cursorWayland->height = image->height;
|
||||||
|
cursorWayland->xhot = image->hotspot_x;
|
||||||
|
cursorWayland->yhot = image->hotspot_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
|
||||||
|
surface,
|
||||||
|
cursorWayland->xhot / scale,
|
||||||
|
cursorWayland->yhot / scale);
|
||||||
|
wl_surface_set_buffer_scale(surface, scale);
|
||||||
|
wl_surface_attach(surface, buffer, 0, 0);
|
||||||
|
wl_surface_damage(surface, 0, 0,
|
||||||
|
cursorWayland->width, cursorWayland->height);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool checkScaleChange(_GLFWwindow* window)
|
static bool checkScaleChange(_GLFWwindow* window)
|
||||||
@@ -73,6 +132,8 @@ static bool checkScaleChange(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
window->wl.scale = scale;
|
window->wl.scale = scale;
|
||||||
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
||||||
|
load_cursor_theme(window);
|
||||||
|
setCursorImage(window);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (window->wl.monitorsCount > 0 && !window->wl.initial_scale_notified) {
|
if (window->wl.monitorsCount > 0 && !window->wl.initial_scale_notified) {
|
||||||
@@ -388,9 +449,9 @@ static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener =
|
|||||||
xdgDecorationHandleConfigure,
|
xdgDecorationHandleConfigure,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handleEnter(void *data,
|
static void surfaceHandleEnter(void *data,
|
||||||
struct wl_surface *surface UNUSED,
|
struct wl_surface *surface UNUSED,
|
||||||
struct wl_output *output)
|
struct wl_output *output)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
_GLFWmonitor* monitor = wl_output_get_user_data(output);
|
_GLFWmonitor* monitor = wl_output_get_user_data(output);
|
||||||
@@ -411,9 +472,9 @@ static void handleEnter(void *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleLeave(void *data,
|
static void surfaceHandleLeave(void *data,
|
||||||
struct wl_surface *surface UNUSED,
|
struct wl_surface *surface UNUSED,
|
||||||
struct wl_output *output)
|
struct wl_output *output)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
_GLFWmonitor* monitor = wl_output_get_user_data(output);
|
_GLFWmonitor* monitor = wl_output_get_user_data(output);
|
||||||
@@ -436,8 +497,8 @@ static void handleLeave(void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_surface_listener surfaceListener = {
|
static const struct wl_surface_listener surfaceListener = {
|
||||||
handleEnter,
|
surfaceHandleEnter,
|
||||||
handleLeave
|
surfaceHandleLeave
|
||||||
};
|
};
|
||||||
|
|
||||||
static void setIdleInhibitor(_GLFWwindow* window, bool enable)
|
static void setIdleInhibitor(_GLFWwindow* window, bool enable)
|
||||||
@@ -679,56 +740,16 @@ static bool createXdgSurface(_GLFWwindow* window)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
setCursorImage(_GLFWcursorWayland* cursorWayland)
|
|
||||||
{
|
|
||||||
struct wl_cursor_image* image;
|
|
||||||
struct wl_buffer* buffer;
|
|
||||||
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
|
||||||
|
|
||||||
if (!cursorWayland->cursor) {
|
|
||||||
buffer = cursorWayland->buffer;
|
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 0);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
image = cursorWayland->cursor->images[cursorWayland->currentImage];
|
|
||||||
buffer = wl_cursor_image_get_buffer(image);
|
|
||||||
if (image->delay) {
|
|
||||||
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, ms_to_monotonic_t(image->delay));
|
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 1);
|
|
||||||
} else {
|
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cursorWayland->width = image->width;
|
|
||||||
cursorWayland->height = image->height;
|
|
||||||
cursorWayland->xhot = image->hotspot_x;
|
|
||||||
cursorWayland->yhot = image->hotspot_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
|
||||||
surface,
|
|
||||||
cursorWayland->xhot,
|
|
||||||
cursorWayland->yhot);
|
|
||||||
wl_surface_attach(surface, buffer, 0, 0);
|
|
||||||
wl_surface_damage(surface, 0, 0,
|
|
||||||
cursorWayland->width, cursorWayland->height);
|
|
||||||
wl_surface_commit(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
incrementCursorImage(_GLFWwindow* window)
|
incrementCursorImage(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window && window->wl.decorations.focus == mainWindow) {
|
if (window && window->wl.decorations.focus == mainWindow && window->cursorMode != GLFW_CURSOR_HIDDEN) {
|
||||||
_GLFWcursor* cursor = window->wl.currentCursor;
|
_GLFWcursor* cursor = window->wl.currentCursor;
|
||||||
if (cursor && cursor->wl.cursor)
|
if (cursor && cursor->wl.cursor)
|
||||||
{
|
{
|
||||||
cursor->wl.currentImage += 1;
|
cursor->wl.currentImage += 1;
|
||||||
cursor->wl.currentImage %= cursor->wl.cursor->image_count;
|
cursor->wl.currentImage %= cursor->wl.cursor->image_count;
|
||||||
setCursorImage(&cursor->wl);
|
setCursorImage(window);
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, cursor->wl.cursor->image_count > 1);
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, cursor->wl.cursor->image_count > 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -744,11 +765,14 @@ animateCursorImage(id_type timer_id UNUSED, void *data UNUSED) {
|
|||||||
static void
|
static void
|
||||||
abortOnFatalError(int last_error) {
|
abortOnFatalError(int last_error) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: fatal display error: %s", strerror(last_error));
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: fatal display error: %s", strerror(last_error));
|
||||||
_GLFWwindow* window = _glfw.windowListHead;
|
if (_glfw.callbacks.application_close) _glfw.callbacks.application_close(1);
|
||||||
while (window)
|
else {
|
||||||
{
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
_glfwInputWindowCloseRequest(window);
|
while (window)
|
||||||
window = window->next;
|
{
|
||||||
|
_glfwInputWindowCloseRequest(window);
|
||||||
|
window = window->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ensure the tick callback is called
|
// ensure the tick callback is called
|
||||||
_glfw.wl.eventLoopData.wakeup_data_read = true;
|
_glfw.wl.eventLoopData.wakeup_data_read = true;
|
||||||
@@ -804,24 +828,25 @@ handleEvents(monotonic_t timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct wl_cursor*
|
static struct wl_cursor*
|
||||||
try_cursor_names(int arg_count, ...) {
|
try_cursor_names(struct wl_cursor_theme* theme, int arg_count, ...) {
|
||||||
struct wl_cursor* ans = NULL;
|
struct wl_cursor* ans = NULL;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, arg_count);
|
va_start(ap, arg_count);
|
||||||
for (int i = 0; i < arg_count && !ans; i++) {
|
for (int i = 0; i < arg_count && !ans; i++) {
|
||||||
const char *name = va_arg(ap, const char *);
|
const char *name = va_arg(ap, const char *);
|
||||||
ans = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, name);
|
ans = wl_cursor_theme_get_cursor(theme, name);
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape shape)
|
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape shape, struct wl_cursor_theme* theme)
|
||||||
{
|
{
|
||||||
static bool warnings[GLFW_INVALID_CURSOR] = {0};
|
static bool warnings[GLFW_INVALID_CURSOR] = {0};
|
||||||
|
if (!theme) return NULL;
|
||||||
#define NUMARGS(...) (sizeof((const char*[]){__VA_ARGS__})/sizeof(const char*))
|
#define NUMARGS(...) (sizeof((const char*[]){__VA_ARGS__})/sizeof(const char*))
|
||||||
#define C(name, ...) case name: { \
|
#define C(name, ...) case name: { \
|
||||||
ans = try_cursor_names(NUMARGS(__VA_ARGS__), __VA_ARGS__); \
|
ans = try_cursor_names(theme, NUMARGS(__VA_ARGS__), __VA_ARGS__); \
|
||||||
if (!ans && !warnings[name]) {\
|
if (!ans && !warnings[name]) {\
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Could not find standard cursor: %s", #name); \
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Could not find standard cursor: %s", #name); \
|
||||||
warnings[name] = true; \
|
warnings[name] = true; \
|
||||||
@@ -831,7 +856,7 @@ struct wl_cursor* _glfwLoadCursor(GLFWCursorShape shape)
|
|||||||
struct wl_cursor* ans = NULL;
|
struct wl_cursor* ans = NULL;
|
||||||
switch (shape)
|
switch (shape)
|
||||||
{
|
{
|
||||||
C(GLFW_ARROW_CURSOR, "arrow", "left_ptr", "default")
|
C(GLFW_ARROW_CURSOR, "left_ptr", "arrow", "default")
|
||||||
C(GLFW_IBEAM_CURSOR, "xterm", "ibeam", "text")
|
C(GLFW_IBEAM_CURSOR, "xterm", "ibeam", "text")
|
||||||
C(GLFW_CROSSHAIR_CURSOR, "crosshair", "cross")
|
C(GLFW_CROSSHAIR_CURSOR, "crosshair", "cross")
|
||||||
C(GLFW_HAND_CURSOR, "hand2", "grab", "grabbing", "closedhand")
|
C(GLFW_HAND_CURSOR, "hand2", "grab", "grabbing", "closedhand")
|
||||||
@@ -901,6 +926,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
window->wl.currentCursor = NULL;
|
window->wl.currentCursor = NULL;
|
||||||
|
// Don't set window->wl.cursorTheme to NULL here.
|
||||||
|
|
||||||
window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
|
window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
|
||||||
window->wl.monitorsCount = 0;
|
window->wl.monitorsCount = 0;
|
||||||
@@ -911,6 +937,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
if (window->wl.cursorTheme) {
|
||||||
|
_wlCursorThemeManage(_glfw.wl.cursorThemeManager,
|
||||||
|
window->wl.cursorTheme,
|
||||||
|
0);
|
||||||
|
window->wl.cursorTheme = NULL;
|
||||||
|
}
|
||||||
if (window == _glfw.wl.pointerFocus)
|
if (window == _glfw.wl.pointerFocus)
|
||||||
{
|
{
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
@@ -929,6 +961,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
window->context.destroy(window);
|
window->context.destroy(window);
|
||||||
|
|
||||||
destroyDecorations(window);
|
destroyDecorations(window);
|
||||||
|
|
||||||
if (window->wl.xdg.decoration)
|
if (window->wl.xdg.decoration)
|
||||||
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
|
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
|
||||||
|
|
||||||
@@ -957,12 +990,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||||||
{
|
{
|
||||||
if (window->wl.title)
|
if (window->wl.title)
|
||||||
free(window->wl.title);
|
free(window->wl.title);
|
||||||
window->wl.title = _glfw_strdup(title);
|
|
||||||
// Wayland cannot handle requests larger than ~8200 bytes. Sending
|
// Wayland cannot handle requests larger than ~8200 bytes. Sending
|
||||||
// one causes an abort(). Since titles this large are meaningless anyway
|
// one causes an abort(). Since titles this large are meaningless anyway
|
||||||
// ensure they do not happen. One should really truncate ensuring valid UTF-8
|
// ensure they do not happen.
|
||||||
// but I cant be bothered.
|
window->wl.title = utf_8_strndup(title, 2048);
|
||||||
if (title && strnlen(title, 2048) >= 2048) window->wl.title[2048] = 0;
|
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
|
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
|
||||||
}
|
}
|
||||||
@@ -970,8 +1001,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,
|
||||||
int count UNUSED, const GLFWimage* images UNUSED)
|
int count UNUSED, const GLFWimage* images UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
"Wayland: Setting window icon not supported");
|
"Wayland: The platform does not support setting the window icon");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
||||||
@@ -979,16 +1010,16 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int
|
|||||||
// A Wayland client is not aware of its position, so just warn and leave it
|
// A Wayland client is not aware of its position, so just warn and leave it
|
||||||
// as (0, 0)
|
// as (0, 0)
|
||||||
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
"Wayland: Window position retrieval not supported");
|
"Wayland: The platform does not provide the window position");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int ypos UNUSED)
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int ypos UNUSED)
|
||||||
{
|
{
|
||||||
// A Wayland client can not set its position, so just warn
|
// A Wayland client can not set its position, so just warn
|
||||||
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
"Wayland: Window position setting not supported");
|
"Wayland: The platform does not support setting the window position");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||||
@@ -1029,6 +1060,8 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window UNUSED,
|
|||||||
{
|
{
|
||||||
// TODO: find out how to trigger a resize.
|
// TODO: find out how to trigger a resize.
|
||||||
// The actual limits are checked in the xdg_toplevel::configure handler.
|
// The actual limits are checked in the xdg_toplevel::configure handler.
|
||||||
|
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||||
|
"Wayland: Window aspect ratio not yet implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED,
|
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED,
|
||||||
@@ -1133,7 +1166,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
|
|||||||
// TODO
|
// TODO
|
||||||
static bool notified = false;
|
static bool notified = false;
|
||||||
if (!notified) {
|
if (!notified) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||||
"Wayland: Window attention request not implemented yet");
|
"Wayland: Window attention request not implemented yet");
|
||||||
notified = true;
|
notified = true;
|
||||||
}
|
}
|
||||||
@@ -1154,8 +1187,8 @@ int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
|
|||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
"Wayland: Focusing a window requires user interaction");
|
"Wayland: The platform does not support setting the input focus");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||||
@@ -1208,7 +1241,7 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
|||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||||
"Wayland: Window attribute setting not implemented yet");
|
"Wayland: Window attribute setting not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1226,7 +1259,7 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
|||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
|
||||||
"Wayland: Window attribute setting not implemented yet");
|
"Wayland: Window attribute setting not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1237,6 +1270,18 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window UNUSED, float opacity UNUSED)
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window UNUSED, float opacity UNUSED)
|
||||||
{
|
{
|
||||||
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
|
"Wayland: The platform does not support setting the window opacity");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window UNUSED, bool enabled UNUSED)
|
||||||
|
{
|
||||||
|
// This is handled in relativePointerHandleRelativeMotion
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _glfwPlatformRawMouseMotionSupported(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
@@ -1309,17 +1354,19 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
cursor->wl.height = image->height;
|
cursor->wl.height = image->height;
|
||||||
cursor->wl.xhot = xhot;
|
cursor->wl.xhot = xhot;
|
||||||
cursor->wl.yhot = yhot;
|
cursor->wl.yhot = yhot;
|
||||||
|
cursor->wl.scale = -1;
|
||||||
|
cursor->wl.shape = GLFW_INVALID_CURSOR;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape)
|
||||||
{
|
{
|
||||||
struct wl_cursor* standardCursor;
|
// Don't actually load the cursor at this point,
|
||||||
|
// because there's not enough info to be properly HiDPI aware.
|
||||||
standardCursor = _glfwLoadCursor(shape);
|
cursor->wl.cursor = NULL;
|
||||||
if (!standardCursor) return false;
|
|
||||||
cursor->wl.cursor = standardCursor;
|
|
||||||
cursor->wl.currentImage = 0;
|
cursor->wl.currentImage = 0;
|
||||||
|
cursor->wl.scale = 0;
|
||||||
|
cursor->wl.shape = shape;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1333,31 +1380,42 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
|||||||
wl_buffer_destroy(cursor->wl.buffer);
|
wl_buffer_destroy(cursor->wl.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleRelativeMotion(void* data,
|
static void relativePointerHandleRelativeMotion(void* data,
|
||||||
struct zwp_relative_pointer_v1* pointer UNUSED,
|
struct zwp_relative_pointer_v1* pointer UNUSED,
|
||||||
uint32_t timeHi UNUSED,
|
uint32_t timeHi UNUSED,
|
||||||
uint32_t timeLo UNUSED,
|
uint32_t timeLo UNUSED,
|
||||||
wl_fixed_t dx UNUSED,
|
wl_fixed_t dx,
|
||||||
wl_fixed_t dy UNUSED,
|
wl_fixed_t dy,
|
||||||
wl_fixed_t dxUnaccel,
|
wl_fixed_t dxUnaccel,
|
||||||
wl_fixed_t dyUnaccel)
|
wl_fixed_t dyUnaccel)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
|
double xpos = window->virtualCursorPosX;
|
||||||
|
double ypos = window->virtualCursorPosY;
|
||||||
|
|
||||||
if (window->cursorMode != GLFW_CURSOR_DISABLED)
|
if (window->cursorMode != GLFW_CURSOR_DISABLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_glfwInputCursorPos(window,
|
if (window->rawMouseMotion)
|
||||||
window->virtualCursorPosX + wl_fixed_to_double(dxUnaccel),
|
{
|
||||||
window->virtualCursorPosY + wl_fixed_to_double(dyUnaccel));
|
xpos += wl_fixed_to_double(dxUnaccel);
|
||||||
|
ypos += wl_fixed_to_double(dyUnaccel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xpos += wl_fixed_to_double(dx);
|
||||||
|
ypos += wl_fixed_to_double(dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputCursorPos(window, xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
|
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
|
||||||
handleRelativeMotion
|
relativePointerHandleRelativeMotion
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handleLocked(void* data UNUSED,
|
static void lockedPointerHandleLocked(void* data UNUSED,
|
||||||
struct zwp_locked_pointer_v1* lockedPointer UNUSED)
|
struct zwp_locked_pointer_v1* lockedPointer UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1377,14 +1435,14 @@ static void unlockPointer(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void lockPointer(_GLFWwindow* window UNUSED);
|
static void lockPointer(_GLFWwindow* window UNUSED);
|
||||||
|
|
||||||
static void handleUnlocked(void* data UNUSED,
|
static void lockedPointerHandleUnlocked(void* data UNUSED,
|
||||||
struct zwp_locked_pointer_v1* lockedPointer UNUSED)
|
struct zwp_locked_pointer_v1* lockedPointer UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
|
static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
|
||||||
handleLocked,
|
lockedPointerHandleLocked,
|
||||||
handleUnlocked
|
lockedPointerHandleUnlocked
|
||||||
};
|
};
|
||||||
|
|
||||||
static void lockPointer(_GLFWwindow* window)
|
static void lockPointer(_GLFWwindow* window)
|
||||||
@@ -1421,7 +1479,7 @@ static void lockPointer(_GLFWwindow* window)
|
|||||||
window->wl.pointerLock.relativePointer = relativePointer;
|
window->wl.pointerLock.relativePointer = relativePointer;
|
||||||
window->wl.pointerLock.lockedPointer = lockedPointer;
|
window->wl.pointerLock.lockedPointer = lockedPointer;
|
||||||
|
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
|
||||||
NULL, 0, 0);
|
NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1432,8 +1490,6 @@ static bool isPointerLocked(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
struct wl_cursor* defaultCursor;
|
|
||||||
|
|
||||||
if (!_glfw.wl.pointer)
|
if (!_glfw.wl.pointer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1450,21 +1506,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||||
{
|
{
|
||||||
if (cursor)
|
setCursorImage(window);
|
||||||
setCursorImage(&cursor->wl);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
defaultCursor = _glfwLoadCursor(GLFW_ARROW_CURSOR);
|
|
||||||
if (!defaultCursor) return;
|
|
||||||
_GLFWcursorWayland cursorWayland = {
|
|
||||||
defaultCursor,
|
|
||||||
NULL,
|
|
||||||
0, 0,
|
|
||||||
0, 0,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
setCursorImage(&cursorWayland);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
@@ -1473,8 +1515,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
}
|
}
|
||||||
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||||
{
|
{
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0);
|
||||||
NULL, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
56
glfw/x11_init.c
vendored
56
glfw/x11_init.c
vendored
@@ -42,11 +42,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
// Check whether the specified atom is supported
|
// Return the atom ID only if it is listed in the specified array
|
||||||
//
|
//
|
||||||
static Atom getSupportedAtom(Atom* supportedAtoms,
|
static Atom getAtomIfSupported(Atom* supportedAtoms,
|
||||||
unsigned long atomCount,
|
unsigned long atomCount,
|
||||||
const char* atomName)
|
const char* atomName)
|
||||||
{
|
{
|
||||||
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
|
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
|
||||||
|
|
||||||
@@ -64,9 +64,8 @@ static Atom getSupportedAtom(Atom* supportedAtoms,
|
|||||||
static void detectEWMH(void)
|
static void detectEWMH(void)
|
||||||
{
|
{
|
||||||
// First we read the _NET_SUPPORTING_WM_CHECK property on the root window
|
// First we read the _NET_SUPPORTING_WM_CHECK property on the root window
|
||||||
Window* windowFromRoot = NULL;
|
|
||||||
|
|
||||||
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
|
Window* windowFromRoot = NULL;
|
||||||
if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
|
if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
_glfw.x11.NET_SUPPORTING_WM_CHECK,
|
_glfw.x11.NET_SUPPORTING_WM_CHECK,
|
||||||
XA_WINDOW,
|
XA_WINDOW,
|
||||||
@@ -93,6 +92,7 @@ static void detectEWMH(void)
|
|||||||
_glfwReleaseErrorHandlerX11();
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
|
||||||
// If the property exists, it should contain the XID of the window
|
// If the property exists, it should contain the XID of the window
|
||||||
|
|
||||||
if (*windowFromRoot != *windowFromChild)
|
if (*windowFromRoot != *windowFromChild)
|
||||||
{
|
{
|
||||||
XFree(windowFromRoot);
|
XFree(windowFromRoot);
|
||||||
@@ -103,49 +103,50 @@ static void detectEWMH(void)
|
|||||||
XFree(windowFromRoot);
|
XFree(windowFromRoot);
|
||||||
XFree(windowFromChild);
|
XFree(windowFromChild);
|
||||||
|
|
||||||
// We are now fairly sure that an EWMH-compliant window manager is running
|
// We are now fairly sure that an EWMH-compliant WM is currently running
|
||||||
// We can now start querying the WM about what features it supports by
|
// We can now start querying the WM about what features it supports by
|
||||||
// looking in the _NET_SUPPORTED property on the root window
|
// looking in the _NET_SUPPORTED property on the root window
|
||||||
// It should contain a list of supported EWMH protocol and state atoms
|
// It should contain a list of supported EWMH protocol and state atoms
|
||||||
|
|
||||||
Atom* supportedAtoms = NULL;
|
Atom* supportedAtoms = NULL;
|
||||||
const unsigned long atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,
|
const unsigned long atomCount =
|
||||||
_glfw.x11.NET_SUPPORTED,
|
_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
XA_ATOM,
|
_glfw.x11.NET_SUPPORTED,
|
||||||
(unsigned char**) &supportedAtoms);
|
XA_ATOM,
|
||||||
|
(unsigned char**) &supportedAtoms);
|
||||||
if (!supportedAtoms)
|
if (!supportedAtoms)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// See which of the atoms we support that are supported by the WM
|
// See which of the atoms we support that are supported by the WM
|
||||||
|
|
||||||
_glfw.x11.NET_WM_STATE =
|
_glfw.x11.NET_WM_STATE =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE");
|
||||||
_glfw.x11.NET_WM_STATE_ABOVE =
|
_glfw.x11.NET_WM_STATE_ABOVE =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
|
||||||
_glfw.x11.NET_WM_STATE_FULLSCREEN =
|
_glfw.x11.NET_WM_STATE_FULLSCREEN =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
||||||
_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =
|
_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
|
||||||
_glfw.x11.NET_WM_FULLSCREEN_MONITORS =
|
_glfw.x11.NET_WM_FULLSCREEN_MONITORS =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
||||||
_glfw.x11.NET_WM_WINDOW_TYPE =
|
_glfw.x11.NET_WM_WINDOW_TYPE =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
||||||
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
|
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||||
_glfw.x11.NET_WORKAREA =
|
_glfw.x11.NET_WORKAREA =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA");
|
||||||
_glfw.x11.NET_CURRENT_DESKTOP =
|
_glfw.x11.NET_CURRENT_DESKTOP =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
||||||
_glfw.x11.NET_ACTIVE_WINDOW =
|
_glfw.x11.NET_ACTIVE_WINDOW =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||||
_glfw.x11.NET_FRAME_EXTENTS =
|
_glfw.x11.NET_FRAME_EXTENTS =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
|
||||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
getAtomIfSupported(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||||
|
|
||||||
XFree(supportedAtoms);
|
XFree(supportedAtoms);
|
||||||
}
|
}
|
||||||
@@ -502,8 +503,11 @@ static Window createHelperWindow(void)
|
|||||||
|
|
||||||
// X error handler
|
// X error handler
|
||||||
//
|
//
|
||||||
static int errorHandler(Display *display UNUSED, XErrorEvent* event)
|
static int errorHandler(Display *display, XErrorEvent* event)
|
||||||
{
|
{
|
||||||
|
if (_glfw.x11.display != display)
|
||||||
|
return 0;
|
||||||
|
|
||||||
_glfw.x11.errorCode = event->error_code;
|
_glfw.x11.errorCode = event->error_code;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
27
glfw/x11_monitor.c
vendored
27
glfw/x11_monitor.c
vendored
@@ -241,7 +241,8 @@ void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
||||||
|
|
||||||
@@ -289,7 +290,8 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
|
|||||||
if (monitor->x11.oldMode == None)
|
if (monitor->x11.oldMode == None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
XRRSetCrtcConfig(_glfw.x11.display,
|
XRRSetCrtcConfig(_glfw.x11.display,
|
||||||
@@ -321,9 +323,10 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
|
XRRScreenResources* sr =
|
||||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
if (ci)
|
if (ci)
|
||||||
{
|
{
|
||||||
if (xpos)
|
if (xpos)
|
||||||
@@ -333,6 +336,7 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
|
|
||||||
XRRFreeCrtcInfo(ci);
|
XRRFreeCrtcInfo(ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRFreeScreenResources(sr);
|
XRRFreeScreenResources(sr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,8 +356,8 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos
|
|||||||
|
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
|
XRRScreenResources* sr =
|
||||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
areaX = ci->x;
|
areaX = ci->x;
|
||||||
@@ -446,7 +450,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
|
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
||||||
|
|
||||||
@@ -493,17 +498,19 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
|
XRRScreenResources* sr =
|
||||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
if (ci) {
|
if (ci)
|
||||||
|
{
|
||||||
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
||||||
if (mi) // mi can be NULL if the monitor has been disconnected
|
if (mi) // mi can be NULL if the monitor has been disconnected
|
||||||
*mode = vidmodeFromModeInfo(mi, ci);
|
*mode = vidmodeFromModeInfo(mi, ci);
|
||||||
|
|
||||||
XRRFreeCrtcInfo(ci);
|
XRRFreeCrtcInfo(ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRFreeScreenResources(sr);
|
XRRFreeScreenResources(sr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
134
glfw/x11_window.c
vendored
134
glfw/x11_window.c
vendored
@@ -455,22 +455,41 @@ static void updateCursorImage(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable XI2 raw mouse motion events
|
||||||
|
//
|
||||||
|
static void enableRawMouseMotion(_GLFWwindow* window UNUSED)
|
||||||
|
{
|
||||||
|
XIEventMask em;
|
||||||
|
unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
|
||||||
|
|
||||||
|
em.deviceid = XIAllMasterDevices;
|
||||||
|
em.mask_len = sizeof(mask);
|
||||||
|
em.mask = mask;
|
||||||
|
XISetMask(mask, XI_RawMotion);
|
||||||
|
|
||||||
|
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable XI2 raw mouse motion events
|
||||||
|
//
|
||||||
|
static void disableRawMouseMotion(_GLFWwindow* window UNUSED)
|
||||||
|
{
|
||||||
|
XIEventMask em;
|
||||||
|
unsigned char mask[] = { 0 };
|
||||||
|
|
||||||
|
em.deviceid = XIAllMasterDevices;
|
||||||
|
em.mask_len = sizeof(mask);
|
||||||
|
em.mask = mask;
|
||||||
|
|
||||||
|
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply disabled cursor mode to a focused window
|
// Apply disabled cursor mode to a focused window
|
||||||
//
|
//
|
||||||
static void disableCursor(_GLFWwindow* window)
|
static void disableCursor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.xi.available)
|
if (window->rawMouseMotion)
|
||||||
{
|
enableRawMouseMotion(window);
|
||||||
XIEventMask em;
|
|
||||||
unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
|
|
||||||
|
|
||||||
em.deviceid = XIAllMasterDevices;
|
|
||||||
em.mask_len = sizeof(mask);
|
|
||||||
em.mask = mask;
|
|
||||||
XISetMask(mask, XI_RawMotion);
|
|
||||||
|
|
||||||
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.x11.disabledCursorWindow = window;
|
_glfw.x11.disabledCursorWindow = window;
|
||||||
_glfwPlatformGetCursorPos(window,
|
_glfwPlatformGetCursorPos(window,
|
||||||
@@ -490,17 +509,8 @@ static void disableCursor(_GLFWwindow* window)
|
|||||||
//
|
//
|
||||||
static void enableCursor(_GLFWwindow* window)
|
static void enableCursor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.xi.available)
|
if (window->rawMouseMotion)
|
||||||
{
|
disableRawMouseMotion(window);
|
||||||
XIEventMask em;
|
|
||||||
unsigned char mask[] = { 0 };
|
|
||||||
|
|
||||||
em.deviceid = XIAllMasterDevices;
|
|
||||||
em.mask_len = sizeof(mask);
|
|
||||||
em.mask = mask;
|
|
||||||
|
|
||||||
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.x11.disabledCursorWindow = NULL;
|
_glfw.x11.disabledCursorWindow = NULL;
|
||||||
XUngrabPointer(_glfw.x11.display, CurrentTime);
|
XUngrabPointer(_glfw.x11.display, CurrentTime);
|
||||||
@@ -1075,6 +1085,21 @@ static void onConfigChange(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_atom_names(Atom *atoms, int count, char **atom_names) {
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
|
XGetAtomNames(_glfw.x11.display, atoms, count, atom_names);
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
if (_glfw.x11.errorCode != Success) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
|
atom_names[i] = XGetAtomName(_glfw.x11.display, atoms[i]);
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
if (_glfw.x11.errorCode != Success) atom_names[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Process the specified X event
|
// Process the specified X event
|
||||||
//
|
//
|
||||||
static void processEvent(XEvent *event)
|
static void processEvent(XEvent *event)
|
||||||
@@ -1107,6 +1132,7 @@ static void processEvent(XEvent *event)
|
|||||||
_GLFWwindow* window = _glfw.x11.disabledCursorWindow;
|
_GLFWwindow* window = _glfw.x11.disabledCursorWindow;
|
||||||
|
|
||||||
if (window &&
|
if (window &&
|
||||||
|
window->rawMouseMotion &&
|
||||||
event->xcookie.extension == _glfw.x11.xi.majorOpcode &&
|
event->xcookie.extension == _glfw.x11.xi.majorOpcode &&
|
||||||
XGetEventData(_glfw.x11.display, &event->xcookie) &&
|
XGetEventData(_glfw.x11.display, &event->xcookie) &&
|
||||||
event->xcookie.evtype == XI_RawMotion)
|
event->xcookie.evtype == XI_RawMotion)
|
||||||
@@ -1151,8 +1177,11 @@ static void processEvent(XEvent *event)
|
|||||||
{
|
{
|
||||||
XkbEvent *kb_event = (XkbEvent*)event;
|
XkbEvent *kb_event = (XkbEvent*)event;
|
||||||
switch(kb_event->any.xkb_type) {
|
switch(kb_event->any.xkb_type) {
|
||||||
case XkbNewKeyboardNotify:
|
case XkbNewKeyboardNotify: {
|
||||||
if(!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return;
|
int32_t old_id = _glfw.x11.xkb.keyboard_device_id;
|
||||||
|
if (!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return;
|
||||||
|
if (old_id != _glfw.x11.xkb.keyboard_device_id) keymap_dirty = true;
|
||||||
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case XkbMapNotify:
|
case XkbMapNotify:
|
||||||
{
|
{
|
||||||
@@ -1250,13 +1279,13 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
// Modern X provides scroll events as mouse button presses
|
// Modern X provides scroll events as mouse button presses
|
||||||
else if (event->xbutton.button == Button4)
|
else if (event->xbutton.button == Button4)
|
||||||
_glfwInputScroll(window, 0.0, 1.0, 0);
|
_glfwInputScroll(window, 0.0, 1.0, 0, mods);
|
||||||
else if (event->xbutton.button == Button5)
|
else if (event->xbutton.button == Button5)
|
||||||
_glfwInputScroll(window, 0.0, -1.0, 0);
|
_glfwInputScroll(window, 0.0, -1.0, 0, mods);
|
||||||
else if (event->xbutton.button == Button6)
|
else if (event->xbutton.button == Button6)
|
||||||
_glfwInputScroll(window, 1.0, 0.0, 0);
|
_glfwInputScroll(window, 1.0, 0.0, 0, mods);
|
||||||
else if (event->xbutton.button == Button7)
|
else if (event->xbutton.button == Button7)
|
||||||
_glfwInputScroll(window, -1.0, 0.0, 0);
|
_glfwInputScroll(window, -1.0, 0.0, 0, mods);
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1348,7 +1377,7 @@ static void processEvent(XEvent *event)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.disabledCursorWindow != window)
|
if (_glfw.x11.disabledCursorWindow != window)
|
||||||
return;
|
return;
|
||||||
if (_glfw.x11.xi.available)
|
if (window->rawMouseMotion)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int dx = x - window->x11.lastCursorPosX;
|
const int dx = x - window->x11.lastCursorPosX;
|
||||||
@@ -1393,12 +1422,18 @@ static void processEvent(XEvent *event)
|
|||||||
if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
|
if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
|
||||||
{
|
{
|
||||||
Window dummy;
|
Window dummy;
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
XTranslateCoordinates(_glfw.x11.display,
|
XTranslateCoordinates(_glfw.x11.display,
|
||||||
window->x11.parent,
|
window->x11.parent,
|
||||||
_glfw.x11.root,
|
_glfw.x11.root,
|
||||||
xpos, ypos,
|
xpos, ypos,
|
||||||
&xpos, &ypos,
|
&xpos, &ypos,
|
||||||
&dummy);
|
&dummy);
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
if (_glfw.x11.errorCode != Success) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to translate ConfigureNotiy co-ords for reparented window");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
|
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
|
||||||
@@ -1474,7 +1509,7 @@ static void processEvent(XEvent *event)
|
|||||||
}
|
}
|
||||||
char **atom_names = calloc(count, sizeof(char**));
|
char **atom_names = calloc(count, sizeof(char**));
|
||||||
if (atom_names) {
|
if (atom_names) {
|
||||||
XGetAtomNames(_glfw.x11.display, formats, count, atom_names);
|
get_atom_names(formats, count, atom_names);
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@@ -1535,17 +1570,21 @@ static void processEvent(XEvent *event)
|
|||||||
const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
|
const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
|
||||||
const int yabs = (event->xclient.data.l[2]) & 0xffff;
|
const int yabs = (event->xclient.data.l[2]) & 0xffff;
|
||||||
Window dummy;
|
Window dummy;
|
||||||
int xpos, ypos;
|
int xpos = 0, ypos = 0;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
XTranslateCoordinates(_glfw.x11.display,
|
XTranslateCoordinates(_glfw.x11.display,
|
||||||
_glfw.x11.root,
|
_glfw.x11.root,
|
||||||
window->x11.handle,
|
window->x11.handle,
|
||||||
xabs, yabs,
|
xabs, yabs,
|
||||||
&xpos, &ypos,
|
&xpos, &ypos,
|
||||||
&dummy);
|
&dummy);
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
if (_glfw.x11.errorCode != Success)
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to get DND event position");
|
||||||
|
|
||||||
_glfwInputCursorPos(window, xpos, ypos);
|
_glfwInputCursorPos(window, xpos, ypos);
|
||||||
|
|
||||||
@@ -1800,7 +1839,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
Visual* visual;
|
Visual* visual = NULL;
|
||||||
int depth;
|
int depth;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
@@ -1826,8 +1865,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_NO_API ||
|
if (!visual)
|
||||||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
|
||||||
{
|
{
|
||||||
visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
|
visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
|
||||||
depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
|
depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
|
||||||
@@ -1973,10 +2011,14 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
|||||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
{
|
{
|
||||||
Window dummy;
|
Window dummy;
|
||||||
int x, y;
|
int x = 0, y = 0;
|
||||||
|
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,
|
XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,
|
||||||
0, 0, &x, &y, &dummy);
|
0, 0, &x, &y, &dummy);
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
if (_glfw.x11.errorCode != Success)
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to get window position");
|
||||||
|
|
||||||
if (xpos)
|
if (xpos)
|
||||||
*xpos = x;
|
*xpos = x;
|
||||||
@@ -2375,6 +2417,7 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
return maximized;
|
return maximized;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned long count =
|
const unsigned long count =
|
||||||
_glfwGetWindowPropertyX11(window->x11.handle,
|
_glfwGetWindowPropertyX11(window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
@@ -2601,6 +2644,25 @@ _glfwDispatchX11Events(void) {
|
|||||||
return dispatched;
|
return dispatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, bool enabled)
|
||||||
|
{
|
||||||
|
if (!_glfw.x11.xi.available)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_glfw.x11.disabledCursorWindow != window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
enableRawMouseMotion(window);
|
||||||
|
else
|
||||||
|
disableRawMouseMotion(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _glfwPlatformRawMouseMotionSupported(void)
|
||||||
|
{
|
||||||
|
return _glfw.x11.xi.available;
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
_glfwDispatchX11Events();
|
_glfwDispatchX11Events();
|
||||||
|
|||||||
3
glfw/xkb_glfw.c
vendored
3
glfw/xkb_glfw.c
vendored
@@ -620,6 +620,9 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t
|
|||||||
}
|
}
|
||||||
if (key_text[0]) { debug("%s: %s ", text_type, key_text); }
|
if (key_text[0]) { debug("%s: %s ", text_type, key_text); }
|
||||||
}
|
}
|
||||||
|
if (xkb_sym == XKB_KEY_ISO_First_Group || xkb_sym == XKB_KEY_ISO_Last_Group || xkb_sym == XKB_KEY_ISO_Next_Group || xkb_sym == XKB_KEY_ISO_Prev_Group || xkb_sym == XKB_KEY_Mode_switch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int glfw_sym = glfw_key_for_sym(xkb_sym);
|
int glfw_sym = glfw_key_for_sym(xkb_sym);
|
||||||
bool is_fallback = false;
|
bool is_fallback = false;
|
||||||
if (glfw_sym == GLFW_KEY_UNKNOWN && !key_text[0]) {
|
if (glfw_sym == GLFW_KEY_UNKNOWN && !key_text[0]) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from typing import TYPE_CHECKING, List, Optional, Tuple
|
from typing import TYPE_CHECKING, List, Optional, Tuple
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ from kitty.constants import cache_dir
|
|||||||
from kitty.typing import BossType
|
from kitty.typing import BossType
|
||||||
|
|
||||||
from ..tui.handler import result_handler
|
from ..tui.handler import result_handler
|
||||||
from ..tui.operations import alternate_screen, styled
|
from ..tui.operations import alternate_screen, set_cursor_visible, styled
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import readline
|
import readline
|
||||||
@@ -69,7 +70,7 @@ class HistoryCompleter:
|
|||||||
def option_text() -> str:
|
def option_text() -> str:
|
||||||
return '''\
|
return '''\
|
||||||
--type -t
|
--type -t
|
||||||
choices=line
|
choices=line,yesno
|
||||||
default=line
|
default=line
|
||||||
Type of input. Defaults to asking for a line of text.
|
Type of input. Defaults to asking for a line of text.
|
||||||
|
|
||||||
@@ -96,14 +97,30 @@ class Response(TypedDict):
|
|||||||
response: Optional[str]
|
response: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
def yesno(cli_opts: AskCLIOptions, items: List[str]) -> Response:
|
||||||
|
import tty
|
||||||
|
with alternate_screen():
|
||||||
|
if cli_opts.message:
|
||||||
|
print(styled(cli_opts.message, bold=True))
|
||||||
|
print()
|
||||||
|
print(' ', styled('Y', fg='green') + 'es', ' ', styled('N', fg='red') + 'o', set_cursor_visible(False))
|
||||||
|
sys.stdout.flush()
|
||||||
|
tty.setraw(sys.stdin.fileno())
|
||||||
|
try:
|
||||||
|
response = sys.stdin.buffer.read(1)
|
||||||
|
yes = response in (b'y', b'Y', b'\r', b'\n' b' ')
|
||||||
|
return {'items': items, 'response': 'y' if yes else 'n'}
|
||||||
|
finally:
|
||||||
|
sys.stdout.write(set_cursor_visible(True))
|
||||||
|
tty.setcbreak(sys.stdin.fileno())
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
def main(args: List[str]) -> Response:
|
def main(args: List[str]) -> Response:
|
||||||
# For some reason importing readline in a key handler in the main kitty process
|
# For some reason importing readline in a key handler in the main kitty process
|
||||||
# causes a crash of the python interpreter, probably because of some global
|
# causes a crash of the python interpreter, probably because of some global
|
||||||
# lock
|
# lock
|
||||||
global readline
|
global readline
|
||||||
import readline as rl
|
|
||||||
readline = rl
|
|
||||||
from kitty.shell import init_readline
|
|
||||||
msg = 'Ask the user for input'
|
msg = 'Ask the user for input'
|
||||||
try:
|
try:
|
||||||
cli_opts, items = parse_args(args[1:], option_text, '', msg, 'kitty ask', result_class=AskCLIOptions)
|
cli_opts, items = parse_args(args[1:], option_text, '', msg, 'kitty ask', result_class=AskCLIOptions)
|
||||||
@@ -113,6 +130,12 @@ def main(args: List[str]) -> Response:
|
|||||||
input('Press enter to quit...')
|
input('Press enter to quit...')
|
||||||
raise SystemExit(e.code)
|
raise SystemExit(e.code)
|
||||||
|
|
||||||
|
if cli_opts.type == 'yesno':
|
||||||
|
return yesno(cli_opts, items)
|
||||||
|
|
||||||
|
import readline as rl
|
||||||
|
readline = rl
|
||||||
|
from kitty.shell import init_readline
|
||||||
init_readline(readline)
|
init_readline(readline)
|
||||||
response = None
|
response = None
|
||||||
|
|
||||||
@@ -134,7 +157,6 @@ def handle_result(args: List[str], data: Response, target_window_id: int, boss:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
|
||||||
ans = main(sys.argv)
|
ans = main(sys.argv)
|
||||||
if ans:
|
if ans:
|
||||||
print(ans)
|
print(ans)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from .config_data import all_options, type_convert
|
|||||||
|
|
||||||
defaults: Optional[DiffOptions] = None
|
defaults: Optional[DiffOptions] = None
|
||||||
|
|
||||||
formats = {
|
formats: Dict[str, str] = {
|
||||||
'title': '',
|
'title': '',
|
||||||
'margin': '',
|
'margin': '',
|
||||||
'text': '',
|
'text': '',
|
||||||
@@ -35,6 +35,7 @@ def set_formats(opts: DiffOptions) -> None:
|
|||||||
formats['added'] = '48' + color_as_sgr(opts.added_bg)
|
formats['added'] = '48' + color_as_sgr(opts.added_bg)
|
||||||
formats['removed'] = '48' + color_as_sgr(opts.removed_bg)
|
formats['removed'] = '48' + color_as_sgr(opts.removed_bg)
|
||||||
formats['filler'] = '48' + color_as_sgr(opts.filler_bg)
|
formats['filler'] = '48' + color_as_sgr(opts.filler_bg)
|
||||||
|
formats['margin_filler'] = '48' + color_as_sgr(opts.margin_filler_bg or opts.filler_bg)
|
||||||
formats['hunk_margin'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.hunk_margin_bg)
|
formats['hunk_margin'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.hunk_margin_bg)
|
||||||
formats['hunk'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.hunk_bg)
|
formats['hunk'] = '38' + color_as_sgr(opts.margin_fg) + ';48' + color_as_sgr(opts.hunk_bg)
|
||||||
formats['removed_highlight'] = '48' + color_as_sgr(opts.highlight_removed_bg)
|
formats['removed_highlight'] = '48' + color_as_sgr(opts.highlight_removed_bg)
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ from gettext import gettext as _
|
|||||||
from typing import Any, Dict, Sequence, Union
|
from typing import Any, Dict, Sequence, Union
|
||||||
|
|
||||||
from kitty.conf.definition import Option, Shortcut, option_func
|
from kitty.conf.definition import Option, Shortcut, option_func
|
||||||
from kitty.conf.utils import positive_int, python_string, to_color
|
from kitty.conf.utils import (
|
||||||
|
positive_int, python_string, to_color, to_color_or_none
|
||||||
|
)
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@@ -78,6 +80,8 @@ c('highlight_added_bg', '#acf2bd')
|
|||||||
c('added_margin_bg', '#cdffd8')
|
c('added_margin_bg', '#cdffd8')
|
||||||
|
|
||||||
c('filler_bg', '#fafbfc', long_text=_('Filler (empty) line background'))
|
c('filler_bg', '#fafbfc', long_text=_('Filler (empty) line background'))
|
||||||
|
c('margin_filler_bg', 'none', option_type=to_color_or_none, long_text=_(
|
||||||
|
'Filler (empty) line background in margins, defaults to the filler background'))
|
||||||
|
|
||||||
c('hunk_margin_bg', '#dbedff', long_text=_('Hunk header colors'))
|
c('hunk_margin_bg', '#dbedff', long_text=_('Hunk header colors'))
|
||||||
c('hunk_bg', '#f1f8ff')
|
c('hunk_bg', '#f1f8ff')
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from pygments.formatter import Formatter # type: ignore
|
|||||||
from pygments.lexers import get_lexer_for_filename # type: ignore
|
from pygments.lexers import get_lexer_for_filename # type: ignore
|
||||||
from pygments.util import ClassNotFound # type: ignore
|
from pygments.util import ClassNotFound # type: ignore
|
||||||
|
|
||||||
|
from kitty.multiprocessing import get_process_pool_executor
|
||||||
from kitty.rgb import color_as_sgr, parse_sharp
|
from kitty.rgb import color_as_sgr, parse_sharp
|
||||||
|
|
||||||
from .collect import Collection, Segment, data_for_path, lines_for_path
|
from .collect import Collection, Segment, data_for_path, lines_for_path
|
||||||
@@ -139,7 +140,7 @@ def highlight_for_diff(path: str, aliases: Dict[str, str]) -> DiffHighlight:
|
|||||||
def highlight_collection(collection: Collection, aliases: Optional[Dict[str, str]] = None) -> Union[str, Dict[str, DiffHighlight]]:
|
def highlight_collection(collection: Collection, aliases: Optional[Dict[str, str]] = None) -> Union[str, Dict[str, DiffHighlight]]:
|
||||||
jobs = {}
|
jobs = {}
|
||||||
ans: Dict[str, DiffHighlight] = {}
|
ans: Dict[str, DiffHighlight] = {}
|
||||||
with concurrent.futures.ProcessPoolExecutor(max_workers=os.cpu_count()) as executor:
|
with get_process_pool_executor(prefer_fork=True) as executor:
|
||||||
for path, item_type, other_path in collection:
|
for path, item_type, other_path in collection:
|
||||||
if item_type != 'rename':
|
if item_type != 'rename':
|
||||||
for p in (path, other_path):
|
for p in (path, other_path):
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
has_highlighter = False
|
has_highlighter = False
|
||||||
|
|
||||||
|
def highlight_collection(collection: 'Collection', aliases: Optional[Dict[str, str]] = None) -> Union[str, Dict[str, 'DiffHighlight']]:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
INITIALIZING, COLLECTED, DIFFED, COMMAND, MESSAGE = range(5)
|
INITIALIZING, COLLECTED, DIFFED, COMMAND, MESSAGE = range(5)
|
||||||
ESCAPE = K['ESCAPE']
|
ESCAPE = K['ESCAPE']
|
||||||
@@ -110,13 +113,13 @@ class DiffHandler(Handler):
|
|||||||
return self.scroll_lines(amt)
|
return self.scroll_lines(amt)
|
||||||
if func == 'change_context':
|
if func == 'change_context':
|
||||||
new_ctx = self.current_context_count
|
new_ctx = self.current_context_count
|
||||||
to = int(args[0])
|
to = args[0]
|
||||||
if to == 'all':
|
if to == 'all':
|
||||||
new_ctx = 100000
|
new_ctx = 100000
|
||||||
elif to == 'default':
|
elif to == 'default':
|
||||||
new_ctx = self.original_context_count
|
new_ctx = self.original_context_count
|
||||||
else:
|
else:
|
||||||
new_ctx += to
|
new_ctx += int(to)
|
||||||
return self.change_context_count(new_ctx)
|
return self.change_context_count(new_ctx)
|
||||||
if func == 'start_search':
|
if func == 'start_search':
|
||||||
self.start_search(bool(args[0]), bool(args[1]))
|
self.start_search(bool(args[0]), bool(args[1]))
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ removed_format = format_func('removed')
|
|||||||
removed_margin_format = format_func('removed_margin')
|
removed_margin_format = format_func('removed_margin')
|
||||||
added_margin_format = format_func('added_margin')
|
added_margin_format = format_func('added_margin')
|
||||||
filler_format = format_func('filler')
|
filler_format = format_func('filler')
|
||||||
|
margin_filler_format = format_func('margin_filler')
|
||||||
hunk_margin_format = format_func('hunk_margin')
|
hunk_margin_format = format_func('hunk_margin')
|
||||||
hunk_format = format_func('hunk')
|
hunk_format = format_func('hunk')
|
||||||
highlight_map = {'remove': ('removed_highlight', 'removed'), 'add': ('added_highlight', 'added')}
|
highlight_map = {'remove': ('removed_highlight', 'removed'), 'add': ('added_highlight', 'added')}
|
||||||
@@ -214,7 +215,7 @@ def split_with_highlights(line: str, width: int, highlights: List, bg_highlight:
|
|||||||
return _split_with_highlights(line, truncate_pts, highlights, bg_highlight)
|
return _split_with_highlights(line, truncate_pts, highlights, bg_highlight)
|
||||||
|
|
||||||
|
|
||||||
margin_bg_map = {'filler': filler_format, 'remove': removed_margin_format, 'add': added_margin_format, 'context': margin_format}
|
margin_bg_map = {'filler': margin_filler_format, 'remove': removed_margin_format, 'add': added_margin_format, 'context': margin_format}
|
||||||
text_bg_map = {'filler': filler_format, 'remove': removed_format, 'add': added_format, 'context': text_format}
|
text_bg_map = {'filler': filler_format, 'remove': removed_format, 'add': added_format, 'context': text_format}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from kitty.key_encoding import (
|
|||||||
KeyEvent, backspace_key, enter_key, key_defs as K
|
KeyEvent, backspace_key, enter_key, key_defs as K
|
||||||
)
|
)
|
||||||
from kitty.typing import BossType, KittyCommonOpts
|
from kitty.typing import BossType, KittyCommonOpts
|
||||||
from kitty.utils import ScreenSize, screen_size_function
|
from kitty.utils import ScreenSize, screen_size_function, set_primary_selection
|
||||||
|
|
||||||
from ..tui.handler import Handler, result_handler
|
from ..tui.handler import Handler, result_handler
|
||||||
from ..tui.loop import Loop
|
from ..tui.loop import Loop
|
||||||
@@ -315,7 +315,7 @@ def functions_for(args: HintsCLIOptions) -> Tuple[str, List[PostprocessorFunc]]:
|
|||||||
pattern = '[0-9a-f]{7,128}'
|
pattern = '[0-9a-f]{7,128}'
|
||||||
elif args.type == 'word':
|
elif args.type == 'word':
|
||||||
chars = args.word_characters
|
chars = args.word_characters
|
||||||
if not chars:
|
if chars is None:
|
||||||
chars = kitty_common_opts()['select_by_word_characters']
|
chars = kitty_common_opts()['select_by_word_characters']
|
||||||
pattern = r'(?u)[{}\w]{{{},}}'.format(escape(chars), args.minimum_match_length)
|
pattern = r'(?u)[{}\w]{{{},}}'.format(escape(chars), args.minimum_match_length)
|
||||||
post_processors.extend((brackets, quotes))
|
post_processors.extend((brackets, quotes))
|
||||||
@@ -349,7 +349,7 @@ def parse_input(text: str) -> str:
|
|||||||
def linenum_marks(text: str, args: HintsCLIOptions, Mark: Type[Mark], extra_cli_args: Sequence[str], *a: Any) -> Generator[Mark, None, None]:
|
def linenum_marks(text: str, args: HintsCLIOptions, Mark: Type[Mark], extra_cli_args: Sequence[str], *a: Any) -> Generator[Mark, None, None]:
|
||||||
regex = args.regex
|
regex = args.regex
|
||||||
if regex == DEFAULT_REGEX:
|
if regex == DEFAULT_REGEX:
|
||||||
regex = r'(?P<path>(?:\S*/\S+)|(?:\S+[.][a-zA-Z0-9]{2,7})):(?P<line>\d+)'
|
regex = r'(?P<path>(?:\S*/\S+?)|(?:\S+[.][a-zA-Z0-9]{2,7})):(?P<line>\d+)'
|
||||||
yield from mark(regex, [brackets, quotes], text, args)
|
yield from mark(regex, [brackets, quotes], text, args)
|
||||||
|
|
||||||
|
|
||||||
@@ -360,12 +360,8 @@ def load_custom_processor(customize_processing: str) -> Any:
|
|||||||
return {k: getattr(m, k) for k in dir(m)}
|
return {k: getattr(m, k) for k in dir(m)}
|
||||||
if customize_processing == '::linenum::':
|
if customize_processing == '::linenum::':
|
||||||
return {'mark': linenum_marks, 'handle_result': linenum_handle_result}
|
return {'mark': linenum_marks, 'handle_result': linenum_handle_result}
|
||||||
from kitty.constants import config_dir
|
from kitty.constants import resolve_custom_file
|
||||||
customize_processing = os.path.expandvars(os.path.expanduser(customize_processing))
|
custom_path = resolve_custom_file(customize_processing)
|
||||||
if os.path.isabs(customize_processing):
|
|
||||||
custom_path = customize_processing
|
|
||||||
else:
|
|
||||||
custom_path = os.path.join(config_dir, customize_processing)
|
|
||||||
import runpy
|
import runpy
|
||||||
return runpy.run_path(custom_path, run_name='__main__')
|
return runpy.run_path(custom_path, run_name='__main__')
|
||||||
|
|
||||||
@@ -413,18 +409,21 @@ OPTIONS = r'''
|
|||||||
type=list
|
type=list
|
||||||
What program to use to open matched text. Defaults to the default open program
|
What program to use to open matched text. Defaults to the default open program
|
||||||
for the operating system. Use a value of :file:`-` to paste the match into the
|
for the operating system. Use a value of :file:`-` to paste the match into the
|
||||||
terminal window instead. A value of :file:`@` will copy the match to the clipboard.
|
terminal window instead. A value of :file:`@` will copy the match to the
|
||||||
A value of :file:`default` will run the default open program. Can be specified
|
clipboard. A value of :file:`*` will copy the match to the primary selection
|
||||||
multiple times to run multiple programs.
|
(on systems that support primary selections). A value of :file:`default` will
|
||||||
|
run the default open program. Can be specified multiple times to run multiple
|
||||||
|
programs.
|
||||||
|
|
||||||
|
|
||||||
--type
|
--type
|
||||||
default=url
|
default=url
|
||||||
choices=url,regex,path,line,hash,word,linenum
|
choices=url,regex,path,line,hash,word,linenum
|
||||||
The type of text to search for. A value of :code:`linenum` looks for error messages
|
The type of text to search for. A value of :code:`linenum` is special, it looks
|
||||||
using the pattern specified with :option:`--regex`, which must have the named groups,
|
for error messages using the pattern specified with :option:`--regex`, which
|
||||||
path and line. If not specified, will look for :code:`path:line`.
|
must have the named groups, :code:`path` and :code:`line`. If not specified,
|
||||||
The :option:`--linenum-action` option controls what to do with the selected error message.
|
will look for :code:`path:line`. The :option:`--linenum-action` option
|
||||||
|
controls what to do with the selected error message, other options are ignored.
|
||||||
|
|
||||||
|
|
||||||
--regex
|
--regex
|
||||||
@@ -629,6 +628,8 @@ def handle_result(args: List[str], data: Dict[str, Any], target_window_id: int,
|
|||||||
w.paste(joined_text())
|
w.paste(joined_text())
|
||||||
elif program == '@':
|
elif program == '@':
|
||||||
set_clipboard_string(joined_text())
|
set_clipboard_string(joined_text())
|
||||||
|
elif program == '*':
|
||||||
|
set_primary_selection(joined_text())
|
||||||
else:
|
else:
|
||||||
cwd = None
|
cwd = None
|
||||||
w = boss.window_id_map.get(target_window_id)
|
w = boss.window_id_map.get(target_window_id)
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import contextlib
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import socket
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import zlib
|
import zlib
|
||||||
@@ -339,6 +341,16 @@ help_text = (
|
|||||||
usage = 'image-file-or-url-or-directory ...'
|
usage = 'image-file-or-url-or-directory ...'
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def socket_timeout(seconds: int) -> Generator[None, None, None]:
|
||||||
|
old = socket.getdefaulttimeout()
|
||||||
|
socket.setdefaulttimeout(seconds)
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
socket.setdefaulttimeout(old)
|
||||||
|
|
||||||
|
|
||||||
def process_single_item(
|
def process_single_item(
|
||||||
item: Union[bytes, str],
|
item: Union[bytes, str],
|
||||||
args: IcatCLIOptions,
|
args: IcatCLIOptions,
|
||||||
@@ -358,7 +370,8 @@ def process_single_item(
|
|||||||
from urllib.request import urlretrieve
|
from urllib.request import urlretrieve
|
||||||
with NamedTemporaryFile(prefix='url-image-data-', delete=False) as tf:
|
with NamedTemporaryFile(prefix='url-image-data-', delete=False) as tf:
|
||||||
try:
|
try:
|
||||||
urlretrieve(item, filename=tf.name)
|
with socket_timeout(30):
|
||||||
|
urlretrieve(item, filename=tf.name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise SystemExit('Failed to download image at URL: {} with error: {}'.format(item, e))
|
raise SystemExit('Failed to download image at URL: {} with error: {}'.format(item, e))
|
||||||
item = tf.name
|
item = tf.name
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ def convert(
|
|||||||
if scaled or width > available_width or height > available_height:
|
if scaled or width > available_width or height > available_height:
|
||||||
width, height = fit_image(width, height, available_width, available_height)
|
width, height = fit_image(width, height, available_width, available_height)
|
||||||
cmd += ['-resize', '{}x{}!'.format(width, height)]
|
cmd += ['-resize', '{}x{}!'.format(width, height)]
|
||||||
|
cmd += ['-depth', '8']
|
||||||
with NamedTemporaryFile(prefix='icat-', suffix='.' + m.mode, delete=False, dir=tdir) as outfile:
|
with NamedTemporaryFile(prefix='icat-', suffix='.' + m.mode, delete=False, dir=tdir) as outfile:
|
||||||
run_imagemagick(path, cmd + [outfile.name])
|
run_imagemagick(path, cmd + [outfile.name])
|
||||||
# ImageMagick sometimes generated rgba images smaller than the specified
|
# ImageMagick sometimes generated rgba images smaller than the specified
|
||||||
|
|||||||
56991
kittens/unicode_input/names.h
generated
56991
kittens/unicode_input/names.h
generated
File diff suppressed because one or more lines are too long
@@ -4,16 +4,16 @@
|
|||||||
|
|
||||||
from enum import IntFlag
|
from enum import IntFlag
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from typing import List, Optional, Sequence, Tuple
|
from typing import Sequence, Tuple
|
||||||
|
|
||||||
from .constants import WindowGeometry
|
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
BORDERS_PROGRAM, add_borders_rect, compile_program, init_borders_program,
|
BORDERS_PROGRAM, add_borders_rect, compile_program, init_borders_program,
|
||||||
os_window_has_background_image
|
os_window_has_background_image
|
||||||
)
|
)
|
||||||
from .options_stub import Options
|
from .options_stub import Options
|
||||||
|
from .typing import LayoutType
|
||||||
from .utils import load_shaders
|
from .utils import load_shaders
|
||||||
from .typing import WindowType, LayoutType
|
from .window_list import WindowGroup, WindowList
|
||||||
|
|
||||||
|
|
||||||
class BorderColor(IntFlag):
|
class BorderColor(IntFlag):
|
||||||
@@ -22,22 +22,40 @@ class BorderColor(IntFlag):
|
|||||||
|
|
||||||
|
|
||||||
def vertical_edge(os_window_id: int, tab_id: int, color: int, width: int, top: int, bottom: int, left: int) -> None:
|
def vertical_edge(os_window_id: int, tab_id: int, color: int, width: int, top: int, bottom: int, left: int) -> None:
|
||||||
add_borders_rect(os_window_id, tab_id, left, top, left + width, bottom, color)
|
if width > 0:
|
||||||
|
add_borders_rect(os_window_id, tab_id, left, top, left + width, bottom, color)
|
||||||
|
|
||||||
|
|
||||||
def horizontal_edge(os_window_id: int, tab_id: int, color: int, height: int, left: int, right: int, top: int) -> None:
|
def horizontal_edge(os_window_id: int, tab_id: int, color: int, height: int, left: int, right: int, top: int) -> None:
|
||||||
add_borders_rect(os_window_id, tab_id, left, top, right, top + height, color)
|
if height > 0:
|
||||||
|
add_borders_rect(os_window_id, tab_id, left, top, right, top + height, color)
|
||||||
|
|
||||||
|
|
||||||
def draw_edges(os_window_id: int, tab_id: int, colors: Sequence[int], width: int, geometry: 'WindowGeometry', base_width: int = 0) -> None:
|
def draw_edges(os_window_id: int, tab_id: int, colors: Sequence[int], wg: WindowGroup, borders: bool = False) -> None:
|
||||||
left = geometry.left - (width + base_width)
|
geometry = wg.geometry
|
||||||
top = geometry.top - (width + base_width)
|
if geometry is None:
|
||||||
right = geometry.right + (width + base_width)
|
return
|
||||||
bottom = geometry.bottom + (width + base_width)
|
pl, pt = wg.effective_padding('left'), wg.effective_padding('top')
|
||||||
horizontal_edge(os_window_id, tab_id, colors[1], width, left, right, top)
|
pr, pb = wg.effective_padding('right'), wg.effective_padding('bottom')
|
||||||
horizontal_edge(os_window_id, tab_id, colors[3], width, left, right, geometry.bottom + base_width)
|
left = geometry.left - pl
|
||||||
vertical_edge(os_window_id, tab_id, colors[0], width, top, bottom, left)
|
top = geometry.top - pt
|
||||||
vertical_edge(os_window_id, tab_id, colors[2], width, top, bottom, geometry.right + base_width)
|
lr = geometry.right
|
||||||
|
right = lr + pr
|
||||||
|
bt = geometry.bottom
|
||||||
|
bottom = bt + pb
|
||||||
|
if borders:
|
||||||
|
width = wg.effective_border()
|
||||||
|
bt = bottom
|
||||||
|
lr = right
|
||||||
|
left -= width
|
||||||
|
top -= width
|
||||||
|
right += width
|
||||||
|
bottom += width
|
||||||
|
pl = pr = pb = pt = width
|
||||||
|
horizontal_edge(os_window_id, tab_id, colors[1], pt, left, right, top)
|
||||||
|
horizontal_edge(os_window_id, tab_id, colors[3], pb, left, right, bt)
|
||||||
|
vertical_edge(os_window_id, tab_id, colors[0], pl, top, bottom, left)
|
||||||
|
vertical_edge(os_window_id, tab_id, colors[2], pr, top, bottom, lr)
|
||||||
|
|
||||||
|
|
||||||
def load_borders_program() -> None:
|
def load_borders_program() -> None:
|
||||||
@@ -54,12 +72,9 @@ class Borders:
|
|||||||
|
|
||||||
def __call__(
|
def __call__(
|
||||||
self,
|
self,
|
||||||
windows: List[WindowType],
|
all_windows: WindowList,
|
||||||
active_window: Optional[WindowType],
|
|
||||||
current_layout: LayoutType,
|
current_layout: LayoutType,
|
||||||
extra_blank_rects: Sequence[Tuple[int, int, int, int]],
|
extra_blank_rects: Sequence[Tuple[int, int, int, int]],
|
||||||
padding_width: int,
|
|
||||||
border_width: int,
|
|
||||||
draw_window_borders: bool = True,
|
draw_window_borders: bool = True,
|
||||||
) -> None:
|
) -> None:
|
||||||
add_borders_rect(self.os_window_id, self.tab_id, 0, 0, 0, 0, BorderColor.default_bg)
|
add_borders_rect(self.os_window_id, self.tab_id, 0, 0, 0, 0, BorderColor.default_bg)
|
||||||
@@ -68,32 +83,34 @@ class Borders:
|
|||||||
for br in chain(current_layout.blank_rects, extra_blank_rects):
|
for br in chain(current_layout.blank_rects, extra_blank_rects):
|
||||||
left, top, right, bottom = br
|
left, top, right, bottom = br
|
||||||
add_borders_rect(self.os_window_id, self.tab_id, left, top, right, bottom, BorderColor.default_bg)
|
add_borders_rect(self.os_window_id, self.tab_id, left, top, right, bottom, BorderColor.default_bg)
|
||||||
bw, pw = border_width, padding_width
|
bw = 0
|
||||||
if bw + pw <= 0:
|
groups = tuple(all_windows.iter_all_layoutable_groups(only_visible=True))
|
||||||
return
|
if groups:
|
||||||
|
bw = groups[0].effective_border()
|
||||||
draw_borders = bw > 0 and draw_window_borders
|
draw_borders = bw > 0 and draw_window_borders
|
||||||
if draw_borders:
|
if draw_borders:
|
||||||
border_data = current_layout.resolve_borders(windows, active_window)
|
border_data = current_layout.resolve_borders(all_windows)
|
||||||
|
active_group = all_windows.active_group
|
||||||
|
|
||||||
for i, w in enumerate(windows):
|
for i, wg in enumerate(groups):
|
||||||
g = w.geometry
|
window_bg = wg.default_bg
|
||||||
window_bg = w.screen.color_profile.default_bg
|
|
||||||
window_bg = (window_bg << 8) | BorderColor.window_bg
|
window_bg = (window_bg << 8) | BorderColor.window_bg
|
||||||
if draw_borders:
|
if draw_borders:
|
||||||
# Draw the border rectangles
|
# Draw the border rectangles
|
||||||
if w is active_window and self.draw_active_borders:
|
if wg is active_group and self.draw_active_borders:
|
||||||
color = BorderColor.active
|
color = BorderColor.active
|
||||||
else:
|
else:
|
||||||
color = BorderColor.bell if w.needs_attention else BorderColor.inactive
|
color = BorderColor.bell if wg.needs_attention else BorderColor.inactive
|
||||||
colors = tuple(color if needed else window_bg for needed in next(border_data))
|
try:
|
||||||
draw_edges(
|
colors = tuple(color if needed else window_bg for needed in next(border_data))
|
||||||
self.os_window_id, self.tab_id, colors, bw, g, base_width=pw)
|
draw_edges(self.os_window_id, self.tab_id, colors, wg, borders=True)
|
||||||
if pw > 0 and not has_background_image:
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
if not has_background_image:
|
||||||
# Draw the background rectangles over the padding region
|
# Draw the background rectangles over the padding region
|
||||||
colors = (window_bg, window_bg, window_bg, window_bg)
|
colors = window_bg, window_bg, window_bg, window_bg
|
||||||
draw_edges(
|
draw_edges(self.os_window_id, self.tab_id, colors, wg)
|
||||||
self.os_window_id, self.tab_id, colors, pw, g)
|
|
||||||
|
|
||||||
color = BorderColor.inactive
|
color = BorderColor.inactive
|
||||||
for (left, top, right, bottom) in current_layout.window_independent_borders(windows, active_window):
|
for (left, top, right, bottom) in current_layout.window_independent_borders(all_windows):
|
||||||
add_borders_rect(self.os_window_id, self.tab_id, left, top, right, bottom, color)
|
add_borders_rect(self.os_window_id, self.tab_id, left, top, right, bottom, color)
|
||||||
|
|||||||
162
kitty/boss.py
162
kitty/boss.py
@@ -27,16 +27,18 @@ from .constants import (
|
|||||||
appname, config_dir, is_macos, kitty_exe, supports_primary_selection
|
appname, config_dir, is_macos, kitty_exe, supports_primary_selection
|
||||||
)
|
)
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
|
CLOSE_BEING_CONFIRMED, IMPERATIVE_CLOSE_REQUESTED, NO_CLOSE_REQUESTED,
|
||||||
ChildMonitor, background_opacity_of, change_background_opacity,
|
ChildMonitor, background_opacity_of, change_background_opacity,
|
||||||
change_os_window_state, cocoa_set_menubar_title, create_os_window,
|
change_os_window_state, cocoa_set_menubar_title, create_os_window,
|
||||||
current_os_window, destroy_global_data, focus_os_window,
|
current_application_quit_request, current_os_window, destroy_global_data,
|
||||||
get_clipboard_string, global_font_size, mark_os_window_for_close,
|
focus_os_window, get_clipboard_string, global_font_size,
|
||||||
os_window_font_size, patch_global_colors, safe_pipe, set_background_image,
|
mark_os_window_for_close, os_window_font_size, patch_global_colors,
|
||||||
set_boss, set_clipboard_string, set_in_sequence_mode, thread_write,
|
safe_pipe, set_application_quit_request, set_background_image, set_boss,
|
||||||
|
set_clipboard_string, set_in_sequence_mode, thread_write,
|
||||||
toggle_fullscreen, toggle_maximized
|
toggle_fullscreen, toggle_maximized
|
||||||
)
|
)
|
||||||
from .keys import get_shortcut, shortcut_matches
|
from .keys import get_shortcut, shortcut_matches
|
||||||
from .layout import set_layout_options
|
from .layout.base import set_layout_options
|
||||||
from .options_stub import Options
|
from .options_stub import Options
|
||||||
from .rgb import Color, color_from_int
|
from .rgb import Color, color_from_int
|
||||||
from .session import Session, create_sessions
|
from .session import Session, create_sessions
|
||||||
@@ -198,7 +200,7 @@ class Boss:
|
|||||||
os_window_id = create_os_window(
|
os_window_id = create_os_window(
|
||||||
initial_window_size_func(opts_for_size, self.cached_values),
|
initial_window_size_func(opts_for_size, self.cached_values),
|
||||||
pre_show_callback,
|
pre_show_callback,
|
||||||
appname, wname or self.args.name or wclass, wclass)
|
self.args.title or appname, wname or self.args.name or wclass, wclass)
|
||||||
tm = TabManager(os_window_id, self.opts, self.args, startup_session)
|
tm = TabManager(os_window_id, self.opts, self.args, startup_session)
|
||||||
self.os_window_map[os_window_id] = tm
|
self.os_window_map[os_window_id] = tm
|
||||||
return os_window_id
|
return os_window_id
|
||||||
@@ -304,10 +306,9 @@ class Boss:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def active_window_for_cwd(self) -> Optional[Window]:
|
def active_window_for_cwd(self) -> Optional[Window]:
|
||||||
w = self.active_window
|
t = self.active_tab
|
||||||
if w is not None and w.overlay_for is not None and w.overlay_for in self.window_id_map:
|
if t is not None:
|
||||||
w = self.window_id_map[w.overlay_for]
|
return t.active_window_for_cwd
|
||||||
return w
|
|
||||||
|
|
||||||
def new_os_window_with_cwd(self, *args: str) -> None:
|
def new_os_window_with_cwd(self, *args: str) -> None:
|
||||||
w = self.active_window_for_cwd
|
w = self.active_window_for_cwd
|
||||||
@@ -336,19 +337,41 @@ class Boss:
|
|||||||
if not getattr(err, 'hide_traceback', False):
|
if not getattr(err, 'hide_traceback', False):
|
||||||
response['tb'] = traceback.format_exc()
|
response['tb'] = traceback.format_exc()
|
||||||
else:
|
else:
|
||||||
response = {'ok': False, 'error': 'Remote control is disabled. Add allow_remote_control to your kitty.conf'}
|
no_response = False
|
||||||
|
try:
|
||||||
|
no_response = json.loads(cmd).get('no_response')
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if not no_response:
|
||||||
|
response = {'ok': False, 'error': 'Remote control is disabled. Add allow_remote_control to your kitty.conf'}
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def remote_control(self, *args: str) -> None:
|
||||||
|
from .remote_control import parse_rc_args
|
||||||
|
from .rc.base import command_for_name, parse_subcommand_cli, PayloadGetter
|
||||||
|
try:
|
||||||
|
global_opts, items = parse_rc_args(['@'] + list(args))
|
||||||
|
if not items:
|
||||||
|
return
|
||||||
|
cmd = items[0]
|
||||||
|
c = command_for_name(cmd)
|
||||||
|
opts, items = parse_subcommand_cli(c, items)
|
||||||
|
payload = c.message_to_kitty(global_opts, opts, items)
|
||||||
|
c.response_from_kitty(self, self.active_window, PayloadGetter(c, payload if isinstance(payload, dict) else {}))
|
||||||
|
except (Exception, SystemExit) as e:
|
||||||
|
self.show_error(_('remote_control mapping failed'), str(e))
|
||||||
|
|
||||||
def peer_message_received(self, msg_bytes: bytes) -> Optional[bytes]:
|
def peer_message_received(self, msg_bytes: bytes) -> Optional[bytes]:
|
||||||
msg = msg_bytes.decode('utf-8')
|
cmd_prefix = b'\x1bP@kitty-cmd'
|
||||||
cmd_prefix = '\x1bP@kitty-cmd'
|
terminator = b'\x1b\\'
|
||||||
if msg.startswith(cmd_prefix):
|
if msg_bytes.startswith(cmd_prefix) and msg_bytes.endswith(terminator):
|
||||||
cmd = msg[len(cmd_prefix):-2]
|
cmd = msg_bytes[len(cmd_prefix):-len(terminator)].decode('utf-8')
|
||||||
response = self._handle_remote_command(cmd, from_peer=True)
|
response = self._handle_remote_command(cmd, from_peer=True)
|
||||||
if response is None:
|
if response is None:
|
||||||
return None
|
return None
|
||||||
return (cmd_prefix + json.dumps(response) + '\x1b\\').encode('utf-8')
|
return cmd_prefix + json.dumps(response).encode('utf-8') + terminator
|
||||||
data = json.loads(msg)
|
|
||||||
|
data = json.loads(msg_bytes.decode('utf-8'))
|
||||||
if isinstance(data, dict) and data.get('cmd') == 'new_instance':
|
if isinstance(data, dict) and data.get('cmd') == 'new_instance':
|
||||||
from .cli_stub import CLIOptions
|
from .cli_stub import CLIOptions
|
||||||
startup_id = data.get('startup_id')
|
startup_id = data.get('startup_id')
|
||||||
@@ -534,7 +557,9 @@ class Boss:
|
|||||||
sz = os_window_font_size(os_window_id)
|
sz = os_window_font_size(os_window_id)
|
||||||
if sz:
|
if sz:
|
||||||
os_window_font_size(os_window_id, sz, True)
|
os_window_font_size(os_window_id, sz, True)
|
||||||
tm.update_dpi_based_sizes()
|
for tab in tm:
|
||||||
|
for window in tab:
|
||||||
|
window.on_dpi_change(sz)
|
||||||
tm.resize()
|
tm.resize()
|
||||||
|
|
||||||
def _set_os_window_background_opacity(self, os_window_id: int, opacity: float) -> None:
|
def _set_os_window_background_opacity(self, os_window_id: int, opacity: float) -> None:
|
||||||
@@ -700,6 +725,32 @@ class Boss:
|
|||||||
text = '\n'.join(parse_uri_list(text))
|
text = '\n'.join(parse_uri_list(text))
|
||||||
w.paste(text)
|
w.paste(text)
|
||||||
|
|
||||||
|
def close_os_window(self) -> None:
|
||||||
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None:
|
||||||
|
self.confirm_os_window_close(tm.os_window_id)
|
||||||
|
|
||||||
|
def confirm_os_window_close(self, os_window_id: int) -> None:
|
||||||
|
tm = self.os_window_map.get(os_window_id)
|
||||||
|
needs_confirmation = tm is not None and self.opts.confirm_os_window_close > 0 and tm.number_of_windows >= self.opts.confirm_os_window_close
|
||||||
|
if not needs_confirmation:
|
||||||
|
mark_os_window_for_close(os_window_id)
|
||||||
|
return
|
||||||
|
if tm is not None:
|
||||||
|
w = tm.active_window
|
||||||
|
self._run_kitten('ask', ['--type=yesno', '--message', _(
|
||||||
|
'Are you sure you want to close this OS window, it has {}'
|
||||||
|
' windows running?').format(tm.number_of_windows)],
|
||||||
|
window=w,
|
||||||
|
custom_callback=partial(self.handle_close_os_window_confirmation, os_window_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle_close_os_window_confirmation(self, os_window_id: int, data: Dict[str, Any], *a: Any) -> None:
|
||||||
|
if data['response'] == 'y':
|
||||||
|
mark_os_window_for_close(os_window_id)
|
||||||
|
else:
|
||||||
|
mark_os_window_for_close(os_window_id, NO_CLOSE_REQUESTED)
|
||||||
|
|
||||||
def on_os_window_closed(self, os_window_id: int, viewport_width: int, viewport_height: int) -> None:
|
def on_os_window_closed(self, os_window_id: int, viewport_width: int, viewport_height: int) -> None:
|
||||||
self.cached_values['window-size'] = viewport_width, viewport_height
|
self.cached_values['window-size'] = viewport_width, viewport_height
|
||||||
tm = self.os_window_map.pop(os_window_id, None)
|
tm = self.os_window_map.pop(os_window_id, None)
|
||||||
@@ -713,6 +764,28 @@ class Boss:
|
|||||||
if action is not None:
|
if action is not None:
|
||||||
action()
|
action()
|
||||||
|
|
||||||
|
def quit(self, *args: Any) -> None:
|
||||||
|
tm = self.active_tab
|
||||||
|
num = 0
|
||||||
|
for q in self.os_window_map.values():
|
||||||
|
num += q.number_of_windows
|
||||||
|
needs_confirmation = tm is not None and self.opts.confirm_os_window_close > 0 and num >= self.opts.confirm_os_window_close
|
||||||
|
if not needs_confirmation:
|
||||||
|
set_application_quit_request(IMPERATIVE_CLOSE_REQUESTED)
|
||||||
|
return
|
||||||
|
if current_application_quit_request() == CLOSE_BEING_CONFIRMED:
|
||||||
|
return
|
||||||
|
assert tm is not None
|
||||||
|
self._run_kitten('ask', ['--type=yesno', '--message', _(
|
||||||
|
'Are you sure you want to quit kitty, it has {} windows running?').format(num)],
|
||||||
|
window=tm.active_window,
|
||||||
|
custom_callback=self.handle_quit_confirmation
|
||||||
|
)
|
||||||
|
set_application_quit_request(CLOSE_BEING_CONFIRMED)
|
||||||
|
|
||||||
|
def handle_quit_confirmation(self, data: Dict[str, Any], *a: Any) -> None:
|
||||||
|
set_application_quit_request(IMPERATIVE_CLOSE_REQUESTED if data['response'] == 'y' else NO_CLOSE_REQUESTED)
|
||||||
|
|
||||||
def notify_on_os_window_death(self, address: str) -> None:
|
def notify_on_os_window_death(self, address: str) -> None:
|
||||||
import socket
|
import socket
|
||||||
s = socket.socket(family=socket.AF_UNIX)
|
s = socket.socket(family=socket.AF_UNIX)
|
||||||
@@ -725,9 +798,9 @@ class Boss:
|
|||||||
|
|
||||||
def display_scrollback(self, window: Window, data: Optional[bytes], cmd: Optional[List[str]]) -> None:
|
def display_scrollback(self, window: Window, data: Optional[bytes], cmd: Optional[List[str]]) -> None:
|
||||||
tab = self.active_tab
|
tab = self.active_tab
|
||||||
if tab is not None and window.overlay_for is None:
|
if tab is not None:
|
||||||
tab.new_special_window(
|
tab.new_special_window(
|
||||||
SpecialWindow(cmd, data, _('History'), overlay_for=window.id),
|
SpecialWindow(cmd, data, _('History'), overlay_for=window.id, cwd=window.cwd_of_child),
|
||||||
copy_colors_from=self.active_window
|
copy_colors_from=self.active_window
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -755,7 +828,7 @@ class Boss:
|
|||||||
window: Optional[Window] = None,
|
window: Optional[Window] = None,
|
||||||
custom_callback: Optional[Callable] = None,
|
custom_callback: Optional[Callable] = None,
|
||||||
action_on_removal: Optional[Callable] = None
|
action_on_removal: Optional[Callable] = None
|
||||||
) -> Optional[Window]:
|
) -> Any:
|
||||||
orig_args, args = list(args), list(args)
|
orig_args, args = list(args), list(args)
|
||||||
from kittens.runner import create_kitten_handler
|
from kittens.runner import create_kitten_handler
|
||||||
end_kitten = create_kitten_handler(kitten, orig_args)
|
end_kitten = create_kitten_handler(kitten, orig_args)
|
||||||
@@ -766,10 +839,9 @@ class Boss:
|
|||||||
w = window
|
w = window
|
||||||
tab = w.tabref() if w else None
|
tab = w.tabref() if w else None
|
||||||
if end_kitten.no_ui:
|
if end_kitten.no_ui:
|
||||||
end_kitten(None, getattr(w, 'id', None), self)
|
return end_kitten(None, getattr(w, 'id', None), self)
|
||||||
return None
|
|
||||||
|
|
||||||
if w is not None and tab is not None and w.overlay_for is None:
|
if w is not None and tab is not None:
|
||||||
args[0:0] = [config_dir, kitten]
|
args[0:0] = [config_dir, kitten]
|
||||||
if input_data is None:
|
if input_data is None:
|
||||||
type_of_input = end_kitten.type_of_input
|
type_of_input = end_kitten.type_of_input
|
||||||
@@ -870,24 +942,35 @@ class Boss:
|
|||||||
custom_callback=done, action_on_removal=done2)
|
custom_callback=done, action_on_removal=done2)
|
||||||
|
|
||||||
def kitty_shell(self, window_type: str) -> None:
|
def kitty_shell(self, window_type: str) -> None:
|
||||||
cmd = ['@', kitty_exe(), '@']
|
kw: Dict[str, Any] = {}
|
||||||
|
cmd = [kitty_exe(), '@']
|
||||||
|
aw = self.active_window
|
||||||
|
if aw is not None:
|
||||||
|
kw['env'] = {'KITTY_SHELL_ACTIVE_WINDOW_ID': str(aw.id)}
|
||||||
if window_type == 'tab':
|
if window_type == 'tab':
|
||||||
self._new_tab(cmd)
|
tab = self._new_tab(SpecialWindow(cmd, **kw))
|
||||||
|
if tab is not None:
|
||||||
|
for w in tab:
|
||||||
|
w.allow_remote_control = True
|
||||||
elif window_type == 'os_window':
|
elif window_type == 'os_window':
|
||||||
os_window_id = self._new_os_window(cmd)
|
os_window_id = self._new_os_window(SpecialWindow(cmd, **kw))
|
||||||
self.os_window_map[os_window_id]
|
for tab in self.os_window_map[os_window_id]:
|
||||||
|
for w in tab:
|
||||||
|
w.allow_remote_control = True
|
||||||
elif window_type == 'overlay':
|
elif window_type == 'overlay':
|
||||||
w = self.active_window
|
|
||||||
tab = self.active_tab
|
tab = self.active_tab
|
||||||
if w is not None and tab is not None and w.overlay_for is None:
|
if aw is not None and tab is not None:
|
||||||
tab.new_special_window(SpecialWindow(cmd, overlay_for=w.id))
|
kw['overlay_for'] = aw.id
|
||||||
|
tab.new_special_window(SpecialWindow(cmd, **kw), allow_remote_control=True)
|
||||||
else:
|
else:
|
||||||
self._new_window(cmd)
|
tab = self.active_tab
|
||||||
|
if tab is not None:
|
||||||
|
tab.new_special_window(SpecialWindow(cmd, **kw), allow_remote_control=True)
|
||||||
|
|
||||||
def switch_focus_to(self, window_idx: int) -> None:
|
def switch_focus_to(self, window_id: int) -> None:
|
||||||
tab = self.active_tab
|
tab = self.active_tab
|
||||||
if tab:
|
if tab:
|
||||||
tab.set_active_window_idx(window_idx)
|
tab.set_active_window(window_id)
|
||||||
|
|
||||||
def open_url(self, url: str, program: Optional[Union[str, List[str]]] = None, cwd: Optional[str] = None) -> None:
|
def open_url(self, url: str, program: Optional[Union[str, List[str]]] = None, cwd: Optional[str] = None) -> None:
|
||||||
if url:
|
if url:
|
||||||
@@ -1021,7 +1104,7 @@ class Boss:
|
|||||||
continue
|
continue
|
||||||
arg = q
|
arg = q
|
||||||
cmdline.append(arg)
|
cmdline.append(arg)
|
||||||
overlay_for = w.id if w and as_overlay and w.overlay_for is None else None
|
overlay_for = w.id if w and as_overlay else None
|
||||||
return SpecialWindow(cmd, input_data, cwd_from=cwd_from, overlay_for=overlay_for, env=env)
|
return SpecialWindow(cmd, input_data, cwd_from=cwd_from, overlay_for=overlay_for, env=env)
|
||||||
|
|
||||||
def run_background_process(
|
def run_background_process(
|
||||||
@@ -1292,11 +1375,8 @@ class Boss:
|
|||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
underlaid_window, overlaid_window = src_tab.detach_window(window)
|
for detached_window in src_tab.detach_window(window):
|
||||||
if underlaid_window:
|
target_tab.attach_window(detached_window)
|
||||||
target_tab.attach_window(underlaid_window)
|
|
||||||
if overlaid_window:
|
|
||||||
target_tab.attach_window(overlaid_window)
|
|
||||||
self._cleanup_tab_after_window_removal(src_tab)
|
self._cleanup_tab_after_window_removal(src_tab)
|
||||||
target_tab.make_active()
|
target_tab.make_active()
|
||||||
|
|
||||||
@@ -1342,8 +1422,6 @@ class Boss:
|
|||||||
done_tab_id = tab_id_map[int(data['groupdicts'][0]['index'])]
|
done_tab_id = tab_id_map[int(data['groupdicts'][0]['index'])]
|
||||||
|
|
||||||
def done2(target_window_id: int, self: Boss) -> None:
|
def done2(target_window_id: int, self: Boss) -> None:
|
||||||
if not hasattr(done, 'tab_id'):
|
|
||||||
return
|
|
||||||
tab_id = done_tab_id
|
tab_id = done_tab_id
|
||||||
target_window = None
|
target_window = None
|
||||||
for w in self.all_windows:
|
for w in self.all_windows:
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ void main() {
|
|||||||
|
|
||||||
// Background {{{
|
// Background {{{
|
||||||
#ifdef NEEDS_BACKROUND
|
#ifdef NEEDS_BACKROUND
|
||||||
float cell_has_non_default_bg = step(1, float(abs(bg_as_uint - default_colors[bg_index])));
|
float cell_has_non_default_bg = step(1, float(abs(bg_as_uint - default_colors[1])));
|
||||||
draw_bg = 1;
|
draw_bg = 1;
|
||||||
|
|
||||||
#if defined(BACKGROUND)
|
#if defined(BACKGROUND)
|
||||||
|
|||||||
@@ -346,7 +346,10 @@ parse_input(ChildMonitor *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(kill_signal_received)) {
|
if (UNLIKELY(kill_signal_received)) {
|
||||||
global_state.terminate = true;
|
global_state.quit_request = IMPERATIVE_CLOSE_REQUESTED;
|
||||||
|
global_state.has_pending_closes = true;
|
||||||
|
request_tick_callback();
|
||||||
|
kill_signal_received = false;
|
||||||
} else {
|
} else {
|
||||||
count = self->count;
|
count = self->count;
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
@@ -461,10 +464,10 @@ set_iutf8(int UNUSED fd, bool UNUSED on) {
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
pyset_iutf8(ChildMonitor *self, PyObject *args) {
|
pyset_iutf8(ChildMonitor *self, PyObject *args) {
|
||||||
unsigned long window_id;
|
id_type window_id;
|
||||||
int on;
|
int on;
|
||||||
PyObject *found = Py_False;
|
PyObject *found = Py_False;
|
||||||
if (!PyArg_ParseTuple(args, "kp", &window_id, &on)) return NULL;
|
if (!PyArg_ParseTuple(args, "Kp", &window_id, &on)) return NULL;
|
||||||
children_mutex(lock);
|
children_mutex(lock);
|
||||||
for (size_t i = 0; i < self->count; i++) {
|
for (size_t i = 0; i < self->count; i++) {
|
||||||
if (children[i].id == window_id) {
|
if (children[i].id == window_id) {
|
||||||
@@ -523,17 +526,6 @@ change_menubar_title(PyObject *title UNUSED) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
|
||||||
update_window_title(Window *w, OSWindow *os_window) {
|
|
||||||
if (w->title && w->title != os_window->window_title) {
|
|
||||||
os_window->window_title = w->title;
|
|
||||||
Py_INCREF(os_window->window_title);
|
|
||||||
set_os_window_title(os_window, PyUnicode_AsUTF8(w->title));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *active_window_id, color_type *active_window_bg, unsigned int *num_visible_windows, bool *all_windows_have_same_bg) {
|
prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *active_window_id, color_type *active_window_bg, unsigned int *num_visible_windows, bool *all_windows_have_same_bg) {
|
||||||
#define TD os_window->tab_bar_render_data
|
#define TD os_window->tab_bar_render_data
|
||||||
@@ -577,7 +569,7 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *
|
|||||||
*active_window_id = w->id;
|
*active_window_id = w->id;
|
||||||
collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window);
|
collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window);
|
||||||
if (w->cursor_visible_at_last_render != WD.screen->cursor_render_info.is_visible || w->last_cursor_x != WD.screen->cursor_render_info.x || w->last_cursor_y != WD.screen->cursor_render_info.y || w->last_cursor_shape != WD.screen->cursor_render_info.shape) needs_render = true;
|
if (w->cursor_visible_at_last_render != WD.screen->cursor_render_info.is_visible || w->last_cursor_x != WD.screen->cursor_render_info.x || w->last_cursor_y != WD.screen->cursor_render_info.y || w->last_cursor_shape != WD.screen->cursor_render_info.shape) needs_render = true;
|
||||||
update_window_title(w, os_window);
|
set_os_window_title_from_window(w, os_window);
|
||||||
*active_window_bg = window_bg;
|
*active_window_bg = window_bg;
|
||||||
} else WD.screen->cursor_render_info.is_visible = false;
|
} else WD.screen->cursor_render_info.is_visible = false;
|
||||||
if (send_cell_data_to_gpu(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) needs_render = true;
|
if (send_cell_data_to_gpu(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) needs_render = true;
|
||||||
@@ -625,15 +617,6 @@ render_os_window(OSWindow *os_window, monotonic_t now, unsigned int active_windo
|
|||||||
#undef TD
|
#undef TD
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
update_os_window_title(OSWindow *os_window) {
|
|
||||||
Tab *tab = os_window->tabs + os_window->active_tab;
|
|
||||||
if (tab->num_windows) {
|
|
||||||
Window *w = tab->windows + tab->active_window;
|
|
||||||
update_window_title(w, os_window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_resizing_text(OSWindow *w) {
|
draw_resizing_text(OSWindow *w) {
|
||||||
char text[32] = {0};
|
char text[32] = {0};
|
||||||
@@ -649,7 +632,13 @@ draw_resizing_text(OSWindow *w) {
|
|||||||
static inline bool
|
static inline bool
|
||||||
no_render_frame_received_recently(OSWindow *w, monotonic_t now, monotonic_t max_wait) {
|
no_render_frame_received_recently(OSWindow *w, monotonic_t now, monotonic_t max_wait) {
|
||||||
bool ans = now - w->last_render_frame_received_at > max_wait;
|
bool ans = now - w->last_render_frame_received_at > max_wait;
|
||||||
if (ans) log_error("No render frame received in %.2f seconds, re-requesting at: %f", monotonic_t_to_s_double(max_wait), monotonic_t_to_s_double(now));
|
if (ans && global_state.debug_rendering) {
|
||||||
|
if (global_state.is_wayland) {
|
||||||
|
log_error("No render frame received in %.2f seconds", monotonic_t_to_s_double(max_wait));
|
||||||
|
} else {
|
||||||
|
log_error("No render frame received in %.2f seconds, re-requesting at: %f", monotonic_t_to_s_double(max_wait), monotonic_t_to_s_double(now));
|
||||||
|
}
|
||||||
|
}
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,32 +853,53 @@ process_pending_resizes(monotonic_t now) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
close_all_windows(void) {
|
close_os_window(ChildMonitor *self, OSWindow *os_window) {
|
||||||
for (size_t w = 0; w < global_state.num_os_windows; w++) mark_os_window_for_close(&global_state.os_windows[w], true);
|
destroy_os_window(os_window);
|
||||||
|
call_boss(on_os_window_closed, "Kii", os_window->id, os_window->window_width, os_window->window_height);
|
||||||
|
for (size_t t=0; t < os_window->num_tabs; t++) {
|
||||||
|
Tab *tab = os_window->tabs + t;
|
||||||
|
for (size_t w = 0; w < tab->num_windows; w++) mark_child_for_close(self, tab->windows[w].id);
|
||||||
|
}
|
||||||
|
remove_os_window(os_window->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
process_pending_closes(ChildMonitor *self) {
|
process_pending_closes(ChildMonitor *self) {
|
||||||
global_state.has_pending_closes = false;
|
if (global_state.quit_request == CONFIRMABLE_CLOSE_REQUESTED) {
|
||||||
|
call_boss(quit, "");
|
||||||
|
}
|
||||||
|
if (global_state.quit_request == IMPERATIVE_CLOSE_REQUESTED) {
|
||||||
|
for (size_t w = 0; w < global_state.num_os_windows; w++) global_state.os_windows[w].close_request = IMPERATIVE_CLOSE_REQUESTED;
|
||||||
|
}
|
||||||
bool has_open_windows = false;
|
bool has_open_windows = false;
|
||||||
for (size_t w = global_state.num_os_windows; w > 0; w--) {
|
for (size_t w = global_state.num_os_windows; w > 0; w--) {
|
||||||
OSWindow *os_window = global_state.os_windows + w - 1;
|
OSWindow *os_window = global_state.os_windows + w - 1;
|
||||||
if (should_os_window_close(os_window)) {
|
switch(os_window->close_request) {
|
||||||
destroy_os_window(os_window);
|
case NO_CLOSE_REQUESTED:
|
||||||
call_boss(on_os_window_closed, "Kii", os_window->id, os_window->window_width, os_window->window_height);
|
has_open_windows = true;
|
||||||
for (size_t t=0; t < os_window->num_tabs; t++) {
|
break;
|
||||||
Tab *tab = os_window->tabs + t;
|
case CONFIRMABLE_CLOSE_REQUESTED:
|
||||||
for (size_t w = 0; w < tab->num_windows; w++) mark_child_for_close(self, tab->windows[w].id);
|
os_window->close_request = CLOSE_BEING_CONFIRMED;
|
||||||
}
|
call_boss(confirm_os_window_close, "K", os_window->id);
|
||||||
remove_os_window(os_window->id);
|
if (os_window->close_request == IMPERATIVE_CLOSE_REQUESTED) {
|
||||||
} else has_open_windows = true;
|
close_os_window(self, os_window);
|
||||||
|
} else has_open_windows = true;
|
||||||
|
break;
|
||||||
|
case CLOSE_BEING_CONFIRMED:
|
||||||
|
has_open_windows = true;
|
||||||
|
break;
|
||||||
|
case IMPERATIVE_CLOSE_REQUESTED:
|
||||||
|
close_os_window(self, os_window);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
global_state.has_pending_closes = false;
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (!OPT(macos_quit_when_last_window_closed)) {
|
if (!OPT(macos_quit_when_last_window_closed)) {
|
||||||
if (!has_open_windows && !application_quit_requested()) has_open_windows = true;
|
if (!has_open_windows && global_state.quit_request != IMPERATIVE_CLOSE_REQUESTED) has_open_windows = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return has_open_windows;
|
return !has_open_windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@@ -950,23 +960,16 @@ process_global_state(void *data) {
|
|||||||
cocoa_pending_actions = 0;
|
cocoa_pending_actions = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (global_state.terminate) {
|
|
||||||
global_state.terminate = false;
|
|
||||||
close_all_windows();
|
|
||||||
#ifdef __APPLE__
|
|
||||||
request_application_quit();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
report_reaped_pids();
|
report_reaped_pids();
|
||||||
bool has_open_windows = true;
|
bool should_quit = false;
|
||||||
if (global_state.has_pending_closes) has_open_windows = process_pending_closes(self);
|
if (global_state.has_pending_closes) should_quit = process_pending_closes(self);
|
||||||
if (has_open_windows) {
|
if (should_quit) {
|
||||||
|
stop_main_loop();
|
||||||
|
} else {
|
||||||
if (maximum_wait >= 0) {
|
if (maximum_wait >= 0) {
|
||||||
if (maximum_wait == 0) request_tick_callback();
|
if (maximum_wait == 0) request_tick_callback();
|
||||||
else state_check_timer_enabled = true;
|
else state_check_timer_enabled = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
stop_main_loop();
|
|
||||||
}
|
}
|
||||||
update_main_loop_timer(state_check_timer, MAX(0, maximum_wait), state_check_timer_enabled);
|
update_main_loop_timer(state_check_timer, MAX(0, maximum_wait), state_check_timer_enabled);
|
||||||
}
|
}
|
||||||
@@ -1279,7 +1282,7 @@ typedef struct {
|
|||||||
char *data;
|
char *data;
|
||||||
size_t capacity, used;
|
size_t capacity, used;
|
||||||
int fd;
|
int fd;
|
||||||
bool finished, close_socket;
|
bool finished, close_socket, is_peer_command;
|
||||||
} PeerReadData;
|
} PeerReadData;
|
||||||
static PeerReadData empty_prd = {.fd = -1, 0};
|
static PeerReadData empty_prd = {.fd = -1, 0};
|
||||||
|
|
||||||
@@ -1329,6 +1332,41 @@ accept_peer(int listen_fd, bool shutting_down) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define KITTY_CMD_PREFIX "\x1bP@kitty-cmd{"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
queue_peer_message(ChildMonitor *self, char *buf, size_t sz, int fd) {
|
||||||
|
children_mutex(lock);
|
||||||
|
ensure_space_for(self, messages, Message, self->messages_count + 1, messages_capacity, 16, true);
|
||||||
|
Message *m = self->messages + self->messages_count++;
|
||||||
|
m->data = buf; m->sz = sz; m->fd = fd;
|
||||||
|
children_mutex(unlock);
|
||||||
|
wakeup_main_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
dispatch_peer_command(ChildMonitor *self, PeerReadData *rd, int fd) {
|
||||||
|
size_t end = 0;
|
||||||
|
for (size_t i = 0; i < rd->used - 1; i++) {
|
||||||
|
if (rd->data[i] == 0x1b && rd->data[i+1] == '\\') {
|
||||||
|
end = i + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!end) return;
|
||||||
|
char *buf = malloc(end + 8);
|
||||||
|
if (buf) {
|
||||||
|
memcpy(buf, rd->data, end);
|
||||||
|
queue_peer_message(self, buf, end, fd);
|
||||||
|
}
|
||||||
|
rd->is_peer_command = false;
|
||||||
|
if (rd->used > end) {
|
||||||
|
rd->used -= end;
|
||||||
|
memmove(rd->data, rd->data + end, rd->used);
|
||||||
|
if (rd->used >= sizeof(KITTY_CMD_PREFIX) - 1 && memcmp(rd->data, KITTY_CMD_PREFIX, sizeof(KITTY_CMD_PREFIX)-1) == 0) rd->is_peer_command = true;
|
||||||
|
} else rd->used = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
read_from_peer(ChildMonitor *self, int s) {
|
read_from_peer(ChildMonitor *self, int s) {
|
||||||
bool read_finished = false;
|
bool read_finished = false;
|
||||||
@@ -1337,26 +1375,28 @@ read_from_peer(ChildMonitor *self, int s) {
|
|||||||
#define failed(msg) { read_finished = true; log_error("%s", msg); rd->finished = true; rd->close_socket = true; break; }
|
#define failed(msg) { read_finished = true; log_error("%s", msg); rd->finished = true; rd->close_socket = true; break; }
|
||||||
if (rd->fd == s) {
|
if (rd->fd == s) {
|
||||||
if (rd->used >= rd->capacity) {
|
if (rd->used >= rd->capacity) {
|
||||||
if (rd->capacity >= 1024 * 1024) failed("Ignoring too large message from peer");
|
if (rd->capacity >= 64 * 1024) failed("Ignoring too large message from peer");
|
||||||
rd->capacity = MAX(8192u, rd->capacity * 2);
|
rd->capacity = MAX(8192u, rd->capacity * 2);
|
||||||
rd->data = realloc(rd->data, rd->capacity);
|
rd->data = realloc(rd->data, rd->capacity);
|
||||||
if (!rd->data) failed("Out of memory");
|
if (!rd->data) failed("Out of memory");
|
||||||
}
|
}
|
||||||
ssize_t n = recv(s, rd->data + rd->used, rd->capacity - rd->used, 0);
|
ssize_t n = recv(s, rd->data + rd->used, rd->capacity - rd->used, 0);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
|
while (rd->is_peer_command) dispatch_peer_command(self, rd, s);
|
||||||
read_finished = true; rd->finished = true;
|
read_finished = true; rd->finished = true;
|
||||||
children_mutex(lock);
|
if (rd->used) queue_peer_message(self, rd->data, rd->used, s);
|
||||||
ensure_space_for(self, messages, Message, self->messages_count + 1, messages_capacity, 16, true);
|
else free(rd->data);
|
||||||
Message *m = self->messages + self->messages_count++;
|
rd->data = NULL;
|
||||||
m->data = rd->data; rd->data = NULL; m->sz = rd->used; m->fd = s;
|
|
||||||
children_mutex(unlock);
|
|
||||||
wakeup_main_loop();
|
|
||||||
} else if (n < 0) {
|
} else if (n < 0) {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
perror("Error reading from talk peer");
|
perror("Error reading from talk peer");
|
||||||
failed("");
|
failed("");
|
||||||
}
|
}
|
||||||
} else rd->used += n;
|
} else {
|
||||||
|
if (!rd->used && memcmp(rd->data, KITTY_CMD_PREFIX, sizeof(KITTY_CMD_PREFIX)-1) == 0) rd->is_peer_command = true;
|
||||||
|
rd->used += n;
|
||||||
|
while (rd->is_peer_command) dispatch_peer_command(self, rd, s);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1541,6 +1581,7 @@ static PyMethodDef methods[] = {
|
|||||||
METHOD(main_loop, METH_NOARGS)
|
METHOD(main_loop, METH_NOARGS)
|
||||||
METHOD(mark_for_close, METH_VARARGS)
|
METHOD(mark_for_close, METH_VARARGS)
|
||||||
METHOD(resize_pty, METH_VARARGS)
|
METHOD(resize_pty, METH_VARARGS)
|
||||||
|
{"set_iutf8_winid", (PyCFunction)pyset_iutf8, METH_VARARGS, ""},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1582,7 +1623,6 @@ static PyMethodDef module_methods[] = {
|
|||||||
{"add_timer", (PyCFunction)add_python_timer, METH_VARARGS, ""},
|
{"add_timer", (PyCFunction)add_python_timer, METH_VARARGS, ""},
|
||||||
{"remove_timer", (PyCFunction)remove_python_timer, METH_VARARGS, ""},
|
{"remove_timer", (PyCFunction)remove_python_timer, METH_VARARGS, ""},
|
||||||
METHODB(monitor_pid, METH_VARARGS),
|
METHODB(monitor_pid, METH_VARARGS),
|
||||||
{"set_iutf8_winid", (PyCFunction)pyset_iutf8, METH_VARARGS, ""},
|
|
||||||
METHODB(cocoa_set_menubar_title, METH_VARARGS),
|
METHODB(cocoa_set_menubar_title, METH_VARARGS),
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
static inline char**
|
static inline char**
|
||||||
serialize_string_tuple(PyObject *src) {
|
serialize_string_tuple(PyObject *src) {
|
||||||
@@ -93,7 +95,7 @@ spawn(PyObject *self UNUSED, PyObject *args) {
|
|||||||
// Establish the controlling terminal (see man 7 credentials)
|
// Establish the controlling terminal (see man 7 credentials)
|
||||||
int tfd = open(name, O_RDWR);
|
int tfd = open(name, O_RDWR);
|
||||||
if (tfd == -1) exit_on_err("Failed to open controlling terminal");
|
if (tfd == -1) exit_on_err("Failed to open controlling terminal");
|
||||||
#ifdef TIOCSTTY
|
#ifdef TIOCSCTTY
|
||||||
// On BSD open() does not establish the controlling terminal
|
// On BSD open() does not establish the controlling terminal
|
||||||
if (ioctl(tfd, TIOCSCTTY, 0) == -1) exit_on_err("Failed to set controlling terminal with TIOCSCTTY");
|
if (ioctl(tfd, TIOCSCTTY, 0) == -1) exit_on_err("Failed to set controlling terminal with TIOCSCTTY");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
33
kitty/cli.py
33
kitty/cli.py
@@ -96,7 +96,9 @@ def opt(text: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def option(x: str) -> str:
|
def option(x: str) -> str:
|
||||||
idx = x.find('-')
|
idx = x.rfind('--')
|
||||||
|
if idx < 0:
|
||||||
|
idx = x.find('-')
|
||||||
if idx > -1:
|
if idx > -1:
|
||||||
x = x[idx:]
|
x = x[idx:]
|
||||||
parts = map(bold, x.split())
|
parts = map(bold, x.split())
|
||||||
@@ -119,6 +121,10 @@ def file(x: str) -> str:
|
|||||||
return italic(x)
|
return italic(x)
|
||||||
|
|
||||||
|
|
||||||
|
def doc(x: str) -> str:
|
||||||
|
return f'https://sw.kovidgoyal.net/kitty/{x}.html'
|
||||||
|
|
||||||
|
|
||||||
OptionSpecSeq = List[Union[str, OptionDict]]
|
OptionSpecSeq = List[Union[str, OptionDict]]
|
||||||
|
|
||||||
|
|
||||||
@@ -283,9 +289,9 @@ class PrintHelpForSeq:
|
|||||||
leading_indent = indent
|
leading_indent = indent
|
||||||
j = '\n' + (' ' * indent)
|
j = '\n' + (' ' * indent)
|
||||||
lines: List[str] = []
|
lines: List[str] = []
|
||||||
for l in text.splitlines():
|
for ln in text.splitlines():
|
||||||
if l:
|
if ln:
|
||||||
lines.extend(wrap(l, limit=linesz - indent))
|
lines.extend(wrap(ln, limit=linesz - indent))
|
||||||
else:
|
else:
|
||||||
lines.append('')
|
lines.append('')
|
||||||
a((' ' * leading_indent) + j.join(lines))
|
a((' ' * leading_indent) + j.join(lines))
|
||||||
@@ -403,7 +409,10 @@ def as_type_stub(seq: OptionSpecSeq, disabled: OptionSpecSeq, class_name: str, e
|
|||||||
elif otype == 'list':
|
elif otype == 'list':
|
||||||
t = 'typing.Sequence[str]'
|
t = 'typing.Sequence[str]'
|
||||||
elif otype in ('choice', 'choices'):
|
elif otype in ('choice', 'choices'):
|
||||||
t = 'str'
|
if opt['choices']:
|
||||||
|
t = 'typing.Literal[{}]'.format(','.join(f'{x!r}' for x in opt['choices']))
|
||||||
|
else:
|
||||||
|
t = 'str'
|
||||||
elif otype.startswith('bool-'):
|
elif otype.startswith('bool-'):
|
||||||
t = 'bool'
|
t = 'bool'
|
||||||
else:
|
else:
|
||||||
@@ -618,12 +627,15 @@ Tell kitty to listen on the specified address for control
|
|||||||
messages. For example, :option:`{appname} --listen-on`=unix:/tmp/mykitty or
|
messages. For example, :option:`{appname} --listen-on`=unix:/tmp/mykitty or
|
||||||
:option:`{appname} --listen-on`=tcp:localhost:12345. On Linux systems, you can
|
:option:`{appname} --listen-on`=tcp:localhost:12345. On Linux systems, you can
|
||||||
also use abstract UNIX sockets, not associated with a file, like this:
|
also use abstract UNIX sockets, not associated with a file, like this:
|
||||||
:option:`{appname} --listen-on`=unix:@mykitty. To control kitty, you can send
|
:option:`{appname} --listen-on`=unix:@mykitty. Environment variables
|
||||||
|
in the setting are expanded and relative paths are resolved with
|
||||||
|
respect to the temporary directory. To control kitty, you can send
|
||||||
it commands with :italic:`kitty @` using the :option:`kitty @ --to` option to
|
it commands with :italic:`kitty @` using the :option:`kitty @ --to` option to
|
||||||
specify this address. This option will be ignored, unless you set
|
specify this address. This option will be ignored, unless you set
|
||||||
:opt:`allow_remote_control` to yes in :file:`kitty.conf`. Note that if you run
|
:opt:`allow_remote_control` to yes in :file:`kitty.conf`. Note that if you run
|
||||||
:italic:`kitty @` within a kitty window, there is no need to specify the :italic:`--to`
|
:italic:`kitty @` within a kitty window, there is no need to specify the :italic:`--to`
|
||||||
option as it is read automatically from the environment.
|
option as it is read automatically from the environment. For UNIX sockets, this
|
||||||
|
can also be specified in :file:`kitty.conf`.
|
||||||
|
|
||||||
|
|
||||||
--start-as
|
--start-as
|
||||||
@@ -656,10 +668,11 @@ can open a new kitty window to replay the commands with::
|
|||||||
Path to file in which to store the raw bytes received from the child process
|
Path to file in which to store the raw bytes received from the child process
|
||||||
|
|
||||||
|
|
||||||
--debug-gl
|
--debug-rendering --debug-gl
|
||||||
type=bool-set
|
type=bool-set
|
||||||
Debug OpenGL commands. This will cause all OpenGL calls to check for errors
|
Debug rendering commands. This will cause all OpenGL calls to check for errors
|
||||||
instead of ignoring them. Useful when debugging rendering problems
|
instead of ignoring them. Also prints out miscellaneous debug information.
|
||||||
|
Useful when debugging rendering problems
|
||||||
|
|
||||||
|
|
||||||
--debug-keyboard
|
--debug-keyboard
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ def screen_cursor_to_column(c: int) -> None:
|
|||||||
write(CSI + '%dG' % c)
|
write(CSI + '%dG' % c)
|
||||||
|
|
||||||
|
|
||||||
def screen_cursor_to_line(l: int) -> None:
|
def screen_cursor_to_line(ln: int) -> None:
|
||||||
write(CSI + '%dd' % l)
|
write(CSI + '%dd' % ln)
|
||||||
|
|
||||||
|
|
||||||
def screen_set_mode(x: int, private: bool) -> None:
|
def screen_set_mode(x: int, private: bool) -> None:
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
// Needed for _NSGetProgname
|
// Needed for _NSGetProgname
|
||||||
#include <crt_externs.h>
|
#include <crt_externs.h>
|
||||||
#include <objc/runtime.h>
|
#include <objc/runtime.h>
|
||||||
|
#include <xlocale.h>
|
||||||
|
|
||||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 101200)
|
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 101200)
|
||||||
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
||||||
@@ -419,7 +420,13 @@ cocoa_get_lang(PyObject UNUSED *self) {
|
|||||||
locale = [[NSLocale currentLocale] localeIdentifier];
|
locale = [[NSLocale currentLocale] localeIdentifier];
|
||||||
}
|
}
|
||||||
if (!locale) { Py_RETURN_NONE; }
|
if (!locale) { Py_RETURN_NONE; }
|
||||||
return Py_BuildValue("s", [locale UTF8String]);
|
// Make sure the locale value is valid, that is it can be used
|
||||||
|
// to construct an actual locale
|
||||||
|
const char* locale_utf8 = [locale UTF8String];
|
||||||
|
locale_t test_locale = newlocale(LC_ALL_MASK, locale_utf8, NULL);
|
||||||
|
if (!test_locale) { Py_RETURN_NONE; }
|
||||||
|
freelocale(test_locale);
|
||||||
|
return Py_BuildValue("s", locale_utf8);
|
||||||
|
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ your shell's rc file.
|
|||||||
|
|
||||||
2) Add an input_parser function, this takes the input from
|
2) Add an input_parser function, this takes the input from
|
||||||
the shell for the text being completed and returns a list of words
|
the shell for the text being completed and returns a list of words
|
||||||
alongwith a boolean indicating if we are on a new word or not. This
|
and a boolean indicating if we are on a new word or not. This
|
||||||
is passed to kitty's completion system.
|
is passed to kitty's completion system.
|
||||||
|
|
||||||
3) An output_serializer function that is responsible for
|
3) An output_serializer function that is responsible for
|
||||||
@@ -47,12 +47,32 @@ def debug(*a: Any, **kw: Any) -> None:
|
|||||||
print(*a, **kw)
|
print(*a, **kw)
|
||||||
|
|
||||||
|
|
||||||
|
class Delegate:
|
||||||
|
|
||||||
|
def __init__(self, words: Sequence[str] = (), pos: int = -1, new_word: bool = False):
|
||||||
|
self.words: Sequence[str] = words
|
||||||
|
self.pos = pos
|
||||||
|
self.num_of_unknown_args = len(words) - pos
|
||||||
|
self.new_word = new_word
|
||||||
|
|
||||||
|
def __bool__(self) -> bool:
|
||||||
|
return self.pos > -1 and self.num_of_unknown_args > 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def precommand(self) -> str:
|
||||||
|
try:
|
||||||
|
return self.words[self.pos]
|
||||||
|
except IndexError:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class Completions:
|
class Completions:
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.match_groups: Dict[str, MathGroup] = {}
|
self.match_groups: Dict[str, MathGroup] = {}
|
||||||
self.no_space_groups: Set[str] = set()
|
self.no_space_groups: Set[str] = set()
|
||||||
self.files_groups: Set[str] = set()
|
self.files_groups: Set[str] = set()
|
||||||
|
self.delegate: Delegate = Delegate()
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=2)
|
@lru_cache(maxsize=2)
|
||||||
@@ -153,6 +173,15 @@ def zsh_output_serializer(ans: Completions) -> str:
|
|||||||
for word in matches:
|
for word in matches:
|
||||||
cmd.append(shlex.quote(word))
|
cmd.append(shlex.quote(word))
|
||||||
lines.append(' '.join(cmd) + ';')
|
lines.append(' '.join(cmd) + ';')
|
||||||
|
|
||||||
|
if ans.delegate:
|
||||||
|
if ans.delegate.num_of_unknown_args == 1 and not ans.delegate.new_word:
|
||||||
|
lines.append('_command_names -e')
|
||||||
|
elif ans.delegate.precommand:
|
||||||
|
for i in range(ans.delegate.pos + 1):
|
||||||
|
lines.append('shift words')
|
||||||
|
lines.append('(( CURRENT-- ))')
|
||||||
|
lines.append(f'_normal -p "{ans.delegate.precommand}"')
|
||||||
# debug('\n'.join(lines))
|
# debug('\n'.join(lines))
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
@@ -188,6 +217,8 @@ def completions_for_first_word(ans: Completions, prefix: str, entry_points: Iter
|
|||||||
list(entry_points) + cmds + ['+' + k for k in namespaced_entry_points]
|
list(entry_points) + cmds + ['+' + k for k in namespaced_entry_points]
|
||||||
if not prefix or k.startswith(prefix)
|
if not prefix or k.startswith(prefix)
|
||||||
}
|
}
|
||||||
|
if prefix:
|
||||||
|
ans.delegate = Delegate([prefix], 0)
|
||||||
|
|
||||||
|
|
||||||
def kitty_cli_opts(ans: Completions, prefix: Optional[str] = None) -> None:
|
def kitty_cli_opts(ans: Completions, prefix: Optional[str] = None) -> None:
|
||||||
@@ -201,9 +232,11 @@ def kitty_cli_opts(ans: Completions, prefix: Optional[str] = None) -> None:
|
|||||||
ans.match_groups['Options'] = matches
|
ans.match_groups['Options'] = matches
|
||||||
|
|
||||||
|
|
||||||
def complete_kitty_cli_arg(ans: Completions, opt: Optional[OptionDict], prefix: str) -> None:
|
def complete_kitty_cli_arg(ans: Completions, opt: Optional[OptionDict], prefix: str, unknown_args: Delegate) -> None:
|
||||||
prefix = prefix or ''
|
prefix = prefix or ''
|
||||||
if not opt:
|
if not opt:
|
||||||
|
if unknown_args.num_of_unknown_args > 0:
|
||||||
|
ans.delegate = unknown_args
|
||||||
return
|
return
|
||||||
dest = opt['dest']
|
dest = opt['dest']
|
||||||
if dest == 'override':
|
if dest == 'override':
|
||||||
@@ -236,24 +269,24 @@ def complete_kitty_cli_arg(ans: Completions, opt: Optional[OptionDict], prefix:
|
|||||||
complete_files_and_dirs(ans, prefix[len('unix:'):], files_group_name='UNIX sockets', add_prefix='unix:')
|
complete_files_and_dirs(ans, prefix[len('unix:'):], files_group_name='UNIX sockets', add_prefix='unix:')
|
||||||
|
|
||||||
|
|
||||||
CompleteArgsFunc = Callable[[Completions, Optional[OptionDict], str], None]
|
CompleteArgsFunc = Callable[[Completions, Optional[OptionDict], str, Delegate], None]
|
||||||
|
|
||||||
|
|
||||||
def complete_alias_map(
|
def complete_alias_map(
|
||||||
ans: Completions,
|
ans: Completions,
|
||||||
words: Sequence[str],
|
words: Sequence[str],
|
||||||
new_word: str,
|
new_word: bool,
|
||||||
option_map: Dict[str, OptionDict],
|
option_map: Dict[str, OptionDict],
|
||||||
complete_args: Optional[CompleteArgsFunc] = None
|
complete_args: Optional[CompleteArgsFunc] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
expecting_arg = False
|
expecting_arg = False
|
||||||
opt: Optional[OptionDict] = None
|
opt: Optional[OptionDict] = None
|
||||||
last_word = words[-1] if words else ''
|
last_word = words[-1] if words else ''
|
||||||
for w in words:
|
for i, w in enumerate(words):
|
||||||
if expecting_arg:
|
if expecting_arg:
|
||||||
if w is last_word and not new_word:
|
if w is last_word and not new_word:
|
||||||
if opt is not None and complete_args is not None:
|
if opt is not None and complete_args is not None:
|
||||||
complete_args(ans, opt, w)
|
complete_args(ans, opt, w, Delegate())
|
||||||
return
|
return
|
||||||
expecting_arg = False
|
expecting_arg = False
|
||||||
continue
|
continue
|
||||||
@@ -263,27 +296,27 @@ def complete_alias_map(
|
|||||||
ans.match_groups['Options'] = {k: opt['help'] for k, opt in option_map.items() if k.startswith(last_word)}
|
ans.match_groups['Options'] = {k: opt['help'] for k, opt in option_map.items() if k.startswith(last_word)}
|
||||||
else:
|
else:
|
||||||
if complete_args is not None:
|
if complete_args is not None:
|
||||||
complete_args(ans, None, last_word)
|
complete_args(ans, None, last_word, Delegate(words, i))
|
||||||
return
|
return
|
||||||
if opt is None:
|
if opt is None:
|
||||||
if complete_args is not None:
|
if complete_args is not None:
|
||||||
complete_args(ans, None, '' if new_word else last_word)
|
complete_args(ans, None, '' if new_word else last_word, Delegate(words, i, new_word))
|
||||||
return # some non-option word encountered
|
return # some non-option word encountered
|
||||||
expecting_arg = not opt.get('type', '').startswith('bool-')
|
expecting_arg = not opt.get('type', '').startswith('bool-')
|
||||||
if expecting_arg:
|
if expecting_arg:
|
||||||
if opt is not None and complete_args is not None:
|
if opt is not None and complete_args is not None:
|
||||||
complete_args(ans, opt, '' if new_word else last_word)
|
complete_args(ans, opt, '' if new_word else last_word, Delegate())
|
||||||
else:
|
else:
|
||||||
prefix = '' if new_word else last_word
|
prefix = '' if new_word else last_word
|
||||||
if complete_args is not None:
|
if complete_args is not None:
|
||||||
complete_args(ans, None, prefix)
|
complete_args(ans, None, prefix, Delegate())
|
||||||
ans.match_groups['Options'] = {k: opt['help'] for k, opt in option_map.items() if k.startswith(prefix)}
|
ans.match_groups['Options'] = {k: opt['help'] for k, opt in option_map.items() if k.startswith(prefix)}
|
||||||
|
|
||||||
|
|
||||||
def complete_cli(
|
def complete_cli(
|
||||||
ans: Completions,
|
ans: Completions,
|
||||||
words: Sequence[str],
|
words: Sequence[str],
|
||||||
new_word: str,
|
new_word: bool,
|
||||||
seq: OptionSpecSeq,
|
seq: OptionSpecSeq,
|
||||||
complete_args: Optional[CompleteArgsFunc] = None
|
complete_args: Optional[CompleteArgsFunc] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
@@ -295,7 +328,7 @@ def complete_cli(
|
|||||||
complete_alias_map(ans, words, new_word, option_map, complete_args)
|
complete_alias_map(ans, words, new_word, option_map, complete_args)
|
||||||
|
|
||||||
|
|
||||||
def complete_remote_command(ans: Completions, cmd_name: str, words: Sequence[str], new_word: str) -> None:
|
def complete_remote_command(ans: Completions, cmd_name: str, words: Sequence[str], new_word: bool) -> None:
|
||||||
aliases, alias_map = options_for_cmd(cmd_name)
|
aliases, alias_map = options_for_cmd(cmd_name)
|
||||||
if not alias_map:
|
if not alias_map:
|
||||||
return
|
return
|
||||||
@@ -358,7 +391,7 @@ def complete_files_and_dirs(
|
|||||||
ans.files_groups.add(files_group_name)
|
ans.files_groups.add(files_group_name)
|
||||||
|
|
||||||
|
|
||||||
def complete_icat_args(ans: Completions, opt: Optional[OptionDict], prefix: str) -> None:
|
def complete_icat_args(ans: Completions, opt: Optional[OptionDict], prefix: str, unknown_args: Delegate) -> None:
|
||||||
from mimetypes import guess_type
|
from mimetypes import guess_type
|
||||||
|
|
||||||
def icat_file_predicate(filename: str) -> bool:
|
def icat_file_predicate(filename: str) -> bool:
|
||||||
@@ -374,7 +407,7 @@ def complete_icat_args(ans: Completions, opt: Optional[OptionDict], prefix: str)
|
|||||||
def remote_files_completer(spec: Tuple[str, Tuple[str, ...]]) -> CompleteArgsFunc:
|
def remote_files_completer(spec: Tuple[str, Tuple[str, ...]]) -> CompleteArgsFunc:
|
||||||
name, matchers = spec
|
name, matchers = spec
|
||||||
|
|
||||||
def complete_files_map(ans: Completions, opt: Optional[OptionDict], prefix: str) -> None:
|
def complete_files_map(ans: Completions, opt: Optional[OptionDict], prefix: str, unknown_args: Delegate) -> None:
|
||||||
|
|
||||||
def predicate(filename: str) -> bool:
|
def predicate(filename: str) -> bool:
|
||||||
for m in matchers:
|
for m in matchers:
|
||||||
@@ -392,14 +425,14 @@ def config_file_predicate(filename: str) -> bool:
|
|||||||
return filename.endswith('.conf')
|
return filename.endswith('.conf')
|
||||||
|
|
||||||
|
|
||||||
def complete_diff_args(ans: Completions, opt: Optional[OptionDict], prefix: str) -> None:
|
def complete_diff_args(ans: Completions, opt: Optional[OptionDict], prefix: str, unknown_args: Delegate) -> None:
|
||||||
if opt is None:
|
if opt is None:
|
||||||
complete_files_and_dirs(ans, prefix, 'Files')
|
complete_files_and_dirs(ans, prefix, 'Files')
|
||||||
elif opt['dest'] == 'config':
|
elif opt['dest'] == 'config':
|
||||||
complete_files_and_dirs(ans, prefix, 'Config Files', config_file_predicate)
|
complete_files_and_dirs(ans, prefix, 'Config Files', config_file_predicate)
|
||||||
|
|
||||||
|
|
||||||
def complete_kitten(ans: Completions, kitten: str, words: Sequence[str], new_word: str) -> None:
|
def complete_kitten(ans: Completions, kitten: str, words: Sequence[str], new_word: bool) -> None:
|
||||||
try:
|
try:
|
||||||
cd = get_kitten_cli_docs(kitten)
|
cd = get_kitten_cli_docs(kitten)
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
@@ -419,7 +452,7 @@ def complete_kitten(ans: Completions, kitten: str, words: Sequence[str], new_wor
|
|||||||
}.get(kitten))
|
}.get(kitten))
|
||||||
|
|
||||||
|
|
||||||
def find_completions(words: Sequence[str], new_word: str, entry_points: Iterable[str], namespaced_entry_points: Iterable[str]) -> Completions:
|
def find_completions(words: Sequence[str], new_word: bool, entry_points: Iterable[str], namespaced_entry_points: Iterable[str]) -> Completions:
|
||||||
ans = Completions()
|
ans = Completions()
|
||||||
if not words or words[0] != 'kitty':
|
if not words or words[0] != 'kitty':
|
||||||
return ans
|
return ans
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import re
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, Callable, Dict, Generator, Iterable, List, Match, Optional, Sequence,
|
Any, Callable, Dict, Generator, Iterable, List, Match, Optional, Sequence,
|
||||||
Set, Tuple, Union, cast, get_type_hints
|
Set, Tuple, Union, get_type_hints
|
||||||
)
|
)
|
||||||
|
|
||||||
from .utils import to_bool
|
from .utils import Choice, to_bool
|
||||||
|
|
||||||
|
|
||||||
def to_string(x: str) -> str:
|
def to_string(x: str) -> str:
|
||||||
@@ -56,6 +56,8 @@ class Option:
|
|||||||
|
|
||||||
if type(self.option_type) is type:
|
if type(self.option_type) is type:
|
||||||
return type_name(self.option_type)
|
return type_name(self.option_type)
|
||||||
|
if isinstance(self.option_type, Choice):
|
||||||
|
return 'typing.Literal[{}]'.format(','.join(f'{x!r}' for x in self.option_type.all_choices))
|
||||||
th = get_type_hints(self.option_type)
|
th = get_type_hints(self.option_type)
|
||||||
try:
|
try:
|
||||||
rettype = th['return']
|
rettype = th['return']
|
||||||
@@ -156,7 +158,7 @@ def remove_markup(text: str) -> str:
|
|||||||
'layouts': 'https://sw.kovidgoyal.net/kitty/index.html#layouts',
|
'layouts': 'https://sw.kovidgoyal.net/kitty/index.html#layouts',
|
||||||
'sessions': 'https://sw.kovidgoyal.net/kitty/index.html#sessions',
|
'sessions': 'https://sw.kovidgoyal.net/kitty/index.html#sessions',
|
||||||
}[m.group(2)]
|
}[m.group(2)]
|
||||||
return cast(str, m.group(2))
|
return str(m.group(2))
|
||||||
|
|
||||||
return re.sub(r':([a-zA-Z0-9]+):`(.+?)`', sub, text, flags=re.DOTALL)
|
return re.sub(r':([a-zA-Z0-9]+):`(.+?)`', sub, text, flags=re.DOTALL)
|
||||||
|
|
||||||
|
|||||||
@@ -68,17 +68,21 @@ def python_string(text: str) -> str:
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def choices(*choices: str) -> Callable[[str], str]:
|
class Choice:
|
||||||
defval = choices[0]
|
|
||||||
uc = frozenset(choices)
|
|
||||||
|
|
||||||
def choice(x: str) -> str:
|
def __init__(self, choices: Sequence[str]):
|
||||||
|
self.defval = choices[0]
|
||||||
|
self.all_choices = frozenset(choices)
|
||||||
|
|
||||||
|
def __call__(self, x: str) -> str:
|
||||||
x = x.lower()
|
x = x.lower()
|
||||||
if x not in uc:
|
if x not in self.all_choices:
|
||||||
x = defval
|
x = self.defval
|
||||||
return x
|
return x
|
||||||
|
|
||||||
return choice
|
|
||||||
|
def choices(*choices: str) -> Choice:
|
||||||
|
return Choice(choices)
|
||||||
|
|
||||||
|
|
||||||
def parse_line(
|
def parse_line(
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import sys
|
|||||||
from contextlib import contextmanager, suppress
|
from contextlib import contextmanager, suppress
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, Callable, Dict, Generator, Iterable, List, Match, NamedTuple,
|
Any, Callable, Dict, Generator, Iterable, List, NamedTuple, Optional,
|
||||||
Optional, Sequence, Set, Tuple, Type, Union
|
Sequence, Set, Tuple, Type, Union
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import fast_data_types as defines
|
from . import fast_data_types as defines
|
||||||
@@ -23,8 +23,8 @@ from .config_data import all_options, parse_mods, type_convert
|
|||||||
from .constants import cache_dir, defconf, is_macos
|
from .constants import cache_dir, defconf, is_macos
|
||||||
from .key_names import get_key_name_lookup, key_name_aliases
|
from .key_names import get_key_name_lookup, key_name_aliases
|
||||||
from .options_stub import Options as OptionsStub
|
from .options_stub import Options as OptionsStub
|
||||||
from .typing import TypedDict
|
from .typing import EdgeLiteral, TypedDict
|
||||||
from .utils import log_error
|
from .utils import expandvars, log_error
|
||||||
|
|
||||||
KeySpec = Tuple[int, bool, int]
|
KeySpec = Tuple[int, bool, int]
|
||||||
KeyMap = Dict[KeySpec, 'KeyAction']
|
KeyMap = Dict[KeySpec, 'KeyAction']
|
||||||
@@ -140,6 +140,20 @@ def float_parse(func: str, rest: str) -> FuncArgsType:
|
|||||||
return func, (float(rest),)
|
return func, (float(rest),)
|
||||||
|
|
||||||
|
|
||||||
|
@func_with_args('signal_child')
|
||||||
|
def signal_child_parse(func: str, rest: str) -> FuncArgsType:
|
||||||
|
import signal
|
||||||
|
signals = []
|
||||||
|
for q in rest.split():
|
||||||
|
try:
|
||||||
|
signum = getattr(signal, q.upper())
|
||||||
|
except AttributeError:
|
||||||
|
log_error(f'Unknown signal: {rest} ignoring')
|
||||||
|
else:
|
||||||
|
signals.append(signum)
|
||||||
|
return func, tuple(signals)
|
||||||
|
|
||||||
|
|
||||||
@func_with_args('change_font_size')
|
@func_with_args('change_font_size')
|
||||||
def parse_change_font_size(func: str, rest: str) -> Tuple[str, Tuple[bool, Optional[str], float]]:
|
def parse_change_font_size(func: str, rest: str) -> Tuple[str, Tuple[bool, Optional[str], float]]:
|
||||||
vals = rest.strip().split(maxsplit=1)
|
vals = rest.strip().split(maxsplit=1)
|
||||||
@@ -240,6 +254,15 @@ def set_colors(func: str, rest: str) -> FuncArgsType:
|
|||||||
return func, r
|
return func, r
|
||||||
|
|
||||||
|
|
||||||
|
@func_with_args('remote_control')
|
||||||
|
def remote_control(func: str, rest: str) -> FuncArgsType:
|
||||||
|
import shlex
|
||||||
|
r = shlex.split(rest)
|
||||||
|
if len(r) < 1:
|
||||||
|
log_error('Too few arguments to remote_control function')
|
||||||
|
return func, r
|
||||||
|
|
||||||
|
|
||||||
@func_with_args('nth_window')
|
@func_with_args('nth_window')
|
||||||
def nth_window(func: str, rest: str) -> FuncArgsType:
|
def nth_window(func: str, rest: str) -> FuncArgsType:
|
||||||
try:
|
try:
|
||||||
@@ -302,7 +325,7 @@ def parse_marker_spec(ftype: str, parts: Sequence[str]) -> Tuple[str, Union[str,
|
|||||||
def toggle_marker(func: str, rest: str) -> FuncArgsType:
|
def toggle_marker(func: str, rest: str) -> FuncArgsType:
|
||||||
parts = rest.split(maxsplit=1)
|
parts = rest.split(maxsplit=1)
|
||||||
if len(parts) != 2:
|
if len(parts) != 2:
|
||||||
raise ValueError('{} if not a valid marker specification'.format(rest))
|
raise ValueError('{} is not a valid marker specification'.format(rest))
|
||||||
ftype, spec = parts
|
ftype, spec = parts
|
||||||
parts = spec.split()
|
parts = spec.split()
|
||||||
return func, list(parse_marker_spec(ftype, parts))
|
return func, list(parse_marker_spec(ftype, parts))
|
||||||
@@ -576,20 +599,6 @@ def handle_deprecated_macos_show_window_title_in_menubar_alias(key: str, val: st
|
|||||||
ans['macos_show_window_title_in'] = macos_show_window_title_in
|
ans['macos_show_window_title_in'] = macos_show_window_title_in
|
||||||
|
|
||||||
|
|
||||||
def expandvars(val: str, env: Dict[str, str]) -> str:
|
|
||||||
|
|
||||||
def sub(m: Match) -> str:
|
|
||||||
key = m.group(1)
|
|
||||||
result = env.get(key)
|
|
||||||
if result is None:
|
|
||||||
result = os.environ.get(key)
|
|
||||||
if result is None:
|
|
||||||
result = m.group()
|
|
||||||
return result
|
|
||||||
|
|
||||||
return re.sub(r'\$\{(\S+?)\}', sub, val)
|
|
||||||
|
|
||||||
|
|
||||||
@special_handler
|
@special_handler
|
||||||
def handle_env(key: str, val: str, ans: Dict[str, Any]) -> None:
|
def handle_env(key: str, val: str, ans: Dict[str, Any]) -> None:
|
||||||
key, val = val.partition('=')[::2]
|
key, val = val.partition('=')[::2]
|
||||||
@@ -730,12 +739,23 @@ def initial_window_size_func(opts: OptionsStub, cached_values: Dict) -> Callable
|
|||||||
# scaling is not needed on Wayland, but is needed on macOS. Not
|
# scaling is not needed on Wayland, but is needed on macOS. Not
|
||||||
# sure about X11.
|
# sure about X11.
|
||||||
xscale = yscale = 1
|
xscale = yscale = 1
|
||||||
|
|
||||||
|
def effective_margin(which: EdgeLiteral) -> float:
|
||||||
|
ans: float = getattr(opts.single_window_margin_width, which)
|
||||||
|
if ans < 0:
|
||||||
|
ans = getattr(opts.window_margin_width, which)
|
||||||
|
return ans
|
||||||
|
|
||||||
if w_unit == 'cells':
|
if w_unit == 'cells':
|
||||||
width = cell_width * w / xscale + (dpi_x / 72) * (opts.window_margin_width + opts.window_padding_width) + 1
|
spacing = effective_margin('left') + effective_margin('right')
|
||||||
|
spacing += opts.window_padding_width.left + opts.window_padding_width.right
|
||||||
|
width = cell_width * w / xscale + (dpi_x / 72) * spacing + 1
|
||||||
else:
|
else:
|
||||||
width = w
|
width = w
|
||||||
if h_unit == 'cells':
|
if h_unit == 'cells':
|
||||||
height = cell_height * h / yscale + (dpi_y / 72) * (opts.window_margin_width + opts.window_padding_width) + 1
|
spacing = effective_margin('top') + effective_margin('bottom')
|
||||||
|
spacing += opts.window_padding_width.top + opts.window_padding_width.bottom
|
||||||
|
height = cell_height * h / yscale + (dpi_y / 72) * spacing + 1
|
||||||
else:
|
else:
|
||||||
height = h
|
height = h
|
||||||
return int(width), int(height)
|
return int(width), int(height)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
import os
|
import os
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, Dict, FrozenSet, Iterable, List, Optional, Sequence, Set, Tuple,
|
Any, Callable, Dict, FrozenSet, Iterable, List, Optional, Sequence, Set,
|
||||||
TypeVar, Union
|
Tuple, TypeVar, Union
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import fast_data_types as defines
|
from . import fast_data_types as defines
|
||||||
@@ -16,9 +16,9 @@ from .conf.utils import (
|
|||||||
choices, positive_float, positive_int, to_bool, to_cmdline, to_color,
|
choices, positive_float, positive_int, to_bool, to_cmdline, to_color,
|
||||||
to_color_or_none, unit_float
|
to_color_or_none, unit_float
|
||||||
)
|
)
|
||||||
from .constants import config_dir, is_macos
|
from .constants import FloatEdges, config_dir, is_macos
|
||||||
from .fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE
|
from .fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE
|
||||||
from .layout import all_layouts
|
from .layout.interface import all_layouts
|
||||||
from .rgb import Color, color_as_int, color_as_sharp, color_from_int
|
from .rgb import Color, color_as_int, color_as_sharp, color_from_int
|
||||||
from .utils import log_error
|
from .utils import log_error
|
||||||
|
|
||||||
@@ -304,6 +304,9 @@ or by defining shortcuts for it in kitty.conf, for example::
|
|||||||
map alt+2 disable_ligatures_in all never
|
map alt+2 disable_ligatures_in all never
|
||||||
map alt+3 disable_ligatures_in tab cursor
|
map alt+3 disable_ligatures_in tab cursor
|
||||||
|
|
||||||
|
Note that this refers to programming ligatures, typically implemented using the
|
||||||
|
:code:`calt` OpenType feature. For disabling general ligatures, use the
|
||||||
|
:opt:`font_features` setting.
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
o('font_features', 'none', long_text=_('''
|
o('font_features', 'none', long_text=_('''
|
||||||
@@ -445,7 +448,8 @@ Program with which to view scrollback in a new window. The scrollback buffer is
|
|||||||
passed as STDIN to this program. If you change it, make sure the program you
|
passed as STDIN to this program. If you change it, make sure the program you
|
||||||
use can handle ANSI escape sequences for colors and text formatting.
|
use can handle ANSI escape sequences for colors and text formatting.
|
||||||
INPUT_LINE_NUMBER in the command line above will be replaced by an integer
|
INPUT_LINE_NUMBER in the command line above will be replaced by an integer
|
||||||
representing which line should be at the top of the screen.'''))
|
representing which line should be at the top of the screen. Similarly CURSOR_LINE and CURSOR_COLUMN
|
||||||
|
will be replaced by the current cursor position.'''))
|
||||||
|
|
||||||
o('scrollback_pager_history_size', 0, option_type=scrollback_pager_history_size, long_text=_('''
|
o('scrollback_pager_history_size', 0, option_type=scrollback_pager_history_size, long_text=_('''
|
||||||
Separate scrollback history size, used only for browsing the scrollback buffer (in MB).
|
Separate scrollback history size, used only for browsing the scrollback buffer (in MB).
|
||||||
@@ -548,7 +552,7 @@ rectangular block with the mouse)'''))
|
|||||||
o('terminal_select_modifiers', 'shift', option_type=to_modifiers, long_text=_('''
|
o('terminal_select_modifiers', 'shift', option_type=to_modifiers, long_text=_('''
|
||||||
The modifiers to override mouse selection even when a terminal application has grabbed the mouse'''))
|
The modifiers to override mouse selection even when a terminal application has grabbed the mouse'''))
|
||||||
|
|
||||||
o('select_by_word_characters', ':@-./_~?&=%+#', long_text=_('''
|
o('select_by_word_characters', '@-./_~?&=%+#', long_text=_('''
|
||||||
Characters considered part of a word when double clicking. In addition to these characters
|
Characters considered part of a word when double clicking. In addition to these characters
|
||||||
any character that is marked as an alphanumeric character in the unicode
|
any character that is marked as an alphanumeric character in the unicode
|
||||||
database will be matched.'''))
|
database will be matched.'''))
|
||||||
@@ -675,15 +679,42 @@ that separate the inactive window from a neighbor. Note that setting
|
|||||||
a non-zero window margin overrides this and causes all borders to be drawn.
|
a non-zero window margin overrides this and causes all borders to be drawn.
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
o('window_margin_width', 0.0, option_type=positive_float, long_text=_('''
|
|
||||||
The window margin (in pts) (blank area outside the border)'''))
|
|
||||||
|
|
||||||
o('single_window_margin_width', -1000.0, option_type=float, long_text=_('''
|
def edge_width(x: str, converter: Callable[[str], float] = positive_float) -> FloatEdges:
|
||||||
|
parts = str(x).split()
|
||||||
|
num = len(parts)
|
||||||
|
if num == 1:
|
||||||
|
val = converter(parts[0])
|
||||||
|
return FloatEdges(val, val, val, val)
|
||||||
|
if num == 2:
|
||||||
|
v = converter(parts[0])
|
||||||
|
h = converter(parts[1])
|
||||||
|
return FloatEdges(h, v, h, v)
|
||||||
|
if num == 3:
|
||||||
|
top, h, bottom = map(converter, parts)
|
||||||
|
return FloatEdges(h, top, h, bottom)
|
||||||
|
top, right, bottom, left = map(converter, parts)
|
||||||
|
return FloatEdges(left, top, right, bottom)
|
||||||
|
|
||||||
|
|
||||||
|
def optional_edge_width(x: str) -> FloatEdges:
|
||||||
|
return edge_width(x, float)
|
||||||
|
|
||||||
|
|
||||||
|
edge_desc = _(
|
||||||
|
'A single value sets all four sides. Two values set the vertical and horizontal sides.'
|
||||||
|
' Three values set top, horizontal and bottom. Four values set top, right, bottom and left.')
|
||||||
|
|
||||||
|
|
||||||
|
o('window_margin_width', '0', option_type=edge_width, long_text=_('''
|
||||||
|
The window margin (in pts) (blank area outside the border). ''' + edge_desc))
|
||||||
|
|
||||||
|
o('single_window_margin_width', '-1', option_type=optional_edge_width, long_text=_('''
|
||||||
The window margin (in pts) to use when only a single window is visible.
|
The window margin (in pts) to use when only a single window is visible.
|
||||||
Negative values will cause the value of :opt:`window_margin_width` to be used instead.'''))
|
Negative values will cause the value of :opt:`window_margin_width` to be used instead. ''' + edge_desc))
|
||||||
|
|
||||||
o('window_padding_width', 0.0, option_type=positive_float, long_text=_('''
|
o('window_padding_width', '0', option_type=edge_width, long_text=_('''
|
||||||
The window padding (in pts) (blank area between the text and the window border)'''))
|
The window padding (in pts) (blank area between the text and the window border). ''' + edge_desc))
|
||||||
|
|
||||||
o('placement_strategy', 'center', option_type=choices('center', 'top-left'), long_text=_('''
|
o('placement_strategy', 'center', option_type=choices('center', 'top-left'), long_text=_('''
|
||||||
When the window size is not an exact multiple of the cell size, the cell area of the terminal
|
When the window size is not an exact multiple of the cell size, the cell area of the terminal
|
||||||
@@ -751,6 +782,12 @@ this option can be used to keep the margins as small as possible when resizing t
|
|||||||
Note that this does not currently work on Wayland.
|
Note that this does not currently work on Wayland.
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
o('confirm_os_window_close', 0, option_type=positive_int, long_text=_('''
|
||||||
|
Ask for confirmation when closing an OS window that has at least this
|
||||||
|
number of kitty windows in it. A value of zero disables confirmation.
|
||||||
|
This confirmation also applies to requests to quit the entire application (all
|
||||||
|
OS windows, via the quite action).
|
||||||
|
'''))
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
g('tabbar') # {{{
|
g('tabbar') # {{{
|
||||||
@@ -761,6 +798,8 @@ def tab_separator(x: str) -> str:
|
|||||||
for q in '\'"':
|
for q in '\'"':
|
||||||
if x.startswith(q) and x.endswith(q):
|
if x.startswith(q) and x.endswith(q):
|
||||||
x = x[1:-1]
|
x = x[1:-1]
|
||||||
|
if not x:
|
||||||
|
return ''
|
||||||
break
|
break
|
||||||
if not x.strip():
|
if not x.strip():
|
||||||
x = ('\xa0' * len(x)) if x else default_tab_separator
|
x = ('\xa0' * len(x)) if x else default_tab_separator
|
||||||
@@ -843,6 +882,11 @@ A template to render the tab title. The default just renders
|
|||||||
the title. If you wish to include the tab-index as well,
|
the title. If you wish to include the tab-index as well,
|
||||||
use something like: :code:`{index}: {title}`. Useful
|
use something like: :code:`{index}: {title}`. Useful
|
||||||
if you have shortcuts mapped for :code:`goto_tab N`.
|
if you have shortcuts mapped for :code:`goto_tab N`.
|
||||||
|
In addition you can use :code:`{layout_name}` for the current
|
||||||
|
layout name and :code:`{num_windows}` for the number of windows
|
||||||
|
in the tab. Note that formatting is done by Python's string formatting
|
||||||
|
machinery, so you can use, for instance, :code:`{layout_name[:2].upper()}` to
|
||||||
|
show only the first two letters of the layout name, upper-cased.
|
||||||
'''))
|
'''))
|
||||||
o('active_tab_title_template', 'none', option_type=active_tab_title_template, long_text=_('''
|
o('active_tab_title_template', 'none', option_type=active_tab_title_template, long_text=_('''
|
||||||
Template to use for active tabs, if not specified falls back
|
Template to use for active tabs, if not specified falls back
|
||||||
@@ -1012,6 +1056,19 @@ you want to prevent programs running on a remote computer over ssh from
|
|||||||
controlling kitty.
|
controlling kitty.
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
|
||||||
|
o('listen_on', 'none', long_text=_('''
|
||||||
|
Tell kitty to listen to the specified unix/tcp socket for remote control
|
||||||
|
connections. Note that this will apply to all kitty instances. It can be
|
||||||
|
overridden by the :option:`kitty --listen-on` command line flag. This
|
||||||
|
option accepts only UNIX sockets, such as unix:${TEMP}/mykitty or (on Linux)
|
||||||
|
unix:@mykitty. Environment variables are expanded. If {kitty_pid} is present
|
||||||
|
then it is replaced by the PID of the kitty process, otherwise the PID of the kitty
|
||||||
|
process is appended to the value, with a hyphen. This option is ignored unless
|
||||||
|
you also set :opt:`allow_remote_control` to enable remote control. See the
|
||||||
|
help for :option:`kitty --listen-on` for more details.
|
||||||
|
'''))
|
||||||
|
|
||||||
o(
|
o(
|
||||||
'+env', '',
|
'+env', '',
|
||||||
add_to_default=False,
|
add_to_default=False,
|
||||||
@@ -1329,8 +1386,7 @@ if is_macos:
|
|||||||
k('close_tab', 'kitty_mod+q', 'close_tab', _('Close tab'))
|
k('close_tab', 'kitty_mod+q', 'close_tab', _('Close tab'))
|
||||||
if is_macos:
|
if is_macos:
|
||||||
k('close_tab', 'cmd+w', 'close_tab', _('Close tab'), add_to_docs=False)
|
k('close_tab', 'cmd+w', 'close_tab', _('Close tab'), add_to_docs=False)
|
||||||
# Not yet implemented
|
k('close_os_window', 'shift+cmd+w', 'close_os_window', _('Close OS window'), add_to_docs=False)
|
||||||
# k('close_os_window', 'shift+cmd+w', 'close_os_window', _('Close os window'), add_to_docs=False)
|
|
||||||
k('move_tab_forward', 'kitty_mod+.', 'move_tab_forward', _('Move tab forward'))
|
k('move_tab_forward', 'kitty_mod+.', 'move_tab_forward', _('Move tab forward'))
|
||||||
k('move_tab_backward', 'kitty_mod+,', 'move_tab_backward', _('Move tab backward'))
|
k('move_tab_backward', 'kitty_mod+,', 'move_tab_backward', _('Move tab backward'))
|
||||||
k('set_tab_title', 'kitty_mod+alt+t', 'set_tab_title', _('Set tab title'))
|
k('set_tab_title', 'kitty_mod+alt+t', 'set_tab_title', _('Set tab title'))
|
||||||
|
|||||||
@@ -20,13 +20,27 @@ class Version(NamedTuple):
|
|||||||
|
|
||||||
|
|
||||||
appname: str = 'kitty'
|
appname: str = 'kitty'
|
||||||
version: Version = Version(0, 17, 0)
|
version: Version = Version(0, 18, 1)
|
||||||
str_version: str = '.'.join(map(str, version))
|
str_version: str = '.'.join(map(str, version))
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_macos: bool = 'darwin' in _plat
|
is_macos: bool = 'darwin' in _plat
|
||||||
base = os.path.dirname(os.path.abspath(__file__))
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
class Edges(NamedTuple):
|
||||||
|
left: int = 0
|
||||||
|
top: int = 0
|
||||||
|
right: int = 0
|
||||||
|
bottom: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
class FloatEdges(NamedTuple):
|
||||||
|
left: float = 0
|
||||||
|
top: float = 0
|
||||||
|
right: float = 0
|
||||||
|
bottom: float = 0
|
||||||
|
|
||||||
|
|
||||||
class ScreenGeometry(NamedTuple):
|
class ScreenGeometry(NamedTuple):
|
||||||
xstart: float
|
xstart: float
|
||||||
ystart: float
|
ystart: float
|
||||||
@@ -43,6 +57,7 @@ class WindowGeometry(NamedTuple):
|
|||||||
bottom: int
|
bottom: int
|
||||||
xnum: int
|
xnum: int
|
||||||
ynum: int
|
ynum: int
|
||||||
|
spaces: Edges = Edges()
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=2)
|
@lru_cache(maxsize=2)
|
||||||
@@ -198,3 +213,10 @@ def running_in_kitty(set_val: Optional[bool] = None) -> bool:
|
|||||||
if set_val is not None:
|
if set_val is not None:
|
||||||
setattr(running_in_kitty, 'ans', set_val)
|
setattr(running_in_kitty, 'ans', set_val)
|
||||||
return bool(getattr(running_in_kitty, 'ans', False))
|
return bool(getattr(running_in_kitty, 'ans', False))
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_custom_file(path: str) -> str:
|
||||||
|
path = os.path.expandvars(os.path.expanduser(path))
|
||||||
|
if not os.path.isabs(path):
|
||||||
|
path = os.path.join(config_dir, path)
|
||||||
|
return path
|
||||||
|
|||||||
@@ -188,6 +188,9 @@
|
|||||||
// *Horizontal position relative*: Same as :data:`CUF`.
|
// *Horizontal position relative*: Same as :data:`CUF`.
|
||||||
#define HPR 'a'
|
#define HPR 'a'
|
||||||
|
|
||||||
|
// Repeat the preceding graphic character Ps times.
|
||||||
|
#define REP 'b'
|
||||||
|
|
||||||
// *Device Attributes*.
|
// *Device Attributes*.
|
||||||
#define DA 'c'
|
#define DA 'c'
|
||||||
|
|
||||||
|
|||||||
@@ -92,10 +92,10 @@ font_descriptor_to_python(CTFontDescriptorRef descriptor) {
|
|||||||
NSString *style = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute);
|
NSString *style = (NSString *) CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute);
|
||||||
NSDictionary *traits = (NSDictionary *) CTFontDescriptorCopyAttribute(descriptor, kCTFontTraitsAttribute);
|
NSDictionary *traits = (NSDictionary *) CTFontDescriptorCopyAttribute(descriptor, kCTFontTraitsAttribute);
|
||||||
unsigned int straits = [traits[(id)kCTFontSymbolicTrait] unsignedIntValue];
|
unsigned int straits = [traits[(id)kCTFontSymbolicTrait] unsignedIntValue];
|
||||||
NSNumber *weightVal = traits[(id)kCTFontWeightTrait];
|
float weightVal = [traits[(id)kCTFontWeightTrait] floatValue];
|
||||||
NSNumber *widthVal = traits[(id)kCTFontWidthTrait];
|
float widthVal = [traits[(id)kCTFontWidthTrait] floatValue];
|
||||||
|
|
||||||
PyObject *ans = Py_BuildValue("{ssssssss sOsOsO sfsfsI}",
|
PyObject *ans = Py_BuildValue("{ssssssss sOsOsOsOsOsO sfsfsI}",
|
||||||
"path", [[url path] UTF8String],
|
"path", [[url path] UTF8String],
|
||||||
"postscript_name", [psName UTF8String],
|
"postscript_name", [psName UTF8String],
|
||||||
"family", [family UTF8String],
|
"family", [family UTF8String],
|
||||||
@@ -104,9 +104,12 @@ font_descriptor_to_python(CTFontDescriptorRef descriptor) {
|
|||||||
"bold", (straits & kCTFontBoldTrait) != 0 ? Py_True : Py_False,
|
"bold", (straits & kCTFontBoldTrait) != 0 ? Py_True : Py_False,
|
||||||
"italic", (straits & kCTFontItalicTrait) != 0 ? Py_True : Py_False,
|
"italic", (straits & kCTFontItalicTrait) != 0 ? Py_True : Py_False,
|
||||||
"monospace", (straits & kCTFontMonoSpaceTrait) != 0 ? Py_True : Py_False,
|
"monospace", (straits & kCTFontMonoSpaceTrait) != 0 ? Py_True : Py_False,
|
||||||
|
"expanded", (straits & kCTFontExpandedTrait) != 0 ? Py_True : Py_False,
|
||||||
|
"condensed", (straits & kCTFontCondensedTrait) != 0 ? Py_True : Py_False,
|
||||||
|
"color_glyphs", (straits & kCTFontColorGlyphsTrait) != 0 ? Py_True : Py_False,
|
||||||
|
|
||||||
"weight", [weightVal floatValue],
|
"weight", weightVal,
|
||||||
"width", [widthVal floatValue],
|
"width", widthVal,
|
||||||
"traits", straits
|
"traits", straits
|
||||||
);
|
);
|
||||||
[url release];
|
[url release];
|
||||||
@@ -309,7 +312,7 @@ harfbuzz_font_for_face(PyObject* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness) {
|
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness, unsigned int* strikethrough_position, unsigned int* strikethrough_thickness) {
|
||||||
// See https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
|
// See https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
|
||||||
CTFace *self = (CTFace*)s;
|
CTFace *self = (CTFace*)s;
|
||||||
#define count (128 - 32)
|
#define count (128 - 32)
|
||||||
@@ -329,6 +332,8 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
|
|||||||
*underline_position = (unsigned int)floor(self->ascent - self->underline_position + 0.5);
|
*underline_position = (unsigned int)floor(self->ascent - self->underline_position + 0.5);
|
||||||
*underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
|
*underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
|
||||||
*baseline = (unsigned int)self->ascent;
|
*baseline = (unsigned int)self->ascent;
|
||||||
|
*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));
|
// 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.
|
// Let CoreText's layout engine calculate the line height. Slower, but hopefully more accurate.
|
||||||
#define W "AQWMH_gyl "
|
#define W "AQWMH_gyl "
|
||||||
@@ -500,10 +505,12 @@ do_render(CTFontRef ct_font, bool bold, bool italic, hb_glyph_info_t *info, hb_g
|
|||||||
Region src = {.bottom=cell_height, .right=canvas_width}, dest = {.bottom=cell_height, .right=canvas_width};
|
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(render_buf, canvas, &src, &dest, canvas_width, canvas_width);
|
||||||
}
|
}
|
||||||
if (num_cells > 1) {
|
if (num_cells && (center_glyph || (num_cells == 2 && *was_colored))) {
|
||||||
// center glyphs
|
// center glyphs (two cell emoji, PUA glyphs, ligatures, etc)
|
||||||
CGFloat delta = canvas_width - br.size.width;
|
CGFloat delta = (((CGFloat)canvas_width - br.size.width) / 2.f);
|
||||||
if (delta > 1) right_shift_canvas(canvas, canvas_width, cell_height, (unsigned)(delta / 2.f));
|
// FiraCode ligatures result in negative origins
|
||||||
|
if (br.origin.x > 0) delta -= br.origin.x;
|
||||||
|
if (delta >= 1.f) right_shift_canvas(canvas, canvas_width, cell_height, (unsigned)(delta));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,59 +216,57 @@ PyInit_fast_data_types(void) {
|
|||||||
if (m == NULL) return NULL;
|
if (m == NULL) return NULL;
|
||||||
init_monotonic();
|
init_monotonic();
|
||||||
|
|
||||||
if (m != NULL) {
|
if (!init_logging(m)) return NULL;
|
||||||
if (!init_logging(m)) return NULL;
|
if (!init_LineBuf(m)) return NULL;
|
||||||
if (!init_LineBuf(m)) return NULL;
|
if (!init_HistoryBuf(m)) return NULL;
|
||||||
if (!init_HistoryBuf(m)) return NULL;
|
if (!init_Line(m)) return NULL;
|
||||||
if (!init_Line(m)) return NULL;
|
if (!init_Cursor(m)) return NULL;
|
||||||
if (!init_Cursor(m)) return NULL;
|
if (!init_child_monitor(m)) return NULL;
|
||||||
if (!init_child_monitor(m)) return NULL;
|
if (!init_ColorProfile(m)) return NULL;
|
||||||
if (!init_ColorProfile(m)) return NULL;
|
if (!init_Screen(m)) return NULL;
|
||||||
if (!init_Screen(m)) return NULL;
|
if (!init_glfw(m)) return NULL;
|
||||||
if (!init_glfw(m)) return NULL;
|
if (!init_child(m)) return NULL;
|
||||||
if (!init_child(m)) return NULL;
|
if (!init_state(m)) return NULL;
|
||||||
if (!init_state(m)) return NULL;
|
if (!init_keys(m)) return NULL;
|
||||||
if (!init_keys(m)) return NULL;
|
if (!init_graphics(m)) return NULL;
|
||||||
if (!init_graphics(m)) return NULL;
|
if (!init_shaders(m)) return NULL;
|
||||||
if (!init_shaders(m)) return NULL;
|
if (!init_mouse(m)) return NULL;
|
||||||
if (!init_mouse(m)) return NULL;
|
if (!init_kittens(m)) return NULL;
|
||||||
if (!init_kittens(m)) return NULL;
|
if (!init_png_reader(m)) return NULL;
|
||||||
if (!init_png_reader(m)) return NULL;
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (!init_macos_process_info(m)) return NULL;
|
if (!init_macos_process_info(m)) return NULL;
|
||||||
if (!init_CoreText(m)) return NULL;
|
if (!init_CoreText(m)) return NULL;
|
||||||
if (!init_cocoa(m)) return NULL;
|
if (!init_cocoa(m)) return NULL;
|
||||||
#else
|
#else
|
||||||
if (!init_freetype_library(m)) return NULL;
|
if (!init_freetype_library(m)) return NULL;
|
||||||
if (!init_fontconfig_library(m)) return NULL;
|
if (!init_fontconfig_library(m)) return NULL;
|
||||||
if (!init_desktop(m)) return NULL;
|
if (!init_desktop(m)) return NULL;
|
||||||
#endif
|
#endif
|
||||||
if (!init_fonts(m)) return NULL;
|
if (!init_fonts(m)) return NULL;
|
||||||
|
|
||||||
PyModule_AddIntConstant(m, "BOLD", BOLD_SHIFT);
|
PyModule_AddIntConstant(m, "BOLD", BOLD_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "ITALIC", ITALIC_SHIFT);
|
PyModule_AddIntConstant(m, "ITALIC", ITALIC_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
|
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
|
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "DIM", DIM_SHIFT);
|
PyModule_AddIntConstant(m, "DIM", DIM_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT);
|
PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "MARK", MARK_SHIFT);
|
PyModule_AddIntConstant(m, "MARK", MARK_SHIFT);
|
||||||
PyModule_AddIntConstant(m, "MARK_MASK", MARK_MASK);
|
PyModule_AddIntConstant(m, "MARK_MASK", MARK_MASK);
|
||||||
PyModule_AddStringMacro(m, ERROR_PREFIX);
|
PyModule_AddStringMacro(m, ERROR_PREFIX);
|
||||||
#ifdef KITTY_VCS_REV
|
#ifdef KITTY_VCS_REV
|
||||||
PyModule_AddStringMacro(m, KITTY_VCS_REV);
|
PyModule_AddStringMacro(m, KITTY_VCS_REV);
|
||||||
#endif
|
#endif
|
||||||
PyModule_AddIntMacro(m, CURSOR_BLOCK);
|
PyModule_AddIntMacro(m, CURSOR_BLOCK);
|
||||||
PyModule_AddIntMacro(m, CURSOR_BEAM);
|
PyModule_AddIntMacro(m, CURSOR_BEAM);
|
||||||
PyModule_AddIntMacro(m, CURSOR_UNDERLINE);
|
PyModule_AddIntMacro(m, CURSOR_UNDERLINE);
|
||||||
PyModule_AddIntMacro(m, DECAWM);
|
PyModule_AddIntMacro(m, DECAWM);
|
||||||
PyModule_AddIntMacro(m, DECCOLM);
|
PyModule_AddIntMacro(m, DECCOLM);
|
||||||
PyModule_AddIntMacro(m, DECOM);
|
PyModule_AddIntMacro(m, DECOM);
|
||||||
PyModule_AddIntMacro(m, IRM);
|
PyModule_AddIntMacro(m, IRM);
|
||||||
PyModule_AddIntMacro(m, CSI);
|
PyModule_AddIntMacro(m, CSI);
|
||||||
PyModule_AddIntMacro(m, DCS);
|
PyModule_AddIntMacro(m, DCS);
|
||||||
PyModule_AddIntMacro(m, APC);
|
PyModule_AddIntMacro(m, APC);
|
||||||
PyModule_AddIntMacro(m, OSC);
|
PyModule_AddIntMacro(m, OSC);
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,17 +253,6 @@ typedef struct {FONTS_DATA_HEAD} *FONTS_DATA_HANDLE;
|
|||||||
|
|
||||||
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;
|
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;
|
||||||
|
|
||||||
#define left_shift_line(line, at, num) { \
|
|
||||||
for(index_type __i__ = (at); __i__ < (line)->xnum - (num); __i__++) { \
|
|
||||||
COPY_CELL(line, __i__ + (num), line, __i__) \
|
|
||||||
} \
|
|
||||||
if ((((line)->gpu_cells[(at)].attrs) & WIDTH_MASK) != 1) { \
|
|
||||||
(line)->cpu_cells[(at)].ch = BLANK_CHAR; \
|
|
||||||
(line)->gpu_cells[(at)].attrs = BLANK_CHAR ? 1 : 0; \
|
|
||||||
clear_sprite_position((line)->gpu_cells[(at)]); \
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ensure_space_for(base, array, type, num, capacity, initial_cap, zero_mem) \
|
#define ensure_space_for(base, array, type, num, capacity, initial_cap, zero_mem) \
|
||||||
if ((base)->capacity < num) { \
|
if ((base)->capacity < num) { \
|
||||||
size_t _newcap = MAX((size_t)initial_cap, MAX(2 * (base)->capacity, (size_t)num)); \
|
size_t _newcap = MAX((size_t)initial_cap, MAX(2 * (base)->capacity, (size_t)num)); \
|
||||||
@@ -313,8 +302,7 @@ void set_mouse_cursor(MouseShape);
|
|||||||
void enter_event(void);
|
void enter_event(void);
|
||||||
void mouse_event(int, int, int);
|
void mouse_event(int, int, int);
|
||||||
void focus_in_event(void);
|
void focus_in_event(void);
|
||||||
void scroll_event(double, double, int);
|
void scroll_event(double, double, int, int);
|
||||||
void fake_scroll(int, bool);
|
|
||||||
void set_special_key_combo(int glfw_key, int mods, bool is_native);
|
void set_special_key_combo(int glfw_key, int mods, bool is_native);
|
||||||
void on_key_input(GLFWkeyevent *ev);
|
void on_key_input(GLFWkeyevent *ev);
|
||||||
void request_window_attention(id_type, bool);
|
void request_window_attention(id_type, bool);
|
||||||
|
|||||||
@@ -30,18 +30,26 @@ static void* libsn_handle = NULL;
|
|||||||
static PyObject*
|
static PyObject*
|
||||||
init_x11_startup_notification(PyObject UNUSED *self, PyObject *args) {
|
init_x11_startup_notification(PyObject UNUSED *self, PyObject *args) {
|
||||||
static bool done = false;
|
static bool done = false;
|
||||||
static const char* libname = "libstartup-notification-1.so";
|
|
||||||
// some installs are missing the .so symlink, so try the full name
|
|
||||||
static const char* libname2 = "libstartup-notification-1.so.0";
|
|
||||||
static const char* libname3 = "libstartup-notification-1.so.0.0.0";
|
|
||||||
if (!done) {
|
if (!done) {
|
||||||
done = true;
|
done = true;
|
||||||
|
|
||||||
libsn_handle = dlopen(libname, RTLD_LAZY);
|
const char* libnames[] = {
|
||||||
if (libsn_handle == NULL) libsn_handle = dlopen(libname2, RTLD_LAZY);
|
#if defined(_KITTY_STARTUP_NOTIFICATION_LIBRARY)
|
||||||
if (libsn_handle == NULL) libsn_handle = dlopen(libname3, RTLD_LAZY);
|
_KITTY_STARTUP_NOTIFICATION_LIBRARY,
|
||||||
|
#else
|
||||||
|
"libstartup-notification-1.so",
|
||||||
|
// some installs are missing the .so symlink, so try the full name
|
||||||
|
"libstartup-notification-1.so.0",
|
||||||
|
"libstartup-notification-1.so.0.0.0",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
for (int i = 0; libnames[i]; i++) {
|
||||||
|
libsn_handle = dlopen(libnames[i], RTLD_LAZY);
|
||||||
|
if (libsn_handle) break;
|
||||||
|
}
|
||||||
if (libsn_handle == NULL) {
|
if (libsn_handle == NULL) {
|
||||||
PyErr_Format(PyExc_OSError, "Failed to load %s with error: %s", libname, dlerror());
|
PyErr_Format(PyExc_OSError, "Failed to load %s with error: %s", libnames[0], dlerror());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
dlerror(); /* Clear any existing error */
|
dlerror(); /* Clear any existing error */
|
||||||
@@ -105,18 +113,26 @@ load_libcanberra_functions(void) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
load_libcanberra(void) {
|
load_libcanberra(void) {
|
||||||
static const char* libname = "libcanberra.so";
|
|
||||||
// some installs are missing the .so symlink, so try the full name
|
|
||||||
static const char* libname2 = "libcanberra.so.0";
|
|
||||||
static const char* libname3 = "libcanberra.so.0.2.5";
|
|
||||||
static bool done = false;
|
static bool done = false;
|
||||||
if (done) return;
|
if (done) return;
|
||||||
done = true;
|
done = true;
|
||||||
libcanberra_handle = dlopen(libname, RTLD_LAZY);
|
const char* libnames[] = {
|
||||||
if (libcanberra_handle == NULL) libcanberra_handle = dlopen(libname2, RTLD_LAZY);
|
#if defined(_KITTY_CANBERRA_LIBRARY)
|
||||||
if (libcanberra_handle == NULL) libcanberra_handle = dlopen(libname3, RTLD_LAZY);
|
_KITTY_CANBERRA_LIBRARY,
|
||||||
|
#else
|
||||||
|
"libcanberra.so",
|
||||||
|
// some installs are missing the .so symlink, so try the full name
|
||||||
|
"libcanberra.so.0",
|
||||||
|
"libcanberra.so.0.2.5",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
for (int i = 0; libnames[i]; i++) {
|
||||||
|
libcanberra_handle = dlopen(libnames[i], RTLD_LAZY);
|
||||||
|
if (libcanberra_handle) break;
|
||||||
|
}
|
||||||
if (libcanberra_handle == NULL) {
|
if (libcanberra_handle == NULL) {
|
||||||
fprintf(stderr, "Failed to load %s, cannot play beep sound, with error: %s\n", libname, dlerror());
|
fprintf(stderr, "Failed to load %s, cannot play beep sound, with error: %s\n", libnames[0], dlerror());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
load_libcanberra_functions();
|
load_libcanberra_functions();
|
||||||
|
|||||||
259
kitty/emoji.h
generated
259
kitty/emoji.h
generated
@@ -1,4 +1,4 @@
|
|||||||
// unicode data, built from the unicode standard on: 2019-10-01
|
// unicode data, built from the unicode standard on: 2020-04-06
|
||||||
// see gen-wcwidth.py
|
// see gen-wcwidth.py
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
@@ -18,14 +18,10 @@ is_emoji(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0xae:
|
case 0xae:
|
||||||
return true;
|
return true;
|
||||||
case 0x200d:
|
|
||||||
return true;
|
|
||||||
case 0x203c:
|
case 0x203c:
|
||||||
return true;
|
return true;
|
||||||
case 0x2049:
|
case 0x2049:
|
||||||
return true;
|
return true;
|
||||||
case 0x20e3:
|
|
||||||
return true;
|
|
||||||
case 0x2122:
|
case 0x2122:
|
||||||
return true;
|
return true;
|
||||||
case 0x2139:
|
case 0x2139:
|
||||||
@@ -38,8 +34,6 @@ is_emoji(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x2328:
|
case 0x2328:
|
||||||
return true;
|
return true;
|
||||||
case 0x2388:
|
|
||||||
return true;
|
|
||||||
case 0x23cf:
|
case 0x23cf:
|
||||||
return true;
|
return true;
|
||||||
case 0x23e9 ... 0x23f3:
|
case 0x23e9 ... 0x23f3:
|
||||||
@@ -56,15 +50,91 @@ is_emoji(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x25fb ... 0x25fe:
|
case 0x25fb ... 0x25fe:
|
||||||
return true;
|
return true;
|
||||||
case 0x2600 ... 0x2605:
|
case 0x2600 ... 0x2604:
|
||||||
return true;
|
return true;
|
||||||
case 0x2607 ... 0x2612:
|
case 0x260e:
|
||||||
return true;
|
return true;
|
||||||
case 0x2614 ... 0x2685:
|
case 0x2611:
|
||||||
return true;
|
return true;
|
||||||
case 0x2690 ... 0x2705:
|
case 0x2614 ... 0x2615:
|
||||||
return true;
|
return true;
|
||||||
case 0x2708 ... 0x2712:
|
case 0x2618:
|
||||||
|
return true;
|
||||||
|
case 0x261d:
|
||||||
|
return true;
|
||||||
|
case 0x2620:
|
||||||
|
return true;
|
||||||
|
case 0x2622 ... 0x2623:
|
||||||
|
return true;
|
||||||
|
case 0x2626:
|
||||||
|
return true;
|
||||||
|
case 0x262a:
|
||||||
|
return true;
|
||||||
|
case 0x262e ... 0x262f:
|
||||||
|
return true;
|
||||||
|
case 0x2638 ... 0x263a:
|
||||||
|
return true;
|
||||||
|
case 0x2640:
|
||||||
|
return true;
|
||||||
|
case 0x2642:
|
||||||
|
return true;
|
||||||
|
case 0x2648 ... 0x2653:
|
||||||
|
return true;
|
||||||
|
case 0x265f ... 0x2660:
|
||||||
|
return true;
|
||||||
|
case 0x2663:
|
||||||
|
return true;
|
||||||
|
case 0x2665 ... 0x2666:
|
||||||
|
return true;
|
||||||
|
case 0x2668:
|
||||||
|
return true;
|
||||||
|
case 0x267b:
|
||||||
|
return true;
|
||||||
|
case 0x267e ... 0x267f:
|
||||||
|
return true;
|
||||||
|
case 0x2692 ... 0x2697:
|
||||||
|
return true;
|
||||||
|
case 0x2699:
|
||||||
|
return true;
|
||||||
|
case 0x269b ... 0x269c:
|
||||||
|
return true;
|
||||||
|
case 0x26a0 ... 0x26a1:
|
||||||
|
return true;
|
||||||
|
case 0x26a7:
|
||||||
|
return true;
|
||||||
|
case 0x26aa ... 0x26ab:
|
||||||
|
return true;
|
||||||
|
case 0x26b0 ... 0x26b1:
|
||||||
|
return true;
|
||||||
|
case 0x26bd ... 0x26be:
|
||||||
|
return true;
|
||||||
|
case 0x26c4 ... 0x26c5:
|
||||||
|
return true;
|
||||||
|
case 0x26c8:
|
||||||
|
return true;
|
||||||
|
case 0x26ce ... 0x26cf:
|
||||||
|
return true;
|
||||||
|
case 0x26d1:
|
||||||
|
return true;
|
||||||
|
case 0x26d3 ... 0x26d4:
|
||||||
|
return true;
|
||||||
|
case 0x26e9 ... 0x26ea:
|
||||||
|
return true;
|
||||||
|
case 0x26f0 ... 0x26f5:
|
||||||
|
return true;
|
||||||
|
case 0x26f7 ... 0x26fa:
|
||||||
|
return true;
|
||||||
|
case 0x26fd:
|
||||||
|
return true;
|
||||||
|
case 0x2702:
|
||||||
|
return true;
|
||||||
|
case 0x2705:
|
||||||
|
return true;
|
||||||
|
case 0x2708 ... 0x270d:
|
||||||
|
return true;
|
||||||
|
case 0x270f:
|
||||||
|
return true;
|
||||||
|
case 0x2712:
|
||||||
return true;
|
return true;
|
||||||
case 0x2714:
|
case 0x2714:
|
||||||
return true;
|
return true;
|
||||||
@@ -90,7 +160,7 @@ is_emoji(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x2757:
|
case 0x2757:
|
||||||
return true;
|
return true;
|
||||||
case 0x2763 ... 0x2767:
|
case 0x2763 ... 0x2764:
|
||||||
return true;
|
return true;
|
||||||
case 0x2795 ... 0x2797:
|
case 0x2795 ... 0x2797:
|
||||||
return true;
|
return true;
|
||||||
@@ -118,15 +188,11 @@ is_emoji(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x3299:
|
case 0x3299:
|
||||||
return true;
|
return true;
|
||||||
case 0xfe0f:
|
case 0x1f004:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f000 ... 0x1f0ff:
|
case 0x1f0cf:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f10d ... 0x1f10f:
|
case 0x1f170 ... 0x1f171:
|
||||||
return true;
|
|
||||||
case 0x1f12f:
|
|
||||||
return true;
|
|
||||||
case 0x1f16c ... 0x1f171:
|
|
||||||
return true;
|
return true;
|
||||||
case 0x1f17e ... 0x1f17f:
|
case 0x1f17e ... 0x1f17f:
|
||||||
return true;
|
return true;
|
||||||
@@ -134,9 +200,9 @@ is_emoji(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x1f191 ... 0x1f19a:
|
case 0x1f191 ... 0x1f19a:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f1ad ... 0x1f1ff:
|
case 0x1f1e6 ... 0x1f1ff:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f201 ... 0x1f20f:
|
case 0x1f201 ... 0x1f202:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f21a:
|
case 0x1f21a:
|
||||||
return true;
|
return true;
|
||||||
@@ -144,44 +210,107 @@ is_emoji(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x1f232 ... 0x1f23a:
|
case 0x1f232 ... 0x1f23a:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f23c ... 0x1f23f:
|
case 0x1f250 ... 0x1f251:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f249 ... 0x1f53d:
|
case 0x1f300 ... 0x1f321:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f546 ... 0x1f64f:
|
case 0x1f324 ... 0x1f393:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f680 ... 0x1f6ff:
|
case 0x1f396 ... 0x1f397:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f774 ... 0x1f77f:
|
case 0x1f399 ... 0x1f39b:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f7d5 ... 0x1f7ff:
|
case 0x1f39e ... 0x1f3f0:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f80c ... 0x1f80f:
|
case 0x1f3f3 ... 0x1f3f5:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f848 ... 0x1f84f:
|
case 0x1f3f7 ... 0x1f4fd:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f85a ... 0x1f85f:
|
case 0x1f4ff ... 0x1f53d:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f888 ... 0x1f88f:
|
case 0x1f549 ... 0x1f54e:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f8ae ... 0x1f8ff:
|
case 0x1f550 ... 0x1f567:
|
||||||
|
return true;
|
||||||
|
case 0x1f56f ... 0x1f570:
|
||||||
|
return true;
|
||||||
|
case 0x1f573 ... 0x1f57a:
|
||||||
|
return true;
|
||||||
|
case 0x1f587:
|
||||||
|
return true;
|
||||||
|
case 0x1f58a ... 0x1f58d:
|
||||||
|
return true;
|
||||||
|
case 0x1f590:
|
||||||
|
return true;
|
||||||
|
case 0x1f595 ... 0x1f596:
|
||||||
|
return true;
|
||||||
|
case 0x1f5a4 ... 0x1f5a5:
|
||||||
|
return true;
|
||||||
|
case 0x1f5a8:
|
||||||
|
return true;
|
||||||
|
case 0x1f5b1 ... 0x1f5b2:
|
||||||
|
return true;
|
||||||
|
case 0x1f5bc:
|
||||||
|
return true;
|
||||||
|
case 0x1f5c2 ... 0x1f5c4:
|
||||||
|
return true;
|
||||||
|
case 0x1f5d1 ... 0x1f5d3:
|
||||||
|
return true;
|
||||||
|
case 0x1f5dc ... 0x1f5de:
|
||||||
|
return true;
|
||||||
|
case 0x1f5e1:
|
||||||
|
return true;
|
||||||
|
case 0x1f5e3:
|
||||||
|
return true;
|
||||||
|
case 0x1f5e8:
|
||||||
|
return true;
|
||||||
|
case 0x1f5ef:
|
||||||
|
return true;
|
||||||
|
case 0x1f5f3:
|
||||||
|
return true;
|
||||||
|
case 0x1f5fa ... 0x1f64f:
|
||||||
|
return true;
|
||||||
|
case 0x1f680 ... 0x1f6c5:
|
||||||
|
return true;
|
||||||
|
case 0x1f6cb ... 0x1f6d2:
|
||||||
|
return true;
|
||||||
|
case 0x1f6d5 ... 0x1f6d7:
|
||||||
|
return true;
|
||||||
|
case 0x1f6e0 ... 0x1f6e5:
|
||||||
|
return true;
|
||||||
|
case 0x1f6e9:
|
||||||
|
return true;
|
||||||
|
case 0x1f6eb ... 0x1f6ec:
|
||||||
|
return true;
|
||||||
|
case 0x1f6f0:
|
||||||
|
return true;
|
||||||
|
case 0x1f6f3 ... 0x1f6fc:
|
||||||
|
return true;
|
||||||
|
case 0x1f7e0 ... 0x1f7eb:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f90c ... 0x1f93a:
|
case 0x1f90c ... 0x1f93a:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f93c ... 0x1f945:
|
case 0x1f93c ... 0x1f945:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f947 ... 0x1fffd:
|
case 0x1f947 ... 0x1f978:
|
||||||
return true;
|
return true;
|
||||||
case 0xe0020 ... 0xe007f:
|
case 0x1f97a ... 0x1f9cb:
|
||||||
return true;
|
return true;
|
||||||
default: return false;
|
case 0x1f9cd ... 0x1f9ff:
|
||||||
}
|
return true;
|
||||||
return false;
|
case 0x1fa70 ... 0x1fa74:
|
||||||
}
|
return true;
|
||||||
static inline bool
|
case 0x1fa78 ... 0x1fa7a:
|
||||||
is_emoji_modifier(char_type code) {
|
return true;
|
||||||
switch(code) {
|
case 0x1fa80 ... 0x1fa86:
|
||||||
case 0x1f3fb ... 0x1f3ff:
|
return true;
|
||||||
|
case 0x1fa90 ... 0x1faa8:
|
||||||
|
return true;
|
||||||
|
case 0x1fab0 ... 0x1fab6:
|
||||||
|
return true;
|
||||||
|
case 0x1fac0 ... 0x1fac2:
|
||||||
|
return true;
|
||||||
|
case 0x1fad0 ... 0x1fad6:
|
||||||
return true;
|
return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
@@ -390,10 +519,12 @@ is_symbol(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x2b76 ... 0x2b95:
|
case 0x2b76 ... 0x2b95:
|
||||||
return true;
|
return true;
|
||||||
case 0x2b98 ... 0x2bff:
|
case 0x2b97 ... 0x2bff:
|
||||||
return true;
|
return true;
|
||||||
case 0x2ce5 ... 0x2cea:
|
case 0x2ce5 ... 0x2cea:
|
||||||
return true;
|
return true;
|
||||||
|
case 0x2e50 ... 0x2e51:
|
||||||
|
return true;
|
||||||
case 0x2e80 ... 0x2e99:
|
case 0x2e80 ... 0x2e99:
|
||||||
return true;
|
return true;
|
||||||
case 0x2e9b ... 0x2ef3:
|
case 0x2e9b ... 0x2ef3:
|
||||||
@@ -450,6 +581,8 @@ is_symbol(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0xab5b:
|
case 0xab5b:
|
||||||
return true;
|
return true;
|
||||||
|
case 0xab6a ... 0xab6b:
|
||||||
|
return true;
|
||||||
case 0xfb29:
|
case 0xfb29:
|
||||||
return true;
|
return true;
|
||||||
case 0xfbb2 ... 0xfbc1:
|
case 0xfbb2 ... 0xfbc1:
|
||||||
@@ -488,7 +621,7 @@ is_symbol(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x1018c ... 0x1018e:
|
case 0x1018c ... 0x1018e:
|
||||||
return true;
|
return true;
|
||||||
case 0x10190 ... 0x1019b:
|
case 0x10190 ... 0x1019c:
|
||||||
return true;
|
return true;
|
||||||
case 0x101a0:
|
case 0x101a0:
|
||||||
return true;
|
return true;
|
||||||
@@ -582,9 +715,7 @@ is_symbol(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x1f0d1 ... 0x1f0f5:
|
case 0x1f0d1 ... 0x1f0f5:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f110 ... 0x1f16c:
|
case 0x1f10d ... 0x1f1ad:
|
||||||
return true;
|
|
||||||
case 0x1f170 ... 0x1f1ac:
|
|
||||||
return true;
|
return true;
|
||||||
case 0x1f1e6 ... 0x1f202:
|
case 0x1f1e6 ... 0x1f202:
|
||||||
return true;
|
return true;
|
||||||
@@ -596,11 +727,11 @@ is_symbol(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x1f260 ... 0x1f265:
|
case 0x1f260 ... 0x1f265:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f300 ... 0x1f6d5:
|
case 0x1f300 ... 0x1f6d7:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f6e0 ... 0x1f6ec:
|
case 0x1f6e0 ... 0x1f6ec:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f6f0 ... 0x1f6fa:
|
case 0x1f6f0 ... 0x1f6fc:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f700 ... 0x1f773:
|
case 0x1f700 ... 0x1f773:
|
||||||
return true;
|
return true;
|
||||||
@@ -618,29 +749,33 @@ is_symbol(char_type code) {
|
|||||||
return true;
|
return true;
|
||||||
case 0x1f890 ... 0x1f8ad:
|
case 0x1f890 ... 0x1f8ad:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f900 ... 0x1f90b:
|
case 0x1f8b0 ... 0x1f8b1:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f90d ... 0x1f971:
|
case 0x1f900 ... 0x1f978:
|
||||||
return true;
|
return true;
|
||||||
case 0x1f973 ... 0x1f976:
|
case 0x1f97a ... 0x1f9cb:
|
||||||
return true;
|
|
||||||
case 0x1f97a ... 0x1f9a2:
|
|
||||||
return true;
|
|
||||||
case 0x1f9a5 ... 0x1f9aa:
|
|
||||||
return true;
|
|
||||||
case 0x1f9ae ... 0x1f9ca:
|
|
||||||
return true;
|
return true;
|
||||||
case 0x1f9cd ... 0x1fa53:
|
case 0x1f9cd ... 0x1fa53:
|
||||||
return true;
|
return true;
|
||||||
case 0x1fa60 ... 0x1fa6d:
|
case 0x1fa60 ... 0x1fa6d:
|
||||||
return true;
|
return true;
|
||||||
case 0x1fa70 ... 0x1fa73:
|
case 0x1fa70 ... 0x1fa74:
|
||||||
return true;
|
return true;
|
||||||
case 0x1fa78 ... 0x1fa7a:
|
case 0x1fa78 ... 0x1fa7a:
|
||||||
return true;
|
return true;
|
||||||
case 0x1fa80 ... 0x1fa82:
|
case 0x1fa80 ... 0x1fa86:
|
||||||
return true;
|
return true;
|
||||||
case 0x1fa90 ... 0x1fa95:
|
case 0x1fa90 ... 0x1faa8:
|
||||||
|
return true;
|
||||||
|
case 0x1fab0 ... 0x1fab6:
|
||||||
|
return true;
|
||||||
|
case 0x1fac0 ... 0x1fac2:
|
||||||
|
return true;
|
||||||
|
case 0x1fad0 ... 0x1fad6:
|
||||||
|
return true;
|
||||||
|
case 0x1fb00 ... 0x1fb92:
|
||||||
|
return true;
|
||||||
|
case 0x1fb94 ... 0x1fbca:
|
||||||
return true;
|
return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ from kitty.options_stub import Options
|
|||||||
|
|
||||||
# Constants {{{
|
# Constants {{{
|
||||||
KITTY_VCS_REV: str
|
KITTY_VCS_REV: str
|
||||||
|
NO_CLOSE_REQUESTED: int
|
||||||
|
IMPERATIVE_CLOSE_REQUESTED: int
|
||||||
|
CLOSE_BEING_CONFIRMED: int
|
||||||
ERROR_PREFIX: str
|
ERROR_PREFIX: str
|
||||||
GLSL_VERSION: int
|
GLSL_VERSION: int
|
||||||
GLFW_IBEAM_CURSOR: int
|
GLFW_IBEAM_CURSOR: int
|
||||||
@@ -323,9 +326,14 @@ FC_MONO: int = 100
|
|||||||
FC_DUAL: int
|
FC_DUAL: int
|
||||||
FC_WEIGHT_REGULAR: int
|
FC_WEIGHT_REGULAR: int
|
||||||
FC_WEIGHT_BOLD: int
|
FC_WEIGHT_BOLD: int
|
||||||
|
FC_WIDTH_NORMAL: int
|
||||||
FC_SLANT_ROMAN: int
|
FC_SLANT_ROMAN: int
|
||||||
FC_SLANT_ITALIC: int
|
FC_SLANT_ITALIC: int
|
||||||
BORDERS_PROGRAM: int
|
BORDERS_PROGRAM: int
|
||||||
|
PRESS: int
|
||||||
|
RELEASE: int
|
||||||
|
DRAG: int
|
||||||
|
MOVE: int
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
@@ -402,6 +410,7 @@ class FontConfigPattern(TypedDict):
|
|||||||
style: str
|
style: str
|
||||||
spacing: str
|
spacing: str
|
||||||
weight: int
|
weight: int
|
||||||
|
width: int
|
||||||
slant: int
|
slant: int
|
||||||
hint_style: int
|
hint_style: int
|
||||||
subpixel: int
|
subpixel: int
|
||||||
@@ -438,6 +447,9 @@ class CoreTextFont(TypedDict):
|
|||||||
style: str
|
style: str
|
||||||
bold: bool
|
bold: bool
|
||||||
italic: bool
|
italic: bool
|
||||||
|
expanded: bool
|
||||||
|
condensed: bool
|
||||||
|
color_glyphs: bool
|
||||||
monospace: bool
|
monospace: bool
|
||||||
weight: float
|
weight: float
|
||||||
width: float
|
width: float
|
||||||
@@ -535,16 +547,20 @@ def update_window_title(
|
|||||||
|
|
||||||
|
|
||||||
def update_window_visibility(
|
def update_window_visibility(
|
||||||
os_window_id: int, tab_id: int, window_id: int, window_idx: int,
|
os_window_id: int, tab_id: int, window_id: int,
|
||||||
visible: bool
|
visible: bool
|
||||||
) -> None:
|
) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def sync_os_window_title(os_window_id: int) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def set_options(
|
def set_options(
|
||||||
opts: Options,
|
opts: Options,
|
||||||
is_wayland: bool = False,
|
is_wayland: bool = False,
|
||||||
debug_gl: bool = False,
|
debug_rendering: bool = False,
|
||||||
debug_font_fallback: bool = False
|
debug_font_fallback: bool = False
|
||||||
) -> None:
|
) -> None:
|
||||||
pass
|
pass
|
||||||
@@ -693,7 +709,15 @@ def cocoa_get_lang() -> Optional[str]:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def mark_os_window_for_close(os_window_id: int, yes: bool = True) -> bool:
|
def mark_os_window_for_close(os_window_id: int, cr_type: int = 2) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def set_application_quit_request(cr_type: int = 2) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def current_application_quit_request() -> int:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -761,15 +785,11 @@ def swap_tabs(os_window_id: int, a: int, b: int) -> None:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def swap_windows(os_window_id: int, tab_id: int, a: int, b: int) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def set_active_tab(os_window_id: int, a: int) -> None:
|
def set_active_tab(os_window_id: int, a: int) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def set_active_window(os_window_id: int, tab_id: int, window_idx: int) -> None:
|
def set_active_window(os_window_id: int, tab_id: int, window_id: int) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -897,7 +917,7 @@ def set_font_data(
|
|||||||
box_drawing_func: Callable[[int, int, int, float],
|
box_drawing_func: Callable[[int, int, int, float],
|
||||||
Tuple[int, Union[bytearray, bytes, Array]]],
|
Tuple[int, Union[bytearray, bytes, Array]]],
|
||||||
prerender_func: Callable[
|
prerender_func: Callable[
|
||||||
[int, int, int, int, int, float, float, float, float],
|
[int, int, int, int, int, int, int, float, float, float, float],
|
||||||
Tuple[Union[Array, int], ...]],
|
Tuple[Union[Array, int], ...]],
|
||||||
descriptor_for_idx: Callable[[int], Tuple[FontObject, bool, bool]],
|
descriptor_for_idx: Callable[[int], Tuple[FontObject, bool, bool]],
|
||||||
bold: int, italic: int, bold_italic: int, num_symbol_fonts: int,
|
bold: int, italic: int, bold_italic: int, num_symbol_fonts: int,
|
||||||
@@ -1050,7 +1070,7 @@ def set_tab_bar_render_data(
|
|||||||
|
|
||||||
|
|
||||||
def set_window_render_data(
|
def set_window_render_data(
|
||||||
os_window_id: int, tab_id: int, window_id: int, window_idx: int,
|
os_window_id: int, tab_id: int, window_id: int,
|
||||||
xstart: float, ystart: float, dx: float, dy: float, screen: Screen,
|
xstart: float, ystart: float, dx: float, dy: float, screen: Screen,
|
||||||
left: int, top: int, right: int, bottom: int
|
left: int, top: int, right: int, bottom: int
|
||||||
) -> None:
|
) -> None:
|
||||||
@@ -1123,3 +1143,7 @@ def spawn(
|
|||||||
|
|
||||||
def key_to_bytes(glfw_key: int, smkx: bool, extended: bool, mods: int, action: int) -> bytes:
|
def key_to_bytes(glfw_key: int, smkx: bool, extended: bool, mods: int, action: int) -> bytes:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def set_window_padding(os_window_id: int, tab_id: int, window_id: int, left: int, top: int, right: int, bottom: int) -> None:
|
||||||
|
pass
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ pattern_as_dict(FcPattern *pat) {
|
|||||||
S(FC_FULLNAME, full_name);
|
S(FC_FULLNAME, full_name);
|
||||||
S(FC_POSTSCRIPT_NAME, postscript_name);
|
S(FC_POSTSCRIPT_NAME, postscript_name);
|
||||||
I(FC_WEIGHT, weight);
|
I(FC_WEIGHT, weight);
|
||||||
|
I(FC_WIDTH, width)
|
||||||
I(FC_SLANT, slant);
|
I(FC_SLANT, slant);
|
||||||
I(FC_HINT_STYLE, hint_style);
|
I(FC_HINT_STYLE, hint_style);
|
||||||
I(FC_INDEX, index);
|
I(FC_INDEX, index);
|
||||||
@@ -247,5 +248,7 @@ init_fontconfig_library(PyObject *module) {
|
|||||||
PyModule_AddIntMacro(module, FC_DUAL);
|
PyModule_AddIntMacro(module, FC_DUAL);
|
||||||
PyModule_AddIntMacro(module, FC_MONO);
|
PyModule_AddIntMacro(module, FC_MONO);
|
||||||
PyModule_AddIntMacro(module, FC_CHARCELL);
|
PyModule_AddIntMacro(module, FC_CHARCELL);
|
||||||
|
PyModule_AddIntMacro(module, FC_WIDTH_NORMAL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
FONTS_DATA_HEAD
|
FONTS_DATA_HEAD
|
||||||
id_type id;
|
id_type id;
|
||||||
unsigned int baseline, underline_position, underline_thickness;
|
unsigned int baseline, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
|
||||||
size_t fonts_capacity, fonts_count, fallback_fonts_count;
|
size_t fonts_capacity, fonts_count, fallback_fonts_count;
|
||||||
ssize_t medium_font_idx, bold_font_idx, italic_font_idx, bi_font_idx, first_symbol_font_idx, first_fallback_font_idx;
|
ssize_t medium_font_idx, bold_font_idx, italic_font_idx, bi_font_idx, first_symbol_font_idx, first_fallback_font_idx;
|
||||||
Font *fonts;
|
Font *fonts;
|
||||||
@@ -422,8 +422,8 @@ python_send_to_gpu(FONTS_DATA_HANDLE fg, unsigned int x, unsigned int y, unsigne
|
|||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
calc_cell_metrics(FontGroup *fg) {
|
calc_cell_metrics(FontGroup *fg) {
|
||||||
unsigned int cell_height, cell_width, baseline, underline_position, underline_thickness;
|
unsigned int cell_height, cell_width, baseline, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
|
||||||
cell_metrics(fg->fonts[fg->medium_font_idx].face, &cell_width, &cell_height, &baseline, &underline_position, &underline_thickness);
|
cell_metrics(fg->fonts[fg->medium_font_idx].face, &cell_width, &cell_height, &baseline, &underline_position, &underline_thickness, &strikethrough_position, &strikethrough_thickness);
|
||||||
if (!cell_width) fatal("Failed to calculate cell width for the specified font");
|
if (!cell_width) fatal("Failed to calculate cell width for the specified font");
|
||||||
unsigned int before_cell_height = cell_height;
|
unsigned int before_cell_height = cell_height;
|
||||||
int cw = cell_width, ch = cell_height;
|
int cw = cell_width, ch = cell_height;
|
||||||
@@ -455,7 +455,7 @@ calc_cell_metrics(FontGroup *fg) {
|
|||||||
}
|
}
|
||||||
sprite_tracker_set_layout(&fg->sprite_tracker, cell_width, cell_height);
|
sprite_tracker_set_layout(&fg->sprite_tracker, cell_width, cell_height);
|
||||||
fg->cell_width = cell_width; fg->cell_height = cell_height;
|
fg->cell_width = cell_width; fg->cell_height = cell_height;
|
||||||
fg->baseline = baseline; fg->underline_position = underline_position; fg->underline_thickness = underline_thickness;
|
fg->baseline = baseline; fg->underline_position = underline_position; fg->underline_thickness = underline_thickness, fg->strikethrough_position = strikethrough_position, fg->strikethrough_thickness = strikethrough_thickness;
|
||||||
free(fg->canvas);
|
free(fg->canvas);
|
||||||
fg->canvas = calloc(CELLS_IN_CANVAS * fg->cell_width * fg->cell_height, sizeof(pixel));
|
fg->canvas = calloc(CELLS_IN_CANVAS * fg->cell_width * fg->cell_height, sizeof(pixel));
|
||||||
if (!fg->canvas) fatal("Out of memory allocating canvas for font group");
|
if (!fg->canvas) fatal("Out of memory allocating canvas for font group");
|
||||||
@@ -1004,14 +1004,20 @@ merge_groups_for_pua_space_ligature(void) {
|
|||||||
G(groups)->is_space_ligature = true;
|
G(groups)->is_space_ligature = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
is_group_calt_ligature(const Group *group) {
|
||||||
|
GPUCell *first_cell = G(first_gpu_cell) + group->first_cell_idx;
|
||||||
|
return group->num_cells > 1 && group->has_special_glyph && (first_cell->attrs & WIDTH_MASK) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
split_run_at_offset(index_type cursor_offset, index_type *left, index_type *right) {
|
split_run_at_offset(index_type cursor_offset, index_type *left, index_type *right) {
|
||||||
*left = 0; *right = 0;
|
*left = 0; *right = 0;
|
||||||
for (unsigned idx = 0; idx < G(group_idx) + 1; idx++) {
|
for (unsigned idx = 0; idx < G(group_idx) + 1; idx++) {
|
||||||
Group *group = G(groups) + idx;
|
Group *group = G(groups) + idx;
|
||||||
if (group->first_cell_idx <= cursor_offset && cursor_offset < group->first_cell_idx + group->num_cells) {
|
if (group->first_cell_idx <= cursor_offset && cursor_offset < group->first_cell_idx + group->num_cells) {
|
||||||
GPUCell *first_cell = G(first_gpu_cell) + group->first_cell_idx;
|
if (is_group_calt_ligature(group)) {
|
||||||
if (group->num_cells > 1 && group->has_special_glyph && (first_cell->attrs & WIDTH_MASK) == 1) {
|
|
||||||
// likely a calt ligature
|
// likely a calt ligature
|
||||||
*left = group->first_cell_idx; *right = group->first_cell_idx + group->num_cells;
|
*left = group->first_cell_idx; *right = group->first_cell_idx + group->num_cells;
|
||||||
}
|
}
|
||||||
@@ -1039,6 +1045,11 @@ render_groups(FontGroup *fg, Font *font, bool center_glyph) {
|
|||||||
// there exist stupid fonts like Powerline that have no space glyph,
|
// there exist stupid fonts like Powerline that have no space glyph,
|
||||||
// so special case it: https://github.com/kovidgoyal/kitty/issues/1225
|
// so special case it: https://github.com/kovidgoyal/kitty/issues/1225
|
||||||
unsigned int num_glyphs = group->is_space_ligature ? 1 : group->num_glyphs;
|
unsigned int num_glyphs = group->is_space_ligature ? 1 : group->num_glyphs;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// FiraCode ligatures need to be centered on macOS
|
||||||
|
// see https://github.com/kovidgoyal/kitty/issues/2591
|
||||||
|
if (is_group_calt_ligature(group)) center_glyph = true;
|
||||||
|
#endif
|
||||||
render_group(fg, group->num_cells, num_glyphs, G(first_cpu_cell) + group->first_cell_idx, G(first_gpu_cell) + group->first_cell_idx, G(info) + group->first_glyph_idx, G(positions) + group->first_glyph_idx, font, primary, &ed, center_glyph);
|
render_group(fg, group->num_cells, num_glyphs, G(first_cpu_cell) + group->first_cell_idx, G(first_gpu_cell) + group->first_cell_idx, G(info) + group->first_glyph_idx, G(positions) + group->first_glyph_idx, font, primary, &ed, center_glyph);
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
@@ -1243,7 +1254,7 @@ send_prerendered_sprites(FontGroup *fg) {
|
|||||||
current_send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, x, y, z, fg->canvas);
|
current_send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, x, y, z, fg->canvas);
|
||||||
do_increment(fg, &error);
|
do_increment(fg, &error);
|
||||||
if (error != 0) { sprite_map_set_error(error); PyErr_Print(); fatal("Failed"); }
|
if (error != 0) { sprite_map_set_error(error); PyErr_Print(); fatal("Failed"); }
|
||||||
PyObject *args = PyObject_CallFunction(prerender_function, "IIIIIffdd", fg->cell_width, fg->cell_height, fg->baseline, fg->underline_position, fg->underline_thickness, OPT(cursor_beam_thickness), fg->logical_dpi_x, fg->logical_dpi_y);
|
PyObject *args = PyObject_CallFunction(prerender_function, "IIIIIIIffdd", fg->cell_width, fg->cell_height, fg->baseline, fg->underline_position, fg->underline_thickness, fg->strikethrough_position, fg->strikethrough_thickness, OPT(cursor_beam_thickness), OPT(cursor_underline_thickness), fg->logical_dpi_x, fg->logical_dpi_y);
|
||||||
if (args == NULL) { PyErr_Print(); fatal("Failed to pre-render cells"); }
|
if (args == NULL) { PyErr_Print(); fatal("Failed to pre-render cells"); }
|
||||||
for (ssize_t i = 0; i < PyTuple_GET_SIZE(args) - 1; i++) {
|
for (ssize_t i = 0; i < PyTuple_GET_SIZE(args) - 1; i++) {
|
||||||
x = fg->sprite_tracker.x; y = fg->sprite_tracker.y; z = fg->sprite_tracker.z;
|
x = fg->sprite_tracker.x; y = fg->sprite_tracker.y; z = fg->sprite_tracker.z;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ int get_glyph_width(PyObject *, glyph_index);
|
|||||||
bool is_glyph_empty(PyObject *, glyph_index);
|
bool is_glyph_empty(PyObject *, glyph_index);
|
||||||
hb_font_t* harfbuzz_font_for_face(PyObject*);
|
hb_font_t* harfbuzz_font_for_face(PyObject*);
|
||||||
bool set_size_for_face(PyObject*, unsigned int, bool, FONTS_DATA_HANDLE);
|
bool set_size_for_face(PyObject*, unsigned int, bool, FONTS_DATA_HANDLE);
|
||||||
void cell_metrics(PyObject*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
|
void cell_metrics(PyObject*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
|
||||||
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *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, bool center_glyph);
|
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *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, bool center_glyph);
|
||||||
PyObject* create_fallback_face(PyObject *base_face, CPUCell* cell, bool bold, bool italic, bool emoji_presentation, FONTS_DATA_HANDLE fg);
|
PyObject* create_fallback_face(PyObject *base_face, CPUCell* cell, bool bold, bool italic, bool emoji_presentation, FONTS_DATA_HANDLE fg);
|
||||||
PyObject* specialize_font_descriptor(PyObject *base_descriptor, FONTS_DATA_HANDLE);
|
PyObject* specialize_font_descriptor(PyObject *base_descriptor, FONTS_DATA_HANDLE);
|
||||||
|
|||||||
@@ -54,12 +54,16 @@ def find_best_match(family: str, bold: bool = False, italic: bool = False) -> Co
|
|||||||
q = re.sub(r'\s+', ' ', family.lower())
|
q = re.sub(r'\s+', ' ', family.lower())
|
||||||
font_map = all_fonts_map()
|
font_map = all_fonts_map()
|
||||||
|
|
||||||
def score(candidate: CoreTextFont) -> Tuple[int, int]:
|
def score(candidate: CoreTextFont) -> Tuple[int, int, int, float]:
|
||||||
style_match = 1 if candidate['bold'] == bold and candidate[
|
style_match = 1 if candidate['bold'] == bold and candidate[
|
||||||
'italic'
|
'italic'
|
||||||
] == italic else 0
|
] == italic else 0
|
||||||
monospace_match = 1 if candidate['monospace'] else 0
|
monospace_match = 1 if candidate['monospace'] else 0
|
||||||
return style_match, monospace_match
|
is_regular_width = not candidate['expanded'] and not candidate['condensed']
|
||||||
|
# prefer demi-bold to bold to heavy, less bold means less chance of
|
||||||
|
# overflow
|
||||||
|
weight_distance_from_medium = abs(candidate['weight'])
|
||||||
|
return style_match, monospace_match, 1 if is_regular_width else 0, 1 - weight_distance_from_medium
|
||||||
|
|
||||||
# First look for an exact match
|
# First look for an exact match
|
||||||
for selector in ('ps_map', 'full_map'):
|
for selector in ('ps_map', 'full_map'):
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from typing import Dict, Generator, List, Optional, Tuple, cast
|
|||||||
|
|
||||||
from kitty.fast_data_types import (
|
from kitty.fast_data_types import (
|
||||||
FC_DUAL, FC_MONO, FC_SLANT_ITALIC, FC_SLANT_ROMAN, FC_WEIGHT_BOLD,
|
FC_DUAL, FC_MONO, FC_SLANT_ITALIC, FC_SLANT_ROMAN, FC_WEIGHT_BOLD,
|
||||||
FC_WEIGHT_REGULAR, fc_list, fc_match as fc_match_impl
|
FC_WEIGHT_REGULAR, FC_WIDTH_NORMAL, fc_list, fc_match as fc_match_impl
|
||||||
)
|
)
|
||||||
from kitty.options_stub import Options
|
from kitty.options_stub import Options
|
||||||
from kitty.typing import FontConfigPattern
|
from kitty.typing import FontConfigPattern
|
||||||
@@ -73,11 +73,13 @@ def find_best_match(family: str, bold: bool = False, italic: bool = False, monos
|
|||||||
q = family_name_to_key(family)
|
q = family_name_to_key(family)
|
||||||
font_map = all_fonts_map(monospaced)
|
font_map = all_fonts_map(monospaced)
|
||||||
|
|
||||||
def score(candidate: FontConfigPattern) -> Tuple[int, int]:
|
def score(candidate: FontConfigPattern) -> Tuple[int, int, int]:
|
||||||
bold_score = abs((FC_WEIGHT_BOLD if bold else FC_WEIGHT_REGULAR) - candidate.get('weight', 0))
|
bold_score = abs((FC_WEIGHT_BOLD if bold else FC_WEIGHT_REGULAR) - candidate.get('weight', 0))
|
||||||
italic_score = abs((FC_SLANT_ITALIC if italic else FC_SLANT_ROMAN) - candidate.get('slant', 0))
|
italic_score = abs((FC_SLANT_ITALIC if italic else FC_SLANT_ROMAN) - candidate.get('slant', 0))
|
||||||
monospace_match = 0 if candidate.get('spacing') == 'MONO' else 1
|
monospace_match = 0 if candidate.get('spacing') == 'MONO' else 1
|
||||||
return bold_score + italic_score, monospace_match
|
width_score = abs(candidate.get('width', FC_WIDTH_NORMAL) - FC_WIDTH_NORMAL)
|
||||||
|
|
||||||
|
return bold_score + italic_score, monospace_match, width_score
|
||||||
|
|
||||||
# First look for an exact match
|
# First look for an exact match
|
||||||
for selector in ('ps_map', 'full_map', 'family_map'):
|
for selector in ('ps_map', 'full_map', 'family_map'):
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import ctypes
|
|||||||
import sys
|
import sys
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from math import ceil, cos, floor, pi
|
from math import ceil, cos, floor, pi
|
||||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
|
from typing import (
|
||||||
|
Any, Callable, Dict, Generator, List, Optional, Tuple, Union, cast
|
||||||
|
)
|
||||||
|
|
||||||
from kitty.config import defaults
|
from kitty.config import defaults
|
||||||
from kitty.constants import is_macos
|
from kitty.constants import is_macos
|
||||||
@@ -43,24 +45,94 @@ def font_for_family(family: str) -> Tuple[FontObject, bool, bool]:
|
|||||||
return font_for_family_fontconfig(family)
|
return font_for_family_fontconfig(family)
|
||||||
|
|
||||||
|
|
||||||
|
Range = Tuple[Tuple[int, int], str]
|
||||||
|
|
||||||
|
|
||||||
|
def merge_ranges(a: Range, b: Range, priority_map: Dict[Tuple[int, int], int]) -> Generator[Range, None, None]:
|
||||||
|
a_start, a_end = a[0]
|
||||||
|
b_start, b_end = b[0]
|
||||||
|
a_val, b_val = a[1], b[1]
|
||||||
|
a_prio, b_prio = priority_map[a[0]], priority_map[b[0]]
|
||||||
|
if b_start > a_end:
|
||||||
|
if b_start == a_end + 1 and a_val == b_val:
|
||||||
|
# ranges can be coalesced
|
||||||
|
r = ((a_start, b_end), a_val)
|
||||||
|
priority_map[r[0]] = max(a_prio, b_prio)
|
||||||
|
yield r
|
||||||
|
return
|
||||||
|
# disjoint ranges
|
||||||
|
yield a
|
||||||
|
yield b
|
||||||
|
return
|
||||||
|
if a_val == b_val:
|
||||||
|
# mergeable ranges
|
||||||
|
r = ((a_start, max(a_end, b_end)), a_val)
|
||||||
|
priority_map[r[0]] = max(a_prio, b_prio)
|
||||||
|
yield r
|
||||||
|
return
|
||||||
|
before_range = mid_range = after_range = None
|
||||||
|
before_range_prio = mid_range_prio = after_range_prio = 0
|
||||||
|
if b_start > a_start:
|
||||||
|
before_range = ((a_start, b_start - 1), a_val)
|
||||||
|
before_range_prio = a_prio
|
||||||
|
mid_end = min(a_end, b_end)
|
||||||
|
if mid_end >= b_start:
|
||||||
|
# overlap range
|
||||||
|
mid_range = ((b_start, mid_end), a_val if priority_map[a[0]] >= priority_map[b[0]] else b_val)
|
||||||
|
mid_range_prio = max(a_prio, b_prio)
|
||||||
|
# after range
|
||||||
|
if mid_end is a_end:
|
||||||
|
if b_end > a_end:
|
||||||
|
after_range = ((a_end + 1, b_end), b_val)
|
||||||
|
after_range_prio = b_prio
|
||||||
|
else:
|
||||||
|
if a_end > b_end:
|
||||||
|
after_range = ((b_end + 1, a_end), a_val)
|
||||||
|
after_range_prio = a_prio
|
||||||
|
# check if the before, mid and after ranges can be coalesced
|
||||||
|
ranges: List[Range] = []
|
||||||
|
priorities: List[int] = []
|
||||||
|
for rq, prio in ((before_range, before_range_prio), (mid_range, mid_range_prio), (after_range, after_range_prio)):
|
||||||
|
if rq is None:
|
||||||
|
continue
|
||||||
|
r = rq
|
||||||
|
if ranges:
|
||||||
|
x = ranges[-1]
|
||||||
|
if x[0][1] + 1 == r[0][0] and x[1] == r[1]:
|
||||||
|
ranges[-1] = ((x[0][0], r[0][1]), x[1])
|
||||||
|
priorities[-1] = max(priorities[-1], prio)
|
||||||
|
else:
|
||||||
|
ranges.append(r)
|
||||||
|
priorities.append(prio)
|
||||||
|
else:
|
||||||
|
ranges.append(r)
|
||||||
|
priorities.append(prio)
|
||||||
|
for r, p in zip(ranges, priorities):
|
||||||
|
priority_map[r[0]] = p
|
||||||
|
yield from ranges
|
||||||
|
|
||||||
|
|
||||||
def coalesce_symbol_maps(maps: Dict[Tuple[int, int], str]) -> Dict[Tuple[int, int], str]:
|
def coalesce_symbol_maps(maps: Dict[Tuple[int, int], str]) -> Dict[Tuple[int, int], str]:
|
||||||
if not maps:
|
if not maps:
|
||||||
return maps
|
return maps
|
||||||
items = tuple((k, maps[k]) for k in sorted(maps))
|
priority_map = {r: i for i, r in enumerate(maps.keys())}
|
||||||
ans = [items[0]]
|
ranges = tuple((r, maps[r]) for r in sorted(maps))
|
||||||
|
ans = [ranges[0]]
|
||||||
|
|
||||||
def merge(prev_item: Tuple[Tuple[int, int], str], item: Tuple[Tuple[int, int], str]) -> None:
|
for i in range(1, len(ranges)):
|
||||||
s, e = item[0]
|
r = ranges[i]
|
||||||
pe = prev_item[0][1]
|
new_ranges = merge_ranges(ans[-1], r, priority_map)
|
||||||
ans[-1] = ((prev_item[0][0], max(pe, e)), prev_item[1])
|
if ans:
|
||||||
|
del ans[-1]
|
||||||
for item in items[1:]:
|
if not ans:
|
||||||
current_item = ans[-1]
|
ans = list(new_ranges)
|
||||||
if current_item[1] != item[1] or item[0][0] > current_item[0][1] + 1:
|
|
||||||
ans.append(item)
|
|
||||||
else:
|
else:
|
||||||
merge(current_item, item)
|
for r in new_ranges:
|
||||||
|
prev = ans[-1]
|
||||||
|
if prev[0][1] + 1 == r[0][0] and prev[1] == r[1]:
|
||||||
|
ans[-1] = (prev[0][0], r[0][1]), prev[1]
|
||||||
|
else:
|
||||||
|
ans.append(r)
|
||||||
return dict(ans)
|
return dict(ans)
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +263,9 @@ def render_special(
|
|||||||
cell_width: int = 0, cell_height: int = 0,
|
cell_width: int = 0, cell_height: int = 0,
|
||||||
baseline: int = 0,
|
baseline: int = 0,
|
||||||
underline_position: int = 0,
|
underline_position: int = 0,
|
||||||
underline_thickness: int = 0
|
underline_thickness: int = 0,
|
||||||
|
strikethrough_position: int = 0,
|
||||||
|
strikethrough_thickness: int = 0
|
||||||
) -> ctypes.Array:
|
) -> ctypes.Array:
|
||||||
underline_position = min(underline_position, cell_height - underline_thickness)
|
underline_position = min(underline_position, cell_height - underline_thickness)
|
||||||
CharTexture = ctypes.c_ubyte * (cell_width * cell_height)
|
CharTexture = ctypes.c_ubyte * (cell_width * cell_height)
|
||||||
@@ -216,8 +290,7 @@ def render_special(
|
|||||||
t = max(1, min(cell_height - underline_position - 1, t))
|
t = max(1, min(cell_height - underline_position - 1, t))
|
||||||
dl([add_line, add_line, add_dline, add_curl][underline], underline_position, t, cell_height)
|
dl([add_line, add_line, add_dline, add_curl][underline], underline_position, t, cell_height)
|
||||||
if strikethrough:
|
if strikethrough:
|
||||||
pos = int(0.65 * baseline)
|
dl(add_line, strikethrough_position, strikethrough_thickness, cell_height)
|
||||||
dl(add_line, pos, underline_thickness, cell_height)
|
|
||||||
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
@@ -268,6 +341,8 @@ def prerender_function(
|
|||||||
baseline: int,
|
baseline: int,
|
||||||
underline_position: int,
|
underline_position: int,
|
||||||
underline_thickness: int,
|
underline_thickness: int,
|
||||||
|
strikethrough_position: int,
|
||||||
|
strikethrough_thickness: int,
|
||||||
cursor_beam_thickness: float,
|
cursor_beam_thickness: float,
|
||||||
cursor_underline_thickness: float,
|
cursor_underline_thickness: float,
|
||||||
dpi_x: float,
|
dpi_x: float,
|
||||||
@@ -276,7 +351,8 @@ def prerender_function(
|
|||||||
# Pre-render the special underline, strikethrough and missing and cursor cells
|
# Pre-render the special underline, strikethrough and missing and cursor cells
|
||||||
f = partial(
|
f = partial(
|
||||||
render_special, cell_width=cell_width, cell_height=cell_height, baseline=baseline,
|
render_special, cell_width=cell_width, cell_height=cell_height, baseline=baseline,
|
||||||
underline_position=underline_position, underline_thickness=underline_thickness)
|
underline_position=underline_position, underline_thickness=underline_thickness,
|
||||||
|
strikethrough_position=strikethrough_position, strikethrough_thickness=strikethrough_thickness)
|
||||||
c = partial(
|
c = partial(
|
||||||
render_cursor, cursor_beam_thickness=cursor_beam_thickness,
|
render_cursor, cursor_beam_thickness=cursor_beam_thickness,
|
||||||
cursor_underline_thickness=cursor_underline_thickness, cell_width=cell_width,
|
cursor_underline_thickness=cursor_underline_thickness, cell_width=cell_width,
|
||||||
|
|||||||
@@ -22,12 +22,13 @@
|
|||||||
|
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
#include FT_BITMAP_H
|
#include FT_BITMAP_H
|
||||||
|
#include FT_TRUETYPE_TABLES_H
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
unsigned int units_per_EM;
|
unsigned int units_per_EM;
|
||||||
int ascender, descender, height, max_advance_width, max_advance_height, underline_position, underline_thickness;
|
int ascender, descender, height, max_advance_width, max_advance_height, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
|
||||||
int hinting, hintstyle, index;
|
int hinting, hintstyle, index;
|
||||||
bool is_scalable, has_color;
|
bool is_scalable, has_color;
|
||||||
float size_in_pts;
|
float size_in_pts;
|
||||||
@@ -207,6 +208,12 @@ init_ft_face(Face *self, PyObject *path, int hinting, int hintstyle, FONTS_DATA_
|
|||||||
if (self->harfbuzz_font == NULL) { PyErr_NoMemory(); return false; }
|
if (self->harfbuzz_font == NULL) { PyErr_NoMemory(); return false; }
|
||||||
hb_ft_font_set_load_flags(self->harfbuzz_font, get_load_flags(self->hinting, self->hintstyle, FT_LOAD_DEFAULT));
|
hb_ft_font_set_load_flags(self->harfbuzz_font, get_load_flags(self->hinting, self->hintstyle, FT_LOAD_DEFAULT));
|
||||||
|
|
||||||
|
TT_OS2 *os2 = (TT_OS2*)FT_Get_Sfnt_Table(self->face, FT_SFNT_OS2);
|
||||||
|
if (os2 != NULL) {
|
||||||
|
self->strikethrough_position = os2->yStrikeoutPosition;
|
||||||
|
self->strikethrough_thickness = os2->yStrikeoutSize;
|
||||||
|
}
|
||||||
|
|
||||||
self->path = path;
|
self->path = path;
|
||||||
Py_INCREF(self->path);
|
Py_INCREF(self->path);
|
||||||
self->index = self->face->face_index & 0xFFFF;
|
self->index = self->face->face_index & 0xFFFF;
|
||||||
@@ -263,11 +270,11 @@ static PyObject *
|
|||||||
repr(Face *self) {
|
repr(Face *self) {
|
||||||
const char *ps_name = FT_Get_Postscript_Name(self->face);
|
const char *ps_name = FT_Get_Postscript_Name(self->face);
|
||||||
return PyUnicode_FromFormat(
|
return PyUnicode_FromFormat(
|
||||||
"Face(family=%s, style=%s, ps_name=%s, path=%S, index=%d, is_scalable=%S, has_color=%S, ascender=%i, descender=%i, height=%i, underline_position=%i, underline_thickness=%i)",
|
"Face(family=%s, style=%s, ps_name=%s, path=%S, index=%d, is_scalable=%S, has_color=%S, ascender=%i, descender=%i, height=%i, underline_position=%i, underline_thickness=%i, strikethrough_position=%i, strikethrough_thickness=%i)",
|
||||||
self->face->family_name ? self->face->family_name : "", self->face->style_name ? self->face->style_name : "",
|
self->face->family_name ? self->face->family_name : "", self->face->style_name ? self->face->style_name : "",
|
||||||
ps_name ? ps_name: "",
|
ps_name ? ps_name: "",
|
||||||
self->path, self->index, self->is_scalable ? Py_True : Py_False, self->has_color ? Py_True : Py_False,
|
self->path, self->index, self->is_scalable ? Py_True : Py_False, self->has_color ? Py_True : Py_False,
|
||||||
self->ascender, self->descender, self->height, self->underline_position, self->underline_thickness
|
self->ascender, self->descender, self->height, self->underline_position, self->underline_thickness, self->strikethrough_position, self->strikethrough_thickness
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,13 +299,24 @@ calc_cell_width(Face *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness) {
|
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness, unsigned int* strikethrough_position, unsigned int* strikethrough_thickness) {
|
||||||
Face *self = (Face*)s;
|
Face *self = (Face*)s;
|
||||||
*cell_width = calc_cell_width(self);
|
*cell_width = calc_cell_width(self);
|
||||||
*cell_height = calc_cell_height(self, true);
|
*cell_height = calc_cell_height(self, true);
|
||||||
*baseline = font_units_to_pixels_y(self, self->ascender);
|
*baseline = font_units_to_pixels_y(self, self->ascender);
|
||||||
*underline_position = MIN(*cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->underline_position)));
|
*underline_position = MIN(*cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->underline_position)));
|
||||||
*underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness));
|
*underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness));
|
||||||
|
|
||||||
|
if (self->strikethrough_position != 0) {
|
||||||
|
*strikethrough_position = MIN(*cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->strikethrough_position)));
|
||||||
|
} else {
|
||||||
|
*strikethrough_position = (unsigned int)floor(*baseline * 0.65);
|
||||||
|
}
|
||||||
|
if (self->strikethrough_thickness > 0) {
|
||||||
|
*strikethrough_thickness = MAX(1, font_units_to_pixels_y(self, self->strikethrough_thickness));
|
||||||
|
} else {
|
||||||
|
*strikethrough_thickness = *underline_thickness;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
@@ -659,6 +677,8 @@ static PyMemberDef members[] = {
|
|||||||
MEM(max_advance_height, T_INT),
|
MEM(max_advance_height, T_INT),
|
||||||
MEM(underline_position, T_INT),
|
MEM(underline_position, T_INT),
|
||||||
MEM(underline_thickness, T_INT),
|
MEM(underline_thickness, T_INT),
|
||||||
|
MEM(strikethrough_position, T_INT),
|
||||||
|
MEM(strikethrough_thickness, T_INT),
|
||||||
MEM(is_scalable, T_BOOL),
|
MEM(is_scalable, T_BOOL),
|
||||||
MEM(path, T_OBJECT_EX),
|
MEM(path, T_OBJECT_EX),
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ gl_init() {
|
|||||||
if (!gl_version) {
|
if (!gl_version) {
|
||||||
fatal("Loading the OpenGL library failed");
|
fatal("Loading the OpenGL library failed");
|
||||||
}
|
}
|
||||||
if (!global_state.debug_gl) {
|
if (!global_state.debug_rendering) {
|
||||||
gladUninstallGLDebug();
|
gladUninstallGLDebug();
|
||||||
}
|
}
|
||||||
gladSetGLPostCallback(check_for_gl_error);
|
gladSetGLPostCallback(check_for_gl_error);
|
||||||
@@ -59,7 +59,7 @@ gl_init() {
|
|||||||
glad_loaded = true;
|
glad_loaded = true;
|
||||||
int gl_major = GLAD_VERSION_MAJOR(gl_version);
|
int gl_major = GLAD_VERSION_MAJOR(gl_version);
|
||||||
int gl_minor = GLAD_VERSION_MINOR(gl_version);
|
int gl_minor = GLAD_VERSION_MINOR(gl_version);
|
||||||
if (global_state.debug_gl) printf("GL version string: '%s' Detected version: %d.%d\n", glGetString(GL_VERSION), gl_major, gl_minor);
|
if (global_state.debug_rendering) printf("GL version string: '%s' Detected version: %d.%d\n", glGetString(GL_VERSION), gl_major, gl_minor);
|
||||||
if (gl_major < OPENGL_REQUIRED_VERSION_MAJOR || (gl_major == OPENGL_REQUIRED_VERSION_MAJOR && gl_minor < OPENGL_REQUIRED_VERSION_MINOR)) {
|
if (gl_major < OPENGL_REQUIRED_VERSION_MAJOR || (gl_major == OPENGL_REQUIRED_VERSION_MAJOR && gl_minor < OPENGL_REQUIRED_VERSION_MINOR)) {
|
||||||
fatal("OpenGL version is %d.%d, version >= 3.3 required for kitty", gl_major, gl_minor);
|
fatal("OpenGL version is %d.%d, version >= 3.3 required for kitty", gl_major, gl_minor);
|
||||||
}
|
}
|
||||||
|
|||||||
7
kitty/glfw-wrapper.c
generated
7
kitty/glfw-wrapper.c
generated
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
#define GFW_EXTERN
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
#include "glfw-wrapper.h"
|
#include "glfw-wrapper.h"
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@@ -215,6 +216,9 @@ load_glfw(const char* path) {
|
|||||||
*(void **) (&glfwSetWindowCloseCallback_impl) = dlsym(handle, "glfwSetWindowCloseCallback");
|
*(void **) (&glfwSetWindowCloseCallback_impl) = dlsym(handle, "glfwSetWindowCloseCallback");
|
||||||
if (glfwSetWindowCloseCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowCloseCallback with error: %s", dlerror());
|
if (glfwSetWindowCloseCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowCloseCallback with error: %s", dlerror());
|
||||||
|
|
||||||
|
*(void **) (&glfwSetApplicationCloseCallback_impl) = dlsym(handle, "glfwSetApplicationCloseCallback");
|
||||||
|
if (glfwSetApplicationCloseCallback_impl == NULL) fail("Failed to load glfw function glfwSetApplicationCloseCallback with error: %s", dlerror());
|
||||||
|
|
||||||
*(void **) (&glfwSetWindowRefreshCallback_impl) = dlsym(handle, "glfwSetWindowRefreshCallback");
|
*(void **) (&glfwSetWindowRefreshCallback_impl) = dlsym(handle, "glfwSetWindowRefreshCallback");
|
||||||
if (glfwSetWindowRefreshCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowRefreshCallback with error: %s", dlerror());
|
if (glfwSetWindowRefreshCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowRefreshCallback with error: %s", dlerror());
|
||||||
|
|
||||||
@@ -245,6 +249,9 @@ load_glfw(const char* path) {
|
|||||||
*(void **) (&glfwSetInputMode_impl) = dlsym(handle, "glfwSetInputMode");
|
*(void **) (&glfwSetInputMode_impl) = dlsym(handle, "glfwSetInputMode");
|
||||||
if (glfwSetInputMode_impl == NULL) fail("Failed to load glfw function glfwSetInputMode with error: %s", dlerror());
|
if (glfwSetInputMode_impl == NULL) fail("Failed to load glfw function glfwSetInputMode with error: %s", dlerror());
|
||||||
|
|
||||||
|
*(void **) (&glfwRawMouseMotionSupported_impl) = dlsym(handle, "glfwRawMouseMotionSupported");
|
||||||
|
if (glfwRawMouseMotionSupported_impl == NULL) fail("Failed to load glfw function glfwRawMouseMotionSupported with error: %s", dlerror());
|
||||||
|
|
||||||
*(void **) (&glfwGetKeyName_impl) = dlsym(handle, "glfwGetKeyName");
|
*(void **) (&glfwGetKeyName_impl) = dlsym(handle, "glfwGetKeyName");
|
||||||
if (glfwGetKeyName_impl == NULL) fail("Failed to load glfw function glfwGetKeyName with error: %s", dlerror());
|
if (glfwGetKeyName_impl == NULL) fail("Failed to load glfw function glfwGetKeyName with error: %s", dlerror());
|
||||||
|
|
||||||
|
|||||||
330
kitty/glfw-wrapper.h
generated
330
kitty/glfw-wrapper.h
generated
@@ -9,6 +9,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "monotonic.h"
|
#include "monotonic.h"
|
||||||
|
|
||||||
|
#ifndef GFW_EXTERN
|
||||||
|
#define GFW_EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*! @name GLFW version macros
|
/*! @name GLFW version macros
|
||||||
@@ -566,6 +569,33 @@
|
|||||||
* @analysis Application programmer error. Fix the offending call.
|
* @analysis Application programmer error. Fix the offending call.
|
||||||
*/
|
*/
|
||||||
#define GLFW_NO_WINDOW_CONTEXT 0x0001000A
|
#define GLFW_NO_WINDOW_CONTEXT 0x0001000A
|
||||||
|
/*! @brief The reuqested feature is not provided by the platform.
|
||||||
|
*
|
||||||
|
* The requested feature is not provided by the platform, so GLFW is unable to
|
||||||
|
* implement it. The documentation for each function notes if it could emit
|
||||||
|
* this error.
|
||||||
|
*
|
||||||
|
* @analysis Platform or platform version limitation. The error can be ignored
|
||||||
|
* unless the feature is critical to the application.
|
||||||
|
*
|
||||||
|
* @par
|
||||||
|
* A function call that emits this error has no effect other than the error and
|
||||||
|
* updating any existing out parameters.
|
||||||
|
*/
|
||||||
|
#define GLFW_FEATURE_UNAVAILABLE 0x0001000C
|
||||||
|
/*! @brief The requested feature is not implemented for the platform.
|
||||||
|
*
|
||||||
|
* The requested feature has not yet been implemented in GLFW for this platform.
|
||||||
|
*
|
||||||
|
* @analysis An incomplete implementation of GLFW for this platform, hopefully
|
||||||
|
* fixed in a future release. The error can be ignored unless the feature is
|
||||||
|
* critical to the application.
|
||||||
|
*
|
||||||
|
* @par
|
||||||
|
* A function call that emits this error has no effect other than the error and
|
||||||
|
* updating any existing out parameters.
|
||||||
|
*/
|
||||||
|
#define GLFW_FEATURE_UNIMPLEMENTED 0x0001000D
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
/*! @addtogroup window
|
/*! @addtogroup window
|
||||||
@@ -836,6 +866,7 @@
|
|||||||
#define GLFW_STICKY_KEYS 0x00033002
|
#define GLFW_STICKY_KEYS 0x00033002
|
||||||
#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
|
#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
|
||||||
#define GLFW_LOCK_KEY_MODS 0x00033004
|
#define GLFW_LOCK_KEY_MODS 0x00033004
|
||||||
|
#define GLFW_RAW_MOUSE_MOTION 0x00033005
|
||||||
|
|
||||||
#define GLFW_CURSOR_NORMAL 0x00034001
|
#define GLFW_CURSOR_NORMAL 0x00034001
|
||||||
#define GLFW_CURSOR_HIDDEN 0x00034002
|
#define GLFW_CURSOR_HIDDEN 0x00034002
|
||||||
@@ -1079,6 +1110,22 @@ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);
|
|||||||
*/
|
*/
|
||||||
typedef void (* GLFWwindowclosefun)(GLFWwindow*);
|
typedef void (* GLFWwindowclosefun)(GLFWwindow*);
|
||||||
|
|
||||||
|
/*! @brief The function pointer type for application close callbacks.
|
||||||
|
*
|
||||||
|
* This is the function pointer type for application close callbacks. A application
|
||||||
|
* close callback function has the following signature:
|
||||||
|
* @code
|
||||||
|
* void function_name(int flags)
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @param[in] flags 0 for a user requested application quit, 1 if a fatal error occurred and application should quit ASAP
|
||||||
|
*
|
||||||
|
* @sa @ref glfwSetApplicationCloseCallback
|
||||||
|
*
|
||||||
|
* @ingroup window
|
||||||
|
*/
|
||||||
|
typedef void (* GLFWapplicationclosefun)(int);
|
||||||
|
|
||||||
/*! @brief The function pointer type for window content refresh callbacks.
|
/*! @brief The function pointer type for window content refresh callbacks.
|
||||||
*
|
*
|
||||||
* This is the function pointer type for window content refresh callbacks.
|
* This is the function pointer type for window content refresh callbacks.
|
||||||
@@ -1310,6 +1357,7 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
|
|||||||
* value 2 for stationary momentum scrolling, value 3 for momentum scrolling
|
* value 2 for stationary momentum scrolling, value 3 for momentum scrolling
|
||||||
* in progress, value 4 for momentum scrolling ended, value 5 for momentum
|
* in progress, value 4 for momentum scrolling ended, value 5 for momentum
|
||||||
* scrolling cancelled and value 6 if scrolling may begin soon.
|
* scrolling cancelled and value 6 if scrolling may begin soon.
|
||||||
|
* @param[int] mods The keyboard modifiers
|
||||||
*
|
*
|
||||||
* @sa @ref scrolling
|
* @sa @ref scrolling
|
||||||
* @sa @ref glfwSetScrollCallback
|
* @sa @ref glfwSetScrollCallback
|
||||||
@@ -1319,7 +1367,7 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
|
|||||||
*
|
*
|
||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
|
typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int,int);
|
||||||
|
|
||||||
/*! @brief The function pointer type for key callbacks.
|
/*! @brief The function pointer type for key callbacks.
|
||||||
*
|
*
|
||||||
@@ -1587,547 +1635,555 @@ typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id);
|
|||||||
typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*);
|
typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*);
|
||||||
typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, const char*);
|
typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, const char*);
|
||||||
typedef int (*glfwInit_func)(monotonic_t);
|
typedef int (*glfwInit_func)(monotonic_t);
|
||||||
glfwInit_func glfwInit_impl;
|
GFW_EXTERN glfwInit_func glfwInit_impl;
|
||||||
#define glfwInit glfwInit_impl
|
#define glfwInit glfwInit_impl
|
||||||
|
|
||||||
typedef void (*glfwRunMainLoop_func)(GLFWtickcallback, void*);
|
typedef void (*glfwRunMainLoop_func)(GLFWtickcallback, void*);
|
||||||
glfwRunMainLoop_func glfwRunMainLoop_impl;
|
GFW_EXTERN glfwRunMainLoop_func glfwRunMainLoop_impl;
|
||||||
#define glfwRunMainLoop glfwRunMainLoop_impl
|
#define glfwRunMainLoop glfwRunMainLoop_impl
|
||||||
|
|
||||||
typedef void (*glfwStopMainLoop_func)(void);
|
typedef void (*glfwStopMainLoop_func)(void);
|
||||||
glfwStopMainLoop_func glfwStopMainLoop_impl;
|
GFW_EXTERN glfwStopMainLoop_func glfwStopMainLoop_impl;
|
||||||
#define glfwStopMainLoop glfwStopMainLoop_impl
|
#define glfwStopMainLoop glfwStopMainLoop_impl
|
||||||
|
|
||||||
typedef unsigned long long (*glfwAddTimer_func)(monotonic_t, bool, GLFWuserdatafun, void *, GLFWuserdatafun);
|
typedef unsigned long long (*glfwAddTimer_func)(monotonic_t, bool, GLFWuserdatafun, void *, GLFWuserdatafun);
|
||||||
glfwAddTimer_func glfwAddTimer_impl;
|
GFW_EXTERN glfwAddTimer_func glfwAddTimer_impl;
|
||||||
#define glfwAddTimer glfwAddTimer_impl
|
#define glfwAddTimer glfwAddTimer_impl
|
||||||
|
|
||||||
typedef void (*glfwUpdateTimer_func)(unsigned long long, monotonic_t, bool);
|
typedef void (*glfwUpdateTimer_func)(unsigned long long, monotonic_t, bool);
|
||||||
glfwUpdateTimer_func glfwUpdateTimer_impl;
|
GFW_EXTERN glfwUpdateTimer_func glfwUpdateTimer_impl;
|
||||||
#define glfwUpdateTimer glfwUpdateTimer_impl
|
#define glfwUpdateTimer glfwUpdateTimer_impl
|
||||||
|
|
||||||
typedef void (*glfwRemoveTimer_func)(unsigned long);
|
typedef void (*glfwRemoveTimer_func)(unsigned long);
|
||||||
glfwRemoveTimer_func glfwRemoveTimer_impl;
|
GFW_EXTERN glfwRemoveTimer_func glfwRemoveTimer_impl;
|
||||||
#define glfwRemoveTimer glfwRemoveTimer_impl
|
#define glfwRemoveTimer glfwRemoveTimer_impl
|
||||||
|
|
||||||
typedef void (*glfwTerminate_func)(void);
|
typedef void (*glfwTerminate_func)(void);
|
||||||
glfwTerminate_func glfwTerminate_impl;
|
GFW_EXTERN glfwTerminate_func glfwTerminate_impl;
|
||||||
#define glfwTerminate glfwTerminate_impl
|
#define glfwTerminate glfwTerminate_impl
|
||||||
|
|
||||||
typedef void (*glfwInitHint_func)(int, int);
|
typedef void (*glfwInitHint_func)(int, int);
|
||||||
glfwInitHint_func glfwInitHint_impl;
|
GFW_EXTERN glfwInitHint_func glfwInitHint_impl;
|
||||||
#define glfwInitHint glfwInitHint_impl
|
#define glfwInitHint glfwInitHint_impl
|
||||||
|
|
||||||
typedef void (*glfwGetVersion_func)(int*, int*, int*);
|
typedef void (*glfwGetVersion_func)(int*, int*, int*);
|
||||||
glfwGetVersion_func glfwGetVersion_impl;
|
GFW_EXTERN glfwGetVersion_func glfwGetVersion_impl;
|
||||||
#define glfwGetVersion glfwGetVersion_impl
|
#define glfwGetVersion glfwGetVersion_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetVersionString_func)(void);
|
typedef const char* (*glfwGetVersionString_func)(void);
|
||||||
glfwGetVersionString_func glfwGetVersionString_impl;
|
GFW_EXTERN glfwGetVersionString_func glfwGetVersionString_impl;
|
||||||
#define glfwGetVersionString glfwGetVersionString_impl
|
#define glfwGetVersionString glfwGetVersionString_impl
|
||||||
|
|
||||||
typedef int (*glfwGetError_func)(const char**);
|
typedef int (*glfwGetError_func)(const char**);
|
||||||
glfwGetError_func glfwGetError_impl;
|
GFW_EXTERN glfwGetError_func glfwGetError_impl;
|
||||||
#define glfwGetError glfwGetError_impl
|
#define glfwGetError glfwGetError_impl
|
||||||
|
|
||||||
typedef GLFWerrorfun (*glfwSetErrorCallback_func)(GLFWerrorfun);
|
typedef GLFWerrorfun (*glfwSetErrorCallback_func)(GLFWerrorfun);
|
||||||
glfwSetErrorCallback_func glfwSetErrorCallback_impl;
|
GFW_EXTERN glfwSetErrorCallback_func glfwSetErrorCallback_impl;
|
||||||
#define glfwSetErrorCallback glfwSetErrorCallback_impl
|
#define glfwSetErrorCallback glfwSetErrorCallback_impl
|
||||||
|
|
||||||
typedef GLFWmonitor** (*glfwGetMonitors_func)(int*);
|
typedef GLFWmonitor** (*glfwGetMonitors_func)(int*);
|
||||||
glfwGetMonitors_func glfwGetMonitors_impl;
|
GFW_EXTERN glfwGetMonitors_func glfwGetMonitors_impl;
|
||||||
#define glfwGetMonitors glfwGetMonitors_impl
|
#define glfwGetMonitors glfwGetMonitors_impl
|
||||||
|
|
||||||
typedef GLFWmonitor* (*glfwGetPrimaryMonitor_func)(void);
|
typedef GLFWmonitor* (*glfwGetPrimaryMonitor_func)(void);
|
||||||
glfwGetPrimaryMonitor_func glfwGetPrimaryMonitor_impl;
|
GFW_EXTERN glfwGetPrimaryMonitor_func glfwGetPrimaryMonitor_impl;
|
||||||
#define glfwGetPrimaryMonitor glfwGetPrimaryMonitor_impl
|
#define glfwGetPrimaryMonitor glfwGetPrimaryMonitor_impl
|
||||||
|
|
||||||
typedef void (*glfwGetMonitorPos_func)(GLFWmonitor*, int*, int*);
|
typedef void (*glfwGetMonitorPos_func)(GLFWmonitor*, int*, int*);
|
||||||
glfwGetMonitorPos_func glfwGetMonitorPos_impl;
|
GFW_EXTERN glfwGetMonitorPos_func glfwGetMonitorPos_impl;
|
||||||
#define glfwGetMonitorPos glfwGetMonitorPos_impl
|
#define glfwGetMonitorPos glfwGetMonitorPos_impl
|
||||||
|
|
||||||
typedef void (*glfwGetMonitorWorkarea_func)(GLFWmonitor*, int*, int*, int*, int*);
|
typedef void (*glfwGetMonitorWorkarea_func)(GLFWmonitor*, int*, int*, int*, int*);
|
||||||
glfwGetMonitorWorkarea_func glfwGetMonitorWorkarea_impl;
|
GFW_EXTERN glfwGetMonitorWorkarea_func glfwGetMonitorWorkarea_impl;
|
||||||
#define glfwGetMonitorWorkarea glfwGetMonitorWorkarea_impl
|
#define glfwGetMonitorWorkarea glfwGetMonitorWorkarea_impl
|
||||||
|
|
||||||
typedef void (*glfwGetMonitorPhysicalSize_func)(GLFWmonitor*, int*, int*);
|
typedef void (*glfwGetMonitorPhysicalSize_func)(GLFWmonitor*, int*, int*);
|
||||||
glfwGetMonitorPhysicalSize_func glfwGetMonitorPhysicalSize_impl;
|
GFW_EXTERN glfwGetMonitorPhysicalSize_func glfwGetMonitorPhysicalSize_impl;
|
||||||
#define glfwGetMonitorPhysicalSize glfwGetMonitorPhysicalSize_impl
|
#define glfwGetMonitorPhysicalSize glfwGetMonitorPhysicalSize_impl
|
||||||
|
|
||||||
typedef void (*glfwGetMonitorContentScale_func)(GLFWmonitor*, float*, float*);
|
typedef void (*glfwGetMonitorContentScale_func)(GLFWmonitor*, float*, float*);
|
||||||
glfwGetMonitorContentScale_func glfwGetMonitorContentScale_impl;
|
GFW_EXTERN glfwGetMonitorContentScale_func glfwGetMonitorContentScale_impl;
|
||||||
#define glfwGetMonitorContentScale glfwGetMonitorContentScale_impl
|
#define glfwGetMonitorContentScale glfwGetMonitorContentScale_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetMonitorName_func)(GLFWmonitor*);
|
typedef const char* (*glfwGetMonitorName_func)(GLFWmonitor*);
|
||||||
glfwGetMonitorName_func glfwGetMonitorName_impl;
|
GFW_EXTERN glfwGetMonitorName_func glfwGetMonitorName_impl;
|
||||||
#define glfwGetMonitorName glfwGetMonitorName_impl
|
#define glfwGetMonitorName glfwGetMonitorName_impl
|
||||||
|
|
||||||
typedef void (*glfwSetMonitorUserPointer_func)(GLFWmonitor*, void*);
|
typedef void (*glfwSetMonitorUserPointer_func)(GLFWmonitor*, void*);
|
||||||
glfwSetMonitorUserPointer_func glfwSetMonitorUserPointer_impl;
|
GFW_EXTERN glfwSetMonitorUserPointer_func glfwSetMonitorUserPointer_impl;
|
||||||
#define glfwSetMonitorUserPointer glfwSetMonitorUserPointer_impl
|
#define glfwSetMonitorUserPointer glfwSetMonitorUserPointer_impl
|
||||||
|
|
||||||
typedef void* (*glfwGetMonitorUserPointer_func)(GLFWmonitor*);
|
typedef void* (*glfwGetMonitorUserPointer_func)(GLFWmonitor*);
|
||||||
glfwGetMonitorUserPointer_func glfwGetMonitorUserPointer_impl;
|
GFW_EXTERN glfwGetMonitorUserPointer_func glfwGetMonitorUserPointer_impl;
|
||||||
#define glfwGetMonitorUserPointer glfwGetMonitorUserPointer_impl
|
#define glfwGetMonitorUserPointer glfwGetMonitorUserPointer_impl
|
||||||
|
|
||||||
typedef GLFWmonitorfun (*glfwSetMonitorCallback_func)(GLFWmonitorfun);
|
typedef GLFWmonitorfun (*glfwSetMonitorCallback_func)(GLFWmonitorfun);
|
||||||
glfwSetMonitorCallback_func glfwSetMonitorCallback_impl;
|
GFW_EXTERN glfwSetMonitorCallback_func glfwSetMonitorCallback_impl;
|
||||||
#define glfwSetMonitorCallback glfwSetMonitorCallback_impl
|
#define glfwSetMonitorCallback glfwSetMonitorCallback_impl
|
||||||
|
|
||||||
typedef const GLFWvidmode* (*glfwGetVideoModes_func)(GLFWmonitor*, int*);
|
typedef const GLFWvidmode* (*glfwGetVideoModes_func)(GLFWmonitor*, int*);
|
||||||
glfwGetVideoModes_func glfwGetVideoModes_impl;
|
GFW_EXTERN glfwGetVideoModes_func glfwGetVideoModes_impl;
|
||||||
#define glfwGetVideoModes glfwGetVideoModes_impl
|
#define glfwGetVideoModes glfwGetVideoModes_impl
|
||||||
|
|
||||||
typedef const GLFWvidmode* (*glfwGetVideoMode_func)(GLFWmonitor*);
|
typedef const GLFWvidmode* (*glfwGetVideoMode_func)(GLFWmonitor*);
|
||||||
glfwGetVideoMode_func glfwGetVideoMode_impl;
|
GFW_EXTERN glfwGetVideoMode_func glfwGetVideoMode_impl;
|
||||||
#define glfwGetVideoMode glfwGetVideoMode_impl
|
#define glfwGetVideoMode glfwGetVideoMode_impl
|
||||||
|
|
||||||
typedef void (*glfwSetGamma_func)(GLFWmonitor*, float);
|
typedef void (*glfwSetGamma_func)(GLFWmonitor*, float);
|
||||||
glfwSetGamma_func glfwSetGamma_impl;
|
GFW_EXTERN glfwSetGamma_func glfwSetGamma_impl;
|
||||||
#define glfwSetGamma glfwSetGamma_impl
|
#define glfwSetGamma glfwSetGamma_impl
|
||||||
|
|
||||||
typedef const GLFWgammaramp* (*glfwGetGammaRamp_func)(GLFWmonitor*);
|
typedef const GLFWgammaramp* (*glfwGetGammaRamp_func)(GLFWmonitor*);
|
||||||
glfwGetGammaRamp_func glfwGetGammaRamp_impl;
|
GFW_EXTERN glfwGetGammaRamp_func glfwGetGammaRamp_impl;
|
||||||
#define glfwGetGammaRamp glfwGetGammaRamp_impl
|
#define glfwGetGammaRamp glfwGetGammaRamp_impl
|
||||||
|
|
||||||
typedef void (*glfwSetGammaRamp_func)(GLFWmonitor*, const GLFWgammaramp*);
|
typedef void (*glfwSetGammaRamp_func)(GLFWmonitor*, const GLFWgammaramp*);
|
||||||
glfwSetGammaRamp_func glfwSetGammaRamp_impl;
|
GFW_EXTERN glfwSetGammaRamp_func glfwSetGammaRamp_impl;
|
||||||
#define glfwSetGammaRamp glfwSetGammaRamp_impl
|
#define glfwSetGammaRamp glfwSetGammaRamp_impl
|
||||||
|
|
||||||
typedef void (*glfwDefaultWindowHints_func)(void);
|
typedef void (*glfwDefaultWindowHints_func)(void);
|
||||||
glfwDefaultWindowHints_func glfwDefaultWindowHints_impl;
|
GFW_EXTERN glfwDefaultWindowHints_func glfwDefaultWindowHints_impl;
|
||||||
#define glfwDefaultWindowHints glfwDefaultWindowHints_impl
|
#define glfwDefaultWindowHints glfwDefaultWindowHints_impl
|
||||||
|
|
||||||
typedef void (*glfwWindowHint_func)(int, int);
|
typedef void (*glfwWindowHint_func)(int, int);
|
||||||
glfwWindowHint_func glfwWindowHint_impl;
|
GFW_EXTERN glfwWindowHint_func glfwWindowHint_impl;
|
||||||
#define glfwWindowHint glfwWindowHint_impl
|
#define glfwWindowHint glfwWindowHint_impl
|
||||||
|
|
||||||
typedef void (*glfwWindowHintString_func)(int, const char*);
|
typedef void (*glfwWindowHintString_func)(int, const char*);
|
||||||
glfwWindowHintString_func glfwWindowHintString_impl;
|
GFW_EXTERN glfwWindowHintString_func glfwWindowHintString_impl;
|
||||||
#define glfwWindowHintString glfwWindowHintString_impl
|
#define glfwWindowHintString glfwWindowHintString_impl
|
||||||
|
|
||||||
typedef GLFWwindow* (*glfwCreateWindow_func)(int, int, const char*, GLFWmonitor*, GLFWwindow*);
|
typedef GLFWwindow* (*glfwCreateWindow_func)(int, int, const char*, GLFWmonitor*, GLFWwindow*);
|
||||||
glfwCreateWindow_func glfwCreateWindow_impl;
|
GFW_EXTERN glfwCreateWindow_func glfwCreateWindow_impl;
|
||||||
#define glfwCreateWindow glfwCreateWindow_impl
|
#define glfwCreateWindow glfwCreateWindow_impl
|
||||||
|
|
||||||
typedef bool (*glfwToggleFullscreen_func)(GLFWwindow*, unsigned int);
|
typedef bool (*glfwToggleFullscreen_func)(GLFWwindow*, unsigned int);
|
||||||
glfwToggleFullscreen_func glfwToggleFullscreen_impl;
|
GFW_EXTERN glfwToggleFullscreen_func glfwToggleFullscreen_impl;
|
||||||
#define glfwToggleFullscreen glfwToggleFullscreen_impl
|
#define glfwToggleFullscreen glfwToggleFullscreen_impl
|
||||||
|
|
||||||
typedef void (*glfwDestroyWindow_func)(GLFWwindow*);
|
typedef void (*glfwDestroyWindow_func)(GLFWwindow*);
|
||||||
glfwDestroyWindow_func glfwDestroyWindow_impl;
|
GFW_EXTERN glfwDestroyWindow_func glfwDestroyWindow_impl;
|
||||||
#define glfwDestroyWindow glfwDestroyWindow_impl
|
#define glfwDestroyWindow glfwDestroyWindow_impl
|
||||||
|
|
||||||
typedef int (*glfwWindowShouldClose_func)(GLFWwindow*);
|
typedef int (*glfwWindowShouldClose_func)(GLFWwindow*);
|
||||||
glfwWindowShouldClose_func glfwWindowShouldClose_impl;
|
GFW_EXTERN glfwWindowShouldClose_func glfwWindowShouldClose_impl;
|
||||||
#define glfwWindowShouldClose glfwWindowShouldClose_impl
|
#define glfwWindowShouldClose glfwWindowShouldClose_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowShouldClose_func)(GLFWwindow*, int);
|
typedef void (*glfwSetWindowShouldClose_func)(GLFWwindow*, int);
|
||||||
glfwSetWindowShouldClose_func glfwSetWindowShouldClose_impl;
|
GFW_EXTERN glfwSetWindowShouldClose_func glfwSetWindowShouldClose_impl;
|
||||||
#define glfwSetWindowShouldClose glfwSetWindowShouldClose_impl
|
#define glfwSetWindowShouldClose glfwSetWindowShouldClose_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowTitle_func)(GLFWwindow*, const char*);
|
typedef void (*glfwSetWindowTitle_func)(GLFWwindow*, const char*);
|
||||||
glfwSetWindowTitle_func glfwSetWindowTitle_impl;
|
GFW_EXTERN glfwSetWindowTitle_func glfwSetWindowTitle_impl;
|
||||||
#define glfwSetWindowTitle glfwSetWindowTitle_impl
|
#define glfwSetWindowTitle glfwSetWindowTitle_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowIcon_func)(GLFWwindow*, int, const GLFWimage*);
|
typedef void (*glfwSetWindowIcon_func)(GLFWwindow*, int, const GLFWimage*);
|
||||||
glfwSetWindowIcon_func glfwSetWindowIcon_impl;
|
GFW_EXTERN glfwSetWindowIcon_func glfwSetWindowIcon_impl;
|
||||||
#define glfwSetWindowIcon glfwSetWindowIcon_impl
|
#define glfwSetWindowIcon glfwSetWindowIcon_impl
|
||||||
|
|
||||||
typedef void (*glfwGetWindowPos_func)(GLFWwindow*, int*, int*);
|
typedef void (*glfwGetWindowPos_func)(GLFWwindow*, int*, int*);
|
||||||
glfwGetWindowPos_func glfwGetWindowPos_impl;
|
GFW_EXTERN glfwGetWindowPos_func glfwGetWindowPos_impl;
|
||||||
#define glfwGetWindowPos glfwGetWindowPos_impl
|
#define glfwGetWindowPos glfwGetWindowPos_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowPos_func)(GLFWwindow*, int, int);
|
typedef void (*glfwSetWindowPos_func)(GLFWwindow*, int, int);
|
||||||
glfwSetWindowPos_func glfwSetWindowPos_impl;
|
GFW_EXTERN glfwSetWindowPos_func glfwSetWindowPos_impl;
|
||||||
#define glfwSetWindowPos glfwSetWindowPos_impl
|
#define glfwSetWindowPos glfwSetWindowPos_impl
|
||||||
|
|
||||||
typedef void (*glfwGetWindowSize_func)(GLFWwindow*, int*, int*);
|
typedef void (*glfwGetWindowSize_func)(GLFWwindow*, int*, int*);
|
||||||
glfwGetWindowSize_func glfwGetWindowSize_impl;
|
GFW_EXTERN glfwGetWindowSize_func glfwGetWindowSize_impl;
|
||||||
#define glfwGetWindowSize glfwGetWindowSize_impl
|
#define glfwGetWindowSize glfwGetWindowSize_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowSizeLimits_func)(GLFWwindow*, int, int, int, int);
|
typedef void (*glfwSetWindowSizeLimits_func)(GLFWwindow*, int, int, int, int);
|
||||||
glfwSetWindowSizeLimits_func glfwSetWindowSizeLimits_impl;
|
GFW_EXTERN glfwSetWindowSizeLimits_func glfwSetWindowSizeLimits_impl;
|
||||||
#define glfwSetWindowSizeLimits glfwSetWindowSizeLimits_impl
|
#define glfwSetWindowSizeLimits glfwSetWindowSizeLimits_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowSizeIncrements_func)(GLFWwindow*, int, int);
|
typedef void (*glfwSetWindowSizeIncrements_func)(GLFWwindow*, int, int);
|
||||||
glfwSetWindowSizeIncrements_func glfwSetWindowSizeIncrements_impl;
|
GFW_EXTERN glfwSetWindowSizeIncrements_func glfwSetWindowSizeIncrements_impl;
|
||||||
#define glfwSetWindowSizeIncrements glfwSetWindowSizeIncrements_impl
|
#define glfwSetWindowSizeIncrements glfwSetWindowSizeIncrements_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowAspectRatio_func)(GLFWwindow*, int, int);
|
typedef void (*glfwSetWindowAspectRatio_func)(GLFWwindow*, int, int);
|
||||||
glfwSetWindowAspectRatio_func glfwSetWindowAspectRatio_impl;
|
GFW_EXTERN glfwSetWindowAspectRatio_func glfwSetWindowAspectRatio_impl;
|
||||||
#define glfwSetWindowAspectRatio glfwSetWindowAspectRatio_impl
|
#define glfwSetWindowAspectRatio glfwSetWindowAspectRatio_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowSize_func)(GLFWwindow*, int, int);
|
typedef void (*glfwSetWindowSize_func)(GLFWwindow*, int, int);
|
||||||
glfwSetWindowSize_func glfwSetWindowSize_impl;
|
GFW_EXTERN glfwSetWindowSize_func glfwSetWindowSize_impl;
|
||||||
#define glfwSetWindowSize glfwSetWindowSize_impl
|
#define glfwSetWindowSize glfwSetWindowSize_impl
|
||||||
|
|
||||||
typedef void (*glfwGetFramebufferSize_func)(GLFWwindow*, int*, int*);
|
typedef void (*glfwGetFramebufferSize_func)(GLFWwindow*, int*, int*);
|
||||||
glfwGetFramebufferSize_func glfwGetFramebufferSize_impl;
|
GFW_EXTERN glfwGetFramebufferSize_func glfwGetFramebufferSize_impl;
|
||||||
#define glfwGetFramebufferSize glfwGetFramebufferSize_impl
|
#define glfwGetFramebufferSize glfwGetFramebufferSize_impl
|
||||||
|
|
||||||
typedef void (*glfwGetWindowFrameSize_func)(GLFWwindow*, int*, int*, int*, int*);
|
typedef void (*glfwGetWindowFrameSize_func)(GLFWwindow*, int*, int*, int*, int*);
|
||||||
glfwGetWindowFrameSize_func glfwGetWindowFrameSize_impl;
|
GFW_EXTERN glfwGetWindowFrameSize_func glfwGetWindowFrameSize_impl;
|
||||||
#define glfwGetWindowFrameSize glfwGetWindowFrameSize_impl
|
#define glfwGetWindowFrameSize glfwGetWindowFrameSize_impl
|
||||||
|
|
||||||
typedef void (*glfwGetWindowContentScale_func)(GLFWwindow*, float*, float*);
|
typedef void (*glfwGetWindowContentScale_func)(GLFWwindow*, float*, float*);
|
||||||
glfwGetWindowContentScale_func glfwGetWindowContentScale_impl;
|
GFW_EXTERN glfwGetWindowContentScale_func glfwGetWindowContentScale_impl;
|
||||||
#define glfwGetWindowContentScale glfwGetWindowContentScale_impl
|
#define glfwGetWindowContentScale glfwGetWindowContentScale_impl
|
||||||
|
|
||||||
typedef monotonic_t (*glfwGetDoubleClickInterval_func)(GLFWwindow*);
|
typedef monotonic_t (*glfwGetDoubleClickInterval_func)(GLFWwindow*);
|
||||||
glfwGetDoubleClickInterval_func glfwGetDoubleClickInterval_impl;
|
GFW_EXTERN glfwGetDoubleClickInterval_func glfwGetDoubleClickInterval_impl;
|
||||||
#define glfwGetDoubleClickInterval glfwGetDoubleClickInterval_impl
|
#define glfwGetDoubleClickInterval glfwGetDoubleClickInterval_impl
|
||||||
|
|
||||||
typedef float (*glfwGetWindowOpacity_func)(GLFWwindow*);
|
typedef float (*glfwGetWindowOpacity_func)(GLFWwindow*);
|
||||||
glfwGetWindowOpacity_func glfwGetWindowOpacity_impl;
|
GFW_EXTERN glfwGetWindowOpacity_func glfwGetWindowOpacity_impl;
|
||||||
#define glfwGetWindowOpacity glfwGetWindowOpacity_impl
|
#define glfwGetWindowOpacity glfwGetWindowOpacity_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowOpacity_func)(GLFWwindow*, float);
|
typedef void (*glfwSetWindowOpacity_func)(GLFWwindow*, float);
|
||||||
glfwSetWindowOpacity_func glfwSetWindowOpacity_impl;
|
GFW_EXTERN glfwSetWindowOpacity_func glfwSetWindowOpacity_impl;
|
||||||
#define glfwSetWindowOpacity glfwSetWindowOpacity_impl
|
#define glfwSetWindowOpacity glfwSetWindowOpacity_impl
|
||||||
|
|
||||||
typedef void (*glfwIconifyWindow_func)(GLFWwindow*);
|
typedef void (*glfwIconifyWindow_func)(GLFWwindow*);
|
||||||
glfwIconifyWindow_func glfwIconifyWindow_impl;
|
GFW_EXTERN glfwIconifyWindow_func glfwIconifyWindow_impl;
|
||||||
#define glfwIconifyWindow glfwIconifyWindow_impl
|
#define glfwIconifyWindow glfwIconifyWindow_impl
|
||||||
|
|
||||||
typedef void (*glfwRestoreWindow_func)(GLFWwindow*);
|
typedef void (*glfwRestoreWindow_func)(GLFWwindow*);
|
||||||
glfwRestoreWindow_func glfwRestoreWindow_impl;
|
GFW_EXTERN glfwRestoreWindow_func glfwRestoreWindow_impl;
|
||||||
#define glfwRestoreWindow glfwRestoreWindow_impl
|
#define glfwRestoreWindow glfwRestoreWindow_impl
|
||||||
|
|
||||||
typedef void (*glfwMaximizeWindow_func)(GLFWwindow*);
|
typedef void (*glfwMaximizeWindow_func)(GLFWwindow*);
|
||||||
glfwMaximizeWindow_func glfwMaximizeWindow_impl;
|
GFW_EXTERN glfwMaximizeWindow_func glfwMaximizeWindow_impl;
|
||||||
#define glfwMaximizeWindow glfwMaximizeWindow_impl
|
#define glfwMaximizeWindow glfwMaximizeWindow_impl
|
||||||
|
|
||||||
typedef void (*glfwShowWindow_func)(GLFWwindow*);
|
typedef void (*glfwShowWindow_func)(GLFWwindow*);
|
||||||
glfwShowWindow_func glfwShowWindow_impl;
|
GFW_EXTERN glfwShowWindow_func glfwShowWindow_impl;
|
||||||
#define glfwShowWindow glfwShowWindow_impl
|
#define glfwShowWindow glfwShowWindow_impl
|
||||||
|
|
||||||
typedef void (*glfwHideWindow_func)(GLFWwindow*);
|
typedef void (*glfwHideWindow_func)(GLFWwindow*);
|
||||||
glfwHideWindow_func glfwHideWindow_impl;
|
GFW_EXTERN glfwHideWindow_func glfwHideWindow_impl;
|
||||||
#define glfwHideWindow glfwHideWindow_impl
|
#define glfwHideWindow glfwHideWindow_impl
|
||||||
|
|
||||||
typedef void (*glfwFocusWindow_func)(GLFWwindow*);
|
typedef void (*glfwFocusWindow_func)(GLFWwindow*);
|
||||||
glfwFocusWindow_func glfwFocusWindow_impl;
|
GFW_EXTERN glfwFocusWindow_func glfwFocusWindow_impl;
|
||||||
#define glfwFocusWindow glfwFocusWindow_impl
|
#define glfwFocusWindow glfwFocusWindow_impl
|
||||||
|
|
||||||
typedef void (*glfwRequestWindowAttention_func)(GLFWwindow*);
|
typedef void (*glfwRequestWindowAttention_func)(GLFWwindow*);
|
||||||
glfwRequestWindowAttention_func glfwRequestWindowAttention_impl;
|
GFW_EXTERN glfwRequestWindowAttention_func glfwRequestWindowAttention_impl;
|
||||||
#define glfwRequestWindowAttention glfwRequestWindowAttention_impl
|
#define glfwRequestWindowAttention glfwRequestWindowAttention_impl
|
||||||
|
|
||||||
typedef int (*glfwWindowBell_func)(GLFWwindow*);
|
typedef int (*glfwWindowBell_func)(GLFWwindow*);
|
||||||
glfwWindowBell_func glfwWindowBell_impl;
|
GFW_EXTERN glfwWindowBell_func glfwWindowBell_impl;
|
||||||
#define glfwWindowBell glfwWindowBell_impl
|
#define glfwWindowBell glfwWindowBell_impl
|
||||||
|
|
||||||
typedef GLFWmonitor* (*glfwGetWindowMonitor_func)(GLFWwindow*);
|
typedef GLFWmonitor* (*glfwGetWindowMonitor_func)(GLFWwindow*);
|
||||||
glfwGetWindowMonitor_func glfwGetWindowMonitor_impl;
|
GFW_EXTERN glfwGetWindowMonitor_func glfwGetWindowMonitor_impl;
|
||||||
#define glfwGetWindowMonitor glfwGetWindowMonitor_impl
|
#define glfwGetWindowMonitor glfwGetWindowMonitor_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowMonitor_func)(GLFWwindow*, GLFWmonitor*, int, int, int, int, int);
|
typedef void (*glfwSetWindowMonitor_func)(GLFWwindow*, GLFWmonitor*, int, int, int, int, int);
|
||||||
glfwSetWindowMonitor_func glfwSetWindowMonitor_impl;
|
GFW_EXTERN glfwSetWindowMonitor_func glfwSetWindowMonitor_impl;
|
||||||
#define glfwSetWindowMonitor glfwSetWindowMonitor_impl
|
#define glfwSetWindowMonitor glfwSetWindowMonitor_impl
|
||||||
|
|
||||||
typedef int (*glfwGetWindowAttrib_func)(GLFWwindow*, int);
|
typedef int (*glfwGetWindowAttrib_func)(GLFWwindow*, int);
|
||||||
glfwGetWindowAttrib_func glfwGetWindowAttrib_impl;
|
GFW_EXTERN glfwGetWindowAttrib_func glfwGetWindowAttrib_impl;
|
||||||
#define glfwGetWindowAttrib glfwGetWindowAttrib_impl
|
#define glfwGetWindowAttrib glfwGetWindowAttrib_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowAttrib_func)(GLFWwindow*, int, int);
|
typedef void (*glfwSetWindowAttrib_func)(GLFWwindow*, int, int);
|
||||||
glfwSetWindowAttrib_func glfwSetWindowAttrib_impl;
|
GFW_EXTERN glfwSetWindowAttrib_func glfwSetWindowAttrib_impl;
|
||||||
#define glfwSetWindowAttrib glfwSetWindowAttrib_impl
|
#define glfwSetWindowAttrib glfwSetWindowAttrib_impl
|
||||||
|
|
||||||
typedef void (*glfwSetWindowUserPointer_func)(GLFWwindow*, void*);
|
typedef void (*glfwSetWindowUserPointer_func)(GLFWwindow*, void*);
|
||||||
glfwSetWindowUserPointer_func glfwSetWindowUserPointer_impl;
|
GFW_EXTERN glfwSetWindowUserPointer_func glfwSetWindowUserPointer_impl;
|
||||||
#define glfwSetWindowUserPointer glfwSetWindowUserPointer_impl
|
#define glfwSetWindowUserPointer glfwSetWindowUserPointer_impl
|
||||||
|
|
||||||
typedef void* (*glfwGetWindowUserPointer_func)(GLFWwindow*);
|
typedef void* (*glfwGetWindowUserPointer_func)(GLFWwindow*);
|
||||||
glfwGetWindowUserPointer_func glfwGetWindowUserPointer_impl;
|
GFW_EXTERN glfwGetWindowUserPointer_func glfwGetWindowUserPointer_impl;
|
||||||
#define glfwGetWindowUserPointer glfwGetWindowUserPointer_impl
|
#define glfwGetWindowUserPointer glfwGetWindowUserPointer_impl
|
||||||
|
|
||||||
typedef GLFWwindowposfun (*glfwSetWindowPosCallback_func)(GLFWwindow*, GLFWwindowposfun);
|
typedef GLFWwindowposfun (*glfwSetWindowPosCallback_func)(GLFWwindow*, GLFWwindowposfun);
|
||||||
glfwSetWindowPosCallback_func glfwSetWindowPosCallback_impl;
|
GFW_EXTERN glfwSetWindowPosCallback_func glfwSetWindowPosCallback_impl;
|
||||||
#define glfwSetWindowPosCallback glfwSetWindowPosCallback_impl
|
#define glfwSetWindowPosCallback glfwSetWindowPosCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowsizefun (*glfwSetWindowSizeCallback_func)(GLFWwindow*, GLFWwindowsizefun);
|
typedef GLFWwindowsizefun (*glfwSetWindowSizeCallback_func)(GLFWwindow*, GLFWwindowsizefun);
|
||||||
glfwSetWindowSizeCallback_func glfwSetWindowSizeCallback_impl;
|
GFW_EXTERN glfwSetWindowSizeCallback_func glfwSetWindowSizeCallback_impl;
|
||||||
#define glfwSetWindowSizeCallback glfwSetWindowSizeCallback_impl
|
#define glfwSetWindowSizeCallback glfwSetWindowSizeCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowclosefun (*glfwSetWindowCloseCallback_func)(GLFWwindow*, GLFWwindowclosefun);
|
typedef GLFWwindowclosefun (*glfwSetWindowCloseCallback_func)(GLFWwindow*, GLFWwindowclosefun);
|
||||||
glfwSetWindowCloseCallback_func glfwSetWindowCloseCallback_impl;
|
GFW_EXTERN glfwSetWindowCloseCallback_func glfwSetWindowCloseCallback_impl;
|
||||||
#define glfwSetWindowCloseCallback glfwSetWindowCloseCallback_impl
|
#define glfwSetWindowCloseCallback glfwSetWindowCloseCallback_impl
|
||||||
|
|
||||||
|
typedef GLFWapplicationclosefun (*glfwSetApplicationCloseCallback_func)(GLFWapplicationclosefun);
|
||||||
|
GFW_EXTERN glfwSetApplicationCloseCallback_func glfwSetApplicationCloseCallback_impl;
|
||||||
|
#define glfwSetApplicationCloseCallback glfwSetApplicationCloseCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowrefreshfun (*glfwSetWindowRefreshCallback_func)(GLFWwindow*, GLFWwindowrefreshfun);
|
typedef GLFWwindowrefreshfun (*glfwSetWindowRefreshCallback_func)(GLFWwindow*, GLFWwindowrefreshfun);
|
||||||
glfwSetWindowRefreshCallback_func glfwSetWindowRefreshCallback_impl;
|
GFW_EXTERN glfwSetWindowRefreshCallback_func glfwSetWindowRefreshCallback_impl;
|
||||||
#define glfwSetWindowRefreshCallback glfwSetWindowRefreshCallback_impl
|
#define glfwSetWindowRefreshCallback glfwSetWindowRefreshCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowfocusfun (*glfwSetWindowFocusCallback_func)(GLFWwindow*, GLFWwindowfocusfun);
|
typedef GLFWwindowfocusfun (*glfwSetWindowFocusCallback_func)(GLFWwindow*, GLFWwindowfocusfun);
|
||||||
glfwSetWindowFocusCallback_func glfwSetWindowFocusCallback_impl;
|
GFW_EXTERN glfwSetWindowFocusCallback_func glfwSetWindowFocusCallback_impl;
|
||||||
#define glfwSetWindowFocusCallback glfwSetWindowFocusCallback_impl
|
#define glfwSetWindowFocusCallback glfwSetWindowFocusCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowocclusionfun (*glfwSetWindowOcclusionCallback_func)(GLFWwindow*, GLFWwindowocclusionfun);
|
typedef GLFWwindowocclusionfun (*glfwSetWindowOcclusionCallback_func)(GLFWwindow*, GLFWwindowocclusionfun);
|
||||||
glfwSetWindowOcclusionCallback_func glfwSetWindowOcclusionCallback_impl;
|
GFW_EXTERN glfwSetWindowOcclusionCallback_func glfwSetWindowOcclusionCallback_impl;
|
||||||
#define glfwSetWindowOcclusionCallback glfwSetWindowOcclusionCallback_impl
|
#define glfwSetWindowOcclusionCallback glfwSetWindowOcclusionCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowiconifyfun (*glfwSetWindowIconifyCallback_func)(GLFWwindow*, GLFWwindowiconifyfun);
|
typedef GLFWwindowiconifyfun (*glfwSetWindowIconifyCallback_func)(GLFWwindow*, GLFWwindowiconifyfun);
|
||||||
glfwSetWindowIconifyCallback_func glfwSetWindowIconifyCallback_impl;
|
GFW_EXTERN glfwSetWindowIconifyCallback_func glfwSetWindowIconifyCallback_impl;
|
||||||
#define glfwSetWindowIconifyCallback glfwSetWindowIconifyCallback_impl
|
#define glfwSetWindowIconifyCallback glfwSetWindowIconifyCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowmaximizefun (*glfwSetWindowMaximizeCallback_func)(GLFWwindow*, GLFWwindowmaximizefun);
|
typedef GLFWwindowmaximizefun (*glfwSetWindowMaximizeCallback_func)(GLFWwindow*, GLFWwindowmaximizefun);
|
||||||
glfwSetWindowMaximizeCallback_func glfwSetWindowMaximizeCallback_impl;
|
GFW_EXTERN glfwSetWindowMaximizeCallback_func glfwSetWindowMaximizeCallback_impl;
|
||||||
#define glfwSetWindowMaximizeCallback glfwSetWindowMaximizeCallback_impl
|
#define glfwSetWindowMaximizeCallback glfwSetWindowMaximizeCallback_impl
|
||||||
|
|
||||||
typedef GLFWframebuffersizefun (*glfwSetFramebufferSizeCallback_func)(GLFWwindow*, GLFWframebuffersizefun);
|
typedef GLFWframebuffersizefun (*glfwSetFramebufferSizeCallback_func)(GLFWwindow*, GLFWframebuffersizefun);
|
||||||
glfwSetFramebufferSizeCallback_func glfwSetFramebufferSizeCallback_impl;
|
GFW_EXTERN glfwSetFramebufferSizeCallback_func glfwSetFramebufferSizeCallback_impl;
|
||||||
#define glfwSetFramebufferSizeCallback glfwSetFramebufferSizeCallback_impl
|
#define glfwSetFramebufferSizeCallback glfwSetFramebufferSizeCallback_impl
|
||||||
|
|
||||||
typedef GLFWwindowcontentscalefun (*glfwSetWindowContentScaleCallback_func)(GLFWwindow*, GLFWwindowcontentscalefun);
|
typedef GLFWwindowcontentscalefun (*glfwSetWindowContentScaleCallback_func)(GLFWwindow*, GLFWwindowcontentscalefun);
|
||||||
glfwSetWindowContentScaleCallback_func glfwSetWindowContentScaleCallback_impl;
|
GFW_EXTERN glfwSetWindowContentScaleCallback_func glfwSetWindowContentScaleCallback_impl;
|
||||||
#define glfwSetWindowContentScaleCallback glfwSetWindowContentScaleCallback_impl
|
#define glfwSetWindowContentScaleCallback glfwSetWindowContentScaleCallback_impl
|
||||||
|
|
||||||
typedef void (*glfwPostEmptyEvent_func)(void);
|
typedef void (*glfwPostEmptyEvent_func)(void);
|
||||||
glfwPostEmptyEvent_func glfwPostEmptyEvent_impl;
|
GFW_EXTERN glfwPostEmptyEvent_func glfwPostEmptyEvent_impl;
|
||||||
#define glfwPostEmptyEvent glfwPostEmptyEvent_impl
|
#define glfwPostEmptyEvent glfwPostEmptyEvent_impl
|
||||||
|
|
||||||
typedef int (*glfwGetInputMode_func)(GLFWwindow*, int);
|
typedef int (*glfwGetInputMode_func)(GLFWwindow*, int);
|
||||||
glfwGetInputMode_func glfwGetInputMode_impl;
|
GFW_EXTERN glfwGetInputMode_func glfwGetInputMode_impl;
|
||||||
#define glfwGetInputMode glfwGetInputMode_impl
|
#define glfwGetInputMode glfwGetInputMode_impl
|
||||||
|
|
||||||
typedef void (*glfwSetInputMode_func)(GLFWwindow*, int, int);
|
typedef void (*glfwSetInputMode_func)(GLFWwindow*, int, int);
|
||||||
glfwSetInputMode_func glfwSetInputMode_impl;
|
GFW_EXTERN glfwSetInputMode_func glfwSetInputMode_impl;
|
||||||
#define glfwSetInputMode glfwSetInputMode_impl
|
#define glfwSetInputMode glfwSetInputMode_impl
|
||||||
|
|
||||||
|
typedef int (*glfwRawMouseMotionSupported_func)(void);
|
||||||
|
GFW_EXTERN glfwRawMouseMotionSupported_func glfwRawMouseMotionSupported_impl;
|
||||||
|
#define glfwRawMouseMotionSupported glfwRawMouseMotionSupported_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetKeyName_func)(int, int);
|
typedef const char* (*glfwGetKeyName_func)(int, int);
|
||||||
glfwGetKeyName_func glfwGetKeyName_impl;
|
GFW_EXTERN glfwGetKeyName_func glfwGetKeyName_impl;
|
||||||
#define glfwGetKeyName glfwGetKeyName_impl
|
#define glfwGetKeyName glfwGetKeyName_impl
|
||||||
|
|
||||||
typedef int (*glfwGetNativeKeyForKey_func)(int);
|
typedef int (*glfwGetNativeKeyForKey_func)(int);
|
||||||
glfwGetNativeKeyForKey_func glfwGetNativeKeyForKey_impl;
|
GFW_EXTERN glfwGetNativeKeyForKey_func glfwGetNativeKeyForKey_impl;
|
||||||
#define glfwGetNativeKeyForKey glfwGetNativeKeyForKey_impl
|
#define glfwGetNativeKeyForKey glfwGetNativeKeyForKey_impl
|
||||||
|
|
||||||
typedef int (*glfwGetKey_func)(GLFWwindow*, int);
|
typedef int (*glfwGetKey_func)(GLFWwindow*, int);
|
||||||
glfwGetKey_func glfwGetKey_impl;
|
GFW_EXTERN glfwGetKey_func glfwGetKey_impl;
|
||||||
#define glfwGetKey glfwGetKey_impl
|
#define glfwGetKey glfwGetKey_impl
|
||||||
|
|
||||||
typedef int (*glfwGetMouseButton_func)(GLFWwindow*, int);
|
typedef int (*glfwGetMouseButton_func)(GLFWwindow*, int);
|
||||||
glfwGetMouseButton_func glfwGetMouseButton_impl;
|
GFW_EXTERN glfwGetMouseButton_func glfwGetMouseButton_impl;
|
||||||
#define glfwGetMouseButton glfwGetMouseButton_impl
|
#define glfwGetMouseButton glfwGetMouseButton_impl
|
||||||
|
|
||||||
typedef void (*glfwGetCursorPos_func)(GLFWwindow*, double*, double*);
|
typedef void (*glfwGetCursorPos_func)(GLFWwindow*, double*, double*);
|
||||||
glfwGetCursorPos_func glfwGetCursorPos_impl;
|
GFW_EXTERN glfwGetCursorPos_func glfwGetCursorPos_impl;
|
||||||
#define glfwGetCursorPos glfwGetCursorPos_impl
|
#define glfwGetCursorPos glfwGetCursorPos_impl
|
||||||
|
|
||||||
typedef void (*glfwSetCursorPos_func)(GLFWwindow*, double, double);
|
typedef void (*glfwSetCursorPos_func)(GLFWwindow*, double, double);
|
||||||
glfwSetCursorPos_func glfwSetCursorPos_impl;
|
GFW_EXTERN glfwSetCursorPos_func glfwSetCursorPos_impl;
|
||||||
#define glfwSetCursorPos glfwSetCursorPos_impl
|
#define glfwSetCursorPos glfwSetCursorPos_impl
|
||||||
|
|
||||||
typedef GLFWcursor* (*glfwCreateCursor_func)(const GLFWimage*, int, int, int);
|
typedef GLFWcursor* (*glfwCreateCursor_func)(const GLFWimage*, int, int, int);
|
||||||
glfwCreateCursor_func glfwCreateCursor_impl;
|
GFW_EXTERN glfwCreateCursor_func glfwCreateCursor_impl;
|
||||||
#define glfwCreateCursor glfwCreateCursor_impl
|
#define glfwCreateCursor glfwCreateCursor_impl
|
||||||
|
|
||||||
typedef GLFWcursor* (*glfwCreateStandardCursor_func)(GLFWCursorShape);
|
typedef GLFWcursor* (*glfwCreateStandardCursor_func)(GLFWCursorShape);
|
||||||
glfwCreateStandardCursor_func glfwCreateStandardCursor_impl;
|
GFW_EXTERN glfwCreateStandardCursor_func glfwCreateStandardCursor_impl;
|
||||||
#define glfwCreateStandardCursor glfwCreateStandardCursor_impl
|
#define glfwCreateStandardCursor glfwCreateStandardCursor_impl
|
||||||
|
|
||||||
typedef void (*glfwDestroyCursor_func)(GLFWcursor*);
|
typedef void (*glfwDestroyCursor_func)(GLFWcursor*);
|
||||||
glfwDestroyCursor_func glfwDestroyCursor_impl;
|
GFW_EXTERN glfwDestroyCursor_func glfwDestroyCursor_impl;
|
||||||
#define glfwDestroyCursor glfwDestroyCursor_impl
|
#define glfwDestroyCursor glfwDestroyCursor_impl
|
||||||
|
|
||||||
typedef void (*glfwSetCursor_func)(GLFWwindow*, GLFWcursor*);
|
typedef void (*glfwSetCursor_func)(GLFWwindow*, GLFWcursor*);
|
||||||
glfwSetCursor_func glfwSetCursor_impl;
|
GFW_EXTERN glfwSetCursor_func glfwSetCursor_impl;
|
||||||
#define glfwSetCursor glfwSetCursor_impl
|
#define glfwSetCursor glfwSetCursor_impl
|
||||||
|
|
||||||
typedef GLFWkeyboardfun (*glfwSetKeyboardCallback_func)(GLFWwindow*, GLFWkeyboardfun);
|
typedef GLFWkeyboardfun (*glfwSetKeyboardCallback_func)(GLFWwindow*, GLFWkeyboardfun);
|
||||||
glfwSetKeyboardCallback_func glfwSetKeyboardCallback_impl;
|
GFW_EXTERN glfwSetKeyboardCallback_func glfwSetKeyboardCallback_impl;
|
||||||
#define glfwSetKeyboardCallback glfwSetKeyboardCallback_impl
|
#define glfwSetKeyboardCallback glfwSetKeyboardCallback_impl
|
||||||
|
|
||||||
typedef void (*glfwUpdateIMEState_func)(GLFWwindow*, int, int, int, int, int);
|
typedef void (*glfwUpdateIMEState_func)(GLFWwindow*, int, int, int, int, int);
|
||||||
glfwUpdateIMEState_func glfwUpdateIMEState_impl;
|
GFW_EXTERN glfwUpdateIMEState_func glfwUpdateIMEState_impl;
|
||||||
#define glfwUpdateIMEState glfwUpdateIMEState_impl
|
#define glfwUpdateIMEState glfwUpdateIMEState_impl
|
||||||
|
|
||||||
typedef GLFWmousebuttonfun (*glfwSetMouseButtonCallback_func)(GLFWwindow*, GLFWmousebuttonfun);
|
typedef GLFWmousebuttonfun (*glfwSetMouseButtonCallback_func)(GLFWwindow*, GLFWmousebuttonfun);
|
||||||
glfwSetMouseButtonCallback_func glfwSetMouseButtonCallback_impl;
|
GFW_EXTERN glfwSetMouseButtonCallback_func glfwSetMouseButtonCallback_impl;
|
||||||
#define glfwSetMouseButtonCallback glfwSetMouseButtonCallback_impl
|
#define glfwSetMouseButtonCallback glfwSetMouseButtonCallback_impl
|
||||||
|
|
||||||
typedef GLFWcursorposfun (*glfwSetCursorPosCallback_func)(GLFWwindow*, GLFWcursorposfun);
|
typedef GLFWcursorposfun (*glfwSetCursorPosCallback_func)(GLFWwindow*, GLFWcursorposfun);
|
||||||
glfwSetCursorPosCallback_func glfwSetCursorPosCallback_impl;
|
GFW_EXTERN glfwSetCursorPosCallback_func glfwSetCursorPosCallback_impl;
|
||||||
#define glfwSetCursorPosCallback glfwSetCursorPosCallback_impl
|
#define glfwSetCursorPosCallback glfwSetCursorPosCallback_impl
|
||||||
|
|
||||||
typedef GLFWcursorenterfun (*glfwSetCursorEnterCallback_func)(GLFWwindow*, GLFWcursorenterfun);
|
typedef GLFWcursorenterfun (*glfwSetCursorEnterCallback_func)(GLFWwindow*, GLFWcursorenterfun);
|
||||||
glfwSetCursorEnterCallback_func glfwSetCursorEnterCallback_impl;
|
GFW_EXTERN glfwSetCursorEnterCallback_func glfwSetCursorEnterCallback_impl;
|
||||||
#define glfwSetCursorEnterCallback glfwSetCursorEnterCallback_impl
|
#define glfwSetCursorEnterCallback glfwSetCursorEnterCallback_impl
|
||||||
|
|
||||||
typedef GLFWscrollfun (*glfwSetScrollCallback_func)(GLFWwindow*, GLFWscrollfun);
|
typedef GLFWscrollfun (*glfwSetScrollCallback_func)(GLFWwindow*, GLFWscrollfun);
|
||||||
glfwSetScrollCallback_func glfwSetScrollCallback_impl;
|
GFW_EXTERN glfwSetScrollCallback_func glfwSetScrollCallback_impl;
|
||||||
#define glfwSetScrollCallback glfwSetScrollCallback_impl
|
#define glfwSetScrollCallback glfwSetScrollCallback_impl
|
||||||
|
|
||||||
typedef GLFWdropfun (*glfwSetDropCallback_func)(GLFWwindow*, GLFWdropfun);
|
typedef GLFWdropfun (*glfwSetDropCallback_func)(GLFWwindow*, GLFWdropfun);
|
||||||
glfwSetDropCallback_func glfwSetDropCallback_impl;
|
GFW_EXTERN glfwSetDropCallback_func glfwSetDropCallback_impl;
|
||||||
#define glfwSetDropCallback glfwSetDropCallback_impl
|
#define glfwSetDropCallback glfwSetDropCallback_impl
|
||||||
|
|
||||||
typedef GLFWliveresizefun (*glfwSetLiveResizeCallback_func)(GLFWwindow*, GLFWliveresizefun);
|
typedef GLFWliveresizefun (*glfwSetLiveResizeCallback_func)(GLFWwindow*, GLFWliveresizefun);
|
||||||
glfwSetLiveResizeCallback_func glfwSetLiveResizeCallback_impl;
|
GFW_EXTERN glfwSetLiveResizeCallback_func glfwSetLiveResizeCallback_impl;
|
||||||
#define glfwSetLiveResizeCallback glfwSetLiveResizeCallback_impl
|
#define glfwSetLiveResizeCallback glfwSetLiveResizeCallback_impl
|
||||||
|
|
||||||
typedef int (*glfwJoystickPresent_func)(int);
|
typedef int (*glfwJoystickPresent_func)(int);
|
||||||
glfwJoystickPresent_func glfwJoystickPresent_impl;
|
GFW_EXTERN glfwJoystickPresent_func glfwJoystickPresent_impl;
|
||||||
#define glfwJoystickPresent glfwJoystickPresent_impl
|
#define glfwJoystickPresent glfwJoystickPresent_impl
|
||||||
|
|
||||||
typedef const float* (*glfwGetJoystickAxes_func)(int, int*);
|
typedef const float* (*glfwGetJoystickAxes_func)(int, int*);
|
||||||
glfwGetJoystickAxes_func glfwGetJoystickAxes_impl;
|
GFW_EXTERN glfwGetJoystickAxes_func glfwGetJoystickAxes_impl;
|
||||||
#define glfwGetJoystickAxes glfwGetJoystickAxes_impl
|
#define glfwGetJoystickAxes glfwGetJoystickAxes_impl
|
||||||
|
|
||||||
typedef const unsigned char* (*glfwGetJoystickButtons_func)(int, int*);
|
typedef const unsigned char* (*glfwGetJoystickButtons_func)(int, int*);
|
||||||
glfwGetJoystickButtons_func glfwGetJoystickButtons_impl;
|
GFW_EXTERN glfwGetJoystickButtons_func glfwGetJoystickButtons_impl;
|
||||||
#define glfwGetJoystickButtons glfwGetJoystickButtons_impl
|
#define glfwGetJoystickButtons glfwGetJoystickButtons_impl
|
||||||
|
|
||||||
typedef const unsigned char* (*glfwGetJoystickHats_func)(int, int*);
|
typedef const unsigned char* (*glfwGetJoystickHats_func)(int, int*);
|
||||||
glfwGetJoystickHats_func glfwGetJoystickHats_impl;
|
GFW_EXTERN glfwGetJoystickHats_func glfwGetJoystickHats_impl;
|
||||||
#define glfwGetJoystickHats glfwGetJoystickHats_impl
|
#define glfwGetJoystickHats glfwGetJoystickHats_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetJoystickName_func)(int);
|
typedef const char* (*glfwGetJoystickName_func)(int);
|
||||||
glfwGetJoystickName_func glfwGetJoystickName_impl;
|
GFW_EXTERN glfwGetJoystickName_func glfwGetJoystickName_impl;
|
||||||
#define glfwGetJoystickName glfwGetJoystickName_impl
|
#define glfwGetJoystickName glfwGetJoystickName_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetJoystickGUID_func)(int);
|
typedef const char* (*glfwGetJoystickGUID_func)(int);
|
||||||
glfwGetJoystickGUID_func glfwGetJoystickGUID_impl;
|
GFW_EXTERN glfwGetJoystickGUID_func glfwGetJoystickGUID_impl;
|
||||||
#define glfwGetJoystickGUID glfwGetJoystickGUID_impl
|
#define glfwGetJoystickGUID glfwGetJoystickGUID_impl
|
||||||
|
|
||||||
typedef void (*glfwSetJoystickUserPointer_func)(int, void*);
|
typedef void (*glfwSetJoystickUserPointer_func)(int, void*);
|
||||||
glfwSetJoystickUserPointer_func glfwSetJoystickUserPointer_impl;
|
GFW_EXTERN glfwSetJoystickUserPointer_func glfwSetJoystickUserPointer_impl;
|
||||||
#define glfwSetJoystickUserPointer glfwSetJoystickUserPointer_impl
|
#define glfwSetJoystickUserPointer glfwSetJoystickUserPointer_impl
|
||||||
|
|
||||||
typedef void* (*glfwGetJoystickUserPointer_func)(int);
|
typedef void* (*glfwGetJoystickUserPointer_func)(int);
|
||||||
glfwGetJoystickUserPointer_func glfwGetJoystickUserPointer_impl;
|
GFW_EXTERN glfwGetJoystickUserPointer_func glfwGetJoystickUserPointer_impl;
|
||||||
#define glfwGetJoystickUserPointer glfwGetJoystickUserPointer_impl
|
#define glfwGetJoystickUserPointer glfwGetJoystickUserPointer_impl
|
||||||
|
|
||||||
typedef int (*glfwJoystickIsGamepad_func)(int);
|
typedef int (*glfwJoystickIsGamepad_func)(int);
|
||||||
glfwJoystickIsGamepad_func glfwJoystickIsGamepad_impl;
|
GFW_EXTERN glfwJoystickIsGamepad_func glfwJoystickIsGamepad_impl;
|
||||||
#define glfwJoystickIsGamepad glfwJoystickIsGamepad_impl
|
#define glfwJoystickIsGamepad glfwJoystickIsGamepad_impl
|
||||||
|
|
||||||
typedef GLFWjoystickfun (*glfwSetJoystickCallback_func)(GLFWjoystickfun);
|
typedef GLFWjoystickfun (*glfwSetJoystickCallback_func)(GLFWjoystickfun);
|
||||||
glfwSetJoystickCallback_func glfwSetJoystickCallback_impl;
|
GFW_EXTERN glfwSetJoystickCallback_func glfwSetJoystickCallback_impl;
|
||||||
#define glfwSetJoystickCallback glfwSetJoystickCallback_impl
|
#define glfwSetJoystickCallback glfwSetJoystickCallback_impl
|
||||||
|
|
||||||
typedef int (*glfwUpdateGamepadMappings_func)(const char*);
|
typedef int (*glfwUpdateGamepadMappings_func)(const char*);
|
||||||
glfwUpdateGamepadMappings_func glfwUpdateGamepadMappings_impl;
|
GFW_EXTERN glfwUpdateGamepadMappings_func glfwUpdateGamepadMappings_impl;
|
||||||
#define glfwUpdateGamepadMappings glfwUpdateGamepadMappings_impl
|
#define glfwUpdateGamepadMappings glfwUpdateGamepadMappings_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetGamepadName_func)(int);
|
typedef const char* (*glfwGetGamepadName_func)(int);
|
||||||
glfwGetGamepadName_func glfwGetGamepadName_impl;
|
GFW_EXTERN glfwGetGamepadName_func glfwGetGamepadName_impl;
|
||||||
#define glfwGetGamepadName glfwGetGamepadName_impl
|
#define glfwGetGamepadName glfwGetGamepadName_impl
|
||||||
|
|
||||||
typedef int (*glfwGetGamepadState_func)(int, GLFWgamepadstate*);
|
typedef int (*glfwGetGamepadState_func)(int, GLFWgamepadstate*);
|
||||||
glfwGetGamepadState_func glfwGetGamepadState_impl;
|
GFW_EXTERN glfwGetGamepadState_func glfwGetGamepadState_impl;
|
||||||
#define glfwGetGamepadState glfwGetGamepadState_impl
|
#define glfwGetGamepadState glfwGetGamepadState_impl
|
||||||
|
|
||||||
typedef void (*glfwSetClipboardString_func)(GLFWwindow*, const char*);
|
typedef void (*glfwSetClipboardString_func)(GLFWwindow*, const char*);
|
||||||
glfwSetClipboardString_func glfwSetClipboardString_impl;
|
GFW_EXTERN glfwSetClipboardString_func glfwSetClipboardString_impl;
|
||||||
#define glfwSetClipboardString glfwSetClipboardString_impl
|
#define glfwSetClipboardString glfwSetClipboardString_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetClipboardString_func)(GLFWwindow*);
|
typedef const char* (*glfwGetClipboardString_func)(GLFWwindow*);
|
||||||
glfwGetClipboardString_func glfwGetClipboardString_impl;
|
GFW_EXTERN glfwGetClipboardString_func glfwGetClipboardString_impl;
|
||||||
#define glfwGetClipboardString glfwGetClipboardString_impl
|
#define glfwGetClipboardString glfwGetClipboardString_impl
|
||||||
|
|
||||||
typedef monotonic_t (*glfwGetTime_func)(void);
|
typedef monotonic_t (*glfwGetTime_func)(void);
|
||||||
glfwGetTime_func glfwGetTime_impl;
|
GFW_EXTERN glfwGetTime_func glfwGetTime_impl;
|
||||||
#define glfwGetTime glfwGetTime_impl
|
#define glfwGetTime glfwGetTime_impl
|
||||||
|
|
||||||
typedef void (*glfwMakeContextCurrent_func)(GLFWwindow*);
|
typedef void (*glfwMakeContextCurrent_func)(GLFWwindow*);
|
||||||
glfwMakeContextCurrent_func glfwMakeContextCurrent_impl;
|
GFW_EXTERN glfwMakeContextCurrent_func glfwMakeContextCurrent_impl;
|
||||||
#define glfwMakeContextCurrent glfwMakeContextCurrent_impl
|
#define glfwMakeContextCurrent glfwMakeContextCurrent_impl
|
||||||
|
|
||||||
typedef GLFWwindow* (*glfwGetCurrentContext_func)(void);
|
typedef GLFWwindow* (*glfwGetCurrentContext_func)(void);
|
||||||
glfwGetCurrentContext_func glfwGetCurrentContext_impl;
|
GFW_EXTERN glfwGetCurrentContext_func glfwGetCurrentContext_impl;
|
||||||
#define glfwGetCurrentContext glfwGetCurrentContext_impl
|
#define glfwGetCurrentContext glfwGetCurrentContext_impl
|
||||||
|
|
||||||
typedef void (*glfwSwapBuffers_func)(GLFWwindow*);
|
typedef void (*glfwSwapBuffers_func)(GLFWwindow*);
|
||||||
glfwSwapBuffers_func glfwSwapBuffers_impl;
|
GFW_EXTERN glfwSwapBuffers_func glfwSwapBuffers_impl;
|
||||||
#define glfwSwapBuffers glfwSwapBuffers_impl
|
#define glfwSwapBuffers glfwSwapBuffers_impl
|
||||||
|
|
||||||
typedef void (*glfwSwapInterval_func)(int);
|
typedef void (*glfwSwapInterval_func)(int);
|
||||||
glfwSwapInterval_func glfwSwapInterval_impl;
|
GFW_EXTERN glfwSwapInterval_func glfwSwapInterval_impl;
|
||||||
#define glfwSwapInterval glfwSwapInterval_impl
|
#define glfwSwapInterval glfwSwapInterval_impl
|
||||||
|
|
||||||
typedef int (*glfwExtensionSupported_func)(const char*);
|
typedef int (*glfwExtensionSupported_func)(const char*);
|
||||||
glfwExtensionSupported_func glfwExtensionSupported_impl;
|
GFW_EXTERN glfwExtensionSupported_func glfwExtensionSupported_impl;
|
||||||
#define glfwExtensionSupported glfwExtensionSupported_impl
|
#define glfwExtensionSupported glfwExtensionSupported_impl
|
||||||
|
|
||||||
typedef GLFWglproc (*glfwGetProcAddress_func)(const char*);
|
typedef GLFWglproc (*glfwGetProcAddress_func)(const char*);
|
||||||
glfwGetProcAddress_func glfwGetProcAddress_impl;
|
GFW_EXTERN glfwGetProcAddress_func glfwGetProcAddress_impl;
|
||||||
#define glfwGetProcAddress glfwGetProcAddress_impl
|
#define glfwGetProcAddress glfwGetProcAddress_impl
|
||||||
|
|
||||||
typedef int (*glfwVulkanSupported_func)(void);
|
typedef int (*glfwVulkanSupported_func)(void);
|
||||||
glfwVulkanSupported_func glfwVulkanSupported_impl;
|
GFW_EXTERN glfwVulkanSupported_func glfwVulkanSupported_impl;
|
||||||
#define glfwVulkanSupported glfwVulkanSupported_impl
|
#define glfwVulkanSupported glfwVulkanSupported_impl
|
||||||
|
|
||||||
typedef const char** (*glfwGetRequiredInstanceExtensions_func)(uint32_t*);
|
typedef const char** (*glfwGetRequiredInstanceExtensions_func)(uint32_t*);
|
||||||
glfwGetRequiredInstanceExtensions_func glfwGetRequiredInstanceExtensions_impl;
|
GFW_EXTERN glfwGetRequiredInstanceExtensions_func glfwGetRequiredInstanceExtensions_impl;
|
||||||
#define glfwGetRequiredInstanceExtensions glfwGetRequiredInstanceExtensions_impl
|
#define glfwGetRequiredInstanceExtensions glfwGetRequiredInstanceExtensions_impl
|
||||||
|
|
||||||
typedef void* (*glfwGetCocoaWindow_func)(GLFWwindow*);
|
typedef void* (*glfwGetCocoaWindow_func)(GLFWwindow*);
|
||||||
glfwGetCocoaWindow_func glfwGetCocoaWindow_impl;
|
GFW_EXTERN glfwGetCocoaWindow_func glfwGetCocoaWindow_impl;
|
||||||
#define glfwGetCocoaWindow glfwGetCocoaWindow_impl
|
#define glfwGetCocoaWindow glfwGetCocoaWindow_impl
|
||||||
|
|
||||||
typedef void* (*glfwGetNSGLContext_func)(GLFWwindow*);
|
typedef void* (*glfwGetNSGLContext_func)(GLFWwindow*);
|
||||||
glfwGetNSGLContext_func glfwGetNSGLContext_impl;
|
GFW_EXTERN glfwGetNSGLContext_func glfwGetNSGLContext_impl;
|
||||||
#define glfwGetNSGLContext glfwGetNSGLContext_impl
|
#define glfwGetNSGLContext glfwGetNSGLContext_impl
|
||||||
|
|
||||||
typedef uint32_t (*glfwGetCocoaMonitor_func)(GLFWmonitor*);
|
typedef uint32_t (*glfwGetCocoaMonitor_func)(GLFWmonitor*);
|
||||||
glfwGetCocoaMonitor_func glfwGetCocoaMonitor_impl;
|
GFW_EXTERN glfwGetCocoaMonitor_func glfwGetCocoaMonitor_impl;
|
||||||
#define glfwGetCocoaMonitor glfwGetCocoaMonitor_impl
|
#define glfwGetCocoaMonitor glfwGetCocoaMonitor_impl
|
||||||
|
|
||||||
typedef GLFWcocoatextinputfilterfun (*glfwSetCocoaTextInputFilter_func)(GLFWwindow*, GLFWcocoatextinputfilterfun);
|
typedef GLFWcocoatextinputfilterfun (*glfwSetCocoaTextInputFilter_func)(GLFWwindow*, GLFWcocoatextinputfilterfun);
|
||||||
glfwSetCocoaTextInputFilter_func glfwSetCocoaTextInputFilter_impl;
|
GFW_EXTERN glfwSetCocoaTextInputFilter_func glfwSetCocoaTextInputFilter_impl;
|
||||||
#define glfwSetCocoaTextInputFilter glfwSetCocoaTextInputFilter_impl
|
#define glfwSetCocoaTextInputFilter glfwSetCocoaTextInputFilter_impl
|
||||||
|
|
||||||
typedef GLFWcocoatogglefullscreenfun (*glfwSetCocoaToggleFullscreenIntercept_func)(GLFWwindow*, GLFWcocoatogglefullscreenfun);
|
typedef GLFWcocoatogglefullscreenfun (*glfwSetCocoaToggleFullscreenIntercept_func)(GLFWwindow*, GLFWcocoatogglefullscreenfun);
|
||||||
glfwSetCocoaToggleFullscreenIntercept_func glfwSetCocoaToggleFullscreenIntercept_impl;
|
GFW_EXTERN glfwSetCocoaToggleFullscreenIntercept_func glfwSetCocoaToggleFullscreenIntercept_impl;
|
||||||
#define glfwSetCocoaToggleFullscreenIntercept glfwSetCocoaToggleFullscreenIntercept_impl
|
#define glfwSetCocoaToggleFullscreenIntercept glfwSetCocoaToggleFullscreenIntercept_impl
|
||||||
|
|
||||||
typedef GLFWapplicationshouldhandlereopenfun (*glfwSetApplicationShouldHandleReopen_func)(GLFWapplicationshouldhandlereopenfun);
|
typedef GLFWapplicationshouldhandlereopenfun (*glfwSetApplicationShouldHandleReopen_func)(GLFWapplicationshouldhandlereopenfun);
|
||||||
glfwSetApplicationShouldHandleReopen_func glfwSetApplicationShouldHandleReopen_impl;
|
GFW_EXTERN glfwSetApplicationShouldHandleReopen_func glfwSetApplicationShouldHandleReopen_impl;
|
||||||
#define glfwSetApplicationShouldHandleReopen glfwSetApplicationShouldHandleReopen_impl
|
#define glfwSetApplicationShouldHandleReopen glfwSetApplicationShouldHandleReopen_impl
|
||||||
|
|
||||||
typedef GLFWapplicationwillfinishlaunchingfun (*glfwSetApplicationWillFinishLaunching_func)(GLFWapplicationwillfinishlaunchingfun);
|
typedef GLFWapplicationwillfinishlaunchingfun (*glfwSetApplicationWillFinishLaunching_func)(GLFWapplicationwillfinishlaunchingfun);
|
||||||
glfwSetApplicationWillFinishLaunching_func glfwSetApplicationWillFinishLaunching_impl;
|
GFW_EXTERN glfwSetApplicationWillFinishLaunching_func glfwSetApplicationWillFinishLaunching_impl;
|
||||||
#define glfwSetApplicationWillFinishLaunching glfwSetApplicationWillFinishLaunching_impl
|
#define glfwSetApplicationWillFinishLaunching glfwSetApplicationWillFinishLaunching_impl
|
||||||
|
|
||||||
typedef void (*glfwGetCocoaKeyEquivalent_func)(int, int, char*, size_t, int*);
|
typedef void (*glfwGetCocoaKeyEquivalent_func)(int, int, char*, size_t, int*);
|
||||||
glfwGetCocoaKeyEquivalent_func glfwGetCocoaKeyEquivalent_impl;
|
GFW_EXTERN glfwGetCocoaKeyEquivalent_func glfwGetCocoaKeyEquivalent_impl;
|
||||||
#define glfwGetCocoaKeyEquivalent glfwGetCocoaKeyEquivalent_impl
|
#define glfwGetCocoaKeyEquivalent glfwGetCocoaKeyEquivalent_impl
|
||||||
|
|
||||||
typedef void (*glfwCocoaRequestRenderFrame_func)(GLFWwindow*, GLFWcocoarenderframefun);
|
typedef void (*glfwCocoaRequestRenderFrame_func)(GLFWwindow*, GLFWcocoarenderframefun);
|
||||||
glfwCocoaRequestRenderFrame_func glfwCocoaRequestRenderFrame_impl;
|
GFW_EXTERN glfwCocoaRequestRenderFrame_func glfwCocoaRequestRenderFrame_impl;
|
||||||
#define glfwCocoaRequestRenderFrame glfwCocoaRequestRenderFrame_impl
|
#define glfwCocoaRequestRenderFrame glfwCocoaRequestRenderFrame_impl
|
||||||
|
|
||||||
typedef void* (*glfwGetX11Display_func)(void);
|
typedef void* (*glfwGetX11Display_func)(void);
|
||||||
glfwGetX11Display_func glfwGetX11Display_impl;
|
GFW_EXTERN glfwGetX11Display_func glfwGetX11Display_impl;
|
||||||
#define glfwGetX11Display glfwGetX11Display_impl
|
#define glfwGetX11Display glfwGetX11Display_impl
|
||||||
|
|
||||||
typedef int32_t (*glfwGetX11Window_func)(GLFWwindow*);
|
typedef int32_t (*glfwGetX11Window_func)(GLFWwindow*);
|
||||||
glfwGetX11Window_func glfwGetX11Window_impl;
|
GFW_EXTERN glfwGetX11Window_func glfwGetX11Window_impl;
|
||||||
#define glfwGetX11Window glfwGetX11Window_impl
|
#define glfwGetX11Window glfwGetX11Window_impl
|
||||||
|
|
||||||
typedef void (*glfwSetPrimarySelectionString_func)(GLFWwindow*, const char*);
|
typedef void (*glfwSetPrimarySelectionString_func)(GLFWwindow*, const char*);
|
||||||
glfwSetPrimarySelectionString_func glfwSetPrimarySelectionString_impl;
|
GFW_EXTERN glfwSetPrimarySelectionString_func glfwSetPrimarySelectionString_impl;
|
||||||
#define glfwSetPrimarySelectionString glfwSetPrimarySelectionString_impl
|
#define glfwSetPrimarySelectionString glfwSetPrimarySelectionString_impl
|
||||||
|
|
||||||
typedef const char* (*glfwGetPrimarySelectionString_func)(GLFWwindow*);
|
typedef const char* (*glfwGetPrimarySelectionString_func)(GLFWwindow*);
|
||||||
glfwGetPrimarySelectionString_func glfwGetPrimarySelectionString_impl;
|
GFW_EXTERN glfwGetPrimarySelectionString_func glfwGetPrimarySelectionString_impl;
|
||||||
#define glfwGetPrimarySelectionString glfwGetPrimarySelectionString_impl
|
#define glfwGetPrimarySelectionString glfwGetPrimarySelectionString_impl
|
||||||
|
|
||||||
typedef int (*glfwGetNativeKeyForName_func)(const char*, int);
|
typedef int (*glfwGetNativeKeyForName_func)(const char*, int);
|
||||||
glfwGetNativeKeyForName_func glfwGetNativeKeyForName_impl;
|
GFW_EXTERN glfwGetNativeKeyForName_func glfwGetNativeKeyForName_impl;
|
||||||
#define glfwGetNativeKeyForName glfwGetNativeKeyForName_impl
|
#define glfwGetNativeKeyForName glfwGetNativeKeyForName_impl
|
||||||
|
|
||||||
typedef void (*glfwRequestWaylandFrameEvent_func)(GLFWwindow*, unsigned long long, GLFWwaylandframecallbackfunc);
|
typedef void (*glfwRequestWaylandFrameEvent_func)(GLFWwindow*, unsigned long long, GLFWwaylandframecallbackfunc);
|
||||||
glfwRequestWaylandFrameEvent_func glfwRequestWaylandFrameEvent_impl;
|
GFW_EXTERN glfwRequestWaylandFrameEvent_func glfwRequestWaylandFrameEvent_impl;
|
||||||
#define glfwRequestWaylandFrameEvent glfwRequestWaylandFrameEvent_impl
|
#define glfwRequestWaylandFrameEvent glfwRequestWaylandFrameEvent_impl
|
||||||
|
|
||||||
typedef unsigned long long (*glfwDBusUserNotify_func)(const char*, const char*, const char*, const char*, const char*, int32_t, GLFWDBusnotificationcreatedfun, void*);
|
typedef unsigned long long (*glfwDBusUserNotify_func)(const char*, const char*, const char*, const char*, const char*, int32_t, GLFWDBusnotificationcreatedfun, void*);
|
||||||
glfwDBusUserNotify_func glfwDBusUserNotify_impl;
|
GFW_EXTERN glfwDBusUserNotify_func glfwDBusUserNotify_impl;
|
||||||
#define glfwDBusUserNotify glfwDBusUserNotify_impl
|
#define glfwDBusUserNotify glfwDBusUserNotify_impl
|
||||||
|
|
||||||
typedef void (*glfwDBusSetUserNotificationHandler_func)(GLFWDBusnotificationactivatedfun);
|
typedef void (*glfwDBusSetUserNotificationHandler_func)(GLFWDBusnotificationactivatedfun);
|
||||||
glfwDBusSetUserNotificationHandler_func glfwDBusSetUserNotificationHandler_impl;
|
GFW_EXTERN glfwDBusSetUserNotificationHandler_func glfwDBusSetUserNotificationHandler_impl;
|
||||||
#define glfwDBusSetUserNotificationHandler glfwDBusSetUserNotificationHandler_impl
|
#define glfwDBusSetUserNotificationHandler glfwDBusSetUserNotificationHandler_impl
|
||||||
|
|
||||||
const char* load_glfw(const char* path);
|
const char* load_glfw(const char* path);
|
||||||
|
|||||||
141
kitty/glfw.c
141
kitty/glfw.c
@@ -152,19 +152,15 @@ blank_os_window(OSWindow *w) {
|
|||||||
static void
|
static void
|
||||||
window_close_callback(GLFWwindow* window) {
|
window_close_callback(GLFWwindow* window) {
|
||||||
if (!set_callback_window(window)) return;
|
if (!set_callback_window(window)) return;
|
||||||
global_state.has_pending_closes = true;
|
if (global_state.callback_os_window->close_request == NO_CLOSE_REQUESTED) {
|
||||||
request_tick_callback();
|
global_state.callback_os_window->close_request = CONFIRMABLE_CLOSE_REQUESTED;
|
||||||
|
global_state.has_pending_closes = true;
|
||||||
|
request_tick_callback();
|
||||||
|
}
|
||||||
|
glfwSetWindowShouldClose(window, false);
|
||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
static void
|
|
||||||
application_quit_canary_close_requested(GLFWwindow *window UNUSED) {
|
|
||||||
global_state.has_pending_closes = true;
|
|
||||||
request_tick_callback();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_occlusion_callback(GLFWwindow *window, bool occluded UNUSED) {
|
window_occlusion_callback(GLFWwindow *window, bool occluded UNUSED) {
|
||||||
if (!set_callback_window(window)) return;
|
if (!set_callback_window(window)) return;
|
||||||
@@ -231,10 +227,38 @@ refresh_callback(GLFWwindow *w) {
|
|||||||
|
|
||||||
static int mods_at_last_key_or_button_event = 0;
|
static int mods_at_last_key_or_button_event = 0;
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
key_to_modifier(int key) {
|
||||||
|
switch(key) {
|
||||||
|
case GLFW_KEY_LEFT_SHIFT:
|
||||||
|
case GLFW_KEY_RIGHT_SHIFT:
|
||||||
|
return GLFW_MOD_SHIFT;
|
||||||
|
case GLFW_KEY_LEFT_CONTROL:
|
||||||
|
case GLFW_KEY_RIGHT_CONTROL:
|
||||||
|
return GLFW_MOD_CONTROL;
|
||||||
|
case GLFW_KEY_LEFT_ALT:
|
||||||
|
case GLFW_KEY_RIGHT_ALT:
|
||||||
|
return GLFW_MOD_ALT;
|
||||||
|
case GLFW_KEY_LEFT_SUPER:
|
||||||
|
case GLFW_KEY_RIGHT_SUPER:
|
||||||
|
return GLFW_MOD_SUPER;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
key_callback(GLFWwindow *w, GLFWkeyevent *ev) {
|
key_callback(GLFWwindow *w, GLFWkeyevent *ev) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
mods_at_last_key_or_button_event = ev->mods;
|
mods_at_last_key_or_button_event = ev->mods;
|
||||||
|
int key_modifier = key_to_modifier(ev->key);
|
||||||
|
if (key_modifier != -1) {
|
||||||
|
if (ev->action == GLFW_RELEASE) {
|
||||||
|
mods_at_last_key_or_button_event &= ~key_modifier;
|
||||||
|
} else {
|
||||||
|
mods_at_last_key_or_button_event |= key_modifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
global_state.callback_os_window->cursor_blink_zero_time = monotonic();
|
global_state.callback_os_window->cursor_blink_zero_time = monotonic();
|
||||||
if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST) {
|
if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST) {
|
||||||
global_state.callback_os_window->is_key_pressed[ev->key] = ev->action == GLFW_RELEASE ? false : true;
|
global_state.callback_os_window->is_key_pressed[ev->key] = ev->action == GLFW_RELEASE ? false : true;
|
||||||
@@ -287,12 +311,12 @@ cursor_pos_callback(GLFWwindow *w, double x, double y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags) {
|
scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags, int mods) {
|
||||||
if (!set_callback_window(w)) return;
|
if (!set_callback_window(w)) return;
|
||||||
show_mouse_cursor(w);
|
show_mouse_cursor(w);
|
||||||
monotonic_t now = monotonic();
|
monotonic_t now = monotonic();
|
||||||
global_state.callback_os_window->last_mouse_activity_at = now;
|
global_state.callback_os_window->last_mouse_activity_at = now;
|
||||||
if (is_window_ready_for_callbacks()) scroll_event(xoffset, yoffset, flags);
|
if (is_window_ready_for_callbacks()) scroll_event(xoffset, yoffset, flags, mods);
|
||||||
request_tick_callback();
|
request_tick_callback();
|
||||||
global_state.callback_os_window = NULL;
|
global_state.callback_os_window = NULL;
|
||||||
}
|
}
|
||||||
@@ -323,25 +347,32 @@ window_focus_callback(GLFWwindow *w, int focused) {
|
|||||||
static int
|
static int
|
||||||
drop_callback(GLFWwindow *w, const char *mime, const char *data, size_t sz) {
|
drop_callback(GLFWwindow *w, const char *mime, const char *data, size_t sz) {
|
||||||
if (!set_callback_window(w)) return 0;
|
if (!set_callback_window(w)) return 0;
|
||||||
|
#define RETURN(x) { global_state.callback_os_window = NULL; return x; }
|
||||||
if (!data) {
|
if (!data) {
|
||||||
if (strcmp(mime, "text/uri-list") == 0) return 3;
|
if (strcmp(mime, "text/uri-list") == 0) RETURN(3);
|
||||||
if (strcmp(mime, "text/plain;charset=utf-8") == 0) return 2;
|
if (strcmp(mime, "text/plain;charset=utf-8") == 0) RETURN(2);
|
||||||
if (strcmp(mime, "text/plain") == 0) return 1;
|
if (strcmp(mime, "text/plain") == 0) RETURN(1);
|
||||||
return 0;
|
RETURN(0);
|
||||||
}
|
}
|
||||||
WINDOW_CALLBACK(on_drop, "sy#", mime, data, (int)sz);
|
WINDOW_CALLBACK(on_drop, "sy#", mime, data, (Py_ssize_t)sz);
|
||||||
request_tick_callback();
|
request_tick_callback();
|
||||||
/* PyObject *s = PyTuple_New(count); */
|
RETURN(0);
|
||||||
/* if (s) { */
|
#undef RETURN
|
||||||
/* for (int i = 0; i < count; i++) PyTuple_SET_ITEM(s, i, PyUnicode_FromString(strings[i])); */
|
|
||||||
/* WINDOW_CALLBACK(on_drop, "O", s); */
|
|
||||||
/* Py_CLEAR(s); */
|
|
||||||
/* request_tick_callback(); */
|
|
||||||
/* } */
|
|
||||||
global_state.callback_os_window = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
application_close_requested_callback(int flags) {
|
||||||
|
if (flags) {
|
||||||
|
global_state.quit_request = IMPERATIVE_CLOSE_REQUESTED;
|
||||||
|
request_tick_callback();
|
||||||
|
} else {
|
||||||
|
if (global_state.quit_request == NO_CLOSE_REQUESTED) {
|
||||||
|
global_state.has_pending_closes = true;
|
||||||
|
global_state.quit_request = CONFIRMABLE_CLOSE_REQUESTED;
|
||||||
|
request_tick_callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -459,6 +490,8 @@ toggle_maximized_for_os_window(OSWindow *w) {
|
|||||||
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
static GLFWwindow *apple_preserve_common_context = NULL;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
filter_option(int key UNUSED, int mods, unsigned int native_key UNUSED, unsigned long flags) {
|
filter_option(int key UNUSED, int mods, unsigned int native_key UNUSED, unsigned long flags) {
|
||||||
if ((mods == GLFW_MOD_ALT) || (mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT))) {
|
if ((mods == GLFW_MOD_ALT) || (mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT))) {
|
||||||
@@ -468,8 +501,6 @@ filter_option(int key UNUSED, int mods, unsigned int native_key UNUSED, unsigned
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWwindow *application_quit_canary = NULL;
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
on_application_reopen(int has_visible_windows) {
|
on_application_reopen(int has_visible_windows) {
|
||||||
if (has_visible_windows) return true;
|
if (has_visible_windows) return true;
|
||||||
@@ -523,13 +554,13 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
|
|||||||
glfwWindowHint(GLFW_DEPTH_BITS, 0);
|
glfwWindowHint(GLFW_DEPTH_BITS, 0);
|
||||||
glfwWindowHint(GLFW_STENCIL_BITS, 0);
|
glfwWindowHint(GLFW_STENCIL_BITS, 0);
|
||||||
if (OPT(hide_window_decorations) & 1) glfwWindowHint(GLFW_DECORATED, false);
|
if (OPT(hide_window_decorations) & 1) glfwWindowHint(GLFW_DECORATED, false);
|
||||||
|
glfwSetApplicationCloseCallback(application_close_requested_callback);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
cocoa_set_activation_policy(OPT(macos_hide_from_tasks));
|
cocoa_set_activation_policy(OPT(macos_hide_from_tasks));
|
||||||
glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, true);
|
glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, true);
|
||||||
glfwSetApplicationShouldHandleReopen(on_application_reopen);
|
glfwSetApplicationShouldHandleReopen(on_application_reopen);
|
||||||
glfwSetApplicationWillFinishLaunching(cocoa_create_global_menu);
|
glfwSetApplicationWillFinishLaunching(cocoa_create_global_menu);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
@@ -549,15 +580,13 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
|
|||||||
// The temp window is used to get the DPI.
|
// The temp window is used to get the DPI.
|
||||||
glfwWindowHint(GLFW_VISIBLE, false);
|
glfwWindowHint(GLFW_VISIBLE, false);
|
||||||
GLFWwindow *common_context = global_state.num_os_windows ? global_state.os_windows[0].handle : NULL;
|
GLFWwindow *common_context = global_state.num_os_windows ? global_state.os_windows[0].handle : NULL;
|
||||||
#ifdef __APPLE__
|
|
||||||
if (is_first_window && !application_quit_canary) {
|
|
||||||
application_quit_canary = glfwCreateWindow(100, 200, "quit_canary", NULL, NULL);
|
|
||||||
glfwSetWindowCloseCallback(application_quit_canary, application_quit_canary_close_requested);
|
|
||||||
}
|
|
||||||
if (!common_context) common_context = application_quit_canary;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GLFWwindow *temp_window = NULL;
|
GLFWwindow *temp_window = NULL;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (!apple_preserve_common_context) {
|
||||||
|
apple_preserve_common_context = glfwCreateWindow(100, 200, "kitty", NULL, common_context);
|
||||||
|
}
|
||||||
|
if (!common_context) common_context = apple_preserve_common_context;
|
||||||
|
#endif
|
||||||
if (!global_state.is_wayland) {
|
if (!global_state.is_wayland) {
|
||||||
// On Wayland windows dont get a content scale until they receive an enterEvent anyway
|
// On Wayland windows dont get a content scale until they receive an enterEvent anyway
|
||||||
// which wont happen until the event loop ticks, so using a temp window is useless.
|
// which wont happen until the event loop ticks, so using a temp window is useless.
|
||||||
@@ -760,21 +789,6 @@ focus_os_window(OSWindow *w, bool also_raise) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
bool
|
|
||||||
application_quit_requested() {
|
|
||||||
return !application_quit_canary || glfwWindowShouldClose(application_quit_canary);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
request_application_quit() {
|
|
||||||
if (application_quit_canary) {
|
|
||||||
global_state.has_pending_closes = true;
|
|
||||||
glfwSetWindowShouldClose(application_quit_canary, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Global functions {{{
|
// Global functions {{{
|
||||||
static void
|
static void
|
||||||
error_callback(int error, const char* description) {
|
error_callback(int error, const char* description) {
|
||||||
@@ -979,12 +993,6 @@ wakeup_main_loop() {
|
|||||||
glfwPostEmptyEvent();
|
glfwPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
mark_os_window_for_close(OSWindow* w, bool yes) {
|
|
||||||
global_state.has_pending_closes = true;
|
|
||||||
glfwSetWindowShouldClose(w->handle, yes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
should_os_window_be_rendered(OSWindow* w) {
|
should_os_window_be_rendered(OSWindow* w) {
|
||||||
return (
|
return (
|
||||||
@@ -994,11 +1002,6 @@ should_os_window_be_rendered(OSWindow* w) {
|
|||||||
) ? false : true;
|
) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
should_os_window_close(OSWindow* w) {
|
|
||||||
return glfwWindowShouldClose(w->handle) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
primary_monitor_size(PYNOARG) {
|
primary_monitor_size(PYNOARG) {
|
||||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||||
@@ -1137,8 +1140,12 @@ wayland_frame_request_callback(id_type os_window_id) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
request_frame_render(OSWindow *w) {
|
request_frame_render(OSWindow *w) {
|
||||||
glfwRequestWaylandFrameEvent(w->handle, w->id, wayland_frame_request_callback);
|
// Some Wayland compositors are too fragile to handle multiple
|
||||||
w->render_state = RENDER_FRAME_REQUESTED;
|
// render frame requests, see https://github.com/kovidgoyal/kitty/issues/2329
|
||||||
|
if (w->render_state != RENDER_FRAME_REQUESTED) {
|
||||||
|
glfwRequestWaylandFrameEvent(w->handle, w->id, wayland_frame_request_callback);
|
||||||
|
w->render_state = RENDER_FRAME_REQUESTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1183,6 +1190,10 @@ run_main_loop(tick_callback_fun cb, void* cb_data) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
stop_main_loop(void) {
|
stop_main_loop(void) {
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (apple_preserve_common_context) glfwDestroyWindow(apple_preserve_common_context);
|
||||||
|
apple_preserve_common_context = NULL;
|
||||||
|
#endif
|
||||||
glfwStopMainLoop();
|
glfwStopMainLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user