Compare commits

...

577 Commits

Author SHA1 Message Date
Kovid Goyal
644ee646a2 version 0.16.0 2020-01-28 08:48:00 +05:30
Kovid Goyal
8f1ec053ef ... 2020-01-27 08:50:29 +05:30
Kovid Goyal
2e3037ce3a Wayland: Fix window titles being set to very long strings on the order of 8KB causing a crash
Fixes #1526
2020-01-27 08:49:25 +05:30
Kovid Goyal
109a856b91 Fix #2313 2020-01-26 08:00:06 +05:30
Kovid Goyal
eaec854bfb ... 2020-01-25 11:51:17 +05:30
Kovid Goyal
2c6cc6f047 Remove unused slot 2020-01-25 11:22:22 +05:30
Kovid Goyal
f32ae10339 Use a global cache instead of a per window cache for grid size calculation 2020-01-25 11:21:05 +05:30
Kovid Goyal
c46317f96f Use typed layout data 2020-01-25 11:11:55 +05:30
Kovid Goyal
a67e4e550e Merge branch 'issue2310' of https://github.com/ctrlcctrlv/kitty 2020-01-24 13:43:15 +05:30
Fredrick Brennan
65a7b19f40 Make each OS window have its own framebuffer
This commit fixes graphics rendering when more than one OS window is
open, all OS windows are semi-transparent, and multiple windows contain
graphics.

This commit closes #2310.
2020-01-24 16:06:57 +08:00
Kovid Goyal
1b5daf930a Make the comment explaining wayland polling more detailed 2020-01-23 15:08:54 +05:30
Kovid Goyal
748ca81d4b Wayland: Fix a freeze in rare circumstances when having multiple OS Windows
Fixes #2307
Fixes #1722
2020-01-23 15:07:22 +05:30
Kovid Goyal
0ea7d24ba4 Fix incorrect offset when rendering images and there are +z-index, -z-index and --z-index images 2020-01-21 08:09:04 +05:30
Kovid Goyal
6c9861cb76 Fix incorrect blending of default bg color when using draw_cells_interleaved_premult with images but no below images 2020-01-21 07:59:44 +05:30
Kovid Goyal
a1125b5cc8 Move draw_bg multiplication into vertex shader 2020-01-21 07:58:34 +05:30
Kovid Goyal
b4e189d2bf Merge branch 'simplify' of https://github.com/Luflosi/kitty 2020-01-21 06:54:28 +05:30
Luflosi
dbc763fca0 Remove useless code from shader 2020-01-21 00:28:55 +01:00
Kovid Goyal
4c03ffeae2 Merge branch 'patch-1' of https://github.com/ctrlcctrlv/kitty 2020-01-18 15:11:03 +05:30
Fredrick Brennan
2719ac7d01 Add :pull:2248 to changelog.rst
It was missing
2020-01-18 17:34:27 +08:00
Kovid Goyal
219b81b5ee typo 2020-01-18 08:19:42 +05:30
Kovid Goyal
8e1443360f Merge branch 'force_ltr' of https://github.com/ctrlcctrlv/kitty 2020-01-18 08:07:56 +05:30
Kovid Goyal
d55242aa82 Merge branch 'master' of https://github.com/mfilenko/kitty 2020-01-17 21:40:10 +05:30
Max Filenko
ba531969ec List layouts in their default order 2020-01-17 16:28:44 +01:00
Max Filenko
c12e7587cb Document default configuration 2020-01-17 16:28:30 +01:00
Kovid Goyal
3aac0860a2 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2020-01-17 20:28:26 +05:30
Luflosi
e4fd12001c Cocoa: Add fully dynamic loading of Vulkan loader
From upstream: 7da87aaae7.
2020-01-17 14:18:28 +01:00
Luflosi
3581ffe04b Cocoa: Select Vulkan surface extension at runtime
From upstream: 15d91801b7.
2020-01-17 14:18:21 +01:00
Luflosi
f6901e4a3d Cocoa: Add support for VK_EXT_metal_surface
From upstream: c5cb4a253a.
2020-01-17 14:18:05 +01:00
Fredrick Brennan
5a2cc4578e force_ltr also makes FriBidi usable
Add above fact to documentation.
2020-01-17 17:57:26 +08:00
Fredrick Brennan
6b5acc4d3d Add force_ltr
Close #2252
2020-01-17 16:22:40 +08:00
Kovid Goyal
43326c9bd0 Fix URL detection not working for urls of the form scheme:///url
Fixes #2292
2020-01-17 07:49:01 +05:30
Kovid Goyal
96f3253e6d goto_tab now maps numbers larger than the last tab to the last tab
Fixes #2291
2020-01-16 20:17:17 +05:30
Kovid Goyal
f5090c951a Merge branch 'with_open' of https://github.com/Luflosi/kitty 2020-01-16 19:41:55 +05:30
Luflosi
edacdc5e25 Use python context manager to open file 2020-01-16 14:11:54 +01:00
Kovid Goyal
c67661af61 oops 2020-01-15 21:39:13 +05:30
Kovid Goyal
5e60329adf Changelog entry to titlebar-only 2020-01-15 21:37:20 +05:30
Kovid Goyal
6b4f8408de Merge branch 'macos_hide_titlebar' of https://github.com/Luflosi/kitty 2020-01-15 21:36:03 +05:30
Luflosi
ea1ef709c6 macOS: Allow hiding the titlebar only instead of all window decorations
Thanks to @ntruong for writing cb8279ec54 and  6807411365, the code was very helpful.
2020-01-15 16:35:36 +01:00
Kovid Goyal
bbf247c5c0 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2020-01-15 19:32:12 +05:30
Kovid Goyal
8243fd505f Make mark colors per window 2020-01-15 18:42:37 +05:30
Luflosi
ed9f9db1b0 X11: Fix parent window handle initialization
From upstream: 9372ba95fa.
2020-01-15 13:19:33 +01:00
Luflosi
74bed658e1 X11: Fix no window position events during resize
From upstream: fe57e3c292.
2020-01-15 13:19:32 +01:00
Kovid Goyal
2f7bdc274d Fix failing test 2020-01-15 11:48:13 +05:30
Kovid Goyal
1347ff27d9 Changelog entry for triple click change 2020-01-15 11:46:50 +05:30
Kovid Goyal
5bf4d520f5 Merge branch 'master' of https://github.com/copy/kitty 2020-01-15 11:43:20 +05:30
Kovid Goyal
cf8d665eb7 Allow having more than one full height window in the :code:tall layout
Fixes #2276
2020-01-15 11:28:58 +05:30
Fabian
b2eee6df5c Multiline triple-click selections: Don't ignore leading spaces in first line 2020-01-14 21:04:59 -06:00
Kovid Goyal
e8121b39ec Add newer layout classes to tests 2020-01-15 08:14:45 +05:30
Kovid Goyal
5359abab76 next version should be 0.16.0 2020-01-15 08:05:45 +05:30
Kovid Goyal
01644ac3f0 Changelog entry for marks 2020-01-15 08:05:12 +05:30
Kovid Goyal
8fbf552494 Allow opening new tabs/windows before the current tab/window as well as after it with the :option:launch --location option. 2020-01-15 08:02:05 +05:30
Kovid Goyal
9c3390c5e6 Allow specifying a marker when launching windows 2020-01-15 07:22:32 +05:30
Kovid Goyal
24d45b99e3 typo 2020-01-15 07:13:32 +05:30
Kovid Goyal
936f2186cc Allow scrolling to marks 2020-01-15 07:11:34 +05:30
Kovid Goyal
c68b302fa2 Merge branch 'wayland' of https://github.com/kennylevinsen/kitty 2020-01-15 06:51:24 +05:30
Kenny Levinsen
ca7cab1a2d wayland: Consistently use errno for errors 2020-01-14 20:06:13 +01:00
Kenny Levinsen
083b294659 wayland: Simplify dispatch_pending error handling
wl_display_dispatch_pending does not return EAGAIN, and always sets an
error when it fails. This allows us to handle errors in a simpler
manner.
2020-01-14 20:04:23 +01:00
Kenny Levinsen
bc24716476 wayland: errno does not have to be cleared
As long as errno is only read on error from an errno-setting function,
then there is no need to reset errno between uses.
2020-01-14 20:04:23 +01:00
Kenny Levinsen
4acab65016 wayland: Only cancel display read after prepare success
The display reader count only increments when wl_display_prepare_read
succeeds.  Calling wl_display_cancel_read when wl_display_prepare_read
has not succeeded results in a negative reader count, which does not
have well-defined behavior.
2020-01-14 20:00:47 +01:00
Kenny Levinsen
f6b03f106c wayland: Cancel display read before abortOnFatalError
Calling wl_display_cancel_read immediately ensures that other readers
waiting on us will have a chance to wake up and discover the error in a
timely manner.
2020-01-14 19:59:02 +01:00
Kovid Goyal
8f9bbeabd7 Fix reference to --debug-config 2020-01-14 19:50:18 +05:30
Kovid Goyal
ac72ac7af2 Wayland: On dispatch error cancel read before running fatal error handlers
Might help #1722
2020-01-14 19:48:28 +05:30
Kovid Goyal
68e00bc8e1 Proper fix for #2270
Fixes #2270
2020-01-14 18:50:06 +05:30
Kovid Goyal
922d6b3b32 Fix #2270 2020-01-14 17:20:35 +05:30
Kovid Goyal
4dde98305e Allow setting markers using remote control 2020-01-14 15:06:52 +05:30
Kovid Goyal
3593189a75 Add a link to the marks docs 2020-01-14 13:45:37 +05:30
Kovid Goyal
4f135be86c Allow creating markers dynamically 2020-01-13 20:05:50 +05:30
Kovid Goyal
605b32f78a Merge branch 'dryer' of https://github.com/Luflosi/kitty 2020-01-13 19:42:56 +05:30
Luflosi
476a8b1429 DRYer
Inspired by e0c66ea5ba.
2020-01-13 14:35:17 +01:00
Kovid Goyal
da9165aebf More marker docs 2020-01-13 12:54:29 +05:30
Kovid Goyal
455a1e9532 Basic docs for marking 2020-01-13 12:38:58 +05:30
Kovid Goyal
f12031e284 Make the run-program example a little fancier 2020-01-13 12:16:43 +05:30
Kovid Goyal
df551bc992 Change marker 1 color 2020-01-13 11:58:18 +05:30
Kovid Goyal
35fb702833 Use only a single marker function
Multipe colors/expressions can instead be combined at definition time
2020-01-13 11:57:19 +05:30
Kovid Goyal
072cd29e3c Make add_marker easier to use with combine 2020-01-13 09:56:39 +05:30
Kovid Goyal
624dd78460 Actually apply mark colors when rendering 2020-01-13 09:51:03 +05:30
Kovid Goyal
51c4737a29 Test function marking 2020-01-13 06:50:37 +05:30
Kovid Goyal
d63ea11cac Marking now works 2020-01-13 06:50:37 +05:30
Kovid Goyal
3d307794be Function to get marks for testing 2020-01-13 06:50:36 +05:30
Kovid Goyal
d32a05925f Code to add and remove markers using maps 2020-01-13 06:50:36 +05:30
Kovid Goyal
04006ea81e Wrapper functions to handle passing matching values to C code 2020-01-13 06:50:36 +05:30
Kovid Goyal
1723616968 Code to apply match colors based on match results 2020-01-13 06:50:36 +05:30
Kovid Goyal
23bc2171c9 Avoid a double call for mark functions 2020-01-13 06:50:36 +05:30
Kovid Goyal
0b3602f764 Code to add markers to Screen 2020-01-13 06:50:36 +05:30
Kovid Goyal
0e448347cd Fix #2279 2020-01-13 06:50:14 +05:30
Kovid Goyal
e0c66ea5ba DRYer 2020-01-12 21:42:12 +05:30
Kovid Goyal
268de9a9d5 Merge branch 'add_CIRCUMFLEX_to_control_codes' of https://github.com/Luflosi/kitty 2020-01-12 21:03:27 +05:30
Luflosi
74eb523178 Add GLFW_KEY_CIRCUMFLEX to control_codes
See https://github.com/kovidgoyal/kitty/issues/1990.
2020-01-12 16:27:40 +01:00
Kovid Goyal
8c540d5a46 Fix #2277 2020-01-12 20:00:08 +05:30
Kovid Goyal
2045055ae3 Use actual color value comparison when detecting default background color
This is very slightly more GPU intensive but means that even if
an application explicitly sets the color to be the same as the default
color, it will be transparent.
2020-01-12 18:14:03 +05:30
Kovid Goyal
d8ed135b46 Clean up rendering of cell backgrounds 2020-01-12 13:20:23 +05:30
Kovid Goyal
3a4ba7e834 Remove un-needed variable 2020-01-12 10:55:14 +05:30
Kovid Goyal
fab57fbdf1 Micro-optimization 2020-01-12 10:53:27 +05:30
Kovid Goyal
76a93b6cd6 DRYer 2020-01-12 10:52:42 +05:30
Kovid Goyal
f44c3a4606 Forgot to update comment describing render pipeline 2020-01-12 10:26:25 +05:30
Kovid Goyal
714bee7f45 Only use an extra draw call for the background when drawing interleaved cells if it is actually required 2020-01-12 09:37:16 +05:30
Kovid Goyal
91673642b3 icat: Allow easily specifying z-index values below background threshold 2020-01-12 09:36:11 +05:30
Kovid Goyal
fee08d746c Merge branch 'replace_exception_with_alias' of https://github.com/Luflosi/kitty 2020-01-11 21:21:52 +05:30
Luflosi
527ff0238a Replace all instances of EnvironmentError with OSError
According to the text just above https://docs.python.org/3/library/exceptions.html#EnvironmentError, `EnvironmentError` has been an alias of `OSError` since Python 3.3. Replacing it makes the code more consistent since `OSError` is used in other places in the code too.
2020-01-11 16:47:36 +01:00
Kovid Goyal
789d649b5c defaultbg should be a local variable 2020-01-11 16:59:50 +05:30
Fredrick Brennan
8020657d8c Allow drawing images below cells w/background 2020-01-11 16:56:59 +05:30
Kovid Goyal
a15d3ff12d ... 2020-01-10 10:19:02 +05:30
Kovid Goyal
fbce95aeda Add an example for open file hints 2020-01-10 10:18:18 +05:30
Kovid Goyal
9bc1b5a2d9 hints kitten: Allow pressing :sc:goto_file_line to quickly open the selected file at the selected line in vim
Fixes #2268
2020-01-10 10:01:03 +05:30
Kovid Goyal
6a8b7bf92f Merge branch 'with_suppress' of https://github.com/Luflosi/kitty 2020-01-09 20:58:37 +05:30
Luflosi
48728bdfdc Use "with suppress()" to suppress a python exception 2020-01-09 16:21:56 +01:00
Kovid Goyal
b6416cf8a9 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2020-01-09 06:58:30 +05:30
Luflosi
053de5763a X11: Fix BadMatch focusing a window on non-EWMH WM
From upstream: aa5e313561.
2020-01-08 19:50:17 +01:00
Kovid Goyal
fdb915d0c8 Merge branch 'zindex' of https://github.com/ctrlcctrlv/kitty 2020-01-08 18:20:34 +05:30
Fredrick Brennan
c2769c9aed Add --z-index to icat kitten
Meow.
2020-01-08 20:08:01 +08:00
Kovid Goyal
57deb19d0b typo 2020-01-07 10:45:05 +05:30
Kovid Goyal
321771b150 Merge branch 'resize-by-increments' of https://github.com/aes/kitty 2020-01-07 10:44:55 +05:30
Kovid Goyal
61dd2011f5 Dont rely on fontconfig to get postscript names 2020-01-07 09:30:41 +05:30
Kovid Goyal
8a5f189213 Ignore invalid font features when parsing config 2020-01-07 09:20:04 +05:30
Kovid Goyal
14560b008a Clean up font features merge 2020-01-07 08:54:32 +05:30
Kovid Goyal
db85e07d41 Merge branch 'master' of https://github.com/ctrlcctrlv/kitty 2020-01-07 07:18:31 +05:30
Kovid Goyal
07c838fe24 Merge branch 'round_printed_timeout' of https://github.com/Luflosi/kitty 2020-01-06 07:14:53 +05:30
Luflosi
1583b1b0c6 Print warning message timeout rounded to two digits after the dot
The timeout is 0.25 seconds. Printing 0.25 instead of 0.250000 looks a lot nicer and a resolution of 10 milliseconds should be enough for this warning message anyways.
2020-01-05 16:10:10 +01:00
Fredrick Brennan
d250555cd0 Make font_feature_settings respect disable_ligatures 2020-01-04 20:11:34 +08:00
Fredrick Brennan
dbd0dab154 Revert addition of ffs_set to Font struct
It was from an earlier stage of development and is not needed
2020-01-04 15:37:05 +08:00
Fredrick Brennan
b479ea410d Prevent leaks
Thanks @martinetd
2020-01-04 15:34:47 +08:00
Fredrick Brennan
1db613e95b Add font_feature_settings
Close #2247
2020-01-04 14:36:20 +08:00
Kovid Goyal
70071fe1f6 Merge branch 'simplify' of https://github.com/Luflosi/kitty 2020-01-03 07:46:58 +05:30
Luflosi
58688dda38 Remove duplicate code
The hints, once set with `glfwWindowHint()`, retain their values until changed again. This means, that the `GLFW_DECORATED` hint only needs to be set once, even on non-macOS.
2020-01-03 03:01:53 +01:00
Kovid Goyal
756d65c41e Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2020-01-03 07:18:25 +05:30
Luflosi
b9a08eacb0 X11: Cleanup
From upstream: 8149a5fc00.
2020-01-03 02:37:19 +01:00
Kovid Goyal
b653711446 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2020-01-03 06:48:30 +05:30
Luflosi
e725c647ef Cocoa: Only create per-monitor display link once
From upstream: b4a8eb9b19.
2020-01-02 18:05:38 +01:00
Kovid Goyal
003f77b257 Merge branch 'add_macos_help_menu_item' of https://github.com/Luflosi/kitty 2019-12-29 22:03:08 +05:30
Luflosi
10b578e6d2 Add help menu to macOS menu bar
Most macOS Apps have a Help menu as the last menu item in the menu bar. They usually have a menu item with the keyboard shortcut <kbd>⌘</kbd>+<kbd>?</kbd>, which shows some kind of help or documentation. I named the menu item "Visit kitty website" and let it open the kitty website as documentation.
macOS also magically adds a search feature to the help menu.
2019-12-29 17:24:12 +01:00
Kovid Goyal
151c6c2c70 Merge branch 'always_show_menu_item' of https://github.com/Luflosi/kitty 2019-12-29 20:53:22 +05:30
Luflosi
53e6de9bd9 Always show the macOS New OS Window menu item
When there is no keyboard shortcut for a new OS window, the macOS menu item should still exist, it should just not have a keyboard shortcut.
2019-12-29 15:27:52 +01:00
Kovid Goyal
66a455a079 Merge branch 'simplify' of https://github.com/Luflosi/kitty 2019-12-29 19:45:07 +05:30
Luflosi
f8855410e0 Simplify some code in kitty/cocoa_window.m
`addItemWithTitle:` can be used instead of `initWithTitle:`. It returns an `NSMenuItem`, which removes the need for allocating an `NSMenuItem` manually and releasing it again.
2019-12-29 14:33:19 +01:00
Kovid Goyal
93e8074325 ... 2019-12-28 08:49:53 +05:30
Kovid Goyal
296f512bfb Forgot you cant use sizeof on arrays passed as function parameters 2019-12-28 08:44:32 +05:30
Kovid Goyal
c8f20d0edf Ensure key name is null terminated 2019-12-28 08:33:13 +05:30
Kovid Goyal
286f3630d7 Merge branch 'macos_fix_keyboard_shortcut_encoding' of https://github.com/Luflosi/kitty 2019-12-28 08:26:03 +05:30
Luflosi
38423505b1 Remove numpad keys from macOS keyboard shortcuts
See previous commit message for the reason.
2019-12-27 15:12:26 +01:00
Luflosi
9a3c621eb6 Fix macOS keyboard shortcut encoding
`glfwGetCocoaKeyEquivalent()` in `glfw/cocoa_window.m` expects the returned characters to be of type `unichar`, which won't work for all unicode characters because it is defined as `unsigned short` according to https://developer.apple.com/documentation/foundation/unichar?language=objc, which is only guaranteed to be at least 16 bits in size. The code calling this function also expects the encoding to be UTF-16.
When I added the various keys in https://github.com/kovidgoyal/kitty/pull/1928, I missed these facts. This means, that `glfwGetCocoaKeyEquivalent()` will behave unexpectedly when called with any of the new-ish keys. Luckily this function is currently only used for determining the macOS shortcut for `new_os_window` but I plan on using it more in the future.
Some of the constants, e.g. `NSBackspaceCharacter` are UTF-16 constants, so we can't just use UTF-8 everywhere.
I fixed the problem by using either UTF-8 characters packed into a `uint32_t` or UTF-16 characters in a `unichar` and then converting them to a UTF-8 encoded char string.

`NSEventModifierFlagNumericPad` isn't guaranteed to fit in a `unichar`, which made this undefined behaviour. It also didn't work. I tried to make it work using `NSEventModifierFlagNumericPad` as a modifier instead, as can be seen in this commit, but couldn't get it to work either because the constants used are native key codes and not unicode characters. Therefore the numpad keys will be removed in the next commit.
2019-12-27 12:42:51 +01:00
Kovid Goyal
bcf847fe98 ... 2019-12-27 15:26:31 +05:30
Kovid Goyal
ee7a5eef99 Have read_shell_environment() not fail when no shell is present 2019-12-27 12:25:01 +05:30
Kovid Goyal
7bed66a458 Ensure ans is set in read_shell_environment
Fixes #2232
2019-12-27 12:20:06 +05:30
Kovid Goyal
b26229c44e Merge branch 'remove_release' of https://github.com/Luflosi/kitty 2019-12-26 08:48:20 +05:30
Luflosi
c497c0f96a Remove call to release on an automatically memory managed object
This call even reliably caused a crash for code I was trying to develop.
2019-12-25 20:29:07 +01:00
Kovid Goyal
6df64613f2 Merge branch 'replace_void_pointer' of https://github.com/Luflosi/kitty 2019-12-25 16:35:08 +05:30
Luflosi
46dd648380 Use the correct pointer type instead of void* 2019-12-25 11:51:40 +01:00
Kovid Goyal
4cd5de78c7 Merge branch 'generate_key_table' of https://github.com/Luflosi/kitty 2019-12-25 08:34:27 +05:30
Luflosi
32fa46d6eb Regenerate key table
Since `CIRCUMFLEX` and `^` were removed from `UN_SHIFTED_PRINTABLE` in b2d428618c by 3a2a16f54c and b5229ec73c, `generate_key_table()` wasn't yet run again.
2019-12-25 02:16:37 +01:00
Kovid Goyal
902c2f6c88 Merge branch 'update_comment' of https://github.com/Luflosi/kitty 2019-12-24 19:31:37 +05:30
Luflosi
2a5196873a Update comment to remove legacy way of starting kitty
Since 9135387cfa kitty should not be started with `python3 .` anymore.
2019-12-24 14:22:37 +01:00
Kovid Goyal
d2067141d3 Fix #2226 2019-12-24 17:10:33 +05:30
Kovid Goyal
b5229ec73c oops 2019-12-23 10:19:02 +05:30
Kovid Goyal
3a2a16f54c Merge branch 'add_circumflex_key' of https://github.com/Luflosi/kitty 2019-12-23 10:08:25 +05:30
Luflosi
b2d428618c Add circumflex (^) key 2019-12-22 18:41:07 +01:00
Kovid Goyal
97af84a063 version 0.15.1 2019-12-21 14:20:28 +05:30
Kovid Goyal
18faee6250 Merge branch 'glad2-regen' of https://github.com/Dav1dde/kitty 2019-12-20 20:19:54 +05:30
David Herberth
fd90a3ddc3 regenerates glad to fix missing APIENTRY 2019-12-20 15:04:23 +01:00
Kovid Goyal
a08931d84d Fix window not being rendered for the first time until some input has been received from child process
Fixes #2216
2019-12-20 08:46:50 +05:30
Kovid Goyal
2f0b6e24c9 Use pre-multiplied alpha when clearing windows
Apparently most systems expect this. See https://github.com/glfw/glfw/issues/1538
2019-12-20 08:16:10 +05:30
Kovid Goyal
33c5fc0fb6 typo 2019-12-20 07:59:55 +05:30
Kovid Goyal
71adb2dcf8 Merge branch 'new_os_window_key_macos' of https://github.com/Luflosi/kitty 2019-12-20 07:59:08 +05:30
Luflosi
1ae324691d Change keyboard shortcut selection algorithm for new_os_window on macOS
On macOS the keyboard shortcuts are visible in the menu bar. When the keyboard shortcut is used, the corresponding menu bar item flashes to indicate which action was just executed.
kitty allows defining multiple keyboard shortcuts for the same action but macOS allows only one, so kitty needs to decide which one should be handled by macOS. Currently it chooses the first keyboard shortcut with only the command key as a modifier key or the first shortcut when there are no shortcuts with only the command key as a modifier.
When a user tries to set their own keyboard shortcut (and doesn't use `clear_all_shortcuts yes`), this won't change the shortcut displayed in the menu bar since the first (default) shortcut with the command key is <kbd>⌘</kbd>+<kbd>n</kbd>.
I think simply choosing the last defined keyboard shortcut is better. This will even allow the user to specify modifier keys other than the command key while still changing the shortcut in the menu bar. This change will not change the default behaviour because all the macOS specific keyboard shortcuts are defined after the non-macOS specific ones.
2019-12-19 22:15:41 +01:00
Kovid Goyal
689d059517 Fix lines at the edge of the window at certain windows sizes when drawing images on a transparent window
Fixes #2079
Fixes #2214
2019-12-19 20:41:31 +05:30
Kovid Goyal
18f0ab9e02 Merge branch 'fix_typo' of https://github.com/Luflosi/kitty 2019-12-19 20:01:12 +05:30
Luflosi
088ab5f137 Fix typo 2019-12-19 13:40:08 +01:00
Kovid Goyal
3dd83975ba Dont cast double to monotonic_t for literals 2019-12-19 17:33:12 +05:30
Kovid Goyal
a796a6cbef Use exponential notation in monotonic.h 2019-12-19 17:22:33 +05:30
Kovid Goyal
4766d7de82 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-19 17:19:42 +05:30
Luflosi
4a3686c16c X11: Cleanup
From upstream: 73a8ebb691.
2019-12-19 12:38:56 +01:00
Kovid Goyal
b49105495c Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-19 17:07:42 +05:30
Luflosi
ca2eda2c5b X11: Cleanup
From upstream: 4e70c95aa3.
2019-12-19 12:35:44 +01:00
Kovid Goyal
4fc7c4aafc Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-19 17:05:10 +05:30
Luflosi
0981828493 X11: Fix updating GLFW_FLOATING on a hidden window
From upstream: 9db156421f.
2019-12-19 12:31:31 +01:00
Kovid Goyal
6bc4f18a59 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-19 16:59:26 +05:30
Luflosi
79532a315c X11: Fix invalid read when clearing GLFW_FLOATING
From upstream: 0b652a44d2.
2019-12-19 12:27:36 +01:00
Kovid Goyal
7472a992ed Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-19 16:56:48 +05:30
Luflosi
e40616a0db X11: Fix missing checks for EWMH attention atoms
From upstream: 9b6d68ec70.
2019-12-19 12:25:09 +01:00
Kovid Goyal
dd8b97a86c Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-19 16:53:38 +05:30
Luflosi
5eff3897de X11: Fix maximization of hidden windows
From upstream: 4837b78ffe.
2019-12-19 12:20:58 +01:00
Kovid Goyal
530cf2eb14 monotonic.h no longer depends on time.h 2019-12-19 16:48:35 +05:30
Kovid Goyal
2baa34beb8 Move a couple of functions to where they are actually needed 2019-12-19 16:43:51 +05:30
Kovid Goyal
87e2f7f86d Missed a couple of macOS timer calls 2019-12-19 16:34:47 +05:30
Kovid Goyal
e142083d53 Remove unused code
Strip out the GLFW timer code, since we use our own kitty based
monotonic clock.
2019-12-19 16:27:25 +05:30
Kovid Goyal
2e850a0d0d Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-19 07:56:04 +05:30
Luflosi
aec9c31bca Formatting
From upstream: 506a6aafde.
2019-12-18 18:34:55 +01:00
Kovid Goyal
598a147500 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-18 22:51:17 +05:30
Luflosi
ba201c4c92 Add curly braces
From upstream: 9486ec0c02.

The upstream commit mainly changes some cmake stuff, which we don't use and only really adds curly braces to `egl_context.c` (and changes some formatting).
2019-12-18 18:12:48 +01:00
Kovid Goyal
5bc7cfaa43 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-18 20:33:44 +05:30
Luflosi
2804e1ff81 Cocoa: Update outdated comment
From upstream: b3544ca43e.
2019-12-18 15:41:31 +01:00
Kovid Goyal
ae27d36902 Fix previous merge 2019-12-18 18:42:59 +05:30
Kovid Goyal
08182fbe4d Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-12-18 18:36:31 +05:30
Luflosi
778474f436 Wayland: Unset the cursor shape on border exit
From upstream: ef6189f348.
2019-12-18 14:01:29 +01:00
Kovid Goyal
c6698ce305 Merge branch 'comment' of https://github.com/Luflosi/kitty 2019-12-18 18:15:30 +05:30
Luflosi
21bc215313 Make comment more accurate
Since all the time values use `monotonic_t` now, `maximum_wait` is no longer measured in seconds. Instead of replacing seconds with nanoseconds, I removed it because the definition of `monotonic_t` is supposed to be changed easily, in which case this comment would not be accurate again.
2019-12-18 12:54:14 +01:00
Kovid Goyal
88a9cc42d2 Merge branch 'fix-panel' of https://github.com/natnat-mc/kitty 2019-12-18 07:32:25 +05:30
Kovid Goyal
28f33a67cf Merge branch 'fix_oserror' of https://github.com/Luflosi/kitty 2019-12-18 07:30:37 +05:30
Nathan DECHER
6742fabfba fix kitty +kitten panel -c <config> resulting in no config at all 2019-12-18 00:33:40 +01:00
Luflosi
b3806f4533 Fix OSError when failing to create config directory on read-only file system
When calling the completion code, kitty tries to access the config directory and create it if it does not exist. If kitty has no permission to create it, a temporary directory will be created instead. This will fail on a read-only file system because that raises an `OSError` and not a `PermissionError`.
In practice this happens when building kitty on macOS Catalina using Nix because `HOME` is set to `/homeless-shelter` for purity and `/` is a read-only filesystem.
2019-12-17 23:42:31 +01:00
Kovid Goyal
6d5fb4ccc6 Fix docs build warning 2019-12-17 20:44:32 +05:30
Kovid Goyal
2487f18f24 Add a new option active_tab_title_template to specify a different template for active tab titles
Fixes #2198
2019-12-17 20:39:46 +05:30
Kovid Goyal
f59afff1d1 Add a new option tab_bar_background to specify a different color for the tab bar
Fixes #2198
2019-12-17 20:08:33 +05:30
Kovid Goyal
b92f95b092 NSGL: Fix disabling of Retina resolution
From upstream: fa60269245
2019-12-15 20:54:21 +05:30
Kovid Goyal
d68ae01448 Make the active window history available when doing kitty @ ls
Fixes #2194
2019-12-13 18:17:13 +05:30
Kovid Goyal
87eda834d3 Use a token for github 2019-12-12 10:05:11 +05:30
Luflosi
c28ff5259a Finish implementing resize by increment 2019-12-09 08:38:41 +01:00
Anders Eurenius
4619259e26 Implement resize by increment 2019-12-09 08:33:32 +01:00
Kovid Goyal
7bf0afa621 Fix #2187 2019-12-08 22:37:47 +05:30
Kovid Goyal
e3e02c7271 Fix #2180 2019-12-01 22:34:56 +05:30
Kovid Goyal
24e17cb7d8 Fix background_opacity incorrectly applying to selected text and reverse video text
Fixes #2177
2019-12-01 15:14:15 +05:30
Kovid Goyal
769998adca Document valid values for pointer_shape_when_grabbed 2019-12-01 08:22:21 +05:30
Kovid Goyal
9b5d88e92d Fix choose item mapping 2019-11-30 17:18:02 +05:30
Kovid Goyal
6d7bebee3a Merge branch 'master' of https://github.com/l-yc/kitty 2019-11-30 16:58:28 +05:30
lyc
1c38654321 Fixed bug in loading libcanberra when falling back on alternative library names 2019-11-30 14:36:22 +08:00
Kovid Goyal
da7a78691f Merge branch 'simplify' of https://github.com/Luflosi/kitty 2019-11-29 09:21:32 +05:30
Luflosi
1eaf7083ef Simplify expression 2019-11-28 23:38:42 +01:00
Kovid Goyal
79a6fcdc5c Oops 2019-11-28 10:12:21 +05:30
Kovid Goyal
90bcbbf426 No need to add index to titles when using hits kitten to choose tab/os_window 2019-11-28 10:11:14 +05:30
Kovid Goyal
41049e2a40 Avoid traceback when cancelling tab selection 2019-11-28 09:42:55 +05:30
Kovid Goyal
c9b8510e9c Also use ascending order for os window selection 2019-11-28 09:23:08 +05:30
Kovid Goyal
d854fc1cd0 Better numbering when asking for tab to detach window to
Fixes #2174
2019-11-28 09:20:38 +05:30
Kovid Goyal
5f7bcae072 hints kitten: Add an option --ascending to control if the hints numbers increase or decrease from top to bottom 2019-11-28 09:20:02 +05:30
Kovid Goyal
652eec3033 Fix a crash/incorrect rendering when detaching a window in some circumstances
Fixes #2173

Ensure all cell related GPU data is resent
2019-11-28 09:01:40 +05:30
Kovid Goyal
a9928ec98a Merge branch 'format' of https://github.com/Luflosi/kitty 2019-11-28 07:24:06 +05:30
Luflosi
e1dfb608ca Format code in kitty/cocoa_window.m a little 2019-11-27 19:56:30 +01:00
Kovid Goyal
2cee3a8809 Better fix for getting clock_gettime() from time.h
Fixes #2169
2019-11-27 22:20:55 +05:30
Kovid Goyal
804f72b31a Get monotonic.h to build on older linux distros 2019-11-27 09:55:00 +05:30
Kovid Goyal
e106dcc83b Dont use -Wfloat-conversion on old compilers 2019-11-27 09:27:23 +05:30
Kovid Goyal
9347be639b version 0.15.0 2019-11-27 09:23:01 +05:30
Kovid Goyal
ffc0c42a63 Merge branch 'faq-font-clarification' of https://github.com/ricci/kitty 2019-11-27 07:31:51 +05:30
Robert Ricci
f5e855b3ad Direct user to rebuild fc-cache in font FAQ
The configuration file that's suggested to force a font to
show up as monospace is very helpful, but it appears you may
need to force fontconfig to rebuild the cache in order for the
change to take effect.
2019-11-26 12:02:23 -07:00
Kovid Goyal
9af4dc4bff Merge branch 'redirect' of https://github.com/Luflosi/kitty 2019-11-26 22:13:51 +05:30
Luflosi
6f6180c34a Change URL to avoid redirect
Since `https://sw.kovidgoyal.net/kitty` redirects to `https://sw.kovidgoyal.net/kitty/`, it would be better to directly use the second URL.
2019-11-26 17:23:21 +01:00
Kovid Goyal
6ddd751713 Merge branch 'simplify' of https://github.com/Luflosi/kitty 2019-11-26 21:09:40 +05:30
Luflosi
2c72b06012 Simplify conditions 2019-11-26 16:06:16 +01:00
Kovid Goyal
88854c1aa4 Merge branch 'fix_stdin_source' of https://github.com/miseran/kitty 2019-11-26 06:47:21 +05:30
Reto Schnyder
5ad704469f Fix condition in stdin selection for launch 2019-11-25 20:10:18 +01:00
Kovid Goyal
c140e17a6f Merge branch 'undo_commenting_out' of https://github.com/Luflosi/kitty 2019-11-24 18:08:14 +05:30
Luflosi
4fc733a9c8 Comment commented out code back in
This piece of code is not run when the `GLFW_COCOA_MENUBAR` init hint is set to `0`, which kitty does.
This reduces the difference to GLFW upstream a little.
2019-11-24 13:29:06 +01:00
Kovid Goyal
c5c59e4c55 Merge branch 'return_type' of https://github.com/Luflosi/kitty 2019-11-24 17:56:26 +05:30
Luflosi
e0edef6719 Change return type of two functions
`on_application_reopen()` and `intercept_cocoa_fullscreen()` both only have two possible return values and can therefore have a return type of `bool`.
2019-11-24 13:06:46 +01:00
Kovid Goyal
0f46ce49e2 Merge branch 'create_menu_bar_in_callback' of https://github.com/Luflosi/kitty 2019-11-24 13:27:35 +05:30
Luflosi
f9fd39b8c1 Create macOS menu bar where GLFW creates it
GLFW creates the menu bar in the applicationWillFinishLaunching method, while kitty creates it in `create_os_window()`. This patch changes the behaviour to match GLFW.
In practice, without this change, there can be a short time where the menu bar is not fully populated.
2019-11-24 08:43:01 +01:00
Kovid Goyal
bd75157428 macOS: Disable mouse hiding by default as getting it to work robustly on Cocoa is too much effort
See #2158
2019-11-24 11:29:23 +05:30
Kovid Goyal
f987f3ba77 Merge branch 'remove_obsolete_comment' of https://github.com/Luflosi/kitty 2019-11-24 08:09:14 +05:30
Luflosi
1c16806efd Remove obsolete comment
In bef9490fa8, `unjam_event_loop()` was removed but not the corresponding comment.
2019-11-23 17:51:38 +01:00
Kovid Goyal
29155fef23 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-11-23 18:59:07 +05:30
Luflosi
c05cbed5b2 Reduce difference to GLFW upstream 2019-11-23 13:19:06 +01:00
Kovid Goyal
4f85d4db71 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-11-22 20:16:22 +05:30
Luflosi
468468ab9f Wayland: Don’t update cursor position in the frame
From upstream: a80788c17f.
2019-11-22 12:38:56 +01:00
Kovid Goyal
1b4a6da577 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-11-22 07:11:14 +05:30
Luflosi
aed7a197c7 Wayland: Don’t reload the cursor on every pointer motion
From upstream: a9f674e719.
2019-11-22 02:35:14 +01:00
Kovid Goyal
c257b7ecfd Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-11-22 07:00:04 +05:30
Luflosi
d6072f6218 X11: Assume 96 DPI if RandR monitor size is zero
From upstream: e96dc5d219.
2019-11-22 02:07:34 +01:00
Kovid Goyal
4ea72a2892 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-11-22 06:34:42 +05:30
Luflosi
89b07a1c6b Cocoa: Fix full screen window iconification
From upstream: 2c519709be.
2019-11-22 01:56:55 +01:00
Kovid Goyal
db0cd61807 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-11-22 06:17:47 +05:30
Luflosi
6feb906953 Cocoa: Cleanup
From upstream: bd452016be.
2019-11-21 18:30:03 +01:00
Kovid Goyal
7cbf8c63bc Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-11-21 20:00:30 +05:30
Luflosi
fae51d4e00 Cocoa: Add comments for Cocoa symbol macros
From upstream: 94cb0347ab.
2019-11-21 14:40:34 +01:00
Kovid Goyal
c510584afd Dont hang trying to read shell environment if the shell never quits. Fixes #2143 2019-11-20 11:53:28 +05:30
Kovid Goyal
738878c2ff unicode input kitten: Add an option :option:kitty +kitten unicode_input --emoji-variation to control the presentation variant of selected emojis
Fixes #2139
2019-11-17 13:13:37 +05:30
Kovid Goyal
d5682fe49a Fix #2137 2019-11-17 08:35:23 +05:30
Kovid Goyal
d8dd22048a Wayland: Ensure that glfw window content scale and kitty window content scale are in sync after the window is placed on a monitor 2019-11-16 10:47:05 +05:30
Kovid Goyal
737d8b96b6 Wayland: Dont bother with creating a temporary window anyway, as it is useless 2019-11-16 10:27:01 +05:30
Kovid Goyal
c8627c9713 Expand user/env vars in csutomize processing path and note that absolute paths can be used in the docs for it. 2019-11-16 10:05:25 +05:30
Kovid Goyal
65fa7da24a Wayland: Use the primary monitor scale for windows on creation
This is needed because on creation the window may not have been assigned
to any monitors, so we fallback to using the scale of the primary
monitor. Fixes #2133. Fixes #2135
2019-11-16 10:00:41 +05:30
Kovid Goyal
c4c6ef799f Dont shadow data 2019-11-13 19:47:08 +05:30
Kovid Goyal
0d18b91895 Grammar 2019-11-13 19:45:48 +05:30
Kovid Goyal
42089aaadc typo 2019-11-13 19:45:28 +05:30
Kovid Goyal
432d0f3318 hints kitten: Allow passing extra CLI args when using --customize-procesing 2019-11-13 17:27:55 +05:30
Kovid Goyal
4ade6587e8 spelling 2019-11-13 16:57:11 +05:30
Kovid Goyal
1724f11429 Deprecate pipe in favor of launch 2019-11-13 16:08:48 +05:30
Kovid Goyal
75d66d1048 Changelog entry for launch 2019-11-13 15:44:57 +05:30
Kovid Goyal
feccef67b9 Document the new launch action 2019-11-13 15:43:38 +05:30
Kovid Goyal
a7d30a199d location should also apply to tab creation 2019-11-13 15:40:46 +05:30
Kovid Goyal
37bbfb11d3 Fix location=neighbor causing a hang on a new tab 2019-11-13 15:39:38 +05:30
Kovid Goyal
79c80b4043 Fix doc generation 2019-11-13 15:03:02 +05:30
Kovid Goyal
18a1402ae2 Remote control interface for launch 2019-11-13 15:00:13 +05:30
Kovid Goyal
5d639b91b0 Switch OS windows when focusing on platforms where it is supported 2019-11-13 14:59:49 +05:30
Kovid Goyal
080c09d22e DRYer 2019-11-13 14:41:45 +05:30
Kovid Goyal
00c2670039 Fix handing of --stdin-source and getting of active window 2019-11-13 14:39:44 +05:30
Kovid Goyal
f113184165 Micro-optimization 2019-11-13 14:39:06 +05:30
Kovid Goyal
d69f8af107 Add a --keep-focus option for launch 2019-11-13 11:48:30 +05:30
Kovid Goyal
ad2bd1bf63 Allow using @selection in the launch cmdline 2019-11-13 10:46:04 +05:30
Kovid Goyal
059786ab66 Implement piping for launch 2019-11-13 10:38:58 +05:30
Kovid Goyal
72dfa5e5e6 Allow creating overlays via launch 2019-11-13 10:14:32 +05:30
Kovid Goyal
d84da6b7b8 Documentation placeholder for the new launch interface 2019-11-13 10:09:43 +05:30
Kovid Goyal
6aa82d82ad Start work on a unified interface for launching processes 2019-11-13 09:58:28 +05:30
Kovid Goyal
a649eb2a48 Coalesce neighboring symbol maps for better lookup performance 2019-11-12 20:05:48 +05:30
Kovid Goyal
83932c8099 Add a remote control command for detach_tab 2019-11-12 15:03:58 +05:30
Kovid Goyal
95e36cece1 Add a detach_window remote control command 2019-11-12 13:04:28 +05:30
Kovid Goyal
7075a7f1c0 Only detach window after the ask overlay is removed 2019-11-12 10:59:36 +05:30
Kovid Goyal
3093610d26 Allow choosing new os window/tab during detach ask 2019-11-12 10:42:07 +05:30
Kovid Goyal
86eed7f895 Speed up taking over of tab 2019-11-12 10:38:57 +05:30
Kovid Goyal
5dc14c5861 Copy cwd when taking over tab 2019-11-12 10:24:37 +05:30
Kovid Goyal
cab87f6fb2 Ensure Tab has cwd even with no initial window 2019-11-12 10:18:42 +05:30
Kovid Goyal
fb3acd1f4a Add a detach_tab command 2019-11-12 10:07:44 +05:30
Kovid Goyal
b247cef85c ... 2019-11-12 08:46:41 +05:30
Kovid Goyal
70445f33e9 Another typo 2019-11-12 06:30:21 +05:30
Kovid Goyal
cadb4f1389 ... 2019-11-12 06:29:55 +05:30
Kovid Goyal
bf75a4de61 Also document debug() 2019-11-12 06:25:27 +05:30
Kovid Goyal
400ab584ac hints kitten: Allow completely customizing the matching and actions performed by the kitten using your own script
Fixes #2124
2019-11-11 21:26:42 +05:30
Kovid Goyal
9edad62144 hints kitten: Allow using named groups in the regular expression. The named groups are passed to the invoked program for further processing. 2019-11-11 17:34:19 +05:30
Kovid Goyal
e94205098f Fix link 2019-11-11 16:00:35 +05:30
Kovid Goyal
35ab7eb472 Add a new action :ref:detach_window that can be used to move the current window into a different tab
Fixes #1310
2019-11-11 15:47:48 +05:30
Kovid Goyal
18619b14ac Merge branch 'simplify' of https://github.com/Luflosi/kitty 2019-11-10 23:35:27 +05:30
Luflosi
97e0b9b65a Simplify code 2019-11-10 16:51:25 +01:00
Kovid Goyal
5175d9f4a6 Properly re-initialize GPU resources when detaching/attaching a window 2019-11-09 13:14:50 +05:30
Kovid Goyal
a5aed0f4ab Forgot to change tab_ref when attaching window 2019-11-09 11:23:04 +05:30
Kovid Goyal
14d693a8ff When attaching window make its parent tab active 2019-11-09 11:09:29 +05:30
Kovid Goyal
645963cc24 Cleanup tab after detaching window 2019-11-09 09:42:17 +05:30
Kovid Goyal
20751c2807 Start work on a detach_window command 2019-11-09 09:20:38 +05:30
Kovid Goyal
dda886b97c Merge branch 'caps_lock_modifier' of https://github.com/Luflosi/kitty 2019-11-09 08:31:59 +05:30
Luflosi
b796ceecdd Add Caps Lock to the list of modifier keys
When a key is pressed and `mouse_hide_wait` is less than zero, kitty will hide the mouse cursor. When a key is pressed, kitty will also scroll the history to the bottom. Both of these things don't happen if the key being pressed was a modifier key. Both of these things should not happen when Caps Lock is pressed, so this key should be added to the list of modifier keys.
`is_modifier_key()` is not used for anything else.
2019-11-09 00:41:12 +01:00
Kovid Goyal
4def89ebb5 Add a note on debugging custom kittens 2019-11-08 16:53:26 +05:30
Kovid Goyal
bd1c1839dd Add API to boss.py to move a window into a different tab 2019-11-08 16:18:52 +05:30
Kovid Goyal
8739f698f9 When attaching window and font sizes changes, resize Screen 2019-11-08 14:58:08 +05:30
Kovid Goyal
b8c8482f20 Better fix for Powerline lacking a space glyph
This does not require increasing the size of the cache key, thereby
improving cache lookup performance
2019-11-08 14:41:31 +05:30
Kovid Goyal
4348ca8cc5 Remove unused function 2019-11-08 14:29:41 +05:30
Kovid Goyal
d1aa59080f Add an API to attach and detach windows from tabs 2019-11-08 14:22:02 +05:30
Kovid Goyal
bf0ffa80be Merge branch 'feature-window-to-tab' of https://github.com/0x17de/kitty
Currently only merged the function to move internal window state.
Want to refactor the changes to tabs.py and boss.py to make them more
orthogonal.
2019-11-08 09:55:51 +05:30
Kovid Goyal
2a89a0c87e Merge branch 'master' of https://github.com/martinpelikan/kitty 2019-11-08 07:57:47 +05:30
Kovid Goyal
de84489a20 Fix a regression in 0.14.5 that caused rendering of private use glyphs with and without spaces to be identical
Fixes #2117
2019-11-08 07:55:41 +05:30
Martin Pelikan
40901778ad Update fish completion docs for fish 3.0.0
As of 3.0.0, fish sources `kitty +complete fish` by default.
2019-11-07 18:11:47 -08:00
Kovid Goyal
c1febea659 Merge branch 'restore_error_reporting' of https://github.com/Luflosi/kitty 2019-11-05 07:07:03 +05:30
Luflosi
b42f4ac288 Restore proper error reporting functionality
In 841c907efc, the `%m` format specifier was replaced by `%%m`, which just prints `%m`. To keep the functionality of `%m` without using `%m`, the error string can be printed manually.
2019-11-05 00:42:29 +01:00
Kovid Goyal
fae57a5868 Website: Add a scrollbar to the sidebar if needed 2019-11-04 18:05:08 +05:30
Kovid Goyal
7a02d09508 Merge branch 'master' of https://github.com/CD3/kitty 2019-11-01 23:23:22 +05:30
C.D. Clark III
8ec6fe960d docs: added '@selection' to pipe documentation. 2019-11-01 08:46:49 -05:00
Kovid Goyal
61a77e19ef X11: Fix content scale fallback value on KDE
From upstream: 75294462b3
2019-10-31 09:10:01 +05:30
Kovid Goyal
82e88b54c7 X11: Fix decoration enabling after window creation
From upstream: 5fc4c01302
2019-10-31 09:04:45 +05:30
Kovid Goyal
ab8975f4da Merge branch 'with_suppress' of https://github.com/Luflosi/kitty 2019-10-29 10:17:19 +05:30
Luflosi
5e7fd21c8d Use "with suppress()" to suppress a python exception 2019-10-28 18:35:21 +01:00
Kovid Goyal
30cd9b2ae4 Merge branch 'fix_two_linker_error' of https://github.com/Luflosi/kitty 2019-10-28 07:31:49 +05:30
Luflosi
4f7d12f3fd Fix error when two linker processes fail
When a linker process fails, `failed` will be set to a value other than `None`. When a second linker process fails, the `else` case will be taken because `failed is None`, which executes `compile_cmd.on_success()`. This function tries to rename or move the file generated by the linker but since the linker process failed, the file will most likely not exist. This will throw an error, which will prevent printing the actual error message from the linker.
2019-10-27 21:50:22 +01:00
Kovid Goyal
62da158823 Merge branch 'fix_potential_error' of https://github.com/Luflosi/kitty 2019-10-27 07:42:21 +05:30
Luflosi
2d19b87208 Fix potential error when $PATH is not defined
When `PATH` is not in `os.environ`, kitty could potentially throw a `KeyError`.
2019-10-27 00:10:55 +02:00
Kovid Goyal
54ca775006 Merge branch 'visual' of https://github.com/toonn/kitty 2019-10-26 09:10:15 +05:30
toonn
a64a0d64cb Prefer VISUAL to EDITOR
Fix #2096
2019-10-25 18:52:17 +02:00
Kovid Goyal
6634dc81fe Merge branch 'simplify' of https://github.com/Luflosi/kitty 2019-10-25 07:45:30 +05:30
Luflosi
a2d5eef398 Simplify access to os.environ
The `if` can be removed by using `get()` with a default parameter to access `os.environ`. This also reduces the number of accesses to `os.environ`.
2019-10-24 20:27:27 +02:00
Kovid Goyal
8184ba246a Load libcanberra dynamically at runtime, as needed
Fixes #2089
2019-10-24 09:03:52 +05:30
Kovid Goyal
54ad1d103a Fix #2087 2019-10-23 18:21:34 +05:30
Kovid Goyal
d92f8a90ef Allow changing colors by mapping a keyboard shortcut to read a kitty config file with color definitions.
Fixes #2083
2019-10-21 14:43:35 +05:30
Kovid Goyal
d33c287344 typo 2019-10-21 14:23:07 +05:30
Kovid Goyal
782eebf976 typo 2019-10-21 14:21:09 +05:30
Kovid Goyal
0fbf75b95a Allow specifying that remote control only works over a socket 2019-10-21 14:20:30 +05:30
Kovid Goyal
5781facf4b Merge branch 'fix_icat' of https://github.com/Luflosi/kitty 2019-10-21 07:32:40 +05:30
Luflosi
b710ffc403 Fix icat kitten
Fixes https://github.com/kovidgoyal/kitty/issues/2081.
This bug was introduced in 10e5fcc375.

One place in the code requires the actual `screen_size_function`, not just the result of it.
2019-10-20 21:37:14 +02:00
Kovid Goyal
7d8edccb04 Merge branch 'pending_scroll_pixels_per_screen' of https://github.com/Luflosi/kitty 2019-10-20 16:58:28 +05:30
Luflosi
3750d70173 Store pending_scroll_pixels for every screen
Scrolling in one screen shouldn't affect the `pending_scroll_pixels` for another screen in the same OS window.
2019-10-20 13:22:46 +02:00
Kovid Goyal
025e0bb546 Merge branch 'var-names-consistency-wrt-scancode' of https://github.com/bew/kitty 2019-10-20 08:08:48 +05:30
Kovid Goyal
033367de91 Merge branch 'fix_line_drawing' of https://github.com/Luflosi/kitty 2019-10-19 06:26:57 +05:30
Luflosi
f93b605b75 Fix line drawing algorithm 2019-10-18 21:26:11 +02:00
Kovid Goyal
7b4141b0c8 Add a changelog entry for powerline tabbar 2019-10-18 19:38:08 +05:30
Kovid Goyal
90acef72dc Merge branch 'add_powerline_style_tabs' of https://github.com/brujoand/kitty 2019-10-18 19:36:31 +05:30
Kovid Goyal
43f200be77 Add an entry for the new box character rendering functions 2019-10-18 17:24:33 +05:30
Kovid Goyal
2fbb167803 Merge branch 'fix-triangle-symbol-scaling' of https://github.com/bew/kitty 2019-10-18 17:13:50 +05:30
Benoit de Chezelles
2b396262f0 Update glyph ids 2019-10-18 11:48:55 +02:00
Benoit de Chezelles
74deca52b9 Remove trailing whitespace 2019-10-18 11:39:51 +02:00
Benoit de Chezelles
058d956464 Merge branch 'master' into fix-triangle-symbol-scaling 2019-10-18 11:30:46 +02:00
brujoand
0f38dc1bd1 Adding powerline style tabs 2019-10-18 11:18:28 +02:00
Kovid Goyal
576b03c047 Implement drawing thick anti-aliased lines
And actually use it for the unicode diagonal box drawing chars and also
the powerline angle separators
2019-10-18 13:19:04 +05:30
Kovid Goyal
59cb1ad1e0 Implement special rendering for the diagonal line box drawing chars 2019-10-18 11:01:51 +05:30
Benoit de Chezelles
f77acdce14 remove useless import in help msg for box drawing debug 2019-10-18 06:08:45 +02:00
Benoit de Chezelles
43a98a1df1 Add missing association between char & glyph id 2019-10-18 06:08:20 +02:00
Benoit de Chezelles
d1cf771c14 Add other corner triangles & enable in C side 2019-10-18 05:45:13 +02:00
Benoit de Chezelles
10e5fcc375 Fix usage of icat function show
The `screen_size` function was not initialized yet
2019-10-18 04:54:14 +02:00
Benoit de Chezelles
2112932d04 Add corner triangle glyphs drawing 2019-10-18 04:48:03 +02:00
Benoit de Chezelles
be505ce6e0 Fix test functions for setup_for_testing's new call syntax 2019-10-18 04:47:04 +02:00
Benoit de Chezelles
4d6472128c Rename scancode to keycode for cocoa implementation 2019-10-17 20:41:48 +02:00
Kovid Goyal
26b7b1ec63 Merge branch 'typo' of https://github.com/Luflosi/kitty 2019-10-17 18:32:42 +05:30
Luflosi
9a8f0a9b5a Fix typo 2019-10-17 13:56:46 +02:00
Kovid Goyal
16dbbf3a1e Make count-lines-of-code a little nicer 2019-10-17 15:19:13 +05:30
Kovid Goyal
8492d0a264 Merge branch 'dont_cloc_parse-graphics-command.h' of https://github.com/Luflosi/kitty 2019-10-17 14:36:53 +05:30
Luflosi
d8f8f1f590 Exclude kitty/parse-graphics-command.h from the line count
This file is automatically generated and should not count towards the total line count.
2019-10-17 10:38:55 +02:00
Kovid Goyal
b762e81da0 Merge branch 'python_encoding_header' of https://github.com/Luflosi/kitty 2019-10-17 06:28:16 +05:30
Luflosi
8b3b68ea69 Unify python encoding headers
All the other python encoding headers are of the form `vim:fileencoding=utf-8`.
2019-10-16 20:34:56 +02:00
Benoit de Chezelles
28525766a5 Final changes before 'ready for review' 2019-10-16 02:47:14 +02:00
Benoit de Chezelles
d8fc23c38f remove outdated 'fixme' 2019-10-16 02:41:26 +02:00
Benoit de Chezelles
8cae70fa36 Update doc 2019-10-16 02:36:55 +02:00
Benoit de Chezelles
7f2b98fad7 Rename all uses of 'scancode' to 'native_key' where relevant 2019-10-16 02:25:20 +02:00
Benoit de Chezelles
2b6dde2ac5 Wish: rename scancode → native_key in glfw codebase 2019-10-16 02:00:24 +02:00
Benoit de Chezelles
0c254fa7c7 GLFWkeyevent: rename scancode → native_key 2019-10-16 02:00:24 +02:00
Kovid Goyal
fe7375becc Merge branch 'grammar' of https://github.com/Luflosi/kitty 2019-10-16 04:19:54 +05:30
Luflosi
b6ee88056e Minor grammar correction 2019-10-16 00:46:52 +02:00
Kovid Goyal
96f691ad64 Merge branch 'mark_parse-graphics-command.h_as_generated' of https://github.com/Luflosi/kitty 2019-10-16 03:31:32 +05:30
Luflosi
8cf3380a77 Mark kitty/parse-graphics-command.h as being generated 2019-10-15 18:16:28 +02:00
Kovid Goyal
e8d7e3e98b Merge branch 'remove_khrplatform.h_references' of https://github.com/Luflosi/kitty 2019-10-15 20:58:16 +05:30
Luflosi
8af0a8476f Remove remaining references to kitty/khrplatform.h
`kitty/khrplatform.h` was removed in f872f955b0.
2019-10-15 17:25:47 +02:00
Kovid Goyal
2de4248f76 Merge branch 'regenerate_glfw-wrapper' of https://github.com/Luflosi/kitty 2019-10-15 20:42:49 +05:30
Luflosi
8c73ab6afb Regenerate kitty/glfw-wrapper.h 2019-10-15 17:10:02 +02:00
Kovid Goyal
ee9bd77dc4 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-15 19:10:50 +05:30
Luflosi
81f31ca215 Reduce difference of glfw/glfw3.h to GLFW upstream 2019-10-15 15:37:35 +02:00
Kovid Goyal
51eff372f8 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-15 18:16:22 +05:30
Luflosi
087376b44d GLFW: Documentation work
From upstream: a43d1a4937.
2019-10-15 14:37:41 +02:00
Kovid Goyal
e49047ef7d Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-15 18:02:17 +05:30
Luflosi
c117f36009 GLFW: Cleanup
From upstream: d5ab3e919a.
2019-10-15 14:25:46 +02:00
Kovid Goyal
5ec83ee759 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-15 16:17:49 +05:30
Luflosi
410165c14d GLFW: Improve (?) reference documentation for callbacks
From upstream: 51bb76c7c3.
2019-10-15 12:11:01 +02:00
Kovid Goyal
973ef9fcda Merge branch 'fix_nix_link' of https://github.com/Luflosi/kitty 2019-10-15 04:14:04 +05:30
Luflosi
396bfb8540 Fix link to Nix kitty package
Instead of a fragment identifier, the URL now needs a query parameter.
2019-10-14 18:48:21 +02:00
Kovid Goyal
aaf597bffd Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-13 09:08:15 +05:30
Luflosi
63c4f64bf5 Reduce difference to GLFW upstream
From upstream: 773f4495f0.
2019-10-12 15:19:44 +02:00
Kovid Goyal
5745dc34f7 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-12 17:58:50 +05:30
Luflosi
114b8cff93 Cleanup
From upstream: 62b7fe8311.
2019-10-11 20:26:27 +02:00
Kovid Goyal
261571bb69 Merge branch 'modern_objective-c' of https://github.com/Luflosi/kitty 2019-10-10 22:01:30 +05:30
Manuel Herrmann
497e2c9163 #1310 move windows into separate tabs 2019-10-10 17:13:34 +02:00
Luflosi
ac01ffaa54 Cocoa: Move slightly towards modern Objective-C 2019-10-10 14:36:52 +02:00
Kovid Goyal
eb9fe06d10 Merge branch 'correct_space' of https://github.com/Luflosi/kitty 2019-10-09 22:15:38 +05:30
Luflosi
506f2f7db7 Replace weird character with space
In 4c4c6ab0e6 you added a weird unicode character, which is apparently called an Object Replacement Character, instead of a space.
2019-10-09 18:32:49 +02:00
Kovid Goyal
f476c56f91 Drop support for the gtk_primary_selection wayland protocol
sway recently decided to start complaining when binding
wp_primary_selection_device_manager interface to gtk_primary_selection
name, which means we either have to maintain an in-tree version
of the gtk_primary_selection protocol or drop support for sway.

Sway has not quite annoyed me enough yet for the latter.

See #1977
2019-10-09 07:37:03 +05:30
Kovid Goyal
474688888d Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-08 17:16:51 +05:30
Luflosi
7ddbb613fe Cocoa: Fix window creation blocking after re-init
From 2fbb560eb7.
2019-10-08 13:41:10 +02:00
Kovid Goyal
adc1c06089 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-08 12:12:00 +05:30
Luflosi
1f8631cc99 Cocoa: Move app delegate and menu creation to init
From ea7eb2ddab.
2019-10-07 21:24:58 +02:00
Kovid Goyal
f9e4e71285 Slightly better error message when opening controlling terminal fails 2019-10-07 20:48:31 +05:30
Kovid Goyal
5529194c8d Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty 2019-10-06 20:39:25 +05:30
Luflosi
5b008163af Cocoa: Add NSApplicationDelegate protocol
From c3ed70a4b7.
2019-10-06 16:58:06 +02:00
Kovid Goyal
802da7087c diff kitten: Allow diffing remote files easily via ssh
See #727
2019-10-04 09:08:22 +05:30
Kovid Goyal
53ab7617ca Dont use space ligatures for symbol_map fonts
space ligatures breaks in font ligatures when there is a trailing space.
So only use them for PUA and cells using a fallback font. Fixes #2019
2019-10-02 07:10:51 +05:30
Kovid Goyal
4369255a25 When drawing unicode symbols that are followed by spaces, use multiple cells to avoid resized or cut-off glyphs
Fixes #1452
2019-10-01 19:56:07 +05:30
Kovid Goyal
b709ee6842 Add a function to check if a codepoint is a symbol 2019-10-01 18:57:06 +05:30
Kovid Goyal
4a8f9efe79 Wayland: Resume key repeat on focus gained if the previously repeated key is pressed 2019-09-30 18:47:43 +05:30
Kovid Goyal
19d36fbe69 Wayland: Fix key repeat not being stopped when focus leaves window. This is expected behavior on Wayland, apparently
Fixes #2014
2019-09-30 16:45:39 +05:30
Kovid Goyal
d37e73db54 Merge branch 'fix_broken_paste' of https://github.com/Luflosi/kitty
Fixes #2008
2019-09-29 08:02:31 +05:30
Luflosi
a8f6615380 Fix broken paste on X11
Fixes https://github.com/kovidgoyal/kitty/issues/2008.
2019-09-29 02:48:09 +02:00
Kovid Goyal
97fe38fbbc monotonic_start_time needs to be a global symbol, not local to each translation unit 2019-09-28 08:18:21 +05:30
Kovid Goyal
3378175450 Hopefully the last macOS float conversion fix 2019-09-27 20:14:05 +05:30
Kovid Goyal
9f60d2aea3 More macOS float conversion fixes 2019-09-27 20:11:32 +05:30
Kovid Goyal
46d49e18c0 More macOS float fixes 2019-09-27 20:07:09 +05:30
Kovid Goyal
43fc335be2 more macOS float fixes 2019-09-27 20:05:11 +05:30
Kovid Goyal
f68339c571 float conversion fixes for macOS 2019-09-27 19:56:48 +05:30
Kovid Goyal
0d68b7078c Check for float conversion issues on build
Useful to catch any errors left over from the migration of times from
double to int64_t
2019-09-27 19:47:25 +05:30
Kovid Goyal
2e71dde780 Merge branch 'monotonic_t' of https://github.com/Luflosi/kitty 2019-09-27 19:23:27 +05:30
Kovid Goyal
51ddd584d6 Merge branch 'mark_unicode_data_as_generated' of https://github.com/Luflosi/kitty 2019-09-27 09:21:29 +05:30
Luflosi
4b090259cd Mark kitty/unicode-data.c as being generated 2019-09-26 21:54:42 +02:00
Luflosi
f3b9ff5f9f Use datatype monotonic_t instead of double to keep track of time
The time is stored in a signed 64 bit integer with nanosecond accuracy. This eliminates the possibility of floating-point inaccuracies.
`monotonic_t` can currently hold values large enough to work correctly for more than 200 years into the future.
Using a typedef instead of directly using `int64_t` everywhere will also allow easily changing the datatype in the future should the need arise for more precise or bigger time values.
2019-09-25 17:43:11 +02:00
Kovid Goyal
4ec1a8d9c3 Merge branch 'extract-glfw-key-event-data' of https://github.com/bew/kitty 2019-09-25 15:44:56 +05:30
Kovid Goyal
350cfeb7ef version 0.14.6 2019-09-25 11:28:55 +05:30
Kovid Goyal
97d379b13e Add changelog entry for DPI change PR 2019-09-25 06:34:55 +05:30
Kovid Goyal
2154d555e5 Merge branch 'update_check_interval_constant' of https://github.com/Luflosi/kitty 2019-09-25 06:23:05 +05:30
Luflosi
1389c36657 Use the update CHECK_INTERVAL constant 2019-09-25 02:46:19 +02:00
Kovid Goyal
bd1e7d6942 Merge branch 'master' of https://github.com/dcolascione/kitty 2019-09-25 05:56:17 +05:30
Benoit de Chezelles
aadab38487 Fix compilation for macos 2019-09-24 22:03:55 +02:00
Daniel Colascione
91299a279b Fix window resize on DPI change 2019-09-24 12:41:23 -07:00
Benoit de Chezelles
53275c9137 Extract key event data to struct 2019-09-24 19:15:35 +02:00
Kovid Goyal
fb1c318a09 macOS: Fix a regression in the previous release that caused a crash when pressing a unprintable key, such as the POWER key
Fixes #1997
2019-09-24 16:07:52 +05:30
Kovid Goyal
2a07b3f46a Fix #1995 2019-09-24 06:40:21 +05:30
Kovid Goyal
ffc4e99717 version 0.14.5 2019-09-23 08:41:38 +05:30
Kovid Goyal
fe807dd66f Fix missing parameter name in docs 2019-09-22 19:39:22 +05:30
Kovid Goyal
40ce5db812 Add completion for listen on 2019-09-22 16:08:37 +05:30
Kovid Goyal
649a9f4a6f oops 2019-09-22 16:01:33 +05:30
Kovid Goyal
e17ce875be Complete more CLI args 2019-09-22 16:01:12 +05:30
Kovid Goyal
415701c58a Add completion of filenames for --config 2019-09-22 15:52:45 +05:30
Kovid Goyal
f16f80b459 Merge branch 'glfw_null_unused_params' of https://github.com/Luflosi/kitty 2019-09-20 06:27:13 +05:30
Luflosi
628e6cc87f Mark unused parameters in glfw/null_*.c
kitty didn't compile on FreeBSD for me because of unused parameters in glfw/null_joystick.c, so I added the `UNUSED` attribute to them.
I also added `UNUSED` to the unused parameters in glfw/null_monitor.c and glfw/null_window.c as well even though they are probably not used.
2019-09-19 20:21:09 +02:00
Kovid Goyal
8f9a225c3a Use selection foreground color for underlines as well
Fixes #1982
2019-09-19 19:28:33 +05:30
Kovid Goyal
7b41bc95e1 Merge branch 'move_allocation_failure_check' of https://github.com/Luflosi/kitty 2019-09-19 18:45:42 +05:30
Luflosi
2d06ee5822 Move allocation failure check closer to allocation 2019-09-19 14:58:39 +02:00
Kovid Goyal
40b4fb966f Merge branch 'add_missing_key_name_aliases' of https://github.com/Luflosi/kitty 2019-09-19 05:53:42 +05:30
Luflosi
be696a9d76 Add missing keys to key_name_aliases 2019-09-18 19:36:56 +02:00
Luflosi
1ffe9bef35 Order key_name_aliases by their ASCII value 2019-09-18 16:23:38 +02:00
Luflosi
ed70d95c44 Move aliases for common key name variations to the end of key_name_aliases 2019-09-18 16:23:01 +02:00
Kovid Goyal
49bf876f73 Merge branch 'remove_plus_key_alias' of https://github.com/Luflosi/kitty 2019-09-18 19:45:19 +05:30
Luflosi
e512b4d3e3 Remove PLUS key from key_name_aliases 2019-09-18 16:07:55 +02:00
Kovid Goyal
e78b6c7c7c Merge branch 'faq' of https://github.com/jacwah/kitty 2019-09-18 09:49:09 +05:30
Jacob Wahlgren
a7403c0005 Update FAQ with FreeBSD termcap info
Thanks to amarshall's help:
https://github.com/kovidgoyal/kitty/issues/765#issuecomment-487381289
2019-09-17 22:19:51 +02:00
Kovid Goyal
5bed0dddaa typo 2019-09-15 06:19:27 +05:30
Kovid Goyal
bc302dad23 Linux: Allow using fonts with spacing=90 in addition to fonts with spacing=100
Fixes #1968
2019-09-15 06:08:40 +05:30
Kovid Goyal
41b0f8852f Only update config_key_map with those entries in key_name_aliases that exist in ENCODING 2019-09-15 04:24:32 +05:30
Kovid Goyal
2fadd3e7ba Add a note to the fontconfig FAQ about how to override spacing 2019-09-15 04:09:26 +05:30
Kovid Goyal
dcfd2b8d60 Fix incorrect rendering of some symbols when followed by a space while using the PowerLine font which does not have a space glyph
Fixes #1225
2019-09-14 17:56:52 +05:30
Kovid Goyal
7fe63a7aad Add changelog entry for key mapping PR 2019-09-14 10:20:18 +05:30
Kovid Goyal
67f2ec2421 Merge branch 'keyboard_improvement' of https://github.com/Luflosi/kitty 2019-09-14 10:17:35 +05:30
Kovid Goyal
8e7a23a7b9 Merge branch 'use_OPT' of https://github.com/Luflosi/kitty 2019-09-12 13:43:12 +05:30
Luflosi
8e96a27d51 Use the OPT() macro where possible 2019-09-12 10:02:53 +02:00
Kovid Goyal
b337d4d9d5 Merge branch 'master' of https://github.com/copy/kitty 2019-09-12 07:43:35 +05:30
Fabian
d9404c0362 Fix color index 232 (should be #080808, not black) 2019-09-11 20:01:52 +02:00
Kovid Goyal
e4ba5f449f When resetting the terminal, also reset parser state, this allows easy recovery from incomplete escape codes
Fixes #1961
2019-09-09 20:56:35 +05:30
Kovid Goyal
17fd749e8d Add some aliases when parsing config files for common key name variations 2019-09-08 19:28:41 +05:30
Luflosi
f3be5b5e57 Regenerate automatically generated key_encoding.py and keys.h 2019-09-08 12:32:20 +02:00
Luflosi
e619eb9cbb Add more keyboard keys 2019-09-08 12:32:19 +02:00
Luflosi
a65ee155c5 Indent lookup table in _glfwGetKeyName() to allow for longer keyboard key names 2019-09-08 12:32:19 +02:00
Luflosi
4037480d2b Allow for up to 256 keys instead of 128 2019-09-08 12:32:19 +02:00
Luflosi
97e6978ed8 Order keyboard keys by their ASCII value 2019-09-08 12:32:19 +02:00
Luflosi
f05eefcc20 Allow adding keys with Unicode names on macOS 2019-09-08 12:32:19 +02:00
Luflosi
3f926dfd8b Use keyboard key constants instead of hardcoded values 2019-09-08 12:32:18 +02:00
Luflosi
59f64c5e33 Blacklist GLFW_KEY_LAST_PRINTABLE in kitty/keys.py 2019-09-08 12:32:18 +02:00
Luflosi
87059a2004 Add GLFW_KEY_LAST_PRINTABLE as a GLFW constant 2019-09-08 12:32:18 +02:00
Luflosi
7c52dd2bd8 Fix update_encoding() not filtering GLFW_KEY_LAST_PRINTABLE
b3b830bb5f did not actually make `update_encoding()` filter `GLFW_KEY_LAST_PRINTABLE` because `name` contained the key name after applying `symbolic_name()`, which replaces underscores with spaces. Instead of replacing the underscore in `LAST_PRINTABLE` with a space, I moved the check above the call to `symbolic_name()`. This is more readable and future-proof in my opinion.
2019-09-08 12:32:18 +02:00
Kovid Goyal
70c2765a6e Allow reading session file from STDIN 2019-09-08 15:20:37 +05:30
Kovid Goyal
3618f4d642 Only try to wakeup talk thread if it has been started 2019-09-08 15:12:17 +05:30
Kovid Goyal
698569536d Output which loo could not be woken up 2019-09-08 14:58:11 +05:30
Kovid Goyal
c398d3d16e Cocoa: Fix glfwSetWindowSize anchor point
This makes glfwSetWindowSize use the top-left corner as anchor point
instead of the bottom-left corner.

Upstream: 7f02898264
2019-09-08 09:16:07 +05:30
Kovid Goyal
9dbc54aad6 Fix comparison of video modes of equal area
This fixes the bug of video modes being discarded if they had
a different resolution but the same area as another mode.

Upstream: 2777f6a754
2019-09-08 09:12:39 +05:30
Kovid Goyal
931cb223cd When all visible windows have the same background color, use that as the color for the global padding, instead of the configured background color
See #1957
2019-09-07 18:47:15 +05:30
Kovid Goyal
336ee53fea Merge branch 'joystick-platform' of https://github.com/jamessan/kitty 2019-09-04 08:43:16 +05:30
James McCoy
34350af61c Only use linux_joystick.c on Linux
Rather than using null_joystick.c when _plat is a bsd, use
linux_joystick.c when _plat is a linux.  This fixes a build issue with
other non-BSD, non-Linux platforms.
2019-09-03 23:02:16 -04:00
Kovid Goyal
72f7cb3b7d Merge branch 'format_key_encoding' of https://github.com/Luflosi/kitty 2019-09-02 07:49:30 +05:30
Luflosi
481047a446 Format kitty/key_encoding.py with yapf 2019-09-01 17:53:52 +02:00
Kovid Goyal
3bf1d73b07 Merge branch 'add_glfw_key_last_printable' of https://github.com/Luflosi/kitty 2019-09-01 17:52:39 +05:30
Luflosi
b3b830bb5f Make adding more printable keys slightly easier
When adding keys after `GLFW_KEY_UNDERSCORE`, one now needs to change a `#define` right below the last printable key instead of changing it elsewhere in the code.
This commit now also marks `GLFW_KEY_PLUS` and `GLFW_KEY_UNDERSCORE` as printable characters.
2019-09-01 11:24:14 +02:00
Kovid Goyal
def0c55df3 Merge branch 'add_missing_named_keys' of https://github.com/Luflosi/kitty 2019-09-01 05:43:27 +05:30
Luflosi
b995e00850 Add missing key to named_keys 2019-09-01 02:03:54 +02:00
Kovid Goyal
32dfc94909 Implement a hack to (mostly) preserve tabs when cat a file with them and then copying the text or passing screen contents to another program
It's a simple enough hack that it seems worth doing. If it causes any
issues, can always be reverted.

Fixes #1829
2019-08-31 12:37:05 +05:30
Kovid Goyal
20f7118432 version 0.14.4 2019-08-31 10:20:47 +05:30
Kovid Goyal
37e6c3f0cb Merge branch 'bool_indentation' of https://github.com/Luflosi/kitty 2019-08-30 19:08:46 +05:30
Luflosi
0459dda5c2 Fix bool indentation
The wrong indentation was caused by the removal of GLFWbool in fe62700825.
2019-08-30 15:32:20 +02:00
Kovid Goyal
a10c816c05 Merge branch 'fix_nslog_string_format' of https://github.com/Luflosi/kitty 2019-08-30 18:40:49 +05:30
Luflosi
c0c7cfacc2 Fix NSLog() printing of unicode format strings
See https://stackoverflow.com/questions/720052/nslog-incorrect-encoding.
The `%s` format placeholder for `NSLog()` expects an encoding other than UTF-8, which leads to garbled Unicode characters when trying to print a UTF-8 encoded string.
```Objective-C
NSLog(@"Ä %s %@", "Ä", @("Ä"));
```
prints `Ä √Ñ Ä`.

As can be seen in the example above, the workaround is to convert the UTF-8 encoded C-string to an `NSString` object and print that instead.
`debug_key()` calls `NSLog()`.
2019-08-30 15:03:51 +02:00
Kovid Goyal
8cdb6647ed Merge branch 'fix_update_encoding' of https://github.com/Luflosi/kitty 2019-08-30 16:20:42 +05:30
Luflosi
b68e3c85b9 Add missing MENU key to key_encoding.py 2019-08-30 12:37:23 +02:00
Luflosi
ef25d5bbd5 Fix update_encoding() not adding the last key 2019-08-30 12:36:37 +02:00
Kovid Goyal
278bf6e897 Fix #1937 2019-08-30 15:02:17 +05:30
Kovid Goyal
90a985b73a Make format_text() more secure 2019-08-28 05:41:20 +05:30
Kovid Goyal
b016353809 Some clarifications for the graphics protocol
See discussion on #33
2019-08-28 05:28:05 +05:30
Kovid Goyal
bc222af2e2 When dumping scrollback as ansi, reset SGR formatting at end of scrollback 2019-08-27 19:35:01 +05:30
Kovid Goyal
44599c9460 Merge branch 'simplify_compile_code' of https://github.com/Luflosi/kitty 2019-08-26 20:25:19 +05:30
Luflosi
902fc22670 Simplify GLFW compilation code
This commit removes the need for `is_macos` in `glfw/glfw.py` by moving a few lines of code. Instead of relying on the information that the compilation is or isn't happening on macOS, the code now does the right thing based on which `module` is being built.
This changes the order of the compilation flags slightly.
2019-08-26 16:47:19 +02:00
Kovid Goyal
d84e22fbf1 Merge branch 'fix_typos' of https://github.com/Luflosi/kitty 2019-08-26 16:34:54 +05:30
Luflosi
6cc720a350 Fix typos
Inspired by 4d3ee554b3.
Found using `codespell`.
2019-08-26 12:31:15 +02:00
Kovid Goyal
c905978874 Merge branch 'fix_issue_1924' of https://github.com/s1341/kitty
Fixes #1924
2019-08-26 10:19:50 +05:30
Kovid Goyal
bfe595a8e8 Merge branch '_glfwInputError_format' of https://github.com/Luflosi/kitty 2019-08-26 06:24:02 +05:30
Luflosi
94d56d1a9e Correct indentation for two _glfwInputError() messages
This commit changes the indentation of two error messages to match the indentation in the rest of the code.
2019-08-25 21:29:58 +02:00
s1341
bd3f0b5363 Properly handle all NULL cases 2019-08-25 17:22:06 +03:00
s1341
6fae3545c7 Fix null pointer deref 2019-08-25 16:39:39 +03:00
s1341
297963f6ab Fix issue #1924 by making prev_cell persistent across line_as_ansi calls 2019-08-25 16:25:36 +03:00
Kovid Goyal
a0ceba407e Merge branch 'drag_and_drop_text' of https://github.com/Luflosi/kitty 2019-08-24 08:39:27 +05:30
Kovid Goyal
35fa91fba2 When the OS returns a fallback font that does not actually contain glyphs for the text, do not exhaust the list of fallback fonts
Fixes #1918

Apparently fontconfig does this for Tangut components.
2019-08-24 08:27:54 +05:30
Kovid Goyal
a5d6cd169e Fix piping PNG images into the icat kitten not working
Fixes #1920
2019-08-24 08:04:04 +05:30
Luflosi
06c2263657 macOS: implement drag and drop of text into kitty
Closes #1368.
2019-08-24 01:29:33 +02:00
Kovid Goyal
472c6f6b8d When running kittens, use the colorscheme of the current window rather than the configured colorscheme
Fixes #1906
2019-08-18 18:27:44 +05:30
Kovid Goyal
afcaca85da Merge branch 'hints_regex_doc' of https://github.com/toonn/kitty 2019-08-18 07:41:14 +05:30
Toon Nolten
2575349ec2 Add expected regex syntax to hints kitten docs
The hints kitten's help documentation did not mention what syntax to use
for the regular expressions. I knew much of kitty was implemented in
python so I guessed correctly but not everyone might know this.

I also fixed some double-spaced sentences because most of them are
single-spaced.
2019-08-17 21:27:53 +02:00
Kovid Goyal
77054f688d Workaround for window managers like xmonad that in some circumstances set window size to zero. Fixes #1910 2019-08-17 18:04:08 +05:30
Kovid Goyal
c5cb24378f Merge branch 'fix_macos_show_window_title_in' of https://github.com/Luflosi/kitty 2019-08-14 06:36:25 +05:30
Luflosi
d66123dd14 Fix hiding the window title in macOS
In b5c2163238 I introduced a bug where only the window title of the first OS window would be hidden. This commit fixes that bug.
The bug was caused by the code hiding the window title being in an `if` statement that only executes once.
2019-08-13 21:02:28 +02:00
Kovid Goyal
4ef8f11f9e Merge branch 'add_frameworks_only_once' of https://github.com/Luflosi/kitty 2019-08-11 07:43:36 +05:30
Luflosi
599be7ddc9 Don't add Apple Frameworks twice
These Frameworks are added again a couple lines below in the check for `module == 'cocoa'`.
2019-08-11 02:26:12 +02:00
Kovid Goyal
685497fc8c Fix shaping test 2019-08-10 08:58:02 +05:30
Kovid Goyal
57542fc204 Only disable liga and dlig for nimbus mono 2019-08-10 08:22:36 +05:30
Kovid Goyal
8d9323aec6 Merge branch 'unnecessary_indentation' of https://github.com/Luflosi/kitty 2019-08-09 07:05:26 +05:30
Luflosi
4984a25b19 Remove unnecessary indentation 2019-08-09 03:27:22 +02:00
Kovid Goyal
3bdcb29e01 Merge branch 'trailing_whitespace' of https://github.com/Luflosi/kitty 2019-08-09 06:34:19 +05:30
Luflosi
b9ab8e6348 Remove trailing whitespace 2019-08-08 20:26:20 +02:00
Kovid Goyal
4a851701e9 Fix a regression that broke setting background_opacity via remote control
Fixes #1895
2019-08-07 15:09:04 +05:30
Kovid Goyal
eafd8af937 Merge branch 'glfw_3.4' of https://github.com/Luflosi/kitty 2019-08-03 07:38:14 +05:30
Luflosi
28bb123be8 Update the GLFW version number from 3.3 to 3.4
Closes https://github.com/kovidgoyal/kitty/issues/1884.
From a337c56848.
2019-08-02 11:00:16 -05:00
Kovid Goyal
8e1ed2f8c3 Update unicode data to 12.1 2019-08-02 14:48:18 +05:30
Kovid Goyal
4a0fcb3cff Merge branch 'macos_show_window_title_in' of https://github.com/Luflosi/kitty 2019-08-02 11:51:38 +05:30
Luflosi
b5c2163238 Add option to hide the window title on macOS
Deprecate `macos_show_window_title_in_menubar` and create a new option `macos_show_window_title_in`.
2019-08-02 00:20:43 -05:00
Kovid Goyal
d0ecdfb330 Add a :opt:kitten_alias option that can be used to alias kitten invocation for brevity and to change kitten option defaults globally
See #1879
2019-08-02 10:40:11 +05:30
Kovid Goyal
bdf7d98a36 hints kitten: Allow specifying :option:kitty +kitten hints --program multiple times to run multiple programs
See #1879
2019-08-02 10:03:04 +05:30
Kovid Goyal
e4b0980d15 DRYer 2019-08-02 07:18:42 +05:30
Kovid Goyal
d99c57aeae Merge branch 'open_context_manager' of https://github.com/Luflosi/kitty 2019-08-02 07:14:11 +05:30
Luflosi
5f855ce547 Use context managers to open files
Inspired by d50a6ddc1b.
2019-08-01 13:21:26 -05:00
Kovid Goyal
68f3b6fbeb Fix the decode_hint function to work with an arbitrary alphabet 2019-08-01 19:31:21 +05:30
Kovid Goyal
dc6d14943e Dont use a global variable for the hints alphabet 2019-08-01 19:24:09 +05:30
Kovid Goyal
05f7334db9 hints kitten: Add a :option:kitty +kitten hints --alphabet option to control what alphabets are used for hints
Fixes #1879
2019-08-01 16:25:54 +05:30
Kovid Goyal
cd707e9335 Merge branch 'wait_for_shell' of https://github.com/Luflosi/kitty 2019-08-01 12:56:12 +05:30
Luflosi
505ed5e43b Fix crash when the shell takes too long to start when reading the environment
According to https://docs.python.org/3/library/subprocess.html#subprocess.Popen.wait, `wait()` throws a `TimeoutExpired` exception when the process is not done after the timeout. I noticed this because kitty crashed for me.
The old code looks like it's trying to wait as long as it takes for the process to finish, which is what I implemented.
2019-08-01 02:03:08 -05:00
Kovid Goyal
9dc8bf5f62 Merge branch 'ignore_directories' of https://github.com/Luflosi/kitty 2019-08-01 06:38:34 +05:30
Luflosi
f8098662b6 Explicitly mark directories as such in .gitignore 2019-07-31 15:27:06 -05:00
Kovid Goyal
de7a0e86c4 Merge branch 'ignore_files_only_in_root' of https://github.com/Luflosi/kitty 2019-07-31 20:56:50 +05:30
Luflosi
ca55438fda Ignore several directories and files only in the root of the repo
These directories are always located in the root directory of the repository. Therefore it's better to only ignore these files in this location.
2019-07-31 10:16:19 -05:00
Kovid Goyal
a4b60e7eef Disable the `liga and dlig` OpenType features so that kitty works with "so-called" monospace fonts such as Nimbus Mono that have non-programming ligatures. 2019-07-31 20:02:48 +05:30
Kovid Goyal
5d22e07738 More details on login shell invocation 2019-07-31 12:20:02 +05:30
Kovid Goyal
bdade7e151 Use a new controlling terminal when reading shell environment
This is because some people do things in their rc files based
on checking the name of the controlling terminal.
2019-07-31 11:34:54 +05:30
Kovid Goyal
6958ded4c4 Dont fail to start if running the shell to read the EDITOR env var fails
Fixes #1869
2019-07-31 06:37:17 +05:30
Kovid Goyal
cc06104be6 Create FUNDING.yml
Add links to the various funding sources
2019-07-30 15:07:12 +05:30
Kovid Goyal
059c34c345 Add a version check to the installer on macOS 2019-07-30 15:01:07 +05:30
Kovid Goyal
9cbb726566 Fix #1865 2019-07-30 06:20:54 +05:30
Kovid Goyal
e8b4356a88 Merge branch 'ignore_build_only_in_root' of https://github.com/Luflosi/kitty 2019-07-29 11:37:36 +05:30
Kovid Goyal
634138cd3b Removed unused entry from .gitignore
Fixes #1859

tags is the file generated by ctags
2019-07-29 11:36:46 +05:30
Luflosi
3f6b07de81 Ignore the build directory only in the root of the repo
The `build` directory is always located at the root directory of the repository. Therefore it's better to only ignore `build` in this location.
2019-07-29 00:59:35 -05:00
179 changed files with 44967 additions and 34670 deletions

4
.gitattributes vendored
View File

@@ -3,11 +3,11 @@ kitty/emoji.h linguist-generated=true
kitty/keys.h linguist-generated=true
kitty/charsets.c linguist-generated=true
kitty/key_encoding.py linguist-generated=true
kitty/unicode-data.c
kitty/unicode-data.c linguist-generated=true
kitty/rgb.py linguist-generated=true
kitty/gl-wrapper.* linguist-generated=true
kitty/khrplatform.h linguist-generated=true
kitty/glfw-wrapper.* linguist-generated=true
kitty/parse-graphics-command.h linguist-generated=true
glfw/*.c linguist-vendored=true
glfw/*.h linguist-vendored=true
kittens/unicode_input/names.h linguist-generated=true

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
patreon: kovidgoyal
liberapay: kovidgoyal
custom: https://sw.kovidgoyal.net/kitty/support.html

27
.gitignore vendored
View File

@@ -1,18 +1,17 @@
*.so
*.pyc
*.pyo
tags
build
linux-package
kitty.app
compile_commands.json
link_commands.json
glad/out
kitty/launcher
*.dSYM
dev
__pycache__
glfw/wayland-*-client-protocol.[ch]
docs/_build
docs/generated
/tags
/build/
/linux-package/
/kitty.app/
/compile_commands.json
/link_commands.json
/glad/out/
/kitty/launcher/
/*.dSYM/
__pycache__/
/glfw/wayland-*-client-protocol.[ch]
/docs/_build/
/docs/generated/
.DS_Store

View File

@@ -1,8 +1,8 @@
ifdef V
VVAL=--verbose
VVAL=--verbose
endif
ifdef VERBOSE
VVAL=--verbose
VVAL=--verbose
endif
all:
@@ -28,7 +28,7 @@ asan:
profile:
python3 setup.py build $(VVAL) --profile
app:
app:
python3 setup.py kitty.app $(VVAL)
man:

View File

@@ -1,5 +1,5 @@
= kitty - the fast, featureful, GPU based, terminal emulator
See https://sw.kovidgoyal.net/kitty
See https://sw.kovidgoyal.net/kitty/
image:https://circleci.com/gh/kovidgoyal/kitty.svg?style=svg["Build status", link="https://circleci.com/gh/kovidgoyal/kitty"]

View File

@@ -92,8 +92,10 @@ def setup_openssl_environment():
if 'SSL_CERT_FILE' not in os.environ and 'SSL_CERT_DIR' not in os.environ:
if os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
os.environ['SSL_CERT_FILE'] = '/etc/pki/tls/certs/ca-bundle.crt'
sys.kitty_ssl_env_var = 'SSL_CERT_FILE'
elif os.path.isdir('/etc/ssl/certs'):
os.environ['SSL_CERT_DIR'] = '/etc/ssl/certs'
sys.kitty_ssl_env_var = 'SSL_CERT_DIR'
def main():

View File

@@ -1,2 +1,27 @@
#!/usr/bin/env bash
cloc --exclude-list-file <(echo -e 'kitty/wcwidth-std.h\nkitty/glfw.c\nkitty/keys.h\nkitty/charsets.c\nkitty/unicode-data.c\nkitty/key_encoding.py\nkitty/rgb.py\nkitty/gl.h\nkitty/gl-wrapper.h\nkitty/gl-wrapper.c\nkitty/khrplatform.h\nkitty/glfw-wrapper.h\nkitty/glfw-wrapper.c\nkitty/emoji.h\nkittens/unicode_input/names.h') kitty kittens
#!/usr/bin/env python
import subprocess
files_to_exclude = '''\
kitty/wcwidth-std.h
kitty/glfw.c
kitty/keys.h
kitty/charsets.c
kitty/unicode-data.c
kitty/key_encoding.py
kitty/rgb.py
kitty/gl.h
kitty/gl-wrapper.h
kitty/gl-wrapper.c
kitty/glfw-wrapper.h
kitty/glfw-wrapper.c
kitty/emoji.h
kittens/unicode_input/names.h
kitty/parse-graphics-command.h
'''
p = subprocess.Popen([
'cloc', '--exclude-list-file', '/dev/stdin', 'kitty', 'kittens'
], stdin=subprocess.PIPE)
p.communicate(files_to_exclude.encode('utf-8'))
raise SystemExit(p.wait())

View File

@@ -78,6 +78,8 @@ body div.document {
div.sphinxsidebar {
font-size: inherit;
line-height: inherit;
max-height: 100%;
overflow-y: auto;
}
#sidebartoc li {

View File

@@ -29,7 +29,7 @@ Build-time dependencies:
* gcc or clang
* pkg-config
* For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for:
``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, ``libcanberra-dev`` and ``libpython-dev``.
``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, and ``libpython-dev``,
if they are not already installed by your distro.
Install and run from source

View File

@@ -4,6 +4,200 @@ Changelog
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
To update |kitty|, :doc:`follow the instructions <binary>`.
0.16.0 [2020-01-28]
--------------------
- A new :doc:`marks` feature that allows highlighting and scrolling to arbitrary
text in the terminal window.
- hints kitten: Allow pressing :sc:`goto_file_line` to quickly open
the selected file at the selected line in vim or a configurable editor (:iss:`2268`)
- Allow having more than one full height window in the :code:`tall` layout
(:iss:`2276`)
- Allow choosing OpenType features for individual fonts via the
:opt:`font_features` option. (:pull:`2248`)
- Wayland: Fix a freeze in rare circumstances when having multiple OS Windows
(:iss:`2307` and :iss:`1722`)
- Wayland: Fix window titles being set to very long strings on the order of 8KB
causing a crash (:iss:`1526`)
- Add an option :opt:`force_ltr` to turn off the display of text in RTL scripts
in right-to-left order (:pull:`2293`)
- Allow opening new tabs/windows before the current tab/window as well as after
it with the :option:`launch --location` option.
- Add a :opt:`resize_in_steps` option that can be used to resize the OS window
in steps as large as character cells (:pull:`2131`)
- When triple-click+dragging to select multiple lines, extend the selection
of the first line to match the rest on the left (:pull:`2284`)
- macOS: Add a :code:`titlebar-only` setting to
:opt:`hide_window_decorations` to only hide the title bar (:pull:`2286`)
- Fix a segfault when using :option:`kitty --debug-config` with maps (:iss:`2270`)
- ``goto_tab`` now maps numbers larger than the last tab to the last tab
(:iss:`2291`)
- Fix URL detection not working for urls of the form scheme:///url
(:iss:`2292`)
- When windows are semi-transparent and all contain graphics, correctly render
them. (:iss:`2310`)
0.15.1 [2019-12-21]
--------------------
- Fix a crash/incorrect rendering when detaching a window in some circumstances
(:iss:`2173`)
- hints kitten: Add an option :option:`kitty +kitten hints --ascending` to
control if the hints numbers increase or decrease from top to bottom
- Fix :opt:`background_opacity` incorrectly applying to selected text and
reverse video text (:iss:`2177`)
- Add a new option :opt:`tab_bar_background` to specify a different color
for the tab bar (:iss:`2198`)
- Add a new option :opt:`active_tab_title_template` to specify a different
template for active tab titles (:iss:`2198`)
- Fix lines at the edge of the window at certain windows sizes when drawing
images on a transparent window (:iss:`2079`)
- Fix window not being rendered for the first time until some input has been
received from child process (:iss:`2216`)
0.15.0 [2019-11-27]
--------------------
- Add a new action :ref:`detach_window <detach_window>` that can be used to move the current
window into a different tab (:iss:`1310`)
- Add a new action :doc:`launch <launch>` that unifies launching of processes
in new kitty windows/tabs.
- Add a new style ``powerline`` for tab bar rendering, see :opt:`tab_bar_style` (:pull:`2021`)
- Allow changing colors by mapping a keyboard shortcut to read a kitty config
file with color definitions. See the :doc:`FAQ <faq>` for details
(:iss:`2083`)
- hints kitten: Allow completely customizing the matching and actions performed
by the kitten using your own script (:iss:`2124`)
- Wayland: Fix key repeat not being stopped when focus leaves window. This is
expected behavior on Wayland, apparently (:iss:`2014`)
- When drawing unicode symbols that are followed by spaces, use multiple cells
to avoid resized or cut-off glyphs (:iss:`1452`)
- diff kitten: Allow diffing remote files easily via ssh (:iss:`727`)
- unicode input kitten: Add an option :option:`kitty +kitten unicode_input
--emoji-variation` to control the presentation variant of selected emojis
(:iss:`2139`)
- Add specialised rendering for a few more box powerline and unicode symbols
(:pull:`2074` and :pull:`2021`)
- Add a new socket only mode for :opt:`allow_remote_control`. This makes
it possible for programs running on the local machine to control kitty
but not programs running over ssh.
- hints kitten: Allow using named groups in the regular expression. The named
groups are passed to the invoked program for further processing.
- Fix a regression in 0.14.5 that caused rendering of private use glyphs
with and without spaces to be identical (:iss:`2117`)
- Wayland: Fix incorrect scale used when first creating an OS window
(:iss:`2133`)
- macOS: Disable mouse hiding by default as getting it to work robustly
on Cocoa is too much effort (:iss:`2158`)
0.14.6 [2019-09-25]
---------------------
- macOS: Fix a regression in the previous release that caused a crash when
pressing a unprintable key, such as the POWER key (:iss:`1997`)
- Fix a regression in the previous release that caused kitty to not always
respond to DPI changes (:pull:`1999`)
0.14.5 [2019-09-23]
---------------------
- Implement a hack to (mostly) preserve tabs when cat-ting a file with them and then
copying the text or passing screen contents to another program (:iss:`1829`)
- When all visible windows have the same background color, use that as the
color for the global padding, instead of the configured background color
(:iss:`1957`)
- When resetting the terminal, also reset parser state, this allows easy
recovery from incomplete escape codes (:iss:`1961`)
- Allow mapping keys commonly found on European keyboards (:pull:`1928`)
- Fix incorrect rendering of some symbols when followed by a space while using
the PowerLine font which does not have a space glyph (:iss:`1225`)
- Linux: Allow using fonts with spacing=90 in addition to fonts with
spacing=100 (:iss:`1968`)
- Use selection foreground color for underlines as well (:iss:`1982`)
0.14.4 [2019-08-31]
---------------------
- hints kitten: Add a :option:`kitty +kitten hints --alphabet` option to
control what alphabets are used for hints (:iss:`1879`)
- hints kitten: Allow specifying :option:`kitty +kitten hints --program`
multiple times to run multiple programs (:iss:`1879`)
- Add a :opt:`kitten_alias` option that can be used to alias kitten invocation
for brevity and to change kitten option defaults globally (:iss:`1879`)
- macOS: Add an option :opt:`macos_show_window_title_in` to control
showing the window title in the menubar/titlebar (:pull:`1837`)
- macOS: Allow drag and drop of text from other applications into kitty
(:pull:`1921`)
- When running kittens, use the colorscheme of the current window
rather than the configured colorscheme (:iss:`1906`)
- Don't fail to start if running the shell to read the EDITOR env var fails
(:iss:`1869`)
- Disable the ``liga`` and ``dlig`` OpenType features for broken fonts
such as Nimbus Mono.
- Fix a regression that broke setting background_opacity via remote control
(:iss:`1895`)
- Fix piping PNG images into the icat kitten not working (:iss:`1920`)
- When the OS returns a fallback font that does not actually contain glyphs
for the text, do not exhaust the list of fallback fonts (:iss:`1918`)
- Fix formatting attributes not reset across line boundaries when passing
buffer as ANSI (:iss:`1924`)
0.14.3 [2019-07-29]
---------------------
@@ -192,7 +386,7 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- macOS: Fix :kbd:`cmd+period` key not working (:iss:`1318`)
- macOS: Add an option :opt:`macos_show_window_title_in_menubar` to not
- macOS: Add an option `macos_show_window_title_in_menubar` to not
show the current window title in the menu-bar (:iss:`1066`)
- macOS: Workaround for cocoa bug that could cause the mouse cursor to become

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fileencoding=utf-8
#
# Configuration file for the Sphinx documentation builder.
#
@@ -243,7 +243,17 @@ def add_html_context(app, pagename, templatename, context, *args):
# CLI docs {{{
def write_cli_docs(all_kitten_names):
from kitty.launch import options_spec as launch_options_spec
from kitty.cli import option_spec_as_rst
with open('generated/launch.rst', 'w') as f:
f.write(option_spec_as_rst(
appname='launch', ospec=launch_options_spec, heading_char='_',
message='''\
Launch an arbitrary program in a new kitty window/tab. Note that
if you specify a program-to-run you can use the special placeholder
:code:`@selection` which will be replaced by the current selection.
'''
))
with open('generated/cli-kitty.rst', 'w') as f:
f.write(option_spec_as_rst(appname='kitty').replace(
'kitty --to', 'kitty @ --to'))

View File

@@ -63,6 +63,18 @@ Really, the correct solution for this is to convince the OpenSSH maintainers to
have ssh do this automatically, if possible, when connecting to a server, so that
all terminals work transparently.
If the server is running FreeBSD, or another system that relies on termcap
rather than terminfo, you will need to convert the terminfo file on your local
machine by running (on local machine with |kitty|)::
infocmp -C xterm-kitty
The output of this command is the termcap description, which should be appended
to :file:`/usr/share/misc/termcap` on the remote server. Then run the following
command to apply your change (on the server)::
cap_mkdb /usr/share/misc/termcap
Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
-------------------------------------------------------------------------------------------------
@@ -97,8 +109,13 @@ How do I change the colors in a running kitty instance?
You can either use the
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands>`_
to set colors or you can enable :doc:`remote control <remote-control>`
for |kitty| and use :ref:`at_set-colors`.
to set colors or you can define keyboard shortcuts to set colors, for example::
map f1 set_colors --configured /path/to/some/config/file/colors.conf
Or you can enable :doc:`remote control <remote-control>` for |kitty| and use :ref:`at_set-colors`.
The shortcut mapping technique has the same syntax as the remote control
command, for details, see :ref:`at_set-colors`.
A list of pre-made color themes for kitty is available at:
`kitty-themes <https://github.com/dexpota/kitty-themes>`_
@@ -152,7 +169,32 @@ 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
monospace. On Linux you can list all monospace fonts with::
fc-list : family spacing | grep spacing=100
fc-list : family spacing | grep -e spacing=100 -e spacing=90
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
monospace font does not have ``spacing=100`` you can override it by using the
following :file:`~/.config/fontconfig/fonts.conf`::
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<match target="scan">
<test name="family">
<string>Your Font Family Name</string>
</test>
<edit name="spacing">
<int>100</int>
</edit>
</match>
</fontconfig>
After creating (or modifying) this file, you may need to run the following
command to rebuild your fontconfig cache::
fc-cache -r
Then, the font will be available in ``kitty list-fonts``.
How can I assign a single global shortcut to bring up the kitty terminal?
@@ -172,7 +214,7 @@ For example::
map alt+s send_text all \x13
This maps :kbd:`alt+s`` to :kbd:`ctrl+s`. To figure out what bytes to use for
This maps :kbd:`alt+s` to :kbd:`ctrl+s`. To figure out what bytes to use for
the :sc:`send_text <send_text>` you can use the ``showkey`` utility. Run::
showkey -a

View File

@@ -107,7 +107,8 @@ features of the graphics protocol:
sys.stdout.flush()
cmd.clear()
write_chunked({'a': 'T', 'f': 100}, open(sys.argv[-1], 'rb').read())
with open(sys.argv[-1], 'rb') as f:
write_chunked({'a': 'T', 'f': 100}, f.read())
Save this script as :file:`png.py`, then you can use it to display any PNG
@@ -255,7 +256,10 @@ sequence of escape codes to the terminal emulator::
Note that only the first escape code needs to have the full set of control
codes such as width, height, format etc. Subsequent chunks must have
only the ``m`` key. The client **must** finish sending all chunks for a single image
before sending any other graphics related escape codes.
before sending any other graphics related escape codes. Note that the cursor
position used to display the image **must** be the position when the final chunk is
received. Finally, terminals must not display anything, until the entire sequence is
received and validated.
Detecting available transmission mediums
@@ -330,7 +334,9 @@ Finally, you can specify the image *z-index*, i.e. the vertical stacking order.
placed in the same location with different z-index values will be blended if
they are semi-transparent. You can specify z-index values using the ``z`` key.
Negative z-index values mean that the images will be drawn under the text. This
allows rendering of text on top of images.
allows rendering of text on top of images. Negative z-index values below
INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background
colors.
Deleting images
---------------------
@@ -413,7 +419,7 @@ Key Value Default Description
``Y`` Positive integer ``0`` The y-offset within the first cell at which to start displaying the image
``c`` Positive integer ``0`` The number of columns to display the image over
``r`` Positive integer ``0`` The number of rows to display the image over
``z`` Integer ``0`` The *z-index* vertical stacking order of the image
``z`` 32-bit integer ``0`` The *z-index* vertical stacking order of the image
**Keys for deleting images**
-----------------------------------------------------------
``d`` Single character. ``a`` What to delete.

View File

@@ -53,13 +53,13 @@ Quickstart
--------------
Pre-built binaries of |kitty| are available for both macOS and Linux.
See the :doc:`binary install instructions </binary>`. You can also
See the :doc:`binary install instructions </binary>`. You can
:doc:`build from source </build>`.
You can also use your favorite package manager to install the |kitty| package.
|kitty| packages are available for:
`macOS with Homebrew (Cask) <https://formulae.brew.sh/cask/kitty>`_,
`macOS and Linux with Nix <https://nixos.org/nixos/packages.html#kitty>`_,
`macOS and Linux with Nix <https://nixos.org/nixos/packages.html?channel=nixpkgs-unstable&query=kitty>`_,
`Ubuntu <https://launchpad.net/ubuntu/+source/kitty>`_,
`Debian <https://packages.debian.org/buster/kitty>`_,
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/kitty>`_,
@@ -173,6 +173,19 @@ You can also define a shortcut to switch to the previously active window::
``nth_window`` will focus the nth window for positive numbers and the
previously active windows for negative numbers.
.. _detach_window:
You can define shortcuts to detach the current window and
move it to another tab or another OS window::
map ctrl+f2 detach_window # moves the window into a new OS window
map ctrl+f3 detach_window new-tab # moves the window into a new Tab
map ctrl+f4 detach_window ask # asks which tab to move the window into
Similarly, you can detach the current tab, with::
map ctrl+f2 detach_tab # moves the tab into a new OS window
map ctrl+f4 detach_tab ask # asks which OS Window to move the tab into
Other keyboard shortcuts
----------------------------------
@@ -211,11 +224,11 @@ using the :sc:`new_window` key combination.
Currently, there are five layouts available,
* **Stack** -- Only a single maximized window is shown at a time
* **Tall** -- One window is shown full height on the left, the rest of the windows are shown one below the other on the right
* **Fat** -- One window is shown full width on the top, the rest of the windows are shown side-by-side on the bottom
* **Fat** -- One (or optionally more) windows are shown full width on the top, the rest of the windows are shown side-by-side on the bottom
* **Grid** -- All windows are shown in a grid
* **Horizontal** -- All windows are shown side-by-side
* **Stack** -- Only a single maximized window is shown at a time
* **Tall** -- One (or optionally more) windows are shown full height on the left, the rest of the windows are shown one below the other on the right
* **Vertical** -- All windows are shown one below the other
You can switch between layouts using the :sc:`next_layout` key combination. You can
@@ -243,13 +256,15 @@ the resizing increment (a positive integer that defaults to 1).
Some layouts take options to control their behavior. For example, the ``fat``
and ``tall`` layouts accept the ``bias`` option to control how the available
space is split up. To specify the option, in :opt:`kitty.conf <enabled_layouts>` use::
and ``tall`` layouts accept the ``bias`` and ``full_size`` options to control
how the available space is split up.
To specify the option, in :opt:`kitty.conf <enabled_layouts>` use::
enabled_layouts tall:bias=70
enabled_layouts tall:bias=70;full_size=2
This will make the tall window occupy ``70%`` of available width. ``bias`` can be
any number between 10 and 90.
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
and 90.
Writing a new layout only requires about a hundred lines of code, so if there
is some layout you want, take a look at `layout.py
@@ -402,7 +417,7 @@ comfortably within the pager.
Additionally, you can pipe the contents of the scrollback buffer to an
arbitrary, command running in a new window, tab or overlay, for example::
map f1 pipe @ansi window less +G -R
map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting less +G -R
Would open the scrollback buffer in a new window when you press the :kbd:`F1`
key. See :sc:`show_scrollback` for details.
@@ -428,6 +443,14 @@ internal buffer named ``a`` and :kbd:`F2` to paste from that buffer. The buffer
names are arbitrary strings, so you can define as many such buffers as you
need.
Marks
-------------
kitty has the ability to mark text on the screen based on regular expressions.
This can be useful to highlight words or phrases when browsing output from long
running programs or similar. To learn how this feature works, see :doc:`marks`.
Frequently Asked Questions
---------------------------------
@@ -478,7 +501,8 @@ completions happens after the call to :file:`compinit`.
fish
~~~~~~~~
Add the following to your :file:`~/.config/fish/config.fish`
For versions of fish earlier than 3.0.0, add the following to your
:file:`~/.config/fish/config.fish`. Later versions source completions by default.
.. code-block:: sh

View File

@@ -20,6 +20,10 @@ import tempfile
py3 = sys.version_info[0] > 2
is64bit = platform.architecture()[0] == '64bit'
is_macos = 'darwin' in sys.platform.lower()
if is_macos:
mac_ver = tuple(map(int, platform.mac_ver()[0].split('.')))
if mac_ver[:2] < (10, 12):
raise SystemExit('Your version of macOS is too old, at least 10.12 is required')
try:
__file__
@@ -225,7 +229,8 @@ def script_launch():
def update_intaller_wrapper():
# To run: python3 -c "import runpy; runpy.run_path('installer.py', run_name='update_wrapper')" installer.sh
src = open(__file__, 'rb').read().decode('utf-8')
with open(__file__, 'rb') as f:
src = f.read().decode('utf-8')
wrapper = sys.argv[-1]
with open(wrapper, 'r+b') as f:
raw = f.read().decode('utf-8')

View File

@@ -128,7 +128,27 @@ layout, by simply adding the line::
boss.toggle_fullscreen()
to the ``handle_result()`` function, above.
To the ``handle_result()`` function, above.
Debugging kittens
--------------------
The part of the kitten that runs in ``main()`` is just a normal program and
the output of print statements will be visible in the kitten window. Or
alternately, you can use::
from kittens.tui.loop import debug
debug('whatever')
The ``debug()`` function is just like ``print()`` except that the output
will appear in the ``STDOUT`` of the kitty process inside which the kitten is
running.
The ``handle_result()`` part of the kitten runs inside the kitty process.
The output of print statements will go to the ``STDOUT`` of the kitty process.
So if you run kitty from another kitty instance, the output will be visible
in the first kitty instance.
.. _external_kittens:

View File

@@ -18,11 +18,71 @@ select anything that looks like a path or filename and then insert it into the
terminal, very useful for picking files from the output of a ``git`` or ``ls`` command and
adding them to the command line for the next command.
You can also press :sc:`goto_file_line` to select anything that looks
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
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}
will open the selected file in a new tab inside neovim when you press
:kbd:`ctrl+g`.
The hints kitten is very powerful to see more detailed help on its various
options and modes of operation, see below. You can use these options to
create mappings in :file:`kitty.conf` to select various different text
snippets. See :sc:`insert_selected_path` for examples.
Completely customizing the matching and actions of the kitten
---------------------------------------------------------------
The hints kitten supports writing simple python scripts that can be used to
completely customize how it finds matches and what happens when a match is
selected. This allows the hints kitten to provide the user interface, while
you can provide the logic for finding matches and performing actions on them.
This is best illustrated with an example. Create the file
:file:`custom-hints.py` in the kitty config directory with the following
contents:
.. code-block:: python
import re
def mark(text, args, Mark, extra_cli_args, *a):
# This function is responsible for finding all
# matching text. extra_cli_args are any extra arguments
# passed on the command line when invoking the kitten.
# We mark all individual word for potential selection
for idx, m in enumerate(re.finditer(r'\w+', text)):
start, end = m.span()
mark_text = text[start:end].replace('\n', '').replace('\0', '')
# The empty dictionary below will be available as groupdicts
# in handle_result() and can contain arbitrary data.
yield Mark(idx, start, end, mark_text, {})
def handle_result(args, data, target_window_id, boss, extra_cli_args, *a):
# This function is responsible for performing some
# action on the selected text.
# matches is a list of the selected entries and groupdicts contains
# the arbitrary data associated with each entry in mark() above
matches, groupdicts = [], []
for m, g in zip(data['match'], data['groupdicts']):
if m:
matches.append(m), groupdicts.append(g)
for word, match_data in zip(matches, groupdicts):
# Lookup the word in a dictionary, the open_url function
# will open the provided url in the system browser
boss.open_url(f'https://www.google.com/search?q=define:{word}')
Now run kitty with::
kitty -o 'map f1 kitten hints --customize-processing custom-hints.py'
When you press the :kbd:`F1` key you will be able to select a word to
look it up in the Google dictionary.
Command Line Interface
-------------------------

View File

@@ -22,3 +22,8 @@ In :guilabel:`Name` mode you instead type words from the character name and use
keys/tab to select the character from the displayed matches. You can also type
a leading period and the index for the match if you don't like to use arrow
keys.
Command Line Interface
-------------------------
.. include:: ../generated/cli-kitten-unicode_input.rst

56
docs/launch.rst Normal file
View File

@@ -0,0 +1,56 @@
Launching programs in new windows/tabs
========================================
.. program:: launch
|kitty| has a :code:`launch` action that can be used to run arbitrary programs
in news windows/tabs. It can be mapped to user defined shortcuts in kitty.conf.
It is very powerful and allows sending the contents of
the current window to the launched program, as well as many other options.
In the simplest form, you can use it to open a new kitty window running the
shell, as shown below::
map f1 launch
To run a different program simply pass the command line as arguments to
launch::
map f1 launch vim path/to/some/file
To open a new window with the same working directory as the currently
active window::
map f1 launch --cwd=current
To open the new window in a new tab::
map f1 launch --type=tab
To pass the contents of the current screen and scrollback to the started process::
map f1 launch --stdin-source=@screen_scrollback less
There are many more powerful options, refer to the complete list below.
The piping environment
--------------------------
When using :option:`launch --stdin-source`, the program to which the data is
piped has a special environment variable declared, ``KITTY_PIPE_DATA`` whose
contents are::
KITTY_PIPE_DATA={scrolled_by}:{cursor_x},{cursor_y}:{lines},{columns}
where ``scrolled_by`` is the number of lines kitty is currently scrolled by,
``cursor_(x|y)`` is the position of the cursor on the screen with ``(1,1)``
being the top left corner and ``{lines},{columns}`` being the number of rows
and columns of the screen.
Syntax reference
------------------
.. include:: /generated/launch.rst

122
docs/marks.rst Normal file
View File

@@ -0,0 +1,122 @@
Marks
=================
kitty has the ability to mark text on the screen based on regular expressions.
This can be useful to highlight words or phrases when browsing output from long
running programs or similar. Lets start with a few examples:
Suppose we want to be able to highlight the word ERROR in the current window.
Add the following to :file:`kitty.conf`::
map f1 toggle_marker text 1 ERROR
Now when you press :kbd:`F1` all instances of the word :code:`ERROR` will be
highlighted. To turn off the highlighting, press :kbd:`F1` again.
If you want to make it case-insensitive, use::
map f1 toggle_marker itext 1 ERROR
To make it match only complete words, use::
map f1 toggle_marker regex 1 \bERROR\b
Suppose you want to highlight both :code:`ERROR` and :code:`WARNING`, case
insensitively::
map f1 toggle_marker iregex 1 \bERROR\b 2 \bWARNING\b
kitty supports up to 3 mark groups (the numbers in the commands above). You
can control the colors used for these groups in :file:`kitty.conf` with::
mark1_foreground red
mark1_background gray
mark2_foreground green
...
.. note::
For performance reasons, matching is done per line only, and only when that line is
altered in any way. So you cannot match text that stretches across multiple
lines.
Creating markers dynamically
---------------------------------
If you want to create markers dynamically rather than pre-defining them in
:file:`kitty.conf` you can do so as follows::
map f1 create_marker
map f2 remove_marker
Then pressing :kbd:`F1` will allow you to enter the marker definition and set
it and pressing :kbd:`F2` will remove the marker.
You can also use the facilities for :doc:`remote-control` to dynamically
add/remove markers.
Scrolling to marks
--------------------
kitty has an action to scroll to the next line that contains a mark. You can
use it by mapping it to some shortcut in :file:`kitty.conf`::
map ctrl+p scroll_to_mark prev
map ctrl+n scroll_to_mark next
Then pressing :kbd:`ctrl+p` will scroll to the first line in the scrollback
buffer above the current top line that contains a mark. Pressing :kbd:`ctrl+n`
will scroll to show the first line below the current last line that contains
a mark. If you wish to jump to a mark of a specific type, you can add that to
the mapping::
map ctrl+1 scroll_to_mark prev 1
Which will scroll only to marks of type 1.
The full syntax for creating marks
-------------------------------------
The syntax of the :code:`toggle_marker` command is::
toggle_marker <marker-type> <specification>
Here :code:`marker-type` is one of:
* :code:`text` - simple substring matching
* :code:`itext` - case-insensitive substring matching
* :code:`regex` - A python regular expression
* :code:`iregex` - A case-insensitive python regular expression
* :code:`function` - An arbitrary function defined in a python file, see
:ref:`marker_funcs`.
.. _marker_funcs:
Arbitrary marker functions
-----------------------------
You can create your own marker functions. Create a python file named
:file:`mymarker.py` and in it create a :code:`marker` function. This
function receives the text of the line as input and must yield three numbers,
the starting character position, the ending character position and the mark
group (1-3). For example:
.. code-block::
def marker(text):
# Function to highlight the letter X
for i, ch in enumerate(text):
if ch.lower() == 'x':
yield i, i, 3
Save this file somewhere and in :file:`kitty.conf`, use::
map f1 toggle_marker function /path/to/mymarker.py
If you save the file in the kitty config directory, you can use::
map f1 toggle_marker function mymarker.py

View File

@@ -1,6 +1,9 @@
Working with the screen and history buffer contents
======================================================
.. warning::
The pipe action has been deprecated in favor of the
:doc:`launch <launch>` action which is more powerful.
You can pipe the contents of the current screen and history buffer as
:file:`STDIN` to an arbitrary program using the ``pipe`` function. The program
@@ -56,6 +59,9 @@ Input placeholders
There are various different kinds of placeholders
``@selection``
Plain text, currently selected text
``@text``
Plain text, current screen + scrollback buffer

View File

@@ -2,7 +2,7 @@ Documentation for the kitty remote control protocol
======================================================
The kitty remote control protocol is a simple protocol that involves sending
data to kitty in the form of JSON. Any individual command ot kitty has the
data to kitty in the form of JSON. Any individual command of kitty has the
form::
<ESC>P@kitty-cmd<JSON object><ESC>\
@@ -21,7 +21,7 @@ standalone client, use the kitty version that you are developing against. Using
a version greater than the version of the kitty instance you are talking to,
will cause a failure.
Set ``no_response`` to True if you dont want a response from kitty.
Set ``no_response`` to True if you don't want a response from kitty.
The optional payload is a JSON object that is specific to the actual command being sent.
The fields in the object for every command are documented below.

View File

@@ -126,7 +126,7 @@ If you do not want to allow all programs running in |kitty| to control it, you c
enable remote control for only some |kitty| windows. Simply create a shortcut
such as::
map ctrl+k new_window @ some_program
map ctrl+k launch --allow-remote-control some_program
Then programs running in windows created with that shortcut can use ``kitty @``
to control kitty. Note that any program with the right level of permissions can

View File

@@ -29,10 +29,12 @@ def get_data(fname, folder='UCD'):
bn = os.path.basename(url)
local = os.path.join('/tmp', bn)
if os.path.exists(local):
data = open(local, 'rb').read()
with open(local, 'rb') as f:
data = f.read()
else:
data = urlopen(url).read()
open(local, 'wb').write(data)
with open(local, 'wb') as f:
f.write(data)
for line in data.decode('utf-8').splitlines():
line = line.strip()
if line and not line.startswith('#'):
@@ -41,6 +43,7 @@ def get_data(fname, folder='UCD'):
# Map of class names to set of codepoints in class
class_maps = {}
all_symbols = set()
name_map = {}
word_search_map = defaultdict(set)
zwj = 0x200d
@@ -87,6 +90,8 @@ def parse_ucd():
not_assigned.discard(codepoint)
if category.startswith('M'):
marks.add(codepoint)
elif category.startswith('S'):
all_symbols.add(codepoint)
# Some common synonyms
word_search_map['bee'] |= word_search_map['honeybee']
@@ -166,21 +171,20 @@ def write_case(spec, p):
@contextmanager
def create_header(path, include_data_types=True):
f = open(path, 'w')
p = partial(print, file=f)
p('// unicode data, built from the unicode standard on:', date.today())
p('// see gen-wcwidth.py')
if path.endswith('.h'):
p('#pragma once')
if include_data_types:
p('#include "data-types.h"\n')
p('START_ALLOW_CASE_RANGE')
p()
yield p
p()
if include_data_types:
p('END_ALLOW_CASE_RANGE')
f.close()
with open(path, 'w') as f:
p = partial(print, file=f)
p('// unicode data, built from the unicode standard on:', date.today())
p('// see gen-wcwidth.py')
if path.endswith('.h'):
p('#pragma once')
if include_data_types:
p('#include "data-types.h"\n')
p('START_ALLOW_CASE_RANGE')
p()
yield p
p()
if include_data_types:
p('END_ALLOW_CASE_RANGE')
def gen_emoji():
@@ -193,6 +197,7 @@ def gen_emoji():
p('\t\tdefault: return false;')
p('\t}')
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'])):
@@ -202,6 +207,15 @@ def gen_emoji():
p('\t}')
p('\treturn false;\n}')
p('static inline bool\nis_symbol(char_type code) {')
p('\tswitch(code) {')
for spec in get_ranges(list(all_symbols)):
write_case(spec, p)
p('\t\t\treturn true;')
p('\t\tdefault: return false;')
p('\t}')
p('\treturn false;\n}')
def category_test(name, p, classes, comment, static=False, extra_chars=frozenset(), exclude=frozenset()):
static = 'static inline ' if static else ''
@@ -282,7 +296,9 @@ def gen_ucd():
p('combining_type mark_for_codepoint(char_type c) {')
rmap = codepoint_to_mark_map(p, mark_map)
p('}\n')
expected = int(re.search(r'^#define VS15 (\d+)', open('kitty/unicode-data.h').read(), re.M).group(1))
with open('kitty/unicode-data.h') as f:
unicode_data = f.read()
expected = int(re.search(r'^#define VS15 (\d+)', unicode_data, re.M).group(1))
if rmap[0xfe0e] != expected:
raise ValueError('The mark for 0xfe0e has changed, you have to update VS15 to {} and VS16 to {} in unicode-data.h'.format(
rmap[0xfe0e], rmap[0xfe0f]

55
glfw/backend_utils.c vendored
View File

@@ -22,19 +22,6 @@
#define ppoll pollts
#endif
static inline double
monotonic(void) {
struct timespec ts = {0};
#ifdef CLOCK_HIGHRES
clock_gettime(CLOCK_HIGHRES, &ts);
#elif CLOCK_MONOTONIC_RAW
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
#else
clock_gettime(CLOCK_MONOTONIC, &ts);
#endif
return (((double)ts.tv_nsec) / 1e9) + (double)ts.tv_sec;
}
void
update_fds(EventLoopData *eld) {
for (nfds_t i = 0; i < eld->watches_count; i++) {
@@ -109,7 +96,7 @@ update_timers(EventLoopData *eld) {
}
id_type
addTimer(EventLoopData *eld, const char *name, double interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free) {
addTimer(EventLoopData *eld, const char *name, monotonic_t interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free) {
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
return 0;
@@ -117,7 +104,7 @@ addTimer(EventLoopData *eld, const char *name, double interval, int enabled, boo
Timer *t = eld->timers + eld->timers_count++;
t->interval = interval;
t->name = name;
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
t->trigger_at = enabled ? monotonic() + interval : MONOTONIC_T_MAX;
t->repeats = repeats;
t->callback = cb;
t->callback_data = cb_data;
@@ -144,7 +131,7 @@ void
toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
for (nfds_t i = 0; i < eld->timers_count; i++) {
if (eld->timers[i].id == timer_id) {
double trigger_at = enabled ? (monotonic() + eld->timers[i].interval) : DBL_MAX;
monotonic_t trigger_at = enabled ? (monotonic() + eld->timers[i].interval) : MONOTONIC_T_MAX;
if (trigger_at != eld->timers[i].trigger_at) {
eld->timers[i].trigger_at = trigger_at;
update_timers(eld);
@@ -155,7 +142,7 @@ toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
}
void
changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval) {
changeTimerInterval(EventLoopData *eld, id_type timer_id, monotonic_t interval) {
for (nfds_t i = 0; i < eld->timers_count; i++) {
if (eld->timers[i].id == timer_id) {
eld->timers[i].interval = interval;
@@ -165,22 +152,28 @@ changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval) {
}
double
prepareForPoll(EventLoopData *eld, double timeout) {
monotonic_t
prepareForPoll(EventLoopData *eld, monotonic_t timeout) {
for (nfds_t i = 0; i < eld->watches_count; i++) eld->fds[i].revents = 0;
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return timeout;
double now = monotonic(), next_repeat_at = eld->timers[0].trigger_at;
if (!eld->timers_count || eld->timers[0].trigger_at == MONOTONIC_T_MAX) return timeout;
monotonic_t now = monotonic(), next_repeat_at = eld->timers[0].trigger_at;
if (timeout < 0 || now + timeout > next_repeat_at) {
timeout = next_repeat_at <= now ? 0 : next_repeat_at - now;
}
return timeout;
}
static inline struct timespec
calc_time(monotonic_t nsec) {
struct timespec result;
result.tv_sec = nsec / (1000LL * 1000LL * 1000LL);
result.tv_nsec = nsec % (1000LL * 1000LL * 1000LL);
return result;
}
int
pollWithTimeout(struct pollfd *fds, nfds_t nfds, double timeout) {
const long seconds = (long) timeout;
const long nanoseconds = (long) ((timeout - seconds) * 1e9);
struct timespec tv = { seconds, nanoseconds };
pollWithTimeout(struct pollfd *fds, nfds_t nfds, monotonic_t timeout) {
struct timespec tv = calc_time(timeout);
return ppoll(fds, nfds, &tv, NULL);
}
@@ -198,10 +191,10 @@ dispatchEvents(EventLoopData *eld) {
unsigned
dispatchTimers(EventLoopData *eld) {
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return 0;
if (!eld->timers_count || eld->timers[0].trigger_at == MONOTONIC_T_MAX) return 0;
static struct { timer_callback_func func; id_type id; void* data; bool repeats; } dispatches[sizeof(eld->timers)/sizeof(eld->timers[0])];
unsigned num_dispatches = 0;
double now = monotonic();
monotonic_t now = monotonic();
for (nfds_t i = 0; i < eld->timers_count && eld->timers[i].trigger_at <= now; i++) {
eld->timers[i].trigger_at = now + eld->timers[i].interval;
dispatches[num_dispatches].func = eld->timers[i].callback;
@@ -299,12 +292,12 @@ finalizePollData(EventLoopData *eld) {
}
int
pollForEvents(EventLoopData *eld, double timeout) {
pollForEvents(EventLoopData *eld, monotonic_t timeout, watch_callback_func display_callback) {
int read_ok = 0;
timeout = prepareForPoll(eld, timeout);
EVDBG("pollForEvents final timeout: %.3f", timeout);
EVDBG("pollForEvents final timeout: %.3f", monotonic_t_to_s_double(timeout));
int result;
double end_time = monotonic() + timeout;
monotonic_t end_time = monotonic() + timeout;
eld->wakeup_fd_ready = false;
while(1) {
@@ -312,6 +305,7 @@ pollForEvents(EventLoopData *eld, double timeout) {
errno = 0;
result = pollWithTimeout(eld->fds, eld->watches_count, timeout);
int saved_errno = errno;
if (display_callback) display_callback(result, eld->fds[0].revents && eld->watches[0].events, NULL);
dispatchTimers(eld);
if (result > 0) {
dispatchEvents(eld);
@@ -326,6 +320,7 @@ pollForEvents(EventLoopData *eld, double timeout) {
errno = 0;
result = poll(eld->fds, eld->watches_count, -1);
int saved_errno = errno;
if (display_callback) display_callback(result, eld->fds[0].revents && eld->watches[0].events, NULL);
dispatchTimers(eld);
if (result > 0) {
dispatchEvents(eld);

15
glfw/backend_utils.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Wayland - www.glfw.org
// GLFW 3.4 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -25,6 +25,7 @@
//========================================================================
#pragma once
#include "../kitty/monotonic.h"
#include <poll.h>
#include <unistd.h>
#include <stdbool.h>
@@ -55,7 +56,7 @@ typedef struct {
typedef struct {
id_type id;
double interval, trigger_at;
monotonic_t interval, trigger_at;
timer_callback_func callback;
void *callback_data;
GLFWuserdatafreefun free;
@@ -82,14 +83,14 @@ void check_for_wakeup_events(EventLoopData *eld);
id_type addWatch(EventLoopData *eld, const char *name, int fd, int events, int enabled, watch_callback_func cb, void *cb_data);
void removeWatch(EventLoopData *eld, id_type watch_id);
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
id_type addTimer(EventLoopData *eld, const char *name, double interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free);
id_type addTimer(EventLoopData *eld, const char *name, monotonic_t interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free);
void removeTimer(EventLoopData *eld, id_type timer_id);
void removeAllTimers(EventLoopData *eld);
void toggleTimer(EventLoopData *eld, id_type timer_id, int enabled);
void changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval);
double prepareForPoll(EventLoopData *eld, double timeout);
int pollWithTimeout(struct pollfd *fds, nfds_t nfds, double timeout);
int pollForEvents(EventLoopData *eld, double timeout);
void changeTimerInterval(EventLoopData *eld, id_type timer_id, monotonic_t interval);
monotonic_t prepareForPoll(EventLoopData *eld, monotonic_t timeout);
int pollWithTimeout(struct pollfd *fds, nfds_t nfds, monotonic_t timeout);
int pollForEvents(EventLoopData *eld, monotonic_t timeout, watch_callback_func);
unsigned dispatchTimers(EventLoopData *eld);
void finalizePollData(EventLoopData *eld);
bool initPollData(EventLoopData *eld, int display_fd);

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 macOS - www.glfw.org
// GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -27,9 +27,13 @@
//========================================================================
#include "internal.h"
#include "../kitty/monotonic.h"
#include <sys/param.h> // For MAXPATHLEN
#include <pthread.h>
// Needed for _NSGetProgname
#include <crt_externs.h>
// Change to our application bundle's resources directory, if present
//
static void changeToResourcesDirectory(void)
@@ -66,14 +70,119 @@ static void changeToResourcesDirectory(void)
chdir(resourcesPath);
}
// Set up the menu bar (manually)
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
// could go away at any moment, lots of stuff that really should be
// localize(d|able), etc. Add a nib to save us this horror.
//
static void createMenuBar(void)
{
size_t i;
NSString* appName = nil;
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
NSString* nameKeys[] =
{
@"CFBundleDisplayName",
@"CFBundleName",
@"CFBundleExecutable",
};
// Try to figure out what the calling application is called
for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
{
id name = bundleInfo[nameKeys[i]];
if (name &&
[name isKindOfClass:[NSString class]] &&
![name isEqualToString:@""])
{
appName = name;
break;
}
}
if (!appName)
{
char** progname = _NSGetProgname();
if (progname && *progname)
appName = @(*progname);
else
appName = @"GLFW Application";
}
NSMenu* bar = [[NSMenu alloc] init];
[NSApp setMainMenu:bar];
NSMenuItem* appMenuItem =
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
NSMenu* appMenu = [[NSMenu alloc] init];
[appMenuItem setSubmenu:appMenu];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
action:@selector(orderFrontStandardAboutPanel:)
keyEquivalent:@""];
[appMenu addItem:[NSMenuItem separatorItem]];
NSMenu* servicesMenu = [[NSMenu alloc] init];
[NSApp setServicesMenu:servicesMenu];
[[appMenu addItemWithTitle:@"Services"
action:NULL
keyEquivalent:@""] setSubmenu:servicesMenu];
[servicesMenu release];
[appMenu addItem:[NSMenuItem separatorItem]];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
action:@selector(hide:)
keyEquivalent:@"h"];
[[appMenu addItemWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"]
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
[appMenu addItemWithTitle:@"Show All"
action:@selector(unhideAllApplications:)
keyEquivalent:@""];
[appMenu addItem:[NSMenuItem separatorItem]];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
action:@selector(terminate:)
keyEquivalent:@"q"];
NSMenuItem* windowMenuItem =
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
[bar release];
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
[NSApp setWindowsMenu:windowMenu];
[windowMenuItem setSubmenu:windowMenu];
[windowMenu addItemWithTitle:@"Minimize"
action:@selector(performMiniaturize:)
keyEquivalent:@"m"];
[windowMenu addItemWithTitle:@"Zoom"
action:@selector(performZoom:)
keyEquivalent:@""];
[windowMenu addItem:[NSMenuItem separatorItem]];
[windowMenu addItemWithTitle:@"Bring All to Front"
action:@selector(arrangeInFront:)
keyEquivalent:@""];
// TODO: Make this appear at the bottom of the menu (for consistency)
[windowMenu addItem:[NSMenuItem separatorItem]];
[[windowMenu addItemWithTitle:@"Enter Full Screen"
action:@selector(toggleFullScreen:)
keyEquivalent:@"f"]
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
// to get the application menu working properly.
SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
}
// Create key code translation tables
//
static void createKeyTables(void)
{
int scancode;
int keycode;
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
memset(_glfw.ns.key_to_keycode, -1, sizeof(_glfw.ns.key_to_keycode));
_glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
_glfw.ns.keycodes[0x12] = GLFW_KEY_1;
@@ -190,11 +299,11 @@ static void createKeyTables(void)
_glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
_glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
for (scancode = 0; scancode < 256; scancode++)
for (keycode = 0; keycode < 256; keycode++)
{
// Store the reverse translation for faster key name lookup
if (_glfw.ns.keycodes[scancode] >= 0)
_glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
if (_glfw.ns.keycodes[keycode] >= 0)
_glfw.ns.key_to_keycode[_glfw.ns.keycodes[keycode]] = keycode;
}
}
@@ -276,6 +385,17 @@ static bool initializeTIS(void)
return updateUnicodeDataNS();
}
static void
display_reconfigured(CGDirectDisplayID display UNUSED, CGDisplayChangeSummaryFlags flags, void *userInfo UNUSED)
{
if (flags & kCGDisplayBeginConfigurationFlag) {
return;
}
if (flags & kCGDisplaySetModeFlag) {
// GPU possibly changed
}
}
@interface GLFWHelper : NSObject
@end
@@ -294,6 +414,102 @@ static bool initializeTIS(void)
@end // GLFWHelper
// Delegate for application related notifications {{{
@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
@end
@implementation GLFWApplicationDelegate
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
(void)sender;
_GLFWwindow* window;
for (window = _glfw.windowListHead; window; window = window->next)
_glfwInputWindowCloseRequest(window);
return NSTerminateCancel;
}
static GLFWapplicationshouldhandlereopenfun handle_reopen_callback = NULL;
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
{
(void)sender;
if (!handle_reopen_callback) return YES;
if (handle_reopen_callback(flag)) return YES;
return NO;
}
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
{
(void)notification;
_GLFWwindow* window;
for (window = _glfw.windowListHead; window; window = window->next)
{
if (window->context.client != GLFW_NO_API)
[window->context.nsgl.object update];
}
_glfwPollMonitorsNS();
}
static GLFWapplicationwillfinishlaunchingfun finish_launching_callback = NULL;
- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
(void)notification;
if (_glfw.hints.init.ns.menubar)
{
// In case we are unbundled, make us a proper UI application
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
// Menu bar setup must go between sharedApplication and finishLaunching
// in order to properly emulate the behavior of NSApplicationMain
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
{
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
owner:NSApp
topLevelObjects:&_glfw.ns.nibObjects];
}
else
createMenuBar();
}
if (finish_launching_callback)
finish_launching_callback();
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
(void)notification;
[NSApp stop:nil];
CGDisplayRegisterReconfigurationCallback(display_reconfigured, NULL);
_glfwCocoaPostEmptyEvent();
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
(void)aNotification;
CGDisplayRemoveReconfigurationCallback(display_reconfigured, NULL);
}
- (void)applicationDidHide:(NSNotification *)notification
{
(void)notification;
int i;
for (i = 0; i < _glfw.monitorCount; i++)
_glfwRestoreVideoModeNS(_glfw.monitors[i]);
}
@end // GLFWApplicationDelegate
// }}}
@interface GLFWApplication : NSApplication
- (void)tick_callback;
- (void)render_frame_received:(id)displayIDAsID;
@@ -313,6 +529,32 @@ static bool initializeTIS(void)
@end
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void* _glfwLoadLocalVulkanLoaderNS(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef url =
CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));
if (!url)
return NULL;
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfw_dlopen(path);
CFRelease(url);
return handle;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
@@ -335,6 +577,18 @@ is_cmd_period(NSEvent *event, NSEventModifierFlags modifierFlags) {
return false;
}
GLFWAPI GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) {
GLFWapplicationshouldhandlereopenfun previous = handle_reopen_callback;
handle_reopen_callback = callback;
return previous;
}
GLFWAPI GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback) {
GLFWapplicationwillfinishlaunchingfun previous = finish_launching_callback;
finish_launching_callback = callback;
return previous;
}
int _glfwPlatformInit(void)
{
@autoreleasepool {
@@ -345,8 +599,21 @@ int _glfwPlatformInit(void)
toTarget:_glfw.ns.helper
withObject:nil];
if (NSApp)
_glfw.ns.finishedLaunching = true;
[GLFWApplication sharedApplication];
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
if (_glfw.ns.delegate == nil)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to create application delegate");
return false;
}
[NSApp setDelegate:_glfw.ns.delegate];
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
{
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
@@ -385,6 +652,10 @@ int _glfwPlatformInit(void)
if (_glfw.hints.init.ns.chdir)
changeToResourcesDirectory();
// Press and Hold prevents some keys from emitting repeated characters
NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
[[NSNotificationCenter defaultCenter]
addObserver:_glfw.ns.helper
selector:@selector(selectedKeyboardInputSourceChanged:)
@@ -402,7 +673,6 @@ int _glfwPlatformInit(void)
if (!initializeTIS())
return false;
_glfwInitTimerNS();
_glfwInitJoysticksNS();
_glfwPollMonitorsNS();
@@ -531,7 +801,7 @@ typedef struct {
NSTimer *os_timer;
unsigned long long id;
bool repeats;
double interval;
monotonic_t interval;
GLFWuserdatafun callback;
void *callback_data;
GLFWuserdatafun free_callback_data;
@@ -551,7 +821,7 @@ remove_timer_at(size_t idx) {
}
static void schedule_timer(Timer *t) {
t->os_timer = [NSTimer scheduledTimerWithTimeInterval:t->interval repeats:(t->repeats ? YES: NO) block:^(NSTimer *os_timer) {
t->os_timer = [NSTimer scheduledTimerWithTimeInterval:monotonic_t_to_s_double(t->interval) repeats:(t->repeats ? YES: NO) block:^(NSTimer *os_timer) {
for (size_t i = 0; i < num_timers; i++) {
if (timers[i].os_timer == os_timer) {
timers[i].callback(timers[i].id, timers[i].callback_data);
@@ -562,7 +832,7 @@ static void schedule_timer(Timer *t) {
}];
}
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback) {
unsigned long long _glfwPlatformAddTimer(monotonic_t interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback) {
static unsigned long long timer_counter = 0;
if (num_timers >= sizeof(timers)/sizeof(timers[0]) - 1) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
@@ -588,7 +858,7 @@ void _glfwPlatformRemoveTimer(unsigned long long timer_id) {
}
}
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled) {
for (size_t i = 0; i < num_timers; i++) {
if (timers[i].id == timer_id) {
Timer *t = timers + i;

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Cocoa - www.glfw.org
// GLFW 3.4 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Cocoa - www.glfw.org
// GLFW 3.4 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 macOS - www.glfw.org
// GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -146,7 +146,7 @@ static bool modeIsGood(CGDisplayModeRef mode)
// Convert Core Graphics display mode to GLFW video mode
//
static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
CVDisplayLinkRef link)
double fallbackRefreshRate)
{
GLFWvidmode result;
result.width = (int) CGDisplayModeGetWidth(mode);
@@ -154,11 +154,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
if (result.refreshRate == 0)
{
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
if (!(time.flags & kCVTimeIsIndefinite))
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
}
result.refreshRate = (int) round(fallbackRefreshRate);
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
@@ -240,6 +236,30 @@ static bool refreshMonitorScreen(_GLFWmonitor* monitor)
return false;
}
// Returns a fallback refresh rate for when Core Graphics says it is zero
//
static double getFallbackRefreshRate(_GLFWmonitor* monitor)
{
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
double refreshRate = CGDisplayModeGetRefreshRate(mode);
CGDisplayModeRelease(mode);
if (refreshRate == 0.0)
{
CVDisplayLinkRef link = NULL;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
if (!(time.flags & kCVTimeIsIndefinite))
refreshRate = (int) (time.timeScale / (double) time.timeValue);
CVDisplayLinkRelease(link);
}
return refreshRate;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
@@ -328,9 +348,10 @@ void _glfwPollMonitorsNS(void)
if (!name)
name = _glfw_strdup("Unknown");
_GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height);
_GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height);
monitor->ns.displayID = displays[i];
monitor->ns.unitNumber = unitNumber;
monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(monitor);
createDisplayLink(monitor->ns.displayID);
free(name);
@@ -354,14 +375,12 @@ void _glfwPollMonitorsNS(void)
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
{
GLFWvidmode current;
const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current);
const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
if (_glfwCompareVideoModes(&current, best) == 0)
return;
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
const CFIndex count = CFArrayGetCount(modes);
CGDisplayModeRef native = NULL;
@@ -372,7 +391,8 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
if (!modeIsGood(dm))
continue;
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
const GLFWvidmode mode =
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
if (_glfwCompareVideoModes(best, &mode) == 0)
{
native = dm;
@@ -391,7 +411,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
}
CFRelease(modes);
CVDisplayLinkRelease(link);
}
// Restore the previously saved (original) video mode
@@ -454,13 +473,13 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
const NSRect frameRect = [monitor->ns.screen visibleFrame];
if (xpos)
*xpos = frameRect.origin.x;
*xpos = (int)frameRect.origin.x;
if (ypos)
*ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
*ypos = (int)_glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
if (width)
*width = frameRect.size.width;
*width = (int)frameRect.size.width;
if (height)
*height = frameRect.size.height;
*height = (int)frameRect.size.height;
}
@@ -468,9 +487,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{
*count = 0;
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
const CFIndex found = CFArrayGetCount(modes);
GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
@@ -481,7 +497,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
if (!modeIsGood(dm))
continue;
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
const GLFWvidmode mode =
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
for (CFIndex j = 0; j < *count; j++)
{
@@ -498,21 +515,14 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
}
CFRelease(modes);
CVDisplayLinkRelease(link);
return result;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
{
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
*mode = vidmodeFromCGDisplayMode(native, link);
*mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate);
CGDisplayModeRelease(native);
CVDisplayLinkRelease(link);
}
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)

34
glfw/cocoa_platform.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 macOS - www.glfw.org
// GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -36,6 +36,9 @@ typedef void* id;
typedef void* CVDisplayLinkRef;
#endif
// NOTE: Many Cocoa enum values have been renamed and we need to build across
// SDK versions where one is unavailable or the other deprecated
// We use the newer names in code and these macros to handle compatibility
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
#define NSEventMaskAny NSAnyEventMask
@@ -62,12 +65,15 @@ typedef void* CVDisplayLinkRef;
#endif
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long);
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
typedef struct VkMacOSSurfaceCreateInfoMVK
{
VkStructureType sType;
@@ -76,7 +82,16 @@ typedef struct VkMacOSSurfaceCreateInfoMVK
const void* pView;
} VkMacOSSurfaceCreateInfoMVK;
typedef struct VkMetalSurfaceCreateInfoEXT
{
VkStructureType sType;
const void* pNext;
VkMetalSurfaceCreateFlagsEXT flags;
const void* pLayer;
} VkMetalSurfaceCreateInfoEXT;
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMetalSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*);
#include "posix_thread.h"
#include "cocoa_joystick.h"
@@ -144,7 +159,7 @@ typedef struct _GLFWDisplayLinkNS
{
CVDisplayLinkRef displayLink;
CGDirectDisplayID displayID;
double lastRenderFrameRequestedAt;
monotonic_t lastRenderFrameRequestedAt;
} _GLFWDisplayLinkNS;
// Cocoa-specific global data
@@ -153,6 +168,7 @@ typedef struct _GLFWlibraryNS
{
CGEventSourceRef eventSource;
id delegate;
bool finishedLaunching;
bool cursorHidden;
TISInputSourceRef inputSource;
IOHIDManagerRef hidManager;
@@ -160,11 +176,12 @@ typedef struct _GLFWlibraryNS
id helper;
id keyUpMonitor;
id keyDownMonitor;
id nibObjects;
char keyName[64];
char text[256];
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
short int key_to_keycode[GLFW_KEY_LAST + 1];
char* clipboardString;
CGPoint cascadePoint;
// Where to place the cursor when re-enabled
@@ -195,6 +212,7 @@ typedef struct _GLFWmonitorNS
CGDisplayModeRef previousMode;
uint32_t unitNumber;
id screen;
double fallbackRefreshRate;
} _GLFWmonitorNS;
@@ -215,14 +233,14 @@ typedef struct _GLFWtimerNS
} _GLFWtimerNS;
void _glfwInitTimerNS(void);
void _glfwPollMonitorsNS(void);
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
float _glfwTransformYNS(float y);
void* _glfwLoadLocalVulkanLoaderNS(void);
void _glfwClearDisplayLinks(void);
void _glfwRestartDisplayLinks(void);
void _glfwDispatchTickCallback(void);

62
glfw/cocoa_time.c vendored
View File

@@ -1,62 +0,0 @@
//========================================================================
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h"
#include <mach/mach_time.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialise timer
//
void _glfwInitTimerNS(void)
{
mach_timebase_info_data_t info;
mach_timebase_info(&info);
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
uint64_t _glfwPlatformGetTimerValue(void)
{
return mach_absolute_time();
}
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.timer.ns.frequency;
}

File diff suppressed because it is too large Load Diff

2
glfw/context.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>

5
glfw/dbus_glfw.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 XKB - www.glfw.org
// GLFW 3.4 XKB - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
//
@@ -27,6 +27,7 @@
#include "internal.h"
#include "dbus_glfw.h"
#include "../kitty/monotonic.h"
#include <stdlib.h>
#include <string.h>
@@ -107,7 +108,7 @@ on_dbus_timer_ready(id_type timer_id UNUSED, void *data) {
static dbus_bool_t
add_dbus_timeout(DBusTimeout *timeout, void *data) {
int enabled = dbus_timeout_get_enabled(timeout) ? 1 : 0;
double interval = ((double)dbus_timeout_get_interval(timeout)) / 1000.0;
monotonic_t interval = ms_to_monotonic_t(dbus_timeout_get_interval(timeout));
if (interval < 0) return FALSE;
id_type timer_id = addTimer(dbus_data->eld, data, interval, enabled, true, on_dbus_timer_ready, timeout, NULL);
if (!timer_id) return FALSE;

2
glfw/dbus_glfw.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 XKB - www.glfw.org
// GLFW 3.4 XKB - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
//

33
glfw/egl_context.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 EGL - www.glfw.org
// GLFW 3.4 EGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -123,23 +123,24 @@ static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
continue;
#if defined(_GLFW_X11)
XVisualInfo vi = {0};
// Only consider EGLConfigs with associated Visuals
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
if (!vi.visualid)
continue;
if (desired->transparent)
{
int count;
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
VisualIDMask, &vi,
&count);
if (vis)
XVisualInfo vi = {0};
// Only consider EGLConfigs with associated Visuals
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
if (!vi.visualid)
continue;
if (desired->transparent)
{
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
XFree(vis);
int count;
XVisualInfo* vis =
XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
if (vis)
{
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
XFree(vis);
}
}
}
#endif // _GLFW_X11

2
glfw/egl_context.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 EGL - www.glfw.org
// GLFW 3.4 EGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View File

@@ -8,11 +8,7 @@ import re
import sys
_plat = sys.platform.lower()
is_macos = 'darwin' in _plat
is_freebsd = 'freebsd' in _plat
is_netbsd = 'netbsd' in _plat
is_dragonflybsd = 'dragonfly' in _plat
is_bsd = is_freebsd or is_netbsd or is_dragonflybsd
is_linux = 'linux' in _plat
base = os.path.dirname(os.path.abspath(__file__))
@@ -23,31 +19,24 @@ def wayland_protocol_file_name(base, ext='c'):
def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
ans = env.copy()
if not is_macos:
ans.cflags.append('-pthread')
ans.ldpaths.append('-pthread')
ans.cflags.append('-fpic')
ans.cppflags.append('-D_GLFW_' + module.upper())
ans.cppflags.append('-D_GLFW_BUILD_DLL')
if is_macos:
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
ans.ldpaths.extend(
"-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo".
split()
)
else:
ans.ldpaths.extend('-lrt -lm -ldl'.split())
sinfo = json.load(open(os.path.join(base, 'source-info.json')))
with open(os.path.join(base, 'source-info.json')) as f:
sinfo = json.load(f)
module_sources = list(sinfo[module]['sources'])
if module in ('x11', 'wayland'):
remove = 'linux_joystick.c' if is_bsd else 'null_joystick.c'
remove = 'null_joystick.c' if is_linux else 'linux_joystick.c'
module_sources.remove(remove)
ans.sources = sinfo['common']['sources'] + module_sources
ans.all_headers = [x for x in os.listdir(base) if x.endswith('.h')]
if module in ('x11', 'wayland'):
ans.cflags.append('-pthread')
ans.ldpaths.append('-pthread')
ans.ldpaths.extend('-lrt -lm -ldl'.split())
at_least_version('xkbcommon', 0, 5)
if module == 'x11':
@@ -56,6 +45,7 @@ def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
ans.ldpaths.extend(pkg_config(dep, '--libs'))
elif module == 'cocoa':
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
for f in 'Cocoa IOKit CoreFoundation CoreVideo'.split():
ans.ldpaths.extend(('-framework', f))
@@ -157,7 +147,8 @@ class Function:
def generate_wrappers(glfw_header):
src = open(glfw_header).read()
with open(glfw_header) as f:
src = f.read()
functions = []
first = None
for m in re.finditer(r'^GLFWAPI\s+(.+[)]);\s*$', src, flags=re.MULTILINE):
@@ -174,13 +165,14 @@ def generate_wrappers(glfw_header):
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, void* cocoa_mods)
GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback)
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char* cocoa_key, size_t key_sz, int* cocoa_mods)
void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback)
void* glfwGetX11Display(void)
int32_t glfwGetX11Window(GLFWwindow* window)
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
const char* glfwGetPrimarySelectionString(GLFWwindow* window, void)
int glfwGetXKBScancode(const char* key_name, int case_sensitive)
int glfwGetNativeKeyForName(const char* key_name, int case_sensitive)
void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback)
unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
@@ -194,15 +186,23 @@ const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callbac
p = src.find('*/', p)
preamble = src[p + 2:first]
header = '''\
//
// THIS FILE IS GENERATED BY glfw.py
//
// SAVE YOURSELF SOME TIME, DO NOT MANUALLY EDIT
//
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "monotonic.h"
{}
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id);
typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*);

898
glfw/glfw3.h vendored

File diff suppressed because it is too large Load Diff

2
glfw/glx_context.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 GLX - www.glfw.org
// GLFW 3.4 GLX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>

26
glfw/glx_context.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 GLX - www.glfw.org
// GLFW 3.4 GLX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -153,18 +153,18 @@ typedef struct _GLFWlibraryGLX
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
bool SGI_swap_control;
bool EXT_swap_control;
bool MESA_swap_control;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_create_context;
bool ARB_create_context_profile;
bool ARB_create_context_robustness;
bool EXT_create_context_es2_profile;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
bool SGI_swap_control;
bool EXT_swap_control;
bool MESA_swap_control;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_create_context;
bool ARB_create_context_profile;
bool ARB_create_context_robustness;
bool EXT_create_context_es2_profile;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
} _GLFWlibraryGLX;

31
glfw/ibus_glfw.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 XKB - www.glfw.org
// GLFW 3.4 XKB - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
//
@@ -107,10 +107,14 @@ get_ibus_text_from_message(DBusMessage *msg) {
}
static inline void
send_text(const char *text, int state) {
send_text(const char *text, int ime_state) {
_GLFWwindow *w = _glfwFocusedWindow();
if (w && w->callbacks.keyboard) {
w->callbacks.keyboard((GLFWwindow*) w, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0, text, state);
GLFWkeyevent fake_ev;
_glfwInitializeKeyEvent(&fake_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0);
fake_ev.text = text;
fake_ev.ime_state = ime_state;
w->callbacks.keyboard((GLFWwindow*) w, &fake_ev);
}
}
@@ -393,31 +397,36 @@ ibus_key_state(unsigned int glfw_modifiers, int action) {
void
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
uint32_t handled = 0;
KeyEvent *ev = (KeyEvent*)data;
bool is_release = ev->action == GLFW_RELEASE;
_GLFWIBUSKeyEvent *ev = (_GLFWIBUSKeyEvent*)data;
// Restore key's text from the text embedded in the structure.
ev->glfw_ev.text = ev->__embedded_text;
bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
bool failed = false;
if (errmsg) {
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
failed = true;
} else {
glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID);
debug("IBUS processed scancode: 0x%x release: %d handled: %u\n", ev->keycode, is_release, handled);
debug("IBUS processed native_key: 0x%x release: %d handled: %u\n", ev->glfw_ev.native_key, is_release, handled);
}
glfw_xkb_key_from_ime(ev, handled ? true : false, failed);
free(ev);
}
bool
ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus) {
ibus_process_key(const _GLFWIBUSKeyEvent *ev_, _GLFWIBUSData *ibus) {
if (!check_connection(ibus)) return false;
KeyEvent *ev = malloc(sizeof(KeyEvent));
_GLFWIBUSKeyEvent *ev = calloc(1, sizeof(_GLFWIBUSKeyEvent));
if (!ev) return false;
memcpy(ev, ev_, sizeof(KeyEvent));
uint32_t state = ibus_key_state(ev->glfw_modifiers, ev->action);
memcpy(ev, ev_, sizeof(_GLFWIBUSKeyEvent));
// Put the key's text in a field IN the structure, for proper serialization.
if (ev->glfw_ev.text) strncpy(ev->__embedded_text, ev->glfw_ev.text, sizeof(ev->__embedded_text) - 1);
ev->glfw_ev.text = NULL;
uint32_t state = ibus_key_state(ev->glfw_ev.mods, ev->glfw_ev.action);
if (!glfw_dbus_call_method_with_reply(
ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
3000, key_event_processed, ev,
DBUS_TYPE_UINT32, &ev->ibus_sym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
DBUS_TYPE_UINT32, &ev->ibus_keysym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
&state, DBUS_TYPE_INVALID)) {
free(ev);
return false;

17
glfw/ibus_glfw.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 XKB - www.glfw.org
// GLFW 3.4 XKB - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
//
@@ -27,6 +27,7 @@
#pragma once
#include "internal.h"
#include "dbus_glfw.h"
#include <xkbcommon/xkbcommon.h>
@@ -38,18 +39,16 @@ typedef struct {
} _GLFWIBUSData;
typedef struct {
xkb_keycode_t keycode, ibus_keycode;
xkb_keysym_t keysym, ibus_sym;
unsigned int glfw_modifiers;
int action;
xkb_keycode_t ibus_keycode;
xkb_keysym_t ibus_keysym;
GLFWid window_id;
int glfw_keycode;
char text[64];
} KeyEvent;
GLFWkeyevent glfw_ev;
char __embedded_text[64];
} _GLFWIBUSKeyEvent;
void glfw_connect_to_ibus(_GLFWIBUSData *ibus);
void glfw_ibus_terminate(_GLFWIBUSData *ibus);
void glfw_ibus_set_focused(_GLFWIBUSData *ibus, bool focused);
void glfw_ibus_dispatch(_GLFWIBUSData *ibus);
bool ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus);
bool ibus_process_key(const _GLFWIBUSKeyEvent *ev_, _GLFWIBUSData *ibus);
void glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h);

12
glfw/init.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@@ -201,7 +201,7 @@ _glfwDebug(const char *format, ...) {
{
va_list vl;
fprintf(stderr, "[%.4f] ", glfwGetTime());
fprintf(stderr, "[%.4f] ", monotonic_t_to_s_double(glfwGetTime()));
va_start(vl, format);
vfprintf(stderr, format, vl);
va_end(vl);
@@ -214,10 +214,11 @@ _glfwDebug(const char *format, ...) {
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwInit(void)
GLFWAPI int glfwInit(monotonic_t start_time)
{
if (_glfw.initialized)
return true;
monotonic_start_time = start_time;
memset(&_glfw, 0, sizeof(_glfw));
_glfw.hints.init = _glfwInitHints;
@@ -239,7 +240,6 @@ GLFWAPI int glfwInit(void)
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
_glfw.initialized = true;
_glfw.timer.offset = _glfwPlatformGetTimerValue();
glfwDefaultWindowHints();
@@ -350,13 +350,13 @@ GLFWAPI void glfwStopMainLoop(void) {
}
GLFWAPI unsigned long long glfwAddTimer(
double interval, bool repeats, GLFWuserdatafun callback,
monotonic_t interval, bool repeats, GLFWuserdatafun callback,
void *callback_data, GLFWuserdatafun free_callback)
{
return _glfwPlatformAddTimer(interval, repeats, callback, callback_data, free_callback);
}
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled) {
_glfwPlatformUpdateTimer(timer_id, interval, enabled);
}

385
glfw/input.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -28,6 +28,7 @@
//========================================================================
#include "internal.h"
#include "../kitty/monotonic.h"
#include <assert.h>
#include <float.h>
@@ -256,33 +257,44 @@ static bool parseMapping(_GLFWmapping* mapping, const char* string)
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods)
{
ev->key = key;
ev->native_key = native_key;
ev->action = action;
ev->mods = mods;
ev->text = NULL;
ev->ime_state = 0;
}
// Notifies shared code of a physical key event
//
void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action, int mods, const char* text, int state)
void _glfwInputKeyboard(_GLFWwindow* window, GLFWkeyevent* ev)
{
if (key >= 0 && key <= GLFW_KEY_LAST)
if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST)
{
bool repeated = false;
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
if (ev->action == GLFW_RELEASE && window->keys[ev->key] == GLFW_RELEASE)
return;
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
if (ev->action == GLFW_PRESS && window->keys[ev->key] == GLFW_PRESS)
repeated = true;
if (action == GLFW_RELEASE && window->stickyKeys)
window->keys[key] = _GLFW_STICK;
if (ev->action == GLFW_RELEASE && window->stickyKeys)
window->keys[ev->key] = _GLFW_STICK;
else
window->keys[key] = (char) action;
window->keys[ev->key] = (char) ev->action;
if (repeated)
action = GLFW_REPEAT;
ev->action = GLFW_REPEAT;
}
// FIXME: will need to update ev->virtual_mods here too?
if (window->callbacks.keyboard) {
if (!window->lockKeyMods) mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
window->callbacks.keyboard((GLFWwindow*) window, key, scancode, action, mods, text, state);
if (!window->lockKeyMods) ev->mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
window->callbacks.keyboard((GLFWwindow*) window, ev);
}
}
@@ -439,132 +451,194 @@ const char* _glfwGetKeyName(int key)
switch (key)
{
// Printable keys
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";
case GLFW_KEY_1: return "1";
case GLFW_KEY_2: return "2";
case GLFW_KEY_3: return "3";
case GLFW_KEY_4: return "4";
case GLFW_KEY_5: return "5";
case GLFW_KEY_6: return "6";
case GLFW_KEY_7: return "7";
case GLFW_KEY_8: return "8";
case GLFW_KEY_9: return "9";
case GLFW_KEY_0: return "0";
case GLFW_KEY_SPACE: return "SPACE";
case GLFW_KEY_MINUS: return "MINUS";
case GLFW_KEY_EQUAL: return "EQUAL";
case GLFW_KEY_LEFT_BRACKET: return "LEFT BRACKET";
case GLFW_KEY_RIGHT_BRACKET: return "RIGHT BRACKET";
case GLFW_KEY_BACKSLASH: return "BACKSLASH";
case GLFW_KEY_SEMICOLON: return "SEMICOLON";
case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
case GLFW_KEY_GRAVE_ACCENT: return "GRAVE ACCENT";
case GLFW_KEY_COMMA: return "COMMA";
case GLFW_KEY_PERIOD: return "PERIOD";
case GLFW_KEY_SLASH: return "SLASH";
case GLFW_KEY_WORLD_1: return "WORLD 1";
case GLFW_KEY_WORLD_2: return "WORLD 2";
case GLFW_KEY_PLUS: return "PLUS";
case GLFW_KEY_UNDERSCORE: return "UNDERSCORE";
case GLFW_KEY_SPACE: return "SPACE";
case GLFW_KEY_EXCLAM: return "EXCLAM";
case GLFW_KEY_DOUBLE_QUOTE: return "DOUBLE_QUOTE";
case GLFW_KEY_NUMBER_SIGN: return "NUMBER_SIGN";
case GLFW_KEY_DOLLAR: return "DOLLAR";
case GLFW_KEY_AMPERSAND: return "AMPERSAND";
case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
case GLFW_KEY_PARENTHESIS_LEFT: return "PARENTHESIS_LEFT";
case GLFW_KEY_PARENTHESIS_RIGHT: return "PARENTHESIS_RIGHT";
case GLFW_KEY_PLUS: return "PLUS";
case GLFW_KEY_COMMA: return "COMMA";
case GLFW_KEY_MINUS: return "MINUS";
case GLFW_KEY_PERIOD: return "PERIOD";
case GLFW_KEY_SLASH: return "SLASH";
case GLFW_KEY_0: return "0";
case GLFW_KEY_1: return "1";
case GLFW_KEY_2: return "2";
case GLFW_KEY_3: return "3";
case GLFW_KEY_4: return "4";
case GLFW_KEY_5: return "5";
case GLFW_KEY_6: return "6";
case GLFW_KEY_7: return "7";
case GLFW_KEY_8: return "8";
case GLFW_KEY_9: return "9";
case GLFW_KEY_COLON: return "COLON";
case GLFW_KEY_SEMICOLON: return "SEMICOLON";
case GLFW_KEY_LESS: return "LESS";
case GLFW_KEY_EQUAL: return "EQUAL";
case GLFW_KEY_GREATER: return "GREATER";
case GLFW_KEY_AT: return "AT";
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";
case GLFW_KEY_LEFT_BRACKET: return "LEFT_BRACKET";
case GLFW_KEY_BACKSLASH: return "BACKSLASH";
case GLFW_KEY_RIGHT_BRACKET: return "RIGHT_BRACKET";
case GLFW_KEY_CIRCUMFLEX: return "CIRCUMFLEX";
case GLFW_KEY_UNDERSCORE: return "UNDERSCORE";
case GLFW_KEY_GRAVE_ACCENT: return "GRAVE_ACCENT";
case GLFW_KEY_WORLD_1: return "WORLD_1";
case GLFW_KEY_WORLD_2: return "WORLD_2";
case GLFW_KEY_PARAGRAPH: return "PARAGRAPH";
case GLFW_KEY_MASCULINE: return "MASCULINE";
case GLFW_KEY_A_GRAVE: return "A_GRAVE";
case GLFW_KEY_A_DIAERESIS: return "A_DIAERESIS";
case GLFW_KEY_A_RING: return "A_RING";
case GLFW_KEY_AE: return "AE";
case GLFW_KEY_C_CEDILLA: return "C_CEDILLA";
case GLFW_KEY_E_GRAVE: return "E_GRAVE";
case GLFW_KEY_E_ACUTE: return "E_ACUTE";
case GLFW_KEY_I_GRAVE: return "I_GRAVE";
case GLFW_KEY_N_TILDE: return "N_TILDE";
case GLFW_KEY_O_GRAVE: return "O_GRAVE";
case GLFW_KEY_O_DIAERESIS: return "O_DIAERESIS";
case GLFW_KEY_O_SLASH: return "O_SLASH";
case GLFW_KEY_U_GRAVE: return "U_GRAVE";
case GLFW_KEY_U_DIAERESIS: return "U_DIAERESIS";
case GLFW_KEY_S_SHARP: return "S_SHARP";
case GLFW_KEY_CYRILLIC_A: return "CYRILLIC_A";
case GLFW_KEY_CYRILLIC_BE: return "CYRILLIC_BE";
case GLFW_KEY_CYRILLIC_VE: return "CYRILLIC_VE";
case GLFW_KEY_CYRILLIC_GHE: return "CYRILLIC_GHE";
case GLFW_KEY_CYRILLIC_DE: return "CYRILLIC_DE";
case GLFW_KEY_CYRILLIC_IE: return "CYRILLIC_IE";
case GLFW_KEY_CYRILLIC_ZHE: return "CYRILLIC_ZHE";
case GLFW_KEY_CYRILLIC_ZE: return "CYRILLIC_ZE";
case GLFW_KEY_CYRILLIC_I: return "CYRILLIC_I";
case GLFW_KEY_CYRILLIC_SHORT_I: return "CYRILLIC_SHORT_I";
case GLFW_KEY_CYRILLIC_KA: return "CYRILLIC_KA";
case GLFW_KEY_CYRILLIC_EL: return "CYRILLIC_EL";
case GLFW_KEY_CYRILLIC_EM: return "CYRILLIC_EM";
case GLFW_KEY_CYRILLIC_EN: return "CYRILLIC_EN";
case GLFW_KEY_CYRILLIC_O: return "CYRILLIC_O";
case GLFW_KEY_CYRILLIC_PE: return "CYRILLIC_PE";
case GLFW_KEY_CYRILLIC_ER: return "CYRILLIC_ER";
case GLFW_KEY_CYRILLIC_ES: return "CYRILLIC_ES";
case GLFW_KEY_CYRILLIC_TE: return "CYRILLIC_TE";
case GLFW_KEY_CYRILLIC_U: return "CYRILLIC_U";
case GLFW_KEY_CYRILLIC_EF: return "CYRILLIC_EF";
case GLFW_KEY_CYRILLIC_HA: return "CYRILLIC_HA";
case GLFW_KEY_CYRILLIC_TSE: return "CYRILLIC_TSE";
case GLFW_KEY_CYRILLIC_CHE: return "CYRILLIC_CHE";
case GLFW_KEY_CYRILLIC_SHA: return "CYRILLIC_SHA";
case GLFW_KEY_CYRILLIC_SHCHA: return "CYRILLIC_SHCHA";
case GLFW_KEY_CYRILLIC_HARD_SIGN: return "CYRILLIC_HARD_SIGN";
case GLFW_KEY_CYRILLIC_YERU: return "CYRILLIC_YERU";
case GLFW_KEY_CYRILLIC_SOFT_SIGN: return "CYRILLIC_SOFT_SIGN";
case GLFW_KEY_CYRILLIC_E: return "CYRILLIC_E";
case GLFW_KEY_CYRILLIC_YU: return "CYRILLIC_YU";
case GLFW_KEY_CYRILLIC_YA: return "CYRILLIC_YA";
case GLFW_KEY_CYRILLIC_IO: return "CYRILLIC_IO";
// Function keys
case GLFW_KEY_ESCAPE: return "ESCAPE";
case GLFW_KEY_F1: return "F1";
case GLFW_KEY_F2: return "F2";
case GLFW_KEY_F3: return "F3";
case GLFW_KEY_F4: return "F4";
case GLFW_KEY_F5: return "F5";
case GLFW_KEY_F6: return "F6";
case GLFW_KEY_F7: return "F7";
case GLFW_KEY_F8: return "F8";
case GLFW_KEY_F9: return "F9";
case GLFW_KEY_F10: return "F10";
case GLFW_KEY_F11: return "F11";
case GLFW_KEY_F12: return "F12";
case GLFW_KEY_F13: return "F13";
case GLFW_KEY_F14: return "F14";
case GLFW_KEY_F15: return "F15";
case GLFW_KEY_F16: return "F16";
case GLFW_KEY_F17: return "F17";
case GLFW_KEY_F18: return "F18";
case GLFW_KEY_F19: return "F19";
case GLFW_KEY_F20: return "F20";
case GLFW_KEY_F21: return "F21";
case GLFW_KEY_F22: return "F22";
case GLFW_KEY_F23: return "F23";
case GLFW_KEY_F24: return "F24";
case GLFW_KEY_F25: return "F25";
case GLFW_KEY_UP: return "UP";
case GLFW_KEY_DOWN: return "DOWN";
case GLFW_KEY_LEFT: return "LEFT";
case GLFW_KEY_RIGHT: return "RIGHT";
case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
case GLFW_KEY_TAB: return "TAB";
case GLFW_KEY_ENTER: return "ENTER";
case GLFW_KEY_BACKSPACE: return "BACKSPACE";
case GLFW_KEY_INSERT: return "INSERT";
case GLFW_KEY_DELETE: return "DELETE";
case GLFW_KEY_PAGE_UP: return "PAGE UP";
case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
case GLFW_KEY_HOME: return "HOME";
case GLFW_KEY_END: return "END";
case GLFW_KEY_KP_0: return "KEYPAD 0";
case GLFW_KEY_KP_1: return "KEYPAD 1";
case GLFW_KEY_KP_2: return "KEYPAD 2";
case GLFW_KEY_KP_3: return "KEYPAD 3";
case GLFW_KEY_KP_4: return "KEYPAD 4";
case GLFW_KEY_KP_5: return "KEYPAD 5";
case GLFW_KEY_KP_6: return "KEYPAD 6";
case GLFW_KEY_KP_7: return "KEYPAD 7";
case GLFW_KEY_KP_8: return "KEYPAD 8";
case GLFW_KEY_KP_9: return "KEYPAD 9";
case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTPLY";
case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
case GLFW_KEY_PAUSE: return "PAUSE";
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
case GLFW_KEY_MENU: return "MENU";
case GLFW_KEY_ESCAPE: return "ESCAPE";
case GLFW_KEY_F1: return "F1";
case GLFW_KEY_F2: return "F2";
case GLFW_KEY_F3: return "F3";
case GLFW_KEY_F4: return "F4";
case GLFW_KEY_F5: return "F5";
case GLFW_KEY_F6: return "F6";
case GLFW_KEY_F7: return "F7";
case GLFW_KEY_F8: return "F8";
case GLFW_KEY_F9: return "F9";
case GLFW_KEY_F10: return "F10";
case GLFW_KEY_F11: return "F11";
case GLFW_KEY_F12: return "F12";
case GLFW_KEY_F13: return "F13";
case GLFW_KEY_F14: return "F14";
case GLFW_KEY_F15: return "F15";
case GLFW_KEY_F16: return "F16";
case GLFW_KEY_F17: return "F17";
case GLFW_KEY_F18: return "F18";
case GLFW_KEY_F19: return "F19";
case GLFW_KEY_F20: return "F20";
case GLFW_KEY_F21: return "F21";
case GLFW_KEY_F22: return "F22";
case GLFW_KEY_F23: return "F23";
case GLFW_KEY_F24: return "F24";
case GLFW_KEY_F25: return "F25";
case GLFW_KEY_UP: return "UP";
case GLFW_KEY_DOWN: return "DOWN";
case GLFW_KEY_LEFT: return "LEFT";
case GLFW_KEY_RIGHT: return "RIGHT";
case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
case GLFW_KEY_TAB: return "TAB";
case GLFW_KEY_ENTER: return "ENTER";
case GLFW_KEY_BACKSPACE: return "BACKSPACE";
case GLFW_KEY_INSERT: return "INSERT";
case GLFW_KEY_DELETE: return "DELETE";
case GLFW_KEY_PAGE_UP: return "PAGE UP";
case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
case GLFW_KEY_HOME: return "HOME";
case GLFW_KEY_END: return "END";
case GLFW_KEY_KP_0: return "KEYPAD 0";
case GLFW_KEY_KP_1: return "KEYPAD 1";
case GLFW_KEY_KP_2: return "KEYPAD 2";
case GLFW_KEY_KP_3: return "KEYPAD 3";
case GLFW_KEY_KP_4: return "KEYPAD 4";
case GLFW_KEY_KP_5: return "KEYPAD 5";
case GLFW_KEY_KP_6: return "KEYPAD 6";
case GLFW_KEY_KP_7: return "KEYPAD 7";
case GLFW_KEY_KP_8: return "KEYPAD 8";
case GLFW_KEY_KP_9: return "KEYPAD 9";
case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTIPLY";
case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
case GLFW_KEY_PAUSE: return "PAUSE";
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
case GLFW_KEY_MENU: return "MENU";
default: return "UNKNOWN";
default: return "UNKNOWN";
}
}
@@ -683,7 +757,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
}
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
GLFWAPI const char* glfwGetKeyName(int key, int native_key)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@@ -691,18 +765,18 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
{
if (key != GLFW_KEY_KP_EQUAL &&
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_LAST_PRINTABLE))
{
return NULL;
}
scancode = _glfwPlatformGetKeyScancode(key);
native_key = _glfwPlatformGetNativeKeyForKey(key);
}
return _glfwPlatformGetScancodeName(scancode);
return _glfwPlatformGetNativeKeyName(native_key);
}
GLFWAPI int glfwGetKeyScancode(int key)
GLFWAPI int glfwGetNativeKeyForKey(int key)
{
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
@@ -712,7 +786,7 @@ GLFWAPI int glfwGetKeyScancode(int key)
return GLFW_RELEASE;
}
return _glfwPlatformGetKeyScancode(key);
return _glfwPlatformGetNativeKeyForKey(key);
}
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
@@ -1405,35 +1479,8 @@ GLFWAPI const char* glfwGetPrimarySelectionString(GLFWwindow* handle UNUSED)
}
#endif
GLFWAPI double glfwGetTime(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
_glfwPlatformGetTimerFrequency();
}
GLFWAPI void glfwSetTime(double time)
{
_GLFW_REQUIRE_INIT();
if (time != time || time < 0.0 || time > 18446744073.0)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
return;
}
_glfw.timer.offset = _glfwPlatformGetTimerValue() -
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
}
GLFWAPI uint64_t glfwGetTimerValue(void)
GLFWAPI monotonic_t glfwGetTime(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return _glfwPlatformGetTimerValue();
}
GLFWAPI uint64_t glfwGetTimerFrequency(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return _glfwPlatformGetTimerFrequency();
return monotonic();
}

32
glfw/internal.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -27,6 +27,8 @@
#pragma once
#include "../kitty/monotonic.h"
#if defined(_GLFW_USE_CONFIG_H)
#include "glfw_config.h"
#endif
@@ -130,6 +132,7 @@ typedef enum VkStructureType
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkStructureType;
@@ -416,6 +419,7 @@ struct _GLFWwindow
int minwidth, minheight;
int maxwidth, maxheight;
int numer, denom;
int widthincr, heightincr;
bool stickyKeys;
bool stickyMouseButtons;
@@ -572,12 +576,6 @@ struct _GLFWlibrary
_GLFWtls contextSlot;
_GLFWmutex errorLock;
struct {
uint64_t offset;
// This is defined in the platform's time.h
_GLFW_PLATFORM_LIBRARY_TIMER_STATE;
} timer;
struct {
bool available;
void* handle;
@@ -591,6 +589,7 @@ struct _GLFWlibrary
bool KHR_win32_surface;
#elif defined(_GLFW_COCOA)
bool MVK_macos_surface;
bool EXT_metal_surface;
#elif defined(_GLFW_X11)
bool KHR_xlib_surface;
bool KHR_xcb_surface;
@@ -638,8 +637,8 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
const char* _glfwPlatformGetScancodeName(int scancode);
int _glfwPlatformGetKeyScancode(int key);
const char* _glfwPlatformGetNativeKeyName(int native_key);
int _glfwPlatformGetNativeKeyForKey(int key);
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
@@ -661,9 +660,6 @@ const char* _glfwPlatformGetPrimarySelectionString(void);
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
void _glfwPlatformUpdateGamepadGUID(char* guid);
uint64_t _glfwPlatformGetTimerValue(void);
uint64_t _glfwPlatformGetTimerFrequency(void);
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
@@ -680,6 +676,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight);
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window, int widthincr, int heightincr);
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
void _glfwInputLiveResize(_GLFWwindow* window, bool started);
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
@@ -687,7 +684,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* right, int* bottom);
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
float* xscale, float* yscale);
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window);
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window);
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
@@ -716,7 +713,7 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c,
void _glfwPlatformPollEvents(void);
void _glfwPlatformWaitEvents(void);
void _glfwPlatformWaitEventsTimeout(double timeout);
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout);
void _glfwPlatformPostEmptyEvent(void);
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
@@ -756,7 +753,8 @@ void _glfwInputWindowDamage(_GLFWwindow* window);
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action, int mods, const char* text, int state);
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods);
void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev);
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags);
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
@@ -823,8 +821,8 @@ _GLFWwindow* _glfwFocusedWindow(void);
_GLFWwindow* _glfwWindowForId(GLFWid id);
void _glfwPlatformRunMainLoop(GLFWtickcallback, void*);
void _glfwPlatformStopMainLoop(void);
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback);
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
unsigned long long _glfwPlatformAddTimer(monotonic_t interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback);
void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled);
void _glfwPlatformRemoveTimer(unsigned long long timer_id);
char* _glfw_strdup(const char* source);

15
glfw/linux_joystick.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Linux - www.glfw.org
// GLFW 3.4 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -144,10 +144,10 @@ static bool openJoystickDevice(const char* path)
char absBits[(ABS_CNT + 7) / 8] = {0};
struct input_id id;
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
ioctl(linjs.fd, EVIOCGID, &id) < 0)
if (ioctl(linjs.fd, (int32_t)EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
ioctl(linjs.fd, (int32_t)EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
ioctl(linjs.fd, (int32_t)EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
ioctl(linjs.fd, (int32_t)EVIOCGID, &id) < 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Linux: Failed to query input device: %s",
@@ -165,7 +165,7 @@ static bool openJoystickDevice(const char* path)
char name[256] = "";
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
if (ioctl(linjs.fd, (int32_t)EVIOCGNAME(sizeof(name)), name) < 0)
strncpy(name, "Unknown", sizeof(name));
char guid[33] = "";
@@ -222,7 +222,8 @@ static bool openJoystickDevice(const char* path)
}
}
_GLFWjoystick* js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
_GLFWjoystick* js =
_glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
if (!js)
{
close(linjs.fd);

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Linux - www.glfw.org
// GLFW 3.4 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -52,7 +52,7 @@ typedef struct _GLFWlibraryLinux
int inotify;
int watch;
regex_t regex;
bool dropped;
bool dropped;
} _GLFWlibraryLinux;

5
glfw/main_loop.h vendored
View File

@@ -7,6 +7,7 @@
#pragma once
#include "internal.h"
#include "../kitty/monotonic.h"
#ifndef GLFW_LOOP_BACKEND
#define GLFW_LOOP_BACKEND x11
@@ -36,7 +37,7 @@ void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) {
EVDBG("main loop exiting");
}
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafreefun callback, void *callback_data, GLFWuserdatafreefun free_callback) {
unsigned long long _glfwPlatformAddTimer(monotonic_t interval, bool repeats, GLFWuserdatafreefun callback, void *callback_data, GLFWuserdatafreefun free_callback) {
return addTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, "user timer", interval, 1, repeats, callback, callback_data, free_callback);
}
@@ -44,7 +45,7 @@ void _glfwPlatformRemoveTimer(unsigned long long timer_id) {
removeTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id);
}
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled) {
changeTimerInterval(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, interval);
toggleTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, enabled);
}

2
glfw/mappings.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
//

6
glfw/monitor.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -56,6 +56,10 @@ static int compareVideoModes(const void* fp, const void* sp)
if (farea != sarea)
return farea - sarea;
// Then sort on width
if (fm->width != sm->width)
return fm->width - sm->width;
// Lastly sort on refresh rate
return fm->refreshRate - sm->refreshRate;
}

10
glfw/monotonic.c vendored Normal file
View File

@@ -0,0 +1,10 @@
/*
* monotonic.c
* Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#define _POSIX_C_SOURCE 200809L
#define MONOTONIC_IMPLEMENTATION
#include "../kitty/monotonic.h"

6
glfw/nsgl_context.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 macOS - www.glfw.org
// GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -32,8 +32,8 @@
//
typedef struct _GLFWcontextNSGL
{
id pixelFormat;
id object;
id pixelFormat;
id object;
} _GLFWcontextNSGL;

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 macOS - www.glfw.org
// GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -271,7 +271,7 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
return false;
}
NSOpenGLContext* share = NULL;
NSOpenGLContext* share = nil;
if (ctxconfig->share)
share = ctxconfig->share->context.nsgl.object;
@@ -293,8 +293,7 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
forParameter:NSOpenGLContextParameterSurfaceOpacity];
}
if (window->ns.retina)
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
[window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
GLint interval = 0;
[window->context.nsgl.object setValues:&interval
@@ -325,7 +324,7 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
if (window->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL;
return nil;
}
return window->context.nsgl.object;

4
glfw/null_init.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -36,7 +36,6 @@
int _glfwPlatformInit(void)
{
_glfwInitTimerPOSIX();
return true;
}
@@ -49,4 +48,3 @@ const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER " null OSMesa";
}

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
//
@@ -33,12 +33,12 @@
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
int _glfwPlatformPollJoystick(_GLFWjoystick* js UNUSED, int mode UNUSED)
{
return false;
}
void _glfwPlatformUpdateGamepadGUID(char* guid)
void _glfwPlatformUpdateGamepadGUID(char* guid UNUSED)
{
}

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//

22
glfw/null_monitor.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -34,15 +34,15 @@
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor UNUSED)
{
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor UNUSED, int* xpos UNUSED, int* ypos UNUSED)
{
}
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor UNUSED,
float* xscale, float* yscale)
{
if (xscale)
@@ -51,27 +51,27 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
*yscale = 1.f;
}
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
int* xpos, int* ypos,
int* width, int* height)
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor UNUSED,
int* xpos UNUSED, int* ypos UNUSED,
int* width UNUSED, int* height UNUSED)
{
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor UNUSED, int* found UNUSED)
{
return NULL;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor UNUSED, GLFWvidmode* mode UNUSED)
{
}
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp UNUSED)
{
return false;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED, const GLFWgammaramp* ramp UNUSED)
{
}

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>

131
glfw/null_window.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -28,6 +28,7 @@
//========================================================================
#include "internal.h"
#include "../kitty/monotonic.h"
static int createNativeWindow(_GLFWwindow* window,
@@ -78,28 +79,28 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->context.destroy(window);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
void _glfwPlatformSetWindowTitle(_GLFWwindow* window UNUSED, const char* title UNUSED)
{
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
const GLFWimage* images)
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED, int count UNUSED,
const GLFWimage* images UNUSED)
{
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window UNUSED,
_GLFWmonitor* monitor UNUSED,
int xpos UNUSED, int ypos UNUSED,
int width UNUSED, int height UNUSED,
int refreshRate UNUSED)
{
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int* ypos UNUSED)
{
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int ypos UNUSED)
{
}
@@ -117,13 +118,17 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
window->null.height = height;
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window UNUSED,
int minwidth UNUSED, int minheight UNUSED,
int maxwidth UNUSED, int maxheight UNUSED)
{
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window UNUSED, int n UNUSED, int d UNUSED)
{
}
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED, int widthincr UNUSED, int heightincr UNUSED)
{
}
@@ -135,13 +140,13 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
*height = window->null.height;
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window UNUSED,
int* left UNUSED, int* top UNUSED,
int* right UNUSED, int* bottom UNUSED)
{
}
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
float* xscale, float* yscale)
{
if (xscale)
@@ -150,101 +155,101 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
*yscale = 1.f;
}
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window)
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
{
return 0.5;
return ms_to_monotonic_t(500ll);
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
void _glfwPlatformIconifyWindow(_GLFWwindow* window UNUSED)
{
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
void _glfwPlatformRestoreWindow(_GLFWwindow* window UNUSED)
{
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
void _glfwPlatformMaximizeWindow(_GLFWwindow* window UNUSED)
{
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
int _glfwPlatformWindowMaximized(_GLFWwindow* window UNUSED)
{
return false;
}
int _glfwPlatformWindowHovered(_GLFWwindow* window)
int _glfwPlatformWindowHovered(_GLFWwindow* window UNUSED)
{
return false;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window UNUSED)
{
return false;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
void _glfwPlatformSetWindowResizable(_GLFWwindow* window UNUSED, bool enabled UNUSED)
{
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window UNUSED, bool enabled UNUSED)
{
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
void _glfwPlatformSetWindowFloating(_GLFWwindow* window UNUSED, bool enabled UNUSED)
{
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
{
return 1.f;
}
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window UNUSED, float opacity UNUSED)
{
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
void _glfwPlatformShowWindow(_GLFWwindow* window UNUSED)
{
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
{
}
int _glfwPlatformWindowBell(_GLFWwindow* window)
int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
{
return false;
}
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
void _glfwPlatformUnhideWindow(_GLFWwindow* window UNUSED)
{
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
void _glfwPlatformHideWindow(_GLFWwindow* window UNUSED)
{
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
{
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
int _glfwPlatformWindowFocused(_GLFWwindow* window UNUSED)
{
return false;
}
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
{
return false;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
int _glfwPlatformWindowIconified(_GLFWwindow* window UNUSED)
{
return false;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
int _glfwPlatformWindowVisible(_GLFWwindow* window UNUSED)
{
return false;
}
@@ -257,7 +262,7 @@ void _glfwPlatformWaitEvents(void)
{
}
void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout UNUSED)
{
}
@@ -265,39 +270,39 @@ void _glfwPlatformPostEmptyEvent(void)
{
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
void _glfwPlatformGetCursorPos(_GLFWwindow* window UNUSED, double* xpos UNUSED, double* ypos UNUSED)
{
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
void _glfwPlatformSetCursorPos(_GLFWwindow* window UNUSED, double x UNUSED, double y UNUSED)
{
}
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
void _glfwPlatformSetCursorMode(_GLFWwindow* window UNUSED, int mode UNUSED)
{
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot, int count)
int _glfwPlatformCreateCursor(_GLFWcursor* cursor UNUSED,
const GLFWimage* image UNUSED,
int xhot UNUSED, int yhot UNUSED, int count UNUSED)
{
return true;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor UNUSED, int shape UNUSED)
{
return true;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor UNUSED)
{
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window UNUSED, _GLFWcursor* cursor UNUSED)
{
}
void _glfwPlatformSetClipboardString(const char* string)
void _glfwPlatformSetClipboardString(const char* string UNUSED)
{
}
@@ -306,31 +311,31 @@ const char* _glfwPlatformGetClipboardString(void)
return NULL;
}
const char* _glfwPlatformGetScancodeName(int scancode)
const char* _glfwPlatformGetNativeKeyName(int native_key UNUSED)
{
return "";
}
int _glfwPlatformGetKeyScancode(int key)
int _glfwPlatformGetNativeKeyForKey(int key UNUSED)
{
return -1;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions UNUSED)
{
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance UNUSED,
VkPhysicalDevice device UNUSED,
uint32_t queuefamily UNUSED)
{
return false;
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance UNUSED,
_GLFWwindow* window UNUSED,
const VkAllocationCallbacks* allocator UNUSED,
VkSurfaceKHR* surface UNUSED)
{
// This seems like the most appropriate error to return here
return VK_ERROR_INITIALIZATION_FAILED;

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 OSMesa - www.glfw.org
// GLFW 3.4 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>

View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 OSMesa - www.glfw.org
// GLFW 3.4 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>

2
glfw/posix_thread.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 POSIX - www.glfw.org
// GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

6
glfw/posix_thread.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 POSIX - www.glfw.org
// GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
@@ -35,7 +35,7 @@
//
typedef struct _GLFWtlsPOSIX
{
bool allocated;
bool allocated;
pthread_key_t key;
} _GLFWtlsPOSIX;
@@ -44,7 +44,7 @@ typedef struct _GLFWtlsPOSIX
//
typedef struct _GLFWmutexPOSIX
{
bool allocated;
bool allocated;
pthread_mutex_t handle;
} _GLFWmutexPOSIX;

87
glfw/posix_time.c vendored
View File

@@ -1,87 +0,0 @@
//========================================================================
// GLFW 3.3 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h"
#include <sys/time.h>
#include <time.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialise timer
//
void _glfwInitTimerPOSIX(void)
{
#if defined(CLOCK_MONOTONIC)
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
{
_glfw.timer.posix.monotonic = true;
_glfw.timer.posix.frequency = 1000000000;
}
else
#endif
{
_glfw.timer.posix.monotonic = false;
_glfw.timer.posix.frequency = 1000000;
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
uint64_t _glfwPlatformGetTimerValue(void)
{
#if defined(CLOCK_MONOTONIC)
if (_glfw.timer.posix.monotonic)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
}
else
#endif
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
}
}
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.timer.posix.frequency;
}

44
glfw/posix_time.h vendored
View File

@@ -1,44 +0,0 @@
//========================================================================
// GLFW 3.3 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
#include <stdint.h>
// POSIX-specific global timer data
//
typedef struct _GLFWtimerPOSIX
{
bool monotonic;
uint64_t frequency;
} _GLFWtimerPOSIX;
void _glfwInitTimerPOSIX(void);

View File

@@ -13,7 +13,6 @@
"cocoa_joystick.m",
"cocoa_monitor.m",
"cocoa_window.m",
"cocoa_time.c",
"posix_thread.c",
"nsgl_context.m",
"egl_context.c",
@@ -31,6 +30,7 @@
"input.c",
"monitor.c",
"vulkan.c",
"monotonic.c",
"window.c"
]
},
@@ -38,7 +38,6 @@
"headers": [
"null_platform.h",
"null_joystick.h",
"posix_time.h",
"posix_thread.h",
"osmesa_context.h"
],
@@ -47,7 +46,6 @@
"null_monitor.c",
"null_window.c",
"null_joystick.c",
"posix_time.c",
"posix_thread.c",
"osmesa_context.c"
]
@@ -55,7 +53,6 @@
"wayland": {
"headers": [
"wl_platform.h",
"posix_time.h",
"posix_thread.h",
"xkb_glfw.h",
"dbus_glfw.h",
@@ -81,7 +78,6 @@
"wl_init.c",
"wl_monitor.c",
"wl_window.c",
"posix_time.c",
"posix_thread.c",
"xkb_glfw.c",
"dbus_glfw.c",
@@ -125,7 +121,6 @@
"dbus_glfw.h",
"ibus_glfw.h",
"backend_utils.h",
"posix_time.h",
"posix_thread.h",
"glx_context.h",
"egl_context.h",
@@ -142,7 +137,6 @@
"xkb_glfw.c",
"dbus_glfw.c",
"ibus_glfw.c",
"posix_time.c",
"posix_thread.c",
"glx_context.c",
"egl_context.c",

6
glfw/vulkan.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@@ -57,6 +57,8 @@ bool _glfwInitVulkan(int mode)
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
#else
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
#endif
@@ -130,6 +132,8 @@ bool _glfwInitVulkan(int mode)
#elif defined(_GLFW_COCOA)
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
_glfw.vk.MVK_macos_surface = true;
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
_glfw.vk.EXT_metal_surface = true;
#elif defined(_GLFW_X11)
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
_glfw.vk.KHR_xlib_surface = true;

29
glfw/window.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
// GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -29,6 +29,7 @@
//========================================================================
#include "internal.h"
#include "../kitty/monotonic.h"
#include <assert.h>
#include <string.h>
@@ -56,8 +57,10 @@ void _glfwInputWindowFocus(_GLFWwindow* window, bool focused)
{
if (window->keys[key] == GLFW_PRESS)
{
const int scancode = _glfwPlatformGetKeyScancode(key);
_glfwInputKeyboard(window, key, scancode, GLFW_RELEASE, 0, "", 0);
const int native_key = _glfwPlatformGetNativeKeyForKey(key);
GLFWkeyevent ev;
_glfwInitializeKeyEvent(&ev, key, native_key, GLFW_RELEASE, 0);
_glfwInputKeyboard(window, &ev);
}
}
@@ -251,6 +254,8 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->maxheight = GLFW_DONT_CARE;
window->numer = GLFW_DONT_CARE;
window->denom = GLFW_DONT_CARE;
window->widthincr = GLFW_DONT_CARE;
window->heightincr = GLFW_DONT_CARE;
// Open the actual window and create its context
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
@@ -687,6 +692,20 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
_glfwPlatformSetWindowAspectRatio(window, numer, denom);
}
GLFWAPI void glfwSetWindowSizeIncrements(GLFWwindow* handle, int widthincr, int heightincr)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(widthincr >= 0);
assert(heightincr >= 0);
_GLFW_REQUIRE_INIT();
window->widthincr = widthincr;
window->heightincr = heightincr;
_glfwPlatformSetWindowSizeIncrements(window, window->widthincr, window->heightincr);
}
GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@@ -736,12 +755,12 @@ GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
_glfwPlatformGetWindowContentScale(window, xscale, yscale);
}
GLFWAPI double glfwGetDoubleClickInterval(GLFWwindow* handle)
GLFWAPI monotonic_t glfwGetDoubleClickInterval(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0.5f);
_GLFW_REQUIRE_INIT_OR_RETURN(ms_to_monotonic_t(500ll));
return _glfwPlatformGetDoubleClickInterval(window);
}

60
glfw/wl_init.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Wayland - www.glfw.org
// GLFW 3.4 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -29,6 +29,7 @@
#define _GNU_SOURCE
#include "internal.h"
#include "backend_utils.h"
#include "../kitty/monotonic.h"
#include <assert.h>
#include <errno.h>
@@ -136,6 +137,7 @@ static void pointerHandleLeave(void* data UNUSED,
_glfw.wl.pointerSerial = serial;
_glfw.wl.pointerFocus = NULL;
_glfwInputCursorEnter(window, false);
_glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
}
static void setCursor(GLFWCursorShape shape)
@@ -164,6 +166,7 @@ static void setCursor(GLFWCursorShape shape)
wl_surface_damage(surface, 0, 0,
image->width, image->height);
wl_surface_commit(surface);
_glfw.wl.cursorPreviousShape = shape;
}
static void pointerHandleMotion(void* data UNUSED,
@@ -174,43 +177,46 @@ static void pointerHandleMotion(void* data UNUSED,
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
GLFWCursorShape cursorShape = GLFW_ARROW_CURSOR;
double x, y;
if (!window)
return;
if (window->cursorMode == GLFW_CURSOR_DISABLED)
return;
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
x = wl_fixed_to_double(sx);
y = wl_fixed_to_double(sy);
switch (window->wl.decorations.focus)
{
case mainWindow:
_glfwInputCursorPos(window,
window->wl.cursorPosX, window->wl.cursorPosY);
window->wl.cursorPosX = x;
window->wl.cursorPosY = y;
_glfwInputCursorPos(window, x, y);
_glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
return;
case topDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
if (y < _GLFW_DECORATION_WIDTH)
cursorShape = GLFW_VRESIZE_CURSOR;
else
cursorShape = GLFW_ARROW_CURSOR;
break;
case leftDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
if (y < _GLFW_DECORATION_WIDTH)
cursorShape = GLFW_NW_RESIZE_CURSOR;
else
cursorShape = GLFW_HRESIZE_CURSOR;
break;
case rightDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
if (y < _GLFW_DECORATION_WIDTH)
cursorShape = GLFW_NE_RESIZE_CURSOR;
else
cursorShape = GLFW_HRESIZE_CURSOR;
break;
case bottomDecoration:
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
if (x < _GLFW_DECORATION_WIDTH)
cursorShape = GLFW_SW_RESIZE_CURSOR;
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
else if (x > window->wl.width + _GLFW_DECORATION_WIDTH)
cursorShape = GLFW_SE_RESIZE_CURSOR;
else
cursorShape = GLFW_VRESIZE_CURSOR;
@@ -218,7 +224,8 @@ static void pointerHandleMotion(void* data UNUSED,
default:
assert(0);
}
setCursor(cursorShape);
if (_glfw.wl.cursorPreviousShape != cursorShape)
setCursor(cursorShape);
}
static void pointerHandleButton(void* data UNUSED,
@@ -284,8 +291,8 @@ static void pointerHandleButton(void* data UNUSED,
{
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
window->wl.cursorPosX,
window->wl.cursorPosY);
(int32_t)window->wl.cursorPosX,
(int32_t)window->wl.cursorPosY);
return;
}
}
@@ -367,7 +374,7 @@ static void keyboardHandleEnter(void* data UNUSED,
struct wl_keyboard* keyboard UNUSED,
uint32_t serial UNUSED,
struct wl_surface* surface,
struct wl_array* keys UNUSED)
struct wl_array* keys)
{
// Happens in the case we just destroyed the surface.
if (!surface)
@@ -383,6 +390,15 @@ static void keyboardHandleEnter(void* data UNUSED,
_glfw.wl.keyboardFocus = window;
_glfwInputWindowFocus(window, true);
uint32_t* key;
if (keys && _glfw.wl.keyRepeatInfo.key) {
wl_array_for_each(key, keys) {
if (*key == _glfw.wl.keyRepeatInfo.key) {
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
break;
}
}
}
}
static void keyboardHandleLeave(void* data UNUSED,
@@ -397,13 +413,14 @@ static void keyboardHandleLeave(void* data UNUSED,
_glfw.wl.keyboardFocus = NULL;
_glfwInputWindowFocus(window, false);
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 0);
}
static void
dispatchPendingKeyRepeats(id_type timer_id UNUSED, void *data UNUSED) {
if (_glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return;
glfw_xkb_handle_key_event(_glfw.wl.keyRepeatInfo.keyboardFocus, &_glfw.wl.xkb, _glfw.wl.keyRepeatInfo.key, GLFW_REPEAT);
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, (1.0 / (double)_glfw.wl.keyboardRepeatRate));
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, (s_to_monotonic_t(1ll) / (monotonic_t)_glfw.wl.keyboardRepeatRate));
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
}
@@ -421,6 +438,7 @@ static void keyboardHandleKey(void* data UNUSED,
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
bool repeatable = false;
_glfw.wl.keyRepeatInfo.key = 0;
if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key))
{
@@ -429,7 +447,7 @@ static void keyboardHandleKey(void* data UNUSED,
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
}
if (repeatable) {
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, (double)(_glfw.wl.keyboardRepeatDelay) / 1000.0);
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, _glfw.wl.keyboardRepeatDelay);
}
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, repeatable ? 1 : 0);
}
@@ -454,7 +472,7 @@ static void keyboardHandleRepeatInfo(void* data UNUSED,
return;
_glfw.wl.keyboardRepeatRate = rate;
_glfw.wl.keyboardRepeatDelay = delay;
_glfw.wl.keyboardRepeatDelay = ms_to_monotonic_t(delay);
}
static const struct wl_keyboard_listener keyboardListener = {
@@ -607,8 +625,7 @@ static void registryHandleGlobal(void* data UNUSED,
_glfwSetupWaylandDataDevice();
}
}
else if (strcmp(interface, "zwp_primary_selection_device_manager_v1") == 0 ||
strcmp(interface, "gtk_primary_selection_device_manager") == 0)
else if (strcmp(interface, "zwp_primary_selection_device_manager_v1") == 0)
{
_glfw.wl.primarySelectionDeviceManager =
wl_registry_bind(registry, name,
@@ -728,8 +745,8 @@ int _glfwPlatformInit(void)
"Wayland: Failed to initialize event loop data");
}
glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData);
_glfw.wl.keyRepeatInfo.keyRepeatTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-key-repeat", 0.5, 0, true, dispatchPendingKeyRepeats, NULL, NULL);
_glfw.wl.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", 0.5, 0, true, animateCursorImage, NULL, NULL);
_glfw.wl.keyRepeatInfo.keyRepeatTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-key-repeat", ms_to_monotonic_t(500ll), 0, true, dispatchPendingKeyRepeats, NULL, NULL);
_glfw.wl.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", ms_to_monotonic_t(500ll), 0, true, animateCursorImage, NULL, NULL);
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
@@ -749,7 +766,6 @@ int _glfwPlatformInit(void)
}
#endif
_glfwInitTimerPOSIX();
if (!_glfw.wl.wmBase)
{
_glfwInputError(GLFW_PLATFORM_ERROR,

2
glfw/wl_monitor.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Wayland - www.glfw.org
// GLFW 3.4 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//

7
glfw/wl_platform.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Wayland - www.glfw.org
// GLFW 3.4 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -43,7 +43,6 @@ typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWa
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
#include "posix_thread.h"
#include "posix_time.h"
#ifdef __linux__
#include "linux_joystick.h"
#else
@@ -156,6 +155,7 @@ typedef struct _GLFWwindowWayland
// We need to track the monitors the window spans on to calculate the
// optimal scaling factor.
int scale;
bool initial_scale_notified;
_GLFWmonitor** monitors;
int monitorsCount;
int monitorsSize;
@@ -247,10 +247,11 @@ typedef struct _GLFWlibraryWayland
struct wl_cursor_theme* cursorTheme;
struct wl_surface* cursorSurface;
GLFWCursorShape cursorPreviousShape;
uint32_t pointerSerial;
int32_t keyboardRepeatRate;
int32_t keyboardRepeatDelay;
monotonic_t keyboardRepeatDelay;
struct {
uint32_t key;
id_type keyRepeatTimer;

106
glfw/wl_window.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 Wayland - www.glfw.org
// GLFW 3.4 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -32,6 +32,7 @@
#include "backend_utils.h"
#include "memfd.h"
#include "linux_notify.h"
#include "../kitty/monotonic.h"
#include <stdio.h>
#include <stdlib.h>
@@ -54,13 +55,18 @@ static bool checkScaleChange(_GLFWwindow* window)
if (_glfw.wl.compositorVersion < 3)
return false;
// Get the scale factor from the highest scale monitor.
// Get the scale factor from the highest scale monitor that this window is on
for (i = 0; i < window->wl.monitorsCount; ++i)
{
monitorScale = window->wl.monitors[i]->wl.scale;
if (scale < monitorScale)
scale = monitorScale;
}
if (window->wl.monitorsCount < 1 && _glfw.monitorCount > 0) {
// The window has not yet been assigned to any monitors, use the primary monitor
_GLFWmonitor *m = _glfw.monitors[0];
if (m && m->wl.scale > scale) scale = m->wl.scale;
}
// Only change the framebuffer size if the scale changed.
if (scale != window->wl.scale)
@@ -69,6 +75,10 @@ static bool checkScaleChange(_GLFWwindow* window)
wl_surface_set_buffer_scale(window->wl.surface, scale);
return true;
}
if (window->wl.monitorsCount > 0 && !window->wl.initial_scale_notified) {
window->wl.initial_scale_notified = true;
return true;
}
return false;
}
@@ -173,7 +183,7 @@ static void dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, in
* SCM_RIGHTS methods.
*
* posix_fallocate() is used to guarantee that disk space is available
* for the file at the given size. If disk space is insufficent, errno
* for the file at the given size. If disk space is insufficient, errno
* is set to ENOSPC. If posix_fallocate() is not supported, program may
* receive SIGBUS on accessing mmap()'ed file contents instead.
*/
@@ -241,8 +251,8 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
if (fd < 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Creating a buffer file for %d B failed: %%m",
length);
"Wayland: Creating a buffer file for %d B failed: %s",
length, strerror(errno));
return NULL;
}
@@ -250,7 +260,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
if (data == MAP_FAILED)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: mmap failed: %%m");
"Wayland: mmap failed: %s", strerror(errno));
close(fd);
return NULL;
}
@@ -545,9 +555,9 @@ static void xdgToplevelHandleConfigure(void* data,
aspectRatio = (float)width / (float)height;
targetRatio = (float)window->numer / (float)window->denom;
if (aspectRatio < targetRatio)
height = width / targetRatio;
height = (int32_t)((float)width / targetRatio);
else if (aspectRatio > targetRatio)
width = height * targetRatio;
width = (int32_t)((float)height * targetRatio);
}
}
}
@@ -684,7 +694,7 @@ setCursorImage(_GLFWcursorWayland* cursorWayland)
image = cursorWayland->cursor->images[cursorWayland->currentImage];
buffer = wl_cursor_image_get_buffer(image);
if (image->delay) {
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, ((double)image->delay) / 1000.0);
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);
@@ -745,24 +755,23 @@ abortOnFatalError(int last_error) {
}
static void
handleEvents(double timeout)
wayland_read_events(int poll_result, int events, void *data UNUSED) {
EVDBG("wayland_read_events poll_result: %d events: %d", poll_result, events);
if (poll_result > 0 && events) wl_display_read_events(_glfw.wl.display);
else wl_display_cancel_read(_glfw.wl.display);
}
static void
handleEvents(monotonic_t timeout)
{
struct wl_display* display = _glfw.wl.display;
errno = 0;
EVDBG("starting handleEvents(%.2f)", timeout);
EVDBG("starting handleEvents(%.2f)", monotonic_t_to_s_double(timeout));
while (wl_display_prepare_read(display) != 0) {
while(1) {
errno = 0;
int num_dispatched = wl_display_dispatch_pending(display);
if (num_dispatched < 0) {
if (errno == EAGAIN) continue;
int last_error = wl_display_get_error(display);
if (last_error) abortOnFatalError(last_error);
wl_display_cancel_read(display);
return;
}
break;
if (wl_display_dispatch_pending(display) == -1) {
abortOnFatalError(errno);
return;
}
}
@@ -772,23 +781,22 @@ handleEvents(double timeout)
errno = 0;
if (wl_display_flush(display) < 0 && errno != EAGAIN)
{
abortOnFatalError(errno);
wl_display_cancel_read(display);
abortOnFatalError(errno);
return;
}
bool display_read_ok = pollForEvents(&_glfw.wl.eventLoopData, timeout);
// we pass in wayland_read_events to ensure that the above wl_display_prepare_read call
// is followed by either wl_display_cancel_read or wl_display_read_events
// before any events/timers are dispatched. This allows other wayland functions
// to be called in the event/timer handlers without causing a deadlock
bool display_read_ok = pollForEvents(&_glfw.wl.eventLoopData, timeout, wayland_read_events);
EVDBG("display_read_ok: %d", display_read_ok);
if (display_read_ok) {
wl_display_read_events(display);
int num = wl_display_dispatch_pending(display);
(void)num;
EVDBG("dispatched %d Wayland events", num);
}
else
{
wl_display_cancel_read(display);
}
glfw_ibus_dispatch(&_glfw.wl.xkb.ibus);
glfw_dbus_session_bus_dispatch();
EVDBG("other dispatch done");
@@ -950,8 +958,13 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
if (window->wl.title)
free(window->wl.title);
window->wl.title = _glfw_strdup(title);
// Wayland cannot handle requests larger than ~8200 bytes. Sending
// on causes an abort(). Since titles this large are meaningless anyway
// ensure they do not happen. One should really truncate ensuring valid UTF-8
// but I cant be bothered.
if (title && strnlen(title, 2048) >= 2048) window->wl.title[2048] = 0;
if (window->wl.xdg.toplevel)
xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,
@@ -1018,6 +1031,13 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window UNUSED,
// The actual limits are checked in the xdg_toplevel::configure handler.
}
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED,
int widthincr UNUSED, int heightincr UNUSED)
{
// TODO: find out how to trigger a resize.
// The actual limits are checked in the xdg_toplevel::configure handler.
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
int* width, int* height)
{
@@ -1052,9 +1072,9 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
*yscale = (float) window->wl.scale;
}
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
{
return 0.5;
return ms_to_monotonic_t(500ll);
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
@@ -1227,11 +1247,11 @@ void _glfwPlatformPollEvents(void)
void _glfwPlatformWaitEvents(void)
{
double timeout = wl_display_dispatch_pending(_glfw.wl.display) > 0 ? 0 : -1;
monotonic_t timeout = wl_display_dispatch_pending(_glfw.wl.display) > 0 ? 0 : -1;
handleEvents(timeout);
}
void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout)
{
if (wl_display_dispatch_pending(_glfw.wl.display) > 0) timeout = 0;
handleEvents(timeout);
@@ -1268,12 +1288,12 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode UNUSED)
_glfwPlatformSetCursor(window, window->wl.currentCursor);
}
const char* _glfwPlatformGetScancodeName(int scancode)
const char* _glfwPlatformGetNativeKeyName(int native_key)
{
return glfw_xkb_keysym_name(scancode);
return glfw_xkb_keysym_name(native_key);
}
int _glfwPlatformGetKeyScancode(int key)
int _glfwPlatformGetNativeKeyForKey(int key)
{
return glfw_xkb_sym_for_key(key);
}
@@ -1462,8 +1482,8 @@ static void send_text(char *text, int fd)
{
if (text) {
size_t len = strlen(text), pos = 0;
double start = glfwGetTime();
while (pos < len && glfwGetTime() - start < 2.0) {
monotonic_t start = glfwGetTime();
while (pos < len && glfwGetTime() - start < s_to_monotonic_t(2ll)) {
ssize_t ret = write(fd, text + pos, len - pos);
if (ret < 0) {
if (errno == EAGAIN || errno == EINTR) continue;
@@ -1496,7 +1516,7 @@ static char* read_offer_string(int data_pipe) {
struct pollfd fds;
fds.fd = data_pipe;
fds.events = POLLIN;
double start = glfwGetTime();
monotonic_t start = glfwGetTime();
#define bail(...) { \
_glfwInputError(GLFW_PLATFORM_ERROR, __VA_ARGS__); \
free(buf); buf = NULL; \
@@ -1504,7 +1524,7 @@ static char* read_offer_string(int data_pipe) {
return NULL; \
}
while (glfwGetTime() - start < 2) {
while (glfwGetTime() - start < s_to_monotonic_t(2ll)) {
int ret = poll(&fds, 1, 2000);
if (ret == -1) {
if (errno == EINTR) continue;
@@ -1836,7 +1856,7 @@ static inline bool _glfwEnsureDataDevice(void) {
if (!_glfw.wl.dataDevice)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Cannot use clipboard, failed to create data device");
"Wayland: Cannot use clipboard, failed to create data device");
return false;
}
}
@@ -2031,7 +2051,7 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle)
return window->wl.surface;
}
GLFWAPI int glfwGetXKBScancode(const char* keyName, bool caseSensitive) {
GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) {
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
}

16
glfw/x11_init.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 X11 - www.glfw.org
// GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -433,12 +433,10 @@ static bool initExtensions(void)
//
void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, bool bypass_cache)
{
// NOTE: Default to the display-wide DPI as we don't currently have a policy
// for which monitor a window is considered to be on
float xdpi = DisplayWidth(_glfw.x11.display, _glfw.x11.screen) *
25.4f / DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
float ydpi = DisplayHeight(_glfw.x11.display, _glfw.x11.screen) *
25.4f / DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
// Start by assuming the default X11 DPI
// NOTE: Some desktop environments (KDE) may remove the Xft.dpi field when it
// would be set to 96, so assume that is the case if we cannot find it
float xdpi = 96.f, ydpi = 96.f;
// NOTE: Basing the scale on Xft.dpi where available should provide the most
// consistent user experience (matches Qt, Gtk, etc), although not
@@ -468,7 +466,7 @@ void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, bool bypass_cac
if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
{
if (type && strcmp(type, "String") == 0)
xdpi = ydpi = atof(value.addr);
xdpi = ydpi = (float)atof(value.addr);
}
XrmDestroyDatabase(db);
@@ -637,8 +635,6 @@ int _glfwPlatformInit(void)
}
#endif
_glfwInitTimerPOSIX();
_glfwPollMonitorsX11();
return true;
}

12
glfw/x11_monitor.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 X11 - www.glfw.org
// GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -166,6 +166,16 @@ void _glfwPollMonitorsX11(void)
heightMM = oi->mm_height;
}
if (widthMM <= 0 || heightMM <= 0)
{
// HACK: If RandR does not provide a physical size, assume the
// X11 default 96 DPI and calcuate from the CRTC viewport
// NOTE: These members are affected by rotation, unlike the mode
// info and output info members
widthMM = (int) (ci->width * 25.4f / 96.f);
heightMM = (int) (ci->height * 25.4f / 96.f);
}
_GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
monitor->x11.output = sr->outputs[i];
monitor->x11.crtc = oi->crtc;

4
glfw/x11_platform.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 X11 - www.glfw.org
// GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -152,7 +152,6 @@ typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSur
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
#include "posix_thread.h"
#include "posix_time.h"
#include "glx_context.h"
#include "egl_context.h"
#include "osmesa_context.h"
@@ -181,6 +180,7 @@ typedef struct _GLFWwindowX11
{
Colormap colormap;
Window handle;
Window parent;
bool iconified;
bool maximized;

338
glfw/x11_window.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 X11 - www.glfw.org
// GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@@ -31,6 +31,7 @@
#include "internal.h"
#include "backend_utils.h"
#include "linux_notify.h"
#include "../kitty/monotonic.h"
#include <X11/cursorfont.h>
#include <X11/Xmd.h>
@@ -51,6 +52,10 @@
#define Button6 6
#define Button7 7
// Motif WM hints flags
#define MWM_HINTS_DECORATIONS 2
#define MWM_DECOR_ALL 1
#define _GLFW_XDND_VERSION 5
@@ -61,9 +66,9 @@
static unsigned _glfwDispatchX11Events(void);
static void
handleEvents(double timeout) {
EVDBG("starting handleEvents(%.2f)", timeout);
int display_read_ok = pollForEvents(&_glfw.x11.eventLoopData, timeout);
handleEvents(monotonic_t timeout) {
EVDBG("starting handleEvents(%.2f)", monotonic_t_to_s_double(timeout));
int display_read_ok = pollForEvents(&_glfw.x11.eventLoopData, timeout, NULL);
EVDBG("display_read_ok: %d", display_read_ok);
if (display_read_ok) {
unsigned dispatched = _glfwDispatchX11Events();
@@ -77,9 +82,9 @@ handleEvents(double timeout) {
}
static bool
waitForX11Event(double timeout) {
// returns true iff there is X11 data waiting to be read, does not run watches and timers
double end_time = glfwGetTime() + timeout;
waitForX11Event(monotonic_t timeout) {
// returns true if there is X11 data waiting to be read, does not run watches and timers
monotonic_t end_time = glfwGetTime() + timeout;
while(true) {
if (timeout >= 0) {
const int result = pollWithTimeout(_glfw.x11.eventLoopData.fds, 1, timeout);
@@ -109,7 +114,7 @@ static bool waitForVisibilityNotify(_GLFWwindow* window)
VisibilityNotify,
&dummy))
{
if (!waitForX11Event(0.1))
if (!waitForX11Event(ms_to_monotonic_t(100ll)))
return false;
}
@@ -250,6 +255,14 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
hints->min_aspect.x = hints->max_aspect.x = window->numer;
hints->min_aspect.y = hints->max_aspect.y = window->denom;
}
if (window->widthincr != GLFW_DONT_CARE &&
window->heightincr != GLFW_DONT_CARE)
{
hints->flags |= PResizeInc;
hints->width_inc = window->widthincr;
hints->height_inc = window->heightincr;
}
}
else
{
@@ -508,8 +521,8 @@ static bool createNativeWindow(_GLFWwindow* window,
if (wndconfig->scaleToMonitor)
{
width *= _glfw.x11.contentScaleX;
height *= _glfw.x11.contentScaleY;
width *= (int)_glfw.x11.contentScaleX;
height *= (int)_glfw.x11.contentScaleY;
}
// Create a colormap based on the visual used by the current context
@@ -520,46 +533,41 @@ static bool createNativeWindow(_GLFWwindow* window,
window->x11.transparent = _glfwIsVisualTransparentX11(visual);
// Create the actual window
XSetWindowAttributes wa = { 0 };
wa.colormap = window->x11.colormap;
wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
ExposureMask | FocusChangeMask | VisibilityChangeMask |
EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
_glfwGrabErrorHandlerX11();
window->x11.parent = _glfw.x11.root;
window->x11.handle = XCreateWindow(_glfw.x11.display,
_glfw.x11.root,
0, 0, // Position
width, height,
0, // Border width
depth, // Color depth
InputOutput,
visual,
CWBorderPixel | CWColormap | CWEventMask,
&wa);
_glfwReleaseErrorHandlerX11();
if (!window->x11.handle)
{
XSetWindowAttributes wa;
const unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;
wa.colormap = window->x11.colormap;
wa.border_pixel = 0;
wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
ExposureMask | FocusChangeMask | VisibilityChangeMask |
EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
_glfwGrabErrorHandlerX11();
window->x11.handle = XCreateWindow(_glfw.x11.display,
_glfw.x11.root,
0, 0,
width, height,
0, // Border width
depth, // Color depth
InputOutput,
visual,
wamask,
&wa);
_glfwReleaseErrorHandlerX11();
if (!window->x11.handle)
{
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
"X11: Failed to create window");
return false;
}
XSaveContext(_glfw.x11.display,
window->x11.handle,
_glfw.x11.context,
(XPointer) window);
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
"X11: Failed to create window");
return false;
}
XSaveContext(_glfw.x11.display,
window->x11.handle,
_glfw.x11.context,
(XPointer) window);
if (!wndconfig->decorated)
_glfwPlatformSetWindowDecorated(window, false);
@@ -589,7 +597,7 @@ static bool createNativeWindow(_GLFWwindow* window,
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &states, count);
PropModeReplace, (unsigned char*) states, count);
}
}
@@ -880,7 +888,7 @@ static const char* getSelectionString(Atom selection)
Atom actualType;
int actualFormat;
unsigned long itemCount, bytesAfter;
double start = glfwGetTime();
monotonic_t start = glfwGetTime();
XEvent notification, dummy;
XConvertSelection(_glfw.x11.display,
@@ -895,10 +903,10 @@ static const char* getSelectionString(Atom selection)
SelectionNotify,
&notification))
{
double time = glfwGetTime();
if (time - start > 2)
monotonic_t time = glfwGetTime();
if (time - start > s_to_monotonic_t(2ll))
return "";
waitForX11Event(2.0 - (time - start));
waitForX11Event(s_to_monotonic_t(2ll) - (time - start));
}
if (notification.xselection.property == None)
@@ -935,10 +943,10 @@ static const char* getSelectionString(Atom selection)
isSelPropNewValueNotify,
(XPointer) &notification))
{
double time = glfwGetTime();
if (time - start > 2)
monotonic_t time = glfwGetTime();
if (time - start > s_to_monotonic_t(2ll))
return "";
waitForX11Event(2.0 - (time - start));
waitForX11Event(s_to_monotonic_t(2ll) - (time - start));
}
XFree(data);
@@ -1177,6 +1185,12 @@ static void processEvent(XEvent *event)
switch (event->type)
{
case ReparentNotify:
{
window->x11.parent = event->xreparent.parent;
return;
}
case KeyPress:
{
UPDATE_KEYMAP_IF_NEEDED;
@@ -1370,18 +1384,28 @@ static void processEvent(XEvent *event)
window->x11.height = event->xconfigure.height;
}
if (event->xconfigure.x != window->x11.xpos ||
event->xconfigure.y != window->x11.ypos)
{
if (event->xany.send_event)
{
_glfwInputWindowPos(window,
event->xconfigure.x,
event->xconfigure.y);
int xpos = event->xconfigure.x;
int ypos = event->xconfigure.y;
window->x11.xpos = event->xconfigure.x;
window->x11.ypos = event->xconfigure.y;
}
// NOTE: ConfigureNotify events from the server are in local
// coordinates, so if we are reparented we need to translate
// the position into root (screen) coordinates
if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
{
Window dummy;
XTranslateCoordinates(_glfw.x11.display,
window->x11.parent,
_glfw.x11.root,
xpos, ypos,
&xpos, &ypos,
&dummy);
}
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
{
_glfwInputWindowPos(window, xpos, ypos);
window->x11.xpos = xpos;
window->x11.ypos = ypos;
}
return;
@@ -2029,6 +2053,14 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer UNUSED, in
XFlush(_glfw.x11.display);
}
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window, int widthincr UNUSED, int heightincr UNUSED)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
updateNormalHints(window, width, height);
XFlush(_glfw.x11.display);
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
{
_glfwPlatformGetWindowSize(window, width, height);
@@ -2066,7 +2098,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
isFrameExtentsEvent,
(XPointer) window))
{
if (!waitForX11Event(0.5))
if (!waitForX11Event(ms_to_monotonic_t(500ll)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
@@ -2103,9 +2135,9 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
*yscale = _glfw.x11.contentScaleY;
}
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
{
return 0.5;
return ms_to_monotonic_t(500ll);
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
@@ -2141,18 +2173,67 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
if (_glfw.x11.NET_WM_STATE &&
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
if (!_glfw.x11.NET_WM_STATE ||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
{
return;
}
if (_glfwPlatformWindowVisible(window))
{
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
1, 0);
XFlush(_glfw.x11.display);
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
1, 0);
}
else
{
Atom* states = NULL;
unsigned long count =
_glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_STATE,
XA_ATOM,
(unsigned char**) &states);
// NOTE: We don't check for failure as this property may not exist yet
// and that's fine (and we'll create it implicitly with append)
Atom missing[2] =
{
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ
};
unsigned long missingCount = 2;
for (unsigned long i = 0; i < count; i++)
{
for (unsigned long j = 0; j < missingCount; j++)
{
if (states[i] == missing[j])
{
missing[j] = missing[missingCount - 1];
missingCount--;
}
}
}
if (states)
XFree(states);
if (!missingCount)
return;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) missing,
missingCount);
}
XFlush(_glfw.x11.display);
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
@@ -2172,6 +2253,9 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION)
return;
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
@@ -2188,7 +2272,7 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
if (_glfw.x11.NET_ACTIVE_WINDOW)
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
else
else if (_glfwPlatformWindowVisible(window))
{
XRaiseWindow(_glfw.x11.display, window->x11.handle);
XSetInputFocus(_glfw.x11.display, window->x11.handle,
@@ -2350,33 +2434,24 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled UNUSED)
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
{
if (enabled)
struct
{
XDeleteProperty(_glfw.x11.display,
window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS);
}
else
{
struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} hints;
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} hints = {0};
hints.flags = 2; // Set decorations
hints.decorations = 0; // No decorations
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = enabled ? MWM_DECOR_ALL : 0;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(hints) / sizeof(long));
}
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(hints) / sizeof(long));
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
@@ -2386,7 +2461,7 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
if (_glfwPlatformWindowVisible(window))
{
const Atom action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
const long action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
action,
@@ -2395,15 +2470,16 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
}
else
{
Atom* states;
Atom* states = NULL;
unsigned long i, count;
count = _glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_STATE,
XA_ATOM,
(unsigned char**) &states);
if (!states)
return;
// NOTE: We don't check for failure as this property may not exist yet
// and that's fine (and we'll create it implicitly with append)
if (enabled)
{
@@ -2413,32 +2489,36 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
break;
}
if (i == count)
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
1);
}
if (i < count)
return;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
1);
}
else
else if (states)
{
for (i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
{
states[i] = states[count - 1];
count--;
}
break;
}
if (i == count)
return;
states[i] = states[count - 1];
count--;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &states, count);
PropModeReplace, (unsigned char*) states, count);
}
XFree(states);
if (states)
XFree(states);
}
XFlush(_glfw.x11.display);
@@ -2512,7 +2592,7 @@ _glfwDispatchX11Events(void) {
}
XFlush(_glfw.x11.display);
// XFlush can cause events to be queued, we dont use QueuedAfterFlush here
// XFlush can cause events to be queued, we don't use QueuedAfterFlush here
// as something might have inserted events into the queue, but we want to guarantee
// a flush.
dispatched += dispatch_x11_queued_events(XEventsQueued(_glfw.x11.display, QueuedAlready));
@@ -2527,11 +2607,11 @@ void _glfwPlatformPollEvents(void)
void _glfwPlatformWaitEvents(void)
{
double timeout = _glfwDispatchX11Events() ? 0 : -1;
monotonic_t timeout = _glfwDispatchX11Events() ? 0 : -1;
handleEvents(timeout);
}
void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout)
{
if (_glfwDispatchX11Events()) timeout = 0;
handleEvents(timeout);
@@ -2585,13 +2665,13 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
XFlush(_glfw.x11.display);
}
const char* _glfwPlatformGetScancodeName(int scancode)
const char* _glfwPlatformGetNativeKeyName(int native_key)
{
return glfw_xkb_keysym_name(scancode);
return glfw_xkb_keysym_name(native_key);
}
int _glfwPlatformGetKeyScancode(int key)
int _glfwPlatformGetNativeKeyForKey(int key)
{
return glfw_xkb_sym_for_key(key);
}
@@ -2870,7 +2950,7 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
return window->x11.handle;
}
GLFWAPI int glfwGetXKBScancode(const char* keyName, bool caseSensitive) {
GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) {
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
}

240
glfw/xkb_glfw.c vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 XKB - www.glfw.org
// GLFW 3.4 XKB - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
//
@@ -37,19 +37,131 @@ START_ALLOW_CASE_RANGE
#define map_key(key) \
switch(key) { \
S(space, SPACE); \
S(exclam, EXCLAM); \
S(quotedbl, DOUBLE_QUOTE); \
S(numbersign, NUMBER_SIGN); \
S(dollar, DOLLAR); \
S(ampersand, AMPERSAND); \
S(apostrophe, APOSTROPHE); \
S(parenleft, PARENTHESIS_LEFT); \
S(parenright, PARENTHESIS_RIGHT); \
S(plus, PLUS); \
S(comma, COMMA); \
S(minus, MINUS); \
S(period, PERIOD); \
S(slash, SLASH); \
R(0, 9, 0, 9); \
S(colon, COLON); \
S(semicolon, SEMICOLON); \
S(less, LESS); \
S(equal, EQUAL); \
S(greater, GREATER); \
S(at, AT); \
D(A, Z, A, Z); \
S(bracketleft, LEFT_BRACKET); \
S(backslash, BACKSLASH); \
S(bracketright, RIGHT_BRACKET); \
S(plus, PLUS); \
S(asciicircum, CIRCUMFLEX); \
S(underscore, UNDERSCORE); \
S(grave, GRAVE_ACCENT); \
R(a, z, A, Z); \
S(paragraph, PARAGRAPH); \
S(masculine, MASCULINE); \
S(agrave, A_GRAVE); \
F(Agrave, A_GRAVE); \
S(adiaeresis, A_DIAERESIS); \
F(Adiaeresis, A_DIAERESIS); \
S(aring, A_RING); \
F(Aring, A_RING); \
S(ae, AE); \
F(AE, AE); \
S(ccedilla, C_CEDILLA); \
F(Ccedilla, C_CEDILLA); \
S(egrave, E_GRAVE); \
F(Egrave, E_GRAVE); \
S(aacute, E_ACUTE); \
F(Eacute, E_ACUTE); \
S(igrave, I_GRAVE); \
F(Igrave, I_GRAVE); \
S(ntilde, N_TILDE); \
F(Ntilde, N_TILDE); \
S(ograve, O_GRAVE); \
F(Ograve, O_GRAVE); \
S(odiaeresis, O_DIAERESIS); \
F(Odiaeresis, O_DIAERESIS); \
S(oslash, O_SLASH); \
F(Oslash, O_SLASH); \
S(ugrave, U_GRAVE); \
F(Ugrave, U_GRAVE); \
S(udiaeresis, U_DIAERESIS); \
F(Udiaeresis, U_DIAERESIS); \
S(ssharp, S_SHARP); \
S(Cyrillic_a, CYRILLIC_A); \
F(Cyrillic_A, CYRILLIC_A); \
S(Cyrillic_be, CYRILLIC_BE); \
F(Cyrillic_BE, CYRILLIC_BE); \
S(Cyrillic_ve, CYRILLIC_VE); \
F(Cyrillic_VE, CYRILLIC_VE); \
S(Cyrillic_ghe, CYRILLIC_GHE); \
F(Cyrillic_GHE, CYRILLIC_GHE); \
S(Cyrillic_de, CYRILLIC_DE); \
F(Cyrillic_DE, CYRILLIC_DE); \
S(Cyrillic_ie, CYRILLIC_IE); \
F(Cyrillic_IE, CYRILLIC_IE); \
S(Cyrillic_zhe, CYRILLIC_ZHE); \
F(Cyrillic_ZHE, CYRILLIC_ZHE); \
S(Cyrillic_ze, CYRILLIC_ZE); \
F(Cyrillic_ZE, CYRILLIC_ZE); \
S(Cyrillic_i, CYRILLIC_I); \
F(Cyrillic_I, CYRILLIC_I); \
S(Cyrillic_shorti, CYRILLIC_SHORT_I); \
F(Cyrillic_SHORTI, CYRILLIC_SHORT_I); \
S(Cyrillic_ka, CYRILLIC_KA); \
F(Cyrillic_KA, CYRILLIC_KA); \
S(Cyrillic_el, CYRILLIC_EL); \
F(Cyrillic_EL, CYRILLIC_EL); \
S(Cyrillic_em, CYRILLIC_EM); \
F(Cyrillic_EM, CYRILLIC_EM); \
S(Cyrillic_en, CYRILLIC_EN); \
F(Cyrillic_EN, CYRILLIC_EN); \
S(Cyrillic_o, CYRILLIC_O); \
F(Cyrillic_O, CYRILLIC_O); \
S(Cyrillic_pe, CYRILLIC_PE); \
F(Cyrillic_PE, CYRILLIC_PE); \
S(Cyrillic_er, CYRILLIC_ER); \
F(Cyrillic_ER, CYRILLIC_ER); \
S(Cyrillic_es, CYRILLIC_ES); \
F(Cyrillic_ES, CYRILLIC_ES); \
S(Cyrillic_te, CYRILLIC_TE); \
F(Cyrillic_TE, CYRILLIC_TE); \
S(Cyrillic_u, CYRILLIC_U); \
F(Cyrillic_U, CYRILLIC_U); \
S(Cyrillic_ef, CYRILLIC_EF); \
F(Cyrillic_EF, CYRILLIC_EF); \
S(Cyrillic_ha, CYRILLIC_HA); \
F(Cyrillic_HA, CYRILLIC_HA); \
S(Cyrillic_tse, CYRILLIC_TSE); \
F(Cyrillic_TSE, CYRILLIC_TSE); \
S(Cyrillic_che, CYRILLIC_CHE); \
F(Cyrillic_CHE, CYRILLIC_CHE); \
S(Cyrillic_sha, CYRILLIC_SHA); \
F(Cyrillic_SHA, CYRILLIC_SHA); \
S(Cyrillic_shcha, CYRILLIC_SHCHA); \
F(Cyrillic_SHCHA, CYRILLIC_SHCHA); \
S(Cyrillic_hardsign, CYRILLIC_HARD_SIGN); \
F(Cyrillic_HARDSIGN, CYRILLIC_HARD_SIGN); \
S(Cyrillic_yeru, CYRILLIC_YERU); \
F(Cyrillic_YERU, CYRILLIC_YERU); \
S(Cyrillic_softsign, CYRILLIC_SOFT_SIGN); \
F(Cyrillic_SOFTSIGN, CYRILLIC_SOFT_SIGN); \
S(Cyrillic_e, CYRILLIC_E); \
F(Cyrillic_E, CYRILLIC_E); \
S(Cyrillic_yu, CYRILLIC_YU); \
F(Cyrillic_YU, CYRILLIC_YU); \
S(Cyrillic_ya, CYRILLIC_YA); \
F(Cyrillic_YA, CYRILLIC_YA); \
S(Cyrillic_io, CYRILLIC_IO); \
F(Cyrillic_IO, CYRILLIC_IO); \
S(Escape, ESCAPE); \
S(Return, ENTER); \
S(Tab, TAB); \
@@ -91,9 +203,6 @@ START_ALLOW_CASE_RANGE
S(Alt_R, RIGHT_ALT); \
S(Super_R, RIGHT_SUPER); \
S(Menu, MENU); \
R(0, 9, 0, 9); \
R(a, z, A, Z); \
D(A, Z, A, Z); \
R(F1, F25, F1, F25); \
R(KP_0, KP_9, KP_0, KP_9); \
@@ -329,24 +438,22 @@ glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_m
}
bool
glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) {
glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t keycode) {
#ifdef _GLFW_WAYLAND
scancode += 8;
keycode += 8;
#endif
return xkb_keymap_key_repeats(xkb->keymap, scancode);
return xkb_keymap_key_repeats(xkb->keymap, keycode);
}
static KeyEvent key_event = {0};
static inline xkb_keysym_t
compose_symbol(struct xkb_compose_state *composeState, xkb_keysym_t sym, int *compose_completed) {
compose_symbol(struct xkb_compose_state *composeState, xkb_keysym_t sym, int *compose_completed, char *key_text, int n) {
*compose_completed = 0;
if (sym == XKB_KEY_NoSymbol || !composeState) return sym;
if (xkb_compose_state_feed(composeState, sym) != XKB_COMPOSE_FEED_ACCEPTED) return sym;
switch (xkb_compose_state_get_status(composeState)) {
case XKB_COMPOSE_COMPOSED:
xkb_compose_state_get_utf8(composeState, key_event.text, sizeof(key_event.text));
xkb_compose_state_get_utf8(composeState, key_text, n);
*compose_completed = 1;
return xkb_compose_state_get_one_sym(composeState);
case XKB_COMPOSE_COMPOSING:
@@ -426,66 +533,74 @@ glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, i
}
void
glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed) {
glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed) {
_GLFWwindow *window = _glfwWindowForId(ev->window_id);
if (failed && window && window->callbacks.keyboard) {
// notify application to remove any existing pre-edit text
window->callbacks.keyboard((GLFWwindow*) window, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0, "", 1);
GLFWkeyevent fake_ev;
_glfwInitializeKeyEvent(&fake_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0);
fake_ev.ime_state = 1;
window->callbacks.keyboard((GLFWwindow*) window, &fake_ev);
}
static xkb_keycode_t last_handled_press_keycode = 0;
// We filter out release events that correspond to the last press event
// handled by the IME system. This wont fix the case of multiple key
// handled by the IME system. This won't fix the case of multiple key
// presses before a release, but is better than nothing. For that case
// you'd need to implement a ring buffer to store pending key presses.
xkb_keycode_t prev_handled_press = last_handled_press_keycode;
last_handled_press_keycode = 0;
bool is_release = ev->action == GLFW_RELEASE;
debug("From IBUS: scancode: 0x%x name: %s is_release: %d\n", ev->keycode, glfw_xkb_keysym_name(ev->keysym), is_release);
if (window && !handled_by_ime && !(is_release && ev->keycode == prev_handled_press)) {
bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
debug("From IBUS: native_key: 0x%x name: %s is_release: %d\n", ev->glfw_ev.native_key, glfw_xkb_keysym_name(ev->glfw_ev.key), is_release);
if (window && !handled_by_ime && !(is_release && ev->glfw_ev.native_key == (int) prev_handled_press)) {
debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n",
ev->glfw_keycode, _glfwGetKeyName(ev->glfw_keycode), ev->keysym, glfw_xkb_keysym_name(ev->keysym),
(ev->action == GLFW_RELEASE ? "RELEASE" : (ev->action == GLFW_PRESS ? "PRESS" : "REPEAT")),
format_mods(ev->glfw_modifiers), ev->text
ev->glfw_ev.native_key, _glfwGetKeyName(ev->glfw_ev.native_key), ev->glfw_ev.key, glfw_xkb_keysym_name(ev->glfw_ev.key),
(ev->glfw_ev.action == GLFW_RELEASE ? "RELEASE" : (ev->glfw_ev.action == GLFW_PRESS ? "PRESS" : "REPEAT")),
format_mods(ev->glfw_ev.mods), ev->glfw_ev.text
);
_glfwInputKeyboard(window, ev->glfw_keycode, ev->keysym, ev->action, ev->glfw_modifiers, ev->text, 0);
ev->glfw_ev.ime_state = 0;
_glfwInputKeyboard(window, &ev->glfw_ev);
} else debug("↳ discarded\n");
if (!is_release && handled_by_ime) last_handled_press_keycode = ev->keycode;
if (!is_release && handled_by_ime)
last_handled_press_keycode = ev->glfw_ev.native_key;
}
void
glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action) {
glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t xkb_keycode, int action) {
static char key_text[64] = {0};
const xkb_keysym_t *syms, *clean_syms, *default_syms;
xkb_keysym_t glfw_sym;
xkb_keycode_t code_for_sym = scancode;
key_event.ibus_keycode = scancode;
xkb_keysym_t xkb_sym;
xkb_keycode_t code_for_sym = xkb_keycode, ibus_keycode = xkb_keycode;
GLFWkeyevent glfw_ev;
_glfwInitializeKeyEvent(&glfw_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0); // init with default values
#ifdef _GLFW_WAYLAND
code_for_sym += 8;
#else
key_event.ibus_keycode -= 8;
ibus_keycode -= 8;
#endif
debug("%s scancode: 0x%x ", action == GLFW_RELEASE ? "Release" : "Press", scancode);
debug("%s xkb_keycode: 0x%x ", action == GLFW_RELEASE ? "Release" : "Press", xkb_keycode);
XKBStateGroup *sg = &xkb->states;
int num_syms = xkb_state_key_get_syms(sg->state, code_for_sym, &syms);
int num_clean_syms = xkb_state_key_get_syms(sg->clean_state, code_for_sym, &clean_syms);
key_event.text[0] = 0;
key_text[0] = 0;
// According to the documentation of xkb_compose_state_feed it does not
// support multi-sym events, so we ignore them
if (num_syms != 1 || num_clean_syms != 1) {
debug("num_syms: %d num_clean_syms: %d ignoring event\n", num_syms, num_clean_syms);
return;
}
glfw_sym = clean_syms[0];
xkb_sym = clean_syms[0];
debug("clean_sym: %s ", glfw_xkb_keysym_name(clean_syms[0]));
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
const char *text_type = "composed_text";
int compose_completed;
glfw_sym = compose_symbol(sg->composeState, syms[0], &compose_completed);
if (glfw_sym == XKB_KEY_NoSymbol && !compose_completed) {
xkb_sym = compose_symbol(sg->composeState, syms[0], &compose_completed, key_text, sizeof(key_text));
if (xkb_sym == XKB_KEY_NoSymbol && !compose_completed) {
debug("compose not complete, ignoring.\n");
return;
}
debug("composed_sym: %s ", glfw_xkb_keysym_name(glfw_sym));
if (glfw_sym == syms[0]) { // composed sym is the same as non-composed sym
debug("composed_sym: %s ", glfw_xkb_keysym_name(xkb_sym));
if (xkb_sym == syms[0]) { // composed sym is the same as non-composed sym
// Only use the clean_sym if no mods other than the mods we report
// are active (for example if ISO_Shift_Level_* mods are active
// they are not reported by GLFW so the key should be the shifted
@@ -493,37 +608,58 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t
xkb_mod_mask_t consumed_unknown_mods = xkb_state_key_get_consumed_mods(sg->state, code_for_sym) & sg->activeUnknownModifiers;
if (sg->activeUnknownModifiers) debug("%s", format_xkb_mods(xkb, "active_unknown_mods", sg->activeUnknownModifiers));
if (consumed_unknown_mods) { debug("%s", format_xkb_mods(xkb, "consumed_unknown_mods", consumed_unknown_mods)); }
else glfw_sym = clean_syms[0];
else xkb_sym = clean_syms[0];
// xkb returns text even if alt and/or super are pressed
if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) & sg->modifiers) == 0) xkb_state_key_get_utf8(sg->state, code_for_sym, key_event.text, sizeof(key_event.text));
if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) & sg->modifiers) == 0) {
xkb_state_key_get_utf8(sg->state, code_for_sym, key_text, sizeof(key_text));
}
text_type = "text";
}
if ((1 <= key_event.text[0] && key_event.text[0] <= 31) || key_event.text[0] == 127) key_event.text[0] = 0; // don't send text for ascii control codes
if (key_event.text[0]) { debug("%s: %s ", text_type, key_event.text); }
if ((1 <= key_text[0] && key_text[0] <= 31) || key_text[0] == 127) {
key_text[0] = 0; // don't send text for ascii control codes
}
if (key_text[0]) { debug("%s: %s ", text_type, key_text); }
}
int glfw_keycode = glfw_key_for_sym(glfw_sym);
int glfw_sym = glfw_key_for_sym(xkb_sym);
bool is_fallback = false;
if (glfw_keycode == GLFW_KEY_UNKNOWN && !key_event.text[0]) {
if (glfw_sym == GLFW_KEY_UNKNOWN && !key_text[0]) {
int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
if (num_default_syms > 0) {
glfw_sym = default_syms[0];
glfw_keycode = glfw_key_for_sym(glfw_sym);
xkb_sym = default_syms[0];
glfw_sym = glfw_key_for_sym(xkb_sym);
is_fallback = true;
}
}
debug(
"%s%s: %d (%s) xkb_key: %d (%s)\n",
format_mods(sg->modifiers),
is_fallback ? "glfw_fallback_key" : "glfw_key", glfw_keycode, _glfwGetKeyName(glfw_keycode),
glfw_sym, glfw_xkb_keysym_name(glfw_sym)
is_fallback ? "glfw_fallback_key" : "glfw_key", glfw_sym, _glfwGetKeyName(glfw_sym),
xkb_sym, glfw_xkb_keysym_name(xkb_sym)
);
key_event.action = action; key_event.glfw_modifiers = sg->modifiers;
key_event.keycode = scancode; key_event.keysym = glfw_sym;
key_event.window_id = window->id; key_event.glfw_keycode = glfw_keycode;
key_event.ibus_sym = syms[0];
if (ibus_process_key(&key_event, &xkb->ibus)) {
debug("↳ to IBUS: keycode: 0x%x keysym: 0x%x (%s) %s\n", key_event.ibus_keycode, key_event.ibus_sym, glfw_xkb_keysym_name(key_event.ibus_sym), format_mods(key_event.glfw_modifiers));
// NOTE: On linux, the reported native key identifier is the XKB keysym value.
// Do not confuse `native_key` with `xkb_keycode` (the native keycode reported for the
// glfw event VS the X internal code for a key).
//
// We use the XKB keysym instead of the X keycode to be able to go back-and-forth between
// the GLFW keysym and the XKB keysym when needed, which is not possible using the X keycode,
// because of the lost information when resolving the keycode to the keysym, like consumed
// mods.
glfw_ev.native_key = xkb_sym;
glfw_ev.action = action;
glfw_ev.key = glfw_sym;
glfw_ev.mods = sg->modifiers;
glfw_ev.text = key_text;
_GLFWIBUSKeyEvent ibus_ev;
ibus_ev.glfw_ev = glfw_ev;
ibus_ev.ibus_keycode = ibus_keycode;
ibus_ev.window_id = window->id;
ibus_ev.ibus_keysym = syms[0];
if (ibus_process_key(&ibus_ev, &xkb->ibus)) {
debug("↳ to IBUS: keycode: 0x%x keysym: 0x%x (%s) %s\n", ibus_ev.ibus_keycode, ibus_ev.ibus_keysym, glfw_xkb_keysym_name(ibus_ev.ibus_keysym), format_mods(ibus_ev.glfw_ev.mods));
} else {
_glfwInputKeyboard(window, glfw_keycode, glfw_sym, action, sg->modifiers, key_event.text, 0);
_glfwInputKeyboard(window, &glfw_ev);
}
}

12
glfw/xkb_glfw.h vendored
View File

@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.3 XKB - www.glfw.org
// GLFW 3.4 XKB - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
//
@@ -67,8 +67,8 @@ typedef struct {
#ifdef _GLFW_X11
int32_t keyboard_device_id;
bool available;
bool detectable;
bool available;
bool detectable;
int majorOpcode;
int eventBase;
int errorBase;
@@ -87,10 +87,10 @@ void glfw_xkb_release(_GLFWXKBData *xkb);
bool glfw_xkb_create_context(_GLFWXKBData *xkb);
bool glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str);
void glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_mask_t latched, xkb_mod_mask_t locked, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group);
bool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode);
bool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t keycode);
const char* glfw_xkb_keysym_name(xkb_keysym_t sym);
xkb_keysym_t glfw_xkb_sym_for_key(int key);
void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action);
void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t keycode, int action);
int glfw_xkb_keysym_from_name(const char *name, bool case_sensitive);
void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d);
void glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed);
void glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed);

View File

@@ -2,14 +2,17 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import atexit
import os
import signal
import subprocess
import sys
import tempfile
import warnings
from collections import defaultdict
from contextlib import suppress
from functools import partial
from gettext import gettext as _
from contextlib import suppress
from kitty.cli import CONFIG_HELP, parse_args
from kitty.constants import appname
@@ -506,7 +509,7 @@ def showwarning(message, category, filename, lineno, file=None, line=None):
showwarning.warnings = []
help_text = 'Show a side-by-side diff of the specified files/directories'
help_text = 'Show a side-by-side diff of the specified files/directories. You can also use ssh:hostname:remote-file-path to diff remote files.'
usage = 'file_or_directory_left file_or_directory_right'
@@ -516,6 +519,20 @@ def terminate_processes(processes):
os.kill(pid, signal.SIGKILL)
def get_remote_file(path):
if path.startswith('ssh:'):
parts = path.split(':', 2)
if len(parts) == 3:
hostname, rpath = parts[1:]
with tempfile.NamedTemporaryFile(suffix='-' + os.path.basename(rpath), prefix='remote:', delete=False) as tf:
atexit.register(os.remove, tf.name)
p = subprocess.Popen(['ssh', hostname, 'cat', rpath], stdout=tf)
if p.wait() != 0:
raise SystemExit(p.returncode)
return tf.name
return path
def main(args):
warnings.showwarning = showwarning
args, items = parse_args(args[1:], OPTIONS, usage, help_text, 'kitty +kitten diff')
@@ -528,6 +545,7 @@ def main(args):
opts = init_config(args)
set_diff_command(opts.diff_cmd)
lines_for_path.replace_tab_by = opts.replace_tab_by
left, right = map(get_remote_file, (left, right))
for f in left, right:
if not os.path.exists(f):
raise SystemExit('{} does not exist'.format(f))

View File

@@ -20,35 +20,42 @@ from ..tui.loop import Loop
from ..tui.operations import faint, styled
URL_PREFIXES = 'http https file ftp'.split()
HINT_ALPHABET = string.digits + string.ascii_lowercase
DEFAULT_HINT_ALPHABET = string.digits + string.ascii_lowercase
DEFAULT_REGEX = r'(?m)^\s*(.+)\s*$'
screen_size = screen_size_function()
class Mark:
__slots__ = ('index', 'start', 'end', 'text')
__slots__ = ('index', 'start', 'end', 'text', 'groupdict')
def __init__(self, index, start, end, text):
def __init__(self, index, start, end, text, groupdict):
self.index, self.start, self.end = index, start, end
self.text = text
self.groupdict = groupdict
@lru_cache(maxsize=2048)
def encode_hint(num):
def encode_hint(num, alphabet):
res = ''
d = len(HINT_ALPHABET)
d = len(alphabet)
while not res or num > 0:
num, i = divmod(num, d)
res = HINT_ALPHABET[i] + res
res = alphabet[i] + res
return res
def decode_hint(x):
return int(x, 36)
def decode_hint(x, alphabet=DEFAULT_HINT_ALPHABET):
base = len(alphabet)
index_map = {c: i for i, c in enumerate(alphabet)}
i = 0
for char in x:
i = i * base + index_map[char]
return i
def highlight_mark(m, text, current_input):
hint = encode_hint(m.index)
def highlight_mark(m, text, current_input, alphabet):
hint = encode_hint(m.index, alphabet)
if current_input and not hint.startswith(current_input):
return faint(text)
hint = hint[len(current_input):] or ' '
@@ -63,11 +70,11 @@ def highlight_mark(m, text, current_input):
)
def render(text, current_input, all_marks, ignore_mark_indices):
def render(text, current_input, all_marks, ignore_mark_indices, alphabet):
for mark in reversed(all_marks):
if mark.index in ignore_mark_indices:
continue
mtext = highlight_mark(mark, text[mark.start:mark.end], current_input)
mtext = highlight_mark(mark, text[mark.start:mark.end], current_input, alphabet)
text = text[:mark.start] + mtext + text[mark.end:]
text = text.replace('\0', '')
@@ -79,6 +86,7 @@ class Hints(Handler):
def __init__(self, text, all_marks, index_map, args):
self.text, self.index_map = text, index_map
self.alphabet = args.alphabet or DEFAULT_HINT_ALPHABET
self.all_marks = all_marks
self.ignore_mark_indices = set()
self.args = args
@@ -88,6 +96,14 @@ class Hints(Handler):
self.chosen = []
self.reset()
@property
def text_matches(self):
return [m.text + self.match_suffix for m in self.chosen]
@property
def groupdicts(self):
return [m.groupdict for m in self.chosen]
def get_match_suffix(self, args):
if args.add_trailing_space == 'always':
return ' '
@@ -111,16 +127,16 @@ class Hints(Handler):
def on_text(self, text, in_bracketed_paste):
changed = False
for c in text:
if c in HINT_ALPHABET:
if c in self.alphabet:
self.current_input += c
changed = True
if changed:
matches = [
m for idx, m in self.index_map.items()
if encode_hint(idx).startswith(self.current_input)
if encode_hint(idx, self.alphabet).startswith(self.current_input)
]
if len(matches) == 1:
self.chosen.append(matches[0].text + self.match_suffix)
self.chosen.append(matches[0])
if self.multiple:
self.ignore_mark_indices.add(matches[0].index)
self.reset()
@@ -137,8 +153,8 @@ class Hints(Handler):
self.draw_screen()
elif key_event is enter_key and self.current_input:
try:
idx = decode_hint(self.current_input)
self.chosen.append(self.index_map[idx].text + self.match_suffix)
idx = decode_hint(self.current_input, self.alphabet)
self.chosen.append(self.index_map[idx])
self.ignore_mark_indices.add(idx)
except Exception:
self.current_input = ''
@@ -164,18 +180,19 @@ class Hints(Handler):
def draw_screen(self):
if self.current_text is None:
self.current_text = render(self.text, self.current_input, self.all_marks, self.ignore_mark_indices)
self.current_text = render(self.text, self.current_input, self.all_marks, self.ignore_mark_indices, self.alphabet)
self.cmd.clear_screen()
self.write(self.current_text)
def regex_finditer(pat, minimum_match_length, text):
has_named_groups = bool(pat.groupindex)
for m in pat.finditer(text):
s, e = m.span(pat.groups)
s, e = m.span(0 if has_named_groups else pat.groups)
while e > s + 1 and text[e-1] == '\0':
e -= 1
if e - s >= minimum_match_length:
yield s, e
yield s, e, m.groupdict()
closing_bracket_map = {'(': ')', '[': ']', '{': '}', '<': '>', '*': '*', '"': '"', "'": "'"}
@@ -234,21 +251,23 @@ def quotes(text, s, e):
def mark(pattern, post_processors, text, args):
pat = re.compile(pattern)
for idx, (s, e) in enumerate(regex_finditer(pat, args.minimum_match_length, text)):
for idx, (s, e, groupdict) in enumerate(regex_finditer(pat, args.minimum_match_length, text)):
for func in post_processors:
s, e = func(text, s, e)
mark_text = text[s:e].replace('\n', '').replace('\0', '')
yield Mark(idx, s, e, mark_text)
yield Mark(idx, s, e, mark_text, groupdict)
def run_loop(args, text, all_marks, index_map):
def run_loop(args, text, all_marks, index_map, extra_cli_args=()):
loop = Loop()
handler = Hints(text, all_marks, index_map, args)
loop.loop(handler)
if handler.chosen and loop.return_code == 0:
return {'match': handler.chosen, 'program': args.program,
'multiple_joiner': args.multiple_joiner,
'type': args.type}
return {
'match': handler.text_matches, 'programs': args.program,
'multiple_joiner': args.multiple_joiner, 'customize_processing': args.customize_processing,
'type': args.type, 'groupdicts': handler.groupdicts, 'extra_cli_args': extra_cli_args, 'linenum_action': args.linenum_action
}
raise SystemExit(loop.return_code)
@@ -305,11 +324,44 @@ def parse_input(text):
return convert_text(text, cols)
def run(args, text):
def linenum_marks(text, args, Mark, extra_cli_args, *a):
regex = args.regex
if regex == DEFAULT_REGEX:
regex = r'(?P<path>(?:\S*/\S+)|(?:\S+[.][a-zA-Z0-9]{2,7})):(?P<line>\d+)'
yield from mark(regex, [brackets, quotes], text, args)
def load_custom_processor(customize_processing):
if customize_processing.startswith('::import::'):
import importlib
m = importlib.import_module(customize_processing[len('::import::'):])
return {k: getattr(m, k) for k in dir(m)}
if customize_processing == '::linenum::':
return {'mark': linenum_marks, 'handle_result': linenum_handle_result}
from kitty.constants import config_dir
customize_processing = os.path.expandvars(os.path.expanduser(customize_processing))
if os.path.isabs(customize_processing):
custom_path = customize_processing
else:
custom_path = os.path.join(config_dir, customize_processing)
import runpy
return runpy.run_path(custom_path, run_name='__main__')
def run(args, text, extra_cli_args=()):
try:
pattern, post_processors = functions_for(args)
text = parse_input(text)
all_marks = tuple(mark(pattern, post_processors, text, args))
pattern, post_processors = functions_for(args)
if args.type == 'linenum':
args.customize_processing = '::linenum::'
if args.customize_processing:
m = load_custom_processor(args.customize_processing)
if 'mark' in m:
all_marks = tuple(m['mark'](text, args, Mark, extra_cli_args))
else:
all_marks = tuple(mark(pattern, post_processors, text, args))
else:
all_marks = tuple(mark(pattern, post_processors, text, args))
if not all_marks:
input(_('No {} found, press Enter to quit.').format(
'URLs' if args.type == 'url' else 'matches'
@@ -319,7 +371,10 @@ def run(args, text):
largest_index = all_marks[-1].index
offset = max(0, args.hints_offset)
for m in all_marks:
m.index = largest_index - m.index + offset
if args.ascending:
m.index += offset
else:
m.index = largest_index - m.index + offset
index_map = {m.index: m for m in all_marks}
except Exception:
import traceback
@@ -327,42 +382,63 @@ def run(args, text):
input('Press Enter to quit.')
raise SystemExit(1)
return run_loop(args, text, all_marks, index_map)
return run_loop(args, text, all_marks, index_map, extra_cli_args)
# CLI {{{
OPTIONS = r'''
--program
default=default
type=list
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.
A value of :file:`default` will run the default open program. Can be specified
multiple times to run multiple programs.
--type
default=url
choices=url,regex,path,line,hash,word
The type of text to search for.
choices=url,regex,path,line,hash,word,linenum
The type of text to search for. A value of :code:`linenum` looks for error messages
using the pattern specified with :option:`--regex`, which must have the named groups,
path and line. If not specified, will look for :code:`path:line`.
The :option:`--linenum-action` option controls what to do with the selected error message.
--regex
default=(?m)^\s*(.+)\s*$
default={default_regex}
The regular expression to use when :option:`kitty +kitten hints --type`=regex.
If you specify a group in the regular expression only the group
will be matched. This allow you to match text ignoring a prefix/suffix, as
needed. The default expression matches lines. To match text over
multiple lines you should prefix the regular expression with :code:`(?ms)`,
which turns on MULTILINE and DOTALL modes for the regex engine.
The regular expression is in python syntax. If you specify a numbered group in
the regular expression only the group will be matched. This allow you to match
text ignoring a prefix/suffix, as needed. The default expression matches lines.
To match text over multiple lines you should prefix the regular expression with
:code:`(?ms)`, which turns on MULTILINE and DOTALL modes for the regex engine.
If you specify named groups and a :option:`kitty +kitten hints --program` then
the program will be passed arguments corresponding to each named group of
the form key=value.
--linenum-action
default=self
type=choice
choices=self,window,tab,os_window,background
The action to perform on the matched errors. The actual action is whatever
arguments are provided to the kitten, for example:
:code:`kitty + kitten hints --type=linenum vim +{line} {path}`
will open the matched path at the matched line number in vim. This option
controls where the action is executed: :code:`self` means the current window,
:code:`window` a new kitty window, :code:`tab` a new tab, :code:`os_window`
a new OS window and :code:`background` run in the background.
--url-prefixes
default={0}
default={url_prefixes}
Comma separated list of recognized URL prefixes.
--word-characters
Characters to consider as part of a word. In addition, all characters marked as
alpha-numeric in the unicode database will be considered as word characters.
alphanumeric in the unicode database will be considered as word characters.
Defaults to the select_by_word_characters setting from kitty.conf.
@@ -401,7 +477,31 @@ default=1
type=int
The offset (from zero) at which to start hint numbering. Note that only numbers
greater than or equal to zero are respected.
'''.format(','.join(sorted(URL_PREFIXES))).format
--alphabet
The list of characters to use for hints. The default is to use numbers and lowercase
English alphabets. Specify your preference as a string of characters. Note that
unless you specify the hints offset as zero the first match will be highlighted with
the second character you specify.
--ascending
type=bool-set
Have the hints increase from top to bottom instead of decreasing from top to bottom.
--customize-processing
Name of a python file in the kitty config directory which will be imported to provide
custom implementations for pattern finding and performing actions
on selected matches. See https://sw.kovidgoyal.net/kitty/kittens/hints.html
for details. You can also specify absolute paths to load the script from elsewhere.
'''.format(
default_regex=DEFAULT_REGEX, url_prefixes=','.join(sorted(URL_PREFIXES)),
line='{{line}}', path='{{path}}'
).format
help_text = 'Select text from the screen using the keyboard. Defaults to searching for URLs.'
usage = ''
@@ -427,16 +527,50 @@ def main(args):
print(e.args[0], file=sys.stderr)
input(_('Press Enter to quit'))
return
if items:
if items and not (args.customize_processing or args.type == 'linenum'):
print('Extra command line arguments present: {}'.format(' '.join(items)), file=sys.stderr)
input(_('Press Enter to quit'))
return run(args, text, items)
def linenum_handle_result(args, data, target_window_id, boss, extra_cli_args, *a):
for m, g in zip(data['match'], data['groupdicts']):
if m:
path, line = g['path'], g['line']
path = path.split(':')[-1]
line = int(line)
break
else:
return
return run(args, text)
cmd = [x.format(path=path, line=line) for x in extra_cli_args or ('vim', '+{line}', '{path}')]
w = boss.window_id_map.get(target_window_id)
action = data['linenum_action']
if action == 'self':
if w is not None:
import shlex
w.paste_bytes(shlex.join(cmd) + '\r')
elif action == 'background':
import subprocess
subprocess.Popen(cmd)
else:
getattr(boss, {
'window': 'new_window_with_cwd', 'tab': 'new_tab_with_cwd', 'os_window': 'new_os_window_with_cwd'
}[action])(*cmd)
def handle_result(args, data, target_window_id, boss):
program = data['program']
matches = tuple(filter(None, data['match']))
if data['customize_processing']:
m = load_custom_processor(data['customize_processing'])
if 'handle_result' in m:
return m['handle_result'](args, data, target_window_id, boss, data['extra_cli_args'])
programs = data['programs'] or ('default',)
matches, groupdicts = [], []
for m, g in zip(data['match'], data['groupdicts']):
if m:
matches.append(m), groupdicts.append(g)
joiner = data['multiple_joiner']
try:
is_int = int(joiner)
@@ -444,6 +578,7 @@ def handle_result(args, data, target_window_id, boss):
is_int = None
text_type = data['type']
@lru_cache()
def joined_text():
if is_int is not None:
try:
@@ -459,20 +594,25 @@ def handle_result(args, data, target_window_id, boss):
q = {'newline': '\n\r', 'space': ' '}.get(joiner, '')
return q.join(matches)
if program == '-':
w = boss.window_id_map.get(target_window_id)
if w is not None:
w.paste(joined_text())
elif program == '@':
set_clipboard_string(joined_text())
else:
cwd = None
w = boss.window_id_map.get(target_window_id)
if w is not None:
cwd = w.cwd_of_child
program = None if program == 'default' else program
for m in matches:
boss.open_url(m, program, cwd=cwd)
for program in programs:
if program == '-':
w = boss.window_id_map.get(target_window_id)
if w is not None:
w.paste(joined_text())
elif program == '@':
set_clipboard_string(joined_text())
else:
cwd = None
w = boss.window_id_map.get(target_window_id)
if w is not None:
cwd = w.cwd_of_child
program = None if program == 'default' else program
for m, groupdict in zip(matches, groupdicts):
if groupdict:
m = []
for k, v in groupdict.items():
m.append('{}={}'.format(k, v or ''))
boss.open_url(m, program, cwd=cwd)
handle_result.type_of_input = 'screen'

View File

@@ -22,7 +22,6 @@ from ..tui.images import (
)
from ..tui.operations import clear_images_on_screen, serialize_gr_command
screen_size = None
OPTIONS = '''\
--align
type=choices
@@ -94,9 +93,31 @@ but you can turn it off or on explicitly, if needed.
--silent
type=bool-set
Do not print out anything to stdout during operation.
--z-index -z
default=0
Z-index of the image. When negative, text will be displayed on top of the image. Use
a double minus for values under the threshold for drawing images under cell background
colors. For example, --1 evaluates as -1,073,741,825.
'''
screen_size = None
def get_screen_size_function():
global screen_size
if screen_size is None:
screen_size = screen_size_function()
return screen_size
def get_screen_size():
screen_size = get_screen_size_function()
return screen_size()
def options_spec():
if not hasattr(options_spec, 'ans'):
options_spec.ans = OPTIONS.format(
@@ -122,7 +143,7 @@ def calculate_in_cell_x_offset(width, cell_width, align):
def set_cursor(cmd, width, height, align):
ss = screen_size()
ss = get_screen_size()
cw = int(ss.width / ss.cols)
num_of_cells_needed = int(ceil(width / cw))
if num_of_cells_needed > ss.cols:
@@ -143,7 +164,7 @@ def set_cursor(cmd, width, height, align):
def set_cursor_for_place(place, cmd, width, height, align):
x = place.left + 1
ss = screen_size()
ss = get_screen_size()
cw = int(ss.width / ss.cols)
num_of_cells_needed = int(ceil(width / cw))
cmd['X'] = calculate_in_cell_x_offset(width, cw, align)
@@ -168,8 +189,8 @@ def write_chunked(cmd, data):
cmd.clear()
def show(outfile, width, height, fmt, transmit_mode='t', align='center', place=None):
cmd = {'a': 'T', 'f': fmt, 's': width, 'v': height}
def show(outfile, width, height, zindex, fmt, transmit_mode='t', align='center', place=None):
cmd = {'a': 'T', 'f': fmt, 's': width, 'v': height, 'z': zindex}
if place:
set_cursor_for_place(place, cmd, width, height, align)
else:
@@ -187,25 +208,36 @@ def show(outfile, width, height, fmt, transmit_mode='t', align='center', place=N
write_chunked(cmd, data)
def parse_z_index(val):
origin = 0
if val.startswith('--'):
val = val[1:]
origin = -1073741824
return origin + int(val)
def process(path, args, is_tempfile):
m = identify(path)
ss = screen_size()
ss = get_screen_size()
available_width = args.place.width * (ss.width / ss.cols) if args.place else ss.width
available_height = args.place.height * (ss.height / ss.rows) if args.place else 10 * m.height
needs_scaling = m.width > available_width or m.height > available_height
needs_scaling = needs_scaling or args.scale_up
file_removed = False
if m.fmt == 'png' and not needs_scaling:
outfile = path
transmit_mode = 't' if is_tempfile else 'f'
fmt = 100
width, height = m.width, m.height
file_removed = transmit_mode == 't'
else:
fmt = 24 if m.mode == 'rgb' else 32
transmit_mode = 't'
outfile, width, height = convert(path, m, available_width, available_height, args.scale_up)
show(outfile, width, height, fmt, transmit_mode, align=args.align, place=args.place)
show(outfile, width, height, args.z_index, fmt, transmit_mode, align=args.align, place=args.place)
if not args.place:
print() # ensure cursor is on a new line
return file_removed
def scan(d):
@@ -272,6 +304,7 @@ usage = 'image-file-or-url-or-directory ...'
def process_single_item(item, args, url_pat=None, maybe_dir=True):
is_tempfile = False
file_removed = False
try:
if isinstance(item, bytes):
tf = NamedTemporaryFile(prefix='stdin-image-data-', delete=False)
@@ -287,7 +320,7 @@ def process_single_item(item, args, url_pat=None, maybe_dir=True):
raise SystemExit('Failed to download image at URL: {} with error: {}'.format(item, e))
item = tf.name
is_tempfile = True
process(item, args, is_tempfile)
file_removed = process(item, args, is_tempfile)
elif item.lower().startswith('file://'):
from urllib.parse import urlparse
from urllib.request import url2pathname
@@ -297,20 +330,19 @@ def process_single_item(item, args, url_pat=None, maybe_dir=True):
else:
item = item.path
item = url2pathname(item)
process(item, args, is_tempfile)
file_removed = process(item, args, is_tempfile)
else:
if maybe_dir and os.path.isdir(item):
for (x, mt) in scan(item):
process_single_item(x, args, url_pat=None, maybe_dir=False)
else:
process(item, args, is_tempfile)
file_removed = process(item, args, is_tempfile)
finally:
if is_tempfile:
if is_tempfile and not file_removed:
os.remove(item)
def main(args=sys.argv):
global screen_size
args, items = parse_args(args[1:], options_spec, usage, help_text, '{} +kitten icat'.format(appname))
if args.print_window_size:
@@ -330,7 +362,7 @@ def main(args=sys.argv):
sys.stdin.close()
sys.stdin = open(os.ctermid(), 'r')
screen_size = screen_size_function()
screen_size = get_screen_size_function()
signal.signal(signal.SIGWINCH, lambda signum, frame: setattr(screen_size, 'changed', True))
if screen_size().width == 0:
if args.detect_support:
@@ -343,6 +375,11 @@ def main(args=sys.argv):
except Exception:
raise SystemExit('Not a valid place specification: {}'.format(args.place))
try:
args.z_index = parse_z_index(args.z_index)
except Exception:
raise SystemExit('Not a valid z-index specification: {}'.format(args.z_index))
if args.detect_support:
if not detect_support(wait_for=args.detection_timeout, silent=True):
raise SystemExit(1)

View File

@@ -130,8 +130,8 @@ def main(sys_args):
if not items:
raise SystemExit('You must specify the program to run')
sys.argv = ['kitty']
if args.config:
sys.argv.append('--config={}'.format(args.config))
for config in args.config:
sys.argv.append('--config={}'.format(config))
for override in args.override:
sys.argv.append('--override={}'.format(override))
sys.argv.extend(items)

View File

@@ -4,6 +4,7 @@
import os
import sys
from contextlib import suppress
from kitty.cli import parse_args
@@ -30,9 +31,8 @@ def real_main(args):
def main(args):
try:
real_main(args)
except KeyboardInterrupt:
pass
with suppress(KeyboardInterrupt):
real_main(args)
except Exception:
import traceback
traceback.print_exc()

View File

@@ -76,6 +76,9 @@ def parse_ssh_args(args):
if arg in boolean_ssh_args:
ssh_args.append(arg)
continue
if arg.startswith('-p') and arg[2:].isdigit():
ssh_args.append(arg)
continue
if arg in other_ssh_args:
if i != len(all_args) - 1:
raise SystemExit('Option {} cannot occur in the middle'.format(arg))
@@ -95,7 +98,7 @@ def parse_ssh_args(args):
def quote(x):
# we have to escape unbalanced quotes and other unparseable
# we have to escape unbalanced quotes and other unparsable
# args as they will break the shell script
# But we do not want to quote things like * or 'echo hello'
# See https://github.com/kovidgoyal/kitty/issues/1787

View File

@@ -249,7 +249,8 @@ class ImageManager:
cmd, standard_b64encode(rgba_path.encode(fsenc)))
else:
import zlib
data = open(rgba_path, 'rb').read()
with open(rgba_path, 'rb') as f:
data = f.read()
cmd['S'] = len(data)
data = zlib.compress(data)
cmd['o'] = 'z'

View File

@@ -5,25 +5,27 @@
import os
import string
import subprocess
import sys
from contextlib import suppress
from functools import lru_cache
from gettext import gettext as _
from contextlib import suppress
from kitty.cli import parse_args
from kitty.config import cached_values_for
from kitty.constants import config_dir
from kitty.utils import get_editor
from kitty.fast_data_types import wcswidth
from kitty.fast_data_types import wcswidth, is_emoji_presentation_base
from kitty.key_encoding import (
DOWN, ESCAPE, F1, F2, F3, F4, F12, LEFT, RELEASE, RIGHT, SHIFT, TAB, UP,
enter_key
)
from kitty.utils import get_editor
from ..tui.line_edit import LineEdit
from ..tui.handler import Handler
from ..tui.line_edit import LineEdit
from ..tui.loop import Loop
from ..tui.operations import (
clear_screen, colored, cursor, faint, set_line_wrapping,
set_window_title, sgr, styled
clear_screen, colored, cursor, faint, set_line_wrapping, set_window_title,
sgr, styled
)
HEX, NAME, EMOTICONS, FAVORITES = 'HEX', 'NAME', 'EMOTICONS', 'FAVORITES'
@@ -131,7 +133,8 @@ def decode_hint(x):
class Table:
def __init__(self):
def __init__(self, emoji_variation):
self.emoji_variation = emoji_variation
self.layout_dirty = True
self.last_rows = self.last_cols = -1
self.codepoints = []
@@ -161,7 +164,10 @@ class Table:
self.layout_dirty = False
def safe_chr(codepoint):
return chr(codepoint).encode('utf-8', 'replace').decode('utf-8')
ans = chr(codepoint).encode('utf-8', 'replace').decode('utf-8')
if self.emoji_variation and is_emoji_presentation_base(codepoint):
ans += self.emoji_variation
return ans
if self.mode is NAME:
def as_parts(i, codepoint):
@@ -248,8 +254,13 @@ def is_index(w):
class UnicodeInput(Handler):
def __init__(self, cached_values):
def __init__(self, cached_values, emoji_variation='none'):
self.cached_values = cached_values
self.emoji_variation = ''
if emoji_variation == 'text':
self.emoji_variation = '\ufe0e'
elif emoji_variation == 'graphic':
self.emoji_variation = '\ufe0f'
self.line_edit = LineEdit()
self.recent = list(self.cached_values.get('recent', DEFAULT_SET))
self.current_char = None
@@ -257,9 +268,17 @@ class UnicodeInput(Handler):
self.last_updated_code_point_at = None
self.choice_line = ''
self.mode = globals().get(cached_values.get('mode', 'HEX'), 'HEX')
self.table = Table()
self.table = Table(self.emoji_variation)
self.update_prompt()
@property
def resolved_current_char(self):
ans = self.current_char
if ans:
if self.emoji_variation and is_emoji_presentation_base(ord(ans[0])):
ans += self.emoji_variation
return ans
def update_codepoints(self):
codepoints = None
if self.mode is HEX:
@@ -320,8 +339,10 @@ class UnicodeInput(Handler):
self.choice_line = ''
else:
c, color = self.current_char, 'green'
if self.emoji_variation and is_emoji_presentation_base(ord(c[0])):
c += self.emoji_variation
self.choice_line = _('Chosen:') + ' {} U+{} {}'.format(
colored(c, 'green'), hex(ord(c))[2:], faint(styled(name(c) or '', italic=True)))
colored(c, 'green'), hex(ord(c[0]))[2:], faint(styled(name(c) or '', italic=True)))
self.prompt = self.prompt_template.format(colored(c, color))
def init_terminal_state(self):
@@ -475,17 +496,43 @@ class UnicodeInput(Handler):
self.refresh()
help_text = 'Input a unicode character'
usage = ''
OPTIONS = '''
--emoji-variation
type=choices
default=none
choices=none,graphic,text
Whether to use the textual or the graphical form for emoji. By default the
default form specified in the unicode standard for the symbol is used.
'''.format
def parse_unicode_input_args(args):
return parse_args(args, OPTIONS, usage, help_text, 'kitty +kitten unicode_input')
def main(args):
try:
args, items = parse_unicode_input_args(args[1:])
except SystemExit as e:
if e.code != 0:
print(e.args[0], file=sys.stderr)
input(_('Press Enter to quit'))
return
loop = Loop()
with cached_values_for('unicode-input') as cached_values:
handler = UnicodeInput(cached_values)
handler = UnicodeInput(cached_values, args.emoji_variation)
loop.loop(handler)
if handler.current_char and loop.return_code == 0:
with suppress(Exception):
handler.recent.remove(ord(handler.current_char))
recent = [ord(handler.current_char)] + handler.recent
cached_values['recent'] = recent[:len(DEFAULT_SET)]
return handler.current_char
return handler.resolved_current_char
if loop.return_code != 0:
raise SystemExit(loop.return_code)
@@ -497,10 +544,10 @@ def handle_result(args, current_char, target_window_id, boss):
if __name__ == '__main__':
import sys
if '-h' in sys.argv or '--help' in sys.argv:
print('Choose a unicode character to input into the terminal')
raise SystemExit(0)
ans = main(sys.argv)
if ans:
print(ans)
elif __name__ == '__doc__':
sys.cli_docs['usage'] = usage
sys.cli_docs['options'] = OPTIONS
sys.cli_docs['help_text'] = help_text

File diff suppressed because one or more lines are too long

View File

@@ -7,5 +7,4 @@ out vec4 color;
void main() {
color = texture(image, texcoord);
color = vec4(color.rgb, color.a);
}

View File

@@ -23,10 +23,10 @@ from .constants import (
from .fast_data_types import (
ChildMonitor, background_opacity_of, change_background_opacity,
change_os_window_state, create_os_window, current_os_window,
destroy_global_data, get_clipboard_string, global_font_size,
mark_os_window_for_close, os_window_font_size, patch_global_colors,
safe_pipe, set_clipboard_string, set_in_sequence_mode, thread_write,
toggle_fullscreen, toggle_maximized
destroy_global_data, focus_os_window, get_clipboard_string,
global_font_size, mark_os_window_for_close, os_window_font_size,
patch_global_colors, safe_pipe, set_clipboard_string, set_in_sequence_mode,
thread_write, toggle_fullscreen, toggle_maximized
)
from .keys import get_shortcut, shortcut_matches
from .layout import set_layout_options
@@ -58,9 +58,9 @@ def data_for_at(w, arg, add_wrap_markers=False):
if arg == '@selection':
return w.text_for_selection()
if arg == '@ansi':
if arg in ('@ansi', '@ansi_screen_scrollback'):
return as_text(as_ansi=True, add_history=True)
if arg == '@text':
if arg in ('@text', '@screen_scrollback'):
return as_text(add_history=True)
if arg == '@screen':
return as_text()
@@ -121,7 +121,7 @@ class Boss:
talk_fd = getattr(single_instance, 'socket', None)
talk_fd = -1 if talk_fd is None else talk_fd.fileno()
listen_fd = -1
if opts.allow_remote_control and args.listen_on:
if args.listen_on and (opts.allow_remote_control in ('y', 'socket-only')):
listen_fd = listen_on(args.listen_on)
self.child_monitor = ChildMonitor(
self.on_child_death,
@@ -146,9 +146,9 @@ class Boss:
from .fast_data_types import cocoa_set_notification_activated_callback
cocoa_set_notification_activated_callback(self.notification_activated)
def add_os_window(self, startup_session, os_window_id=None, wclass=None, wname=None, opts_for_size=None, startup_id=None):
def add_os_window(self, startup_session=None, os_window_id=None, wclass=None, wname=None, opts_for_size=None, startup_id=None):
if os_window_id is None:
opts_for_size = opts_for_size or startup_session.os_window_size or self.opts
opts_for_size = opts_for_size or getattr(startup_session, 'os_window_size', None) or self.opts
cls = wclass or self.args.cls or appname
with startup_notification_handler(do_notify=startup_id is not None, startup_id=startup_id) as pre_show_callback:
os_window_id = create_os_window(
@@ -235,7 +235,7 @@ class Boss:
if tab:
yield tab
def set_active_window(self, window):
def set_active_window(self, window, switch_os_window_if_needed=False):
for os_window_id, tm in self.os_window_map.items():
for tab in tm:
for w in tab:
@@ -243,6 +243,8 @@ class Boss:
if tab is not self.active_tab:
tm.set_active_tab(tab)
tab.set_active_window(w)
if switch_os_window_if_needed and current_os_window() != os_window_id:
focus_os_window(os_window_id, True)
return os_window_id
def _new_os_window(self, args, cwd_from=None):
@@ -276,9 +278,9 @@ class Boss:
self.child_monitor.add_child(window.id, window.child.pid, window.child.child_fd, window.screen)
self.window_id_map[window.id] = window
def _handle_remote_command(self, cmd, window=None):
def _handle_remote_command(self, cmd, window=None, from_peer=False):
response = None
if self.opts.allow_remote_control or getattr(window, 'allow_remote_control', False):
if self.opts.allow_remote_control == 'y' or from_peer or getattr(window, 'allow_remote_control', False):
try:
response = handle_cmd(self, window, cmd)
except Exception as err:
@@ -287,7 +289,7 @@ class Boss:
if not getattr(err, 'hide_traceback', False):
response['tb'] = traceback.format_exc()
else:
response = {'ok': False, 'error': 'Remote control is disabled. Add allow_remote_control yes to your kitty.conf'}
response = {'ok': False, 'error': 'Remote control is disabled. Add allow_remote_control to your kitty.conf'}
return response
def peer_message_received(self, msg):
@@ -295,7 +297,7 @@ class Boss:
cmd_prefix = '\x1bP@kitty-cmd'
if msg.startswith(cmd_prefix):
cmd = msg[len(cmd_prefix):-2]
response = self._handle_remote_command(cmd)
response = self._handle_remote_command(cmd, from_peer=True)
if response is not None:
response = (cmd_prefix + json.dumps(response) + '\x1b\\').encode('utf-8')
return response
@@ -321,6 +323,16 @@ class Boss:
if window is not None:
window.send_cmd_response(response)
def _cleanup_tab_after_window_removal(self, src_tab):
if len(src_tab) < 1:
tm = src_tab.tab_manager_ref()
if tm is not None:
tm.remove(src_tab)
src_tab.destroy()
if len(tm) == 0:
if not self.shutting_down:
mark_os_window_for_close(src_tab.os_window_id)
def on_child_death(self, window_id):
window = self.window_id_map.pop(window_id, None)
if window is None:
@@ -334,20 +346,22 @@ class Boss:
os_window_id = window.os_window_id
window.destroy()
tm = self.os_window_map.get(os_window_id)
if tm is None:
return
for tab in tm:
if window in tab:
break
else:
return
tab.remove_window(window)
if len(tab) == 0:
tm.remove(tab)
tab.destroy()
if len(tm) == 0:
if not self.shutting_down:
mark_os_window_for_close(os_window_id)
tab = None
if tm is not None:
for q in tm:
if window in q:
tab = q
break
if tab is not None:
tab.remove_window(window)
self._cleanup_tab_after_window_removal(tab)
if window.action_on_removal:
try:
window.action_on_removal(window)
except Exception:
import traceback
traceback.print_exc()
window.action_on_close = window.action_on_removal = None
def close_window(self, window=None):
if window is None:
@@ -512,27 +526,27 @@ class Boss:
if t is not None:
return t.active_window
def dispatch_special_key(self, key, scancode, action, mods):
def dispatch_special_key(self, key, native_key, action, mods):
# Handles shortcuts, return True if the key was consumed
key_action = get_shortcut(self.keymap, mods, key, scancode)
key_action = get_shortcut(self.keymap, mods, key, native_key)
if key_action is None:
sequences = get_shortcut(self.opts.sequence_map, mods, key, scancode)
sequences = get_shortcut(self.opts.sequence_map, mods, key, native_key)
if sequences:
self.pending_sequences = sequences
set_in_sequence_mode(True)
return True
else:
self.current_key_press_info = key, scancode, action, mods
self.current_key_press_info = key, native_key, action, mods
return self.dispatch_action(key_action)
def process_sequence(self, key, scancode, action, mods):
def process_sequence(self, key, native_key, action, mods):
if not self.pending_sequences:
set_in_sequence_mode(False)
remaining = {}
matched_action = None
for seq, key_action in self.pending_sequences.items():
if shortcut_matches(seq[0], mods, key, scancode):
if shortcut_matches(seq[0], mods, key, native_key):
seq = seq[1:]
if seq:
remaining[seq] = key_action
@@ -619,12 +633,12 @@ class Boss:
if tm is not None:
tm.update_tab_bar_data()
def on_drop(self, os_window_id, paths):
def on_drop(self, os_window_id, strings):
tm = self.os_window_map.get(os_window_id)
if tm is not None:
w = tm.active_window
if w is not None:
w.paste('\n'.join(paths))
w.paste('\n'.join(strings))
def on_os_window_closed(self, os_window_id, viewport_width, viewport_height):
self.cached_values['window-size'] = viewport_width, viewport_height
@@ -643,7 +657,7 @@ class Boss:
with suppress(Exception):
s.connect(address)
s.sendall(b'c')
with suppress(EnvironmentError):
with suppress(OSError):
s.shutdown(socket.SHUT_RDWR)
s.close()
@@ -670,7 +684,7 @@ class Boss:
output += str(s.linebuf.line(i))
return output
def _run_kitten(self, kitten, args=(), input_data=None, window=None):
def _run_kitten(self, kitten, args=(), input_data=None, window=None, custom_callback=None, action_on_removal=None):
orig_args, args = list(args), list(args)
from kittens.runner import create_kitten_handler
end_kitten = create_kitten_handler(kitten, orig_args)
@@ -716,8 +730,13 @@ class Boss:
},
cwd=w.cwd_of_child,
overlay_for=w.id
))
overlay_window.action_on_close = partial(self.on_kitten_finish, w.id, end_kitten)
),
copy_colors_from=w
)
wid = w.id
overlay_window.action_on_close = partial(self.on_kitten_finish, wid, custom_callback or end_kitten)
if action_on_removal is not None:
overlay_window.action_on_removal = lambda *a: action_on_removal(wid, self)
return overlay_window
def kitten(self, kitten, *args):
@@ -742,9 +761,6 @@ class Boss:
args = ['--name=tab-title', '--message', _('Enter the new title for this tab below.'), 'do_set_tab_title', str(tab.id)]
self._run_kitten('ask', args)
def show_error(self, title, msg):
self._run_kitten('show_error', args=['--title', title], input_data=msg)
def do_set_tab_title(self, title, tab_id):
tm = self.active_tab_manager
if tm is not None and title:
@@ -754,6 +770,32 @@ class Boss:
tab.set_title(title)
break
def show_error(self, title, msg):
self._run_kitten('show_error', args=['--title', title], input_data=msg)
def create_marker(self):
w = self.active_window
if w:
spec = None
def done(data, target_window_id, self):
nonlocal spec
spec = data['response']
def done2(target_window_id, self):
w = self.window_id_map.get(target_window_id)
if w is not None and spec:
try:
w.set_marker(spec)
except Exception as err:
self.show_error(_('Invalid marker specification'), str(err))
self._run_kitten('ask', [
'--name=create-marker', '--message',
_('Create marker, for example:\ntext 1 ERROR\nSee https://sw.kovidgoyal.net/kitty/marks.html\n')
],
custom_callback=done, action_on_removal=done2)
def kitty_shell(self, window_type):
cmd = ['@', kitty_exe(), '@']
if window_type == 'tab':
@@ -879,6 +921,9 @@ class Boss:
stdin = stdin.encode('utf-8')
return env, stdin
def data_for_at(self, which, window=None, add_wrap_markers=False):
return data_for_at(window or self.active_window, which, add_wrap_markers=add_wrap_markers)
def special_window_for_cmd(self, cmd, window=None, stdin=None, cwd_from=None, as_overlay=False):
w = window or self.active_window
env, stdin = self.process_stdin_source(w, stdin)
@@ -892,6 +937,25 @@ class Boss:
overlay_for = w.id if as_overlay and w.overlay_for is None else None
return SpecialWindow(cmd, stdin, cwd_from=cwd_from, overlay_for=overlay_for, env=env)
def run_background_process(self, cmd, cwd=None, env=None, stdin=None, cwd_from=None):
import subprocess
if cwd_from:
with suppress(Exception):
cwd = cwd_of_process(cwd_from)
if stdin:
r, w = safe_pipe(False)
try:
subprocess.Popen(cmd, env=env, stdin=r, cwd=cwd)
except Exception:
os.close(w)
else:
thread_write(w, stdin)
finally:
os.close(r)
else:
subprocess.Popen(cmd, env=env, cwd=cwd)
def pipe(self, source, dest, exe, *args):
cmd = [exe] + list(args)
window = self.active_window
@@ -917,24 +981,8 @@ class Boss:
func = set_clipboard_string if dest == 'clipboard' else set_primary_selection
func(stdin)
else:
import subprocess
env, stdin = self.process_stdin_source(stdin=source, window=window)
cwd = None
if cwd_from:
with suppress(Exception):
cwd = cwd_of_process(cwd_from)
if stdin:
r, w = safe_pipe(False)
try:
subprocess.Popen(cmd, env=env, stdin=r, cwd=cwd)
except Exception:
os.close(w)
else:
thread_write(w, stdin)
finally:
os.close(r)
else:
subprocess.Popen(cmd, env=env, cwd=cwd)
self.run_background_process(cmd, cwd_from=cwd_from, stdin=stdin, env=env)
def args_to_special_window(self, args, cwd_from=None):
args = list(args)
@@ -989,14 +1037,20 @@ class Boss:
def _new_window(self, args, cwd_from=None):
tab = self.active_tab
if tab is not None:
allow_remote_control = False
location = None
if args and args[0].startswith('!'):
location = args[0][1:].lower()
args = args[1:]
if args and args[0] == '@':
args = args[1:]
allow_remote_control = True
if args:
return tab.new_special_window(self.args_to_special_window(args, cwd_from=cwd_from), location=location)
return tab.new_special_window(
self.args_to_special_window(args, cwd_from=cwd_from),
location=location, allow_remote_control=allow_remote_control)
else:
return tab.new_window(cwd_from=cwd_from, location=location)
return tab.new_window(cwd_from=cwd_from, location=location, allow_remote_control=allow_remote_control)
def new_window(self, *args):
self._new_window(args)
@@ -1008,6 +1062,11 @@ class Boss:
cwd_from = w.child.pid_for_cwd if w is not None else None
self._new_window(args, cwd_from=cwd_from)
def launch(self, *args):
from kitty.launch import parse_launch_args, launch
opts, args = parse_launch_args(args)
launch(self, opts, args)
def move_tab_forward(self):
tm = self.active_tab_manager
if tm is not None:
@@ -1094,3 +1153,144 @@ class Boss:
msg = '\n'.join(map(format_bad_line, bad_lines)).rstrip()
self.show_error(_('Errors in kitty.conf'), msg)
def set_colors(self, *args):
from .cmds import parse_subcommand_cli, cmd_set_colors, set_colors
opts, items = parse_subcommand_cli(cmd_set_colors, ['set-colors'] + list(args))
payload = cmd_set_colors(None, opts, items)
set_colors(self, self.active_window, payload)
def _move_window_to(self, window=None, target_tab_id=None, target_os_window_id=None):
window = window or self.active_window
if not window:
return
src_tab = self.tab_for_window(window)
if src_tab is None:
return
if target_os_window_id == 'new':
target_os_window_id = self.add_os_window()
tm = self.os_window_map[target_os_window_id]
target_tab = tm.new_tab(empty_tab=True)
else:
target_os_window_id = target_os_window_id or current_os_window()
if target_tab_id == 'new':
tm = self.os_window_map[target_os_window_id]
target_tab = tm.new_tab(empty_tab=True)
else:
for tab in self.all_tabs:
if tab.id == target_tab_id:
target_tab = tab
target_os_window_id = tab.os_window_id
break
else:
return
underlaid_window, overlaid_window = src_tab.detach_window(window)
if underlaid_window:
target_tab.attach_window(underlaid_window)
if overlaid_window:
target_tab.attach_window(overlaid_window)
self._cleanup_tab_after_window_removal(src_tab)
target_tab.make_active()
def _move_tab_to(self, tab=None, target_os_window_id=None):
tab = tab or self.active_tab
if tab is None:
return
if target_os_window_id is None:
target_os_window_id = self.add_os_window()
tm = self.os_window_map[target_os_window_id]
target_tab = tm.new_tab(empty_tab=True)
target_tab.take_over_from(tab)
self._cleanup_tab_after_window_removal(tab)
target_tab.make_active()
def detach_window(self, *args):
if not args or args[0] == 'new':
return self._move_window_to(target_os_window_id='new')
if args[0] == 'new-tab':
return self._move_window_to(target_tab_id='new')
lines = [
'Choose a tab to move the window to',
''
]
fmt = ': {1}'
tab_id_map = {}
current_tab = self.active_tab
for i, tab in enumerate(self.all_tabs):
if tab is not current_tab:
tab_id_map[len(tab_id_map)] = tab.id
lines.append(fmt.format(i + 1, tab.title))
new_idx = len(tab_id_map) + 1
tab_id_map[new_idx - 1] = 'new'
lines.append(fmt.format(new_idx, 'New tab'))
new_idx = len(tab_id_map) + 1
tab_id_map[new_idx - 1] = None
lines.append(fmt.format(new_idx, 'New OS Window'))
def done(data, target_window_id, self):
done.tab_id = tab_id_map[int(data['groupdicts'][0]['index'])]
def done2(target_window_id, self):
if not hasattr(done, 'tab_id'):
return
tab_id = done.tab_id
target_window = None
for w in self.all_windows:
if w.id == target_window_id:
target_window = w
break
if tab_id is None:
self._move_window_to(window=target_window, target_os_window_id='new')
else:
self._move_window_to(window=target_window, target_tab_id=tab_id)
self._run_kitten(
'hints', args=(
'--ascending', '--customize-processing=::import::kitty.choose_entry',
r'--regex=(?m)^:\s+.+$',
), input_data='\r\n'.join(lines).encode('utf-8'), custom_callback=done, action_on_removal=done2
)
def detach_tab(self, *args):
if not args or args[0] == 'new':
return self._move_tab_to()
lines = [
'Choose an OS window to move the tab to',
''
]
fmt = ': {1}'
os_window_id_map = {}
current_os_window = getattr(self.active_tab, 'os_window_id', 0)
for i, osw in enumerate(self.os_window_map):
tm = self.os_window_map[osw]
if current_os_window != osw and tm.active_tab and tm.active_tab:
os_window_id_map[len(os_window_id_map)] = osw
lines.append(fmt.format(i + 1, tm.active_tab.title))
new_idx = len(os_window_id_map) + 1
os_window_id_map[new_idx - 1] = None
lines.append(fmt.format(new_idx, 'New OS Window'))
def done(data, target_window_id, self):
done.os_window_id = os_window_id_map[int(data['groupdicts'][0]['index'])]
def done2(target_window_id, self):
if not hasattr(done, 'os_window_id'):
return
os_window_id = done.os_window_id
target_tab = self.active_tab
for w in self.all_windows:
if w.id == target_window_id:
target_tab = w.tabref()
break
if target_tab and target_tab.os_window_id == os_window_id:
return
self._move_tab_to(tab=target_tab, target_os_window_id=os_window_id)
self._run_kitten(
'hints', args=(
'--ascending', '--customize-processing=::import::kitty.choose_entry',
r'--regex=(?m)^:\s+.+$',
), input_data='\r\n'.join(lines).encode('utf-8'), custom_callback=done, action_on_removal=done2
)

View File

@@ -12,6 +12,7 @@
#ifdef NEEDS_BACKROUND
in vec3 background;
in float draw_bg;
#if defined(TRANSPARENT) || defined(SPECIAL)
in float bg_alpha;
#endif
@@ -76,11 +77,13 @@ vec4 blend_onto_opaque_premul(vec3 over, float over_alpha, vec3 under) {
*
* 2a) Opaque bg with images under text
* There are multiple passes, each pass is blended onto the previous using the opaque blend func (alpha, 1- alpha):
* 1) Draw only the background -- expected output is color with alpha 1
* 2) Draw the images that are supposed to be below text. This happens in the graphics shader
* 3) Draw the special cells (selection/cursor). Output is same as from step 1, with bg_alpha 1 for special cells and 0 otherwise
* 4) Draw the foreground -- expected output is color with alpha which is blended using the opaque blend func
* 5) Draw the images that are supposed to be above text again in the graphics shader
* 1) Draw background for all cells
* 2) Draw the images that are supposed to be below both the background and text, if any. This happens in the graphics shader
* 3) Draw the background of cells that don't have the default background if any images were drawn in 2 above
4) Draw the images that are supposed to be below text but not background, again in graphics shader.
* 5) Draw the special cells (selection/cursor). Output is same as from step 1, with bg_alpha 1 for special cells and 0 otherwise
* 6) Draw the foreground -- expected output is color with alpha which is blended using the opaque blend func
* 7) Draw the images that are supposed to be above text again in the graphics shader
*
* 2b) Transparent bg with images
* First everything is rendered into a framebuffer, and then the framebauffer is blended onto
@@ -126,10 +129,10 @@ void main() {
#endif
#ifdef BACKGROUND
#ifdef TRANSPARENT
#if defined(TRANSPARENT)
final_color = vec4(background.rgb * bg_alpha, bg_alpha);
#else
final_color = vec4(background.rgb, 1.0f);
final_color = vec4(background.rgb, draw_bg);
#endif
#endif

View File

@@ -5,7 +5,10 @@
#define REVERSE_SHIFT {REVERSE_SHIFT}
#define STRIKE_SHIFT {STRIKE_SHIFT}
#define DIM_SHIFT {DIM_SHIFT}
#define MARK_SHIFT {MARK_SHIFT}
#define MARK_MASK {MARK_MASK}
#define USE_SELECTION_FG
#define NUM_COLORS 256
// Inputs {{{
layout(std140) uniform CellRenderData {
@@ -16,8 +19,11 @@ layout(std140) uniform CellRenderData {
uint xnum, ynum, cursor_fg_sprite_idx;
float cursor_x, cursor_y, cursor_w;
uint color_table[256];
uint color_table[NUM_COLORS + MARK_MASK + MARK_MASK + 2];
};
#ifdef BACKGROUND
uniform uint draw_bg_bitfield;
#endif
// Have to use fixed locations here as all variants of the cell program share the same VAO
layout(location=0) in uvec3 colors;
@@ -45,6 +51,7 @@ const uvec2 cell_pos_map[] = uvec2[4](
#ifdef NEEDS_BACKROUND
out vec3 background;
out float draw_bg;
#if defined(TRANSPARENT) || defined(SPECIAL)
out float bg_alpha;
#endif
@@ -114,7 +121,7 @@ vec3 choose_color(float q, vec3 a, vec3 b) {
return mix(b, a, q);
}
float are_integers_equal(float a, float b) { // return 1 iff equal otherwise 0
float are_integers_equal(float a, float b) { // return 1 if equal otherwise 0
float delta = abs(a - b); // delta can be 0, 1 or larger
return step(delta, 0.5); // 0 if 0.5 < delta else 1
}
@@ -151,13 +158,18 @@ void main() {
// set cell color indices {{{
uvec2 default_colors = uvec2(default_fg, default_bg);
uint text_attrs = sprite_coords[3];
uint is_inverted = ((text_attrs >> REVERSE_SHIFT) & ONE) + inverted;
uint is_reversed = ((text_attrs >> REVERSE_SHIFT) & ONE);
uint is_inverted = is_reversed + inverted;
int fg_index = fg_index_map[is_inverted];
int bg_index = 1 - fg_index;
float cell_has_cursor = is_cursor(c, r);
float is_block_cursor = step(float(cursor_fg_sprite_idx), 0.5);
float cell_has_block_cursor = cell_has_cursor * is_block_cursor;
vec3 bg = to_color(colors[bg_index], default_colors[bg_index]);
int mark = int(text_attrs >> MARK_SHIFT) & MARK_MASK;
uint has_mark = uint(step(1, float(mark)));
uint bg_as_uint = resolve_color(colors[bg_index], default_colors[bg_index]);
bg_as_uint = has_mark * color_table[NUM_COLORS + mark] + (ONE - has_mark) * bg_as_uint;
vec3 bg = color_to_vec(bg_as_uint);
// }}}
// Foreground {{{
@@ -168,17 +180,20 @@ void main() {
colored_sprite = float((sprite_coords.z & COLOR_MASK) >> 14);
// Foreground
uint resolved_fg = resolve_color(colors[fg_index], default_colors[fg_index]);
foreground = color_to_vec(resolved_fg);
uint fg_as_uint = resolve_color(colors[fg_index], default_colors[fg_index]);
fg_as_uint = has_mark * color_table[NUM_COLORS + MARK_MASK + 1 + mark] + (ONE - has_mark) * fg_as_uint;
foreground = color_to_vec(fg_as_uint);
float has_dim = float((text_attrs >> DIM_SHIFT) & ONE);
effective_text_alpha = inactive_text_alpha * mix(1.0, dim_opacity, has_dim);
float in_url = float((is_selected & TWO) >> 1);
decoration_fg = choose_color(in_url, color_to_vec(url_color), to_color(colors[2], fg_as_uint));
#ifdef USE_SELECTION_FG
// Selection
foreground = choose_color(float(is_selected & ONE), color_to_vec(highlight_fg), foreground);
vec3 selection_color = color_to_vec(highlight_fg);
foreground = choose_color(float(is_selected & ONE), selection_color, foreground);
decoration_fg = choose_color(float(is_selected & ONE), selection_color, decoration_fg);
#endif
// Underline and strike through (rendered via sprites)
float in_url = float((is_selected & TWO) >> 1);
decoration_fg = choose_color(in_url, color_to_vec(url_color), to_color(colors[2], resolved_fg));
underline_pos = choose_color(in_url, to_sprite_pos(pos, url_style, ZERO, ZERO), to_sprite_pos(pos, (text_attrs >> DECORATION_SHIFT) & THREE, ZERO, ZERO));
strike_pos = to_sprite_pos(pos, ((text_attrs >> STRIKE_SHIFT) & ONE) * FOUR, ZERO, ZERO);
@@ -193,26 +208,39 @@ void main() {
// Background {{{
#ifdef NEEDS_BACKROUND
float cell_has_non_default_bg = step(1, float(abs(bg_as_uint - default_colors[bg_index])));
draw_bg = 1;
#if defined(BACKGROUND)
background = bg;
// draw_bg_bitfield has bit 0 set to draw default bg cells and bit 1 set to draw non-default bg cells
uint draw_bg_mask = uint(2 * cell_has_non_default_bg + (1 - cell_has_non_default_bg));
draw_bg = step(1, float(draw_bg_bitfield & draw_bg_mask));
#endif
#if defined(TRANSPARENT) && !defined(SPECIAL)
// If the background color is default, set its opacity to background_opacity, otherwise it should be opaque
bg_alpha = step(0.5, float(colors[bg_index] & BYTE_MASK));
// Cursor must not be affected by background_opacity
bg_alpha = mix(bg_alpha, 1.0, cell_has_block_cursor);
#ifdef TRANSPARENT
// Set bg_alpha to background_opacity on cells that have the default background color
// Which means they must not have a block cursor or a selection or reverse video
// On other cells it should be 1. For the SPECIAL program it should be 1 on cells with
// selections/block cursor and 0 everywhere else.
float is_special_cell = cell_has_block_cursor + float(is_selected & ONE);
#ifndef SPECIAL
is_special_cell += cell_has_non_default_bg + float(is_reversed);
#endif
bg_alpha = step(0.5, is_special_cell);
#ifndef SPECIAL
bg_alpha = bg_alpha + (1.0f - bg_alpha) * background_opacity;
bg_alpha *= draw_bg;
#endif
#endif
#if defined(SPECIAL) || defined(SIMPLE)
// Selection and cursor
bg = choose_color(float(is_selected & ONE), color_to_vec(highlight_bg), bg);
background = choose_color(cell_has_block_cursor, color_to_vec(cursor_color), bg);
#ifdef SPECIAL
// bg_alpha should be 1 if cursor/selection otherwise 0
bg_alpha = mix(0.0, 1.0, step(0.5, float(is_selected & ONE) + cell_has_block_cursor));
#if !defined(TRANSPARENT) && defined(SPECIAL)
float is_special_cell = cell_has_block_cursor + float(is_selected & ONE);
bg_alpha = step(0.5, is_special_cell);
#endif
#endif

View File

@@ -11,6 +11,7 @@
#include "screen.h"
#include "fonts.h"
#include "charsets.h"
#include "monotonic.h"
#include <termios.h>
#include <unistd.h>
#include <float.h>
@@ -34,7 +35,7 @@ extern PyTypeObject Screen_Type;
#endif
#define USE_RENDER_FRAMES (global_state.has_render_frames && OPT(sync_to_monitor))
static void (*parse_func)(Screen*, PyObject*, double);
static void (*parse_func)(Screen*, PyObject*, monotonic_t);
typedef struct {
char *data;
@@ -108,12 +109,12 @@ static size_t reaped_pids_count = 0;
#define INCREF_CHILD(x) XREF_CHILD(x, Py_INCREF)
#define DECREF_CHILD(x) XREF_CHILD(x, Py_DECREF)
// The max time (in secs) to wait for events from the window system
// The max time to wait for events from the window system
// before ticking over the main loop. Negative values mean wait forever.
static double maximum_wait = -1.0;
static monotonic_t maximum_wait = -1;
static inline void
set_maximum_wait(double val) {
set_maximum_wait(monotonic_t val) {
if (val >= 0 && (val < maximum_wait || maximum_wait < 0)) maximum_wait = val;
}
@@ -168,7 +169,7 @@ dealloc(ChildMonitor* self) {
static void
wakeup_io_loop(ChildMonitor *self, bool in_signal_handler) {
wakeup_loop(&self->io_loop_data, in_signal_handler);
wakeup_loop(&self->io_loop_data, in_signal_handler, "io_loop");
}
static void* io_loop(void *data);
@@ -296,11 +297,11 @@ shutdown_monitor(ChildMonitor *self, PyObject *a UNUSED) {
}
static inline bool
do_parse(ChildMonitor *self, Screen *screen, double now) {
do_parse(ChildMonitor *self, Screen *screen, monotonic_t now) {
bool input_read = false;
screen_mutex(lock, read);
if (screen->read_buf_sz || screen->pending_mode.used) {
double time_since_new_input = now - screen->new_input_at;
monotonic_t time_since_new_input = now - screen->new_input_at;
if (time_since_new_input >= OPT(input_delay)) {
bool read_buf_full = screen->read_buf_sz >= READ_BUF_SZ;
input_read = true;
@@ -308,7 +309,7 @@ do_parse(ChildMonitor *self, Screen *screen, double now) {
if (read_buf_full) wakeup_io_loop(self, false); // Ensure the read fd has POLLIN set
screen->new_input_at = 0;
if (screen->pending_mode.activated_at) {
double time_since_pending = MAX(0, now - screen->pending_mode.activated_at);
monotonic_t time_since_pending = MAX(0, now - screen->pending_mode.activated_at);
set_maximum_wait(screen->pending_mode.wait_time - time_since_pending);
}
} else set_maximum_wait(OPT(input_delay) - time_since_new_input);
@@ -322,7 +323,7 @@ parse_input(ChildMonitor *self) {
// Parse all available input that was read in the I/O thread.
size_t count = 0, remove_count = 0;
bool input_read = false;
double now = monotonic();
monotonic_t now = monotonic();
PyObject *msg = NULL;
children_mutex(lock);
while (remove_queue_count) {
@@ -485,22 +486,22 @@ pyset_iutf8(ChildMonitor *self, PyObject *args) {
extern void cocoa_update_menu_bar_title(PyObject*);
static inline void
collect_cursor_info(CursorRenderInfo *ans, Window *w, double now, OSWindow *os_window) {
collect_cursor_info(CursorRenderInfo *ans, Window *w, monotonic_t now, OSWindow *os_window) {
ScreenRenderData *rd = &w->render_data;
Cursor *cursor = rd->screen->cursor;
ans->x = cursor->x; ans->y = cursor->y;
ans->is_visible = false;
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) return;
double time_since_start_blink = now - os_window->cursor_blink_zero_time;
monotonic_t time_since_start_blink = now - os_window->cursor_blink_zero_time;
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && os_window->is_focused && (OPT(cursor_stop_blinking_after) == 0 || time_since_start_blink <= OPT(cursor_stop_blinking_after));
bool do_draw_cursor = true;
if (cursor_blinking) {
int t = (int)(time_since_start_blink * 1000);
int d = (int)(OPT(cursor_blink_interval) * 1000);
int t = monotonic_t_to_ms(time_since_start_blink);
int d = monotonic_t_to_ms(OPT(cursor_blink_interval));
int n = t / d;
do_draw_cursor = n % 2 == 0 ? true : false;
double bucket = (n + 1) * d;
double delay = (bucket / 1000.0) - time_since_start_blink;
monotonic_t bucket = ms_to_monotonic_t((n + 1) * d);
monotonic_t delay = bucket - time_since_start_blink;
set_maximum_wait(delay);
}
if (!do_draw_cursor) { ans->is_visible = false; return; }
@@ -518,7 +519,7 @@ update_window_title(Window *w, OSWindow *os_window) {
Py_INCREF(os_window->window_title);
set_os_window_title(os_window, PyUnicode_AsUTF8(w->title));
#ifdef __APPLE__
if (os_window->is_focused && OPT(macos_show_window_title_in_menubar)) cocoa_update_menu_bar_title(w->title);
if (os_window->is_focused && (OPT(macos_show_window_title_in) & MENUBAR)) cocoa_update_menu_bar_title(w->title);
#endif
return true;
}
@@ -526,7 +527,7 @@ update_window_title(Window *w, OSWindow *os_window) {
}
static inline bool
prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *active_window_id, color_type *active_window_bg, unsigned int *num_visible_windows) {
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
bool needs_render = os_window->needs_render;
os_window->needs_render = false;
@@ -543,16 +544,22 @@ prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *activ
}
Tab *tab = os_window->tabs + os_window->active_tab;
*active_window_bg = OPT(background);
*all_windows_have_same_bg = true;
*num_visible_windows = 0;
color_type first_window_bg = 0;
for (unsigned int i = 0; i < tab->num_windows; i++) {
Window *w = tab->windows + i;
#define WD w->render_data
if (w->visible && WD.screen) {
*num_visible_windows += 1;
color_type window_bg = colorprofile_to_color(WD.screen->color_profile, WD.screen->color_profile->overridden.default_bg, WD.screen->color_profile->configured.default_bg);
if (*num_visible_windows == 1) first_window_bg = window_bg;
if (first_window_bg != window_bg) all_windows_have_same_bg = false;
if (w->last_drag_scroll_at > 0) {
if (now - w->last_drag_scroll_at >= 0.02) {
if (now - w->last_drag_scroll_at >= ms_to_monotonic_t(20ll)) {
if (drag_scroll(w, os_window)) {
w->last_drag_scroll_at = now;
set_maximum_wait(0.02);
set_maximum_wait(ms_to_monotonic_t(20ll));
needs_render = true;
} else w->last_drag_scroll_at = 0;
} else set_maximum_wait(now - w->last_drag_scroll_at);
@@ -563,7 +570,7 @@ prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *activ
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;
update_window_title(w, os_window);
*active_window_bg = colorprofile_to_color(WD.screen->color_profile, WD.screen->color_profile->overridden.default_bg, WD.screen->color_profile->configured.default_bg);
*active_window_bg = window_bg;
} 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 (WD.screen->start_visual_bell_at != 0) needs_render = true;
@@ -573,7 +580,7 @@ prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *activ
}
static inline void
render_os_window(OSWindow *os_window, double now, unsigned int active_window_id, color_type active_window_bg, unsigned int num_visible_windows) {
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) {
// ensure all pixels are cleared to background color at least once in every buffer
if (os_window->clear_count++ < 3) blank_os_window(os_window);
Tab *tab = os_window->tabs + os_window->active_tab;
@@ -581,11 +588,11 @@ render_os_window(OSWindow *os_window, double now, unsigned int active_window_id,
bool static_live_resize_in_progress = os_window->live_resize.in_progress && OPT(resize_draw_strategy) == RESIZE_DRAW_STATIC;
float x_ratio = 1, y_ratio = 1;
if (static_live_resize_in_progress) {
x_ratio = os_window->viewport_width / (double) os_window->live_resize.width;
y_ratio = os_window->viewport_height / (double) os_window->live_resize.height;
x_ratio = (float) os_window->viewport_width / (float) os_window->live_resize.width;
y_ratio = (float) os_window->viewport_height / (float) os_window->live_resize.height;
}
if (!static_live_resize_in_progress) {
draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, os_window->viewport_width, os_window->viewport_height, active_window_bg, num_visible_windows, os_window);
draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, os_window->viewport_width, os_window->viewport_height, active_window_bg, num_visible_windows, all_windows_have_same_bg, os_window);
br->is_dirty = false;
}
if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx * x_ratio, TD.dy * y_ratio, TD.screen, os_window, true, false);
@@ -595,7 +602,7 @@ render_os_window(OSWindow *os_window, double now, unsigned int active_window_id,
bool is_active_window = i == tab->active_window;
draw_cells(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx * x_ratio, WD.dy * y_ratio, WD.screen, os_window, is_active_window, true);
if (WD.screen->start_visual_bell_at != 0) {
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
monotonic_t bell_left = OPT(visual_bell_duration) - (now - WD.screen->start_visual_bell_at);
set_maximum_wait(bell_left);
}
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;
@@ -626,23 +633,23 @@ draw_resizing_text(OSWindow *w) {
snprintf(text, sizeof(text), "%u x %u cells", width / w->fonts_data->cell_width, height / w->fonts_data->cell_height);
StringCanvas rendered = render_simple_text(w->fonts_data, text);
if (rendered.canvas) {
draw_centered_alpha_mask(w->gvao_idx, width, height, rendered.width, rendered.height, rendered.canvas);
draw_centered_alpha_mask(w, width, height, rendered.width, rendered.height, rendered.canvas);
free(rendered.canvas);
}
}
static inline bool
no_render_frame_received_recently(OSWindow *w, double now, double 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;
if (ans) log_error("No render frame received in %f seconds, re-requesting at: %f", max_wait, now);
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));
return ans;
}
static inline void
render(double now, bool input_read) {
render(monotonic_t now, bool input_read) {
EVDBG("input_read: %d", input_read);
static double last_render_at = -DBL_MAX;
double time_since_last_render = now - last_render_at;
static monotonic_t last_render_at = MONOTONIC_T_MIN;
monotonic_t time_since_last_render = last_render_at == MONOTONIC_T_MIN ? OPT(repaint_delay) : now - last_render_at;
if (!input_read && time_since_last_render < OPT(repaint_delay)) {
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
return;
@@ -656,7 +663,7 @@ render(double now, bool input_read) {
continue;
}
if (USE_RENDER_FRAMES && w->render_state != RENDER_FRAME_READY) {
if (w->render_state == RENDER_FRAME_NOT_REQUESTED || no_render_frame_received_recently(w, now, 0.25)) request_frame_render(w);
if (w->render_state == RENDER_FRAME_NOT_REQUESTED || no_render_frame_received_recently(w, now, ms_to_monotonic_t(250ll))) request_frame_render(w);
continue;
}
make_os_window_context_current(w);
@@ -676,11 +683,12 @@ render(double now, bool input_read) {
needs_render = true;
}
unsigned int active_window_id = 0, num_visible_windows = 0;
bool all_windows_have_same_bg;
color_type active_window_bg = 0;
if (!w->fonts_data) { log_error("No fonts data found for window id: %llu", w->id); continue; }
if (prepare_to_render_os_window(w, now, &active_window_id, &active_window_bg, &num_visible_windows)) needs_render = true;
if (prepare_to_render_os_window(w, now, &active_window_id, &active_window_bg, &num_visible_windows, &all_windows_have_same_bg)) needs_render = true;
if (w->last_active_window_id != active_window_id || w->last_active_tab != w->active_tab || w->focused_at_last_render != w->is_focused) needs_render = true;
if (needs_render) render_os_window(w, now, active_window_id, active_window_bg, num_visible_windows);
if (needs_render) render_os_window(w, now, active_window_id, active_window_bg, num_visible_windows, all_windows_have_same_bg);
}
last_render_at = now;
#undef TD
@@ -799,7 +807,7 @@ add_python_timer(PyObject *self UNUSED, PyObject *args) {
double interval;
int repeats = 1;
if (!PyArg_ParseTuple(args, "Od|p", &callback, &interval, &repeats)) return NULL;
unsigned long long timer_id = add_main_loop_timer(interval, repeats ? true: false, python_timer_callback, callback, python_timer_cleanup);
unsigned long long timer_id = add_main_loop_timer(s_double_to_monotonic_t(interval), repeats ? true: false, python_timer_callback, callback, python_timer_cleanup);
Py_INCREF(callback);
return Py_BuildValue("K", timer_id);
}
@@ -814,7 +822,7 @@ remove_python_timer(PyObject *self UNUSED, PyObject *args) {
static inline void
process_pending_resizes(double now) {
process_pending_resizes(monotonic_t now) {
global_state.has_pending_resizes = false;
for (size_t i = 0; i < global_state.num_os_windows; i++) {
OSWindow *w = global_state.os_windows + i;
@@ -823,11 +831,11 @@ process_pending_resizes(double now) {
if (w->live_resize.from_os_notification) {
if (w->live_resize.os_says_resize_complete || (now - w->live_resize.last_resize_event_at) > 1) update_viewport = true;
} else {
double debounce_time = OPT(resize_debounce_time);
monotonic_t debounce_time = OPT(resize_debounce_time);
// if more than one resize event has occurred, wait at least 0.2 secs
// before repainting, to avoid rapid transitions between the cells banner
// and the normal screen
if (w->live_resize.num_of_resize_events > 1 && OPT(resize_draw_strategy) == RESIZE_DRAW_SIZE) debounce_time = MAX(0.2, debounce_time);
if (w->live_resize.num_of_resize_events > 1 && OPT(resize_draw_strategy) == RESIZE_DRAW_SIZE) debounce_time = MAX(ms_to_monotonic_t(200ll), debounce_time);
if (now - w->live_resize.last_resize_event_at >= debounce_time) update_viewport = true;
else {
global_state.has_pending_resizes = true;
@@ -908,10 +916,14 @@ process_global_state(void *data) {
ChildMonitor *self = data;
maximum_wait = -1;
bool state_check_timer_enabled = false;
bool input_read = false;
double now = monotonic();
if (global_state.has_pending_resizes) process_pending_resizes(now);
bool input_read = parse_input(self);
monotonic_t now = monotonic();
if (global_state.has_pending_resizes) {
process_pending_resizes(now);
input_read = true;
}
if (parse_input(self)) input_read = true;
render(now, input_read);
#ifdef __APPLE__
if (cocoa_pending_actions) {
@@ -1160,7 +1172,7 @@ io_loop(void *data) {
size_t i;
int ret;
bool has_more, data_received, has_pending_wakeups = false;
double last_main_loop_wakeup_at = -1, now = -1;
monotonic_t last_main_loop_wakeup_at = -1, now = -1;
Screen *screen;
ChildMonitor *self = (ChildMonitor*)data;
set_thread_name("KittyChildMon");
@@ -1181,8 +1193,8 @@ io_loop(void *data) {
}
if (has_pending_wakeups) {
now = monotonic();
double time_delta = OPT(input_delay) - (now - last_main_loop_wakeup_at);
if (time_delta >= 0) ret = poll(fds, self->count + EXTRA_FDS, (int)ceil(1000 * time_delta));
monotonic_t time_delta = OPT(input_delay) - (now - last_main_loop_wakeup_at);
if (time_delta >= 0) ret = poll(fds, self->count + EXTRA_FDS, monotonic_t_to_ms(time_delta));
else ret = 0;
} else {
ret = poll(fds, self->count + EXTRA_FDS, -1);
@@ -1414,7 +1426,7 @@ prune_finished_writes(void) {
static void
wakeup_talk_loop(bool in_signal_handler) {
wakeup_loop(&talk_data.loop_data, in_signal_handler);
if (talk_thread_started) wakeup_loop(&talk_data.loop_data, in_signal_handler, "talk_loop");
}
static inline void

View File

@@ -4,9 +4,9 @@
import fcntl
import os
import sys
from collections import defaultdict
from contextlib import contextmanager
from contextlib import suppress
from contextlib import contextmanager, suppress
import kitty.fast_data_types as fast_data_types
@@ -30,14 +30,16 @@ if is_macos:
else:
def cmdline_of_process(pid):
return list(filter(None, open('/proc/{}/cmdline'.format(pid), 'rb').read().decode('utf-8').split('\0')))
with open('/proc/{}/cmdline'.format(pid), 'rb') as f:
return list(filter(None, f.read().decode('utf-8').split('\0')))
def cwd_of_process(pid):
ans = '/proc/{}/cwd'.format(pid)
return os.path.realpath(ans)
def _environ_of_process(pid):
return open('/proc/{}/environ'.format(pid), 'rb').read().decode('utf-8')
with open('/proc/{}/environ'.format(pid), 'rb') as f:
return f.read().decode('utf-8')
def process_group_map():
ans = defaultdict(list)
@@ -47,8 +49,9 @@ else:
except Exception:
continue
try:
raw = open('/proc/' + x + '/stat', 'rb').read().decode('utf-8')
except EnvironmentError:
with open('/proc/' + x + '/stat', 'rb') as f:
raw = f.read().decode('utf-8')
except OSError:
continue
try:
q = int(raw.split(' ', 5)[4])
@@ -118,31 +121,47 @@ def remove_cloexec(fd):
fcntl.fcntl(fd, fcntl.F_SETFD, fcntl.fcntl(fd, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC)
def remove_blocking(fd):
os.set_blocking(fd, False)
def process_env():
ans = os.environ
ssl_env_var = getattr(sys, 'kitty_ssl_env_var', None)
if ssl_env_var is not None:
ans = ans.copy()
ans.pop(ssl_env_var, None)
return ans
def default_env():
try:
return default_env.env
except AttributeError:
return os.environ
return process_env()
def set_default_env(val=None):
env = os.environ.copy()
env = process_env().copy()
if val:
env.update(val)
default_env.env = env
def openpty():
master, slave = os.openpty() # Note that master and slave are in blocking mode
remove_cloexec(slave)
fast_data_types.set_iutf8_fd(master, True)
return master, slave
class Child:
child_fd = pid = None
forked = False
def __init__(self, argv, cwd, opts, stdin=None, env=None, cwd_from=None):
self.allow_remote_control = False
if argv and argv[0] == '@':
self.allow_remote_control = True
if len(argv) > 1:
argv = argv[1:]
def __init__(self, argv, cwd, opts, stdin=None, env=None, cwd_from=None, allow_remote_control=False):
self.allow_remote_control = allow_remote_control
self.argv = argv
if cwd_from is not None:
try:
@@ -166,7 +185,7 @@ class Child:
env['TERM'] = self.opts.term
env['COLORTERM'] = 'truecolor'
if self.cwd:
# needed incase cwd is a symlink, in which case shells
# needed in case cwd is a symlink, in which case shells
# can use it to display the current directory name rather
# than the resolved path
env['PWD'] = self.cwd
@@ -178,9 +197,7 @@ class Child:
if self.forked:
return
self.forked = True
master, slave = os.openpty() # Note that master and slave are in blocking mode
remove_cloexec(slave)
fast_data_types.set_iutf8_fd(master, True)
master, slave = openpty()
stdin, self.stdin = self.stdin, None
ready_read_fd, ready_write_fd = os.pipe()
remove_cloexec(ready_read_fd)
@@ -194,8 +211,20 @@ class Child:
argv = list(self.argv)
exe = argv[0]
if is_macos and exe == shell_path:
# Some macOS machines need the shell to have argv[0] prefixed by
# hyphen, see https://github.com/kovidgoyal/kitty/issues/247
# bash will only source ~/.bash_profile if it detects it is a login
# shell (see the invocation section of the bash man page), which it
# does if argv[0] is prefixed by a hyphen see
# https://github.com/kovidgoyal/kitty/issues/247
# it is apparently common to use ~/.bash_profile instead of the
# more correct ~/.bashrc on macOS to setup env vars, so if
# the default shell is used prefix argv[0] by '-'
#
# it is arguable whether graphical terminals should start shells
# in login mode in general, there are at least a few Linux users
# that also make this incorrect assumption, see for example
# https://github.com/kovidgoyal/kitty/issues/1870
# xterm, urxvt, konsole and gnome-terminal do not do it in my
# testing.
argv[0] = ('-' + exe.split('/')[-1])
pid = fast_data_types.spawn(exe, self.cwd, tuple(argv), env, master, slave, stdin_read_fd, stdin_write_fd, ready_read_fd, ready_write_fd)
os.close(slave)
@@ -206,7 +235,7 @@ class Child:
fast_data_types.thread_write(stdin_write_fd, stdin)
os.close(ready_read_fd)
self.terminal_ready_fd = ready_write_fd
fcntl.fcntl(self.child_fd, fcntl.F_SETFL, fcntl.fcntl(self.child_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
remove_blocking(self.child_fd)
return pid
def mark_terminal_ready(self):
@@ -238,6 +267,13 @@ class Child:
except Exception:
return list(self.argv)
@property
def foreground_cmdline(self):
try:
return cmdline_of_process(self.pid_for_cwd) or self.cmdline
except Exception:
return self.cmdline
@property
def environ(self):
try:
@@ -263,3 +299,14 @@ class Child:
def foreground_cwd(self):
with suppress(Exception):
return cwd_of_process(self.pid_for_cwd) or None
@property
def foreground_environ(self):
try:
return environ_of_process(self.pid_for_cwd)
except Exception:
try:
return environ_of_process(self.pid)
except Exception:
pass
return {}

12
kitty/choose_entry.py Normal file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
import re
def mark(text, args, Mark, extra_cli_args, *a):
for idx, m in enumerate(re.finditer(args.regex, text)):
start, end = m.span()
mark_text = text[start:end].replace('\n', '').replace('\0', '')
yield Mark(idx, start, end, mark_text, {'index': idx})

View File

@@ -223,9 +223,9 @@ def get_defaults_from_seq(seq):
default_msg = ('''\
Run the :italic:`{appname}` terminal emulator. You can also specify the :italic:`program`
to run inside :italic:`{appname}` as normal arguments following the :italic:`options`.
For example: {appname} /bin/sh
For example: {appname} sh -c "echo hello, world. Press ENTER to quit; read"
For comprehensive documentation for kitty, please see: https://sw.kovidgoyal.net/kitty''').format(appname=appname)
For comprehensive documentation for kitty, please see: https://sw.kovidgoyal.net/kitty/''').format(appname=appname)
def print_help_for_seq(seq, usage, message, appname):
@@ -233,7 +233,7 @@ def print_help_for_seq(seq, usage, message, appname):
screen_size = screen_size_function()
try:
linesz = min(screen_size().cols, 76)
except EnvironmentError:
except OSError:
linesz = 76
blocks = []
a = blocks.append
@@ -423,8 +423,8 @@ class Options:
class Namespace:
def __init__(self, kwargs):
for name in kwargs:
setattr(self, name, kwargs[name])
for name, val in kwargs.items():
setattr(self, name, val)
def parse_cmdline(oc, disabled, args=None):
@@ -514,7 +514,7 @@ Detach from the controlling terminal, if any
--session
Path to a file containing the startup :italic:`session` (tabs, windows, layout, programs).
See the README file for details and an example.
Use - to read from STDIN. See the README file for details and an example.
--hold
@@ -728,9 +728,11 @@ def create_opts(args, debug_config=False, accumulate_bad_lines=None):
import subprocess
print(' '.join(subprocess.check_output(['sw_vers']).decode('utf-8').splitlines()).strip())
if os.path.exists('/etc/issue'):
print(open('/etc/issue', encoding='utf-8', errors='replace').read().strip())
with open('/etc/issue', encoding='utf-8', errors='replace') as f:
print(f.read().strip())
if os.path.exists('/etc/lsb-release'):
print(open('/etc/lsb-release', encoding='utf-8', errors='replace').read().strip())
with open('/etc/lsb-release', encoding='utf-8', errors='replace') as f:
print(f.read().strip())
config = tuple(x for x in config if os.path.exists(x))
if config:
print(green('Loaded config files:'), ', '.join(config))

View File

@@ -157,7 +157,8 @@ def replay(raw):
def main(path):
raw = open(path).read()
with open(path) as f:
raw = f.read()
replay(raw)
with suppress(EOFError, KeyboardInterrupt):
input()

View File

@@ -7,10 +7,16 @@ import os
import sys
from contextlib import suppress
from .cli import parse_args, parse_option_spec, get_defaults_from_seq
from .cli import (
Namespace, get_defaults_from_seq, parse_args, parse_option_spec
)
from .config import parse_config, parse_send_text_bytes
from .constants import appname
from .fast_data_types import focus_os_window
from .launch import (
launch as do_launch, options_spec as launch_options_spec,
parse_launch_args
)
from .tabs import SpecialWindow
from .utils import natsort_ints
@@ -375,6 +381,176 @@ def set_tab_title(boss, window, payload):
# }}}
# create_marker {{{
@cmd(
'Create a marker that highlights specified text',
'Create a marker which can highlight text in the specified window. For example: '
'create_marker text 1 ERROR. For full details see: https://sw.kovidgoyal.net/kitty/marks.html',
options_spec=MATCH_WINDOW_OPTION + '''\n
--self
type=bool-set
If specified apply marker to the window this command is run in, rather than the active window.
''',
argspec='MARKER SPECIFICATION'
)
def cmd_create_marker(global_opts, opts, args):
'''
match: Which window to detach
self: Boolean indicating whether to detach the window the command is run in
marker_spec: A list or arguments that define the marker specification, for example: ['text', '1', 'ERROR']
'''
from .config import parse_marker_spec
if len(args) < 2:
raise ValueError('Invalid marker specification: {}'.format(' '.join(args)))
parse_marker_spec(args[0], args[1:])
return {'match': opts.match, 'self': opts.self, 'marker_spec': args}
def create_marker(boss, window, payload):
pg = cmd_create_marker.payload_get
match = pg(payload, 'match')
if match:
windows = tuple(boss.match_windows(match))
if not windows:
raise MatchError(match)
else:
windows = [window if window and pg(payload, 'self') else boss.active_window]
args = pg(payload, 'marker_spec')
for window in windows:
window.set_marker(args)
# }}}
# remove_marker {{{
@cmd(
'Remove the currently set marker, if any.',
options_spec=MATCH_WINDOW_OPTION + '''\n
--self
type=bool-set
If specified apply marker to the window this command is run in, rather than the active window.
''',
argspec=''
)
def cmd_remove_marker(global_opts, opts, args):
'''
match: Which window to detach
self: Boolean indicating whether to detach the window the command is run in
'''
return {'match': opts.match, 'self': opts.self}
def remove_marker(boss, window, payload):
pg = cmd_create_marker.payload_get
match = pg(payload, 'match')
if match:
windows = tuple(boss.match_windows(match))
if not windows:
raise MatchError(match)
else:
windows = [window if window and pg(payload, 'self') else boss.active_window]
for window in windows:
window.remove_marker()
# }}}
# detach_window {{{
@cmd(
'Detach a window and place it in a different/new tab',
'Detach the specified window and either move it into a new tab, a new OS window'
' or add it to the specified tab. Use the special value :code:`new` for --target-tab'
' to move to a new tab. If no target tab is specified the window is moved to a new OS window.',
options_spec=MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--target-tab -t') + '''\n
--self
type=bool-set
If specified detach the window this command is run in, rather than the active window.
''',
argspec=''
)
def cmd_detach_window(global_opts, opts, args):
'''
match: Which window to detach
target: Which tab to move the detached window to
self: Boolean indicating whether to detach the window the command is run in
'''
return {'match': opts.match, 'target': opts.target_tab, 'self': opts.self}
def detach_window(boss, window, payload):
pg = cmd_detach_window.payload_get
match = pg(payload, 'match')
if match:
windows = tuple(boss.match_windows(match))
if not windows:
raise MatchError(match)
else:
windows = [window if window and pg(payload, 'self') else boss.active_window]
match = pg(payload, 'target_tab')
kwargs = {}
if match:
if match == 'new':
kwargs['target_tab_id'] = 'new'
else:
tabs = tuple(boss.match_tabs(match))
if not tabs:
raise MatchError(match, 'tabs')
kwargs['target_tab_id'] = tabs[0].id
if not kwargs:
kwargs['target_os_window_id'] = 'new'
for window in windows:
boss._move_window_to(window=window, **kwargs)
# }}}
# detach_tab {{{
@cmd(
'Detach a tab and place it in a different/new OS Window',
'Detach the specified tab and either move it into a new OS window'
' or add it to the OS Window containing the tab specified by --target-tab',
options_spec=MATCH_TAB_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--target-tab -t') + '''\n
--self
type=bool-set
If specified detach the tab this command is run in, rather than the active tab.
''',
argspec=''
)
def cmd_detach_tab(global_opts, opts, args):
'''
match: Which tab to detach
target: Which OS Window to move the detached tab to
self: Boolean indicating whether to detach the tab the command is run in
'''
return {'match': opts.match, 'target': opts.target_tab, 'self': opts.self}
def detach_tab(boss, window, payload):
pg = cmd_detach_tab.payload_get
match = pg(payload, 'match')
if match:
tabs = tuple(boss.match_tabs(match))
if not tabs:
raise MatchError(match)
else:
tabs = [window.tabref() if pg(payload, 'self') and window and window.tabref() else boss.active_tab]
match = pg(payload, 'target_tab')
kwargs = {}
if match:
targets = tuple(boss.match_tabs(match))
if not targets:
raise MatchError(match, 'tabs')
kwargs['target_os_window_id'] = targets[0].os_window_id
for tab in tabs:
boss._move_tab_to(tab=tab, **kwargs)
# }}}
# goto_layout {{{
@cmd(
'Set the window layout',
@@ -675,6 +851,77 @@ def new_window(boss, window, payload):
# }}}
# launch {{{
@cmd(
'Run an arbitrary process in a new window/tab',
' Prints out the id of the newly opened window. Any command line arguments'
' are assumed to be the command line used to run in the new window, if none'
' are provided, the default shell is run. For example:'
' :italic:`kitty @ launch --title Email mutt`.',
options_spec=MATCH_TAB_OPTION + '\n\n' + '''\
--no-response
type=bool-set
Do not print out the id of the newly created window.
--self
type=bool-set
If specified the tab containing the window this command is run in is used
instead of the active tab
''' + '\n\n' + launch_options_spec().replace(':option:`launch', ':option:`kitty @ launch'),
argspec='[CMD ...]'
)
def cmd_launch(global_opts, opts, args):
'''
args+: The command line to run in the new window, as a list, use an empty list to run the default shell
match: The tab to open the new window in
window_title: Title for the new window
cwd: Working directory for the new window
env: List of environment varibles of the form NAME=VALUE
tab_title: Title for the new tab
type: The type of window to open
keep_focus: Boolean indicating whether the current window should retain focus or not
copy_colors: Boolean indicating whether to copy the colors from the current window
copy_cmdline: Boolean indicating whether to copy the cmdline from the current window
copy_env: Boolean indicating whether to copy the environ from the current window
location: Where in the tab to open the new window
allow_remote_control: Boolean indicating whether to allow remote control from the new window
stdin_source: Where to get stdin for thew process from
stdin_add_formatting: Boolean indicating whether to add formatting codes to stdin
stdin_add_line_wrap_markers: Boolean indicating whether to add line wrap markers to stdin
no_response: Boolean indicating whether to send back the window id
marker: Specification for marker for new window, for example: "text 1 ERROR"
'''
if opts.no_response:
global_opts.no_command_response = True
ans = {'args': args or []}
for attr, val in opts.__dict__.items():
ans[attr] = val
return ans
def launch(boss, window, payload):
pg = cmd_launch.payload_get
default_opts = parse_launch_args()[0]
opts = {}
for key, default_value in default_opts.__dict__.items():
opts[key] = payload.get(key, default_value)
opts = Namespace(opts)
match = pg(payload, 'match')
if match:
tabs = tuple(boss.match_tabs(match))
if not tabs:
raise MatchError(match, 'tabs')
else:
tabs = [boss.active_tab]
if pg(payload, 'self') and window and window.tabref():
tabs = [window.tabref()]
tab = tabs[0]
w = do_launch(boss, opts, pg(payload, 'args') or None, target_tab=tab)
return None if pg(payload, 'no_response') else str(getattr(w, 'id', 0))
# }}}
# focus_window {{{
@cmd(
'Focus the specified window',
@@ -882,7 +1129,7 @@ this option, any color arguments are ignored and --configured and --all are impl
def cmd_set_colors(global_opts, opts, args):
'''
colors+: An object mapping names to colors as 24-bit RGB integers
cursor_text_color: A 24-bit clor for text under the cursor
cursor_text_color: A 24-bit color for text under the cursor
match_window: Window to change colors in
match_tab: Tab to change colors in
all: Boolean indicating change colors everywhere or not
@@ -999,7 +1246,7 @@ def cmd_set_background_opacity(global_opts, opts, args):
def set_background_opacity(boss, window, payload):
if not boss.opts.dynamic_background_opacity:
raise OpacityError('You must turn on the dynamic_background_opacity option in kitty.conf to be able to set background opacity')
windows = windows_for_payload(payload)
windows = windows_for_payload(boss, window, payload)
for os_window_id in {w.os_window_id for w in windows}:
boss._set_os_window_background_opacity(os_window_id, payload['opacity'])
# }}}

View File

@@ -7,6 +7,7 @@
#include "state.h"
#include "monotonic.h"
#include <Cocoa/Cocoa.h>
#include <AvailabilityMacros.h>
@@ -72,16 +73,21 @@ find_app_name(void) {
@implementation GlobalMenuTarget
- (void) show_preferences : (id)sender {
- (void)show_preferences:(id)sender {
(void)sender;
set_cocoa_pending_action(PREFERENCES_WINDOW, NULL);
}
- (void) new_os_window : (id)sender {
- (void)new_os_window:(id)sender {
(void)sender;
set_cocoa_pending_action(NEW_OS_WINDOW, NULL);
}
- (void)open_kitty_website_url:(id)sender {
(void)sender;
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://sw.kovidgoyal.net/kitty/"]];
}
+ (GlobalMenuTarget *) shared_instance
{
@@ -96,7 +102,7 @@ find_app_name(void) {
@end
static unichar new_window_key = 0;
static char new_window_key[32] = {0};
static NSEventModifierFlags new_window_mods = 0;
static PyObject*
@@ -104,9 +110,9 @@ cocoa_set_new_window_trigger(PyObject *self UNUSED, PyObject *args) {
int mods, key;
if (!PyArg_ParseTuple(args, "ii", &mods, &key)) return NULL;
int nwm;
get_cocoa_key_equivalent(key, mods, &new_window_key, &nwm);
get_cocoa_key_equivalent(key, mods, new_window_key, sizeof(new_window_key), &nwm);
new_window_mods = nwm;
if (new_window_key) Py_RETURN_TRUE;
if (new_window_key[0]) Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
@@ -117,10 +123,10 @@ get_dock_menu(id self UNUSED, SEL _cmd UNUSED, NSApplication *sender UNUSED) {
if (!dockMenu) {
GlobalMenuTarget *global_menu_target = [GlobalMenuTarget shared_instance];
dockMenu = [[NSMenu alloc] init];
NSMenuItem *newWindowItem = [dockMenu addItemWithTitle:@"New OS window"
action:@selector(new_os_window:)
keyEquivalent:@""];
[newWindowItem setTarget:global_menu_target];
[[dockMenu addItemWithTitle:@"New OS window"
action:@selector(new_os_window:)
keyEquivalent:@""]
setTarget:global_menu_target];
}
return dockMenu;
}
@@ -231,41 +237,41 @@ cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
// global menu {{{
void
cocoa_create_global_menu(void) {
@autoreleasepool {
NSString* app_name = find_app_name();
NSMenu* bar = [[NSMenu alloc] init];
GlobalMenuTarget *global_menu_target = [GlobalMenuTarget shared_instance];
[NSApp setMainMenu:bar];
NSMenuItem* appMenuItem =
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
[bar addItemWithTitle:@""
action:NULL
keyEquivalent:@""];
NSMenu* appMenu = [[NSMenu alloc] init];
[appMenuItem setSubmenu:appMenu];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", app_name]
action:@selector(orderFrontStandardAboutPanel:)
keyEquivalent:@""];
keyEquivalent:@""];
[appMenu addItem:[NSMenuItem separatorItem]];
NSMenuItem* preferences_menu_item = [[NSMenuItem alloc] initWithTitle:@"Preferences..." action:@selector(show_preferences:) keyEquivalent:@","], *new_os_window_menu_item = NULL;
[preferences_menu_item setTarget:global_menu_target];
[appMenu addItem:preferences_menu_item];
if (new_window_key) {
NSString *s = [NSString stringWithCharacters:&new_window_key length:1];
new_os_window_menu_item = [[NSMenuItem alloc] initWithTitle:@"New OS window" action:@selector(new_os_window:) keyEquivalent:s];
[new_os_window_menu_item setKeyEquivalentModifierMask:new_window_mods];
[new_os_window_menu_item setTarget:global_menu_target];
[appMenu addItem:new_os_window_menu_item];
[s release];
}
[[appMenu addItemWithTitle:@"Preferences..."
action:@selector(show_preferences:)
keyEquivalent:@","]
setTarget:global_menu_target];
NSMenuItem* new_os_window_menu_item =
[appMenu addItemWithTitle:@"New OS window"
action:@selector(new_os_window:)
keyEquivalent:@(new_window_key)];
[new_os_window_menu_item setKeyEquivalentModifierMask:new_window_mods];
[new_os_window_menu_item setTarget:global_menu_target];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", app_name]
action:@selector(hide:)
keyEquivalent:@"h"];
[[appMenu addItemWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"]
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"]
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
[appMenu addItemWithTitle:@"Show All"
action:@selector(unhideAllApplications:)
@@ -275,19 +281,21 @@ cocoa_create_global_menu(void) {
NSMenu* servicesMenu = [[NSMenu alloc] init];
[NSApp setServicesMenu:servicesMenu];
[[appMenu addItemWithTitle:@"Services"
action:NULL
keyEquivalent:@""] setSubmenu:servicesMenu];
action:NULL
keyEquivalent:@""] setSubmenu:servicesMenu];
[servicesMenu release];
[appMenu addItem:[NSMenuItem separatorItem]];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", app_name]
action:@selector(terminate:)
keyEquivalent:@"q"];
keyEquivalent:@"q"];
[appMenu release];
NSMenuItem* windowMenuItem =
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
[bar addItemWithTitle:@""
action:NULL
keyEquivalent:@""];
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
[windowMenuItem setSubmenu:windowMenu];
@@ -309,28 +317,34 @@ cocoa_create_global_menu(void) {
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
[NSApp setWindowsMenu:windowMenu];
[windowMenu release];
[preferences_menu_item release];
if (new_os_window_menu_item) {
[new_os_window_menu_item release];
}
NSMenuItem* helpMenuItem =
[bar addItemWithTitle:@"Help"
action:NULL
keyEquivalent:@""];
NSMenu* helpMenu = [[NSMenu alloc] initWithTitle:@"Help"];
[helpMenuItem setSubmenu:helpMenu];
[[helpMenu addItemWithTitle:[NSString stringWithFormat:@"Visit %@ website", app_name]
action:@selector(open_kitty_website_url:)
keyEquivalent:@"?"]
setTarget:global_menu_target];
[helpMenu release];
[bar release];
class_addMethod(
object_getClass([NSApp delegate]),
@selector(applicationDockMenu:),
(IMP)get_dock_menu,
"@@:@");
object_getClass([NSApp delegate]),
@selector(applicationDockMenu:),
(IMP)get_dock_menu,
"@@:@");
[NSApp setServicesProvider:[[[ServiceProvider alloc] init] autorelease]];
} // autoreleasepool
}
void
cocoa_update_menu_bar_title(PyObject *pytitle) {
NSString *title = [[NSString alloc] initWithUTF8String:PyUnicode_AsUTF8(pytitle)];
NSString *title = @(PyUnicode_AsUTF8(pytitle));
NSMenu *bar = [NSApp mainMenu];
if (title_menu != NULL) {
[bar removeItem:title_menu];
@@ -339,7 +353,6 @@ cocoa_update_menu_bar_title(PyObject *pytitle) {
NSMenu *m = [[NSMenu alloc] initWithTitle:[NSString stringWithFormat:@" :: %@", title]];
[title_menu setSubmenu:m];
[m release];
[title release];
} // }}}
bool
@@ -367,7 +380,7 @@ cocoa_make_window_resizable(void *w, bool resizable) {
bool
cocoa_alt_option_key_pressed(NSUInteger flags) {
NSUInteger q = (OPT(macos_option_as_alt) == 1) ? NSRightAlternateKeyMask : NSLeftAlternateKeyMask;
return ((q & flags) == q) ? true : false;
return (q & flags) == q;
}
void
@@ -411,7 +424,7 @@ cocoa_get_lang(PyObject UNUSED *self) {
} // autoreleasepool
}
double
monotonic_t
cocoa_cursor_blink_interval(void) {
@autoreleasepool {
@@ -420,12 +433,12 @@ cocoa_cursor_blink_interval(void) {
double off_period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriodOff"];
double period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriod"];
double max_value = 60 * 1000.0, ans = -1.0;
if (on_period_ms || off_period_ms) {
if (on_period_ms != 0. || off_period_ms != 0.) {
ans = on_period_ms + off_period_ms;
} else if (period_ms) {
} else if (period_ms != 0.) {
ans = period_ms;
}
return ans > max_value ? 0.0 : ans;
return ans > max_value ? 0ll : ms_double_to_monotonic_t(ans);
} // autoreleasepool
}
@@ -473,6 +486,40 @@ cleanup() {
dockMenu = nil;
if (notification_activated_callback) Py_DECREF(notification_activated_callback);
notification_activated_callback = NULL;
} // autoreleasepool
}
void
cocoa_hide_window_title(void *w)
{
@autoreleasepool {
NSWindow *window = (NSWindow*)w;
[window setTitleVisibility:NSWindowTitleHidden];
} // autoreleasepool
}
void
cocoa_hide_titlebar(void *w)
{
@autoreleasepool {
cocoa_hide_window_title(w);
NSWindow *window = (NSWindow*)w;
NSButton *button;
button = [window standardWindowButton: NSWindowCloseButton];
if (button) button.hidden = true;
button = [window standardWindowButton: NSWindowMiniaturizeButton];
if (button) button.hidden = true;
button = [window standardWindowButton: NSWindowZoomButton];
if (button) button.hidden = true;
[window setTitlebarAppearsTransparent:YES];
[window setStyleMask:
[window styleMask] | NSWindowStyleMaskFullSizeContentView];
} // autoreleasepool
}

Some files were not shown because too many files have changed in this diff Show More